Merge branch 'acpi-pci-hotplug'
* acpi-pci-hotplug: (34 commits) ACPI / PM: Hold acpi_scan_lock over system PM transitions ACPI / hotplug / PCI: Fix NULL pointer dereference in cleanup_bridge() PCI / ACPI: Use dev_dbg() instead of dev_info() in acpi_pci_set_power_state() ACPI / hotplug / PCI: Get rid of check_sub_bridges() ACPI / hotplug / PCI: Clean up bridge_mutex usage ACPI / hotplug / PCI: Redefine enable_device() and disable_device() ACPI / hotplug / PCI: Sanitize acpiphp_get_(latch)|(adapter)_status() ACPI / hotplug / PCI: Get rid of unused constants in acpiphp.h ACPI / hotplug / PCI: Check for new devices on enabled slots ACPI / hotplug / PCI: Allow slots without new devices to be rescanned ACPI / hotplug / PCI: Do not check SLOT_ENABLED in enable_device() ACPI / hotplug / PCI: Do not exectute _PS0 and _PS3 directly ACPI / hotplug / PCI: Do not queue up event handling work items in vain ACPI / hotplug / PCI: Consolidate slot disabling and ejecting ACPI / hotplug / PCI: Drop redundant checks from check_hotplug_bridge() ACPI / hotplug / PCI: Rework namespace scanning and trimming routines ACPI / hotplug / PCI: Store parent in functions and bus in slots ACPI / hotplug / PCI: Drop handle field from struct acpiphp_bridge ACPI / hotplug / PCI: Drop handle field from struct acpiphp_func ACPI / hotplug / PCI: Embed function struct into struct acpiphp_context ...
This commit is contained in:
commit
abe5430e9d
|
@ -210,6 +210,8 @@ static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
|
|||
r = &dev->resource[idx];
|
||||
if (!r->flags)
|
||||
continue;
|
||||
if (r->parent) /* Already allocated */
|
||||
continue;
|
||||
if (!r->start || pci_claim_resource(dev, idx) < 0) {
|
||||
/*
|
||||
* Something is wrong with the region.
|
||||
|
@ -318,6 +320,8 @@ static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
|
|||
r = &dev->resource[PCI_ROM_RESOURCE];
|
||||
if (!r->flags || !r->start)
|
||||
return;
|
||||
if (r->parent) /* Already allocated */
|
||||
return;
|
||||
|
||||
if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
|
||||
r->end -= r->start;
|
||||
|
|
|
@ -159,12 +159,16 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
|||
return AE_OK;
|
||||
}
|
||||
|
||||
void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle)
|
||||
void acpi_pci_slot_enumerate(struct pci_bus *bus)
|
||||
{
|
||||
mutex_lock(&slot_list_lock);
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
|
||||
register_slot, NULL, bus, NULL);
|
||||
mutex_unlock(&slot_list_lock);
|
||||
acpi_handle handle = ACPI_HANDLE(bus->bridge);
|
||||
|
||||
if (handle) {
|
||||
mutex_lock(&slot_list_lock);
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
|
||||
register_slot, NULL, bus, NULL);
|
||||
mutex_unlock(&slot_list_lock);
|
||||
}
|
||||
}
|
||||
|
||||
void acpi_pci_slot_remove(struct pci_bus *bus)
|
||||
|
|
|
@ -420,10 +420,21 @@ static void acpi_pm_finish(void)
|
|||
}
|
||||
|
||||
/**
|
||||
* acpi_pm_end - Finish up suspend sequence.
|
||||
* acpi_pm_start - Start system PM transition.
|
||||
*/
|
||||
static void acpi_pm_start(u32 acpi_state)
|
||||
{
|
||||
acpi_target_sleep_state = acpi_state;
|
||||
acpi_sleep_tts_switch(acpi_target_sleep_state);
|
||||
acpi_scan_lock_acquire();
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_pm_end - Finish up system PM transition.
|
||||
*/
|
||||
static void acpi_pm_end(void)
|
||||
{
|
||||
acpi_scan_lock_release();
|
||||
/*
|
||||
* This is necessary in case acpi_pm_finish() is not called during a
|
||||
* failing transition to a sleep state.
|
||||
|
@ -451,21 +462,19 @@ static u32 acpi_suspend_states[] = {
|
|||
static int acpi_suspend_begin(suspend_state_t pm_state)
|
||||
{
|
||||
u32 acpi_state = acpi_suspend_states[pm_state];
|
||||
int error = 0;
|
||||
int error;
|
||||
|
||||
error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (sleep_states[acpi_state]) {
|
||||
acpi_target_sleep_state = acpi_state;
|
||||
acpi_sleep_tts_switch(acpi_target_sleep_state);
|
||||
} else {
|
||||
printk(KERN_ERR "ACPI does not support this state: %d\n",
|
||||
pm_state);
|
||||
error = -ENOSYS;
|
||||
if (!sleep_states[acpi_state]) {
|
||||
pr_err("ACPI does not support sleep state S%u\n", acpi_state);
|
||||
return -ENOSYS;
|
||||
}
|
||||
return error;
|
||||
|
||||
acpi_pm_start(acpi_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -631,10 +640,8 @@ static int acpi_hibernation_begin(void)
|
|||
int error;
|
||||
|
||||
error = nvs_nosave ? 0 : suspend_nvs_alloc();
|
||||
if (!error) {
|
||||
acpi_target_sleep_state = ACPI_STATE_S4;
|
||||
acpi_sleep_tts_switch(acpi_target_sleep_state);
|
||||
}
|
||||
if (!error)
|
||||
acpi_pm_start(ACPI_STATE_S4);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -713,8 +720,10 @@ static int acpi_hibernation_begin_old(void)
|
|||
if (!error) {
|
||||
if (!nvs_nosave)
|
||||
error = suspend_nvs_alloc();
|
||||
if (!error)
|
||||
if (!error) {
|
||||
acpi_target_sleep_state = ACPI_STATE_S4;
|
||||
acpi_scan_lock_acquire();
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
|
||||
struct acpiphp_context;
|
||||
struct acpiphp_bridge;
|
||||
struct acpiphp_slot;
|
||||
|
||||
|
@ -59,6 +60,7 @@ struct slot {
|
|||
struct hotplug_slot *hotplug_slot;
|
||||
struct acpiphp_slot *acpi_slot;
|
||||
struct hotplug_slot_info info;
|
||||
unsigned int sun; /* ACPI _SUN (Slot User Number) value */
|
||||
};
|
||||
|
||||
static inline const char *slot_name(struct slot *slot)
|
||||
|
@ -75,15 +77,11 @@ struct acpiphp_bridge {
|
|||
struct list_head list;
|
||||
struct list_head slots;
|
||||
struct kref ref;
|
||||
acpi_handle handle;
|
||||
|
||||
/* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
|
||||
struct acpiphp_func *func;
|
||||
struct acpiphp_context *context;
|
||||
|
||||
int nr_slots;
|
||||
|
||||
u32 flags;
|
||||
|
||||
/* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */
|
||||
struct pci_bus *pci_bus;
|
||||
|
||||
|
@ -99,15 +97,13 @@ struct acpiphp_bridge {
|
|||
*/
|
||||
struct acpiphp_slot {
|
||||
struct list_head node;
|
||||
struct acpiphp_bridge *bridge; /* parent */
|
||||
struct pci_bus *bus;
|
||||
struct list_head funcs; /* one slot may have different
|
||||
objects (i.e. for each function) */
|
||||
struct slot *slot;
|
||||
struct mutex crit_sect;
|
||||
|
||||
u8 device; /* pci device# */
|
||||
|
||||
unsigned long long sun; /* ACPI _SUN (slot unique number) */
|
||||
u32 flags; /* see below */
|
||||
};
|
||||
|
||||
|
@ -119,15 +115,32 @@ struct acpiphp_slot {
|
|||
* typically 8 objects per slot (i.e. for each PCI function)
|
||||
*/
|
||||
struct acpiphp_func {
|
||||
struct acpiphp_slot *slot; /* parent */
|
||||
struct acpiphp_bridge *parent;
|
||||
struct acpiphp_slot *slot;
|
||||
|
||||
struct list_head sibling;
|
||||
acpi_handle handle;
|
||||
|
||||
u8 function; /* pci function# */
|
||||
u32 flags; /* see below */
|
||||
};
|
||||
|
||||
struct acpiphp_context {
|
||||
acpi_handle handle;
|
||||
struct acpiphp_func func;
|
||||
struct acpiphp_bridge *bridge;
|
||||
unsigned int refcount;
|
||||
};
|
||||
|
||||
static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
|
||||
{
|
||||
return container_of(func, struct acpiphp_context, func);
|
||||
}
|
||||
|
||||
static inline acpi_handle func_to_handle(struct acpiphp_func *func)
|
||||
{
|
||||
return func_to_context(func)->handle;
|
||||
}
|
||||
|
||||
/*
|
||||
* struct acpiphp_attention_info - device specific attention registration
|
||||
*
|
||||
|
@ -141,45 +154,32 @@ struct acpiphp_attention_info
|
|||
struct module *owner;
|
||||
};
|
||||
|
||||
/* PCI bus bridge HID */
|
||||
#define ACPI_PCI_HOST_HID "PNP0A03"
|
||||
|
||||
/* ACPI _STA method value (ignore bit 4; battery present) */
|
||||
#define ACPI_STA_ALL (0x0000000f)
|
||||
|
||||
/* bridge flags */
|
||||
#define BRIDGE_HAS_EJ0 (0x00000001)
|
||||
|
||||
/* slot flags */
|
||||
|
||||
#define SLOT_POWEREDON (0x00000001)
|
||||
#define SLOT_ENABLED (0x00000002)
|
||||
#define SLOT_MULTIFUNCTION (0x00000004)
|
||||
#define SLOT_ENABLED (0x00000001)
|
||||
|
||||
/* function flags */
|
||||
|
||||
#define FUNC_HAS_STA (0x00000001)
|
||||
#define FUNC_HAS_EJ0 (0x00000002)
|
||||
#define FUNC_HAS_PS0 (0x00000010)
|
||||
#define FUNC_HAS_PS1 (0x00000020)
|
||||
#define FUNC_HAS_PS2 (0x00000040)
|
||||
#define FUNC_HAS_PS3 (0x00000080)
|
||||
#define FUNC_HAS_DCK (0x00000100)
|
||||
#define FUNC_HAS_DCK (0x00000004)
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
/* acpiphp_core.c */
|
||||
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);
|
||||
int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot, unsigned int sun);
|
||||
void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
|
||||
|
||||
/* acpiphp_glue.c */
|
||||
typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
|
||||
|
||||
int acpiphp_enable_slot(struct acpiphp_slot *slot);
|
||||
int acpiphp_disable_slot(struct acpiphp_slot *slot);
|
||||
int acpiphp_eject_slot(struct acpiphp_slot *slot);
|
||||
int acpiphp_disable_and_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);
|
||||
|
|
|
@ -155,15 +155,11 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
|
|||
static int disable_slot(struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
struct slot *slot = hotplug_slot->private;
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
|
||||
|
||||
/* disable the specified slot */
|
||||
retval = acpiphp_disable_slot(slot->acpi_slot);
|
||||
if (!retval)
|
||||
retval = acpiphp_eject_slot(slot->acpi_slot);
|
||||
return retval;
|
||||
return acpiphp_disable_and_eject_slot(slot->acpi_slot);
|
||||
}
|
||||
|
||||
|
||||
|
@ -290,7 +286,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
|
|||
}
|
||||
|
||||
/* callback routine to initialize 'struct slot' for each slot */
|
||||
int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
|
||||
int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot,
|
||||
unsigned int sun)
|
||||
{
|
||||
struct slot *slot;
|
||||
int retval = -ENOMEM;
|
||||
|
@ -317,12 +314,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
|
|||
slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
|
||||
|
||||
acpiphp_slot->slot = slot;
|
||||
snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun);
|
||||
slot->sun = sun;
|
||||
snprintf(name, SLOT_NAME_SIZE, "%u", sun);
|
||||
|
||||
retval = pci_hp_register(slot->hotplug_slot,
|
||||
acpiphp_slot->bridge->pci_bus,
|
||||
acpiphp_slot->device,
|
||||
name);
|
||||
retval = pci_hp_register(slot->hotplug_slot, acpiphp_slot->bus,
|
||||
acpiphp_slot->device, name);
|
||||
if (retval == -EBUSY)
|
||||
goto error_hpslot;
|
||||
if (retval) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -66,7 +66,7 @@ do { \
|
|||
#define IBM_HARDWARE_ID1 "IBM37D0"
|
||||
#define IBM_HARDWARE_ID2 "IBM37D4"
|
||||
|
||||
#define hpslot_to_sun(A) (((struct slot *)((A)->private))->acpi_slot->sun)
|
||||
#define hpslot_to_sun(A) (((struct slot *)((A)->private))->sun)
|
||||
|
||||
/* union apci_descriptor - allows access to the
|
||||
* various device descriptors that are embedded in the
|
||||
|
|
|
@ -210,7 +210,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
|||
}
|
||||
|
||||
if (!error)
|
||||
dev_info(&dev->dev, "power state changed by ACPI to %s\n",
|
||||
dev_dbg(&dev->dev, "power state changed by ACPI to %s\n",
|
||||
acpi_power_state_string(state_conv[state]));
|
||||
|
||||
return error;
|
||||
|
@ -290,24 +290,16 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {
|
|||
|
||||
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)
|
||||
if (acpi_pci_disabled || !bus->bridge)
|
||||
return;
|
||||
|
||||
acpi_pci_slot_enumerate(bus, handle);
|
||||
acpiphp_enumerate_slots(bus, handle);
|
||||
acpi_pci_slot_enumerate(bus);
|
||||
acpiphp_enumerate_slots(bus);
|
||||
}
|
||||
|
||||
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)
|
||||
if (acpi_pci_disabled || !bus->bridge)
|
||||
return;
|
||||
|
||||
acpiphp_remove_slots(bus);
|
||||
|
|
|
@ -47,24 +47,22 @@ void acpi_pci_remove_bus(struct pci_bus *bus);
|
|||
|
||||
#ifdef CONFIG_ACPI_PCI_SLOT
|
||||
void acpi_pci_slot_init(void);
|
||||
void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle);
|
||||
void acpi_pci_slot_enumerate(struct pci_bus *bus);
|
||||
void acpi_pci_slot_remove(struct pci_bus *bus);
|
||||
#else
|
||||
static inline void acpi_pci_slot_init(void) { }
|
||||
static inline void acpi_pci_slot_enumerate(struct pci_bus *bus,
|
||||
acpi_handle handle) { }
|
||||
static inline void acpi_pci_slot_enumerate(struct pci_bus *bus) { }
|
||||
static inline void acpi_pci_slot_remove(struct pci_bus *bus) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_PCI_ACPI
|
||||
void acpiphp_init(void);
|
||||
void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle);
|
||||
void acpiphp_enumerate_slots(struct pci_bus *bus);
|
||||
void acpiphp_remove_slots(struct pci_bus *bus);
|
||||
void acpiphp_check_host_bridge(acpi_handle handle);
|
||||
#else
|
||||
static inline void acpiphp_init(void) { }
|
||||
static inline void acpiphp_enumerate_slots(struct pci_bus *bus,
|
||||
acpi_handle handle) { }
|
||||
static inline void acpiphp_enumerate_slots(struct pci_bus *bus) { }
|
||||
static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
|
||||
static inline void acpiphp_check_host_bridge(acpi_handle handle) { }
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue