diff options
Diffstat (limited to 'drivers/pci/hotplug')
| -rw-r--r-- | drivers/pci/hotplug/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 35 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_core.c | 30 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 415 | ||||
| -rw-r--r-- | drivers/pci/hotplug/cpci_hotplug.h | 44 | ||||
| -rw-r--r-- | drivers/pci/hotplug/cpqphp.h | 70 | ||||
| -rw-r--r-- | drivers/pci/hotplug/cpqphp_nvram.h | 12 | ||||
| -rw-r--r-- | drivers/pci/hotplug/ibmphp.h | 66 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pci_hotplug_core.c | 15 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp.h | 22 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_acpi.c | 2 | ||||
| -rw-r--r-- | drivers/pci/hotplug/rpadlpar.h | 8 | ||||
| -rw-r--r-- | drivers/pci/hotplug/rpaphp.h | 16 | ||||
| -rw-r--r-- | drivers/pci/hotplug/s390_pci_hpc.c | 12 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp.h | 26 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_sysfs.c | 2 | 
16 files changed, 313 insertions, 469 deletions
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index 13e9e63a726..9fcb87f353d 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -52,15 +52,12 @@ config HOTPLUG_PCI_IBM  	  When in doubt, say N.  config HOTPLUG_PCI_ACPI -	tristate "ACPI PCI Hotplug driver" -	depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK) +	bool "ACPI PCI Hotplug driver" +	depends on HOTPLUG_PCI=y && ((!ACPI_DOCK && ACPI) || (ACPI_DOCK))  	help  	  Say Y here if you have a system that supports PCI Hotplug using  	  ACPI. -	  To compile this driver as a module, choose M here: the -	  module will be called acpiphp. -  	  When in doubt, say N.  config HOTPLUG_PCI_ACPI_IBM diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index b70ac00a117..6fdd49c6f0b 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -73,8 +73,9 @@ static inline const char *slot_name(struct slot *slot)   */  struct acpiphp_bridge {  	struct list_head list; +	struct list_head slots; +	struct kref ref;  	acpi_handle handle; -	struct acpiphp_slot *slots;  	/* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */  	struct acpiphp_func *func; @@ -97,7 +98,7 @@ struct acpiphp_bridge {   * PCI slot information for each *physical* PCI slot   */  struct acpiphp_slot { -	struct acpiphp_slot *next; +	struct list_head node;  	struct acpiphp_bridge *bridge;	/* parent */  	struct list_head funcs;		/* one slot may have different  					   objects (i.e. for each function) */ @@ -119,7 +120,6 @@ struct acpiphp_slot {   */  struct acpiphp_func {  	struct acpiphp_slot *slot;	/* parent */ -	struct acpiphp_bridge *bridge;	/* Ejectable PCI-to-PCI bridge */  	struct list_head sibling;  	struct notifier_block nb; @@ -146,10 +146,6 @@ struct acpiphp_attention_info  #define ACPI_PCI_HOST_HID		"PNP0A03"  /* ACPI _STA method value (ignore bit 4; battery present) */ -#define ACPI_STA_PRESENT		(0x00000001) -#define ACPI_STA_ENABLED		(0x00000002) -#define ACPI_STA_SHOW_IN_UI		(0x00000004) -#define ACPI_STA_FUNCTIONING		(0x00000008)  #define ACPI_STA_ALL			(0x0000000f)  /* bridge flags */ @@ -174,25 +170,24 @@ struct acpiphp_attention_info  /* function prototypes */  /* acpiphp_core.c */ -extern int acpiphp_register_attention(struct acpiphp_attention_info*info); -extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info); -extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); -extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); +int acpiphp_register_attention(struct acpiphp_attention_info*info); +int acpiphp_unregister_attention(struct acpiphp_attention_info *info); +int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); +void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);  /* acpiphp_glue.c */ -extern int acpiphp_glue_init (void); -extern void acpiphp_glue_exit (void);  typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); -extern int acpiphp_enable_slot (struct acpiphp_slot *slot); -extern int acpiphp_disable_slot (struct acpiphp_slot *slot); -extern int acpiphp_eject_slot (struct acpiphp_slot *slot); -extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot); -extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot); -extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); -extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); +int acpiphp_enable_slot(struct acpiphp_slot *slot); +int acpiphp_disable_slot(struct acpiphp_slot *slot); +int acpiphp_eject_slot(struct acpiphp_slot *slot); +u8 acpiphp_get_power_status(struct acpiphp_slot *slot); +u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); +u8 acpiphp_get_latch_status(struct acpiphp_slot *slot); +u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot);  /* variables */  extern bool acpiphp_debug; +extern bool acpiphp_disabled;  #endif /* _ACPIPHP_H */ diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index c2fd3095701..ca8127950fc 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -37,6 +37,7 @@  #include <linux/kernel.h>  #include <linux/pci.h> +#include <linux/pci-acpi.h>  #include <linux/pci_hotplug.h>  #include <linux/slab.h>  #include <linux/smp.h> @@ -48,6 +49,7 @@  #define SLOT_NAME_SIZE  21              /* {_SUN} */  bool acpiphp_debug; +bool acpiphp_disabled;  /* local variables */  static struct acpiphp_attention_info *attention_info; @@ -60,7 +62,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_LICENSE("GPL");  MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); +MODULE_PARM_DESC(disable, "disable acpiphp driver");  module_param_named(debug, acpiphp_debug, bool, 0644); +module_param_named(disable, acpiphp_disabled, bool, 0444);  /* export the attention callback registration methods */  EXPORT_SYMBOL_GPL(acpiphp_register_attention); @@ -351,27 +355,9 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)  } -static int __init acpiphp_init(void) +void __init acpiphp_init(void)  { -	info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - -	if (acpi_pci_disabled) -		return 0; - -	/* read all the ACPI info from the system */ -	/* initialize internal data structure etc. */ -	return acpiphp_glue_init(); -} - - -static void __exit acpiphp_exit(void) -{ -	if (acpi_pci_disabled) -		return; - -	/* deallocate internal data structures etc. */ -	acpiphp_glue_exit(); +	info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n", +		acpiphp_disabled ? ", disabled by user; please report a bug" +				 : "");  } - -module_init(acpiphp_init); -module_exit(acpiphp_exit); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 270fdbadc19..96fed19c6d9 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -54,6 +54,7 @@  #include "acpiphp.h"  static LIST_HEAD(bridge_list); +static DEFINE_MUTEX(bridge_mutex);  #define MY_NAME "acpiphp_glue" @@ -61,6 +62,7 @@ static void handle_hotplug_event_bridge (acpi_handle, u32, void *);  static void acpiphp_sanitize_bus(struct pci_bus *bus);  static void acpiphp_set_hpp_values(struct pci_bus *bus);  static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); +static void free_bridge(struct kref *kref);  /* callback routine to check for the existence of a pci dock device */  static acpi_status @@ -76,6 +78,39 @@ is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)  	}  } +static inline void get_bridge(struct acpiphp_bridge *bridge) +{ +	kref_get(&bridge->ref); +} + +static inline void put_bridge(struct acpiphp_bridge *bridge) +{ +	kref_put(&bridge->ref, free_bridge); +} + +static void free_bridge(struct kref *kref) +{ +	struct acpiphp_bridge *bridge; +	struct acpiphp_slot *slot, *next; +	struct acpiphp_func *func, *tmp; + +	bridge = container_of(kref, struct acpiphp_bridge, ref); + +	list_for_each_entry_safe(slot, next, &bridge->slots, node) { +		list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { +			kfree(func); +		} +		kfree(slot); +	} + +	/* Release reference acquired by acpiphp_bridge_handle_to_function() */ +	if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) +		put_bridge(bridge->func->slot->bridge); +	put_device(&bridge->pci_bus->dev); +	pci_dev_put(bridge->pci_dev); +	kfree(bridge); +} +  /*   * the _DCK method can do funny things... and sometimes not   * hah-hah funny. @@ -154,9 +189,10 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)  	acpi_handle tmp;  	acpi_status status = AE_OK;  	unsigned long long adr, sun; -	int device, function, retval; +	int device, function, retval, found = 0;  	struct pci_bus *pbus = bridge->pci_bus;  	struct pci_dev *pdev; +	u32 val;  	if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))  		return AE_OK; @@ -170,7 +206,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)  	device = (adr >> 16) & 0xffff;  	function = adr & 0xffff; -	pdev = pbus->self; +	pdev = bridge->pci_dev;  	if (pdev && device_is_managed_by_native_pciehp(pdev))  		return AE_OK; @@ -178,7 +214,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)  	if (!newfunc)  		return AE_NO_MEMORY; -	INIT_LIST_HEAD(&newfunc->sibling);  	newfunc->handle = handle;  	newfunc->function = function; @@ -207,14 +242,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)  	}  	/* search for objects that share the same slot */ -	for (slot = bridge->slots; slot; slot = slot->next) +	list_for_each_entry(slot, &bridge->slots, node)  		if (slot->device == device) {  			if (slot->sun != sun)  				warn("sibling found, but _SUN doesn't match!\n"); +			found = 1;  			break;  		} -	if (!slot) { +	if (!found) {  		slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);  		if (!slot) {  			kfree(newfunc); @@ -227,9 +263,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)  		INIT_LIST_HEAD(&slot->funcs);  		mutex_init(&slot->crit_sect); -		slot->next = bridge->slots; -		bridge->slots = slot; - +		mutex_lock(&bridge_mutex); +		list_add_tail(&slot->node, &bridge->slots); +		mutex_unlock(&bridge_mutex);  		bridge->nr_slots++;  		dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", @@ -247,13 +283,13 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)  	}  	newfunc->slot = slot; +	mutex_lock(&bridge_mutex);  	list_add_tail(&newfunc->sibling, &slot->funcs); +	mutex_unlock(&bridge_mutex); -	pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); -	if (pdev) { +	if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function), +				       &val, 60*1000))  		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); -		pci_dev_put(pdev); -	}  	if (is_dock_device(handle)) {  		/* we don't want to call this device's _EJ0 @@ -290,7 +326,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)   err_exit:  	bridge->nr_slots--; -	bridge->slots = slot->next; +	mutex_lock(&bridge_mutex); +	list_del(&slot->node); +	mutex_unlock(&bridge_mutex);  	kfree(slot);  	kfree(newfunc); @@ -315,13 +353,17 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)  	acpi_status status;  	/* must be added to the list prior to calling register_slot */ +	mutex_lock(&bridge_mutex);  	list_add(&bridge->list, &bridge_list); +	mutex_unlock(&bridge_mutex);  	/* register all slot objects under this bridge */  	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,  				     register_slot, NULL, bridge, NULL);  	if (ACPI_FAILURE(status)) { +		mutex_lock(&bridge_mutex);  		list_del(&bridge->list); +		mutex_unlock(&bridge_mutex);  		return;  	} @@ -351,178 +393,46 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle  {  	struct acpiphp_bridge *bridge;  	struct acpiphp_slot *slot; -	struct acpiphp_func *func; +	struct acpiphp_func *func = NULL; +	mutex_lock(&bridge_mutex);  	list_for_each_entry(bridge, &bridge_list, list) { -		for (slot = bridge->slots; slot; slot = slot->next) { +		list_for_each_entry(slot, &bridge->slots, node) {  			list_for_each_entry(func, &slot->funcs, sibling) { -				if (func->handle == handle) +				if (func->handle == handle) { +					get_bridge(func->slot->bridge); +					mutex_unlock(&bridge_mutex);  					return func; +				}  			}  		}  	} +	mutex_unlock(&bridge_mutex);  	return NULL;  } -static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) -{ -	acpi_handle dummy_handle; -	struct acpiphp_func *func; - -	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, -					"_EJ0", &dummy_handle))) { -		bridge->flags |= BRIDGE_HAS_EJ0; - -		dbg("found ejectable p2p bridge\n"); - -		/* make link between PCI bridge and PCI function */ -		func = acpiphp_bridge_handle_to_function(bridge->handle); -		if (!func) -			return; -		bridge->func = func; -		func->bridge = bridge; -	} -} - - -/* allocate and initialize host bridge data structure */ -static void add_host_bridge(struct acpi_pci_root *root) -{ -	struct acpiphp_bridge *bridge; -	acpi_handle handle = root->device->handle; - -	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); -	if (bridge == NULL) -		return; - -	bridge->handle = handle; - -	bridge->pci_bus = root->bus; - -	init_bridge_misc(bridge); -} - - -/* allocate and initialize PCI-to-PCI bridge data structure */ -static void add_p2p_bridge(acpi_handle *handle) -{ -	struct acpiphp_bridge *bridge; - -	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); -	if (bridge == NULL) { -		err("out of memory\n"); -		return; -	} - -	bridge->handle = handle; -	config_p2p_bridge_flags(bridge); - -	bridge->pci_dev = acpi_get_pci_dev(handle); -	bridge->pci_bus = bridge->pci_dev->subordinate; -	if (!bridge->pci_bus) { -		err("This is not a PCI-to-PCI bridge!\n"); -		goto err; -	} - -	/* -	 * Grab a ref to the subordinate PCI bus in case the bus is -	 * removed via PCI core logical hotplug. The ref pins the bus -	 * (which we access during module unload). -	 */ -	get_device(&bridge->pci_bus->dev); - -	init_bridge_misc(bridge); -	return; - err: -	pci_dev_put(bridge->pci_dev); -	kfree(bridge); -	return; -} - - -/* callback routine to find P2P bridges */ -static acpi_status -find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) -{ -	acpi_status status; -	struct pci_dev *dev; - -	dev = acpi_get_pci_dev(handle); -	if (!dev || !dev->subordinate) -		goto out; - -	/* check if this bridge has ejectable slots */ -	if ((detect_ejectable_slots(handle) > 0)) { -		dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); -		add_p2p_bridge(handle); -	} - -	/* search P2P bridges under this p2p bridge */ -	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, -				     find_p2p_bridge, NULL, NULL, NULL); -	if (ACPI_FAILURE(status)) -		warn("find_p2p_bridge failed (error code = 0x%x)\n", status); - - out: -	pci_dev_put(dev); -	return AE_OK; -} - - -/* find hot-pluggable slots, and then find P2P bridge */ -static int add_bridge(struct acpi_pci_root *root) -{ -	acpi_status status; -	unsigned long long tmp; -	acpi_handle dummy_handle; -	acpi_handle handle = root->device->handle; - -	/* if the bridge doesn't have _STA, we assume it is always there */ -	status = acpi_get_handle(handle, "_STA", &dummy_handle); -	if (ACPI_SUCCESS(status)) { -		status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); -		if (ACPI_FAILURE(status)) { -			dbg("%s: _STA evaluation failure\n", __func__); -			return 0; -		} -		if ((tmp & ACPI_STA_FUNCTIONING) == 0) -			/* don't register this object */ -			return 0; -	} - -	/* check if this bridge has ejectable slots */ -	if (detect_ejectable_slots(handle) > 0) { -		dbg("found PCI host-bus bridge with hot-pluggable slots\n"); -		add_host_bridge(root); -	} - -	/* search P2P bridges under this host bridge */ -	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, -				     find_p2p_bridge, NULL, NULL, NULL); - -	if (ACPI_FAILURE(status)) -		warn("find_p2p_bridge failed (error code = 0x%x)\n", status); - -	return 0; -} -  static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)  {  	struct acpiphp_bridge *bridge; +	mutex_lock(&bridge_mutex);  	list_for_each_entry(bridge, &bridge_list, list) -		if (bridge->handle == handle) +		if (bridge->handle == handle) { +			get_bridge(bridge); +			mutex_unlock(&bridge_mutex);  			return bridge; +		} +	mutex_unlock(&bridge_mutex);  	return NULL;  }  static void cleanup_bridge(struct acpiphp_bridge *bridge)  { -	struct acpiphp_slot *slot, *next; -	struct acpiphp_func *func, *tmp; +	struct acpiphp_slot *slot; +	struct acpiphp_func *func;  	acpi_status status;  	acpi_handle handle = bridge->handle; @@ -543,10 +453,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)  			err("failed to install interrupt notify handler\n");  	} -	slot = bridge->slots; -	while (slot) { -		next = slot->next; -		list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { +	list_for_each_entry(slot, &bridge->slots, node) { +		list_for_each_entry(func, &slot->funcs, sibling) {  			if (is_dock_device(func->handle)) {  				unregister_hotplug_dock_device(func->handle);  				unregister_dock_notifier(&func->nb); @@ -558,63 +466,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)  				if (ACPI_FAILURE(status))  					err("failed to remove notify handler\n");  			} -			list_del(&func->sibling); -			kfree(func);  		}  		acpiphp_unregister_hotplug_slot(slot); -		list_del(&slot->funcs); -		kfree(slot); -		slot = next;  	} -	/* -	 * Only P2P bridges have a pci_dev -	 */ -	if (bridge->pci_dev) -		put_device(&bridge->pci_bus->dev); - -	pci_dev_put(bridge->pci_dev); +	mutex_lock(&bridge_mutex);  	list_del(&bridge->list); -	kfree(bridge); -} - -static acpi_status -cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) -{ -	struct acpiphp_bridge *bridge; - -	/* cleanup p2p bridges under this P2P bridge -	   in a depth-first manner */ -	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, -				cleanup_p2p_bridge, NULL, NULL, NULL); - -	bridge = acpiphp_handle_to_bridge(handle); -	if (bridge) -		cleanup_bridge(bridge); - -	return AE_OK; -} - -static void remove_bridge(struct acpi_pci_root *root) -{ -	struct acpiphp_bridge *bridge; -	acpi_handle handle = root->device->handle; - -	/* cleanup p2p bridges under this host bridge -	   in a depth-first manner */ -	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, -				(u32)1, cleanup_p2p_bridge, NULL, NULL, NULL); - -	/* -	 * On root bridges with hotplug slots directly underneath (ie, -	 * no p2p bridge between), we call cleanup_bridge().  -	 * -	 * The else clause cleans up root bridges that either had no -	 * hotplug slots at all, or had a p2p bridge underneath. -	 */ -	bridge = acpiphp_handle_to_bridge(handle); -	if (bridge) -		cleanup_bridge(bridge); +	mutex_unlock(&bridge_mutex);  }  static int power_on_slot(struct acpiphp_slot *slot) @@ -798,6 +656,7 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev)  		}  	}  } +  /**   * enable_device - enable, configure a slot   * @slot: slot to be enabled @@ -810,9 +669,7 @@ static int __ref enable_device(struct acpiphp_slot *slot)  	struct pci_dev *dev;  	struct pci_bus *bus = slot->bridge->pci_bus;  	struct acpiphp_func *func; -	int retval = 0;  	int num, max, pass; -	acpi_status status;  	if (slot->flags & SLOT_ENABLED)  		goto err_exit; @@ -867,23 +724,11 @@ static int __ref enable_device(struct acpiphp_slot *slot)  			slot->flags &= (~SLOT_ENABLED);  			continue;  		} - -		if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && -		    dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) { -			pci_dev_put(dev); -			continue; -		} - -		status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); -		if (ACPI_FAILURE(status)) -			warn("find_p2p_bridge failed (error code = 0x%x)\n", -				status); -		pci_dev_put(dev);  	}   err_exit: -	return retval; +	return 0;  }  /* return first device in slot, acquiring a reference on it */ @@ -912,23 +757,6 @@ static int disable_device(struct acpiphp_slot *slot)  {  	struct acpiphp_func *func;  	struct pci_dev *pdev; -	struct pci_bus *bus = slot->bridge->pci_bus; - -	/* The slot will be enabled when func 0 is added, so check -	   func 0 before disable the slot. */ -	pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0)); -	if (!pdev) -		goto err_exit; -	pci_dev_put(pdev); - -	list_for_each_entry(func, &slot->funcs, sibling) { -		if (func->bridge) { -			/* cleanup p2p bridges under this P2P bridge */ -			cleanup_p2p_bridge(func->bridge->handle, -						(u32)1, NULL, NULL); -			func->bridge = NULL; -		} -	}  	/*  	 * enable_device() enumerates all functions in this device via @@ -947,7 +775,6 @@ static int disable_device(struct acpiphp_slot *slot)  	slot->flags &= (~SLOT_ENABLED); -err_exit:  	return 0;  } @@ -1037,7 +864,7 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)  	enabled = disabled = 0; -	for (slot = bridge->slots; slot; slot = slot->next) { +	list_for_each_entry(slot, &bridge->slots, node) {  		unsigned int status = get_slot_status(slot);  		if (slot->flags & SLOT_ENABLED) {  			if (status == ACPI_STA_ALL) @@ -1082,11 +909,11 @@ static void acpiphp_set_hpp_values(struct pci_bus *bus)   */  static void acpiphp_sanitize_bus(struct pci_bus *bus)  { -	struct pci_dev *dev; +	struct pci_dev *dev, *tmp;  	int i;  	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; -	list_for_each_entry(dev, &bus->devices, bus_list) { +	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {  		for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {  			struct resource *res = &dev->resource[i];  			if ((res->flags & type_mask) && !res->start && @@ -1118,6 +945,7 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)  		dbg("%s: re-enumerating slots under %s\n",  			__func__, objname);  		acpiphp_check_bridge(bridge); +		put_bridge(bridge);  	}  	return AE_OK ;  } @@ -1195,6 +1023,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)  	acpi_scan_lock_release();  	kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ +	put_bridge(bridge);  }  /** @@ -1208,6 +1037,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)  static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,  					void *context)  { +	struct acpiphp_bridge *bridge = context; +  	/*  	 * Currently the code adds all hotplug events to the kacpid_wq  	 * queue when it should add hotplug events to the kacpi_hotplug_wq. @@ -1216,6 +1047,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,  	 * For now just re-add this work to the kacpi_hotplug_wq so we  	 * don't deadlock on hotplug actions.  	 */ +	get_bridge(bridge);  	alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);  } @@ -1270,6 +1102,7 @@ static void _handle_hotplug_event_func(struct work_struct *work)  	acpi_scan_lock_release();  	kfree(hp_work); /* allocated in handle_hotplug_event_func */ +	put_bridge(func->slot->bridge);  }  /** @@ -1283,6 +1116,8 @@ static void _handle_hotplug_event_func(struct work_struct *work)  static void handle_hotplug_event_func(acpi_handle handle, u32 type,  				      void *context)  { +	struct acpiphp_func *func = context; +  	/*  	 * Currently the code adds all hotplug events to the kacpid_wq  	 * queue when it should add hotplug events to the kacpi_hotplug_wq. @@ -1291,33 +1126,69 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,  	 * For now just re-add this work to the kacpi_hotplug_wq so we  	 * don't deadlock on hotplug actions.  	 */ +	get_bridge(func->slot->bridge);  	alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func);  } -static struct acpi_pci_driver acpi_pci_hp_driver = { -	.add =		add_bridge, -	.remove =	remove_bridge, -}; - -/** - * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures +/* + * Create hotplug slots for the PCI bus. + * It should always return 0 to avoid skipping following notifiers.   */ -int __init acpiphp_glue_init(void) +void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle)  { -	acpi_pci_register_driver(&acpi_pci_hp_driver); +	acpi_handle dummy_handle; +	struct acpiphp_bridge *bridge; -	return 0; -} +	if (acpiphp_disabled) +		return; +	if (detect_ejectable_slots(handle) <= 0) +		return; -/** - * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures - * - * This function frees all data allocated in acpiphp_glue_init(). - */ -void  acpiphp_glue_exit(void) +	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); +	if (bridge == NULL) { +		err("out of memory\n"); +		return; +	} + +	INIT_LIST_HEAD(&bridge->slots); +	kref_init(&bridge->ref); +	bridge->handle = handle; +	bridge->pci_dev = pci_dev_get(bus->self); +	bridge->pci_bus = bus; + +	/* +	 * Grab a ref to the subordinate PCI bus in case the bus is +	 * removed via PCI core logical hotplug. The ref pins the bus +	 * (which we access during module unload). +	 */ +	get_device(&bus->dev); + +	if (!pci_is_root_bus(bridge->pci_bus) && +	    ACPI_SUCCESS(acpi_get_handle(bridge->handle, +					"_EJ0", &dummy_handle))) { +		dbg("found ejectable p2p bridge\n"); +		bridge->flags |= BRIDGE_HAS_EJ0; +		bridge->func = acpiphp_bridge_handle_to_function(handle); +	} + +	init_bridge_misc(bridge); +} + +/* Destroy hotplug slots associated with the PCI bus */ +void acpiphp_remove_slots(struct pci_bus *bus)  { -	acpi_pci_unregister_driver(&acpi_pci_hp_driver); +	struct acpiphp_bridge *bridge, *tmp; + +	if (acpiphp_disabled) +		return; + +	list_for_each_entry_safe(bridge, tmp, &bridge_list, list) +		if (bridge->pci_bus == bus) { +			cleanup_bridge(bridge); +			put_bridge(bridge); +			break; +		}  }  /** @@ -1396,7 +1267,7 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot)  	sta = get_slot_status(slot); -	return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1; +	return (sta & ACPI_STA_DEVICE_UI) ? 0 : 1;  } diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h index 9fff878cf02..1356211431d 100644 --- a/drivers/pci/hotplug/cpci_hotplug.h +++ b/drivers/pci/hotplug/cpci_hotplug.h @@ -75,28 +75,36 @@ static inline const char *slot_name(struct slot *slot)  	return hotplug_slot_name(slot->hotplug_slot);  } -extern int cpci_hp_register_controller(struct cpci_hp_controller *controller); -extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller); -extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last); -extern int cpci_hp_unregister_bus(struct pci_bus *bus); -extern int cpci_hp_start(void); -extern int cpci_hp_stop(void); +int cpci_hp_register_controller(struct cpci_hp_controller *controller); +int cpci_hp_unregister_controller(struct cpci_hp_controller *controller); +int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last); +int cpci_hp_unregister_bus(struct pci_bus *bus); +int cpci_hp_start(void); +int cpci_hp_stop(void);  /*   * Internal function prototypes, these functions should not be used by   * board/chassis drivers.   */ -extern u8 cpci_get_attention_status(struct slot *slot); -extern u8 cpci_get_latch_status(struct slot *slot); -extern u8 cpci_get_adapter_status(struct slot *slot); -extern u16 cpci_get_hs_csr(struct slot * slot); -extern int cpci_set_attention_status(struct slot *slot, int status); -extern int cpci_check_and_clear_ins(struct slot * slot); -extern int cpci_check_ext(struct slot * slot); -extern int cpci_clear_ext(struct slot * slot); -extern int cpci_led_on(struct slot * slot); -extern int cpci_led_off(struct slot * slot); -extern int cpci_configure_slot(struct slot *slot); -extern int cpci_unconfigure_slot(struct slot *slot); +u8 cpci_get_attention_status(struct slot *slot); +u8 cpci_get_latch_status(struct slot *slot); +u8 cpci_get_adapter_status(struct slot *slot); +u16 cpci_get_hs_csr(struct slot * slot); +int cpci_set_attention_status(struct slot *slot, int status); +int cpci_check_and_clear_ins(struct slot * slot); +int cpci_check_ext(struct slot * slot); +int cpci_clear_ext(struct slot * slot); +int cpci_led_on(struct slot * slot); +int cpci_led_off(struct slot * slot); +int cpci_configure_slot(struct slot *slot); +int cpci_unconfigure_slot(struct slot *slot); + +#ifdef CONFIG_HOTPLUG_PCI_CPCI +int cpci_hotplug_init(int debug); +void cpci_hotplug_exit(void); +#else +static inline int cpci_hotplug_init(int debug) { return 0; } +static inline void cpci_hotplug_exit(void) { } +#endif  #endif	/* _CPCI_HOTPLUG_H */ diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index d8ffc736680..516b87738b6 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h @@ -404,50 +404,44 @@ struct resource_lists {  /* debugfs functions for the hotplug controller info */ -extern void cpqhp_initialize_debugfs(void); -extern void cpqhp_shutdown_debugfs(void); -extern void cpqhp_create_debugfs_files(struct controller *ctrl); -extern void cpqhp_remove_debugfs_files(struct controller *ctrl); +void cpqhp_initialize_debugfs(void); +void cpqhp_shutdown_debugfs(void); +void cpqhp_create_debugfs_files(struct controller *ctrl); +void cpqhp_remove_debugfs_files(struct controller *ctrl);  /* controller functions */ -extern void cpqhp_pushbutton_thread(unsigned long event_pointer); -extern irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data); -extern int cpqhp_find_available_resources(struct controller *ctrl, -					  void __iomem *rom_start); -extern int cpqhp_event_start_thread(void); -extern void cpqhp_event_stop_thread(void); -extern struct pci_func *cpqhp_slot_create(unsigned char busnumber); -extern struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device, -					unsigned char index); -extern int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func); -extern int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func); -extern int cpqhp_hardware_test(struct controller *ctrl, int test_num); +void cpqhp_pushbutton_thread(unsigned long event_pointer); +irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data); +int cpqhp_find_available_resources(struct controller *ctrl, +				   void __iomem *rom_start); +int cpqhp_event_start_thread(void); +void cpqhp_event_stop_thread(void); +struct pci_func *cpqhp_slot_create(unsigned char busnumber); +struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device, +				 unsigned char index); +int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func); +int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func); +int cpqhp_hardware_test(struct controller *ctrl, int test_num);  /* resource functions */ -extern int	cpqhp_resource_sort_and_combine	(struct pci_resource **head); +int	cpqhp_resource_sort_and_combine	(struct pci_resource **head);  /* pci functions */ -extern int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); -extern int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, -			     u8 slot); -extern int cpqhp_save_config(struct controller *ctrl, int busnumber, -			     int is_hot_plug); -extern int cpqhp_save_base_addr_length(struct controller *ctrl, -				       struct pci_func *func); -extern int cpqhp_save_used_resources(struct controller *ctrl, -				     struct pci_func *func); -extern int cpqhp_configure_board(struct controller *ctrl, -				 struct pci_func *func); -extern int cpqhp_save_slot_config(struct controller *ctrl, -				  struct pci_func *new_slot); -extern int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func); -extern void cpqhp_destroy_board_resources(struct pci_func *func); -extern int cpqhp_return_board_resources	(struct pci_func *func, -					 struct resource_lists *resources); -extern void cpqhp_destroy_resource_list(struct resource_lists *resources); -extern int cpqhp_configure_device(struct controller *ctrl, -				  struct pci_func *func); -extern int cpqhp_unconfigure_device(struct pci_func *func); +int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); +int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, +		      u8 slot); +int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug); +int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func); +int cpqhp_save_used_resources(struct controller *ctrl, struct pci_func *func); +int cpqhp_configure_board(struct controller *ctrl, struct pci_func *func); +int cpqhp_save_slot_config(struct controller *ctrl, struct pci_func *new_slot); +int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func); +void cpqhp_destroy_board_resources(struct pci_func *func); +int cpqhp_return_board_resources(struct pci_func *func, +				 struct resource_lists *resources); +void cpqhp_destroy_resource_list(struct resource_lists *resources); +int cpqhp_configure_device(struct controller *ctrl, struct pci_func *func); +int cpqhp_unconfigure_device(struct pci_func *func);  /* Global variables */  extern int cpqhp_debug; diff --git a/drivers/pci/hotplug/cpqphp_nvram.h b/drivers/pci/hotplug/cpqphp_nvram.h index e89c0702119..34e4e54fcf1 100644 --- a/drivers/pci/hotplug/cpqphp_nvram.h +++ b/drivers/pci/hotplug/cpqphp_nvram.h @@ -30,26 +30,26 @@  #ifndef CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM -static inline void compaq_nvram_init (void __iomem *rom_start) +static inline void compaq_nvram_init(void __iomem *rom_start)  {  	return;  } -static inline int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) +static inline int compaq_nvram_load(void __iomem *rom_start, struct controller *ctrl)  {  	return 0;  } -static inline int compaq_nvram_store (void __iomem *rom_start) +static inline int compaq_nvram_store(void __iomem *rom_start)  {  	return 0;  }  #else -extern void compaq_nvram_init	(void __iomem *rom_start); -extern int compaq_nvram_load	(void __iomem *rom_start, struct controller *ctrl); -extern int compaq_nvram_store	(void __iomem *rom_start); +void compaq_nvram_init(void __iomem *rom_start); +int compaq_nvram_load(void __iomem *rom_start, struct controller *ctrl); +int compaq_nvram_store(void __iomem *rom_start);  #endif diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index a8d391a4957..8c5b25871d0 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h @@ -275,17 +275,17 @@ extern struct list_head ibmphp_slot_head;  * FUNCTION PROTOTYPES                                      *  ***********************************************************/ -extern void ibmphp_free_ebda_hpc_queue (void); -extern int ibmphp_access_ebda (void); -extern struct slot *ibmphp_get_slot_from_physical_num (u8); -extern int ibmphp_get_total_hp_slots (void); -extern void ibmphp_free_ibm_slot (struct slot *); -extern void ibmphp_free_bus_info_queue (void); -extern void ibmphp_free_ebda_pci_rsrc_queue (void); -extern struct bus_info *ibmphp_find_same_bus_num (u32); -extern int ibmphp_get_bus_index (u8); -extern u16 ibmphp_get_total_controllers (void); -extern int ibmphp_register_pci (void); +void ibmphp_free_ebda_hpc_queue(void); +int ibmphp_access_ebda(void); +struct slot *ibmphp_get_slot_from_physical_num(u8); +int ibmphp_get_total_hp_slots(void); +void ibmphp_free_ibm_slot(struct slot *); +void ibmphp_free_bus_info_queue(void); +void ibmphp_free_ebda_pci_rsrc_queue(void); +struct bus_info *ibmphp_find_same_bus_num(u32); +int ibmphp_get_bus_index(u8); +u16 ibmphp_get_total_controllers(void); +int ibmphp_register_pci(void);  /* passed parameters */  #define MEM		0 @@ -381,24 +381,24 @@ struct res_needed {  /* functions */ -extern int ibmphp_rsrc_init (void); -extern int ibmphp_add_resource (struct resource_node *); -extern int ibmphp_remove_resource (struct resource_node *); -extern int ibmphp_find_resource (struct bus_node *, u32, struct resource_node **, int); -extern int ibmphp_check_resource (struct resource_node *, u8); -extern int ibmphp_remove_bus (struct bus_node *, u8); -extern void ibmphp_free_resources (void); -extern int ibmphp_add_pfmem_from_mem (struct resource_node *); -extern struct bus_node *ibmphp_find_res_bus (u8); -extern void ibmphp_print_test (void);	/* for debugging purposes */ +int ibmphp_rsrc_init(void); +int ibmphp_add_resource(struct resource_node *); +int ibmphp_remove_resource(struct resource_node *); +int ibmphp_find_resource(struct bus_node *, u32, struct resource_node **, int); +int ibmphp_check_resource(struct resource_node *, u8); +int ibmphp_remove_bus(struct bus_node *, u8); +void ibmphp_free_resources(void); +int ibmphp_add_pfmem_from_mem(struct resource_node *); +struct bus_node *ibmphp_find_res_bus(u8); +void ibmphp_print_test(void);	/* for debugging purposes */ -extern void ibmphp_hpc_initvars (void); -extern int ibmphp_hpc_readslot (struct slot *, u8, u8 *); -extern int ibmphp_hpc_writeslot (struct slot *, u8); -extern void ibmphp_lock_operations (void); -extern void ibmphp_unlock_operations (void); -extern int ibmphp_hpc_start_poll_thread (void); -extern void ibmphp_hpc_stop_poll_thread (void); +void ibmphp_hpc_initvars(void); +int ibmphp_hpc_readslot(struct slot *, u8, u8 *); +int ibmphp_hpc_writeslot(struct slot *, u8); +void ibmphp_lock_operations(void); +void ibmphp_unlock_operations(void); +int ibmphp_hpc_start_poll_thread(void); +void ibmphp_hpc_stop_poll_thread(void);  //---------------------------------------------------------------------------- @@ -749,11 +749,11 @@ struct controller {  /* Functions */ -extern int ibmphp_init_devno (struct slot **);	/* This function is called from EBDA, so we need it not be static */ -extern int ibmphp_do_disable_slot (struct slot *slot_cur); -extern int ibmphp_update_slot_info (struct slot *);	/* This function is called from HPC, so we need it to not be be static */ -extern int ibmphp_configure_card (struct pci_func *, u8); -extern int ibmphp_unconfigure_card (struct slot **, int); +int ibmphp_init_devno(struct slot **);	/* This function is called from EBDA, so we need it not be static */ +int ibmphp_do_disable_slot(struct slot *slot_cur); +int ibmphp_update_slot_info(struct slot *);	/* This function is called from HPC, so we need it to not be be static */ +int ibmphp_configure_card(struct pci_func *, u8); +int ibmphp_unconfigure_card(struct slot **, int);  extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops;  #endif				//__IBMPHP_H diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 202f4a969eb..ec20f74c898 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -41,6 +41,7 @@  #include <linux/pci_hotplug.h>  #include <asm/uaccess.h>  #include "../pci.h" +#include "cpci_hotplug.h"  #define MY_NAME	"pci_hotplug" @@ -63,14 +64,6 @@ static bool debug;  static LIST_HEAD(pci_hotplug_slot_list);  static DEFINE_MUTEX(pci_hp_mutex); -#ifdef CONFIG_HOTPLUG_PCI_CPCI -extern int cpci_hotplug_init(int debug); -extern void cpci_hotplug_exit(void); -#else -static inline int cpci_hotplug_init(int debug) { return 0; } -static inline void cpci_hotplug_exit(void) { } -#endif -  /* Weee, fun with macros... */  #define GET_STATUS(name,type)	\  static int get_##name (struct hotplug_slot *slot, type *value)		\ @@ -524,13 +517,11 @@ int pci_hp_deregister(struct hotplug_slot *hotplug)   *   * Returns 0 if successful, anything else for an error.   */ -int __must_check pci_hp_change_slot_info(struct hotplug_slot *hotplug, -					 struct hotplug_slot_info *info) +int pci_hp_change_slot_info(struct hotplug_slot *hotplug, +			    struct hotplug_slot_info *info)  { -	struct pci_slot *slot;  	if (!hotplug || !info)  		return -ENODEV; -	slot = hotplug->pci_slot;  	memcpy(hotplug->info, info, sizeof(struct hotplug_slot_info)); diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 2c113de9432..7fb326983ed 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -127,15 +127,15 @@ struct controller {  #define NO_CMD_CMPL(ctrl)	((ctrl)->slot_cap & PCI_EXP_SLTCAP_NCCS)  #define PSN(ctrl)		((ctrl)->slot_cap >> 19) -extern int pciehp_sysfs_enable_slot(struct slot *slot); -extern int pciehp_sysfs_disable_slot(struct slot *slot); -extern u8 pciehp_handle_attention_button(struct slot *p_slot); -extern u8 pciehp_handle_switch_change(struct slot *p_slot); -extern u8 pciehp_handle_presence_change(struct slot *p_slot); -extern u8 pciehp_handle_power_fault(struct slot *p_slot); -extern int pciehp_configure_device(struct slot *p_slot); -extern int pciehp_unconfigure_device(struct slot *p_slot); -extern void pciehp_queue_pushbutton_work(struct work_struct *work); +int pciehp_sysfs_enable_slot(struct slot *slot); +int pciehp_sysfs_disable_slot(struct slot *slot); +u8 pciehp_handle_attention_button(struct slot *p_slot); +u8 pciehp_handle_switch_change(struct slot *p_slot); +u8 pciehp_handle_presence_change(struct slot *p_slot); +u8 pciehp_handle_power_fault(struct slot *p_slot); +int pciehp_configure_device(struct slot *p_slot); +int pciehp_unconfigure_device(struct slot *p_slot); +void pciehp_queue_pushbutton_work(struct work_struct *work);  struct controller *pcie_init(struct pcie_device *dev);  int pcie_init_notification(struct controller *ctrl);  int pciehp_enable_slot(struct slot *p_slot); @@ -166,8 +166,8 @@ static inline const char *slot_name(struct slot *slot)  #include <acpi/acpi_bus.h>  #include <linux/pci-acpi.h> -extern void __init pciehp_acpi_slot_detection_init(void); -extern int pciehp_acpi_slot_detection_check(struct pci_dev *dev); +void __init pciehp_acpi_slot_detection_init(void); +int pciehp_acpi_slot_detection_check(struct pci_dev *dev);  static inline void pciehp_firmware_init(void)  { diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 24d709b7388..ead7c534095 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c @@ -90,7 +90,7 @@ static int __init dummy_probe(struct pcie_device *dev)  	slot = kzalloc(sizeof(*slot), GFP_KERNEL);  	if (!slot)  		return -ENOMEM; -	slot->number = slot_cap >> 19; +	slot->number = (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19;  	list_for_each_entry(tmp, &dummy_slots, list) {  		if (tmp->number == slot->number)  			dup_slot_id++; diff --git a/drivers/pci/hotplug/rpadlpar.h b/drivers/pci/hotplug/rpadlpar.h index 4a0a59b82ea..81df93931ad 100644 --- a/drivers/pci/hotplug/rpadlpar.h +++ b/drivers/pci/hotplug/rpadlpar.h @@ -15,10 +15,10 @@  #ifndef _RPADLPAR_IO_H_  #define _RPADLPAR_IO_H_ -extern int dlpar_sysfs_init(void); -extern void dlpar_sysfs_exit(void); +int dlpar_sysfs_init(void); +void dlpar_sysfs_exit(void); -extern int dlpar_add_slot(char *drc_name); -extern int dlpar_remove_slot(char *drc_name); +int dlpar_add_slot(char *drc_name); +int dlpar_remove_slot(char *drc_name);  #endif diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index df5677440a0..3135856e5e1 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -86,18 +86,18 @@ extern struct list_head rpaphp_slot_head;  /* function prototypes */  /* rpaphp_pci.c */ -extern int rpaphp_enable_slot(struct slot *slot); -extern int rpaphp_get_sensor_state(struct slot *slot, int *state); +int rpaphp_enable_slot(struct slot *slot); +int rpaphp_get_sensor_state(struct slot *slot, int *state);  /* rpaphp_core.c */ -extern int rpaphp_add_slot(struct device_node *dn); -extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, +int rpaphp_add_slot(struct device_node *dn); +int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,  		char **drc_name, char **drc_type, int *drc_power_domain);  /* rpaphp_slot.c */ -extern void dealloc_slot_struct(struct slot *slot); -extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); -extern int rpaphp_register_slot(struct slot *slot); -extern int rpaphp_deregister_slot(struct slot *slot); +void dealloc_slot_struct(struct slot *slot); +struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); +int rpaphp_register_slot(struct slot *slot); +int rpaphp_deregister_slot(struct slot *slot);  #endif				/* _PPC64PHP_H */ diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c index 7db249a2501..46a7b738f61 100644 --- a/drivers/pci/hotplug/s390_pci_hpc.c +++ b/drivers/pci/hotplug/s390_pci_hpc.c @@ -16,6 +16,7 @@  #include <linux/pci.h>  #include <linux/pci_hotplug.h>  #include <linux/init.h> +#include <asm/pci_debug.h>  #include <asm/sclp.h>  #define SLOT_NAME_SIZE	10 @@ -49,6 +50,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)  		return -EIO;  	rc = sclp_pci_configure(slot->zdev->fid); +	zpci_dbg(3, "conf fid:%x, rc:%d\n", slot->zdev->fid, rc);  	if (!rc) {  		slot->zdev->state = ZPCI_FN_STATE_CONFIGURED;  		/* automatically scan the device after is was configured */ @@ -66,16 +68,16 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)  	if (!zpci_fn_configured(slot->zdev->state))  		return -EIO; +	rc = zpci_disable_device(slot->zdev); +	if (rc) +		return rc;  	/* TODO: we rely on the user to unbind/remove the device, is that plausible  	 *	 or do we need to trigger that here?  	 */  	rc = sclp_pci_deconfigure(slot->zdev->fid); -	if (!rc) { -		/* Fixme: better call List-PCI to find the disabled FH -		   for the FID since the FH should be opaque... */ -		slot->zdev->fh &= 0x7fffffff; +	zpci_dbg(3, "deconf fid:%x, rc:%d\n", slot->zdev->fid, rc); +	if (!rc)  		slot->zdev->state = ZPCI_FN_STATE_STANDBY; -	}  	return rc;  } diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index b849f995075..e260f207a90 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -168,19 +168,19 @@ struct controller {  #define WRONG_BUS_FREQUENCY		0x0000000D  #define POWER_FAILURE			0x0000000E -extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl); -extern void shpchp_remove_ctrl_files(struct controller *ctrl); -extern int shpchp_sysfs_enable_slot(struct slot *slot); -extern int shpchp_sysfs_disable_slot(struct slot *slot); -extern u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl); -extern u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl); -extern u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl); -extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl); -extern int shpchp_configure_device(struct slot *p_slot); -extern int shpchp_unconfigure_device(struct slot *p_slot); -extern void cleanup_slots(struct controller *ctrl); -extern void shpchp_queue_pushbutton_work(struct work_struct *work); -extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); +int __must_check shpchp_create_ctrl_files(struct controller *ctrl); +void shpchp_remove_ctrl_files(struct controller *ctrl); +int shpchp_sysfs_enable_slot(struct slot *slot); +int shpchp_sysfs_disable_slot(struct slot *slot); +u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl); +u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl); +u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl); +u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl); +int shpchp_configure_device(struct slot *p_slot); +int shpchp_unconfigure_device(struct slot *p_slot); +void cleanup_slots(struct controller *ctrl); +void shpchp_queue_pushbutton_work(struct work_struct *work); +int shpc_init( struct controller *ctrl, struct pci_dev *pdev);  static inline const char *slot_name(struct slot *slot)  { diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index eeb23ceae4a..e8c31fe2056 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c @@ -85,7 +85,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha  }  static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); -int __must_check shpchp_create_ctrl_files (struct controller *ctrl) +int shpchp_create_ctrl_files (struct controller *ctrl)  {  	return device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);  }  |