mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 17:08:10 +00:00
ACPI: Add post_eject to struct acpi_scan_handler for cpu hotplug
struct acpi_scan_handler has a detach callback that is used to remove a driver when a bus is changed. When interacting with an eject-request, the detach callback is called before _EJ0. This means the ACPI processor driver can't use _STA to determine if a CPU has been made not-present, or some of the other _STA bits have been changed. acpi_processor_remove() needs to know the value of _STA after _EJ0 has been called. Add a post_eject callback to struct acpi_scan_handler. This is called after acpi_scan_hot_remove() has successfully called _EJ0. Because acpi_scan_check_and_detach() also clears the handler pointer, it needs to be told if the caller will go on to call acpi_bus_post_eject(), so that acpi_device_clear_enumerated() and clearing the handler pointer can be deferred. An extra flag is added to flags field introduced in the previous patch to achieve this. Signed-off-by: James Morse <james.morse@arm.com> Reviewed-by: Gavin Shan <gshan@redhat.com> Tested-by: Miguel Luis <miguel.luis@oracle.com> Tested-by: Vishnu Pajjuri <vishnu@os.amperecomputing.com> Tested-by: Jianyong Wu <jianyong.wu@arm.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Hanjun Guo <guohanjun@huawei.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Link: https://lore.kernel.org/r/20240529133446.28446-11-Jonathan.Cameron@huawei.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
parent
1859a671bd
commit
3b9d0a78ae
3 changed files with 30 additions and 5 deletions
|
@ -475,7 +475,7 @@ static int acpi_processor_add(struct acpi_device *device,
|
|||
|
||||
#ifdef CONFIG_ACPI_HOTPLUG_CPU
|
||||
/* Removal */
|
||||
static void acpi_processor_remove(struct acpi_device *device)
|
||||
static void acpi_processor_post_eject(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_processor *pr;
|
||||
|
||||
|
@ -643,7 +643,7 @@ static struct acpi_scan_handler processor_handler = {
|
|||
.ids = processor_device_ids,
|
||||
.attach = acpi_processor_add,
|
||||
#ifdef CONFIG_ACPI_HOTPLUG_CPU
|
||||
.detach = acpi_processor_remove,
|
||||
.post_eject = acpi_processor_post_eject,
|
||||
#endif
|
||||
.hotplug = {
|
||||
.enabled = true,
|
||||
|
|
|
@ -244,6 +244,7 @@ static int acpi_scan_try_to_offline(struct acpi_device *device)
|
|||
}
|
||||
|
||||
#define ACPI_SCAN_CHECK_FLAG_STATUS BIT(0)
|
||||
#define ACPI_SCAN_CHECK_FLAG_EJECT BIT(1)
|
||||
|
||||
static int acpi_scan_check_and_detach(struct acpi_device *adev, void *p)
|
||||
{
|
||||
|
@ -272,8 +273,6 @@ static int acpi_scan_check_and_detach(struct acpi_device *adev, void *p)
|
|||
if (handler) {
|
||||
if (handler->detach)
|
||||
handler->detach(adev);
|
||||
|
||||
adev->handler = NULL;
|
||||
} else {
|
||||
device_release_driver(&adev->dev);
|
||||
}
|
||||
|
@ -283,6 +282,28 @@ static int acpi_scan_check_and_detach(struct acpi_device *adev, void *p)
|
|||
*/
|
||||
acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
|
||||
adev->flags.initialized = false;
|
||||
|
||||
/* For eject this is deferred to acpi_bus_post_eject() */
|
||||
if (!(flags & ACPI_SCAN_CHECK_FLAG_EJECT)) {
|
||||
adev->handler = NULL;
|
||||
acpi_device_clear_enumerated(adev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_bus_post_eject(struct acpi_device *adev, void *not_used)
|
||||
{
|
||||
struct acpi_scan_handler *handler = adev->handler;
|
||||
|
||||
acpi_dev_for_each_child_reverse(adev, acpi_bus_post_eject, NULL);
|
||||
|
||||
if (handler) {
|
||||
if (handler->post_eject)
|
||||
handler->post_eject(adev);
|
||||
|
||||
adev->handler = NULL;
|
||||
}
|
||||
|
||||
acpi_device_clear_enumerated(adev);
|
||||
|
||||
return 0;
|
||||
|
@ -300,6 +321,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
|
|||
acpi_handle handle = device->handle;
|
||||
unsigned long long sta;
|
||||
acpi_status status;
|
||||
uintptr_t flags = ACPI_SCAN_CHECK_FLAG_EJECT;
|
||||
|
||||
if (device->handler && device->handler->hotplug.demand_offline) {
|
||||
if (!acpi_scan_is_offline(device, true))
|
||||
|
@ -312,7 +334,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
|
|||
|
||||
acpi_handle_debug(handle, "Ejecting\n");
|
||||
|
||||
acpi_bus_trim(device);
|
||||
acpi_scan_check_and_detach(device, (void *)flags);
|
||||
|
||||
acpi_evaluate_lck(handle, 0);
|
||||
/*
|
||||
|
@ -335,6 +357,8 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
|
|||
} else if (sta & ACPI_STA_DEVICE_ENABLED) {
|
||||
acpi_handle_warn(handle,
|
||||
"Eject incomplete - status 0x%llx\n", sta);
|
||||
} else {
|
||||
acpi_bus_post_eject(device, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -134,6 +134,7 @@ struct acpi_scan_handler {
|
|||
bool (*match)(const char *idstr, const struct acpi_device_id **matchid);
|
||||
int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
|
||||
void (*detach)(struct acpi_device *dev);
|
||||
void (*post_eject)(struct acpi_device *dev);
|
||||
void (*bind)(struct device *phys_dev);
|
||||
void (*unbind)(struct device *phys_dev);
|
||||
struct acpi_hotplug_profile hotplug;
|
||||
|
|
Loading…
Reference in a new issue