aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-06-25 16:46:47 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-06-25 16:46:47 -0400
commit96c9ddae034a301bbd32c52da5c972778d73ad2e (patch)
tree25ca63815efbe874ec2140efd7b6ad034afea387
parent9e895ace5d82df8929b16f58e9f515f6d54ab82d (diff)
parent44521527be36172864e6e7a6fba4b66e9aa48e40 (diff)
Merge branch 'acpi-fixes'
* acpi-fixes: libata-acpi: add back ACPI based hotplug functionality ACPI / dock / PCI: Synchronous handling of dock events for PCI devices PCI / ACPI: Use boot-time resource allocation rules during hotplug ACPI / dock: Initialize ACPI dock subsystem upfront
-rw-r--r--drivers/acpi/dock.c179
-rw-r--r--drivers/acpi/internal.h5
-rw-r--r--drivers/acpi/scan.c1
-rw-r--r--drivers/ata/libata-acpi.c37
-rw-r--r--drivers/ata/libata-core.c2
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c53
-rw-r--r--drivers/pci/pci.h5
-rw-r--r--drivers/pci/setup-bus.c8
-rw-r--r--include/acpi/acpi_drivers.h8
10 files changed, 194 insertions, 106 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index ec117c6c996c..14de9f46972e 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -66,20 +66,21 @@ struct dock_station {
66 spinlock_t dd_lock; 66 spinlock_t dd_lock;
67 struct mutex hp_lock; 67 struct mutex hp_lock;
68 struct list_head dependent_devices; 68 struct list_head dependent_devices;
69 struct list_head hotplug_devices;
70 69
71 struct list_head sibling; 70 struct list_head sibling;
72 struct platform_device *dock_device; 71 struct platform_device *dock_device;
73}; 72};
74static LIST_HEAD(dock_stations); 73static LIST_HEAD(dock_stations);
75static int dock_station_count; 74static int dock_station_count;
75static DEFINE_MUTEX(hotplug_lock);
76 76
77struct dock_dependent_device { 77struct dock_dependent_device {
78 struct list_head list; 78 struct list_head list;
79 struct list_head hotplug_list;
80 acpi_handle handle; 79 acpi_handle handle;
81 const struct acpi_dock_ops *ops; 80 const struct acpi_dock_ops *hp_ops;
82 void *context; 81 void *hp_context;
82 unsigned int hp_refcount;
83 void (*hp_release)(void *);
83}; 84};
84 85
85#define DOCK_DOCKING 0x00000001 86#define DOCK_DOCKING 0x00000001
@@ -111,7 +112,6 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
111 112
112 dd->handle = handle; 113 dd->handle = handle;
113 INIT_LIST_HEAD(&dd->list); 114 INIT_LIST_HEAD(&dd->list);
114 INIT_LIST_HEAD(&dd->hotplug_list);
115 115
116 spin_lock(&ds->dd_lock); 116 spin_lock(&ds->dd_lock);
117 list_add_tail(&dd->list, &ds->dependent_devices); 117 list_add_tail(&dd->list, &ds->dependent_devices);
@@ -121,35 +121,90 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
121} 121}
122 122
123/** 123/**
124 * dock_add_hotplug_device - associate a hotplug handler with the dock station 124 * dock_init_hotplug - Initialize a hotplug device on a docking station.
125 * @ds: The dock station 125 * @dd: Dock-dependent device.
126 * @dd: The dependent device struct 126 * @ops: Dock operations to attach to the dependent device.
127 * 127 * @context: Data to pass to the @ops callbacks and @release.
128 * Add the dependent device to the dock's hotplug device list 128 * @init: Optional initialization routine to run after setting up context.
129 * @release: Optional release routine to run on removal.
129 */ 130 */
130static void 131static int dock_init_hotplug(struct dock_dependent_device *dd,
131dock_add_hotplug_device(struct dock_station *ds, 132 const struct acpi_dock_ops *ops, void *context,
132 struct dock_dependent_device *dd) 133 void (*init)(void *), void (*release)(void *))
133{ 134{
134 mutex_lock(&ds->hp_lock); 135 int ret = 0;
135 list_add_tail(&dd->hotplug_list, &ds->hotplug_devices); 136
136 mutex_unlock(&ds->hp_lock); 137 mutex_lock(&hotplug_lock);
138
139 if (dd->hp_context) {
140 ret = -EEXIST;
141 } else {
142 dd->hp_refcount = 1;
143 dd->hp_ops = ops;
144 dd->hp_context = context;
145 dd->hp_release = release;
146 }
147
148 if (!WARN_ON(ret) && init)
149 init(context);
150
151 mutex_unlock(&hotplug_lock);
152 return ret;
137} 153}
138 154
139/** 155/**
140 * dock_del_hotplug_device - remove a hotplug handler from the dock station 156 * dock_release_hotplug - Decrement hotplug reference counter of dock device.
141 * @ds: The dock station 157 * @dd: Dock-dependent device.
142 * @dd: the dependent device struct
143 * 158 *
144 * Delete the dependent device from the dock's hotplug device list 159 * Decrement the reference counter of @dd and if 0, detach its hotplug
160 * operations from it, reset its context pointer and run the optional release
161 * routine if present.
145 */ 162 */
146static void 163static void dock_release_hotplug(struct dock_dependent_device *dd)
147dock_del_hotplug_device(struct dock_station *ds,
148 struct dock_dependent_device *dd)
149{ 164{
150 mutex_lock(&ds->hp_lock); 165 void (*release)(void *) = NULL;
151 list_del(&dd->hotplug_list); 166 void *context = NULL;
152 mutex_unlock(&ds->hp_lock); 167
168 mutex_lock(&hotplug_lock);
169
170 if (dd->hp_context && !--dd->hp_refcount) {
171 dd->hp_ops = NULL;
172 context = dd->hp_context;
173 dd->hp_context = NULL;
174 release = dd->hp_release;
175 dd->hp_release = NULL;
176 }
177
178 if (release && context)
179 release(context);
180
181 mutex_unlock(&hotplug_lock);
182}
183
184static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
185 bool uevent)
186{
187 acpi_notify_handler cb = NULL;
188 bool run = false;
189
190 mutex_lock(&hotplug_lock);
191
192 if (dd->hp_context) {
193 run = true;
194 dd->hp_refcount++;
195 if (dd->hp_ops)
196 cb = uevent ? dd->hp_ops->uevent : dd->hp_ops->handler;
197 }
198
199 mutex_unlock(&hotplug_lock);
200
201 if (!run)
202 return;
203
204 if (cb)
205 cb(dd->handle, event, dd->hp_context);
206
207 dock_release_hotplug(dd);
153} 208}
154 209
155/** 210/**
@@ -360,9 +415,8 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
360 /* 415 /*
361 * First call driver specific hotplug functions 416 * First call driver specific hotplug functions
362 */ 417 */
363 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) 418 list_for_each_entry(dd, &ds->dependent_devices, list)
364 if (dd->ops && dd->ops->handler) 419 dock_hotplug_event(dd, event, false);
365 dd->ops->handler(dd->handle, event, dd->context);
366 420
367 /* 421 /*
368 * Now make sure that an acpi_device is created for each 422 * Now make sure that an acpi_device is created for each
@@ -398,9 +452,8 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
398 if (num == DOCK_EVENT) 452 if (num == DOCK_EVENT)
399 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); 453 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
400 454
401 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) 455 list_for_each_entry(dd, &ds->dependent_devices, list)
402 if (dd->ops && dd->ops->uevent) 456 dock_hotplug_event(dd, event, true);
403 dd->ops->uevent(dd->handle, event, dd->context);
404 457
405 if (num != DOCK_EVENT) 458 if (num != DOCK_EVENT)
406 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); 459 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
@@ -570,19 +623,24 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
570 * @handle: the handle of the device 623 * @handle: the handle of the device
571 * @ops: handlers to call after docking 624 * @ops: handlers to call after docking
572 * @context: device specific data 625 * @context: device specific data
626 * @init: Optional initialization routine to run after registration
627 * @release: Optional release routine to run on unregistration
573 * 628 *
574 * If a driver would like to perform a hotplug operation after a dock 629 * If a driver would like to perform a hotplug operation after a dock
575 * event, they can register an acpi_notifiy_handler to be called by 630 * event, they can register an acpi_notifiy_handler to be called by
576 * the dock driver after _DCK is executed. 631 * the dock driver after _DCK is executed.
577 */ 632 */
578int 633int register_hotplug_dock_device(acpi_handle handle,
579register_hotplug_dock_device(acpi_handle handle, const struct acpi_dock_ops *ops, 634 const struct acpi_dock_ops *ops, void *context,
580 void *context) 635 void (*init)(void *), void (*release)(void *))
581{ 636{
582 struct dock_dependent_device *dd; 637 struct dock_dependent_device *dd;
583 struct dock_station *dock_station; 638 struct dock_station *dock_station;
584 int ret = -EINVAL; 639 int ret = -EINVAL;
585 640
641 if (WARN_ON(!context))
642 return -EINVAL;
643
586 if (!dock_station_count) 644 if (!dock_station_count)
587 return -ENODEV; 645 return -ENODEV;
588 646
@@ -597,12 +655,8 @@ register_hotplug_dock_device(acpi_handle handle, const struct acpi_dock_ops *ops
597 * ops 655 * ops
598 */ 656 */
599 dd = find_dock_dependent_device(dock_station, handle); 657 dd = find_dock_dependent_device(dock_station, handle);
600 if (dd) { 658 if (dd && !dock_init_hotplug(dd, ops, context, init, release))
601 dd->ops = ops;
602 dd->context = context;
603 dock_add_hotplug_device(dock_station, dd);
604 ret = 0; 659 ret = 0;
605 }
606 } 660 }
607 661
608 return ret; 662 return ret;
@@ -624,7 +678,7 @@ void unregister_hotplug_dock_device(acpi_handle handle)
624 list_for_each_entry(dock_station, &dock_stations, sibling) { 678 list_for_each_entry(dock_station, &dock_stations, sibling) {
625 dd = find_dock_dependent_device(dock_station, handle); 679 dd = find_dock_dependent_device(dock_station, handle);
626 if (dd) 680 if (dd)
627 dock_del_hotplug_device(dock_station, dd); 681 dock_release_hotplug(dd);
628 } 682 }
629} 683}
630EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); 684EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
@@ -953,7 +1007,6 @@ static int __init dock_add(acpi_handle handle)
953 mutex_init(&dock_station->hp_lock); 1007 mutex_init(&dock_station->hp_lock);
954 spin_lock_init(&dock_station->dd_lock); 1008 spin_lock_init(&dock_station->dd_lock);
955 INIT_LIST_HEAD(&dock_station->sibling); 1009 INIT_LIST_HEAD(&dock_station->sibling);
956 INIT_LIST_HEAD(&dock_station->hotplug_devices);
957 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); 1010 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
958 INIT_LIST_HEAD(&dock_station->dependent_devices); 1011 INIT_LIST_HEAD(&dock_station->dependent_devices);
959 1012
@@ -994,30 +1047,6 @@ err_unregister:
994} 1047}
995 1048
996/** 1049/**
997 * dock_remove - free up resources related to the dock station
998 */
999static int dock_remove(struct dock_station *ds)
1000{
1001 struct dock_dependent_device *dd, *tmp;
1002 struct platform_device *dock_device = ds->dock_device;
1003
1004 if (!dock_station_count)
1005 return 0;
1006
1007 /* remove dependent devices */
1008 list_for_each_entry_safe(dd, tmp, &ds->dependent_devices, list)
1009 kfree(dd);
1010
1011 list_del(&ds->sibling);
1012
1013 /* cleanup sysfs */
1014 sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group);
1015 platform_device_unregister(dock_device);
1016
1017 return 0;
1018}
1019
1020/**
1021 * find_dock_and_bay - look for dock stations and bays 1050 * find_dock_and_bay - look for dock stations and bays
1022 * @handle: acpi handle of a device 1051 * @handle: acpi handle of a device
1023 * @lvl: unused 1052 * @lvl: unused
@@ -1035,7 +1064,7 @@ find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
1035 return AE_OK; 1064 return AE_OK;
1036} 1065}
1037 1066
1038static int __init dock_init(void) 1067int __init acpi_dock_init(void)
1039{ 1068{
1040 if (acpi_disabled) 1069 if (acpi_disabled)
1041 return 0; 1070 return 0;
@@ -1054,19 +1083,3 @@ static int __init dock_init(void)
1054 ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); 1083 ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
1055 return 0; 1084 return 0;
1056} 1085}
1057
1058static void __exit dock_exit(void)
1059{
1060 struct dock_station *tmp, *dock_station;
1061
1062 unregister_acpi_bus_notifier(&dock_acpi_notifier);
1063 list_for_each_entry_safe(dock_station, tmp, &dock_stations, sibling)
1064 dock_remove(dock_station);
1065}
1066
1067/*
1068 * Must be called before drivers of devices in dock, otherwise we can't know
1069 * which devices are in a dock
1070 */
1071subsys_initcall(dock_init);
1072module_exit(dock_exit);
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 297cbf456f86..c610a76d92c4 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -40,6 +40,11 @@ void acpi_container_init(void);
40#else 40#else
41static inline void acpi_container_init(void) {} 41static inline void acpi_container_init(void) {}
42#endif 42#endif
43#ifdef CONFIG_ACPI_DOCK
44void acpi_dock_init(void);
45#else
46static inline void acpi_dock_init(void) {}
47#endif
43#ifdef CONFIG_ACPI_HOTPLUG_MEMORY 48#ifdef CONFIG_ACPI_HOTPLUG_MEMORY
44void acpi_memory_hotplug_init(void); 49void acpi_memory_hotplug_init(void);
45#else 50#else
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index b14ac46948c9..27da63061e11 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2042,6 +2042,7 @@ int __init acpi_scan_init(void)
2042 acpi_lpss_init(); 2042 acpi_lpss_init();
2043 acpi_container_init(); 2043 acpi_container_init();
2044 acpi_memory_hotplug_init(); 2044 acpi_memory_hotplug_init();
2045 acpi_dock_init();
2045 2046
2046 mutex_lock(&acpi_scan_lock); 2047 mutex_lock(&acpi_scan_lock);
2047 /* 2048 /*
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 87f2f395d79a..cf4e7020adac 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -156,8 +156,10 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
156 156
157 spin_unlock_irqrestore(ap->lock, flags); 157 spin_unlock_irqrestore(ap->lock, flags);
158 158
159 if (wait) 159 if (wait) {
160 ata_port_wait_eh(ap); 160 ata_port_wait_eh(ap);
161 flush_work(&ap->hotplug_task.work);
162 }
161} 163}
162 164
163static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data) 165static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
@@ -214,6 +216,39 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = {
214 .uevent = ata_acpi_ap_uevent, 216 .uevent = ata_acpi_ap_uevent,
215}; 217};
216 218
219void ata_acpi_hotplug_init(struct ata_host *host)
220{
221 int i;
222
223 for (i = 0; i < host->n_ports; i++) {
224 struct ata_port *ap = host->ports[i];
225 acpi_handle handle;
226 struct ata_device *dev;
227
228 if (!ap)
229 continue;
230
231 handle = ata_ap_acpi_handle(ap);
232 if (handle) {
233 /* we might be on a docking station */
234 register_hotplug_dock_device(handle,
235 &ata_acpi_ap_dock_ops, ap,
236 NULL, NULL);
237 }
238
239 ata_for_each_dev(dev, &ap->link, ALL) {
240 handle = ata_dev_acpi_handle(dev);
241 if (!handle)
242 continue;
243
244 /* we might be on a docking station */
245 register_hotplug_dock_device(handle,
246 &ata_acpi_dev_dock_ops,
247 dev, NULL, NULL);
248 }
249 }
250}
251
217/** 252/**
218 * ata_acpi_dissociate - dissociate ATA host from ACPI objects 253 * ata_acpi_dissociate - dissociate ATA host from ACPI objects
219 * @host: target ATA host 254 * @host: target ATA host
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index f2184276539d..adf002a3c584 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6148,6 +6148,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
6148 if (rc) 6148 if (rc)
6149 goto err_tadd; 6149 goto err_tadd;
6150 6150
6151 ata_acpi_hotplug_init(host);
6152
6151 /* set cable, sata_spd_limit and report */ 6153 /* set cable, sata_spd_limit and report */
6152 for (i = 0; i < host->n_ports; i++) { 6154 for (i = 0; i < host->n_ports; i++) {
6153 struct ata_port *ap = host->ports[i]; 6155 struct ata_port *ap = host->ports[i];
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index c949dd311b2e..577d902bc4de 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -122,6 +122,7 @@ extern int ata_acpi_register(void);
122extern void ata_acpi_unregister(void); 122extern void ata_acpi_unregister(void);
123extern void ata_acpi_bind(struct ata_device *dev); 123extern void ata_acpi_bind(struct ata_device *dev);
124extern void ata_acpi_unbind(struct ata_device *dev); 124extern void ata_acpi_unbind(struct ata_device *dev);
125extern void ata_acpi_hotplug_init(struct ata_host *host);
125#else 126#else
126static inline void ata_acpi_dissociate(struct ata_host *host) { } 127static inline void ata_acpi_dissociate(struct ata_host *host) { }
127static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; } 128static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
@@ -134,6 +135,7 @@ static inline int ata_acpi_register(void) { return 0; }
134static inline void ata_acpi_unregister(void) { } 135static inline void ata_acpi_unregister(void) { }
135static inline void ata_acpi_bind(struct ata_device *dev) { } 136static inline void ata_acpi_bind(struct ata_device *dev) { }
136static inline void ata_acpi_unbind(struct ata_device *dev) { } 137static inline void ata_acpi_unbind(struct ata_device *dev) { }
138static inline void ata_acpi_hotplug_init(struct ata_host *host) {}
137#endif 139#endif
138 140
139/* libata-scsi.c */ 141/* libata-scsi.c */
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);
61static void handle_hotplug_event_bridge (acpi_handle, u32, void *); 61static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
62static void acpiphp_sanitize_bus(struct pci_bus *bus); 62static void acpiphp_sanitize_bus(struct pci_bus *bus);
63static void acpiphp_set_hpp_values(struct pci_bus *bus); 63static void acpiphp_set_hpp_values(struct pci_bus *bus);
64static void hotplug_event_func(acpi_handle handle, u32 type, void *context);
64static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); 65static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context);
65static void free_bridge(struct kref *kref); 66static void free_bridge(struct kref *kref);
66 67
@@ -147,7 +148,7 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
147 148
148 149
149static const struct acpi_dock_ops acpiphp_dock_ops = { 150static const struct acpi_dock_ops acpiphp_dock_ops = {
150 .handler = handle_hotplug_event_func, 151 .handler = hotplug_event_func,
151}; 152};
152 153
153/* Check whether the PCI device is managed by native PCIe hotplug driver */ 154/* 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)
179 return true; 180 return true;
180} 181}
181 182
183static void acpiphp_dock_init(void *data)
184{
185 struct acpiphp_func *func = data;
186
187 get_bridge(func->slot->bridge);
188}
189
190static void acpiphp_dock_release(void *data)
191{
192 struct acpiphp_func *func = data;
193
194 put_bridge(func->slot->bridge);
195}
196
182/* callback routine to register each ACPI PCI slot object */ 197/* callback routine to register each ACPI PCI slot object */
183static acpi_status 198static acpi_status
184register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) 199register_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)
298 */ 313 */
299 newfunc->flags &= ~FUNC_HAS_EJ0; 314 newfunc->flags &= ~FUNC_HAS_EJ0;
300 if (register_hotplug_dock_device(handle, 315 if (register_hotplug_dock_device(handle,
301 &acpiphp_dock_ops, newfunc)) 316 &acpiphp_dock_ops, newfunc,
317 acpiphp_dock_init, acpiphp_dock_release))
302 dbg("failed to register dock device\n"); 318 dbg("failed to register dock device\n");
303 319
304 /* we need to be notified when dock events happen 320 /* we need to be notified when dock events happen
@@ -670,6 +686,7 @@ static int __ref enable_device(struct acpiphp_slot *slot)
670 struct pci_bus *bus = slot->bridge->pci_bus; 686 struct pci_bus *bus = slot->bridge->pci_bus;
671 struct acpiphp_func *func; 687 struct acpiphp_func *func;
672 int num, max, pass; 688 int num, max, pass;
689 LIST_HEAD(add_list);
673 690
674 if (slot->flags & SLOT_ENABLED) 691 if (slot->flags & SLOT_ENABLED)
675 goto err_exit; 692 goto err_exit;
@@ -694,13 +711,15 @@ static int __ref enable_device(struct acpiphp_slot *slot)
694 max = pci_scan_bridge(bus, dev, max, pass); 711 max = pci_scan_bridge(bus, dev, max, pass);
695 if (pass && dev->subordinate) { 712 if (pass && dev->subordinate) {
696 check_hotplug_bridge(slot, dev); 713 check_hotplug_bridge(slot, dev);
697 pci_bus_size_bridges(dev->subordinate); 714 pcibios_resource_survey_bus(dev->subordinate);
715 __pci_bus_size_bridges(dev->subordinate,
716 &add_list);
698 } 717 }
699 } 718 }
700 } 719 }
701 } 720 }
702 721
703 pci_bus_assign_resources(bus); 722 __pci_bus_assign_resources(bus, &add_list, NULL);
704 acpiphp_sanitize_bus(bus); 723 acpiphp_sanitize_bus(bus);
705 acpiphp_set_hpp_values(bus); 724 acpiphp_set_hpp_values(bus);
706 acpiphp_set_acpi_region(slot); 725 acpiphp_set_acpi_region(slot);
@@ -1065,22 +1084,12 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
1065 alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge); 1084 alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);
1066} 1085}
1067 1086
1068static void _handle_hotplug_event_func(struct work_struct *work) 1087static void hotplug_event_func(acpi_handle handle, u32 type, void *context)
1069{ 1088{
1070 struct acpiphp_func *func; 1089 struct acpiphp_func *func = context;
1071 char objname[64]; 1090 char objname[64];
1072 struct acpi_buffer buffer = { .length = sizeof(objname), 1091 struct acpi_buffer buffer = { .length = sizeof(objname),
1073 .pointer = objname }; 1092 .pointer = objname };
1074 struct acpi_hp_work *hp_work;
1075 acpi_handle handle;
1076 u32 type;
1077
1078 hp_work = container_of(work, struct acpi_hp_work, work);
1079 handle = hp_work->handle;
1080 type = hp_work->type;
1081 func = (struct acpiphp_func *)hp_work->context;
1082
1083 acpi_scan_lock_acquire();
1084 1093
1085 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); 1094 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1086 1095
@@ -1113,6 +1122,18 @@ static void _handle_hotplug_event_func(struct work_struct *work)
1113 warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); 1122 warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
1114 break; 1123 break;
1115 } 1124 }
1125}
1126
1127static void _handle_hotplug_event_func(struct work_struct *work)
1128{
1129 struct acpi_hp_work *hp_work;
1130 struct acpiphp_func *func;
1131
1132 hp_work = container_of(work, struct acpi_hp_work, work);
1133 func = hp_work->context;
1134 acpi_scan_lock_acquire();
1135
1136 hotplug_event_func(hp_work->handle, hp_work->type, func);
1116 1137
1117 acpi_scan_lock_release(); 1138 acpi_scan_lock_release();
1118 kfree(hp_work); /* allocated in handle_hotplug_event_func */ 1139 kfree(hp_work); /* allocated in handle_hotplug_event_func */
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 68678ed76b0d..d1182c4a754e 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -202,6 +202,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
202 struct resource *res, unsigned int reg); 202 struct resource *res, unsigned int reg);
203int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type); 203int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type);
204void pci_configure_ari(struct pci_dev *dev); 204void pci_configure_ari(struct pci_dev *dev);
205void __ref __pci_bus_size_bridges(struct pci_bus *bus,
206 struct list_head *realloc_head);
207void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
208 struct list_head *realloc_head,
209 struct list_head *fail_head);
205 210
206/** 211/**
207 * pci_ari_enabled - query ARI forwarding status 212 * pci_ari_enabled - query ARI forwarding status
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 16abaaa1f83c..d254e2379533 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1044,7 +1044,7 @@ handle_done:
1044 ; 1044 ;
1045} 1045}
1046 1046
1047static void __ref __pci_bus_size_bridges(struct pci_bus *bus, 1047void __ref __pci_bus_size_bridges(struct pci_bus *bus,
1048 struct list_head *realloc_head) 1048 struct list_head *realloc_head)
1049{ 1049{
1050 struct pci_dev *dev; 1050 struct pci_dev *dev;
@@ -1115,9 +1115,9 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
1115} 1115}
1116EXPORT_SYMBOL(pci_bus_size_bridges); 1116EXPORT_SYMBOL(pci_bus_size_bridges);
1117 1117
1118static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, 1118void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
1119 struct list_head *realloc_head, 1119 struct list_head *realloc_head,
1120 struct list_head *fail_head) 1120 struct list_head *fail_head)
1121{ 1121{
1122 struct pci_bus *b; 1122 struct pci_bus *b;
1123 struct pci_dev *dev; 1123 struct pci_dev *dev;
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index e6168a24b9f0..b420939f5eb5 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -123,7 +123,9 @@ extern int register_dock_notifier(struct notifier_block *nb);
123extern void unregister_dock_notifier(struct notifier_block *nb); 123extern void unregister_dock_notifier(struct notifier_block *nb);
124extern int register_hotplug_dock_device(acpi_handle handle, 124extern int register_hotplug_dock_device(acpi_handle handle,
125 const struct acpi_dock_ops *ops, 125 const struct acpi_dock_ops *ops,
126 void *context); 126 void *context,
127 void (*init)(void *),
128 void (*release)(void *));
127extern void unregister_hotplug_dock_device(acpi_handle handle); 129extern void unregister_hotplug_dock_device(acpi_handle handle);
128#else 130#else
129static inline int is_dock_device(acpi_handle handle) 131static inline int is_dock_device(acpi_handle handle)
@@ -139,7 +141,9 @@ static inline void unregister_dock_notifier(struct notifier_block *nb)
139} 141}
140static inline int register_hotplug_dock_device(acpi_handle handle, 142static inline int register_hotplug_dock_device(acpi_handle handle,
141 const struct acpi_dock_ops *ops, 143 const struct acpi_dock_ops *ops,
142 void *context) 144 void *context,
145 void (*init)(void *),
146 void (*release)(void *))
143{ 147{
144 return -ENODEV; 148 return -ENODEV;
145} 149}