aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/acpiphp_glue.c
diff options
context:
space:
mode:
authorKristen Accardi <kristen.c.accardi@intel.com>2006-06-28 03:08:06 -0400
committerLen Brown <len.brown@intel.com>2006-06-28 03:08:06 -0400
commit4e8662bbd680c54496189ac68f398e847f3ca374 (patch)
tree8f9a0be5098b206025cd63fe965ccc37c922753e /drivers/pci/hotplug/acpiphp_glue.c
parenta5e1b94008f2a96abf4a0c0371a55a56b320c13e (diff)
ACPIPHP: use ACPI dock driver
Modify the acpiphp driver to use the ACPI dock driver for dock notifications. Only load the acpiphp driver if we find we have pci dock devices. Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c111
1 files changed, 84 insertions, 27 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index d370f999782e..faf7eed5d963 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -116,6 +116,59 @@ is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
116 } 116 }
117} 117}
118 118
119/* callback routine to check for the existance of a pci dock device */
120static acpi_status
121is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
122{
123 int *count = (int *)context;
124
125 if (is_dock_device(handle)) {
126 (*count)++;
127 return AE_CTRL_TERMINATE;
128 } else {
129 return AE_OK;
130 }
131}
132
133
134
135
136/*
137 * the _DCK method can do funny things... and sometimes not
138 * hah-hah funny.
139 *
140 * TBD - figure out a way to only call fixups for
141 * systems that require them.
142 */
143static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
144 void *v)
145{
146 struct acpiphp_func *func = container_of(nb, struct acpiphp_func, nb);
147 struct pci_bus *bus = func->slot->bridge->pci_bus;
148 u32 buses;
149
150 if (!bus->self)
151 return NOTIFY_OK;
152
153 /* fixup bad _DCK function that rewrites
154 * secondary bridge on slot
155 */
156 pci_read_config_dword(bus->self,
157 PCI_PRIMARY_BUS,
158 &buses);
159
160 if (((buses >> 8) & 0xff) != bus->secondary) {
161 buses = (buses & 0xff000000)
162 | ((unsigned int)(bus->primary) << 0)
163 | ((unsigned int)(bus->secondary) << 8)
164 | ((unsigned int)(bus->subordinate) << 16);
165 pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
166 }
167 return NOTIFY_OK;
168}
169
170
171
119 172
120/* callback routine to register each ACPI PCI slot object */ 173/* callback routine to register each ACPI PCI slot object */
121static acpi_status 174static acpi_status
@@ -124,7 +177,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
124 struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; 177 struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
125 struct acpiphp_slot *slot; 178 struct acpiphp_slot *slot;
126 struct acpiphp_func *newfunc; 179 struct acpiphp_func *newfunc;
127 struct dependent_device *dd;
128 acpi_handle tmp; 180 acpi_handle tmp;
129 acpi_status status = AE_OK; 181 acpi_status status = AE_OK;
130 unsigned long adr, sun; 182 unsigned long adr, sun;
@@ -137,7 +189,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
137 189
138 status = acpi_get_handle(handle, "_EJ0", &tmp); 190 status = acpi_get_handle(handle, "_EJ0", &tmp);
139 191
140 if (ACPI_FAILURE(status) && !(is_dependent_device(handle))) 192 if (ACPI_FAILURE(status) && !(is_dock_device(handle)))
141 return AE_OK; 193 return AE_OK;
142 194
143 device = (adr >> 16) & 0xffff; 195 device = (adr >> 16) & 0xffff;
@@ -162,18 +214,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
162 if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) 214 if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
163 newfunc->flags |= FUNC_HAS_PS3; 215 newfunc->flags |= FUNC_HAS_PS3;
164 216
165 if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) { 217 if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp)))
166 newfunc->flags |= FUNC_HAS_DCK; 218 newfunc->flags |= FUNC_HAS_DCK;
167 /* add to devices dependent on dock station,
168 * because this may actually be the dock bridge
169 */
170 dd = alloc_dependent_device(handle);
171 if (!dd)
172 err("Can't allocate memory for "
173 "new dependent device!\n");
174 else
175 add_dependent_device(dd);
176 }
177 219
178 status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); 220 status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
179 if (ACPI_FAILURE(status)) 221 if (ACPI_FAILURE(status))
@@ -225,20 +267,23 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
225 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); 267 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
226 } 268 }
227 269
228 /* if this is a device dependent on a dock station, 270 if (is_dock_device(handle)) {
229 * associate the acpiphp_func to the dependent_device 271 /* we don't want to call this device's _EJ0
230 * struct. 272 * because we want the dock notify handler
231 */ 273 * to call it after it calls _DCK
232 if ((dd = get_dependent_device(handle))) {
233 newfunc->flags |= FUNC_IS_DD;
234 /*
235 * we don't want any devices which is dependent
236 * on the dock to have it's _EJ0 method executed.
237 * because we need to run _DCK first.
238 */ 274 */
239 newfunc->flags &= ~FUNC_HAS_EJ0; 275 newfunc->flags &= ~FUNC_HAS_EJ0;
240 dd->func = newfunc; 276 if (register_hotplug_dock_device(handle,
241 add_pci_dependent_device(dd); 277 handle_hotplug_event_func, newfunc))
278 dbg("failed to register dock device\n");
279
280 /* we need to be notified when dock events happen
281 * outside of the hotplug operation, since we may
282 * need to do fixups before we can hotplug.
283 */
284 newfunc->nb.notifier_call = post_dock_fixups;
285 if (register_dock_notifier(&newfunc->nb))
286 dbg("failed to register a dock notifier");
242 } 287 }
243 288
244 /* install notify handler */ 289 /* install notify handler */
@@ -277,6 +322,15 @@ static int detect_ejectable_slots(acpi_handle *bridge_handle)
277 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1, 322 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
278 is_ejectable_slot, (void *)&count, NULL); 323 is_ejectable_slot, (void *)&count, NULL);
279 324
325 /*
326 * we also need to add this bridge if there is a dock bridge or
327 * other pci device on a dock station (removable)
328 */
329 if (!count)
330 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle,
331 (u32)1, is_pci_dock_device, (void *)&count,
332 NULL);
333
280 return count; 334 return count;
281} 335}
282 336
@@ -487,8 +541,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
487 goto out; 541 goto out;
488 542
489 /* check if this bridge has ejectable slots */ 543 /* check if this bridge has ejectable slots */
490 if ((detect_ejectable_slots(handle) > 0) || 544 if ((detect_ejectable_slots(handle) > 0)) {
491 (detect_dependent_devices(handle) > 0)) {
492 dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); 545 dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
493 add_p2p_bridge(handle, dev); 546 add_p2p_bridge(handle, dev);
494 } 547 }
@@ -605,6 +658,10 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
605 list_for_each_safe (list, tmp, &slot->funcs) { 658 list_for_each_safe (list, tmp, &slot->funcs) {
606 struct acpiphp_func *func; 659 struct acpiphp_func *func;
607 func = list_entry(list, struct acpiphp_func, sibling); 660 func = list_entry(list, struct acpiphp_func, sibling);
661 if (is_dock_device(func->handle)) {
662 unregister_hotplug_dock_device(func->handle);
663 unregister_dock_notifier(&func->nb);
664 }
608 if (!(func->flags & FUNC_HAS_DCK)) { 665 if (!(func->flags & FUNC_HAS_DCK)) {
609 status = acpi_remove_notify_handler(func->handle, 666 status = acpi_remove_notify_handler(func->handle,
610 ACPI_SYSTEM_NOTIFY, 667 ACPI_SYSTEM_NOTIFY,