acpiphp_glue.c revision e81995bb1c0077a312cb621abc406a36f65a986a
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ACPI PCI HotPlug glue functions to ACPI CA subsystem
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002,2003 NEC Corporation
742f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)
842f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah * Copyright (C) 2003-2005 Hewlett Packard
98e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah * Copyright (C) 2005 Rajesh Shah (rajesh.shah@intel.com)
108e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah * Copyright (C) 2005 Intel Corporation
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All rights reserved.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * your option) any later version.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NON INFRINGEMENT.  See the GNU General Public License for more
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * details.
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
29998be20fdff12274cd0e6a9f71ce1a93abf40718Kristen Carlson Accardi * Send feedback to <kristen.c.accardi@intel.com>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3342f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah/*
3442f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah * Lifetime rules for pci_dev:
3542f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah *  - The one in acpiphp_bridge has its refcount elevated by pci_get_slot()
3642f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah *    when the bridge is scanned and it loses a refcount when the bridge
3742f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah *    is removed.
385d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang *  - When a P2P bridge is present, we elevate the refcount on the subordinate
395d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang *    bus. It loses the refcount when the the driver unloads.
4042f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah */
4142f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
477a54f25cef6c763f16c9fd49ae382de162147873Greg Kroah-Hartman#include <linux/pci_hotplug.h>
48e8c331e963c58b83db24b7d0e39e8c07f687dbc6Kenji Kaneshige#include <linux/pci-acpi.h>
496aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar#include <linux/mutex.h>
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "../pci.h"
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "acpiphp.h"
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic LIST_HEAD(bridge_list);
55600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchistatic LIST_HEAD(ioapic_list);
56600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchistatic DEFINE_SPINLOCK(ioapic_list_lock);
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MY_NAME "acpiphp_glue"
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void handle_hotplug_event_bridge (acpi_handle, u32, void *);
618e5dce35221850759671b2847a2e51030f7626bdKristen Accardistatic void acpiphp_sanitize_bus(struct pci_bus *bus);
62fca6825ad7382ae9df8ecda9068ac13ee9e343f4Bjorn Helgaasstatic void acpiphp_set_hpp_values(struct pci_bus *bus);
632b85e1307fe3a84eca2e1a21c6c857359908dab4Len Brownstatic void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context);
648e5dce35221850759671b2847a2e51030f7626bdKristen Accardi
655a340ed87987c8c61dd9d1a8a5384dab1ace2566MUNEDA Takahiro/* callback routine to check for the existence of a pci dock device */
664e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardistatic acpi_status
674e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardiis_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
684e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi{
694e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	int *count = (int *)context;
704e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi
714e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	if (is_dock_device(handle)) {
724e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		(*count)++;
734e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		return AE_CTRL_TERMINATE;
744e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	} else {
754e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		return AE_OK;
764e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	}
774e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi}
784e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi
794e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi/*
804e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi * the _DCK method can do funny things... and sometimes not
814e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi * hah-hah funny.
824e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi *
834e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi * TBD - figure out a way to only call fixups for
844e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi * systems that require them.
854e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi */
864e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardistatic int post_dock_fixups(struct notifier_block *nb, unsigned long val,
874e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	void *v)
884e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi{
894e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	struct acpiphp_func *func = container_of(nb, struct acpiphp_func, nb);
904e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	struct pci_bus *bus = func->slot->bridge->pci_bus;
914e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	u32 buses;
924e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi
934e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	if (!bus->self)
944e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		return  NOTIFY_OK;
954e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi
964e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	/* fixup bad _DCK function that rewrites
974e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	 * secondary bridge on slot
984e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	 */
994e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	pci_read_config_dword(bus->self,
1004e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi			PCI_PRIMARY_BUS,
1014e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi			&buses);
1024e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi
1034e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	if (((buses >> 8) & 0xff) != bus->secondary) {
1044e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		buses = (buses & 0xff000000)
1052a9d35219c593bdf46ec21f2b75a6370af7af1b0Alex Chiang			| ((unsigned int)(bus->primary)     <<  0)
1062a9d35219c593bdf46ec21f2b75a6370af7af1b0Alex Chiang			| ((unsigned int)(bus->secondary)   <<  8)
1072a9d35219c593bdf46ec21f2b75a6370af7af1b0Alex Chiang			| ((unsigned int)(bus->subordinate) << 16);
1084e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
1094e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	}
1104e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	return NOTIFY_OK;
1114e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi}
1124e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi
1134e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi
1141253f7aabfebc51446dbec5c8895c5c8846dfe06Shaohua Listatic struct acpi_dock_ops acpiphp_dock_ops = {
1151253f7aabfebc51446dbec5c8895c5c8846dfe06Shaohua Li	.handler = handle_hotplug_event_func,
1161253f7aabfebc51446dbec5c8895c5c8846dfe06Shaohua Li};
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* callback routine to register each ACPI PCI slot object */
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic acpi_status
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsregister_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_slot *slot;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_func *newfunc;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_handle tmp;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_status status = AE_OK;
12727663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox	unsigned long long adr, sun;
128e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro	int device, function, retval;
129e8c331e963c58b83db24b7d0e39e8c07f687dbc6Kenji Kaneshige	struct pci_bus *pbus = bridge->pci_bus;
1309d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang	struct pci_dev *pdev;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
132e8c331e963c58b83db24b7d0e39e8c07f687dbc6Kenji Kaneshige	if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return AE_OK;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13556ee325e25a0f76fc3267872867b3d70af179aadMatthew Garrett	acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device = (adr >> 16) & 0xffff;
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	function = adr & 0xffff;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
139f5afe8064f3087bead8fea7e32547c2a3ada5fd0Eric Sesterhenn	newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!newfunc)
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return AE_NO_MEMORY;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&newfunc->sibling);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	newfunc->handle = handle;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	newfunc->function = function;
14656ee325e25a0f76fc3267872867b3d70af179aadMatthew Garrett
14756ee325e25a0f76fc3267872867b3d70af179aadMatthew Garrett	if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
14820416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		newfunc->flags = FUNC_HAS_EJ0;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		newfunc->flags |= FUNC_HAS_STA;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp)))
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		newfunc->flags |= FUNC_HAS_PS0;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		newfunc->flags |= FUNC_HAS_PS3;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1594e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp)))
16020416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		newfunc->flags |= FUNC_HAS_DCK;
16120416ea54087c25502d6fb973b8e119973e16341Kristen Accardi
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
16395b38b3f453c16de0f8cddcde3e71050bbfb37b9Kristen Accardi	if (ACPI_FAILURE(status)) {
16495b38b3f453c16de0f8cddcde3e71050bbfb37b9Kristen Accardi		/*
16595b38b3f453c16de0f8cddcde3e71050bbfb37b9Kristen Accardi		 * use the count of the number of slots we've found
16695b38b3f453c16de0f8cddcde3e71050bbfb37b9Kristen Accardi		 * for the number of the slot
16795b38b3f453c16de0f8cddcde3e71050bbfb37b9Kristen Accardi		 */
16895b38b3f453c16de0f8cddcde3e71050bbfb37b9Kristen Accardi		sun = bridge->nr_slots+1;
16995b38b3f453c16de0f8cddcde3e71050bbfb37b9Kristen Accardi	}
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* search for objects that share the same slot */
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (slot = bridge->slots; slot; slot = slot->next)
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (slot->device == device) {
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (slot->sun != sun)
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				warn("sibling found, but _SUN doesn't match!\n");
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!slot) {
180f5afe8064f3087bead8fea7e32547c2a3ada5fd0Eric Sesterhenn		slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!slot) {
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kfree(newfunc);
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return AE_NO_MEMORY;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->bridge = bridge;
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->device = device;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->sun = sun;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		INIT_LIST_HEAD(&slot->funcs);
1906aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar		mutex_init(&slot->crit_sect);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->next = bridge->slots;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bridge->slots = slot;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bridge->nr_slots++;
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
197b6adc1955d31515be6631e63b1fe4bcdcd41db77Justin Chen		dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",
198e8c331e963c58b83db24b7d0e39e8c07f687dbc6Kenji Kaneshige		    slot->sun, pci_domain_nr(pbus), pbus->number, device);
199e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro		retval = acpiphp_register_hotplug_slot(slot);
200e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro		if (retval) {
201f46753c5e354b857b20ab8e0fe7b2579831dc369Alex Chiang			if (retval == -EBUSY)
202b6adc1955d31515be6631e63b1fe4bcdcd41db77Justin Chen				warn("Slot %llu already registered by another "
203f46753c5e354b857b20ab8e0fe7b2579831dc369Alex Chiang					"hotplug driver\n", slot->sun);
204f46753c5e354b857b20ab8e0fe7b2579831dc369Alex Chiang			else
205f46753c5e354b857b20ab8e0fe7b2579831dc369Alex Chiang				warn("acpiphp_register_hotplug_slot failed "
206f46753c5e354b857b20ab8e0fe7b2579831dc369Alex Chiang					"(err code = 0x%x)\n", retval);
207e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro			goto err_exit;
208e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro		}
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	newfunc->slot = slot;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_add_tail(&newfunc->sibling, &slot->funcs);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2149d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang	pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
2159d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang	if (pdev) {
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
2179d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang		pci_dev_put(pdev);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2204e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi	if (is_dock_device(handle)) {
2214e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		/* we don't want to call this device's _EJ0
2224e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		 * because we want the dock notify handler
2234e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		 * to call it after it calls _DCK
22420416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		 */
22520416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		newfunc->flags &= ~FUNC_HAS_EJ0;
2264e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		if (register_hotplug_dock_device(handle,
2271253f7aabfebc51446dbec5c8895c5c8846dfe06Shaohua Li			&acpiphp_dock_ops, newfunc))
2284e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi			dbg("failed to register dock device\n");
2294e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi
2304e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		/* we need to be notified when dock events happen
2314e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		 * outside of the hotplug operation, since we may
2324e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		 * need to do fixups before we can hotplug.
2334e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		 */
2344e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		newfunc->nb.notifier_call = post_dock_fixups;
2354e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi		if (register_dock_notifier(&newfunc->nb))
2364e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi			dbg("failed to register a dock notifier");
23720416ea54087c25502d6fb973b8e119973e16341Kristen Accardi	}
23820416ea54087c25502d6fb973b8e119973e16341Kristen Accardi
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* install notify handler */
24020416ea54087c25502d6fb973b8e119973e16341Kristen Accardi	if (!(newfunc->flags & FUNC_HAS_DCK)) {
24120416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		status = acpi_install_notify_handler(handle,
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     ACPI_SYSTEM_NOTIFY,
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     handle_hotplug_event_func,
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     newfunc);
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24620416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		if (ACPI_FAILURE(status))
24720416ea54087c25502d6fb973b8e119973e16341Kristen Accardi			err("failed to register interrupt notify handler\n");
24820416ea54087c25502d6fb973b8e119973e16341Kristen Accardi	} else
24920416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		status = AE_OK;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25120416ea54087c25502d6fb973b8e119973e16341Kristen Accardi	return status;
252e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro
253e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro err_exit:
254e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro	bridge->nr_slots--;
255e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro	bridge->slots = slot->next;
256e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro	kfree(slot);
257e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro	kfree(newfunc);
258e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro
259e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro	return AE_OK;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* see if it's worth looking at this bridge */
2646edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiangstatic int detect_ejectable_slots(acpi_handle handle)
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2667f53866932fd08add06ee2f93ead129949158490Alex Chiang	int found = acpi_pci_detect_ejectable(handle);
267e8c331e963c58b83db24b7d0e39e8c07f687dbc6Kenji Kaneshige	if (!found) {
2686edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
269e8c331e963c58b83db24b7d0e39e8c07f687dbc6Kenji Kaneshige				    is_pci_dock_device, (void *)&found, NULL);
270e8c331e963c58b83db24b7d0e39e8c07f687dbc6Kenji Kaneshige	}
271e8c331e963c58b83db24b7d0e39e8c07f687dbc6Kenji Kaneshige	return found;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void init_bridge_misc(struct acpiphp_bridge *bridge)
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_status status;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
279e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro	/* must be added to the list prior to calling register_slot */
280e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro	list_add(&bridge->list, &bridge_list);
281e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* register all slot objects under this bridge */
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     register_slot, bridge, NULL);
285e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro	if (ACPI_FAILURE(status)) {
286e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro		list_del(&bridge->list);
287e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro		return;
288e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro	}
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* install notify handler */
2918e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	if (bridge->type != BRIDGE_TYPE_HOST) {
292551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
293551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			status = acpi_remove_notify_handler(bridge->func->handle,
294551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro						ACPI_SYSTEM_NOTIFY,
295551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro						handle_hotplug_event_func);
296551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			if (ACPI_FAILURE(status))
297551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro				err("failed to remove notify handler\n");
298551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		}
2998e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		status = acpi_install_notify_handler(bridge->handle,
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     ACPI_SYSTEM_NOTIFY,
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     handle_hotplug_event_bridge,
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     bridge);
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3048e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		if (ACPI_FAILURE(status)) {
3058e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah			err("failed to register interrupt notify handler\n");
3068e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		}
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro/* find acpiphp_func from acpiphp_bridge */
312551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahirostatic struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle)
313551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro{
314551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	struct list_head *node, *l;
315551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	struct acpiphp_bridge *bridge;
316551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	struct acpiphp_slot *slot;
317551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	struct acpiphp_func *func;
318551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
319551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	list_for_each(node, &bridge_list) {
320551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		bridge = list_entry(node, struct acpiphp_bridge, list);
321551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		for (slot = bridge->slots; slot; slot = slot->next) {
322551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			list_for_each(l, &slot->funcs) {
323551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro				func = list_entry(l, struct acpiphp_func,
324551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro							sibling);
325551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro				if (func->handle == handle)
326551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro					return func;
327551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			}
328551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		}
329551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	}
330551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
331551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	return NULL;
332551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro}
333551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
334551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
335551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahirostatic inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
336551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro{
337551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	acpi_handle dummy_handle;
338551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
339551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
340551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro					"_STA", &dummy_handle)))
341551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		bridge->flags |= BRIDGE_HAS_STA;
342551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
343551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
344551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro					"_EJ0", &dummy_handle)))
345551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		bridge->flags |= BRIDGE_HAS_EJ0;
346551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
347551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
348551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro					"_PS0", &dummy_handle)))
349551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		bridge->flags |= BRIDGE_HAS_PS0;
350551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
351551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
352551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro					"_PS3", &dummy_handle)))
353551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		bridge->flags |= BRIDGE_HAS_PS3;
354551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
355551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	/* is this ejectable p2p bridge? */
356551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	if (bridge->flags & BRIDGE_HAS_EJ0) {
357551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		struct acpiphp_func *func;
358551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
359551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		dbg("found ejectable p2p bridge\n");
360551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
361551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		/* make link between PCI bridge and PCI function */
362551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		func = acpiphp_bridge_handle_to_function(bridge->handle);
363551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		if (!func)
364551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			return;
365551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		bridge->func = func;
366551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		func->bridge = bridge;
367551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	}
368551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro}
369551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
370551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* allocate and initialize host bridge data structure */
3726edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiangstatic void add_host_bridge(acpi_handle *handle)
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_bridge *bridge;
3756edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang	struct acpi_pci_root *root = acpi_pci_find_root(handle);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
377f5afe8064f3087bead8fea7e32547c2a3ada5fd0Eric Sesterhenn	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bridge == NULL)
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bridge->type = BRIDGE_TYPE_HOST;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bridge->handle = handle;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3846edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang	bridge->pci_bus = root->bus;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&bridge->res_lock);
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_bridge_misc(bridge);
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* allocate and initialize PCI-to-PCI bridge data structure */
3936edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiangstatic void add_p2p_bridge(acpi_handle *handle)
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_bridge *bridge;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
397f5afe8064f3087bead8fea7e32547c2a3ada5fd0Eric Sesterhenn	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bridge == NULL) {
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("out of memory\n");
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bridge->type = BRIDGE_TYPE_P2P;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bridge->handle = handle;
405551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	config_p2p_bridge_flags(bridge);
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4076edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang	bridge->pci_dev = acpi_get_pci_dev(handle);
4086edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang	bridge->pci_bus = bridge->pci_dev->subordinate;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!bridge->pci_bus) {
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("This is not a PCI-to-PCI bridge!\n");
41142f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		goto err;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4145d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang	/*
4155d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang	 * Grab a ref to the subordinate PCI bus in case the bus is
4165d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang	 * removed via PCI core logical hotplug. The ref pins the bus
4175d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang	 * (which we access during module unload).
4185d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang	 */
4195d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang	get_device(&bridge->pci_bus->dev);
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&bridge->res_lock);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_bridge_misc(bridge);
42342f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	return;
42442f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah err:
4256edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang	pci_dev_put(bridge->pci_dev);
42642f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	kfree(bridge);
42742f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	return;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* callback routine to find P2P bridges */
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic acpi_status
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfind_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_status status;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4386edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang	dev = acpi_get_pci_dev(handle);
43942f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	if (!dev || !dev->subordinate)
44042f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		goto out;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if this bridge has ejectable slots */
4436edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang	if ((detect_ejectable_slots(handle) > 0)) {
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
4456edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang		add_p2p_bridge(handle);
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4487c8f25da12a3dda46fb730699582895d5fc51287Kenji Kaneshige	/* search P2P bridges under this p2p bridge */
4497c8f25da12a3dda46fb730699582895d5fc51287Kenji Kaneshige	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
4506edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang				     find_p2p_bridge, NULL, NULL);
4517c8f25da12a3dda46fb730699582895d5fc51287Kenji Kaneshige	if (ACPI_FAILURE(status))
452551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
4537c8f25da12a3dda46fb730699582895d5fc51287Kenji Kaneshige
45442f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah out:
45542f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	pci_dev_put(dev);
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return AE_OK;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* find hot-pluggable slots, and then find P2P bridge */
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int add_bridge(acpi_handle handle)
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_status status;
46427663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox	unsigned long long tmp;
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_handle dummy_handle;
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the bridge doesn't have _STA, we assume it is always there */
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = acpi_get_handle(handle, "_STA", &dummy_handle);
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ACPI_SUCCESS(status)) {
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ACPI_FAILURE(status)) {
47266bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison			dbg("%s: _STA evaluation failure\n", __func__);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((tmp & ACPI_STA_FUNCTIONING) == 0)
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* don't register this object */
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if this bridge has ejectable slots */
4816edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang	if (detect_ejectable_slots(handle) > 0) {
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dbg("found PCI host-bus bridge with hot-pluggable slots\n");
4836edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang		add_host_bridge(handle);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* search P2P bridges under this host bridge */
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
4886edd7679db92376ca54f328d6b0f12291c2dab35Alex Chiang				     find_p2p_bridge, NULL, NULL);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ACPI_FAILURE(status))
491551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49642f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shahstatic struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
49742f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah{
49842f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	struct list_head *head;
49942f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	list_for_each(head, &bridge_list) {
50042f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		struct acpiphp_bridge *bridge = list_entry(head,
50142f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah						struct acpiphp_bridge, list);
50242f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		if (bridge->handle == handle)
50342f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah			return bridge;
50442f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	}
50542f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah
50642f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	return NULL;
50742f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah}
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
509364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shahstatic void cleanup_bridge(struct acpiphp_bridge *bridge)
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
51142f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	struct list_head *list, *tmp;
51242f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	struct acpiphp_slot *slot;
51342f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	acpi_status status;
514364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah	acpi_handle handle = bridge->handle;
51542f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah
51642f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
51742f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah					    handle_hotplug_event_bridge);
51842f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	if (ACPI_FAILURE(status))
51942f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		err("failed to remove notify handler\n");
52042f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah
521551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	if ((bridge->type != BRIDGE_TYPE_HOST) &&
522551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	    ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) {
523551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		status = acpi_install_notify_handler(bridge->func->handle,
524551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro						ACPI_SYSTEM_NOTIFY,
525551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro						handle_hotplug_event_func,
526551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro						bridge->func);
527551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		if (ACPI_FAILURE(status))
528551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			err("failed to install interrupt notify handler\n");
529551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	}
530551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
53142f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	slot = bridge->slots;
53242f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	while (slot) {
53342f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		struct acpiphp_slot *next = slot->next;
53442f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		list_for_each_safe (list, tmp, &slot->funcs) {
53542f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah			struct acpiphp_func *func;
53642f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah			func = list_entry(list, struct acpiphp_func, sibling);
5374e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi			if (is_dock_device(func->handle)) {
5384e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi				unregister_hotplug_dock_device(func->handle);
5394e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi				unregister_dock_notifier(&func->nb);
5404e8662bbd680c54496189ac68f398e847f3ca374Kristen Accardi			}
54120416ea54087c25502d6fb973b8e119973e16341Kristen Accardi			if (!(func->flags & FUNC_HAS_DCK)) {
54220416ea54087c25502d6fb973b8e119973e16341Kristen Accardi				status = acpi_remove_notify_handler(func->handle,
54342f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah						ACPI_SYSTEM_NOTIFY,
54442f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah						handle_hotplug_event_func);
54520416ea54087c25502d6fb973b8e119973e16341Kristen Accardi				if (ACPI_FAILURE(status))
54620416ea54087c25502d6fb973b8e119973e16341Kristen Accardi					err("failed to remove notify handler\n");
54720416ea54087c25502d6fb973b8e119973e16341Kristen Accardi			}
54842f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah			list_del(list);
54942f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah			kfree(func);
55042f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		}
551e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro		acpiphp_unregister_hotplug_slot(slot);
552e27da3814170385a4d2797397d706e554635812dMUNEDA Takahiro		list_del(&slot->funcs);
55342f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		kfree(slot);
55442f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		slot = next;
55542f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	}
55642f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah
5575d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang	/*
5585d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang	 * Only P2P bridges have a pci_dev
5595d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang	 */
5605d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang	if (bridge->pci_dev)
5615d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang		put_device(&bridge->pci_bus->dev);
5625d4a4b25ddc3e864d3a562c024bebdc922118854Alex Chiang
56342f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	pci_dev_put(bridge->pci_dev);
56442f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	list_del(&bridge->list);
56542f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	kfree(bridge);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
568364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shahstatic acpi_status
569364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shahcleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
570364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah{
571364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah	struct acpiphp_bridge *bridge;
572364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah
573551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	/* cleanup p2p bridges under this P2P bridge
574551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	   in a depth-first manner */
575551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
576551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro				cleanup_p2p_bridge, NULL, NULL);
577551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
578a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang	bridge = acpiphp_handle_to_bridge(handle);
579a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang	if (bridge)
580a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang		cleanup_bridge(bridge);
581a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang
582364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah	return AE_OK;
583364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah}
584364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah
585364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shahstatic void remove_bridge(acpi_handle handle)
586364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah{
587364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah	struct acpiphp_bridge *bridge;
588364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah
589551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	/* cleanup p2p bridges under this host bridge
590551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	   in a depth-first manner */
591551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
592551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro				(u32)1, cleanup_p2p_bridge, NULL, NULL);
593551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
594a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang	/*
595a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang	 * On root bridges with hotplug slots directly underneath (ie,
596a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang	 * no p2p bridge inbetween), we call cleanup_bridge().
597a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang	 *
598a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang	 * The else clause cleans up root bridges that either had no
599a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang	 * hotplug slots at all, or had a p2p bridge underneath.
600a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang	 */
601364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah	bridge = acpiphp_handle_to_bridge(handle);
602551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	if (bridge)
603364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah		cleanup_bridge(bridge);
604a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang	else
605a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang		acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
606a13307cef8bf51990ef1d525b1cbdcc2cfe07e2aAlex Chiang					   handle_hotplug_event_bridge);
607364d5094a43ff2ceff3d19e40c4199771cb6cb8fRajesh Shah}
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
609a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshigestatic struct pci_dev * get_apic_pci_info(acpi_handle handle)
610a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige{
611a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	struct pci_dev *dev;
612a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
613d6aa484c1c0cd39ff3a42f4050b55d2a5b285ef5Alexander Chiang	dev = acpi_get_pci_dev(handle);
614a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	if (!dev)
615a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		return NULL;
616a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
617a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) &&
618a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	    (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC))
619a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	{
620a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		pci_dev_put(dev);
621a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		return NULL;
622a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	}
623a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
624a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	return dev;
625a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige}
626a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
627a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshigestatic int get_gsi_base(acpi_handle handle, u32 *gsi_base)
628a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige{
629a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	acpi_status status;
630a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	int result = -1;
63127663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox	unsigned long long gsb;
632a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
633a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	union acpi_object *obj;
634a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	void *table;
635a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
636a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
637a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	if (ACPI_SUCCESS(status)) {
638a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		*gsi_base = (u32)gsb;
639a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		return 0;
640a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	}
641a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
642a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer);
643a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer)
644a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		return -1;
645a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
646a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	obj = buffer.pointer;
647a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	if (obj->type != ACPI_TYPE_BUFFER)
648a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		goto out;
649a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
650a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	table = obj->buffer.pointer;
65115a58ed12142939d51076380e6e58af477ad96ecAlexey Starikovskiy	switch (((struct acpi_subtable_header *)table)->type) {
65215a58ed12142939d51076380e6e58af477ad96ecAlexey Starikovskiy	case ACPI_MADT_TYPE_IO_SAPIC:
65315a58ed12142939d51076380e6e58af477ad96ecAlexey Starikovskiy		*gsi_base = ((struct acpi_madt_io_sapic *)table)->global_irq_base;
654a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		result = 0;
655a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		break;
65615a58ed12142939d51076380e6e58af477ad96ecAlexey Starikovskiy	case ACPI_MADT_TYPE_IO_APIC:
65715a58ed12142939d51076380e6e58af477ad96ecAlexey Starikovskiy		*gsi_base = ((struct acpi_madt_io_apic *)table)->global_irq_base;
658a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		result = 0;
659a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		break;
660a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	default:
661a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		break;
662a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	}
663a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige out:
66481b26bcacd5df0f65344fb430b1bf7fe9cfbfe2aKristen Accardi	kfree(buffer.pointer);
665a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	return result;
666a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige}
667a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
668a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshigestatic acpi_status
669a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshigeioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
670a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige{
671a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	acpi_status status;
67227663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox	unsigned long long sta;
673a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	acpi_handle tmp;
674a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	struct pci_dev *pdev;
675a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	u32 gsi_base;
676a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	u64 phys_addr;
677600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	struct acpiphp_ioapic *ioapic;
678a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
679a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	/* Evaluate _STA if present */
680a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
681a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
682a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		return AE_CTRL_DEPTH;
683a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
684a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	/* Scan only PCI bus scope */
685a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	status = acpi_get_handle(handle, "_HID", &tmp);
686a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	if (ACPI_SUCCESS(status))
687a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		return AE_CTRL_DEPTH;
688a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
689a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	if (get_gsi_base(handle, &gsi_base))
690a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		return AE_OK;
691a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
692600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL);
693600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	if (!ioapic)
694600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		return AE_NO_MEMORY;
695600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
696a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	pdev = get_apic_pci_info(handle);
697a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	if (!pdev)
698600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		goto exit_kfree;
699a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
700600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	if (pci_enable_device(pdev))
701600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		goto exit_pci_dev_put;
702a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
703a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	pci_set_master(pdev);
704a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
705600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)"))
706600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		goto exit_pci_disable_device;
707a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
708a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	phys_addr = pci_resource_start(pdev, 0);
709600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	if (acpi_register_ioapic(handle, phys_addr, gsi_base))
710600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		goto exit_pci_release_region;
711600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
712600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	ioapic->gsi_base = gsi_base;
713600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	ioapic->dev = pdev;
714600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	spin_lock(&ioapic_list_lock);
715600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	list_add_tail(&ioapic->list, &ioapic_list);
716600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	spin_unlock(&ioapic_list_lock);
717600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
718600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	return AE_OK;
719600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
720600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi exit_pci_release_region:
721600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	pci_release_region(pdev, 0);
722600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi exit_pci_disable_device:
723600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	pci_disable_device(pdev);
724600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi exit_pci_dev_put:
725600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	pci_dev_put(pdev);
726600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi exit_kfree:
727600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	kfree(ioapic);
728600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
729600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	return AE_OK;
730600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi}
731600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
732600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchistatic acpi_status
733600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchiioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv)
734600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi{
735600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	acpi_status status;
73627663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox	unsigned long long sta;
737600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	acpi_handle tmp;
738600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	u32 gsi_base;
739600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	struct acpiphp_ioapic *pos, *n, *ioapic = NULL;
740600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
741600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	/* Evaluate _STA if present */
742600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
743600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
744600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		return AE_CTRL_DEPTH;
745600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
746600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	/* Scan only PCI bus scope */
747600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	status = acpi_get_handle(handle, "_HID", &tmp);
748600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	if (ACPI_SUCCESS(status))
749600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		return AE_CTRL_DEPTH;
750600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
751600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	if (get_gsi_base(handle, &gsi_base))
752a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige		return AE_OK;
753600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
754600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	acpi_unregister_ioapic(handle, gsi_base);
755600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
756600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	spin_lock(&ioapic_list_lock);
757600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	list_for_each_entry_safe(pos, n, &ioapic_list, list) {
758600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		if (pos->gsi_base != gsi_base)
759600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi			continue;
760600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		ioapic = pos;
761600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		list_del(&ioapic->list);
762600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		break;
763a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	}
764600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	spin_unlock(&ioapic_list_lock);
765600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
766600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	if (!ioapic)
767600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		return AE_OK;
768600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
769600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	pci_release_region(ioapic->dev, 0);
770600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	pci_disable_device(ioapic->dev);
771600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	pci_dev_put(ioapic->dev);
772600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	kfree(ioapic);
773a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
774a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	return AE_OK;
775a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige}
776a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
777a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshigestatic int acpiphp_configure_ioapics(acpi_handle handle)
778a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige{
7799b1d19ee86746618a8b43d2aaef8319c01af1514Satoru Takeuchi	ioapic_add(handle, 0, NULL, NULL);
780a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
781a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige			    ACPI_UINT32_MAX, ioapic_add, NULL, NULL);
782a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	return 0;
783a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige}
784a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige
785600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchistatic int acpiphp_unconfigure_ioapics(acpi_handle handle)
786600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi{
787600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	ioapic_remove(handle, 0, NULL, NULL);
788600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
789600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi			    ACPI_UINT32_MAX, ioapic_remove, NULL, NULL);
790600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	return 0;
791600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi}
792600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int power_on_slot(struct acpiphp_slot *slot)
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_status status;
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_func *func;
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head *l;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval = 0;
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if already enabled, just skip */
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (slot->flags & SLOT_POWEREDON)
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_exit;
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each (l, &slot->funcs) {
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		func = list_entry(l, struct acpiphp_func, sibling);
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (func->flags & FUNC_HAS_PS0) {
80866bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison			dbg("%s: executing _PS0\n", __func__);
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ACPI_FAILURE(status)) {
81166bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison				warn("%s: _PS0 failed\n", __func__);
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				retval = -1;
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto err_exit;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* TBD: evaluate _STA to check if the slot is enabled */
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	slot->flags |= SLOT_POWEREDON;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err_exit:
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int power_off_slot(struct acpiphp_slot *slot)
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_status status;
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_func *func;
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head *l;
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval = 0;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if already disabled, just skip */
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((slot->flags & SLOT_POWEREDON) == 0)
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_exit;
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each (l, &slot->funcs) {
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		func = list_entry(l, struct acpiphp_func, sibling);
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8432f523b15901f654a9448bbd47ebe1e783ec3195bRajesh Shah		if (func->flags & FUNC_HAS_PS3) {
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ACPI_FAILURE(status)) {
84666bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison				warn("%s: _PS3 failed\n", __func__);
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				retval = -1;
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto err_exit;
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* TBD: evaluate _STA to check if the slot is disabled */
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	slot->flags &= (~SLOT_POWEREDON);
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err_exit:
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
86315a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi
86415a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi/**
86526e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * acpiphp_max_busnr - return the highest reserved bus number under the given bus.
86615a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi * @bus: bus to start search with
86715a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi */
86815a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardistatic unsigned char acpiphp_max_busnr(struct pci_bus *bus)
86915a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi{
87015a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	struct list_head *tmp;
87115a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	unsigned char max, n;
87215a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi
87315a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	/*
87415a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 * pci_bus_max_busnr will return the highest
87515a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 * reserved busnr for all these children.
87615a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 * that is equivalent to the bus->subordinate
87715a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 * value.  We don't want to use the parent's
87815a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 * bus->subordinate value because it could have
87915a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 * padding in it.
88015a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 */
88115a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	max = bus->secondary;
88215a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi
88315a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	list_for_each(tmp, &bus->children) {
88415a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi		n = pci_bus_max_busnr(pci_bus_b(tmp));
88515a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi		if (n > max)
88615a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi			max = n;
88715a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	}
88815a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	return max;
88915a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi}
89015a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi
89115a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi
89215a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi/**
89315a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi * acpiphp_bus_add - add a new bus to acpi subsystem
89415a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi * @func: acpiphp_func of the bridge
89515a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi */
89615a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardistatic int acpiphp_bus_add(struct acpiphp_func *func)
89715a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi{
89815a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	acpi_handle phandle;
89915a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	struct acpi_device *device, *pdevice;
90015a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	int ret_val;
90115a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi
90215a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	acpi_get_parent(func->handle, &phandle);
90315a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	if (acpi_bus_get_device(phandle, &pdevice)) {
90415a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi		dbg("no parent device, assuming NULL\n");
90515a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi		pdevice = NULL;
90615a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	}
90720416ea54087c25502d6fb973b8e119973e16341Kristen Accardi	if (!acpi_bus_get_device(func->handle, &device)) {
90820416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		dbg("bus exists... trim\n");
90920416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		/* this shouldn't be in here, so remove
91020416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		 * the bus then re-add it...
91120416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		 */
91220416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		ret_val = acpi_bus_trim(device, 1);
91320416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		dbg("acpi_bus_trim return %x\n", ret_val);
91420416ea54087c25502d6fb973b8e119973e16341Kristen Accardi	}
91520416ea54087c25502d6fb973b8e119973e16341Kristen Accardi
91620416ea54087c25502d6fb973b8e119973e16341Kristen Accardi	ret_val = acpi_bus_add(&device, pdevice, func->handle,
91720416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		ACPI_BUS_TYPE_DEVICE);
91820416ea54087c25502d6fb973b8e119973e16341Kristen Accardi	if (ret_val) {
91920416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		dbg("error adding bus, %x\n",
92020416ea54087c25502d6fb973b8e119973e16341Kristen Accardi			-ret_val);
92120416ea54087c25502d6fb973b8e119973e16341Kristen Accardi		goto acpiphp_bus_add_out;
92215a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	}
92315a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	/*
92415a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 * try to start anyway.  We could have failed to add
92515a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 * simply because this bus had previously been added
92615a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 * on another add.  Don't bother with the return value
92715a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 * we just keep going.
92815a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	 */
92915a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	ret_val = acpi_bus_start(device);
93015a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi
93115a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardiacpiphp_bus_add_out:
93215a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	return ret_val;
93315a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi}
93415a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi
93515a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi
93692c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro/**
93792c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro * acpiphp_bus_trim - trim a bus from acpi subsystem
93892c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro * @handle: handle to acpi namespace
93992c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro */
9406d47a5e4c3f8b6458002065d98a9cc6ff90fb597Adrian Bunkstatic int acpiphp_bus_trim(acpi_handle handle)
94192c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro{
94292c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro	struct acpi_device *device;
94392c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro	int retval;
94492c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro
94592c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro	retval = acpi_bus_get_device(handle, &device);
94692c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro	if (retval) {
94792c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro		dbg("acpi_device not found\n");
94892c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro		return retval;
94992c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro	}
95092c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro
95192c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro	retval = acpi_bus_trim(device, 1);
95292c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro	if (retval)
95392c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro		err("cannot remove from acpi list\n");
95492c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro
95592c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro	return retval;
95692c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro}
95715a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * enable_device - enable, configure a slot
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @slot: slot to be enabled
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function should be called per *physical slot*,
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not per each slot object in ACPI namespace.
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9650ab2b57f8db8a1bcdf24089074f5d2856a3ffb42Sam Ravnborgstatic int __ref enable_device(struct acpiphp_slot *slot)
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
96842f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	struct pci_bus *bus = slot->bridge->pci_bus;
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head *l;
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_func *func;
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval = 0;
97242f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	int num, max, pass;
973551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro	acpi_status status;
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (slot->flags & SLOT_ENABLED)
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_exit;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* sanity check: dev should be NULL when hot-plugged in */
97942f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev) {
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* This case shouldn't happen */
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("pci_dev structure already exists.\n");
98342f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		pci_dev_put(dev);
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = -1;
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_exit;
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
98842f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
98942f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	if (num == 0) {
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("No new device found\n");
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = -1;
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_exit;
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
99515a1ae74879925d0d3f71ebc3f56d0a2c5db393aKristen Accardi	max = acpiphp_max_busnr(bus);
99642f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	for (pass = 0; pass < 2; pass++) {
99742f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		list_for_each_entry(dev, &bus->devices, bus_list) {
99842f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah			if (PCI_SLOT(dev->devfn) != slot->device)
99942f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah				continue;
100042f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
1001c64b5eead93f9d3a8ca0e9ca0ffba0b99dc565b9Kristen Accardi			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
100242f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah				max = pci_scan_bridge(bus, dev, max, pass);
100392c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro				if (pass && dev->subordinate)
1004c64b5eead93f9d3a8ca0e9ca0ffba0b99dc565b9Kristen Accardi					pci_bus_size_bridges(dev->subordinate);
1005c64b5eead93f9d3a8ca0e9ca0ffba0b99dc565b9Kristen Accardi			}
100642f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		}
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
100992c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro	list_for_each (l, &slot->funcs) {
101092c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro		func = list_entry(l, struct acpiphp_func, sibling);
101192c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro		acpiphp_bus_add(func);
101292c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro	}
101392c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro
101442f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	pci_bus_assign_resources(bus);
10158e5dce35221850759671b2847a2e51030f7626bdKristen Accardi	acpiphp_sanitize_bus(bus);
1016fca6825ad7382ae9df8ecda9068ac13ee9e343f4Bjorn Helgaas	acpiphp_set_hpp_values(bus);
10179b1d19ee86746618a8b43d2aaef8319c01af1514Satoru Takeuchi	list_for_each_entry(func, &slot->funcs, sibling)
10189b1d19ee86746618a8b43d2aaef8319c01af1514Satoru Takeuchi		acpiphp_configure_ioapics(func->handle);
10198e5dce35221850759671b2847a2e51030f7626bdKristen Accardi	pci_enable_bridges(bus);
102042f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	pci_bus_add_devices(bus);
102142f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each (l, &slot->funcs) {
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		func = list_entry(l, struct acpiphp_func, sibling);
10249d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang		dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
10259d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang						  func->function));
10269d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang		if (!dev)
1027551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			continue;
1028551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
10299d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang		if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
10309d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang		    dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) {
10319d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang			pci_dev_put(dev);
1032551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			continue;
10339d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang		}
1034551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
1035551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		status = find_p2p_bridge(func->handle, (u32)1, bus, NULL);
1036551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		if (ACPI_FAILURE(status))
1037551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			warn("find_p2p_bridge failed (error code = 0x%x)\n",
1038551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro				status);
10399d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang		pci_dev_put(dev);
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	slot->flags |= SLOT_ENABLED;
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err_exit:
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1048d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchistatic void disable_bridges(struct pci_bus *bus)
1049d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi{
1050d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi	struct pci_dev *dev;
1051d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi	list_for_each_entry(dev, &bus->devices, bus_list) {
1052d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi		if (dev->subordinate) {
1053d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi			disable_bridges(dev->subordinate);
1054d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi			pci_disable_device(dev);
1055d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi		}
1056d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi	}
1057d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi}
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * disable_device - disable a slot
106126e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @slot: ACPI PHP slot
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int disable_device(struct acpiphp_slot *slot)
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_func *func;
10669d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang	struct pci_dev *pdev;
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* is this slot already disabled? */
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(slot->flags & SLOT_ENABLED))
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_exit;
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10729d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang	list_for_each_entry(func, &slot->funcs, sibling) {
1073551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		if (func->bridge) {
1074551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			/* cleanup p2p bridges under this P2P bridge */
1075551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			cleanup_p2p_bridge(func->bridge->handle,
1076551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro						(u32)1, NULL, NULL);
1077551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			func->bridge = NULL;
1078551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		}
1079551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro
10809d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang		pdev = pci_get_slot(slot->bridge->pci_bus,
10819d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang				    PCI_DEVFN(slot->device, func->function));
10829d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang		if (pdev) {
10839d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang			pci_stop_bus_device(pdev);
10849d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang			if (pdev->subordinate) {
10859d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang				disable_bridges(pdev->subordinate);
10869d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang				pci_disable_device(pdev);
1087d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi			}
10889d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang			pci_remove_bus_device(pdev);
10899d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang			pci_dev_put(pdev);
1090d5cdb67236dba94496de052c9f9f431e1fc658f4Satoru Takeuchi		}
1091600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi	}
1092600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi
10939d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang	list_for_each_entry(func, &slot->funcs, sibling) {
1094600812ecead0da2e7b6f9e5f5aad68b1ad8ae581Satoru Takeuchi		acpiphp_unconfigure_ioapics(func->handle);
109592c9be95549632da09088320f202fa5c05b21ddfMUNEDA Takahiro		acpiphp_bus_trim(func->handle);
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	slot->flags &= (~SLOT_ENABLED);
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11009d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiangerr_exit:
11019d911d7903926a65ef49ec671bacd86bcee5eb51Alex Chiang	return 0;
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get_slot_status - get ACPI slot status
110726e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @slot: ACPI PHP slot
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
110926e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * If a slot has _STA for each function and if any one of them
111026e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * returned non-zero status, return it.
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111226e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * If a slot doesn't have _STA and if any one of its functions'
111326e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * configuration space is configured, return 0x0f as a _STA.
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111526e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Otherwise return 0.
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int get_slot_status(struct acpiphp_slot *slot)
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_status status;
112027663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox	unsigned long long sta = 0;
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 dvid;
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head *l;
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_func *func;
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each (l, &slot->funcs) {
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		func = list_entry(l, struct acpiphp_func, sibling);
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (func->flags & FUNC_HAS_STA) {
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta);
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ACPI_SUCCESS(status) && sta)
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_bus_read_config_dword(slot->bridge->pci_bus,
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  PCI_DEVFN(slot->device,
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							    func->function),
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  PCI_VENDOR_ID, &dvid);
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dvid != 0xffffffff) {
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sta = ACPI_STA_ALL;
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (unsigned int)sta;
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
11488d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah * acpiphp_eject_slot - physically eject the slot
114926e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @slot: ACPI PHP slot
11508d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah */
1151bfceafc5979d9055e04f03f970de6ff7a4bce1b6Gary Hadeint acpiphp_eject_slot(struct acpiphp_slot *slot)
11528d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah{
11538d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah	acpi_status status;
11548d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah	struct acpiphp_func *func;
11558d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah	struct list_head *l;
11568d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah	struct acpi_object_list arg_list;
11578d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah	union acpi_object arg;
11588d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah
11598d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah	list_for_each (l, &slot->funcs) {
11608d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah		func = list_entry(l, struct acpiphp_func, sibling);
11618d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah
11628d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah		/* We don't want to call _EJ0 on non-existing functions. */
11638d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah		if ((func->flags & FUNC_HAS_EJ0)) {
11648d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah			/* _EJ0 method take one argument */
11658d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah			arg_list.count = 1;
11668d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah			arg_list.pointer = &arg;
11678d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah			arg.type = ACPI_TYPE_INTEGER;
11688d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah			arg.integer.value = 1;
11698d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah
11708d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah			status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
11718d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah			if (ACPI_FAILURE(status)) {
117266bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison				warn("%s: _EJ0 failed\n", __func__);
11738d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah				return -1;
11748d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah			} else
11758d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah				break;
11768d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah		}
11778d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah	}
11788d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah	return 0;
11798d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah}
11808d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah
11818d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah/**
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * acpiphp_check_bridge - re-enumerate devices
118326e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @bridge: where to begin re-enumeration
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Iterate over all slots under this bridge and make sure that if a
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * card is present they are enabled, and if not they are disabled.
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_slot *slot;
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval = 0;
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int enabled, disabled;
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enabled = disabled = 0;
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (slot = bridge->slots; slot; slot = slot->next) {
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int status = get_slot_status(slot);
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (slot->flags & SLOT_ENABLED) {
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (status == ACPI_STA_ALL)
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			retval = acpiphp_disable_slot(slot);
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (retval) {
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err("Error occurred in disabling\n");
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto err_exit;
12058d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah			} else {
12068d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah				acpiphp_eject_slot(slot);
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			disabled++;
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (status != ACPI_STA_ALL)
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			retval = acpiphp_enable_slot(slot);
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (retval) {
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err("Error occurred in enabling\n");
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto err_exit;
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enabled++;
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
122166bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison	dbg("%s: %d enabled, %d disabled\n", __func__, enabled, disabled);
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err_exit:
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1227fca6825ad7382ae9df8ecda9068ac13ee9e343f4Bjorn Helgaasstatic void acpiphp_set_hpp_values(struct pci_bus *bus)
12288e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah{
12298e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	struct pci_dev *dev;
12308e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
1231e81995bb1c0077a312cb621abc406a36f65a986aBjorn Helgaas	list_for_each_entry(dev, &bus->devices, bus_list)
1232e81995bb1c0077a312cb621abc406a36f65a986aBjorn Helgaas		pci_configure_slot(dev);
12338e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah}
12348e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
12358e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah/*
12368e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah * Remove devices for which we could not assign resources, call
12378e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah * arch specific code to fix-up the bus
12388e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah */
12398e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shahstatic void acpiphp_sanitize_bus(struct pci_bus *bus)
12408e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah{
12418e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	struct pci_dev *dev;
12428e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	int i;
12438e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
12448e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
12458e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	list_for_each_entry(dev, &bus->devices, bus_list) {
12468e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
12478e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah			struct resource *res = &dev->resource[i];
12488e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah			if ((res->flags & type_mask) && !res->start &&
12498e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah					res->end) {
12508e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah				/* Could not assign a required resources
12518e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah				 * for this device, remove it */
12528e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah				pci_remove_bus_device(dev);
12538e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah				break;
12548e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah			}
12558e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		}
12568e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	}
12578e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah}
12588e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
12598e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah/* Program resources in newly inserted bridge */
12608e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shahstatic int acpiphp_configure_bridge (acpi_handle handle)
12618e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah{
12627f53866932fd08add06ee2f93ead129949158490Alex Chiang	struct pci_bus *bus;
12637f53866932fd08add06ee2f93ead129949158490Alex Chiang
12647f53866932fd08add06ee2f93ead129949158490Alex Chiang	if (acpi_is_root_bridge(handle)) {
12657f53866932fd08add06ee2f93ead129949158490Alex Chiang		struct acpi_pci_root *root = acpi_pci_find_root(handle);
12667f53866932fd08add06ee2f93ead129949158490Alex Chiang		bus = root->bus;
12677f53866932fd08add06ee2f93ead129949158490Alex Chiang	} else {
12687f53866932fd08add06ee2f93ead129949158490Alex Chiang		struct pci_dev *pdev = acpi_get_pci_dev(handle);
12697f53866932fd08add06ee2f93ead129949158490Alex Chiang		bus = pdev->subordinate;
12707f53866932fd08add06ee2f93ead129949158490Alex Chiang		pci_dev_put(pdev);
12717f53866932fd08add06ee2f93ead129949158490Alex Chiang	}
12728e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
12738e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	pci_bus_size_bridges(bus);
12748e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	pci_bus_assign_resources(bus);
12758e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	acpiphp_sanitize_bus(bus);
1276fca6825ad7382ae9df8ecda9068ac13ee9e343f4Bjorn Helgaas	acpiphp_set_hpp_values(bus);
12778e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	pci_enable_bridges(bus);
1278a0d399a808916d22c1c222c6b5ca4e8edd6d91a9Kenji Kaneshige	acpiphp_configure_ioapics(handle);
12798e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	return 0;
12808e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah}
12818e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
12828e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shahstatic void handle_bridge_insertion(acpi_handle handle, u32 type)
12838e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah{
12848e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	struct acpi_device *device, *pdevice;
12858e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	acpi_handle phandle;
12868e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
12878e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	if ((type != ACPI_NOTIFY_BUS_CHECK) &&
12888e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah			(type != ACPI_NOTIFY_DEVICE_CHECK)) {
12898e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		err("unexpected notification type %d\n", type);
12908e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		return;
12918e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	}
12928e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
12938e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	acpi_get_parent(handle, &phandle);
12948e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	if (acpi_bus_get_device(phandle, &pdevice)) {
12958e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		dbg("no parent device, assuming NULL\n");
12968e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		pdevice = NULL;
12978e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	}
12988e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) {
12998e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		err("cannot add bridge to acpi list\n");
13008e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		return;
13018e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	}
13028e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	if (!acpiphp_configure_bridge(handle) &&
13038e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		!acpi_bus_start(device))
13048e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		add_bridge(handle);
13058e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	else
13068e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		err("cannot configure and start bridge\n");
13078e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
13088e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah}
13098e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ACPI event handlers
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13140bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hadestatic acpi_status
13150bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hadecount_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
13160bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade{
13170bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	int *count = (int *)context;
13180bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	struct acpiphp_bridge *bridge;
13190bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade
13200bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	bridge = acpiphp_handle_to_bridge(handle);
13210bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	if (bridge)
13220bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade		(*count)++;
13230bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	return AE_OK ;
13240bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade}
13250bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade
13260bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hadestatic acpi_status
13270bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hadecheck_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
13280bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade{
13290bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	struct acpiphp_bridge *bridge;
13300bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	char objname[64];
13310bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	struct acpi_buffer buffer = { .length = sizeof(objname),
13320bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade				      .pointer = objname };
13330bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade
13340bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	bridge = acpiphp_handle_to_bridge(handle);
13350bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	if (bridge) {
13360bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
13370bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade		dbg("%s: re-enumerating slots under %s\n",
133866bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison			__func__, objname);
13390bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade		acpiphp_check_bridge(bridge);
13400bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	}
13410bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	return AE_OK ;
13420bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade}
13430bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * handle_hotplug_event_bridge - handle ACPI event on bridges
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @handle: Notify()'ed acpi_handle
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @type: Notify code
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @context: pointer to acpiphp_bridge structure
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
135026e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Handles ACPI event notification on {host,p2p} bridges.
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context)
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_bridge *bridge;
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char objname[64];
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpi_buffer buffer = { .length = sizeof(objname),
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      .pointer = objname };
13588e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	struct acpi_device *device;
13590bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	int num_sub_bridges = 0;
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13618e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	if (acpi_bus_get_device(handle, &device)) {
13628e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		/* This bridge must have just been physically inserted */
13638e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		handle_bridge_insertion(handle, type);
13648e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		return;
13658e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	}
13668e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
13678e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	bridge = acpiphp_handle_to_bridge(handle);
13680bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	if (type == ACPI_NOTIFY_BUS_CHECK) {
13690bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
13700bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade			count_sub_bridges, &num_sub_bridges, NULL);
13710bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	}
13720bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade
13730bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade	if (!bridge && !num_sub_bridges) {
13748e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		err("cannot get bridge info\n");
13758e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		return;
13768e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	}
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (type) {
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_BUS_CHECK:
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* bus re-enumerate */
138366bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison		dbg("%s: Bus check notify on %s\n", __func__, objname);
13840bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade		if (bridge) {
13850bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade			dbg("%s: re-enumerating slots under %s\n",
138666bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison				__func__, objname);
13870bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade			acpiphp_check_bridge(bridge);
13880bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade		}
13890bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade		if (num_sub_bridges)
13900bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade			acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
13910bbd6424c55f0ab9e7fcd6a851bc49e265259ff5Gary Hade				ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL);
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_DEVICE_CHECK:
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* device check */
139666bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison		dbg("%s: Device check notify on %s\n", __func__, objname);
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		acpiphp_check_bridge(bridge);
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_DEVICE_WAKE:
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* wake event */
140266bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison		dbg("%s: Device wake notify on %s\n", __func__, objname);
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_EJECT_REQUEST:
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* request device eject */
140766bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison		dbg("%s: Device eject notify on %s\n", __func__, objname);
1408551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		if ((bridge->type != BRIDGE_TYPE_HOST) &&
1409551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		    (bridge->flags & BRIDGE_HAS_EJ0)) {
1410551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			struct acpiphp_slot *slot;
1411551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			slot = bridge->func->slot;
1412551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro			if (!acpiphp_disable_slot(slot))
1413551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro				acpiphp_eject_slot(slot);
1414551bcb75b3d9f23348a524210ccfff26d865e425MUNEDA Takahiro		}
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "Device %s cannot be configured due"
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				" to a frequency mismatch\n", objname);
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "Device %s cannot be configured due"
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				" to a bus mode mismatch\n", objname);
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_POWER_FAULT:
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "Device %s has suffered a power fault\n",
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				objname);
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @handle: Notify()'ed acpi_handle
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @type: Notify code
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @context: pointer to acpiphp_func structure
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
144426e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Handles ACPI event notification on slots.
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14462b85e1307fe3a84eca2e1a21c6c857359908dab4Len Brownstatic void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_func *func;
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char objname[64];
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpi_buffer buffer = { .length = sizeof(objname),
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      .pointer = objname };
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	func = (struct acpiphp_func *)context;
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (type) {
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_BUS_CHECK:
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* bus re-enumerate */
146066bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison		dbg("%s: Bus check notify on %s\n", __func__, objname);
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		acpiphp_enable_slot(func->slot);
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_DEVICE_CHECK:
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* device check : re-enumerate from parent bus */
146666bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison		dbg("%s: Device check notify on %s\n", __func__, objname);
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		acpiphp_check_bridge(func->slot->bridge);
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_DEVICE_WAKE:
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* wake event */
147266bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison		dbg("%s: Device wake notify on %s\n", __func__, objname);
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_NOTIFY_EJECT_REQUEST:
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* request device eject */
147766bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison		dbg("%s: Device eject notify on %s\n", __func__, objname);
14788d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah		if (!(acpiphp_disable_slot(func->slot)))
14798d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah			acpiphp_eject_slot(func->slot);
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14888e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
14898e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shahstatic acpi_status
14908e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shahfind_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
14918e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah{
14928e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	int *count = (int *)context;
14938e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah
1494275582031f9b3597a1b973f3ff617adfe639faa2Alexander Chiang	if (acpi_is_root_bridge(handle)) {
14958e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
14968e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah				handle_hotplug_event_bridge, NULL);
14978e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah			(*count)++;
14988e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	}
14998e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	return AE_OK ;
15008e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah}
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct acpi_pci_driver acpi_pci_hp_driver = {
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.add =		add_bridge,
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove =	remove_bridge,
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init acpiphp_glue_init(void)
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15128e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	int num = 0;
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15148e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
15158e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah			ACPI_UINT32_MAX, find_root_bridges, &num, NULL);
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (num <= 0)
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
15198e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah	else
15208e7561cfbdf00fb1cee694cef0e825d0548aedbcRajesh Shah		acpi_pci_register_driver(&acpi_pci_hp_driver);
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
152926e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * This function frees all data allocated in acpiphp_glue_init().
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1531031f30d2bc69f78cf542c0e5874a9d67c03d0ffeKristen Carlson Accardivoid  acpiphp_glue_exit(void)
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_pci_unregister_driver(&acpi_pci_hp_driver);
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * acpiphp_get_num_slots - count number of slots in a system
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init acpiphp_get_num_slots(void)
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_bridge *bridge;
1543467c442f092e22acf86a3b4ad4863d097d7257daAkinobu Mita	int num_slots = 0;
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1545467c442f092e22acf86a3b4ad4863d097d7257daAkinobu Mita	list_for_each_entry (bridge, &bridge_list, list) {
154642f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah		dbg("Bus %04x:%02x has %d slot%s\n",
154742f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah				pci_domain_nr(bridge->pci_bus),
154842f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah				bridge->pci_bus->number, bridge->nr_slots,
154942f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah				bridge->nr_slots == 1 ? "" : "s");
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		num_slots += bridge->nr_slots;
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
155342f49a6ae5dca90cd0594475502bf1c43ff1dc07Rajesh Shah	dbg("Total %d slots\n", num_slots);
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return num_slots;
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * acpiphp_for_each_slot - call function for each slot
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fn: callback function
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @data: context to be passed to callback function
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head *node;
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_bridge *bridge;
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpiphp_slot *slot;
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval = 0;
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each (node, &bridge_list) {
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bridge = (struct acpiphp_bridge *)node;
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (slot = bridge->slots; slot; slot = slot->next) {
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			retval = fn(slot, data);
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!retval)
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto err_exit;
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err_exit:
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * acpiphp_enable_slot - power on slot
158826e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @slot: ACPI PHP slot
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint acpiphp_enable_slot(struct acpiphp_slot *slot)
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval;
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15946aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar	mutex_lock(&slot->crit_sect);
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* wake up all functions */
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = power_on_slot(slot);
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval)
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_exit;
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1601cde0e5d722c77d1194f40de54a99c90afe365480MUNEDA Takahiro	if (get_slot_status(slot) == ACPI_STA_ALL) {
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* configure all functions */
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = enable_device(slot);
1604cde0e5d722c77d1194f40de54a99c90afe365480MUNEDA Takahiro		if (retval)
1605cde0e5d722c77d1194f40de54a99c90afe365480MUNEDA Takahiro			power_off_slot(slot);
1606cde0e5d722c77d1194f40de54a99c90afe365480MUNEDA Takahiro	} else {
160766bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison		dbg("%s: Slot status is not ACPI_STA_ALL\n", __func__);
1608cde0e5d722c77d1194f40de54a99c90afe365480MUNEDA Takahiro		power_off_slot(slot);
1609cde0e5d722c77d1194f40de54a99c90afe365480MUNEDA Takahiro	}
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err_exit:
16126aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar	mutex_unlock(&slot->crit_sect);
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * acpiphp_disable_slot - power off slot
161826e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @slot: ACPI PHP slot
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint acpiphp_disable_slot(struct acpiphp_slot *slot)
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval = 0;
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16246aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar	mutex_lock(&slot->crit_sect);
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* unconfigure all functions */
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = disable_device(slot);
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval)
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_exit;
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* power off all functions */
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = power_off_slot(slot);
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval)
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_exit;
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err_exit:
16376aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar	mutex_unlock(&slot->crit_sect);
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * slot enabled:  1
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * slot disabled: 0
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu8 acpiphp_get_power_status(struct acpiphp_slot *slot)
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16488d50e332c8bd4f4e8cc76e8ed7326aa6f18182aaRajesh Shah	return (slot->flags & SLOT_POWEREDON);
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
165335ae61a0f43ebbabc3cb4345136ca529fc4d6700MUNEDA Takahiro * latch   open:  1
165435ae61a0f43ebbabc3cb4345136ca529fc4d6700MUNEDA Takahiro * latch closed:  0
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu8 acpiphp_get_latch_status(struct acpiphp_slot *slot)
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int sta;
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sta = get_slot_status(slot);
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
166235ae61a0f43ebbabc3cb4345136ca529fc4d6700MUNEDA Takahiro	return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1;
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * adapter presence : 1
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *          absence : 0
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int sta;
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sta = get_slot_status(slot);
16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (sta == 0) ? 0 : 1;
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1678