diff options
Diffstat (limited to 'drivers/pci')
37 files changed, 598 insertions, 796 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 8647dc6f52d..748f8f3e9ff 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -202,20 +202,16 @@ void pci_bus_add_devices(const struct pci_bus *bus)  		if (dev->is_added)  			continue;  		retval = pci_bus_add_device(dev); +		if (retval) +			dev_err(&dev->dev, "Error adding device (%d)\n", +				retval);  	}  	list_for_each_entry(dev, &bus->devices, bus_list) {  		BUG_ON(!dev->is_added); -  		child = dev->subordinate; - -		if (!child) -			continue; -		pci_bus_add_devices(child); - -		if (child->is_added) -			continue; -		child->is_added = 1; +		if (child) +			pci_bus_add_devices(child);  	}  } 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);  } diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 00cc78c7aa0..d40bed72676 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -22,10 +22,12 @@  #include <linux/slab.h>  #include "pci.h" -#include "msi.h"  static int pci_msi_enable = 1; +#define msix_table_size(flags)	((flags & PCI_MSIX_FLAGS_QSIZE) + 1) + +  /* Arch hooks */  #ifndef arch_msi_check_device @@ -111,32 +113,26 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)  }  #endif -static void msi_set_enable(struct pci_dev *dev, int pos, int enable) +static void msi_set_enable(struct pci_dev *dev, int enable)  {  	u16 control; -	BUG_ON(!pos); - -	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); +	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);  	control &= ~PCI_MSI_FLAGS_ENABLE;  	if (enable)  		control |= PCI_MSI_FLAGS_ENABLE; -	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); +	pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);  }  static void msix_set_enable(struct pci_dev *dev, int enable)  { -	int pos;  	u16 control; -	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); -	if (pos) { -		pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); -		control &= ~PCI_MSIX_FLAGS_ENABLE; -		if (enable) -			control |= PCI_MSIX_FLAGS_ENABLE; -		pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); -	} +	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); +	control &= ~PCI_MSIX_FLAGS_ENABLE; +	if (enable) +		control |= PCI_MSIX_FLAGS_ENABLE; +	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);  }  static inline __attribute_const__ u32 msi_mask(unsigned x) @@ -247,18 +243,18 @@ void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)  		msg->data = readl(base + PCI_MSIX_ENTRY_DATA);  	} else {  		struct pci_dev *dev = entry->dev; -		int pos = entry->msi_attrib.pos; +		int pos = dev->msi_cap;  		u16 data; -		pci_read_config_dword(dev, msi_lower_address_reg(pos), -					&msg->address_lo); +		pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, +				      &msg->address_lo);  		if (entry->msi_attrib.is_64) { -			pci_read_config_dword(dev, msi_upper_address_reg(pos), -						&msg->address_hi); -			pci_read_config_word(dev, msi_data_reg(pos, 1), &data); +			pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, +					      &msg->address_hi); +			pci_read_config_word(dev, pos + PCI_MSI_DATA_64, &data);  		} else {  			msg->address_hi = 0; -			pci_read_config_word(dev, msi_data_reg(pos, 0), &data); +			pci_read_config_word(dev, pos + PCI_MSI_DATA_32, &data);  		}  		msg->data = data;  	} @@ -302,24 +298,24 @@ void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)  		writel(msg->data, base + PCI_MSIX_ENTRY_DATA);  	} else {  		struct pci_dev *dev = entry->dev; -		int pos = entry->msi_attrib.pos; +		int pos = dev->msi_cap;  		u16 msgctl; -		pci_read_config_word(dev, msi_control_reg(pos), &msgctl); +		pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);  		msgctl &= ~PCI_MSI_FLAGS_QSIZE;  		msgctl |= entry->msi_attrib.multiple << 4; -		pci_write_config_word(dev, msi_control_reg(pos), msgctl); +		pci_write_config_word(dev, pos + PCI_MSI_FLAGS, msgctl); -		pci_write_config_dword(dev, msi_lower_address_reg(pos), -					msg->address_lo); +		pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, +				       msg->address_lo);  		if (entry->msi_attrib.is_64) { -			pci_write_config_dword(dev, msi_upper_address_reg(pos), -						msg->address_hi); -			pci_write_config_word(dev, msi_data_reg(pos, 1), -						msg->data); +			pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, +					       msg->address_hi); +			pci_write_config_word(dev, pos + PCI_MSI_DATA_64, +					      msg->data);  		} else { -			pci_write_config_word(dev, msi_data_reg(pos, 0), -						msg->data); +			pci_write_config_word(dev, pos + PCI_MSI_DATA_32, +					      msg->data);  		}  	}  	entry->msg = *msg; @@ -391,7 +387,6 @@ static void pci_intx_for_msi(struct pci_dev *dev, int enable)  static void __pci_restore_msi_state(struct pci_dev *dev)  { -	int pos;  	u16 control;  	struct msi_desc *entry; @@ -399,22 +394,20 @@ static void __pci_restore_msi_state(struct pci_dev *dev)  		return;  	entry = irq_get_msi_desc(dev->irq); -	pos = entry->msi_attrib.pos;  	pci_intx_for_msi(dev, 0); -	msi_set_enable(dev, pos, 0); +	msi_set_enable(dev, 0);  	arch_restore_msi_irqs(dev, dev->irq); -	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); +	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);  	msi_mask_irq(entry, msi_capable_mask(control), entry->masked);  	control &= ~PCI_MSI_FLAGS_QSIZE;  	control |= (entry->msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE; -	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); +	pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);  }  static void __pci_restore_msix_state(struct pci_dev *dev)  { -	int pos;  	struct msi_desc *entry;  	u16 control; @@ -422,13 +415,12 @@ static void __pci_restore_msix_state(struct pci_dev *dev)  		return;  	BUG_ON(list_empty(&dev->msi_list));  	entry = list_first_entry(&dev->msi_list, struct msi_desc, list); -	pos = entry->msi_attrib.pos; -	pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); +	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);  	/* route the table */  	pci_intx_for_msi(dev, 0);  	control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL; -	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); +	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);  	list_for_each_entry(entry, &dev->msi_list, list) {  		arch_restore_msi_irqs(dev, entry->irq); @@ -436,7 +428,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)  	}  	control &= ~PCI_MSIX_FLAGS_MASKALL; -	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); +	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);  }  void pci_restore_msi_state(struct pci_dev *dev) @@ -484,12 +476,12 @@ static struct msi_attribute mode_attribute =  	__ATTR(mode, S_IRUGO, show_msi_mode, NULL); -struct attribute *msi_irq_default_attrs[] = { +static struct attribute *msi_irq_default_attrs[] = {  	&mode_attribute.attr,  	NULL  }; -void msi_kobj_release(struct kobject *kobj) +static void msi_kobj_release(struct kobject *kobj)  {  	struct msi_desc *entry = to_msi_desc(kobj); @@ -552,27 +544,27 @@ out_unroll:  static int msi_capability_init(struct pci_dev *dev, int nvec)  {  	struct msi_desc *entry; -	int pos, ret; +	int ret;  	u16 control;  	unsigned mask; -	pos = pci_find_capability(dev, PCI_CAP_ID_MSI); -	msi_set_enable(dev, pos, 0);	/* Disable MSI during set up */ +	msi_set_enable(dev, 0);	/* Disable MSI during set up */ -	pci_read_config_word(dev, msi_control_reg(pos), &control); +	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);  	/* MSI Entry Initialization */  	entry = alloc_msi_entry(dev);  	if (!entry)  		return -ENOMEM;  	entry->msi_attrib.is_msix	= 0; -	entry->msi_attrib.is_64		= is_64bit_address(control); +	entry->msi_attrib.is_64		= !!(control & PCI_MSI_FLAGS_64BIT);  	entry->msi_attrib.entry_nr	= 0; -	entry->msi_attrib.maskbit	= is_mask_bit_support(control); +	entry->msi_attrib.maskbit	= !!(control & PCI_MSI_FLAGS_MASKBIT);  	entry->msi_attrib.default_irq	= dev->irq;	/* Save IOAPIC IRQ */ -	entry->msi_attrib.pos		= pos; +	entry->msi_attrib.pos		= dev->msi_cap; -	entry->mask_pos = msi_mask_reg(pos, entry->msi_attrib.is_64); +	entry->mask_pos = dev->msi_cap + (control & PCI_MSI_FLAGS_64BIT) ? +		PCI_MSI_MASK_64 : PCI_MSI_MASK_32;  	/* All MSIs are unmasked by default, Mask them all */  	if (entry->msi_attrib.maskbit)  		pci_read_config_dword(dev, entry->mask_pos, &entry->masked); @@ -598,31 +590,30 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)  	/* Set MSI enabled bits	 */  	pci_intx_for_msi(dev, 0); -	msi_set_enable(dev, pos, 1); +	msi_set_enable(dev, 1);  	dev->msi_enabled = 1;  	dev->irq = entry->irq;  	return 0;  } -static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos, -							unsigned nr_entries) +static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries)  {  	resource_size_t phys_addr;  	u32 table_offset;  	u8 bir; -	pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); -	bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); -	table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; +	pci_read_config_dword(dev, dev->msix_cap + PCI_MSIX_TABLE, +			      &table_offset); +	bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR); +	table_offset &= PCI_MSIX_TABLE_OFFSET;  	phys_addr = pci_resource_start(dev, bir) + table_offset;  	return ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);  } -static int msix_setup_entries(struct pci_dev *dev, unsigned pos, -				void __iomem *base, struct msix_entry *entries, -				int nvec) +static int msix_setup_entries(struct pci_dev *dev, void __iomem *base, +			      struct msix_entry *entries, int nvec)  {  	struct msi_desc *entry;  	int i; @@ -642,7 +633,7 @@ static int msix_setup_entries(struct pci_dev *dev, unsigned pos,  		entry->msi_attrib.is_64		= 1;  		entry->msi_attrib.entry_nr	= entries[i].entry;  		entry->msi_attrib.default_irq	= dev->irq; -		entry->msi_attrib.pos		= pos; +		entry->msi_attrib.pos		= dev->msix_cap;  		entry->mask_base		= base;  		list_add_tail(&entry->list, &dev->msi_list); @@ -652,7 +643,7 @@ static int msix_setup_entries(struct pci_dev *dev, unsigned pos,  }  static void msix_program_entries(struct pci_dev *dev, -					struct msix_entry *entries) +				 struct msix_entry *entries)  {  	struct msi_desc *entry;  	int i = 0; @@ -682,23 +673,22 @@ static void msix_program_entries(struct pci_dev *dev,  static int msix_capability_init(struct pci_dev *dev,  				struct msix_entry *entries, int nvec)  { -	int pos, ret; +	int ret;  	u16 control;  	void __iomem *base; -	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); -	pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); +	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);  	/* Ensure MSI-X is disabled while it is set up */  	control &= ~PCI_MSIX_FLAGS_ENABLE; -	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); +	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);  	/* Request & Map MSI-X table region */ -	base = msix_map_region(dev, pos, multi_msix_capable(control)); +	base = msix_map_region(dev, msix_table_size(control));  	if (!base)  		return -ENOMEM; -	ret = msix_setup_entries(dev, pos, base, entries, nvec); +	ret = msix_setup_entries(dev, base, entries, nvec);  	if (ret)  		return ret; @@ -712,7 +702,7 @@ static int msix_capability_init(struct pci_dev *dev,  	 * interrupts coming in before they're fully set up.  	 */  	control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE; -	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); +	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);  	msix_program_entries(dev, entries); @@ -727,7 +717,7 @@ static int msix_capability_init(struct pci_dev *dev,  	dev->msix_enabled = 1;  	control &= ~PCI_MSIX_FLAGS_MASKALL; -	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); +	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);  	return 0; @@ -795,9 +785,6 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)  	if (ret)  		return ret; -	if (!pci_find_capability(dev, type)) -		return -EINVAL; -  	return 0;  } @@ -816,13 +803,13 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)   */  int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)  { -	int status, pos, maxvec; +	int status, maxvec;  	u16 msgctl; -	pos = pci_find_capability(dev, PCI_CAP_ID_MSI); -	if (!pos) +	if (!dev->msi_cap)  		return -EINVAL; -	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); + +	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);  	maxvec = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);  	if (nvec > maxvec)  		return maxvec; @@ -847,14 +834,13 @@ EXPORT_SYMBOL(pci_enable_msi_block);  int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)  { -	int ret, pos, nvec; +	int ret, nvec;  	u16 msgctl; -	pos = pci_find_capability(dev, PCI_CAP_ID_MSI); -	if (!pos) +	if (!dev->msi_cap)  		return -EINVAL; -	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); +	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);  	ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);  	if (maxvec) @@ -876,21 +862,19 @@ void pci_msi_shutdown(struct pci_dev *dev)  	struct msi_desc *desc;  	u32 mask;  	u16 ctrl; -	unsigned pos;  	if (!pci_msi_enable || !dev || !dev->msi_enabled)  		return;  	BUG_ON(list_empty(&dev->msi_list));  	desc = list_first_entry(&dev->msi_list, struct msi_desc, list); -	pos = desc->msi_attrib.pos; -	msi_set_enable(dev, pos, 0); +	msi_set_enable(dev, 0);  	pci_intx_for_msi(dev, 1);  	dev->msi_enabled = 0;  	/* Return the device with MSI unmasked as initial states */ -	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl); +	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &ctrl);  	mask = msi_capable_mask(ctrl);  	/* Keep cached state to be restored */  	__msi_mask_irq(desc, mask, ~mask); @@ -917,15 +901,13 @@ EXPORT_SYMBOL(pci_disable_msi);   */  int pci_msix_table_size(struct pci_dev *dev)  { -	int pos;  	u16 control; -	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); -	if (!pos) +	if (!dev->msix_cap)  		return 0; -	pci_read_config_word(dev, msi_control_reg(pos), &control); -	return multi_msix_capable(control); +	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); +	return msix_table_size(control);  }  /** @@ -948,7 +930,7 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)  	int status, nr_entries;  	int i, j; -	if (!entries) +	if (!entries || !dev->msix_cap)  		return -EINVAL;  	status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX); @@ -1048,15 +1030,17 @@ EXPORT_SYMBOL(pci_msi_enabled);  void pci_msi_init_pci_dev(struct pci_dev *dev)  { -	int pos;  	INIT_LIST_HEAD(&dev->msi_list);  	/* Disable the msi hardware to avoid screaming interrupts  	 * during boot.  This is the power on reset default so  	 * usually this should be a noop.  	 */ -	pos = pci_find_capability(dev, PCI_CAP_ID_MSI); -	if (pos) -		msi_set_enable(dev, pos, 0); -	msix_set_enable(dev, 0); +	dev->msi_cap = pci_find_capability(dev, PCI_CAP_ID_MSI); +	if (dev->msi_cap) +		msi_set_enable(dev, 0); + +	dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX); +	if (dev->msix_cap) +		msix_set_enable(dev, 0);  } diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h deleted file mode 100644 index 65c42f80f23..00000000000 --- a/drivers/pci/msi.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2003-2004 Intel - * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) - */ - -#ifndef MSI_H -#define MSI_H - -#define msi_control_reg(base)		(base + PCI_MSI_FLAGS) -#define msi_lower_address_reg(base)	(base + PCI_MSI_ADDRESS_LO) -#define msi_upper_address_reg(base)	(base + PCI_MSI_ADDRESS_HI) -#define msi_data_reg(base, is64bit)	\ -	(base + ((is64bit == 1) ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32)) -#define msi_mask_reg(base, is64bit)	\ -	(base + ((is64bit == 1) ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32)) -#define is_64bit_address(control)	(!!(control & PCI_MSI_FLAGS_64BIT)) -#define is_mask_bit_support(control)	(!!(control & PCI_MSI_FLAGS_MASKBIT)) - -#define msix_table_offset_reg(base)	(base + PCI_MSIX_TABLE) -#define msix_pba_offset_reg(base)	(base + PCI_MSIX_PBA) -#define msix_table_size(control) 	((control & PCI_MSIX_FLAGS_QSIZE)+1) -#define multi_msix_capable(control)	msix_table_size((control)) - -#endif /* MSI_H */ diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 5147c210df5..e4b1fb2c0f5 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -288,6 +288,32 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {  	.run_wake = acpi_pci_run_wake,  }; +void acpi_pci_add_bus(struct pci_bus *bus) +{ +	acpi_handle handle = NULL; + +	if (bus->bridge) +		handle = ACPI_HANDLE(bus->bridge); +	if (acpi_pci_disabled || handle == NULL) +		return; + +	acpi_pci_slot_enumerate(bus, handle); +	acpiphp_enumerate_slots(bus, handle); +} + +void acpi_pci_remove_bus(struct pci_bus *bus) +{ +	/* +	 * bus->bridge->acpi_node.handle has already been reset to NULL +	 * when acpi_pci_remove_bus() is called, so don't check ACPI handle. +	 */ +	if (acpi_pci_disabled) +		return; + +	acpiphp_remove_slots(bus); +	acpi_pci_slot_remove(bus); +} +  /* ACPI bus type */  static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)  { @@ -362,7 +388,11 @@ static int __init acpi_pci_init(void)  	ret = register_acpi_bus_type(&acpi_pci_bus);  	if (ret)  		return 0; +  	pci_set_platform_pm(&acpi_pci_platform_pm); +	acpi_pci_slot_init(); +	acpiphp_init(); +  	return 0;  }  arch_initcall(acpi_pci_init); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 9c6e9bb674e..5b4a9d9cd20 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -897,7 +897,7 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,  	if (pci_resource_len(pdev, resno) == 0)  		return 0; -	nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; +	nr = vma_pages(vma);  	start = vma->vm_pgoff;  	size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;  	pci_start = (mmap_api == PCI_MMAP_PROCFS) ? diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b099e0025d2..a899d8bb190 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -646,15 +646,11 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)  		error = platform_pci_set_power_state(dev, state);  		if (!error)  			pci_update_current_state(dev, state); -		/* Fall back to PCI_D0 if native PM is not supported */ -		if (!dev->pm_cap) -			dev->current_state = PCI_D0; -	} else { +	} else  		error = -ENODEV; -		/* Fall back to PCI_D0 if native PM is not supported */ -		if (!dev->pm_cap) -			dev->current_state = PCI_D0; -	} + +	if (error && !dev->pm_cap) /* Fall back to PCI_D0 */ +		dev->current_state = PCI_D0;  	return error;  } @@ -1575,7 +1571,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)  {  	u16 pmcsr; -	if (!dev->pm_cap) +	if (!dev->pme_support)  		return;  	pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); @@ -1924,6 +1920,7 @@ void pci_pm_init(struct pci_dev *dev)  	dev->wakeup_prepared = false;  	dev->pm_cap = 0; +	dev->pme_support = 0;  	/* find PCI PM capability in list */  	pm = pci_find_capability(dev, PCI_CAP_ID_PM); @@ -1975,8 +1972,6 @@ void pci_pm_init(struct pci_dev *dev)  		device_set_wakeup_capable(&dev->dev, true);  		/* Disable the PME# generation functionality */  		pci_pme_active(dev, false); -	} else { -		dev->pme_support = 0;  	}  } @@ -2619,7 +2614,7 @@ void pci_release_selected_regions(struct pci_dev *pdev, int bars)  			pci_release_region(pdev, i);  } -int __pci_request_selected_regions(struct pci_dev *pdev, int bars, +static int __pci_request_selected_regions(struct pci_dev *pdev, int bars,  				 const char *res_name, int excl)  {  	int i; @@ -3699,7 +3694,7 @@ static DEFINE_SPINLOCK(resource_alignment_lock);   * RETURNS: Resource alignment if it is specified.   *          Zero if it is not specified.   */ -resource_size_t pci_specified_resource_alignment(struct pci_dev *dev) +static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)  {  	int seg, bus, slot, func, align_order, count;  	resource_size_t align = 0; @@ -3812,7 +3807,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)  	}  } -ssize_t pci_set_resource_alignment_param(const char *buf, size_t count) +static ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)  {  	if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1)  		count = RESOURCE_ALIGNMENT_PARAM_SIZE - 1; @@ -3823,7 +3818,7 @@ ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)  	return count;  } -ssize_t pci_get_resource_alignment_param(char *buf, size_t size) +static ssize_t pci_get_resource_alignment_param(char *buf, size_t size)  {  	size_t count;  	spin_lock(&resource_alignment_lock); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 7346ee68f47..68678ed76b0 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -8,26 +8,25 @@  /* Functions internal to the PCI core code */ -extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); -extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); +int pci_create_sysfs_dev_files(struct pci_dev *pdev); +void pci_remove_sysfs_dev_files(struct pci_dev *pdev);  #if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI)  static inline void pci_create_firmware_label_files(struct pci_dev *pdev)  { return; }  static inline void pci_remove_firmware_label_files(struct pci_dev *pdev)  { return; }  #else -extern void pci_create_firmware_label_files(struct pci_dev *pdev); -extern void pci_remove_firmware_label_files(struct pci_dev *pdev); +void pci_create_firmware_label_files(struct pci_dev *pdev); +void pci_remove_firmware_label_files(struct pci_dev *pdev);  #endif -extern void pci_cleanup_rom(struct pci_dev *dev); +void pci_cleanup_rom(struct pci_dev *dev);  #ifdef HAVE_PCI_MMAP  enum pci_mmap_api {  	PCI_MMAP_SYSFS,	/* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */  	PCI_MMAP_PROCFS	/* mmap on /proc/bus/pci/<BDF> */  }; -extern int pci_mmap_fits(struct pci_dev *pdev, int resno, -			 struct vm_area_struct *vmai, -			 enum pci_mmap_api mmap_api); +int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai, +		  enum pci_mmap_api mmap_api);  #endif  int pci_probe_reset_function(struct pci_dev *dev); @@ -60,17 +59,17 @@ struct pci_platform_pm_ops {  	int (*run_wake)(struct pci_dev *dev, bool enable);  }; -extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); -extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state); -extern void pci_power_up(struct pci_dev *dev); -extern void pci_disable_enabled_device(struct pci_dev *dev); -extern int pci_finish_runtime_suspend(struct pci_dev *dev); -extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign); -extern void pci_wakeup_bus(struct pci_bus *bus); -extern void pci_config_pm_runtime_get(struct pci_dev *dev); -extern void pci_config_pm_runtime_put(struct pci_dev *dev); -extern void pci_pm_init(struct pci_dev *dev); -extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); +int pci_set_platform_pm(struct pci_platform_pm_ops *ops); +void pci_update_current_state(struct pci_dev *dev, pci_power_t state); +void pci_power_up(struct pci_dev *dev); +void pci_disable_enabled_device(struct pci_dev *dev); +int pci_finish_runtime_suspend(struct pci_dev *dev); +int __pci_pme_wakeup(struct pci_dev *dev, void *ign); +void pci_wakeup_bus(struct pci_bus *bus); +void pci_config_pm_runtime_get(struct pci_dev *dev); +void pci_config_pm_runtime_put(struct pci_dev *dev); +void pci_pm_init(struct pci_dev *dev); +void pci_allocate_cap_save_buffers(struct pci_dev *dev);  void pci_free_cap_save_buffers(struct pci_dev *dev);  static inline void pci_wakeup_event(struct pci_dev *dev) @@ -96,7 +95,7 @@ struct pci_vpd {  	struct bin_attribute *attr; /* descriptor for sysfs VPD entry */  }; -extern int pci_vpd_pci22_init(struct pci_dev *dev); +int pci_vpd_pci22_init(struct pci_dev *dev);  static inline void pci_vpd_release(struct pci_dev *dev)  {  	if (dev->vpd) @@ -105,9 +104,9 @@ static inline void pci_vpd_release(struct pci_dev *dev)  /* PCI /proc functions */  #ifdef CONFIG_PROC_FS -extern int pci_proc_attach_device(struct pci_dev *dev); -extern int pci_proc_detach_device(struct pci_dev *dev); -extern int pci_proc_detach_bus(struct pci_bus *bus); +int pci_proc_attach_device(struct pci_dev *dev); +int pci_proc_detach_device(struct pci_dev *dev); +int pci_proc_detach_bus(struct pci_bus *bus);  #else  static inline int pci_proc_attach_device(struct pci_dev *dev) { return 0; }  static inline int pci_proc_detach_device(struct pci_dev *dev) { return 0; } @@ -118,8 +117,8 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }  int pci_hp_add_bridge(struct pci_dev *dev);  #ifdef HAVE_PCI_LEGACY -extern void pci_create_legacy_files(struct pci_bus *bus); -extern void pci_remove_legacy_files(struct pci_bus *bus); +void pci_create_legacy_files(struct pci_bus *bus); +void pci_remove_legacy_files(struct pci_bus *bus);  #else  static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }  static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; } @@ -134,7 +133,7 @@ extern unsigned int pci_pm_d3_delay;  #ifdef CONFIG_PCI_MSI  void pci_no_msi(void); -extern void pci_msi_init_pci_dev(struct pci_dev *dev); +void pci_msi_init_pci_dev(struct pci_dev *dev);  #else  static inline void pci_no_msi(void) { }  static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } @@ -198,12 +197,11 @@ enum pci_bar_type {  bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *pl,  				int crs_timeout); -extern int pci_setup_device(struct pci_dev *dev); -extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, -				struct resource *res, unsigned int reg); -extern int pci_resource_bar(struct pci_dev *dev, int resno, -			    enum pci_bar_type *type); -extern void pci_configure_ari(struct pci_dev *dev); +int pci_setup_device(struct pci_dev *dev); +int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, +		    struct resource *res, unsigned int reg); +int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type); +void pci_configure_ari(struct pci_dev *dev);  /**   * pci_ari_enabled - query ARI forwarding status @@ -217,7 +215,7 @@ static inline int pci_ari_enabled(struct pci_bus *bus)  }  void pci_reassigndev_resource_alignment(struct pci_dev *dev); -extern void pci_disable_bridge_window(struct pci_dev *dev); +void pci_disable_bridge_window(struct pci_dev *dev);  /* Single Root I/O Virtualization */  struct pci_sriov { @@ -241,7 +239,7 @@ struct pci_sriov {  };  #ifdef CONFIG_PCI_ATS -extern void pci_restore_ats_state(struct pci_dev *dev); +void pci_restore_ats_state(struct pci_dev *dev);  #else  static inline void pci_restore_ats_state(struct pci_dev *dev)  { @@ -249,14 +247,13 @@ static inline void pci_restore_ats_state(struct pci_dev *dev)  #endif /* CONFIG_PCI_ATS */  #ifdef CONFIG_PCI_IOV -extern int pci_iov_init(struct pci_dev *dev); -extern void pci_iov_release(struct pci_dev *dev); -extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, -				enum pci_bar_type *type); -extern resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, -						    int resno); -extern void pci_restore_iov_state(struct pci_dev *dev); -extern int pci_iov_bus_range(struct pci_bus *bus); +int pci_iov_init(struct pci_dev *dev); +void pci_iov_release(struct pci_dev *dev); +int pci_iov_resource_bar(struct pci_dev *dev, int resno, +			 enum pci_bar_type *type); +resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno); +void pci_restore_iov_state(struct pci_dev *dev); +int pci_iov_bus_range(struct pci_bus *bus);  #else  static inline int pci_iov_init(struct pci_dev *dev) @@ -282,10 +279,10 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)  #endif /* CONFIG_PCI_IOV */ -extern unsigned long pci_cardbus_resource_alignment(struct resource *); +unsigned long pci_cardbus_resource_alignment(struct resource *);  static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, -					 struct resource *res) +						     struct resource *res)  {  #ifdef CONFIG_PCI_IOV  	int resno = res - dev->resource; @@ -298,7 +295,7 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,  	return resource_alignment(res);  } -extern void pci_enable_acs(struct pci_dev *dev); +void pci_enable_acs(struct pci_dev *dev);  struct pci_dev_reset_methods {  	u16 vendor; @@ -307,7 +304,7 @@ struct pci_dev_reset_methods {  };  #ifdef CONFIG_PCI_QUIRKS -extern int pci_dev_specific_reset(struct pci_dev *dev, int probe); +int pci_dev_specific_reset(struct pci_dev *dev, int probe);  #else  static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)  { diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index fde4a32a029..569f82fc9e2 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -82,4 +82,4 @@ endchoice  config PCIE_PME  	def_bool y -	depends on PCIEPORTBUS && PM_RUNTIME && ACPI +	depends on PCIEPORTBUS && PM_RUNTIME diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 4e24cb8a94a..587e7e85310 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -212,8 +212,8 @@ out:  	return ops->read(bus, devfn, where, size, val);  } -int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size, -		  u32 val) +static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, +			 int size, u32 val)  {  	u32 *sim;  	struct aer_error *err; @@ -334,13 +334,13 @@ static int aer_inject(struct aer_error_inj *einj)  		return -ENODEV;  	rpdev = pcie_find_root_port(dev);  	if (!rpdev) { -		ret = -ENOTTY; +		ret = -ENODEV;  		goto out_put;  	}  	pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);  	if (!pos_cap_err) { -		ret = -ENOTTY; +		ret = -EPERM;  		goto out_put;  	}  	pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever); @@ -350,7 +350,7 @@ static int aer_inject(struct aer_error_inj *einj)  	rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);  	if (!rp_pos_cap_err) { -		ret = -ENOTTY; +		ret = -EPERM;  		goto out_put;  	} diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index 22f840f4dda..d12c77cd699 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h @@ -110,15 +110,15 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,  }  extern struct bus_type pcie_port_bus_type; -extern void aer_do_secondary_bus_reset(struct pci_dev *dev); -extern int aer_init(struct pcie_device *dev); -extern void aer_isr(struct work_struct *work); -extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); -extern void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); -extern irqreturn_t aer_irq(int irq, void *context); +void aer_do_secondary_bus_reset(struct pci_dev *dev); +int aer_init(struct pcie_device *dev); +void aer_isr(struct work_struct *work); +void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); +void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); +irqreturn_t aer_irq(int irq, void *context);  #ifdef CONFIG_ACPI_APEI -extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev); +int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);  #else  static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)  { diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 564d97f94b6..8ec8b4f4856 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -89,8 +89,6 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)  	return -ENOSPC;  } -#define	PCI_BUS(x)	(((x) >> 8) & 0xff) -  /**   * is_error_source - check whether the device is source of reported error   * @dev: pointer to pci_dev to be checked @@ -106,7 +104,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)  	 * When bus id is equal to 0, it might be a bad id  	 * reported by root port.  	 */ -	if (!nosourceid && (PCI_BUS(e_info->id) != 0)) { +	if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) {  		/* Device ID match? */  		if (e_info->id == ((dev->bus->number << 8) | dev->devfn))  			return true; diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 9ca0dc9ffd8..795db1f9d50 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c @@ -19,8 +19,6 @@  #include <linux/interrupt.h>  #include <linux/device.h>  #include <linux/pcieport_if.h> -#include <linux/acpi.h> -#include <linux/pci-acpi.h>  #include <linux/pm_runtime.h>  #include "../pci.h" diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index eea2ca2375e..d2eb80aab56 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -21,18 +21,18 @@  #define get_descriptor_id(type, service) (((type - 4) << 4) | service)  extern struct bus_type pcie_port_bus_type; -extern int pcie_port_device_register(struct pci_dev *dev); +int pcie_port_device_register(struct pci_dev *dev);  #ifdef CONFIG_PM -extern int pcie_port_device_suspend(struct device *dev); -extern int pcie_port_device_resume(struct device *dev); +int pcie_port_device_suspend(struct device *dev); +int pcie_port_device_resume(struct device *dev);  #endif -extern void pcie_port_device_remove(struct pci_dev *dev); -extern int __must_check pcie_port_bus_register(void); -extern void pcie_port_bus_unregister(void); +void pcie_port_device_remove(struct pci_dev *dev); +int __must_check pcie_port_bus_register(void); +void pcie_port_bus_unregister(void);  struct pci_dev; -extern void pcie_clear_root_pme_status(struct pci_dev *dev); +void pcie_clear_root_pme_status(struct pci_dev *dev);  #ifdef CONFIG_HOTPLUG_PCI_PCIE  extern bool pciehp_msi_disabled; @@ -59,7 +59,7 @@ static inline bool pcie_pme_no_msi(void)  	return pcie_pme_msi_disabled;  } -extern void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable); +void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable);  #else /* !CONFIG_PCIE_PME */  static inline void pcie_pme_disable_msi(void) {}  static inline bool pcie_pme_no_msi(void) { return false; } @@ -67,7 +67,7 @@ static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {}  #endif /* !CONFIG_PCIE_PME */  #ifdef CONFIG_ACPI -extern int pcie_port_acpi_setup(struct pci_dev *port, int *mask); +int pcie_port_acpi_setup(struct pci_dev *port, int *mask);  static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask)  { diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c index a86b56e5f2f..b4d2894ee3f 100644 --- a/drivers/pci/pcie/portdrv_acpi.c +++ b/drivers/pci/pcie/portdrv_acpi.c @@ -17,6 +17,7 @@  #include "aer/aerdrv.h"  #include "../pci.h" +#include "portdrv.h"  /**   * pcie_port_acpi_setup - Request the BIOS to release control of PCIe services. diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index ed4d0949833..696caed5fdf 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -259,11 +259,9 @@ static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,  					enum pci_channel_state error)  {  	struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER}; -	int ret; - -	/* can not fail */ -	ret = device_for_each_child(&dev->dev, &data, error_detected_iter); +	/* get true return value from &data */ +	device_for_each_child(&dev->dev, &data, error_detected_iter);  	return data.result;  } @@ -295,10 +293,9 @@ static int mmio_enabled_iter(struct device *device, void *data)  static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)  {  	pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; -	int retval;  	/* get true return value from &status */ -	retval = device_for_each_child(&dev->dev, &status, mmio_enabled_iter); +	device_for_each_child(&dev->dev, &status, mmio_enabled_iter);  	return status;  } @@ -330,7 +327,6 @@ static int slot_reset_iter(struct device *device, void *data)  static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)  {  	pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; -	int retval;  	/* If fatal, restore cfg space for possible link reset at upstream */  	if (dev->error_state == pci_channel_io_frozen) { @@ -341,8 +337,7 @@ static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)  	}  	/* get true return value from &status */ -	retval = device_for_each_child(&dev->dev, &status, slot_reset_iter); - +	device_for_each_child(&dev->dev, &status, slot_reset_iter);  	return status;  } @@ -368,9 +363,7 @@ static int resume_iter(struct device *device, void *data)  static void pcie_portdrv_err_resume(struct pci_dev *dev)  { -	int retval; -	/* nothing to do with error value, if it ever happens */ -	retval = device_for_each_child(&dev->dev, NULL, resume_iter); +	device_for_each_child(&dev->dev, NULL, resume_iter);  }  /* diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b494066ef32..43ece5d41d3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -673,6 +673,8 @@ add_dev:  	ret = device_register(&child->dev);  	WARN_ON(ret < 0); +	pcibios_add_bus(child); +  	/* Create legacy_io and legacy_mem files for this bus */  	pci_create_legacy_files(child); @@ -1627,8 +1629,7 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)  	if (!bus->is_added) {  		dev_dbg(&bus->dev, "fixups for bus\n");  		pcibios_fixup_bus(bus); -		if (pci_is_root_bus(bus)) -			bus->is_added = 1; +		bus->is_added = 1;  	}  	for (pass=0; pass < 2; pass++) @@ -1661,6 +1662,14 @@ int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)  	return 0;  } +void __weak pcibios_add_bus(struct pci_bus *bus) +{ +} + +void __weak pcibios_remove_bus(struct pci_bus *bus) +{ +} +  struct pci_bus *pci_create_root_bus(struct device *parent, int bus,  		struct pci_ops *ops, void *sysdata, struct list_head *resources)  { @@ -1715,6 +1724,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,  	if (error)  		goto class_dev_reg_err; +	pcibios_add_bus(b); +  	/* Create legacy_io and legacy_mem files for this bus */  	pci_create_legacy_files(b); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 0369fb6fc1d..7d68aeebf56 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -324,29 +324,30 @@ static void quirk_cs5536_vsa(struct pci_dev *dev)  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa); -static void quirk_io_region(struct pci_dev *dev, unsigned region, -	unsigned size, int nr, const char *name) +static void quirk_io_region(struct pci_dev *dev, int port, +				unsigned size, int nr, const char *name)  { -	region &= ~(size-1); -	if (region) { -		struct pci_bus_region bus_region; -		struct resource *res = dev->resource + nr; +	u16 region; +	struct pci_bus_region bus_region; +	struct resource *res = dev->resource + nr; -		res->name = pci_name(dev); -		res->start = region; -		res->end = region + size - 1; -		res->flags = IORESOURCE_IO; +	pci_read_config_word(dev, port, ®ion); +	region &= ~(size - 1); -		/* Convert from PCI bus to resource space.  */ -		bus_region.start = res->start; -		bus_region.end = res->end; -		pcibios_bus_to_resource(dev, res, &bus_region); +	if (!region) +		return; -		if (pci_claim_resource(dev, nr) == 0) -			dev_info(&dev->dev, "quirk: %pR claimed by %s\n", -				 res, name); -	} -}	 +	res->name = pci_name(dev); +	res->flags = IORESOURCE_IO; + +	/* Convert from PCI bus to resource space */ +	bus_region.start = region; +	bus_region.end = region + size - 1; +	pcibios_bus_to_resource(dev, res, &bus_region); + +	if (!pci_claim_resource(dev, nr)) +		dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name); +}  /*   *	ATI Northbridge setups MCE the processor if you even @@ -374,12 +375,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI,	PCI_DEVICE_ID_ATI_RS100,   quirk_ati_   */  static void quirk_ali7101_acpi(struct pci_dev *dev)  { -	u16 region; - -	pci_read_config_word(dev, 0xE0, ®ion); -	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI"); -	pci_read_config_word(dev, 0xE2, ®ion); -	quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB"); +	quirk_io_region(dev, 0xE0, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI"); +	quirk_io_region(dev, 0xE2, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB");  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M7101,		quirk_ali7101_acpi); @@ -442,12 +439,10 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int   */  static void quirk_piix4_acpi(struct pci_dev *dev)  { -	u32 region, res_a; +	u32 res_a; -	pci_read_config_dword(dev, 0x40, ®ion); -	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI"); -	pci_read_config_dword(dev, 0x90, ®ion); -	quirk_io_region(dev, region, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB"); +	quirk_io_region(dev, 0x40, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI"); +	quirk_io_region(dev, 0x90, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");  	/* Device resource A has enables for some of the other ones */  	pci_read_config_dword(dev, 0x5c, &res_a); @@ -491,7 +486,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443MX_3,	qui   */  static void quirk_ich4_lpc_acpi(struct pci_dev *dev)  { -	u32 region;  	u8 enable;  	/* @@ -503,22 +497,14 @@ static void quirk_ich4_lpc_acpi(struct pci_dev *dev)  	*/  	pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); -	if (enable & ICH4_ACPI_EN) { -		pci_read_config_dword(dev, ICH_PMBASE, ®ion); -		region &= PCI_BASE_ADDRESS_IO_MASK; -		if (region >= PCIBIOS_MIN_IO) -			quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, -					"ICH4 ACPI/GPIO/TCO"); -	} +	if (enable & ICH4_ACPI_EN) +		quirk_io_region(dev, ICH_PMBASE, 128, PCI_BRIDGE_RESOURCES, +				 "ICH4 ACPI/GPIO/TCO");  	pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable); -	if (enable & ICH4_GPIO_EN) { -		pci_read_config_dword(dev, ICH4_GPIOBASE, ®ion); -		region &= PCI_BASE_ADDRESS_IO_MASK; -		if (region >= PCIBIOS_MIN_IO) -			quirk_io_region(dev, region, 64, -					PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO"); -	} +	if (enable & ICH4_GPIO_EN) +		quirk_io_region(dev, ICH4_GPIOBASE, 64, PCI_BRIDGE_RESOURCES+1, +				"ICH4 GPIO");  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,		quirk_ich4_lpc_acpi);  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,		quirk_ich4_lpc_acpi); @@ -533,26 +519,17 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_ESB_1,		qui  static void ich6_lpc_acpi_gpio(struct pci_dev *dev)  { -	u32 region;  	u8 enable;  	pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); -	if (enable & ICH6_ACPI_EN) { -		pci_read_config_dword(dev, ICH_PMBASE, ®ion); -		region &= PCI_BASE_ADDRESS_IO_MASK; -		if (region >= PCIBIOS_MIN_IO) -			quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, -					"ICH6 ACPI/GPIO/TCO"); -	} +	if (enable & ICH6_ACPI_EN) +		quirk_io_region(dev, ICH_PMBASE, 128, PCI_BRIDGE_RESOURCES, +				 "ICH6 ACPI/GPIO/TCO");  	pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable); -	if (enable & ICH6_GPIO_EN) { -		pci_read_config_dword(dev, ICH6_GPIOBASE, ®ion); -		region &= PCI_BASE_ADDRESS_IO_MASK; -		if (region >= PCIBIOS_MIN_IO) -			quirk_io_region(dev, region, 64, -					PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO"); -	} +	if (enable & ICH6_GPIO_EN) +		quirk_io_region(dev, ICH6_GPIOBASE, 64, PCI_BRIDGE_RESOURCES+1, +				"ICH6 GPIO");  }  static void ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize) @@ -650,13 +627,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_ICH10_1, qui   */  static void quirk_vt82c586_acpi(struct pci_dev *dev)  { -	u32 region; - -	if (dev->revision & 0x10) { -		pci_read_config_dword(dev, 0x48, ®ion); -		region &= PCI_BASE_ADDRESS_IO_MASK; -		quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI"); -	} +	if (dev->revision & 0x10) +		quirk_io_region(dev, 0x48, 256, PCI_BRIDGE_RESOURCES, +				"vt82c586 ACPI");  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_vt82c586_acpi); @@ -668,18 +641,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_vt   */  static void quirk_vt82c686_acpi(struct pci_dev *dev)  { -	u16 hm; -	u32 smb; -  	quirk_vt82c586_acpi(dev); -	pci_read_config_word(dev, 0x70, &hm); -	hm &= PCI_BASE_ADDRESS_IO_MASK; -	quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c686 HW-mon"); +	quirk_io_region(dev, 0x70, 128, PCI_BRIDGE_RESOURCES+1, +				 "vt82c686 HW-mon"); -	pci_read_config_dword(dev, 0x90, &smb); -	smb &= PCI_BASE_ADDRESS_IO_MASK; -	quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB"); +	quirk_io_region(dev, 0x90, 16, PCI_BRIDGE_RESOURCES+2, "vt82c686 SMB");  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vt82c686_acpi); @@ -690,15 +657,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vt   */  static void quirk_vt8235_acpi(struct pci_dev *dev)  { -	u16 pm, smb; - -	pci_read_config_word(dev, 0x88, &pm); -	pm &= PCI_BASE_ADDRESS_IO_MASK; -	quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM"); - -	pci_read_config_word(dev, 0xd0, &smb); -	smb &= PCI_BASE_ADDRESS_IO_MASK; -	quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1, "vt8235 SMB"); +	quirk_io_region(dev, 0x88, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM"); +	quirk_io_region(dev, 0xd0, 16, PCI_BRIDGE_RESOURCES+1, "vt8235 SMB");  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8235,	quirk_vt8235_acpi); @@ -2594,6 +2554,14 @@ static void quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)  		dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;  	pci_dev_put(p);  } +static void quirk_msi_intx_disable_qca_bug(struct pci_dev *dev) +{ +	/* AR816X/AR817X/E210X MSI is fixed at HW level from revision 0x18 */ +	if (dev->revision < 0x18) { +		dev_info(&dev->dev, "set MSI_INTX_DISABLE_BUG flag\n"); +		dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG; +	} +}  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,  			PCI_DEVICE_ID_TIGON3_5780,  			quirk_msi_intx_disable_bug); @@ -2643,6 +2611,16 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1073,  			quirk_msi_intx_disable_bug);  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1083,  			quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1090, +			quirk_msi_intx_disable_qca_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1091, +			quirk_msi_intx_disable_qca_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x10a0, +			quirk_msi_intx_disable_qca_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x10a1, +			quirk_msi_intx_disable_qca_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0xe091, +			quirk_msi_intx_disable_qca_bug);  #endif /* CONFIG_PCI_MSI */  /* Allow manual resource allocation for PCI hotplug bridges diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index cc875e6ed15..8fc54b7327b 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -50,10 +50,8 @@ void pci_remove_bus(struct pci_bus *bus)  	list_del(&bus->node);  	pci_bus_release_busn_res(bus);  	up_write(&pci_bus_sem); -	if (!bus->is_added) -		return; -  	pci_remove_legacy_files(bus); +	pcibios_remove_bus(bus);  	device_unregister(&bus->dev);  }  EXPORT_SYMBOL(pci_remove_bus); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 7e8739e25b9..16abaaa1f83 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1044,7 +1044,7 @@ handle_done:  	;  } -void __ref __pci_bus_size_bridges(struct pci_bus *bus, +static void __ref __pci_bus_size_bridges(struct pci_bus *bus,  			struct list_head *realloc_head)  {  	struct pci_dev *dev; @@ -1545,6 +1545,8 @@ again:  enable_all:  	retval = pci_reenable_device(bridge); +	if (retval) +		dev_err(&bridge->dev, "Error reenabling bridge (%d)\n", retval);  	pci_set_master(bridge);  	pci_enable_bridges(parent);  } diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 81b88bda793..07f2eddc09c 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -261,7 +261,6 @@ int pci_assign_resource(struct pci_dev *dev, int resno)  {  	struct resource *res = dev->resource + resno;  	resource_size_t align, size; -	struct pci_bus *bus;  	int ret;  	align = pci_resource_alignment(dev, res); @@ -271,7 +270,6 @@ int pci_assign_resource(struct pci_dev *dev, int resno)  		return -EINVAL;  	} -	bus = dev->bus;  	size = resource_size(res);  	ret = _pci_assign_resource(dev, resno, size, align); diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index ac6412fb8d6..c1e9284a677 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -377,14 +377,17 @@ void pci_hp_create_module_link(struct pci_slot *pci_slot)  {  	struct hotplug_slot *slot = pci_slot->hotplug;  	struct kobject *kobj = NULL; -	int no_warn; +	int ret;  	if (!slot || !slot->ops)  		return;  	kobj = kset_find_obj(module_kset, slot->ops->mod_name);  	if (!kobj)  		return; -	no_warn = sysfs_create_link(&pci_slot->kobj, kobj, "module"); +	ret = sysfs_create_link(&pci_slot->kobj, kobj, "module"); +	if (ret) +		dev_err(&pci_slot->bus->dev, "Error creating sysfs link (%d)\n", +			ret);  	kobject_put(kobj);  }  EXPORT_SYMBOL_GPL(pci_hp_create_module_link);  |