Merge branch 'acpi-pci-hotplug'
* acpi-pci-hotplug: ACPI / hotplug / PCI: Avoid parent bus rescans on spurious device checks ACPI / hotplug / PCI: Use _OST to notify firmware about notify status ACPI / hotplug / PCI: Avoid doing too much for spurious notifies ACPI / hotplug / PCI: Don't trim devices before scanning the namespace
This commit is contained in:
commit
08e97ff277
@ -487,7 +487,6 @@ static void acpiphp_bus_add(acpi_handle handle)
|
|||||||
{
|
{
|
||||||
struct acpi_device *adev = NULL;
|
struct acpi_device *adev = NULL;
|
||||||
|
|
||||||
acpiphp_bus_trim(handle);
|
|
||||||
acpi_bus_scan(handle);
|
acpi_bus_scan(handle);
|
||||||
acpi_bus_get_device(handle, &adev);
|
acpi_bus_get_device(handle, &adev);
|
||||||
if (adev)
|
if (adev)
|
||||||
@ -529,6 +528,16 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int acpiphp_rescan_slot(struct acpiphp_slot *slot)
|
||||||
|
{
|
||||||
|
struct acpiphp_func *func;
|
||||||
|
|
||||||
|
list_for_each_entry(func, &slot->funcs, sibling)
|
||||||
|
acpiphp_bus_add(func_to_handle(func));
|
||||||
|
|
||||||
|
return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enable_slot - enable, configure a slot
|
* enable_slot - enable, configure a slot
|
||||||
* @slot: slot to be enabled
|
* @slot: slot to be enabled
|
||||||
@ -543,12 +552,9 @@ static void __ref enable_slot(struct acpiphp_slot *slot)
|
|||||||
struct acpiphp_func *func;
|
struct acpiphp_func *func;
|
||||||
int max, pass;
|
int max, pass;
|
||||||
LIST_HEAD(add_list);
|
LIST_HEAD(add_list);
|
||||||
|
int nr_found;
|
||||||
|
|
||||||
list_for_each_entry(func, &slot->funcs, sibling)
|
nr_found = acpiphp_rescan_slot(slot);
|
||||||
acpiphp_bus_add(func_to_handle(func));
|
|
||||||
|
|
||||||
pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
|
|
||||||
|
|
||||||
max = acpiphp_max_busnr(bus);
|
max = acpiphp_max_busnr(bus);
|
||||||
for (pass = 0; pass < 2; pass++) {
|
for (pass = 0; pass < 2; pass++) {
|
||||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||||
@ -567,8 +573,11 @@ static void __ref enable_slot(struct acpiphp_slot *slot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__pci_bus_assign_resources(bus, &add_list, NULL);
|
__pci_bus_assign_resources(bus, &add_list, NULL);
|
||||||
|
/* Nothing more to do here if there are no new devices on this bus. */
|
||||||
|
if (!nr_found && (slot->flags & SLOT_ENABLED))
|
||||||
|
return;
|
||||||
|
|
||||||
acpiphp_sanitize_bus(bus);
|
acpiphp_sanitize_bus(bus);
|
||||||
acpiphp_set_hpp_values(bus);
|
acpiphp_set_hpp_values(bus);
|
||||||
acpiphp_set_acpi_region(slot);
|
acpiphp_set_acpi_region(slot);
|
||||||
@ -837,11 +846,22 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
|
|||||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||||
/* device check */
|
/* device check */
|
||||||
dbg("%s: Device check notify on %s\n", __func__, objname);
|
dbg("%s: Device check notify on %s\n", __func__, objname);
|
||||||
if (bridge)
|
if (bridge) {
|
||||||
acpiphp_check_bridge(bridge);
|
acpiphp_check_bridge(bridge);
|
||||||
else
|
} else {
|
||||||
acpiphp_check_bridge(func->parent);
|
struct acpiphp_slot *slot = func->slot;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if anything has changed in the slot and rescan
|
||||||
|
* from the parent if that's the case.
|
||||||
|
*/
|
||||||
|
mutex_lock(&slot->crit_sect);
|
||||||
|
ret = acpiphp_rescan_slot(slot);
|
||||||
|
mutex_unlock(&slot->crit_sect);
|
||||||
|
if (ret)
|
||||||
|
acpiphp_check_bridge(func->parent);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||||
@ -867,6 +887,8 @@ static void hotplug_event_work(struct work_struct *work)
|
|||||||
hotplug_event(hp_work->handle, hp_work->type, context);
|
hotplug_event(hp_work->handle, hp_work->type, context);
|
||||||
|
|
||||||
acpi_scan_lock_release();
|
acpi_scan_lock_release();
|
||||||
|
acpi_evaluate_hotplug_ost(hp_work->handle, hp_work->type,
|
||||||
|
ACPI_OST_SC_SUCCESS, NULL);
|
||||||
kfree(hp_work); /* allocated in handle_hotplug_event() */
|
kfree(hp_work); /* allocated in handle_hotplug_event() */
|
||||||
put_bridge(context->func.parent);
|
put_bridge(context->func.parent);
|
||||||
}
|
}
|
||||||
@ -882,11 +904,15 @@ static void hotplug_event_work(struct work_struct *work)
|
|||||||
static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
|
static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
|
||||||
{
|
{
|
||||||
struct acpiphp_context *context;
|
struct acpiphp_context *context;
|
||||||
|
u32 ost_code = ACPI_OST_SC_SUCCESS;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ACPI_NOTIFY_BUS_CHECK:
|
case ACPI_NOTIFY_BUS_CHECK:
|
||||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||||
|
break;
|
||||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||||
|
ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS;
|
||||||
|
acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACPI_NOTIFY_DEVICE_WAKE:
|
case ACPI_NOTIFY_DEVICE_WAKE:
|
||||||
@ -895,20 +921,21 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
|
|||||||
case ACPI_NOTIFY_FREQUENCY_MISMATCH:
|
case ACPI_NOTIFY_FREQUENCY_MISMATCH:
|
||||||
acpi_handle_err(handle, "Device cannot be configured due "
|
acpi_handle_err(handle, "Device cannot be configured due "
|
||||||
"to a frequency mismatch\n");
|
"to a frequency mismatch\n");
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
case ACPI_NOTIFY_BUS_MODE_MISMATCH:
|
case ACPI_NOTIFY_BUS_MODE_MISMATCH:
|
||||||
acpi_handle_err(handle, "Device cannot be configured due "
|
acpi_handle_err(handle, "Device cannot be configured due "
|
||||||
"to a bus mode mismatch\n");
|
"to a bus mode mismatch\n");
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
case ACPI_NOTIFY_POWER_FAULT:
|
case ACPI_NOTIFY_POWER_FAULT:
|
||||||
acpi_handle_err(handle, "Device has suffered a power fault\n");
|
acpi_handle_err(handle, "Device has suffered a power fault\n");
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
|
acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
|
||||||
return;
|
ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&acpiphp_context_lock);
|
mutex_lock(&acpiphp_context_lock);
|
||||||
@ -917,8 +944,14 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
|
|||||||
get_bridge(context->func.parent);
|
get_bridge(context->func.parent);
|
||||||
acpiphp_put_context(context);
|
acpiphp_put_context(context);
|
||||||
alloc_acpi_hp_work(handle, type, context, hotplug_event_work);
|
alloc_acpi_hp_work(handle, type, context, hotplug_event_work);
|
||||||
|
mutex_unlock(&acpiphp_context_lock);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
mutex_unlock(&acpiphp_context_lock);
|
mutex_unlock(&acpiphp_context_lock);
|
||||||
|
ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
|
||||||
|
|
||||||
|
out:
|
||||||
|
acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user