diff options
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r-- | drivers/pci/hotplug/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 53 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_sysfs.c | 22 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 4 | ||||
-rw-r--r-- | drivers/pci/hotplug/s390_pci_hpc.c | 60 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_core.c | 3 |
6 files changed, 86 insertions, 58 deletions
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index 9fcb87f353d4..bb7ebb22db01 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -4,7 +4,7 @@ menuconfig HOTPLUG_PCI tristate "Support for PCI Hotplug" - depends on PCI && HOTPLUG && SYSFS + depends on PCI && SYSFS ---help--- Say Y here if you have a motherboard with a PCI Hotplug controller. This allows you to add and remove PCI cards while the machine is diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 716aa93fff76..59df8575a48c 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -61,6 +61,7 @@ static DEFINE_MUTEX(bridge_mutex); static void handle_hotplug_event_bridge (acpi_handle, u32, void *); static void acpiphp_sanitize_bus(struct pci_bus *bus); static void acpiphp_set_hpp_values(struct pci_bus *bus); +static void hotplug_event_func(acpi_handle handle, u32 type, void *context); static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); static void free_bridge(struct kref *kref); @@ -147,7 +148,7 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, static const struct acpi_dock_ops acpiphp_dock_ops = { - .handler = handle_hotplug_event_func, + .handler = hotplug_event_func, }; /* Check whether the PCI device is managed by native PCIe hotplug driver */ @@ -179,6 +180,20 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) return true; } +static void acpiphp_dock_init(void *data) +{ + struct acpiphp_func *func = data; + + get_bridge(func->slot->bridge); +} + +static void acpiphp_dock_release(void *data) +{ + struct acpiphp_func *func = data; + + put_bridge(func->slot->bridge); +} + /* callback routine to register each ACPI PCI slot object */ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) @@ -298,7 +313,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) */ newfunc->flags &= ~FUNC_HAS_EJ0; if (register_hotplug_dock_device(handle, - &acpiphp_dock_ops, newfunc)) + &acpiphp_dock_ops, newfunc, + acpiphp_dock_init, acpiphp_dock_release)) dbg("failed to register dock device\n"); /* we need to be notified when dock events happen @@ -670,6 +686,7 @@ static int __ref enable_device(struct acpiphp_slot *slot) struct pci_bus *bus = slot->bridge->pci_bus; struct acpiphp_func *func; int num, max, pass; + LIST_HEAD(add_list); if (slot->flags & SLOT_ENABLED) goto err_exit; @@ -694,13 +711,15 @@ static int __ref enable_device(struct acpiphp_slot *slot) max = pci_scan_bridge(bus, dev, max, pass); if (pass && dev->subordinate) { check_hotplug_bridge(slot, dev); - pci_bus_size_bridges(dev->subordinate); + pcibios_resource_survey_bus(dev->subordinate); + __pci_bus_size_bridges(dev->subordinate, + &add_list); } } } } - pci_bus_assign_resources(bus); + __pci_bus_assign_resources(bus, &add_list, NULL); acpiphp_sanitize_bus(bus); acpiphp_set_hpp_values(bus); acpiphp_set_acpi_region(slot); @@ -1065,22 +1084,12 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge); } -static void _handle_hotplug_event_func(struct work_struct *work) +static void hotplug_event_func(acpi_handle handle, u32 type, void *context) { - struct acpiphp_func *func; + struct acpiphp_func *func = context; char objname[64]; struct acpi_buffer buffer = { .length = sizeof(objname), .pointer = objname }; - struct acpi_hp_work *hp_work; - acpi_handle handle; - u32 type; - - hp_work = container_of(work, struct acpi_hp_work, work); - handle = hp_work->handle; - type = hp_work->type; - func = (struct acpiphp_func *)hp_work->context; - - acpi_scan_lock_acquire(); acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); @@ -1113,6 +1122,18 @@ static void _handle_hotplug_event_func(struct work_struct *work) warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); break; } +} + +static void _handle_hotplug_event_func(struct work_struct *work) +{ + struct acpi_hp_work *hp_work; + struct acpiphp_func *func; + + hp_work = container_of(work, struct acpi_hp_work, work); + func = hp_work->context; + acpi_scan_lock_acquire(); + + hotplug_event_func(hp_work->handle, hp_work->type, func); acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_func */ diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index 4cb30447a486..17c1f36315d1 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c @@ -167,26 +167,8 @@ exit: static loff_t lseek(struct file *file, loff_t off, int whence) { - struct ctrl_dbg *dbg; - loff_t new = -1; - - mutex_lock(&cpqphp_mutex); - dbg = file->private_data; - - switch (whence) { - case 0: - new = off; - break; - case 1: - new = file->f_pos + off; - break; - } - if (new < 0 || new > dbg->size) { - mutex_unlock(&cpqphp_mutex); - return -EINVAL; - } - mutex_unlock(&cpqphp_mutex); - return (file->f_pos = new); + struct ctrl_dbg *dbg = file->private_data; + return fixed_size_llseek(file, off, whence, dbg->size); } static ssize_t read(struct file *file, char __user *buf, diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 5127f3f41821..b2255736ac81 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -773,14 +773,12 @@ static void pcie_shutdown_notification(struct controller *ctrl) static int pcie_init_slot(struct controller *ctrl) { struct slot *slot; - char name[32]; slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; - snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl)); - slot->wq = alloc_workqueue(name, 0, 0); + slot->wq = alloc_workqueue("pciehp-%u", 0, 0, PSN(ctrl)); if (!slot->wq) goto abort; diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c index 46a7b738f61f..ea3fa90d020a 100644 --- a/drivers/pci/hotplug/s390_pci_hpc.c +++ b/drivers/pci/hotplug/s390_pci_hpc.c @@ -41,6 +41,28 @@ struct slot { struct zpci_dev *zdev; }; +static inline int slot_configure(struct slot *slot) +{ + int ret = sclp_pci_configure(slot->zdev->fid); + + zpci_dbg(3, "conf fid:%x, rc:%d\n", slot->zdev->fid, ret); + if (!ret) + slot->zdev->state = ZPCI_FN_STATE_CONFIGURED; + + return ret; +} + +static inline int slot_deconfigure(struct slot *slot) +{ + int ret = sclp_pci_deconfigure(slot->zdev->fid); + + zpci_dbg(3, "deconf fid:%x, rc:%d\n", slot->zdev->fid, ret); + if (!ret) + slot->zdev->state = ZPCI_FN_STATE_STANDBY; + + return ret; +} + static int enable_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; @@ -49,14 +71,23 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) if (slot->zdev->state != ZPCI_FN_STATE_STANDBY) return -EIO; - rc = sclp_pci_configure(slot->zdev->fid); - zpci_dbg(3, "conf fid:%x, rc:%d\n", slot->zdev->fid, rc); - if (!rc) { - slot->zdev->state = ZPCI_FN_STATE_CONFIGURED; - /* automatically scan the device after is was configured */ - zpci_enable_device(slot->zdev); - zpci_scan_device(slot->zdev); - } + rc = slot_configure(slot); + if (rc) + return rc; + + rc = zpci_enable_device(slot->zdev); + if (rc) + goto out_deconfigure; + + slot->zdev->state = ZPCI_FN_STATE_ONLINE; + + pci_scan_slot(slot->zdev->bus, ZPCI_DEVFN); + pci_bus_add_devices(slot->zdev->bus); + + return rc; + +out_deconfigure: + slot_deconfigure(slot); return rc; } @@ -68,17 +99,14 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) if (!zpci_fn_configured(slot->zdev->state)) return -EIO; + if (slot->zdev->pdev) + pci_stop_and_remove_bus_device(slot->zdev->pdev); + rc = zpci_disable_device(slot->zdev); if (rc) return rc; - /* TODO: we rely on the user to unbind/remove the device, is that plausible - * or do we need to trigger that here? - */ - rc = sclp_pci_deconfigure(slot->zdev->fid); - zpci_dbg(3, "deconf fid:%x, rc:%d\n", slot->zdev->fid, rc); - if (!rc) - slot->zdev->state = ZPCI_FN_STATE_STANDBY; - return rc; + + return slot_deconfigure(slot); } static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 3100c52c837c..d3f757df691c 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -128,8 +128,7 @@ static int init_slots(struct controller *ctrl) slot->hpc_ops = ctrl->hpc_ops; slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); - snprintf(name, sizeof(name), "shpchp-%d", slot->number); - slot->wq = alloc_workqueue(name, 0, 0); + slot->wq = alloc_workqueue("shpchp-%d", 0, 0, slot->number); if (!slot->wq) { retval = -ENOMEM; goto error_info; |