diff options
-rw-r--r-- | arch/s390/include/asm/pci.h | 2 | ||||
-rw-r--r-- | arch/s390/pci/pci.c | 11 | ||||
-rw-r--r-- | arch/s390/pci/pci_bus.c | 35 | ||||
-rw-r--r-- | arch/s390/pci/pci_bus.h | 1 | ||||
-rw-r--r-- | arch/s390/pci/pci_event.c | 14 |
5 files changed, 33 insertions, 30 deletions
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index d810ea4d358f..35c2af9371a9 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -201,7 +201,7 @@ extern unsigned int s390_pci_no_rid; Prototypes ----------------------------------------------------------------------------- */ /* Base stuff */ -int zpci_create_device(u32 fid, u32 fh, enum zpci_state state); +struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state); int zpci_enable_device(struct zpci_dev *); int zpci_disable_device(struct zpci_dev *); int zpci_configure_device(struct zpci_dev *zdev, u32 fh); diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 023c3c2ab7f1..d6c6b5119a14 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -690,9 +690,9 @@ int zpci_disable_device(struct zpci_dev *zdev) * Creates a new zpci device and adds it to its, possibly newly created, zbus * as well as zpci_list. * - * Returns: 0 on success, an error value otherwise + * Returns: the zdev on success or an error pointer otherwise */ -int zpci_create_device(u32 fid, u32 fh, enum zpci_state state) +struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state) { struct zpci_dev *zdev; int rc; @@ -700,7 +700,7 @@ int zpci_create_device(u32 fid, u32 fh, enum zpci_state state) zpci_dbg(3, "add fid:%x, fh:%x, c:%d\n", fid, fh, state); zdev = kzalloc(sizeof(*zdev), GFP_KERNEL); if (!zdev) - return -ENOMEM; + return ERR_PTR(-ENOMEM); /* FID and Function Handle are the static/dynamic identifiers */ zdev->fid = fid; @@ -727,14 +727,14 @@ int zpci_create_device(u32 fid, u32 fh, enum zpci_state state) list_add_tail(&zdev->entry, &zpci_list); spin_unlock(&zpci_list_lock); - return 0; + return zdev; error_destroy_iommu: zpci_destroy_iommu(zdev); error: zpci_dbg(0, "add fid:%x, rc:%d\n", fid, rc); kfree(zdev); - return rc; + return ERR_PTR(rc); } /** @@ -959,6 +959,7 @@ static int __init pci_base_init(void) rc = clp_scan_pci_devices(); if (rc) goto out_find; + zpci_bus_scan_busses(); s390_pci_initialized = 1; return 0; diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c index 9bc869afe011..9629f9779c79 100644 --- a/arch/s390/pci/pci_bus.c +++ b/arch/s390/pci/pci_bus.c @@ -160,6 +160,23 @@ int zpci_bus_scan_bus(struct zpci_bus *zbus) return ret; } +/* zpci_bus_scan_busses - Scan all registered busses + * + * Scan all available zbusses + * + */ +void zpci_bus_scan_busses(void) +{ + struct zpci_bus *zbus = NULL; + + mutex_lock(&zbus_list_lock); + list_for_each_entry(zbus, &zbus_list, bus_next) { + zpci_bus_scan_bus(zbus); + cond_resched(); + } + mutex_unlock(&zbus_list_lock); +} + /* 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 @@ -387,24 +404,6 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) if (rc) goto error; - if (zdev->state != ZPCI_FN_STATE_CONFIGURED) - return 0; - - /* the PCI function will be scanned once function 0 appears */ - if (!zdev->zbus->bus) - return 0; - - /* For function 0 scan whole bus as we might have to pick up existing - * functions waiting for it to allow creating the PCI bus - */ - if (zdev->devfn == 0 && zdev->zbus->multifunction) - rc = zpci_bus_scan_bus(zdev->zbus); - else - rc = zpci_bus_scan_device(zdev); - - if (rc) - goto error; - return 0; error: diff --git a/arch/s390/pci/pci_bus.h b/arch/s390/pci/pci_bus.h index 981876ae3bd7..b877a97e6745 100644 --- a/arch/s390/pci/pci_bus.h +++ b/arch/s390/pci/pci_bus.h @@ -11,6 +11,7 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops); void zpci_bus_device_unregister(struct zpci_dev *zdev); int zpci_bus_scan_bus(struct zpci_bus *zbus); +void zpci_bus_scan_busses(void); int zpci_bus_scan_device(struct zpci_dev *zdev); void zpci_bus_remove_device(struct zpci_dev *zdev, bool set_error); diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c index ae3054d85491..1178b48a66df 100644 --- a/arch/s390/pci/pci_event.c +++ b/arch/s390/pci/pci_event.c @@ -104,13 +104,15 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) switch (ccdf->pec) { case 0x0301: /* Reserved|Standby -> Configured */ if (!zdev) { - zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED); - break; + zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED); + if (IS_ERR(zdev)) + break; + } else { + /* the configuration request may be stale */ + if (zdev->state != ZPCI_FN_STATE_STANDBY) + break; + zdev->state = ZPCI_FN_STATE_CONFIGURED; } - /* the configuration request may be stale */ - if (zdev->state != ZPCI_FN_STATE_STANDBY) - break; - zdev->state = ZPCI_FN_STATE_CONFIGURED; zpci_configure_device(zdev, ccdf->fh); break; case 0x0302: /* Reserved -> Standby */ |