From f22ff5523af8b365167cb79189f8b91470d57c8c Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:34 +0800 Subject: ACPI / dock: avoid initializing acpi_dock_notifier_list multiple times Function dock_add() will be called multiple times if there are multiple dock stations, which causes acpi_dock_notifier_list to be initialized multiple times. To avoid that, move the initialization of acpi_dock_notifier_list from dock_add() to acpi_dock_init(). [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 8265607..c36de86 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -1007,7 +1007,6 @@ static int __init dock_add(acpi_handle handle) mutex_init(&dock_station->hp_lock); spin_lock_init(&dock_station->dd_lock); INIT_LIST_HEAD(&dock_station->sibling); - ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); INIT_LIST_HEAD(&dock_station->dependent_devices); /* we want the dock device to send uevents */ @@ -1078,6 +1077,7 @@ void __init acpi_dock_init(void) return; } + ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); register_acpi_bus_notifier(&dock_acpi_notifier); pr_info(PREFIX "%s: %d docks/bays found\n", ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); -- cgit v0.10.2 From ed633e709fa633c6bc24f4d6ecb55ad0c14fd335 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:35 +0800 Subject: ACPI / dock: drop redundant spin lock in dock station object All dock station objects are created during initialization and don't change at runtime, so drop the redundant spin lock from struct dock_station. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index c36de86..750f958 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -63,7 +63,6 @@ struct dock_station { acpi_handle handle; unsigned long last_dock_time; u32 flags; - spinlock_t dd_lock; struct mutex hp_lock; struct list_head dependent_devices; @@ -112,10 +111,7 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) dd->handle = handle; INIT_LIST_HEAD(&dd->list); - - spin_lock(&ds->dd_lock); list_add_tail(&dd->list, &ds->dependent_devices); - spin_unlock(&ds->dd_lock); return 0; } @@ -220,14 +216,10 @@ find_dock_dependent_device(struct dock_station *ds, acpi_handle handle) { struct dock_dependent_device *dd; - spin_lock(&ds->dd_lock); - list_for_each_entry(dd, &ds->dependent_devices, list) { - if (handle == dd->handle) { - spin_unlock(&ds->dd_lock); + list_for_each_entry(dd, &ds->dependent_devices, list) + if (handle == dd->handle) return dd; - } - } - spin_unlock(&ds->dd_lock); + return NULL; } @@ -1005,7 +997,6 @@ static int __init dock_add(acpi_handle handle) dock_station->last_dock_time = jiffies - HZ; mutex_init(&dock_station->hp_lock); - spin_lock_init(&dock_station->dd_lock); INIT_LIST_HEAD(&dock_station->sibling); INIT_LIST_HEAD(&dock_station->dependent_devices); -- cgit v0.10.2 From d423c083ff3b3adc1e42a2f2c03c8430a6e0220f Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:36 +0800 Subject: ACPI / dock: mark initialization functions with __init Mark all initialization functions with __init to reduce runtime memory consumption. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 750f958..f3ec722 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -100,7 +100,7 @@ struct dock_dependent_device { * * Add the dependent device to the dock's dependent device list. */ -static int +static int __init add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) { struct dock_dependent_device *dd; @@ -244,7 +244,7 @@ static int is_dock(acpi_handle handle) return 1; } -static int is_ejectable(acpi_handle handle) +static int __init is_ejectable(acpi_handle handle) { acpi_status status; acpi_handle tmp; @@ -255,7 +255,7 @@ static int is_ejectable(acpi_handle handle) return 1; } -static int is_ata(acpi_handle handle) +static int __init is_ata(acpi_handle handle) { acpi_handle tmp; @@ -268,7 +268,7 @@ static int is_ata(acpi_handle handle) return 0; } -static int is_battery(acpi_handle handle) +static int __init is_battery(acpi_handle handle) { struct acpi_device_info *info; int ret = 1; @@ -284,7 +284,7 @@ static int is_battery(acpi_handle handle) return ret; } -static int is_ejectable_bay(acpi_handle handle) +static int __init is_ejectable_bay(acpi_handle handle) { acpi_handle phandle; @@ -848,7 +848,7 @@ static struct notifier_block dock_acpi_notifier = { * check to see if an object has an _EJD method. If it does, then it * will see if it is dependent on the dock station. */ -static acpi_status +static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; -- cgit v0.10.2 From 472d963befe28b8614ea2789757b27536c8d79eb Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:37 +0800 Subject: ACPI / dock: simplify dock_create_acpi_device() The return value of dock_create_acpi_device() is not used at all, so change its signature to return void and simplify the implementation of it. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index f3ec722..1bdb1fa 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -351,10 +351,8 @@ static int dock_present(struct dock_station *ds) * handle if one does not exist already. This should cause * acpi to scan for drivers for the given devices, and call * matching driver's add routine. - * - * Returns a pointer to the acpi_device corresponding to the handle. */ -static struct acpi_device * dock_create_acpi_device(acpi_handle handle) +static void dock_create_acpi_device(acpi_handle handle) { struct acpi_device *device; int ret; @@ -367,10 +365,7 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) ret = acpi_bus_scan(handle); if (ret) pr_debug("error adding bus, %x\n", -ret); - - acpi_bus_get_device(handle, &device); } - return device; } /** -- cgit v0.10.2 From 952c63e9512b63220886105cfc791507046fa39a Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:38 +0800 Subject: ACPI: introduce helper function acpi_has_method() Introduce helper function acpi_has_method() and use it in a number of places to simplify code. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 082b4dd..a762716 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -548,12 +548,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) static int acpi_battery_init_alarm(struct acpi_battery *battery) { - acpi_status status = AE_OK; - acpi_handle handle = NULL; - /* See if alarms are supported, and if so, set default */ - status = acpi_get_handle(battery->device->handle, "_BTP", &handle); - if (ACPI_FAILURE(status)) { + if (!acpi_has_method(battery->device->handle, "_BTP")) { clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags); return 0; } @@ -1066,7 +1062,7 @@ static int acpi_battery_add(struct acpi_device *device) { int result = 0; struct acpi_battery *battery = NULL; - acpi_handle handle; + if (!device) return -EINVAL; battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); @@ -1078,8 +1074,7 @@ static int acpi_battery_add(struct acpi_device *device) device->driver_data = battery; mutex_init(&battery->lock); mutex_init(&battery->sysfs_lock); - if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, - "_BIX", &handle))) + if (acpi_has_method(battery->device->handle, "_BIX")) set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); result = acpi_battery_update(battery); if (result) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 80403c1..84bf06c 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1049,10 +1049,8 @@ int __init acpi_ec_ecdt_probe(void) * which needs it, has fake EC._INI method, so use it as flag. * Keep boot_ec struct as it will be needed soon. */ - acpi_handle dummy; if (!dmi_name_in_vendors("ASUS") || - ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", - &dummy))) + !acpi_has_method(boot_ec->handle, "_INI")) return -ENODEV; } install: diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 1e9732d..51d7948 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -164,17 +164,12 @@ static void acpi_processor_ppc_ost(acpi_handle handle, int status) {.type = ACPI_TYPE_INTEGER,}, }; struct acpi_object_list arg_list = {2, params}; - acpi_handle temp; - params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE; - params[1].integer.value = status; - - /* when there is no _OST , skip it */ - if (ACPI_FAILURE(acpi_get_handle(handle, "_OST", &temp))) - return; - - acpi_evaluate_object(handle, "_OST", &arg_list, NULL); - return; + if (acpi_has_method(handle, "_OST")) { + params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE; + params[1].integer.value = status; + acpi_evaluate_object(handle, "_OST", &arg_list, NULL); + } } int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag) @@ -468,14 +463,11 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) int acpi_processor_get_performance_info(struct acpi_processor *pr) { int result = 0; - acpi_status status = AE_OK; - acpi_handle handle = NULL; if (!pr || !pr->performance || !pr->handle) return -EINVAL; - status = acpi_get_handle(pr->handle, "_PCT", &handle); - if (ACPI_FAILURE(status)) { + if (!acpi_has_method(pr->handle, "_PCT")) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI-based processor performance control unavailable\n")); return -ENODEV; @@ -501,7 +493,7 @@ int acpi_processor_get_performance_info(struct acpi_processor *pr) */ update_bios: #ifdef CONFIG_X86 - if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){ + if (acpi_has_method(pr->handle, "_PPC")) { if(boot_cpu_has(X86_FEATURE_EST)) printk(KERN_WARNING FW_BUG "BIOS needs update for CPU " "frequency support\n"); diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 3322b47..b7201fc 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -505,14 +505,12 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, void *preproc_data) { struct res_proc_context c; - acpi_handle not_used; acpi_status status; if (!adev || !adev->handle || !list_empty(list)) return -EINVAL; - status = acpi_get_handle(adev->handle, METHOD_NAME__CRS, ¬_used); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(adev->handle, METHOD_NAME__CRS)) return 0; c.list = list; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 1098557..ada0b4c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -193,7 +193,6 @@ static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl, static int acpi_scan_hot_remove(struct acpi_device *device) { acpi_handle handle = device->handle; - acpi_handle not_used; struct acpi_object_list arg_list; union acpi_object arg; struct device *errdev; @@ -258,7 +257,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device) put_device(&device->dev); device = NULL; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", ¬_used))) { + if (acpi_has_method(handle, "_LCK")) { arg_list.count = 1; arg_list.pointer = &arg; arg.type = ACPI_TYPE_INTEGER; @@ -652,7 +651,6 @@ static int acpi_device_setup_files(struct acpi_device *dev) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; acpi_status status; - acpi_handle temp; unsigned long long sun; int result = 0; @@ -678,8 +676,7 @@ static int acpi_device_setup_files(struct acpi_device *dev) /* * If device has _STR, 'description' file is created */ - status = acpi_get_handle(dev->handle, "_STR", &temp); - if (ACPI_SUCCESS(status)) { + if (acpi_has_method(dev->handle, "_STR")) { status = acpi_evaluate_object(dev->handle, "_STR", NULL, &buffer); if (ACPI_FAILURE(status)) @@ -709,8 +706,7 @@ static int acpi_device_setup_files(struct acpi_device *dev) * If device has _EJ0, 'eject' file is created that is used to trigger * hot-removal function from userland. */ - status = acpi_get_handle(dev->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) { + if (acpi_has_method(dev->handle, "_EJ0")) { result = device_create_file(&dev->dev, &dev_attr_eject); if (result) return result; @@ -732,9 +728,6 @@ end: static void acpi_device_remove_files(struct acpi_device *dev) { - acpi_status status; - acpi_handle temp; - if (dev->flags.power_manageable) { device_remove_file(&dev->dev, &dev_attr_power_state); if (dev->power.flags.power_resources) @@ -745,20 +738,17 @@ static void acpi_device_remove_files(struct acpi_device *dev) /* * If device has _STR, remove 'description' file */ - status = acpi_get_handle(dev->handle, "_STR", &temp); - if (ACPI_SUCCESS(status)) { + if (acpi_has_method(dev->handle, "_STR")) { kfree(dev->pnp.str_obj); device_remove_file(&dev->dev, &dev_attr_description); } /* * If device has _EJ0, remove 'eject' file. */ - status = acpi_get_handle(dev->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(dev->handle, "_EJ0")) device_remove_file(&dev->dev, &dev_attr_eject); - status = acpi_get_handle(dev->handle, "_SUN", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(dev->handle, "_SUN")) device_remove_file(&dev->dev, &dev_attr_sun); if (dev->pnp.unique_id) @@ -1334,13 +1324,10 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) { - acpi_handle temp; - acpi_status status = 0; int err; /* Presence of _PRW indicates wake capable */ - status = acpi_get_handle(device->handle, "_PRW", &temp); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(device->handle, "_PRW")) return; err = acpi_bus_extract_wakeup_device_power_package(device->handle, @@ -1370,7 +1357,6 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state) struct acpi_device_power_state *ps = &device->power.states[state]; char pathname[5] = { '_', 'P', 'R', '0' + state, '\0' }; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - acpi_handle handle; acpi_status status; INIT_LIST_HEAD(&ps->resources); @@ -1393,8 +1379,7 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state) /* Evaluate "_PSx" to see if we can do explicit sets */ pathname[2] = 'S'; - status = acpi_get_handle(device->handle, pathname, &handle); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, pathname)) ps->flags.explicit_set = 1; /* @@ -1413,28 +1398,21 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state) static void acpi_bus_get_power_flags(struct acpi_device *device) { - acpi_status status; - acpi_handle handle; u32 i; /* Presence of _PS0|_PR0 indicates 'power manageable' */ - status = acpi_get_handle(device->handle, "_PS0", &handle); - if (ACPI_FAILURE(status)) { - status = acpi_get_handle(device->handle, "_PR0", &handle); - if (ACPI_FAILURE(status)) - return; - } + if (!acpi_has_method(device->handle, "_PS0") && + !acpi_has_method(device->handle, "_PR0")) + return; device->flags.power_manageable = 1; /* * Power Management Flags */ - status = acpi_get_handle(device->handle, "_PSC", &handle); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_PSC")) device->power.flags.explicit_get = 1; - status = acpi_get_handle(device->handle, "_IRC", &handle); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_IRC")) device->power.flags.inrush_current = 1; /* @@ -1468,28 +1446,18 @@ static void acpi_bus_get_power_flags(struct acpi_device *device) static void acpi_bus_get_flags(struct acpi_device *device) { - acpi_status status = AE_OK; - acpi_handle temp = NULL; - /* Presence of _STA indicates 'dynamic_status' */ - status = acpi_get_handle(device->handle, "_STA", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_STA")) device->flags.dynamic_status = 1; /* Presence of _RMV indicates 'removable' */ - status = acpi_get_handle(device->handle, "_RMV", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_RMV")) device->flags.removable = 1; /* Presence of _EJD|_EJ0 indicates 'ejectable' */ - status = acpi_get_handle(device->handle, "_EJD", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_EJD") || + acpi_has_method(device->handle, "_EJ0")) device->flags.ejectable = 1; - else { - status = acpi_get_handle(device->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) - device->flags.ejectable = 1; - } } static void acpi_device_get_busid(struct acpi_device *device) @@ -1538,27 +1506,24 @@ static void acpi_device_get_busid(struct acpi_device *device) */ static int acpi_bay_match(acpi_handle handle) { - acpi_status status; - acpi_handle tmp; acpi_handle phandle; - status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(handle, "_EJ0")) return -ENODEV; - if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) + if (acpi_has_method(handle, "_GTF") || + acpi_has_method(handle, "_GTM") || + acpi_has_method(handle, "_STM") || + acpi_has_method(handle, "_SDD")) return 0; if (acpi_get_parent(handle, &phandle)) return -ENODEV; - if ((ACPI_SUCCESS(acpi_get_handle(phandle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(phandle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(phandle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(phandle, "_SDD", &tmp)))) + if (acpi_has_method(phandle, "_GTF") || + acpi_has_method(phandle, "_GTM") || + acpi_has_method(phandle, "_STM") || + acpi_has_method(phandle, "_SDD")) return 0; return -ENODEV; @@ -1610,7 +1575,6 @@ static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id) */ static int acpi_ibm_smbus_match(acpi_handle handle) { - acpi_handle h_dummy; struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; int result; @@ -1629,9 +1593,9 @@ static int acpi_ibm_smbus_match(acpi_handle handle) /* Does it have the necessary (but misnamed) methods? */ result = -ENODEV; - if (ACPI_SUCCESS(acpi_get_handle(handle, "SBI", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(handle, "SBR", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(handle, "SBW", &h_dummy))) + if (acpi_has_method(handle, "SBI") && + acpi_has_method(handle, "SBR") && + acpi_has_method(handle, "SBW")) result = 0; out: kfree(path.pointer); @@ -1898,7 +1862,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, struct acpi_device *device = NULL; int type; unsigned long long sta; - acpi_status status; int result; acpi_bus_get_device(handle, &device); @@ -1919,10 +1882,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, if (!(sta & ACPI_STA_DEVICE_PRESENT) && !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { struct acpi_device_wakeup wakeup; - acpi_handle temp; - status = acpi_get_handle(handle, "_PRW", &temp); - if (ACPI_SUCCESS(status)) { + if (acpi_has_method(handle, "_PRW")) { acpi_bus_extract_wakeup_device_power_package(handle, &wakeup); acpi_power_resources_list_free(&wakeup.resources); diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 74437130..b08d973 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -495,3 +495,18 @@ acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...) kfree(buffer.pointer); } EXPORT_SYMBOL(acpi_handle_printk); + +/** + * acpi_has_method: Check whether @handle has a method named @name + * @handle: ACPI device handle + * @name: name of object or method + * + * Check whether @handle has a method named @name. + */ +bool acpi_has_method(acpi_handle handle, char *name) +{ + acpi_handle tmp; + + return ACPI_SUCCESS(acpi_get_handle(handle, name, &tmp)); +} +EXPORT_SYMBOL(acpi_has_method); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 5d7075d..a84533e 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -875,28 +875,21 @@ out: static void acpi_video_device_find_cap(struct acpi_video_device *device) { - acpi_handle h_dummy1; - - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { + if (acpi_has_method(device->dev->handle, "_ADR")) device->cap._ADR = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCL", &h_dummy1))) { + if (acpi_has_method(device->dev->handle, "_BCL")) device->cap._BCL = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) { + if (acpi_has_method(device->dev->handle, "_BCM")) device->cap._BCM = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1))) + if (acpi_has_method(device->dev->handle, "_BQC")) { device->cap._BQC = 1; - else if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCQ", - &h_dummy1))) { + } else if (acpi_has_method(device->dev->handle, "_BCQ")) { printk(KERN_WARNING FW_BUG "_BCQ is used instead of _BQC\n"); device->cap._BCQ = 1; } - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { + if (acpi_has_method(device->dev->handle, "_DDC")) device->cap._DDC = 1; - } if (acpi_video_backlight_support()) { struct backlight_properties props; @@ -984,26 +977,18 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) static void acpi_video_bus_find_cap(struct acpi_video_bus *video) { - acpi_handle h_dummy1; - - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_DOS")) video->cap._DOS = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOD", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_DOD")) video->cap._DOD = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_ROM", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_ROM")) video->cap._ROM = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_GPD", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_GPD")) video->cap._GPD = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_SPD", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_SPD")) video->cap._SPD = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_VPO", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_VPO")) video->cap._VPO = 1; - } } /* diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index e6bd910..ddefa5f 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -51,14 +51,13 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, void **retyurn_value) { long *cap = context; - acpi_handle h_dummy; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) { + if (acpi_has_method(handle, "_BCM") && + acpi_has_method(handle, "_BCL")) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " "support\n")); *cap |= ACPI_VIDEO_BACKLIGHT; - if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy))) + if (!acpi_has_method(handle, "_BQC")) printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, " "cannot determine initial brightness\n"); /* We have backlight support, no need to scan further */ @@ -77,22 +76,20 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, */ long acpi_is_video_device(acpi_handle handle) { - acpi_handle h_dummy; long video_caps = 0; /* Is this device able to support video switching ? */ - if (ACPI_SUCCESS(acpi_get_handle(handle, "_DOD", &h_dummy)) || - ACPI_SUCCESS(acpi_get_handle(handle, "_DOS", &h_dummy))) + if (acpi_has_method(handle, "_DOD") || acpi_has_method(handle, "_DOS")) video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; /* Is this device able to retrieve a video ROM ? */ - if (ACPI_SUCCESS(acpi_get_handle(handle, "_ROM", &h_dummy))) + if (acpi_has_method(handle, "_ROM")) video_caps |= ACPI_VIDEO_ROM_AVAILABLE; /* Is this device able to configure which video head to be POSTed ? */ - if (ACPI_SUCCESS(acpi_get_handle(handle, "_VPO", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(handle, "_GPD", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(handle, "_SPD", &h_dummy))) + if (acpi_has_method(handle, "_VPO") && + acpi_has_method(handle, "_GPD") && + acpi_has_method(handle, "_SPD")) video_caps |= ACPI_VIDEO_DEVICE_POSTING; /* Only check for backlight functionality if one of the above hit. */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 56e6b68..62b2811 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -56,6 +56,9 @@ acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event, acpi_status acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld); + +bool acpi_has_method(acpi_handle handle, char *name); + #ifdef CONFIG_ACPI #include -- cgit v0.10.2 From 0db98202605c3d32e023d43c30b5bd878f520976 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:39 +0800 Subject: ACPI: introduce helper function acpi_execute_simple_method() Introduce helper function acpi_execute_simple_method() and use it in a number of places to simplify code. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index a762716..74669ac 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -525,18 +525,14 @@ static int acpi_battery_get_state(struct acpi_battery *battery) static int acpi_battery_set_alarm(struct acpi_battery *battery) { acpi_status status = 0; - union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &arg0 }; if (!acpi_battery_present(battery) || !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags)) return -ENODEV; - arg0.integer.value = battery->alarm; - mutex_lock(&battery->lock); - status = acpi_evaluate_object(battery->device->handle, "_BTP", - &arg_list, NULL); + status = acpi_execute_simple_method(battery->device->handle, "_BTP", + battery->alarm); mutex_unlock(&battery->lock); if (ACPI_FAILURE(status)) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a5bb33b..a5a032e 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -593,8 +593,6 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) static int __init acpi_bus_init_irq(void) { acpi_status status; - union acpi_object arg = { ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &arg }; char *message = NULL; @@ -623,9 +621,7 @@ static int __init acpi_bus_init_irq(void) printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message); - arg.integer.value = acpi_irq_model; - - status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL); + status = acpi_execute_simple_method(NULL, "\\_PIC", acpi_irq_model); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC")); return -ENODEV; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 5c28c89..1460c88 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -637,9 +637,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev, } /* Execute _PSW */ - arg_list.count = 1; - in_arg[0].integer.value = enable; - status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL); + status = acpi_execute_simple_method(dev->handle, "_PSW", enable); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { printk(KERN_ERR PREFIX "_PSW execution failed\n"); dev->wakeup.flags.valid = 0; diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 187ab61..81b0f03 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -31,12 +31,9 @@ static u8 sleep_states[ACPI_S_STATE_COUNT]; static void acpi_sleep_tts_switch(u32 acpi_state) { - union acpi_object in_arg = { ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &in_arg }; - acpi_status status = AE_OK; + acpi_status status; - in_arg.integer.value = acpi_state; - status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL); + status = acpi_execute_simple_method(NULL, "\\_TTS", acpi_state); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { /* * OS can't evaluate the _TTS object correctly. Some warning diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index a33821c..94523c7 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -239,26 +239,16 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz) static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode) { - acpi_status status = AE_OK; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &arg0 }; - acpi_handle handle = NULL; - - if (!tz) return -EINVAL; - status = acpi_get_handle(tz->device->handle, "_SCP", &handle); - if (ACPI_FAILURE(status)) { + if (!acpi_has_method(tz->device->handle, "_SCP")) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n")); return -ENODEV; - } - - arg0.integer.value = mode; - - status = acpi_evaluate_object(handle, NULL, &arg_list, NULL); - if (ACPI_FAILURE(status)) + } else if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle, + "_SCP", mode))) { return -ENODEV; + } return 0; } diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index b08d973..87b8588 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -510,3 +510,15 @@ bool acpi_has_method(acpi_handle handle, char *name) return ACPI_SUCCESS(acpi_get_handle(handle, name, &tmp)); } EXPORT_SYMBOL(acpi_has_method); + +acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, + u64 arg) +{ + union acpi_object obj = { .type = ACPI_TYPE_INTEGER }; + struct acpi_object_list arg_list = { .count = 1, .pointer = &obj, }; + + obj.integer.value = arg; + + return acpi_evaluate_object(handle, method, &arg_list, NULL); +} +EXPORT_SYMBOL(acpi_execute_simple_method); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a84533e..b862c7f 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -353,14 +353,10 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) { int status; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list args = { 1, &arg0 }; int state; - arg0.integer.value = level; - - status = acpi_evaluate_object(device->dev->handle, "_BCM", - &args, NULL); + status = acpi_execute_simple_method(device->dev->handle, + "_BCM", level); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Evaluating _BCM failed")); return -EIO; @@ -628,18 +624,15 @@ static int acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) { acpi_status status; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list args = { 1, &arg0 }; if (!video->cap._DOS) return 0; if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) return -EINVAL; - arg0.integer.value = (lcd_flag << 2) | bios_flag; - video->dos_setting = arg0.integer.value; - status = acpi_evaluate_object(video->device->handle, "_DOS", - &args, NULL); + video->dos_setting = (lcd_flag << 2) | bios_flag; + status = acpi_execute_simple_method(video->device->handle, "_DOS", + (lcd_flag << 2) | bios_flag); if (ACPI_FAILURE(status)) return -EIO; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 62b2811..e386258 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -58,6 +58,8 @@ acpi_status acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld); bool acpi_has_method(acpi_handle handle, char *name); +acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, + u64 arg); #ifdef CONFIG_ACPI -- cgit v0.10.2 From 7d2421f84b445dc48c68d33911f1fd6ce6853ee3 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:40 +0800 Subject: ACPI: introduce two helper functions for _EJ0 and _LCK Introduce two helper functions, acpi_evaluate_ej0() and acpi_evaluate_lck(), that will execute the _EJ0 and _LCK ACPI control methods, respectively, and use them to simplify the ACPI scan code. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index ada0b4c..4c25c3b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -193,8 +193,6 @@ static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl, static int acpi_scan_hot_remove(struct acpi_device *device) { acpi_handle handle = device->handle; - struct acpi_object_list arg_list; - union acpi_object arg; struct device *errdev; acpi_status status; unsigned long long sta; @@ -257,32 +255,15 @@ static int acpi_scan_hot_remove(struct acpi_device *device) put_device(&device->dev); device = NULL; - if (acpi_has_method(handle, "_LCK")) { - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 0; - acpi_evaluate_object(handle, "_LCK", &arg_list, NULL); - } - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - + acpi_evaluate_lck(handle, 0); /* * TBD: _EJD support. */ - status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_FOUND) { - return -ENODEV; - } else { - acpi_handle_warn(handle, "Eject failed (0x%x)\n", - status); - return -EIO; - } - } + status = acpi_evaluate_ej0(handle); + if (status == AE_NOT_FOUND) + return -ENODEV; + else if (ACPI_FAILURE(status)) + return -EIO; /* * Verify if eject was indeed successful. If not, log an error diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 87b8588..552248b 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -522,3 +522,46 @@ acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, return acpi_evaluate_object(handle, method, &arg_list, NULL); } EXPORT_SYMBOL(acpi_execute_simple_method); + +/** + * acpi_evaluate_ej0: Evaluate _EJ0 method for hotplug operations + * @handle: ACPI device handle + * + * Evaluate device's _EJ0 method for hotplug operations. + */ +acpi_status acpi_evaluate_ej0(acpi_handle handle) +{ + acpi_status status; + + status = acpi_execute_simple_method(handle, "_EJ0", 1); + if (status == AE_NOT_FOUND) + acpi_handle_warn(handle, "No _EJ0 support for device\n"); + else if (ACPI_FAILURE(status)) + acpi_handle_warn(handle, "Eject failed (0x%x)\n", status); + + return status; +} + +/** + * acpi_evaluate_lck: Evaluate _LCK method to lock/unlock device + * @handle: ACPI device handle + * @lock: lock device if non-zero, otherwise unlock device + * + * Evaluate device's _LCK method if present to lock/unlock device + */ +acpi_status acpi_evaluate_lck(acpi_handle handle, int lock) +{ + acpi_status status; + + status = acpi_execute_simple_method(handle, "_LCK", !!lock); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + if (lock) + acpi_handle_warn(handle, + "Locking device failed (0x%x)\n", status); + else + acpi_handle_warn(handle, + "Unlocking device failed (0x%x)\n", status); + } + + return status; +} diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e386258..f499157 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -60,6 +60,8 @@ acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld bool acpi_has_method(acpi_handle handle, char *name); acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, u64 arg); +acpi_status acpi_evaluate_ej0(acpi_handle handle); +acpi_status acpi_evaluate_lck(acpi_handle handle, int lock); #ifdef CONFIG_ACPI -- cgit v0.10.2 From ebf4df8db0e7e5db9f7fca5fcd0c2b90ac954385 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:41 +0800 Subject: ACPI: Export acpi_(bay)|(dock)_match() from scan.c Functions acpi_dock_match() and acpi_bay_match() in scan.c can be shared with dock.c to reduce code duplication, so export them as global functions. Also add a new function acpi_ata_match() to check whether an ACPI device object represents an ATA device. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4c25c3b..62e2055 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1480,43 +1480,45 @@ static void acpi_device_get_busid(struct acpi_device *device) } /* + * acpi_ata_match - see if an acpi object is an ATA device + * + * If an acpi object has one of the ACPI ATA methods defined, + * then we can safely call it an ATA device. + */ +bool acpi_ata_match(acpi_handle handle) +{ + return acpi_has_method(handle, "_GTF") || + acpi_has_method(handle, "_GTM") || + acpi_has_method(handle, "_STM") || + acpi_has_method(handle, "_SDD"); +} + +/* * acpi_bay_match - see if an acpi object is an ejectable driver bay * * If an acpi object is ejectable and has one of the ACPI ATA methods defined, * then we can safely call it an ejectable drive bay */ -static int acpi_bay_match(acpi_handle handle) +bool acpi_bay_match(acpi_handle handle) { acpi_handle phandle; if (!acpi_has_method(handle, "_EJ0")) - return -ENODEV; + return false; + if (acpi_ata_match(handle)) + return true; + if (ACPI_FAILURE(acpi_get_parent(handle, &phandle))) + return false; - if (acpi_has_method(handle, "_GTF") || - acpi_has_method(handle, "_GTM") || - acpi_has_method(handle, "_STM") || - acpi_has_method(handle, "_SDD")) - return 0; - - if (acpi_get_parent(handle, &phandle)) - return -ENODEV; - - if (acpi_has_method(phandle, "_GTF") || - acpi_has_method(phandle, "_GTM") || - acpi_has_method(phandle, "_STM") || - acpi_has_method(phandle, "_SDD")) - return 0; - - return -ENODEV; + return acpi_ata_match(phandle); } /* * acpi_dock_match - see if an acpi object has a _DCK method */ -static int acpi_dock_match(acpi_handle handle) +bool acpi_dock_match(acpi_handle handle) { - acpi_handle tmp; - return acpi_get_handle(handle, "_DCK", &tmp); + return acpi_has_method(handle, "_DCK"); } const char *acpi_device_hid(struct acpi_device *device) @@ -1554,33 +1556,26 @@ static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id) * lacks the SMBUS01 HID and the methods do not have the necessary "_" * prefix. Work around this. */ -static int acpi_ibm_smbus_match(acpi_handle handle) +static bool acpi_ibm_smbus_match(acpi_handle handle) { - struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; - int result; + char node_name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer path = { sizeof(node_name), node_name }; if (!dmi_name_in_vendors("IBM")) - return -ENODEV; + return false; /* Look for SMBS object */ - result = acpi_get_name(handle, ACPI_SINGLE_NAME, &path); - if (result) - return result; - - if (strcmp("SMBS", path.pointer)) { - result = -ENODEV; - goto out; - } + if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &path)) || + strcmp("SMBS", path.pointer)) + return false; /* Does it have the necessary (but misnamed) methods? */ - result = -ENODEV; if (acpi_has_method(handle, "SBI") && acpi_has_method(handle, "SBR") && acpi_has_method(handle, "SBW")) - result = 0; -out: - kfree(path.pointer); - return result; + return true; + + return false; } static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, @@ -1628,11 +1623,11 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, */ if (acpi_is_video_device(handle)) acpi_add_id(pnp, ACPI_VIDEO_HID); - else if (ACPI_SUCCESS(acpi_bay_match(handle))) + else if (acpi_bay_match(handle)) acpi_add_id(pnp, ACPI_BAY_HID); - else if (ACPI_SUCCESS(acpi_dock_match(handle))) + else if (acpi_dock_match(handle)) acpi_add_id(pnp, ACPI_DOCK_HID); - else if (!acpi_ibm_smbus_match(handle)) + else if (acpi_ibm_smbus_match(handle)) acpi_add_id(pnp, ACPI_SMBUS_IBM_HID); else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) { acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index f499157..facc0ba 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -62,6 +62,9 @@ acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, u64 arg); acpi_status acpi_evaluate_ej0(acpi_handle handle); acpi_status acpi_evaluate_lck(acpi_handle handle, int lock); +bool acpi_ata_match(acpi_handle handle); +bool acpi_bay_match(acpi_handle handle); +bool acpi_dock_match(acpi_handle handle); #ifdef CONFIG_ACPI -- cgit v0.10.2 From c9b5471f8866956919955b70ab27b4737b8bce30 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:42 +0800 Subject: ACPI: simplify dock driver with new helper functions Use helper functions introduced previously to simplify the ACPI dock driver. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 1bdb1fa..810d1d7 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -226,48 +226,6 @@ find_dock_dependent_device(struct dock_station *ds, acpi_handle handle) /***************************************************************************** * Dock functions * *****************************************************************************/ -/** - * is_dock - see if a device is a dock station - * @handle: acpi handle of the device - * - * If an acpi object has a _DCK method, then it is by definition a dock - * station, so return true. - */ -static int is_dock(acpi_handle handle) -{ - acpi_status status; - acpi_handle tmp; - - status = acpi_get_handle(handle, "_DCK", &tmp); - if (ACPI_FAILURE(status)) - return 0; - return 1; -} - -static int __init is_ejectable(acpi_handle handle) -{ - acpi_status status; - acpi_handle tmp; - - status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) - return 0; - return 1; -} - -static int __init is_ata(acpi_handle handle) -{ - acpi_handle tmp; - - if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) - return 1; - - return 0; -} - static int __init is_battery(acpi_handle handle) { struct acpi_device_info *info; @@ -284,17 +242,13 @@ static int __init is_battery(acpi_handle handle) return ret; } -static int __init is_ejectable_bay(acpi_handle handle) +/* Check whether ACPI object is an ejectable battery or disk bay */ +static bool __init is_ejectable_bay(acpi_handle handle) { - acpi_handle phandle; + if (acpi_has_method(handle, "_EJ0") && is_battery(handle)) + return true; - if (!is_ejectable(handle)) - return 0; - if (is_battery(handle) || is_ata(handle)) - return 1; - if (!acpi_get_parent(handle, &phandle) && is_ata(phandle)) - return 1; - return 0; + return acpi_bay_match(handle); } /** @@ -312,7 +266,7 @@ int is_dock_device(acpi_handle handle) if (!dock_station_count) return 0; - if (is_dock(handle)) + if (acpi_dock_match(handle)) return 1; list_for_each_entry(dock_station, &dock_stations, sibling) @@ -447,37 +401,6 @@ static void dock_event(struct dock_station *ds, u32 event, int num) } /** - * eject_dock - respond to a dock eject request - * @ds: the dock station - * - * This is called after _DCK is called, to execute the dock station's - * _EJ0 method. - */ -static void eject_dock(struct dock_station *ds) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status; - acpi_handle tmp; - - /* all dock devices should have _EJ0, but check anyway */ - status = acpi_get_handle(ds->handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) { - pr_debug("No _EJ0 support for dock device\n"); - return; - } - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - - status = acpi_evaluate_object(ds->handle, "_EJ0", &arg_list, NULL); - if (ACPI_FAILURE(status)) - pr_debug("Failed to evaluate _EJ0!\n"); -} - -/** * handle_dock - handle a dock event * @ds: the dock station * @dock: to dock, or undock - that is the question @@ -537,27 +460,6 @@ static inline void complete_undock(struct dock_station *ds) ds->flags &= ~(DOCK_UNDOCKING); } -static void dock_lock(struct dock_station *ds, int lock) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status; - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = !!lock; - status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - if (lock) - acpi_handle_warn(ds->handle, - "Locking device failed (0x%x)\n", status); - else - acpi_handle_warn(ds->handle, - "Unlocking device failed (0x%x)\n", status); - } -} - /** * dock_in_progress - see if we are in the middle of handling a dock event * @ds: the dock station @@ -692,8 +594,8 @@ static int handle_eject_request(struct dock_station *ds, u32 event) hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); undock(ds); - dock_lock(ds, 0); - eject_dock(ds); + acpi_evaluate_lck(ds->handle, 0); + acpi_evaluate_ej0(ds->handle); if (dock_present(ds)) { acpi_handle_err(ds->handle, "Unable to undock!\n"); return -EBUSY; @@ -752,7 +654,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) hotplug_dock_devices(ds, event); complete_dock(ds); dock_event(ds, event, DOCK_EVENT); - dock_lock(ds, 1); + acpi_evaluate_lck(ds->handle, 1); acpi_update_all_gpes(); break; } @@ -998,9 +900,9 @@ static int __init dock_add(acpi_handle handle) /* we want the dock device to send uevents */ dev_set_uevent_suppress(&dd->dev, 0); - if (is_dock(handle)) + if (acpi_dock_match(handle)) dock_station->flags |= DOCK_IS_DOCK; - if (is_ata(handle)) + if (acpi_ata_match(handle)) dock_station->flags |= DOCK_IS_ATA; if (is_battery(handle)) dock_station->flags |= DOCK_IS_BAT; @@ -1043,7 +945,7 @@ err_unregister: static __init acpi_status find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv) { - if (is_dock(handle) || is_ejectable_bay(handle)) + if (acpi_dock_match(handle) || is_ejectable_bay(handle)) dock_add(handle); return AE_OK; -- cgit v0.10.2 From ecd046da57d3327367b930478234e58f01bc9f0f Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:43 +0800 Subject: ACPI: simplify acpiphp driver with new helper functions Use the new helper functions introduced previously to simplify the ACPI-based PCI hotplug (acpiphp) driver. [rjw: Changelog] Signed-off-by: Jiang Liu Acked-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 59df857..a0a7133 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -201,7 +201,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; struct acpiphp_slot *slot; struct acpiphp_func *newfunc; - acpi_handle tmp; acpi_status status = AE_OK; unsigned long long adr, sun; int device, function, retval, found = 0; @@ -232,19 +231,19 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) newfunc->handle = handle; newfunc->function = function; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp))) + if (acpi_has_method(handle, "_EJ0")) newfunc->flags = FUNC_HAS_EJ0; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) + if (acpi_has_method(handle, "_STA")) newfunc->flags |= FUNC_HAS_STA; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp))) + if (acpi_has_method(handle, "_PS0")) newfunc->flags |= FUNC_HAS_PS0; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) + if (acpi_has_method(handle, "_PS3")) newfunc->flags |= FUNC_HAS_PS3; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) + if (acpi_has_method(handle, "_DCK")) newfunc->flags |= FUNC_HAS_DCK; status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); @@ -843,25 +842,14 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) */ int acpiphp_eject_slot(struct acpiphp_slot *slot) { - acpi_status status; struct acpiphp_func *func; - struct acpi_object_list arg_list; - union acpi_object arg; list_for_each_entry(func, &slot->funcs, sibling) { /* We don't want to call _EJ0 on non-existing functions. */ if ((func->flags & FUNC_HAS_EJ0)) { - /* _EJ0 method take one argument */ - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - - status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); - if (ACPI_FAILURE(status)) { - warn("%s: _EJ0 failed\n", __func__); + if (ACPI_FAILURE(acpi_evaluate_ej0(func->handle))) return -1; - } else + else break; } } @@ -1171,7 +1159,6 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, */ void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) { - acpi_handle dummy_handle; struct acpiphp_bridge *bridge; if (acpiphp_disabled) @@ -1200,8 +1187,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) get_device(&bus->dev); if (!pci_is_root_bus(bridge->pci_bus) && - ACPI_SUCCESS(acpi_get_handle(bridge->handle, - "_EJ0", &dummy_handle))) { + acpi_has_method(bridge->handle, "_EJ0")) { dbg("found ejectable p2p bridge\n"); bridge->flags |= BRIDGE_HAS_EJ0; bridge->func = acpiphp_bridge_handle_to_function(handle); -- cgit v0.10.2 From d460acebd7959cc91e7edc594d90adb9b72a0b05 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:42:51 +0200 Subject: ACPI / dock: Drop the hp_lock mutex from struct dock_station The only existing user of the hp_lock mutex in struct dock_station, hotplug_dock_devices(), is always called under acpi_scan_lock and cannot race with another instance of itself, so drop the mutex which is not necessary. Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 810d1d7..c107615 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -63,7 +63,6 @@ struct dock_station { acpi_handle handle; unsigned long last_dock_time; u32 flags; - struct mutex hp_lock; struct list_head dependent_devices; struct list_head sibling; @@ -351,8 +350,6 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) { struct dock_dependent_device *dd; - mutex_lock(&ds->hp_lock); - /* * First call driver specific hotplug functions */ @@ -371,7 +368,6 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) else dock_create_acpi_device(dd->handle); } - mutex_unlock(&ds->hp_lock); } static void dock_event(struct dock_station *ds, u32 event, int num) @@ -893,7 +889,6 @@ static int __init dock_add(acpi_handle handle) dock_station->dock_device = dd; dock_station->last_dock_time = jiffies - HZ; - mutex_init(&dock_station->hp_lock); INIT_LIST_HEAD(&dock_station->sibling); INIT_LIST_HEAD(&dock_station->dependent_devices); -- cgit v0.10.2 From 96c0a4d4902c3d5f56bde95d3e2d96689ca64b6d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:46:02 +0200 Subject: ACPI / dock: Rework and simplify find_dock_devices() Since acpi_walk_namespace() calls find_dock_devices() during tree pre-order visit, the latter doesn't need to add devices whose parents have _EJD pointing to the docking station to the list of that station's dependent devices, because those parents are going to be added to that list anyway and the removal of a parent will take care of the removal of its children in those cases. For this reason, rework find_dock_devices() to only call add_dock_dependent_device() for devices whose _EJD point directy to the docking station represented by its context argument and simplify it slightly. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index c107615..7c86d01 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -741,29 +741,16 @@ static struct notifier_block dock_acpi_notifier = { * check to see if an object has an _EJD method. If it does, then it * will see if it is dependent on the dock station. */ -static acpi_status __init -find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv) +static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl, + void *context, void **rv) { - acpi_status status; - acpi_handle tmp, parent; struct dock_station *ds = context; + acpi_handle ejd = NULL; - status = acpi_bus_get_ejd(handle, &tmp); - if (ACPI_FAILURE(status)) { - /* try the parent device as well */ - status = acpi_get_parent(handle, &parent); - if (ACPI_FAILURE(status)) - goto fdd_out; - /* see if parent is dependent on dock */ - status = acpi_bus_get_ejd(parent, &tmp); - if (ACPI_FAILURE(status)) - goto fdd_out; - } - - if (tmp == ds->handle) + acpi_bus_get_ejd(handle, &ejd); + if (ejd == ds->handle) add_dock_dependent_device(ds, handle); -fdd_out: return AE_OK; } -- cgit v0.10.2 From 37f908778f20bbcc35ab9a98a5b584329c6abf08 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:46:42 +0200 Subject: ACPI / dock: Walk list in reverse order during removal of devices If there are indirect dependencies between devices in a dock station's dependent devices list, they may be broken if the devices are removed in the same order in which they have been added. For this reason, make the code in handle_eject_request() walk the list of dependent devices in reverse order. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 7c86d01..41c5d04 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -337,9 +337,29 @@ static void dock_remove_acpi_device(acpi_handle handle) } /** - * hotplug_dock_devices - insert or remove devices on the dock station + * hot_remove_dock_devices - Remove dock station devices. + * @ds: Dock station. + */ +static void hot_remove_dock_devices(struct dock_station *ds) +{ + struct dock_dependent_device *dd; + + /* + * Walk the list in reverse order so that devices that have been added + * last are removed first (in case there are some indirect dependencies + * between them). + */ + list_for_each_entry_reverse(dd, &ds->dependent_devices, list) + dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false); + + list_for_each_entry_reverse(dd, &ds->dependent_devices, list) + dock_remove_acpi_device(dd->handle); +} + +/** + * hotplug_dock_devices - Insert devices on a dock station. * @ds: the dock station - * @event: either bus check or eject request + * @event: either bus check or device check request * * Some devices on the dock station need to have drivers called * to perform hotplug operations after a dock event has occurred. @@ -350,24 +370,17 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) { struct dock_dependent_device *dd; - /* - * First call driver specific hotplug functions - */ + /* Call driver specific hotplug functions. */ list_for_each_entry(dd, &ds->dependent_devices, list) dock_hotplug_event(dd, event, false); /* - * Now make sure that an acpi_device is created for each - * dependent device, or removed if this is an eject request. - * This will cause acpi_drivers to be stopped/started if they - * exist + * Now make sure that an acpi_device is created for each dependent + * device. That will cause scan handlers to be attached to device + * objects or acpi_drivers to be stopped/started if they are present. */ - list_for_each_entry(dd, &ds->dependent_devices, list) { - if (event == ACPI_NOTIFY_EJECT_REQUEST) - dock_remove_acpi_device(dd->handle); - else - dock_create_acpi_device(dd->handle); - } + list_for_each_entry(dd, &ds->dependent_devices, list) + dock_create_acpi_device(dd->handle); } static void dock_event(struct dock_station *ds, u32 event, int num) @@ -588,7 +601,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event) */ dock_event(ds, event, UNDOCK_EVENT); - hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); + hot_remove_dock_devices(ds); undock(ds); acpi_evaluate_lck(ds->handle, 0); acpi_evaluate_ej0(ds->handle); -- cgit v0.10.2 From 4ec24065a65b4debfdeb591cc01a4aa092651f53 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:47:14 +0200 Subject: ACPI / dock: Simplify dock_init_hotplug() and dock_release_hotplug() Make dock_init_hotplug() and dock_release_hotplug() slightly simpler and move some checks in those functions to the code paths where they are needed. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 41c5d04..b1170d6 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -130,19 +130,16 @@ static int dock_init_hotplug(struct dock_dependent_device *dd, int ret = 0; mutex_lock(&hotplug_lock); - - if (dd->hp_context) { + if (WARN_ON(dd->hp_context)) { ret = -EEXIST; } else { dd->hp_refcount = 1; dd->hp_ops = ops; dd->hp_context = context; dd->hp_release = release; + if (init) + init(context); } - - if (!WARN_ON(ret) && init) - init(context); - mutex_unlock(&hotplug_lock); return ret; } @@ -157,22 +154,17 @@ static int dock_init_hotplug(struct dock_dependent_device *dd, */ static void dock_release_hotplug(struct dock_dependent_device *dd) { - void (*release)(void *) = NULL; - void *context = NULL; - mutex_lock(&hotplug_lock); - if (dd->hp_context && !--dd->hp_refcount) { + void (*release)(void *) = dd->hp_release; + void *context = dd->hp_context; + dd->hp_ops = NULL; - context = dd->hp_context; dd->hp_context = NULL; - release = dd->hp_release; dd->hp_release = NULL; + if (release) + release(context); } - - if (release && context) - release(context); - mutex_unlock(&hotplug_lock); } -- cgit v0.10.2 From 59401ccce8729e5c43f9781cc5570da5ca470e27 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:48:49 +0200 Subject: ACPI / dock: Rework the handling of notifications The ACPI dock driver uses register_acpi_bus_notifier() which installs a notifier triggered globally for all system notifications. That first of all is inefficient, because the dock driver is only interested in notifications associated with the devices it handles, but it has to handle all system notifies for all devices. Moreover, it does that even if no docking stations are present in the system (CONFIG_ACPI_DOCK set is sufficient for that to happen). Besides, that is inconvenient, because it requires the driver to do extra work for each notification to find the target dock station object. For these reasons, rework the dock driver to install a notify handler individually for each dock station in the system using acpi_install_notify_handler(). This allows the dock station object to be passed directly to the notify handler and makes it possible to simplify the dock driver quite a bit. It also reduces the overhead related to the handling of all system notifies when CONFIG_ACPI_DOCK is set. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index b1170d6..a326c79 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -607,18 +607,17 @@ static int handle_eject_request(struct dock_station *ds, u32 event) /** * dock_notify - act upon an acpi dock notification - * @handle: the dock station handle + * @ds: dock station * @event: the acpi event - * @data: our driver data struct * * If we are notified to dock, then check to see if the dock is * present and then dock. Notify all drivers of the dock event, * and then hotplug and devices that may need hotplugging. */ -static void dock_notify(acpi_handle handle, u32 event, void *data) +static void dock_notify(struct dock_station *ds, u32 event) { - struct dock_station *ds = data; - struct acpi_device *tmp; + acpi_handle handle = ds->handle; + struct acpi_device *ad; int surprise_removal = 0; /* @@ -641,8 +640,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: - if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle, - &tmp)) { + if (!dock_in_progress(ds) && acpi_bus_get_device(handle, &ad)) { begin_dock(ds); dock(ds); if (!dock_present(ds)) { @@ -679,9 +677,8 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) } struct dock_data { - acpi_handle handle; - unsigned long event; struct dock_station *ds; + u32 event; }; static void acpi_dock_deferred_cb(void *context) @@ -689,52 +686,31 @@ static void acpi_dock_deferred_cb(void *context) struct dock_data *data = context; acpi_scan_lock_acquire(); - dock_notify(data->handle, data->event, data->ds); + dock_notify(data->ds, data->event); acpi_scan_lock_release(); kfree(data); } -static int acpi_dock_notifier_call(struct notifier_block *this, - unsigned long event, void *data) +static void dock_notify_handler(acpi_handle handle, u32 event, void *data) { - struct dock_station *dock_station; - acpi_handle handle = data; + struct dock_data *dd; if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK && event != ACPI_NOTIFY_EJECT_REQUEST) - return 0; - - acpi_scan_lock_acquire(); - - list_for_each_entry(dock_station, &dock_stations, sibling) { - if (dock_station->handle == handle) { - struct dock_data *dd; - acpi_status status; - - dd = kmalloc(sizeof(*dd), GFP_KERNEL); - if (!dd) - break; + return; - dd->handle = handle; - dd->event = event; - dd->ds = dock_station; - status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, - dd); - if (ACPI_FAILURE(status)) - kfree(dd); + dd = kmalloc(sizeof(*dd), GFP_KERNEL); + if (dd) { + acpi_status status; - break; - } + dd->ds = data; + dd->event = event; + status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); + if (ACPI_FAILURE(status)) + kfree(dd); } - - acpi_scan_lock_release(); - return 0; } -static struct notifier_block dock_acpi_notifier = { - .notifier_call = acpi_dock_notifier_call, -}; - /** * find_dock_devices - find devices on the dock station * @handle: the handle of the device we are examining @@ -868,6 +844,7 @@ static int __init dock_add(acpi_handle handle) int ret, id; struct dock_station ds, *dock_station; struct platform_device *dd; + acpi_status status; id = dock_station_count; memset(&ds, 0, sizeof(ds)); @@ -908,6 +885,11 @@ static int __init dock_add(acpi_handle handle) if (ret) goto err_rmgroup; + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + dock_notify_handler, dock_station); + if (ACPI_FAILURE(status)) + goto err_rmgroup; + dock_station_count++; list_add(&dock_station->sibling, &dock_stations); return 0; @@ -953,7 +935,6 @@ void __init acpi_dock_init(void) } ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); - register_acpi_bus_notifier(&dock_acpi_notifier); pr_info(PREFIX "%s: %d docks/bays found\n", ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); } -- cgit v0.10.2 From f716fc2ac037c45a6c641eb9f20ec602e8d04e14 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:49:55 +0200 Subject: ACPI: Drop ACPI bus notifier call chain There are no users of the ACPI bus notifier call chain, acpi_bus_notify_list, any more, so drop it. Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a5a032e..6fd27a9 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -499,19 +499,6 @@ static void acpi_bus_check_scope(acpi_handle handle) */ } -static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list); -int register_acpi_bus_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&acpi_bus_notify_list, nb); -} -EXPORT_SYMBOL_GPL(register_acpi_bus_notifier); - -void unregister_acpi_bus_notifier(struct notifier_block *nb) -{ - blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb); -} -EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier); - /** * acpi_bus_notify * --------------- @@ -525,9 +512,6 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n", type, handle)); - blocking_notifier_call_chain(&acpi_bus_notify_list, - type, (void *)handle); - switch (type) { case ACPI_NOTIFY_BUS_CHECK: diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index facc0ba..71f3fd4 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -366,8 +366,6 @@ extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); extern int register_acpi_notifier(struct notifier_block *); extern int unregister_acpi_notifier(struct notifier_block *); -extern int register_acpi_bus_notifier(struct notifier_block *nb); -extern void unregister_acpi_bus_notifier(struct notifier_block *nb); /* * External Functions */ -- cgit v0.10.2 From a30c4c5ee85680bb66ed8a6c0b0bf4921125c378 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:50:24 +0200 Subject: ACPI / dock: Do not leak memory on falilures to add a dock station The function creating and registering dock station objects, dock_add(), leaks memory if there's an error after it's walked the ACPI namespace calling find_dock_devices(), because it doesn't free the list of dependent devices it's just created in those cases. Fix that issue by adding the missing code to free the list of dependent devices on errors. Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index a326c79..3e20b13 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -115,6 +115,16 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) return 0; } +static void remove_dock_dependent_devices(struct dock_station *ds) +{ + struct dock_dependent_device *dd, *aux; + + list_for_each_entry_safe(dd, aux, &ds->dependent_devices, list) { + list_del(&dd->list); + kfree(dd); + } +} + /** * dock_init_hotplug - Initialize a hotplug device on a docking station. * @dd: Dock-dependent device. @@ -895,6 +905,7 @@ static int __init dock_add(acpi_handle handle) return 0; err_rmgroup: + remove_dock_dependent_devices(dock_station); sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group); err_unregister: platform_device_unregister(dd); -- cgit v0.10.2 From e6c215f15a1cbf4cdd6996d95fba0c0d6c0f3ccc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Jul 2013 03:02:25 +0200 Subject: ACPI / dock: Do not check CONFIG_ACPI_DOCK_MODULE Since commit 94add0f (ACPI / dock: Initialize ACPI dock subsystem upfront) the ACPI dock driver cannot be a module, so CONFIG_ACPI_DOCK_MODULE is never set. For this reason, simplify the preprocessor conditional in include/acpi/acpi_drivers.h referring to that sybbol unnecessarily. Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index b420939..0cf8578 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -117,7 +117,7 @@ struct acpi_dock_ops { acpi_notify_handler uevent; }; -#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) +#ifdef CONFIG_ACPI_DOCK extern int is_dock_device(acpi_handle handle); extern int register_dock_notifier(struct notifier_block *nb); extern void unregister_dock_notifier(struct notifier_block *nb); @@ -150,6 +150,6 @@ static inline int register_hotplug_dock_device(acpi_handle handle, static inline void unregister_hotplug_dock_device(acpi_handle handle) { } -#endif +#endif /* CONFIG_ACPI_DOCK */ #endif /*__ACPI_DRIVERS_H__*/ -- cgit v0.10.2 From f09ce741a03ad7de591aa47e760fbeee28567b63 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Jul 2013 03:03:25 +0200 Subject: ACPI / dock / PCI: Drop ACPI dock notifier chain The only user of the ACPI dock notifier chain is the ACPI-based PCI hotplug (acpiphp) driver that uses it to carry out post-dock fixups needed by some systems with broken _DCK. However, it is not necessary to use a separate notifier chain for that, as it can be simply replaced with a new callback in struct acpi_dock_ops. For this reason, add a new .fixup() callback to struct acpi_dock_ops and make hotplug_dock_devices() execute it for all dock devices with hotplug operations registered. Accordingly, make acpiphp point that callback to the function carrying out the post-dock fixups and do not register a separate dock notifier for each device registering dock operations. Finally, drop the ACPI dock notifier chain that has no more users. Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 3e20b13..c89a9c3 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -51,8 +51,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to " " the driver to wait for userspace to write the undock sysfs file " " before undocking"); -static struct atomic_notifier_head dock_notifier_list; - static const struct acpi_device_id dock_device_ids[] = { {"LNXDOCK", 0}, {"", 0}, @@ -89,6 +87,12 @@ struct dock_dependent_device { #define DOCK_EVENT 3 #define UNDOCK_EVENT 2 +enum dock_callback_type { + DOCK_CALL_HANDLER, + DOCK_CALL_FIXUP, + DOCK_CALL_UEVENT, +}; + /***************************************************************************** * Dock Dependent device functions * *****************************************************************************/ @@ -179,7 +183,7 @@ static void dock_release_hotplug(struct dock_dependent_device *dd) } static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, - bool uevent) + enum dock_callback_type cb_type) { acpi_notify_handler cb = NULL; bool run = false; @@ -189,8 +193,18 @@ static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, if (dd->hp_context) { run = true; dd->hp_refcount++; - if (dd->hp_ops) - cb = uevent ? dd->hp_ops->uevent : dd->hp_ops->handler; + if (dd->hp_ops) { + switch (cb_type) { + case DOCK_CALL_FIXUP: + cb = dd->hp_ops->fixup; + break; + case DOCK_CALL_UEVENT: + cb = dd->hp_ops->uevent; + break; + default: + cb = dd->hp_ops->handler; + } + } } mutex_unlock(&hotplug_lock); @@ -372,9 +386,13 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) { struct dock_dependent_device *dd; + /* Call driver specific post-dock fixups. */ + list_for_each_entry(dd, &ds->dependent_devices, list) + dock_hotplug_event(dd, event, DOCK_CALL_FIXUP); + /* Call driver specific hotplug functions. */ list_for_each_entry(dd, &ds->dependent_devices, list) - dock_hotplug_event(dd, event, false); + dock_hotplug_event(dd, event, DOCK_CALL_HANDLER); /* * Now make sure that an acpi_device is created for each dependent @@ -405,7 +423,7 @@ static void dock_event(struct dock_station *ds, u32 event, int num) kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); list_for_each_entry(dd, &ds->dependent_devices, list) - dock_hotplug_event(dd, event, true); + dock_hotplug_event(dd, event, DOCK_CALL_UEVENT); if (num != DOCK_EVENT) kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); @@ -488,37 +506,6 @@ static int dock_in_progress(struct dock_station *ds) } /** - * register_dock_notifier - add yourself to the dock notifier list - * @nb: the callers notifier block - * - * If a driver wishes to be notified about dock events, they can - * use this function to put a notifier block on the dock notifier list. - * this notifier call chain will be called after a dock event, but - * before hotplugging any new devices. - */ -int register_dock_notifier(struct notifier_block *nb) -{ - if (!dock_station_count) - return -ENODEV; - - return atomic_notifier_chain_register(&dock_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(register_dock_notifier); - -/** - * unregister_dock_notifier - remove yourself from the dock notifier list - * @nb: the callers notifier block - */ -void unregister_dock_notifier(struct notifier_block *nb) -{ - if (!dock_station_count) - return; - - atomic_notifier_chain_unregister(&dock_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(unregister_dock_notifier); - -/** * register_hotplug_dock_device - register a hotplug function * @handle: the handle of the device * @ops: handlers to call after docking @@ -658,8 +645,6 @@ static void dock_notify(struct dock_station *ds, u32 event) complete_dock(ds); break; } - atomic_notifier_call_chain(&dock_notifier_list, - event, NULL); hotplug_dock_devices(ds, event); complete_dock(ds); dock_event(ds, event, DOCK_EVENT); @@ -945,7 +930,6 @@ void __init acpi_dock_init(void) return; } - ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); pr_info(PREFIX "%s: %d docks/bays found\n", ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); } diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 6fdd49c..6c781ed 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -122,7 +122,6 @@ struct acpiphp_func { struct acpiphp_slot *slot; /* parent */ struct list_head sibling; - struct notifier_block nb; acpi_handle handle; u8 function; /* pci function# */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a0a7133..8bfad0d 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -119,15 +119,14 @@ static void free_bridge(struct kref *kref) * TBD - figure out a way to only call fixups for * systems that require them. */ -static int post_dock_fixups(struct notifier_block *nb, unsigned long val, - void *v) +static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) { - struct acpiphp_func *func = container_of(nb, struct acpiphp_func, nb); + struct acpiphp_func *func = data; struct pci_bus *bus = func->slot->bridge->pci_bus; u32 buses; if (!bus->self) - return NOTIFY_OK; + return; /* fixup bad _DCK function that rewrites * secondary bridge on slot @@ -143,11 +142,11 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, | ((unsigned int)(bus->busn_res.end) << 16); pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); } - return NOTIFY_OK; } static const struct acpi_dock_ops acpiphp_dock_ops = { + .fixup = post_dock_fixups, .handler = hotplug_event_func, }; @@ -315,14 +314,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) &acpiphp_dock_ops, newfunc, acpiphp_dock_init, acpiphp_dock_release)) dbg("failed to register dock device\n"); - - /* we need to be notified when dock events happen - * outside of the hotplug operation, since we may - * need to do fixups before we can hotplug. - */ - newfunc->nb.notifier_call = post_dock_fixups; - if (register_dock_notifier(&newfunc->nb)) - dbg("failed to register a dock notifier"); } /* install notify handler */ @@ -472,7 +463,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) 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); } if (!(func->flags & FUNC_HAS_DCK)) { status = acpi_remove_notify_handler(func->handle, diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 0cf8578..1cedfcb 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -113,14 +113,13 @@ void pci_acpi_crs_quirks(void); Dock Station -------------------------------------------------------------------------- */ struct acpi_dock_ops { + acpi_notify_handler fixup; acpi_notify_handler handler; acpi_notify_handler uevent; }; #ifdef CONFIG_ACPI_DOCK extern int is_dock_device(acpi_handle handle); -extern int register_dock_notifier(struct notifier_block *nb); -extern void unregister_dock_notifier(struct notifier_block *nb); extern int register_hotplug_dock_device(acpi_handle handle, const struct acpi_dock_ops *ops, void *context, @@ -132,13 +131,6 @@ static inline int is_dock_device(acpi_handle handle) { return 0; } -static inline int register_dock_notifier(struct notifier_block *nb) -{ - return -ENODEV; -} -static inline void unregister_dock_notifier(struct notifier_block *nb) -{ -} static inline int register_hotplug_dock_device(acpi_handle handle, const struct acpi_dock_ops *ops, void *context, -- cgit v0.10.2 From 2efbca4dfc7b43951de6dd1647f9eebda9d4372b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Jul 2013 03:23:36 +0200 Subject: ACPI / dock: Drop unnecessary local variable from dock_add() The local variable id in dock_add() is not necessary, so drop it. While we're at it, use an initializer to clear the local variable ds and drop the memset() used for this purpose. Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index c89a9c3..f601658 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -836,14 +836,13 @@ static struct attribute_group dock_attribute_group = { */ static int __init dock_add(acpi_handle handle) { - int ret, id; - struct dock_station ds, *dock_station; + struct dock_station *dock_station, ds = { NULL, }; struct platform_device *dd; acpi_status status; + int ret; - id = dock_station_count; - memset(&ds, 0, sizeof(ds)); - dd = platform_device_register_data(NULL, "dock", id, &ds, sizeof(ds)); + dd = platform_device_register_data(NULL, "dock", dock_station_count, + &ds, sizeof(ds)); if (IS_ERR(dd)) return PTR_ERR(dd); -- cgit v0.10.2 From 0177f29fea534ef5e6af2d76e9a9be0fdd325c4d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 17 Jul 2013 08:33:25 +0800 Subject: ACPI / dock: fix error return code in dock_add() Fix to return -ENODEV in the acpi notify handler install error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index f601658..b527c1b 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -881,8 +881,10 @@ static int __init dock_add(acpi_handle handle) status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, dock_notify_handler, dock_station); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + ret = -ENODEV; goto err_rmgroup; + } dock_station_count++; list_add(&dock_station->sibling, &dock_stations); -- cgit v0.10.2