From b408a054931cdd1274f72fbeb297e3e3c7ce85f8 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:49 +0800 Subject: olpc_xo15_sci: convert acpi_evaluate_object() to acpi_execute_simple_method() acpi_execute_simple_method() is a new ACPI API introduced to invoke an ACPI control method that has single integer parameter and no return value. Convert acpi_evaluate_object() to acpi_execute_simple_method() in arch/x86/platform/olpc/olpc-xo15-sci.c Signed-off-by: Zhang Rui CC: Daniel Drake CC: H. Peter Anvin Signed-off-by: Rafael J. Wysocki diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c index fef7d0b..649a12b 100644 --- a/arch/x86/platform/olpc/olpc-xo15-sci.c +++ b/arch/x86/platform/olpc/olpc-xo15-sci.c @@ -40,16 +40,9 @@ static bool lid_wake_on_close; */ static int set_lid_wake_behavior(bool wake_on_close) { - 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 = wake_on_close; - - status = acpi_evaluate_object(NULL, "\\_SB.PCI0.LID.LIDW", &arg_list, NULL); + status = acpi_execute_simple_method(NULL, "\\_SB.PCI0.LID.LIDW", wake_on_close); if (ACPI_FAILURE(status)) { pr_warning(PFX "failed to set lid behavior\n"); return 1; -- cgit v0.10.2 From 5e8ac96f2969aa7b73f630259ce7f5e40e2f8edd Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:50 +0800 Subject: gpiolib-acpi: convert acpi_evaluate_object() to acpi_execute_simple_method() acpi_execute_simple_method() is a new ACPI API introduced to invoke an ACPI control method that has single integer parameter and no return value. Convert acpi_evaluate_object() to acpi_execute_simple_method() in drivers/gpio/gpiolib-acpi.c Signed-off-by: Zhang Rui CC: Linus Walleij Acked-by: Mika Westerberg Acked-by: Mathias Nyman Signed-off-by: Rafael J. Wysocki diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 5c1ef2b..f2beb72 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -73,15 +73,8 @@ static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data) { struct acpi_gpio_evt_pin *evt_pin = data; - struct acpi_object_list args; - union acpi_object arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = evt_pin->pin; - args.count = 1; - args.pointer = &arg; - - acpi_evaluate_object(evt_pin->evt_handle, NULL, &args, NULL); + acpi_execute_simple_method(evt_pin->evt_handle, NULL, evt_pin->pin); return IRQ_HANDLED; } -- cgit v0.10.2 From fca41991296444ebab32c0fc9850c62d838082f2 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:51 +0800 Subject: eeepc-laptop: convert acpi_evaluate_object() to acpi_execute_simple_method() acpi_execute_simple_method() is a new ACPI API introduced to invoke an ACPI control method that has single integer parameter and no return value. Convert acpi_evaluate_object() to acpi_execute_simple_method() in drivers/platform/x86/eeepc-laptop.c Signed-off-by: Zhang Rui CC: Matthew Garrett CC: Corentin Chary Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index a6afd41..aefcc32 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -190,16 +190,10 @@ struct eeepc_laptop { */ static int write_acpi_int(acpi_handle handle, const char *method, int val) { - struct acpi_object_list params; - union acpi_object in_obj; acpi_status status; - params.count = 1; - params.pointer = &in_obj; - in_obj.type = ACPI_TYPE_INTEGER; - in_obj.integer.value = val; + status = acpi_execute_simple_method(handle, (char *)method, val); - status = acpi_evaluate_object(handle, (char *)method, ¶ms, NULL); return (status == AE_OK ? 0 : -1); } -- cgit v0.10.2 From 6c7fe47a4a3c6e243830ba5f9c6908a38f5ee3ed Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:52 +0800 Subject: fujitsu-laptop: convert acpi_evaluate_object() to acpi_execute_simple_method() acpi_execute_simple_method() is a new ACPI API introduced to invoke an ACPI control method that has single integer parameter and no return value. Convert acpi_evaluate_object() to acpi_execute_simple_method() in drivers/platform/x86/fujitsu-laptop.c Signed-off-by: Zhang Rui CC: Matthew Garrett Acked-by: Jonathan Woithe Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 52b8a97..29738cb 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -317,8 +317,6 @@ static enum led_brightness kblamps_get(struct led_classdev *cdev) static int set_lcd_level(int level) { acpi_status status = AE_OK; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &arg0 }; acpi_handle handle = NULL; vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n", @@ -333,9 +331,8 @@ static int set_lcd_level(int level) return -ENODEV; } - arg0.integer.value = level; - status = acpi_evaluate_object(handle, NULL, &arg_list, NULL); + status = acpi_execute_simple_method(handle, NULL, level); if (ACPI_FAILURE(status)) return -ENODEV; @@ -345,8 +342,6 @@ static int set_lcd_level(int level) static int set_lcd_level_alt(int level) { acpi_status status = AE_OK; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &arg0 }; acpi_handle handle = NULL; vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBL2 [%d]\n", @@ -361,9 +356,7 @@ static int set_lcd_level_alt(int level) return -ENODEV; } - arg0.integer.value = level; - - status = acpi_evaluate_object(handle, NULL, &arg_list, NULL); + status = acpi_execute_simple_method(handle, NULL, level); if (ACPI_FAILURE(status)) return -ENODEV; -- cgit v0.10.2 From b92f7a9f94841f3f0d39127a83c8728505a82fd5 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:53 +0800 Subject: intel-rst: convert acpi_evaluate_object() to acpi_execute_simple_method() acpi_execute_simple_method() is a new ACPI API introduced to invoke an ACPI control method that has single integer parameter and no return value. Convert acpi_evaluate_object() to acpi_execute_simple_method() in drivers/platform/x86/intel-rst.c Signed-off-by: Zhang Rui CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/intel-rst.c b/drivers/platform/x86/intel-rst.c index 41b740c..c6346cc 100644 --- a/drivers/platform/x86/intel-rst.c +++ b/drivers/platform/x86/intel-rst.c @@ -54,8 +54,6 @@ static ssize_t irst_store_wakeup_events(struct device *dev, const char *buf, size_t count) { struct acpi_device *acpi; - struct acpi_object_list input; - union acpi_object param; acpi_status status; unsigned long value; int error; @@ -67,13 +65,7 @@ static ssize_t irst_store_wakeup_events(struct device *dev, if (error) return error; - param.type = ACPI_TYPE_INTEGER; - param.integer.value = value; - - input.count = 1; - input.pointer = ¶m; - - status = acpi_evaluate_object(acpi->handle, "SFFS", &input, NULL); + status = acpi_execute_simple_method(acpi->handle, "SFFS", value); if (!ACPI_SUCCESS(status)) return -EINVAL; @@ -116,8 +108,6 @@ static ssize_t irst_store_wakeup_time(struct device *dev, const char *buf, size_t count) { struct acpi_device *acpi; - struct acpi_object_list input; - union acpi_object param; acpi_status status; unsigned long value; int error; @@ -129,13 +119,7 @@ static ssize_t irst_store_wakeup_time(struct device *dev, if (error) return error; - param.type = ACPI_TYPE_INTEGER; - param.integer.value = value; - - input.count = 1; - input.pointer = ¶m; - - status = acpi_evaluate_object(acpi->handle, "SFTV", &input, NULL); + status = acpi_execute_simple_method(acpi->handle, "SFTV", value); if (!ACPI_SUCCESS(status)) return -EINVAL; -- cgit v0.10.2 From 77c39851401121046b3129de9e5aeb2fd5ef7405 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:54 +0800 Subject: intel-smartconnect: convert acpi_evaluate_object() to acpi_execute_simple_method() acpi_execute_simple_method() is a new ACPI API introduced to invoke an ACPI control method that has single integer parameter and no return value. Convert acpi_evaluate_object() to acpi_execute_simple_method() in drivers/platform/x86/intel-smartconnect.c Signed-off-by: Zhang Rui CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/intel-smartconnect.c b/drivers/platform/x86/intel-smartconnect.c index 52259dc..8984008 100644 --- a/drivers/platform/x86/intel-smartconnect.c +++ b/drivers/platform/x86/intel-smartconnect.c @@ -25,10 +25,8 @@ MODULE_LICENSE("GPL"); static int smartconnect_acpi_init(struct acpi_device *acpi) { - struct acpi_object_list input; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *result; - union acpi_object param; acpi_status status; status = acpi_evaluate_object(acpi->handle, "GAOS", NULL, &output); @@ -43,15 +41,8 @@ static int smartconnect_acpi_init(struct acpi_device *acpi) } if (result->integer.value & 0x1) { - param.type = ACPI_TYPE_INTEGER; - param.integer.value = 0; - - input.count = 1; - input.pointer = ¶m; - dev_info(&acpi->dev, "Disabling Intel Smart Connect\n"); - status = acpi_evaluate_object(acpi->handle, "SAOS", &input, - NULL); + status = acpi_execute_simple_method(acpi->handle, "SAOS", 0); } kfree(result); -- cgit v0.10.2 From a7f6451f0c78dcca2de1569edbf55fa30c9bae71 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:55 +0800 Subject: topstar-laptop: convert acpi_evaluate_object() to acpi_execute_simple_method() acpi_execute_simple_method() is a new ACPI API introduced to invoke an ACPI control method that has single integer parameter and no return value. Convert acpi_evaluate_object() to acpi_execute_simple_method() in drivers/platform/x86/topstar-laptop.c Signed-off-by: Zhang Rui CC: Herton Ronaldo Krzesinski CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index 4ab618c..67897c8 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -80,13 +80,9 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event) static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) { acpi_status status; - union acpi_object fncx_params[1] = { - { .type = ACPI_TYPE_INTEGER } - }; - struct acpi_object_list fncx_arg_list = { 1, &fncx_params[0] }; - fncx_params[0].integer.value = state ? 0x86 : 0x87; - status = acpi_evaluate_object(device->handle, "FNCX", &fncx_arg_list, NULL); + status = acpi_execute_simple_method(device->handle, "FNCX", + state ? 0x86 : 0x87); if (ACPI_FAILURE(status)) { pr_err("Unable to switch FNCX notifications\n"); return -ENODEV; -- cgit v0.10.2 From 619400dae9f2ee46ffa0a15a4a8a34a306b2aa24 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:56 +0800 Subject: toshiba_acpi: convert acpi_evaluate_object() to acpi_execute_simple_method() acpi_execute_simple_method() is a new ACPI API introduced to invoke an ACPI control method that has single integer parameter and no return value. Convert acpi_evaluate_object() to acpi_execute_simple_method() in drivers/platform/x86/toshiba_acpi.c Signed-off-by: Zhang Rui CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index eb3467e..4c0e657 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -191,16 +191,9 @@ static __inline__ void _set_bit(u32 * word, u32 mask, int value) static int write_acpi_int(const char *methodName, int val) { - struct acpi_object_list params; - union acpi_object in_objs[1]; acpi_status status; - params.count = ARRAY_SIZE(in_objs); - params.pointer = in_objs; - in_objs[0].type = ACPI_TYPE_INTEGER; - in_objs[0].integer.value = val; - - status = acpi_evaluate_object(NULL, (char *)methodName, ¶ms, NULL); + status = acpi_execute_simple_method(NULL, (char *)methodName, val); return (status == AE_OK) ? 0 : -EIO; } -- cgit v0.10.2 From 8122ab66b129678bf871aef7559640323eb465bb Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:57 +0800 Subject: wmi: convert acpi_evaluate_object() to acpi_execute_simple_method() acpi_execute_simple_method() is a new ACPI API introduced to invoke an ACPI control method that has single integer parameter and no return value. Convert acpi_evaluate_object() to acpi_execute_simple_method() in drivers/platform/x86/wmi.c Signed-off-by: Zhang Rui CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 601ea95..3bb5506 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -252,8 +252,6 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) { struct guid_block *block = NULL; char method[5]; - struct acpi_object_list input; - union acpi_object params[1]; acpi_status status; acpi_handle handle; @@ -263,13 +261,9 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) if (!block) return AE_NOT_EXIST; - input.count = 1; - input.pointer = params; - params[0].type = ACPI_TYPE_INTEGER; - params[0].integer.value = enable; snprintf(method, 5, "WE%02X", block->notify_id); - status = acpi_evaluate_object(handle, method, &input, NULL); + status = acpi_execute_simple_method(handle, method, enable); if (status != AE_OK && status != AE_NOT_FOUND) return status; @@ -355,8 +349,8 @@ struct acpi_buffer *out) struct wmi_block *wblock = NULL; acpi_handle handle, wc_handle; acpi_status status, wc_status = AE_ERROR; - struct acpi_object_list input, wc_input; - union acpi_object wc_params[1], wq_params[1]; + struct acpi_object_list input; + union acpi_object wq_params[1]; char method[5]; char wc_method[5] = "WC"; @@ -386,11 +380,6 @@ struct acpi_buffer *out) * enable collection. */ if (block->flags & ACPI_WMI_EXPENSIVE) { - wc_input.count = 1; - wc_input.pointer = wc_params; - wc_params[0].type = ACPI_TYPE_INTEGER; - wc_params[0].integer.value = 1; - strncat(wc_method, block->object_id, 2); /* @@ -400,8 +389,8 @@ struct acpi_buffer *out) */ wc_status = acpi_get_handle(handle, wc_method, &wc_handle); if (ACPI_SUCCESS(wc_status)) - wc_status = acpi_evaluate_object(handle, wc_method, - &wc_input, NULL); + wc_status = acpi_execute_simple_method(handle, + wc_method, 1); } strcpy(method, "WQ"); @@ -414,9 +403,7 @@ struct acpi_buffer *out) * the WQxx method failed - we should disable collection anyway. */ if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) { - wc_params[0].integer.value = 0; - status = acpi_evaluate_object(handle, - wc_method, &wc_input, NULL); + status = acpi_execute_simple_method(handle, wc_method, 0); } return status; -- cgit v0.10.2 From 7ca9b574915a17a588db37c5635890fe660ef7e9 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:58 +0800 Subject: pcc_freq: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/cpufreq/pcc_freq.c in this patch. Signed-off-by: Zhang Rui Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index d81c4e5..70438de 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -396,15 +396,14 @@ static int __init pcc_cpufreq_probe(void) struct pcc_memory_resource *mem_resource; struct pcc_register_resource *reg_resource; union acpi_object *out_obj, *member; - acpi_handle handle, osc_handle, pcch_handle; + acpi_handle handle, osc_handle; int ret = 0; status = acpi_get_handle(NULL, "\\_SB", &handle); if (ACPI_FAILURE(status)) return -ENODEV; - status = acpi_get_handle(handle, "PCCH", &pcch_handle); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(handle, "PCCH")) return -ENODEV; status = acpi_get_handle(handle, "_OSC", &osc_handle); -- cgit v0.10.2 From 2a3ca1429589521df49fd9348fc382c34b57a88f Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:31:59 +0800 Subject: i915: intel_acpi: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/gpu/drm/i915/intel_acpi.c in this patch. Signed-off-by: Zhang Rui Acked-by: Daniel Vetter Signed-off-by: Rafael J. Wysocki diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index 57fe1ae..43959ed 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c @@ -193,16 +193,14 @@ out: static bool intel_dsm_pci_probe(struct pci_dev *pdev) { - acpi_handle dhandle, intel_handle; - acpi_status status; + acpi_handle dhandle; int ret; dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); if (!dhandle) return false; - status = acpi_get_handle(dhandle, "_DSM", &intel_handle); - if (ACPI_FAILURE(status)) { + if (!acpi_has_method(dhandle, "_DSM")) { DRM_DEBUG_KMS("no _DSM method for intel device\n"); return false; } -- cgit v0.10.2 From 187b5b5d520c2318a1f88fb8d8913a9d7fbf7d92 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:00 +0800 Subject: nouveau_acpi: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/gpu/drm/nouveau/nouveau_acpi.c in this patch. Signed-off-by: Zhang Rui CC: Ben Skeggs CC: Dave Airlie Signed-off-by: Rafael J. Wysocki diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index dd7d2e1..cfbeee6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -253,18 +253,15 @@ static struct vga_switcheroo_handler nouveau_dsm_handler = { static int nouveau_dsm_pci_probe(struct pci_dev *pdev) { - acpi_handle dhandle, nvidia_handle; - acpi_status status; + acpi_handle dhandle; int retval = 0; dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); if (!dhandle) return false; - status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle); - if (ACPI_FAILURE(status)) { + if (!acpi_has_method(dhandle, "_DSM")) return false; - } if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) retval |= NOUVEAU_DSM_HAS_MUX; -- cgit v0.10.2 From 2fd6f9c302153ad136455a6bfb36afa97f631e41 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:01 +0800 Subject: acpi_pcihp: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/pci/hotplug/acpi_pcihp.c in this patch. Signed-off-by: Zhang Rui CC: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 2a47e82..5440131 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -411,13 +411,10 @@ EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); static int pcihp_is_ejectable(acpi_handle handle) { acpi_status status; - acpi_handle tmp; unsigned long long removable; - status = acpi_get_handle(handle, "_ADR", &tmp); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(handle, "_ADR")) return 0; - status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(handle, "_EJ0")) return 1; status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable); if (ACPI_SUCCESS(status) && removable) -- cgit v0.10.2 From be07c00e1639e6aa098d8ac5ea4d5ac58c3dbc50 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:02 +0800 Subject: pci-acpi: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/pci/pci-acpi.c in this patch. Signed-off-by: Zhang Rui CC: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index b0299e6..dfd1f59 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -181,7 +181,6 @@ static bool acpi_pci_power_manageable(struct pci_dev *dev) static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) { acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); - acpi_handle tmp; static const u8 state_conv[] = { [PCI_D0] = ACPI_STATE_D0, [PCI_D1] = ACPI_STATE_D1, @@ -192,7 +191,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) int error = -EINVAL; /* If the ACPI device has _EJ0, ignore the device */ - if (!handle || ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp))) + if (!handle || acpi_has_method(handle, "_EJ0")) return -ENODEV; switch (state) { -- cgit v0.10.2 From dd13b9a6d58d15a2cc596e1eb0baa043705c7bc8 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:03 +0800 Subject: fujitsu-laptop: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/platform/x86/fujitsu-laptop.c in this patch. Signed-off-by: Zhang Rui CC: Matthew Garrett Acked-by: Jonathan Woithe Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 29738cb..765d8c1 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -579,11 +579,10 @@ static struct platform_driver fujitsupf_driver = { static void dmi_check_cb_common(const struct dmi_system_id *id) { - acpi_handle handle; pr_info("Identified laptop model '%s'\n", id->ident); if (use_alt_lcd_levels == -1) { - if (ACPI_SUCCESS(acpi_get_handle(NULL, - "\\_SB.PCI0.LPCB.FJEX.SBL2", &handle))) + if (acpi_has_method(NULL, + "\\_SB.PCI0.LPCB.FJEX.SBL2")) use_alt_lcd_levels = 1; else use_alt_lcd_levels = 0; @@ -646,7 +645,6 @@ static struct dmi_system_id fujitsu_dmi_table[] = { static int acpi_fujitsu_add(struct acpi_device *device) { - acpi_handle handle; int result = 0; int state = 0; struct input_dev *input; @@ -695,8 +693,7 @@ static int acpi_fujitsu_add(struct acpi_device *device) fujitsu->dev = device; - if (ACPI_SUCCESS - (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) { + if (acpi_has_method(device->handle, METHOD_NAME__INI)) { vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n"); if (ACPI_FAILURE (acpi_evaluate_object @@ -796,7 +793,6 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event) static int acpi_fujitsu_hotkey_add(struct acpi_device *device) { - acpi_handle handle; int result = 0; int state = 0; struct input_dev *input; @@ -859,8 +855,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) fujitsu_hotkey->dev = device; - if (ACPI_SUCCESS - (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) { + if (acpi_has_method(device->handle, METHOD_NAME__INI)) { vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n"); if (ACPI_FAILURE (acpi_evaluate_object -- cgit v0.10.2 From 70122e3d3108d89d7d2dc0d8a11e7163a84d9d40 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:04 +0800 Subject: intel_menlow: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/platform/x86/intel_menlow.c in this patch. Signed-off-by: Zhang Rui CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c index d6cfc15..11244f8 100644 --- a/drivers/platform/x86/intel_menlow.c +++ b/drivers/platform/x86/intel_menlow.c @@ -156,19 +156,15 @@ static struct thermal_cooling_device_ops memory_cooling_ops = { static int intel_menlow_memory_add(struct acpi_device *device) { int result = -ENODEV; - acpi_status status = AE_OK; - acpi_handle dummy; struct thermal_cooling_device *cdev; if (!device) return -EINVAL; - status = acpi_get_handle(device->handle, MEMORY_GET_BANDWIDTH, &dummy); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(device->handle, MEMORY_GET_BANDWIDTH)) goto end; - status = acpi_get_handle(device->handle, MEMORY_SET_BANDWIDTH, &dummy); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(device->handle, MEMORY_SET_BANDWIDTH)) goto end; cdev = thermal_cooling_device_register("Memory controller", device, -- cgit v0.10.2 From 8a8bce1dc50c9beab55fc697230f910a9142fc3d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:05 +0800 Subject: sony-laptop: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/platform/x86/sony-laptop.c in this patch. Signed-off-by: Zhang Rui CC: Matthew Garrett CC: Mattia Dongili Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index d3fd520..3b32852d 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1509,7 +1509,6 @@ static void sony_nc_function_resume(void) static int sony_nc_resume(struct device *dev) { struct sony_nc_value *item; - acpi_handle handle; for (item = sony_nc_values; item->name; item++) { int ret; @@ -1524,15 +1523,13 @@ static int sony_nc_resume(struct device *dev) } } - if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", - &handle))) { + if (acpi_has_method(sony_nc_acpi_handle, "ECON")) { int arg = 1; if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL)) dprintk("ECON Method failed\n"); } - if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", - &handle))) + if (acpi_has_method(sony_nc_acpi_handle, "SN00")) sony_nc_function_resume(); return 0; @@ -2690,7 +2687,6 @@ static void sony_nc_backlight_ng_read_limits(int handle, static void sony_nc_backlight_setup(void) { - acpi_handle unused; int max_brightness = 0; const struct backlight_ops *ops = NULL; struct backlight_properties props; @@ -2725,8 +2721,7 @@ static void sony_nc_backlight_setup(void) sony_nc_backlight_ng_read_limits(0x14c, &sony_bl_props); max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; - } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", - &unused))) { + } else if (acpi_has_method(sony_nc_acpi_handle, "GBRT")) { ops = &sony_backlight_ops; max_brightness = SONY_MAX_BRIGHTNESS - 1; @@ -2758,7 +2753,6 @@ static int sony_nc_add(struct acpi_device *device) { acpi_status status; int result = 0; - acpi_handle handle; struct sony_nc_value *item; pr_info("%s v%s\n", SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION); @@ -2798,15 +2792,13 @@ static int sony_nc_add(struct acpi_device *device) goto outplatform; } - if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", - &handle))) { + if (acpi_has_method(sony_nc_acpi_handle, "ECON")) { int arg = 1; if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL)) dprintk("ECON Method failed\n"); } - if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", - &handle))) { + if (acpi_has_method(sony_nc_acpi_handle, "SN00")) { dprintk("Doing SNC setup\n"); /* retrieve the available handles */ result = sony_nc_handles_setup(sony_pf_device); @@ -2829,9 +2821,8 @@ static int sony_nc_add(struct acpi_device *device) /* find the available acpiget as described in the DSDT */ for (; item->acpiget && *item->acpiget; ++item->acpiget) { - if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, - *item->acpiget, - &handle))) { + if (acpi_has_method(sony_nc_acpi_handle, + *item->acpiget)) { dprintk("Found %s getter: %s\n", item->name, *item->acpiget); item->devattr.attr.mode |= S_IRUGO; @@ -2841,9 +2832,8 @@ static int sony_nc_add(struct acpi_device *device) /* find the available acpiset as described in the DSDT */ for (; item->acpiset && *item->acpiset; ++item->acpiset) { - if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, - *item->acpiset, - &handle))) { + if (acpi_has_method(sony_nc_acpi_handle, + *item->acpiset)) { dprintk("Found %s setter: %s\n", item->name, *item->acpiset); item->devattr.attr.mode |= S_IWUSR; -- cgit v0.10.2 From e2e196069fd68fcf8c20fd478f8b683e5403e575 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:06 +0800 Subject: toshiba_acpi: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/platform/x86/toshiba_acpi.c in this patch. Signed-off-by: Zhang Rui CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 4c0e657..235185b 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -974,7 +974,7 @@ static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev, static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) { acpi_status status; - acpi_handle ec_handle, handle; + acpi_handle ec_handle; int error; u32 hci_result; @@ -1001,10 +1001,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) */ status = AE_ERROR; ec_handle = ec_get_handle(); - if (ec_handle) - status = acpi_get_handle(ec_handle, "NTFY", &handle); - - if (ACPI_SUCCESS(status)) { + if (ec_handle && acpi_has_method(ec_handle, "NTFY")) { INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work); error = i8042_install_filter(toshiba_acpi_i8042_filter); @@ -1020,10 +1017,9 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) * Determine hotkey query interface. Prefer using the INFO * method when it is available. */ - status = acpi_get_handle(dev->acpi_dev->handle, "INFO", &handle); - if (ACPI_SUCCESS(status)) { + if (acpi_has_method(dev->acpi_dev->handle, "INFO")) dev->info_supported = 1; - } else { + else { hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); if (hci_result == HCI_SUCCESS) dev->system_event_supported = 1; @@ -1148,15 +1144,10 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev) static const char *find_hci_method(acpi_handle handle) { - acpi_status status; - acpi_handle hci_handle; - - status = acpi_get_handle(handle, "GHCI", &hci_handle); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(handle, "GHCI")) return "GHCI"; - status = acpi_get_handle(handle, "SPFC", &hci_handle); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(handle, "SPFC")) return "SPFC"; return NULL; -- cgit v0.10.2 From 54f14c277d78cd4fee860f5daf391a5759f8596f Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:07 +0800 Subject: wmi: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/platform/x86/wmi.c in this patch. Signed-off-by: Zhang Rui CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 3bb5506..62e8c22 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -347,7 +347,7 @@ struct acpi_buffer *out) { struct guid_block *block = NULL; struct wmi_block *wblock = NULL; - acpi_handle handle, wc_handle; + acpi_handle handle; acpi_status status, wc_status = AE_ERROR; struct acpi_object_list input; union acpi_object wq_params[1]; @@ -387,8 +387,7 @@ struct acpi_buffer *out) * expensive, but have no corresponding WCxx method. So we * should not fail if this happens. */ - wc_status = acpi_get_handle(handle, wc_method, &wc_handle); - if (ACPI_SUCCESS(wc_status)) + if (acpi_has_method(handle, wc_method)) wc_status = acpi_execute_simple_method(handle, wc_method, 1); } -- cgit v0.10.2 From 0e77e2c416e8fa110fa0e749db0ae1e9344b6050 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:08 +0800 Subject: pnpacpi: convert acpi_get_handle() to acpi_has_method() acpi_has_method() is a new ACPI API introduced to check the existence of an ACPI control method. It can be used to replace acpi_get_handle() in the case that 1. the calling function doesn't need the ACPI handle of the control method. and 2. the calling function doesn't care the reason why the method is unavailable. Convert acpi_get_handle() to acpi_has_method() in drivers/pnp/pnpacpi/core.c in this patch. Signed-off-by: Zhang Rui CC: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 34049b0..747826d 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -239,8 +239,6 @@ static char *__init pnpacpi_get_id(struct acpi_device *device) static int __init pnpacpi_add_device(struct acpi_device *device) { - acpi_handle temp = NULL; - acpi_status status; struct pnp_dev *dev; char *pnpid; struct acpi_hardware_id *id; @@ -253,8 +251,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) * If a PnPacpi device is not present , the device * driver should not be loaded. */ - status = acpi_get_handle(device->handle, "_CRS", &temp); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(device->handle, "_CRS")) return 0; pnpid = pnpacpi_get_id(device); @@ -271,16 +268,14 @@ static int __init pnpacpi_add_device(struct acpi_device *device) dev->data = device; /* .enabled means the device can decode the resources */ dev->active = device->status.enabled; - status = acpi_get_handle(device->handle, "_SRS", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_SRS")) dev->capabilities |= PNP_CONFIGURABLE; dev->capabilities |= PNP_READ; if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE)) dev->capabilities |= PNP_WRITE; if (device->flags.removable) dev->capabilities |= PNP_REMOVABLE; - status = acpi_get_handle(device->handle, "_DIS", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_DIS")) dev->capabilities |= PNP_DISABLE; if (strlen(acpi_device_name(device))) -- cgit v0.10.2 From 6ebb5bc9e61be4315202c15a0f53f636e8f0bf2e Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:09 +0800 Subject: acpi_processor: convert acpi_evaluate_object() to acpi_evaluate_integer() acpi_evaluate_integer() is an ACPI API introduced to evaluate an ACPI control method that is known to have an integer return value. This API can simplify the code because the calling function does not need to use the specified acpi_buffer structure required by acpi_evaluate_object(); Convert acpi_evaluate_object() to acpi_evaluate_integer() in drivers/acpi/acpi_processor.c in this patch. Signed-off-by: Zhang Rui Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f29e06e..357abdc 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -219,6 +219,7 @@ static int acpi_processor_get_info(struct acpi_device *device) int cpu_index, device_declaration = 0; acpi_status status = AE_OK; static int cpu0_initialized; + unsigned long long value; if (num_online_cpus() > 1) errata.smp = TRUE; @@ -258,7 +259,6 @@ static int acpi_processor_get_info(struct acpi_device *device) * Declared with "Device" statement; match _UID. * Note that we don't handle string _UIDs yet. */ - unsigned long long value; status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, NULL, &value); if (ACPI_FAILURE(status)) { @@ -332,9 +332,9 @@ static int acpi_processor_get_info(struct acpi_device *device) * ensure we get the right value in the "physical id" field * of /proc/cpuinfo */ - status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer); + status = acpi_evaluate_integer(pr->handle, "_SUN", NULL, &value); if (ACPI_SUCCESS(status)) - arch_fix_phys_package_id(pr->id, object.integer.value); + arch_fix_phys_package_id(pr->id, value); return 0; } -- cgit v0.10.2 From 6a868e171c3800442f59b74ec1e0eaf7d858eb58 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:10 +0800 Subject: ACPI: dock: convert acpi_evaluate_object() to acpi_evaluate_integer() acpi_evaluate_integer() is an ACPI API introduced to evaluate an ACPI control method that is known to have an integer return value. This API can simplify the code because the calling function does not need to use the specified acpi_buffer structure required by acpi_evaluate_object(); Convert acpi_evaluate_object() to acpi_evaluate_integer() in drivers/acpi/dock.c in this patch. Signed-off-by: Zhang Rui Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 05ea4be..ca86c1c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -441,7 +441,7 @@ static void handle_dock(struct dock_station *ds, int dock) acpi_status status; struct acpi_object_list arg_list; union acpi_object arg; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + unsigned long long value; acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking"); @@ -450,12 +450,10 @@ static void handle_dock(struct dock_station *ds, int dock) arg_list.pointer = &arg; arg.type = ACPI_TYPE_INTEGER; arg.integer.value = dock; - status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); + status = acpi_evaluate_integer(ds->handle, "_DCK", &arg_list, &value); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n", status); - - kfree(buffer.pointer); } static inline void dock(struct dock_station *ds) -- cgit v0.10.2 From 74da276028966f333acc97b59292f928c16c1709 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:11 +0800 Subject: i2c-hid: convert acpi_evaluate_object() to acpi_evaluate_integer() acpi_evaluate_integer() is an ACPI API introduced to evaluate an ACPI control method that is known to have an integer return value. This API can simplify the code because the calling function does not need to use the specified acpi_buffer structure required by acpi_evaluate_object(); Convert acpi_evaluate_object() to acpi_evaluate_integer() in drivers/hid/i2c-hid/i2c-hid.c in this patch. Signed-off-by: Zhang Rui Acked-by: Jiri Kosina Acked-by: Benjamin Tissoires Signed-off-by: Rafael J. Wysocki diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index c133619..fd7ce37 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -854,10 +854,10 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client, 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45, 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE, }; - struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object params[4], *obj; + union acpi_object params[4]; struct acpi_object_list input; struct acpi_device *adev; + unsigned long long value; acpi_handle handle; handle = ACPI_HANDLE(&client->dev); @@ -878,22 +878,14 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client, params[3].package.count = 0; params[3].package.elements = NULL; - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf))) { + if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_DSM", &input, + &value))) { dev_err(&client->dev, "device _DSM execution failed\n"); return -ENODEV; } - obj = (union acpi_object *)buf.pointer; - if (obj->type != ACPI_TYPE_INTEGER) { - dev_err(&client->dev, "device _DSM returned invalid type: %d\n", - obj->type); - kfree(buf.pointer); - return -EINVAL; - } - - pdata->hid_descriptor_address = obj->integer.value; + pdata->hid_descriptor_address = value; - kfree(buf.pointer); return 0; } -- cgit v0.10.2 From 29c29a9bb4d5abdb92480375e42e48a9190306e8 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:12 +0800 Subject: fujitsu-laptop: convert acpi_evaluate_object() to acpi_evaluate_integer() acpi_evaluate_integer() is an ACPI API introduced to evaluate an ACPI control method that is known to have an integer return value. This API can simplify the code because the calling function does not need to use the specified acpi_buffer structure required by acpi_evaluate_object(); Convert acpi_evaluate_object() to acpi_evaluate_integer() in drivers/platform/x86/fujitsu-laptop.c in this patch. Signed-off-by: Zhang Rui CC: Matthew Garrett Acked-by: Jonathan Woithe Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 765d8c1..9d30d69 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -219,8 +219,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2) { .type = ACPI_TYPE_INTEGER } }; struct acpi_object_list arg_list = { 4, ¶ms[0] }; - struct acpi_buffer output; - union acpi_object out_obj; + unsigned long long value; acpi_handle handle = NULL; status = acpi_get_handle(fujitsu_hotkey->acpi_handle, "FUNC", &handle); @@ -235,10 +234,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2) params[2].integer.value = arg1; params[3].integer.value = arg2; - output.length = sizeof(out_obj); - output.pointer = &out_obj; - - status = acpi_evaluate_object(handle, NULL, &arg_list, &output); + status = acpi_evaluate_integer(handle, NULL, &arg_list, &value); if (ACPI_FAILURE(status)) { vdbg_printk(FUJLAPTOP_DBG_WARN, "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n", @@ -246,18 +242,10 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2) return -ENODEV; } - if (out_obj.type != ACPI_TYPE_INTEGER) { - vdbg_printk(FUJLAPTOP_DBG_WARN, - "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) did not " - "return an integer\n", - cmd, arg0, arg1, arg2); - return -ENODEV; - } - vdbg_printk(FUJLAPTOP_DBG_TRACE, "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n", - cmd, arg0, arg1, arg2, (int)out_obj.integer.value); - return out_obj.integer.value; + cmd, arg0, arg1, arg2, (int)value); + return value; } #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) -- cgit v0.10.2 From c7c878a41d8b087f292015d4afeb2950a5d28830 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:13 +0800 Subject: intel-rst: convert acpi_evaluate_object() to acpi_evaluate_integer() acpi_evaluate_integer() is an ACPI API introduced to evaluate an ACPI control method that is known to have an integer return value. This API can simplify the code because the calling function does not need to use the specified acpi_buffer structure required by acpi_evaluate_object(); Convert acpi_evaluate_object() to acpi_evaluate_integer() in drivers/platform/x86/intel-rst.c in this patch. Plus, this should also fix a memory leak that the acpi_buffer is not freed in some cases. Signed-off-by: Zhang Rui CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/intel-rst.c b/drivers/platform/x86/intel-rst.c index c6346cc..a2083a9 100644 --- a/drivers/platform/x86/intel-rst.c +++ b/drivers/platform/x86/intel-rst.c @@ -29,24 +29,16 @@ static ssize_t irst_show_wakeup_events(struct device *dev, char *buf) { struct acpi_device *acpi; - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *result; + unsigned long long value; acpi_status status; acpi = to_acpi_device(dev); - status = acpi_evaluate_object(acpi->handle, "GFFS", NULL, &output); + status = acpi_evaluate_integer(acpi->handle, "GFFS", NULL, &value); if (!ACPI_SUCCESS(status)) return -EINVAL; - result = output.pointer; - - if (result->type != ACPI_TYPE_INTEGER) { - kfree(result); - return -EINVAL; - } - - return sprintf(buf, "%lld\n", result->integer.value); + return sprintf(buf, "%lld\n", value); } static ssize_t irst_store_wakeup_events(struct device *dev, @@ -83,24 +75,16 @@ static ssize_t irst_show_wakeup_time(struct device *dev, struct device_attribute *attr, char *buf) { struct acpi_device *acpi; - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *result; + unsigned long long value; acpi_status status; acpi = to_acpi_device(dev); - status = acpi_evaluate_object(acpi->handle, "GFTV", NULL, &output); + status = acpi_evaluate_integer(acpi->handle, "GFTV", NULL, &value); if (!ACPI_SUCCESS(status)) return -EINVAL; - result = output.pointer; - - if (result->type != ACPI_TYPE_INTEGER) { - kfree(result); - return -EINVAL; - } - - return sprintf(buf, "%lld\n", result->integer.value); + return sprintf(buf, "%lld\n", value); } static ssize_t irst_store_wakeup_time(struct device *dev, -- cgit v0.10.2 From 4a2d6f6637d59bafa8be5cd4c323684224422ef1 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:14 +0800 Subject: intel-smartconnect: convert acpi_evaluate_object() to acpi_evaluate_integer() acpi_evaluate_integer() is an ACPI API introduced to evaluate an ACPI control method that is known to have an integer return value. This API can simplify the code because the calling function does not need to use the specified acpi_buffer structure required by acpi_evaluate_object(); Convert acpi_evaluate_object() to acpi_evaluate_integer() in drivers/platform/x86/intel-smartconnect.c in this patch. Signed-off-by: Zhang Rui CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/intel-smartconnect.c b/drivers/platform/x86/intel-smartconnect.c index 8984008..1838400 100644 --- a/drivers/platform/x86/intel-smartconnect.c +++ b/drivers/platform/x86/intel-smartconnect.c @@ -25,28 +25,18 @@ MODULE_LICENSE("GPL"); static int smartconnect_acpi_init(struct acpi_device *acpi) { - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *result; + unsigned long long value; acpi_status status; - status = acpi_evaluate_object(acpi->handle, "GAOS", NULL, &output); + status = acpi_evaluate_integer(acpi->handle, "GAOS", NULL, &value); if (!ACPI_SUCCESS(status)) return -EINVAL; - result = output.pointer; - - if (result->type != ACPI_TYPE_INTEGER) { - kfree(result); - return -EINVAL; - } - - if (result->integer.value & 0x1) { + if (value & 0x1) { dev_info(&acpi->dev, "Disabling Intel Smart Connect\n"); status = acpi_execute_simple_method(acpi->handle, "SAOS", 0); } - kfree(result); - return 0; } -- cgit v0.10.2 From 74facaf75d3de2dd81193d907d0bee050c259f0c Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 3 Sep 2013 08:32:15 +0800 Subject: toshiba_acpi: convert acpi_evaluate_object() to acpi_evaluate_integer() acpi_evaluate_integer() is an ACPI API introduced to evaluate an ACPI control method that is known to have an integer return value. This API can simplify the code because the calling function does not need to use the specified acpi_buffer structure required by acpi_evaluate_object(); Convert acpi_evaluate_object() to acpi_evaluate_integer() in drivers/platform/x86/toshiba_acpi.c in this patch. Signed-off-by: Zhang Rui CC: Matthew Garrett Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 235185b..0cfadb6 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -940,21 +940,17 @@ static void toshiba_acpi_hotkey_work(struct work_struct *work) */ static int toshiba_acpi_query_hotkey(struct toshiba_acpi_dev *dev) { - struct acpi_buffer buf; - union acpi_object out_obj; + unsigned long long value; acpi_status status; - buf.pointer = &out_obj; - buf.length = sizeof(out_obj); - - status = acpi_evaluate_object(dev->acpi_dev->handle, "INFO", - NULL, &buf); - if (ACPI_FAILURE(status) || out_obj.type != ACPI_TYPE_INTEGER) { + status = acpi_evaluate_integer(dev->acpi_dev->handle, "INFO", + NULL, &value); + if (ACPI_FAILURE(status)) { pr_err("ACPI INFO method execution failed\n"); return -EIO; } - return out_obj.integer.value; + return value; } static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev, -- cgit v0.10.2 From ca9f62ac783bf88c54143f8065adc0fc8df859c1 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Sep 2013 11:57:34 +0800 Subject: ACPI / processor: Introduce apic_id in struct processor to save parsed APIC id For cpu hot add, we evaluate _MAT or parse MADT twice to get APIC id, here is the code logic: acpi_processor_add() acpi_processor_get_info() acpi_get_cpuid() will evaluate _MAT or parse MADT; acpi_processor_hotadd_init() acpi_map_lsapic() will evaluate _MAT again; This can be done more effectively, this patch introduces apic_id in struct processor to save parsed APIC id, and then we can use it and remove the duplicated _MAT evaluation. Signed-off-by: Jiang Liu Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f29e06e..f89f914 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -270,7 +270,9 @@ static int acpi_processor_get_info(struct acpi_device *device) device_declaration = 1; pr->acpi_id = value; } - cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id); + pr->apic_id = acpi_get_apicid(pr->handle, device_declaration, + pr->acpi_id); + cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id); /* Handle UP system running SMP kernel, with no LAPIC in MADT */ if (!cpu0_initialized && (cpu_index == -1) && diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index cf34d90..b3171f3 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -162,16 +162,23 @@ exit: return apic_id; } -int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) +int acpi_get_apicid(acpi_handle handle, int type, u32 acpi_id) { -#ifdef CONFIG_SMP - int i; -#endif - int apic_id = -1; + int apic_id; apic_id = map_mat_entry(handle, type, acpi_id); if (apic_id == -1) apic_id = map_madt_entry(type, acpi_id); + + return apic_id; +} + +int acpi_map_cpuid(int apic_id, u32 acpi_id) +{ +#ifdef CONFIG_SMP + int i; +#endif + if (apic_id == -1) { /* * On UP processor, there is no _MAT or MADT table. @@ -211,6 +218,15 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) #endif return -1; } + +int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) +{ + int apic_id; + + apic_id = acpi_get_apicid(handle, type, acpi_id); + + return acpi_map_cpuid(apic_id, acpi_id); +} EXPORT_SYMBOL_GPL(acpi_get_cpuid); static bool __init processor_physically_present(acpi_handle handle) diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 66096d0..7816e45 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -199,6 +199,7 @@ struct acpi_processor_flags { struct acpi_processor { acpi_handle handle; u32 acpi_id; + u32 apic_id; u32 id; u32 pblk; int performance_platform_limit; @@ -314,6 +315,8 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) /* in processor_core.c */ void acpi_processor_set_pdc(acpi_handle handle); +int acpi_get_apicid(acpi_handle, int type, u32 acpi_id); +int acpi_map_cpuid(int apic_id, u32 acpi_id); int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id); /* in processor_throttling.c */ -- cgit v0.10.2 From d536bf3dc97417471e2c5098837a1cddd7fbb3c7 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Sep 2013 11:57:35 +0800 Subject: ACPI / processor: use apic_id and remove duplicated _MAT evaluation Since APIC id is saved in processor struct, just use it and remove the duplicated _MAT evaluation. Signed-off-by: Jiang Liu Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 5eb71d2..59d52e3 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -882,40 +882,10 @@ __init void prefill_possible_map(void) set_cpu_possible(i, true); } -static int _acpi_map_lsapic(acpi_handle handle, int *pcpu) +static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) { - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - struct acpi_madt_local_sapic *lsapic; cpumask_t tmp_map; - int cpu, physid; - - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) - return -EINVAL; - - if (!buffer.length || !buffer.pointer) - return -EINVAL; - - obj = buffer.pointer; - if (obj->type != ACPI_TYPE_BUFFER) - { - kfree(buffer.pointer); - return -EINVAL; - } - - lsapic = (struct acpi_madt_local_sapic *)obj->buffer.pointer; - - if ((lsapic->header.type != ACPI_MADT_TYPE_LOCAL_SAPIC) || - (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))) { - kfree(buffer.pointer); - return -EINVAL; - } - - physid = ((lsapic->id << 8) | (lsapic->eid)); - - kfree(buffer.pointer); - buffer.length = ACPI_ALLOCATE_BUFFER; - buffer.pointer = NULL; + int cpu; cpumask_complement(&tmp_map, cpu_present_mask); cpu = cpumask_first(&tmp_map); @@ -934,9 +904,9 @@ static int _acpi_map_lsapic(acpi_handle handle, int *pcpu) } /* wrapper to silence section mismatch warning */ -int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu) +int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) { - return _acpi_map_lsapic(handle, pcpu); + return _acpi_map_lsapic(handle, physid, pcpu); } EXPORT_SYMBOL(acpi_map_lsapic); diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 40c7660..f6dbb2f 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -614,44 +614,12 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) #endif } -static int _acpi_map_lsapic(acpi_handle handle, int *pcpu) +static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) { - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - struct acpi_madt_local_apic *lapic; cpumask_var_t tmp_map, new_map; - u8 physid; int cpu; int retval = -ENOMEM; - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) - return -EINVAL; - - if (!buffer.length || !buffer.pointer) - return -EINVAL; - - obj = buffer.pointer; - if (obj->type != ACPI_TYPE_BUFFER || - obj->buffer.length < sizeof(*lapic)) { - kfree(buffer.pointer); - return -EINVAL; - } - - lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer; - - if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC || - !(lapic->lapic_flags & ACPI_MADT_ENABLED)) { - kfree(buffer.pointer); - return -EINVAL; - } - - physid = lapic->id; - - kfree(buffer.pointer); - buffer.length = ACPI_ALLOCATE_BUFFER; - buffer.pointer = NULL; - lapic = NULL; - if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL)) goto out; @@ -689,9 +657,9 @@ out: } /* wrapper to silence section mismatch warning */ -int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu) +int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) { - return _acpi_map_lsapic(handle, pcpu); + return _acpi_map_lsapic(handle, physid, pcpu); } EXPORT_SYMBOL(acpi_map_lsapic); diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f89f914..66c9b70 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -181,7 +181,7 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr) cpu_maps_update_begin(); cpu_hotplug_begin(); - ret = acpi_map_lsapic(pr->handle, &pr->id); + ret = acpi_map_lsapic(pr->handle, pr->apic_id, &pr->id); if (ret) goto out; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index a5db4ae..3bc7414 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -116,7 +116,7 @@ void acpi_numa_arch_fixup(void); #ifdef CONFIG_ACPI_HOTPLUG_CPU /* Arch dependent functions for cpu hotplug support */ -int acpi_map_lsapic(acpi_handle handle, int *pcpu); +int acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu); int acpi_unmap_lsapic(int cpu); #endif /* CONFIG_ACPI_HOTPLUG_CPU */ -- cgit v0.10.2 From 7e1f85f96def9453ac5322329503e6d43c5ecd01 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Sep 2013 11:57:36 +0800 Subject: x86 / ACPI: simplify _acpi_map_lsapic() In acpi_register_lapic(), it will generates a new logical cpu number and maps to the local APIC id, this logical cpu number can be returned to simplify _acpi_map_lsapic() implementation. Signed-off-by: Jiang Liu Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 626cf70..3142a94 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -94,7 +94,7 @@ static inline void early_reserve_e820_mpc_new(void) { } #define default_get_smp_config x86_init_uint_noop #endif -void generic_processor_info(int apicid, int version); +int generic_processor_info(int apicid, int version); #ifdef CONFIG_ACPI extern void mp_register_ioapic(int id, u32 address, u32 gsi_base); extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index f6dbb2f..1f7c074 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -189,24 +189,31 @@ static int __init acpi_parse_madt(struct acpi_table_header *table) return 0; } -static void acpi_register_lapic(int id, u8 enabled) +/** + * acpi_register_lapic - register a local apic and generates a logic cpu number + * @id: local apic id to register + * @enabled: this cpu is enabled or not + * + * Returns the logic cpu number which maps to the local apic + */ +static int acpi_register_lapic(int id, u8 enabled) { unsigned int ver = 0; if (id >= MAX_LOCAL_APIC) { printk(KERN_INFO PREFIX "skipped apicid that is too big\n"); - return; + return -EINVAL; } if (!enabled) { ++disabled_cpus; - return; + return -EINVAL; } if (boot_cpu_physical_apicid != -1U) ver = apic_version[boot_cpu_physical_apicid]; - generic_processor_info(id, ver); + return generic_processor_info(id, ver); } static int __init @@ -616,44 +623,19 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) { - cpumask_var_t tmp_map, new_map; int cpu; - int retval = -ENOMEM; - - if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL)) - goto out; - if (!alloc_cpumask_var(&new_map, GFP_KERNEL)) - goto free_tmp_map; - - cpumask_copy(tmp_map, cpu_present_mask); - acpi_register_lapic(physid, ACPI_MADT_ENABLED); - - /* - * If acpi_register_lapic successfully generates a new logical cpu - * number, then the following will get us exactly what was mapped - */ - cpumask_andnot(new_map, cpu_present_mask, tmp_map); - if (cpumask_empty(new_map)) { - printk ("Unable to map lapic to logical cpu number\n"); - retval = -EINVAL; - goto free_new_map; + cpu = acpi_register_lapic(physid, ACPI_MADT_ENABLED); + if (cpu < 0) { + pr_info(PREFIX "Unable to map lapic to logical cpu number\n"); + return cpu; } acpi_processor_set_pdc(handle); - - cpu = cpumask_first(new_map); acpi_map_cpu2node(handle, cpu, physid); *pcpu = cpu; - retval = 0; - -free_new_map: - free_cpumask_var(new_map); -free_tmp_map: - free_cpumask_var(tmp_map); -out: - return retval; + return 0; } /* wrapper to silence section mismatch warning */ diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index a7eb82d..ed165d6 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -2107,7 +2107,7 @@ void disconnect_bsp_APIC(int virt_wire_setup) apic_write(APIC_LVT1, value); } -void generic_processor_info(int apicid, int version) +int generic_processor_info(int apicid, int version) { int cpu, max = nr_cpu_ids; bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid, @@ -2127,7 +2127,7 @@ void generic_processor_info(int apicid, int version) " Processor %d/0x%x ignored.\n", max, thiscpu, apicid); disabled_cpus++; - return; + return -ENODEV; } if (num_processors >= nr_cpu_ids) { @@ -2138,7 +2138,7 @@ void generic_processor_info(int apicid, int version) " Processor %d/0x%x ignored.\n", max, thiscpu, apicid); disabled_cpus++; - return; + return -EINVAL; } num_processors++; @@ -2183,6 +2183,8 @@ void generic_processor_info(int apicid, int version) #endif set_cpu_possible(cpu, true); set_cpu_present(cpu, true); + + return cpu; } int hard_smp_processor_id(void) -- cgit v0.10.2 From 2d4d3e2a06bd25fba52a4693b09ec72d61d250d9 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Sep 2013 11:57:37 +0800 Subject: ACPI / processor: remove some dead code in acpi_processor_get_info() errata.smp is used by nowhere, so the variable assignment is meanless, remove it. Signed-off-by: Jiang Liu Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 66c9b70..5364d02 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -220,9 +220,6 @@ static int acpi_processor_get_info(struct acpi_device *device) acpi_status status = AE_OK; static int cpu0_initialized; - if (num_online_cpus() > 1) - errata.smp = TRUE; - acpi_processor_errata(pr); /* -- cgit v0.10.2 From 082e12a05cf317acec2feaf3a78de3f3372feeb3 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Mon, 2 Sep 2013 11:57:38 +0800 Subject: ACPI / processor: remove unnecessary if (!pr) check acpi_processor_errata() is only called in acpi_processor_get_info(), and the argument 'pr' passed to acpi_processor_errata() will never be NULL, so the if (!pr) check is unnecessary and can be removed. Since the 'pr' argument is not used by acpi_processor_errata() any more, so change the argument into void too. Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 5364d02..7ce0750 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -140,15 +140,11 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev) return 0; } -static int acpi_processor_errata(struct acpi_processor *pr) +static int acpi_processor_errata(void) { int result = 0; struct pci_dev *dev = NULL; - - if (!pr) - return -EINVAL; - /* * PIIX4 */ @@ -220,7 +216,7 @@ static int acpi_processor_get_info(struct acpi_device *device) acpi_status status = AE_OK; static int cpu0_initialized; - acpi_processor_errata(pr); + acpi_processor_errata(); /* * Check to see if we have bus mastering arbitration control. This -- cgit v0.10.2 From 7cc34680c1ab418d5c7fd0f9621515b7a0aa1d66 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Mon, 2 Sep 2013 11:57:39 +0800 Subject: ACPI / processor: Remove outdated comments acpi_get_processor_id() can be find nowhere, and the acpi id is synchronized to APIC id when acpi_get_cpuid() is called, so the comments can be removed. Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 7ce0750..da42892 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -240,11 +240,6 @@ static int acpi_processor_get_info(struct acpi_device *device) return -ENODEV; } - /* - * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. - * >>> 'acpi_get_processor_id(acpi_id, &id)' in - * arch/xxx/acpi.c - */ pr->acpi_id = object.processor.proc_id; } else { /* -- cgit v0.10.2 From 1bb25df0fde2cdb2f250a7e7e43c2ec1ba65d0f5 Mon Sep 17 00:00:00 2001 From: Jianguo Wu Date: Fri, 30 Aug 2013 09:25:40 +0800 Subject: ACPI / mm: use NUMA_NO_NODE Use more appropriate NUMA_NO_NODE instead of -1 Signed-off-by: Jianguo Wu Acked-by: David Rientjes Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 999adb5..c00a3a7 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -281,7 +281,7 @@ static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device) if (!info->enabled) continue; - if (nid < 0) + if (nid == NUMA_NO_NODE) nid = memory_add_physaddr_to_nid(info->start_addr); acpi_unbind_memory_blocks(info, handle); diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 2e82e5d..a2343a1 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -73,7 +73,7 @@ int acpi_map_pxm_to_node(int pxm) { int node = pxm_to_node_map[pxm]; - if (node < 0) { + if (node == NUMA_NO_NODE) { if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) return NUMA_NO_NODE; node = first_unset_node(nodes_found_map); @@ -334,7 +334,7 @@ int acpi_get_pxm(acpi_handle h) int acpi_get_node(acpi_handle *handle) { - int pxm, node = -1; + int pxm, node = NUMA_NO_NODE; pxm = acpi_get_pxm(handle); if (pxm >= 0 && pxm < MAX_PXM_DOMAINS) -- cgit v0.10.2 From bf9b59f2571d0d0470f904842a283ac7957438cd Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 30 Aug 2013 12:30:51 +0200 Subject: ACPI / processor: remove superfluous pr == NULL checks The only acpi_processor_get_power_info_fadt() user (acpi_processor_get_power_info()) dereferences pr before calling the function. The only acpi_processor_hotplug() user (acpi_cpu_soft_notify()) checks for pr == NULL before calling the function. The only acpi_processor_cst_has_changed() user (acpi_processor_notify()) checks for pr == NULL before calling the function. The only acpi_processor_power_init() user (__acpi_processor_start()) dereferences pr before calling the function. Thus remove superfluous pr == NULL checks from affected functions. Also: While at it remove redundant brackets from acpi_processor_hotplug(). Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f98dd00..35c8f2b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -272,9 +272,6 @@ static void tsc_check_state(int state) { return; } static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) { - if (!pr) - return -EINVAL; - if (!pr->pblk) return -ENODEV; @@ -1076,12 +1073,8 @@ int acpi_processor_hotplug(struct acpi_processor *pr) if (disabled_by_idle_boot_param()) return 0; - if (!pr) - return -EINVAL; - - if (nocst) { + if (nocst) return -ENODEV; - } if (!pr->flags.power_setup_done) return -ENODEV; @@ -1108,9 +1101,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) if (disabled_by_idle_boot_param()) return 0; - if (!pr) - return -EINVAL; - if (nocst) return -ENODEV; @@ -1183,9 +1173,6 @@ int acpi_processor_power_init(struct acpi_processor *pr) first_run++; } - if (!pr) - return -EINVAL; - if (acpi_gbl_FADT.cst_control && !nocst) { status = acpi_os_write_port(acpi_gbl_FADT.smi_command, acpi_gbl_FADT.cst_control, 8); -- cgit v0.10.2 From 568b6ad834e90351f1a1e6e6cf93bf0e0d8a0eae Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Fri, 30 Aug 2013 16:16:05 -0500 Subject: ACP / fan: trivial style cleanup Remove label indentation in acpi_fan_add(). Signed-off-by: Felipe Contreras Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 41ade65..ba3da88 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -168,7 +168,7 @@ static int acpi_fan_add(struct acpi_device *device) acpi_device_name(device), acpi_device_bid(device), !device->power.state ? "on" : "off"); - end: +end: return result; } -- cgit v0.10.2 From eba682a5aeb6c9bf08a9751f8d3ecafe043d8f88 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 30 Aug 2013 12:25:10 +0200 Subject: intel_idle: shrink states tables There is no reason to define CPUIDLE_STATE_MAX (currently 10) entries in states tables if the driver always stops iterating over table when it encounters first .enter == NULL entry. $ size drivers/idle/intel_idle.o.* text data bss dec hex filename 2886 5440 32 8358 20a6 drivers/idle/intel_idle.o.before 2886 3752 32 6670 1a0e drivers/idle/intel_idle.o.after Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index fa6964d..9c97fbb42 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -123,7 +123,7 @@ static struct cpuidle_state *cpuidle_state_table; * which is also the index into the MWAIT hint array. * Thus C0 is a dummy. */ -static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = { +static struct cpuidle_state nehalem_cstates[] = { { .name = "C1-NHM", .desc = "MWAIT 0x00", @@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = { .enter = NULL } }; -static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = { +static struct cpuidle_state snb_cstates[] = { { .name = "C1-SNB", .desc = "MWAIT 0x00", @@ -196,7 +196,7 @@ static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = { .enter = NULL } }; -static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = { +static struct cpuidle_state ivb_cstates[] = { { .name = "C1-IVB", .desc = "MWAIT 0x00", @@ -236,7 +236,7 @@ static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = { .enter = NULL } }; -static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = { +static struct cpuidle_state hsw_cstates[] = { { .name = "C1-HSW", .desc = "MWAIT 0x00", @@ -297,7 +297,7 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = { .enter = NULL } }; -static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = { +static struct cpuidle_state atom_cstates[] = { { .name = "C1E-ATM", .desc = "MWAIT 0x00", @@ -628,7 +628,7 @@ static int intel_idle_cpu_init(int cpu) int num_substates, mwait_hint, mwait_cstate, mwait_substate; if (cpuidle_state_table[cstate].enter == NULL) - continue; + break; if (cstate + 1 > max_cstate) { printk(PREFIX "max_cstate %d reached\n", max_cstate); -- cgit v0.10.2 From 9d046ccb98085f1d437585f84748c783a04ba240 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 30 Aug 2013 12:26:42 +0200 Subject: intel_idle: mark states tables with __initdata tag States tables are only accessed during driver initialization so they can be marked with __initdata tag. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Reviewed-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 9c97fbb42..53b24f1 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -123,7 +123,7 @@ static struct cpuidle_state *cpuidle_state_table; * which is also the index into the MWAIT hint array. * Thus C0 is a dummy. */ -static struct cpuidle_state nehalem_cstates[] = { +static struct cpuidle_state nehalem_cstates[] __initdata = { { .name = "C1-NHM", .desc = "MWAIT 0x00", @@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[] = { .enter = NULL } }; -static struct cpuidle_state snb_cstates[] = { +static struct cpuidle_state snb_cstates[] __initdata = { { .name = "C1-SNB", .desc = "MWAIT 0x00", @@ -196,7 +196,7 @@ static struct cpuidle_state snb_cstates[] = { .enter = NULL } }; -static struct cpuidle_state ivb_cstates[] = { +static struct cpuidle_state ivb_cstates[] __initdata = { { .name = "C1-IVB", .desc = "MWAIT 0x00", @@ -236,7 +236,7 @@ static struct cpuidle_state ivb_cstates[] = { .enter = NULL } }; -static struct cpuidle_state hsw_cstates[] = { +static struct cpuidle_state hsw_cstates[] __initdata = { { .name = "C1-HSW", .desc = "MWAIT 0x00", @@ -297,7 +297,7 @@ static struct cpuidle_state hsw_cstates[] = { .enter = NULL } }; -static struct cpuidle_state atom_cstates[] = { +static struct cpuidle_state atom_cstates[] __initdata = { { .name = "C1E-ATM", .desc = "MWAIT 0x00", -- cgit v0.10.2 From 00f3e755513748a6a4f2c370742227aabd8af170 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 30 Aug 2013 12:27:45 +0200 Subject: intel_idle: mark some functions with __init tag intel_idle_probe() and intel_idle_cpuidle_driver_init() can be marked with __init tag as they are only called from intel_idle_init(). Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Reviewed-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 53b24f1..33e599e 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -490,7 +490,7 @@ MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); /* * intel_idle_probe() */ -static int intel_idle_probe(void) +static int __init intel_idle_probe(void) { unsigned int eax, ebx, ecx; const struct x86_cpu_id *id; @@ -558,7 +558,7 @@ static void intel_idle_cpuidle_devices_uninit(void) * intel_idle_cpuidle_driver_init() * allocate, initialize cpuidle_states */ -static int intel_idle_cpuidle_driver_init(void) +static int __init intel_idle_cpuidle_driver_init(void) { int cstate; struct cpuidle_driver *drv = &intel_idle_driver; -- cgit v0.10.2 From 35baa3369d1c68921b37af64495f63933850ad80 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 30 Aug 2013 12:15:04 +0200 Subject: ARM: EXYNOS: convert cpuidle driver to be a platform driver ARM EXYNOS cpuidle driver is currently not multiplatform support ready (as it uses device_initcall() for initialization and doesn't check on what platform it is running). Fix it by converting the driver to be a platform driver and registering exynos_cpuidle platform device from exynos[4,5]_dt_machine_init(). Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index ba95e5d..c17407b 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -294,6 +295,16 @@ void exynos5_restart(enum reboot_mode mode, const char *cmd) __raw_writel(val, addr); } +static struct platform_device exynos_cpuidle = { + .name = "exynos_cpuidle", + .id = -1, +}; + +void __init exynos_cpuidle_init(void) +{ + platform_device_register(&exynos_cpuidle); +} + void __init exynos_init_late(void) { if (of_machine_is_compatible("samsung,exynos5440")) diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 8646a14..b2ac188 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -22,6 +22,7 @@ struct map_desc; void exynos_init_io(void); void exynos4_restart(enum reboot_mode mode, const char *cmd); void exynos5_restart(enum reboot_mode mode, const char *cmd); +void exynos_cpuidle_init(void); void exynos_init_late(void); void exynos_firmware_init(void); diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index ac139226..1bde6ad 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -192,7 +193,7 @@ static void __init exynos5_core_down_clk(void) __raw_writel(tmp, EXYNOS5_PWR_CTRL2); } -static int __init exynos4_init_cpuidle(void) +static int __init exynos_cpuidle_probe(struct platform_device *pdev) { int cpu_id, ret; struct cpuidle_device *device; @@ -226,4 +227,13 @@ static int __init exynos4_init_cpuidle(void) return 0; } -device_initcall(exynos4_init_cpuidle); + +static struct platform_driver exynos_cpuidle_driver = { + .probe = exynos_cpuidle_probe, + .driver = { + .name = "exynos_cpuidle", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(exynos_cpuidle_driver); diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index 0099c6c..53a3dc3 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -25,6 +25,8 @@ static void __init exynos4_dt_machine_init(void) { + exynos_cpuidle_init(); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c index f874b77..c9f7dd1 100644 --- a/arch/arm/mach-exynos/mach-exynos5-dt.c +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c @@ -47,6 +47,8 @@ static void __init exynos5_dt_machine_init(void) } } + exynos_cpuidle_init(); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -- cgit v0.10.2 From f28eb9f5009abdc74d4052ae05c01795e254a6fc Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:51:13 +0800 Subject: ACPICA: Improve error message for "too many parent prefixes" condition. Emit the full offending pathname in the error message. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index c5316e5..aff79c7 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -424,8 +424,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* Current scope has no parent scope */ ACPI_ERROR((AE_INFO, - "ACPI path has too many parent prefixes (^) " - "- reached beyond root node")); + "%s: Path has too many parent prefixes (^) " + "- reached beyond root node", + pathname)); return_ACPI_STATUS(AE_NOT_FOUND); } } -- cgit v0.10.2 From c3faedcdb41a2fedbec8ca8f8612d67b012b44a2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 23 Sep 2013 09:51:22 +0800 Subject: ACPICA: acpi_read: On error, do not modify the return value target location. If an error happens in the middle of a split 32/32 64-bit I/O operation, do not modify the target of the return value pointer. Makes the code consistent with the rest of ACPICA. Bjorn Helgaas. Signed-off-by: Bjorn Helgaas Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 5ee7a814..f81fb06 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -119,7 +119,8 @@ ACPI_EXPORT_SYMBOL(acpi_reset) ******************************************************************************/ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) { - u32 value; + u32 value_lo; + u32 value_hi; u32 width; u64 address; acpi_status status; @@ -137,13 +138,8 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) return (status); } - /* Initialize entire 64-bit return value to zero */ - - *return_value = 0; - value = 0; - /* - * Two address spaces supported: Memory or IO. PCI_Config is + * Two address spaces supported: Memory or I/O. PCI_Config is * not supported here because the GAS structure is insufficient */ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { @@ -155,29 +151,35 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) } } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ + value_lo = 0; + value_hi = 0; + width = reg->bit_width; if (width == 64) { width = 32; /* Break into two 32-bit transfers */ } status = acpi_hw_read_port((acpi_io_address) - address, &value, width); + address, &value_lo, width); if (ACPI_FAILURE(status)) { return (status); } - *return_value = value; if (reg->bit_width == 64) { /* Read the top 32 bits */ status = acpi_hw_read_port((acpi_io_address) - (address + 4), &value, 32); + (address + 4), &value_hi, + 32); if (ACPI_FAILURE(status)) { return (status); } - *return_value |= ((u64)value << 32); } + + /* Set the return value only if status is AE_OK */ + + *return_value = (value_lo | ((u64)value_hi << 32)); } ACPI_DEBUG_PRINT((ACPI_DB_IO, @@ -186,7 +188,7 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); - return (status); + return (AE_OK); } ACPI_EXPORT_SYMBOL(acpi_read) -- cgit v0.10.2 From 2856846e3a7bee02ce6b498c760376061e41aaed Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:51:39 +0800 Subject: ACPICA: Debug output: small formatting update, no functional change. Allow for longer filenames in the module name output during trace operations. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 5796e11..ffd0db5 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -190,7 +190,7 @@ acpi_debug_print(u32 requested_debug_level, * Display the module name, current line number, thread ID (if requested), * current procedure nesting level, and the current procedure name */ - acpi_os_printf("%8s-%04ld ", module_name, line_number); + acpi_os_printf("%9s-%04ld ", module_name, line_number); if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf("[%u] ", (u32)thread_id); -- cgit v0.10.2 From 30095207072665503a5f6c769d16be26de38fa6a Mon Sep 17 00:00:00 2001 From: Naresh Bhat Date: Mon, 23 Sep 2013 09:51:46 +0800 Subject: ACPICA: Linux-specific header: enable "aarch64" 64-bit build. Add support for the __aarch64__ define for 64-bit builds. Signed-off-by: Naresh Bhat Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 68534ef..fda0f3e 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -87,7 +87,7 @@ #define ACPI_FLUSH_CPU_CACHE() #define ACPI_CAST_PTHREAD_T(pthread) ((acpi_thread_id) (pthread)) -#if defined(__ia64__) || defined(__x86_64__) +#if defined(__ia64__) || defined(__x86_64__) || defined(__aarch64__) #define ACPI_MACHINE_WIDTH 64 #define COMPILER_DEPENDENT_INT64 long #define COMPILER_DEPENDENT_UINT64 unsigned long -- cgit v0.10.2 From 1f5210a1e6c21ef850a290bac2a85ae1da2f0c2e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:51:52 +0800 Subject: ACPICA: Debugger: Prevent possible command line buffer overflow, kernel behavior is not affected. Increase the size of a couple of the debugger line buffers. ACPICA BZ 1037. The debugger related code is not in the kernel so the behavior of the kernel is not affected. Buglink: http://bugs.acpica.org/show_bug.cgi?id=1037 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 90e846f..c9ad2e1 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -445,13 +445,6 @@ ACPI_EXTERN u8 acpi_gbl_db_opt_tables; ACPI_EXTERN u8 acpi_gbl_db_opt_stats; ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods; ACPI_EXTERN u8 acpi_gbl_db_opt_no_region_support; - -ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]; -ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]; -ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]; -ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]; -ACPI_EXTERN char acpi_gbl_db_scope_buf[80]; -ACPI_EXTERN char acpi_gbl_db_debug_filename[80]; ACPI_EXTERN u8 acpi_gbl_db_output_to_file; ACPI_EXTERN char *acpi_gbl_db_buffer; ACPI_EXTERN char *acpi_gbl_db_filename; @@ -459,6 +452,16 @@ ACPI_EXTERN u32 acpi_gbl_db_debug_level; ACPI_EXTERN u32 acpi_gbl_db_console_debug_level; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node; +ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]; +ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]; + +/* These buffers should all be the same size */ + +ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_EXTERN char acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_EXTERN char acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE]; + /* * Statistic globals */ -- cgit v0.10.2 From d53d820741806a5488d0f002b61765deb58371f3 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:51:58 +0800 Subject: ACPICA: Validate start object for acpi_walk_namespace. Perform a sanity check on the start object to prevent problems later. ACPICA BZ 1025. This patch only adds additional input parameter validation, no actual kernel suffering has been discovered. Buglink: http://bugs.acpica.org/show_bug.cgi?id=1025 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index b38b4b0..481a6b4 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -605,11 +605,19 @@ acpi_walk_namespace(acpi_object_type type, goto unlock_and_exit; } + /* Now we can validate the starting node */ + + if (!acpi_ns_validate_handle(start_object)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit2; + } + status = acpi_ns_walk_namespace(type, start_object, max_depth, ACPI_NS_WALK_UNLOCK, descending_callback, ascending_callback, context, return_value); + unlock_and_exit2: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); unlock_and_exit: -- cgit v0.10.2 From a2fd4b4b4e2884405c54a91514b0fad3853aea01 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 23 Sep 2013 09:52:05 +0800 Subject: ACPICA: Add support for host-installed SCI handlers. This change adds support to allow hosts to install System Control Interrupt handlers. Certain ACPI functionality requires the host to handle raw SCIs. For example, the "SCI Doorbell" that is defined for memory power state support requires the host device driver to handle SCIs to examine if the doorbell has been activated. Multiple SCI handlers can be installed to allow for future expansion. Debugger support is included. Lv Zheng, Bob Moore. ACPICA BZ 1032. Bug summary: It is reported when the PCC (Platform Communication Channel, via MPST table, defined in ACPI specification 5.0) subchannel responds to the host, it issues an SCI and the host must probe the subchannel for channel status. Buglink: http://bugs.acpica.org/show_bug.cgi?id=1032 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 9feba08..30c2d69 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -113,11 +113,12 @@ void acpi_db_display_handlers(void); ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_gpe(char *gpe_arg, char *block_arg)) + ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void)) /* * dbconvert - miscellaneous conversion routines */ - acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value); +acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value); acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object); diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index ab0e977..3ae5fd0 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -242,11 +242,11 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, */ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context); -u32 acpi_ev_install_sci_handler(void); +u32 acpi_ev_sci_dispatch(void); -acpi_status acpi_ev_remove_sci_handler(void); +u32 acpi_ev_install_sci_handler(void); -u32 acpi_ev_initialize_SCI(u32 program_SCI); +acpi_status acpi_ev_remove_all_sci_handlers(void); ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void)) #endif /* __ACEVENTS_H__ */ diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index c9ad2e1..0fba431 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -269,6 +269,7 @@ ACPI_EXTERN acpi_table_handler acpi_gbl_table_handler; ACPI_EXTERN void *acpi_gbl_table_handler_context; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler; +ACPI_EXTERN struct acpi_sci_handler_info *acpi_gbl_sci_handler_list; /* Owner ID support */ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 0ed0066..be9e30e 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -398,6 +398,14 @@ struct acpi_simple_repair_info { * ****************************************************************************/ +/* Dispatch info for each host-installed SCI handler */ + +struct acpi_sci_handler_info { + struct acpi_sci_handler_info *next; + acpi_sci_handler address; /* Address of handler */ + void *context; /* Context to be passed to handler */ +}; + /* Dispatch info for each GPE -- either a method or handler, cannot be both */ struct acpi_gpe_handler_info { diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index b24dbb8..d523390 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -196,7 +196,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, * * FUNCTION: acpi_ev_get_gpe_xrupt_block * - * PARAMETERS: interrupt_number - Interrupt for a GPE block + * PARAMETERS: interrupt_number - Interrupt for a GPE block * * RETURN: A GPE interrupt block * diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 1b111ef..a568754 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -264,13 +264,6 @@ void acpi_ev_terminate(void) status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); - /* Remove SCI handler */ - - status = acpi_ev_remove_sci_handler(); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); - } - status = acpi_ev_remove_global_lock_handler(); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, @@ -280,6 +273,13 @@ void acpi_ev_terminate(void) acpi_gbl_events_initialized = FALSE; } + /* Remove SCI handlers */ + + status = acpi_ev_remove_all_sci_handlers(); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); + } + /* Deallocate all handler objects installed within GPE info structs */ status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL); diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index b905acf..b2f0fb2 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -54,6 +54,52 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context); /******************************************************************************* * + * FUNCTION: acpi_ev_sci_dispatch + * + * PARAMETERS: None + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers. + * + ******************************************************************************/ + +u32 acpi_ev_sci_dispatch(void) +{ + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; + u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; + + ACPI_FUNCTION_NAME(ev_sci_dispatch); + + /* Are there any host-installed SCI handlers? */ + + if (!acpi_gbl_sci_handler_list) { + return (int_status); + } + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Invoke all host-installed SCI handlers */ + + sci_handler = acpi_gbl_sci_handler_list; + while (sci_handler) { + + /* Invoke the installed handler (at interrupt level) */ + + int_status |= sci_handler->address((u32)acpi_gbl_FADT. + sci_interrupt, + sci_handler->context); + + sci_handler = sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return (int_status); +} + +/******************************************************************************* + * * FUNCTION: acpi_ev_sci_xrupt_handler * * PARAMETERS: context - Calling Context @@ -89,6 +135,10 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); + /* Invoke all host-installed SCI handlers */ + + interrupt_handled |= acpi_ev_sci_dispatch(); + return_UINT32(interrupt_handled); } @@ -112,14 +162,13 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler); /* - * We are guaranteed by the ACPI CA initialization/shutdown code that + * We are guaranteed by the ACPICA initialization/shutdown code that * if this interrupt handler is installed, ACPI is enabled. */ /* GPEs: Check for and dispatch any GPEs that have occurred */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - return_UINT32(interrupt_handled); } @@ -150,15 +199,15 @@ u32 acpi_ev_install_sci_handler(void) /****************************************************************************** * - * FUNCTION: acpi_ev_remove_sci_handler + * FUNCTION: acpi_ev_remove_all_sci_handlers * * PARAMETERS: none * - * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not + * RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not * installed to begin with * * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be - * taken. + * taken. Remove all host-installed SCI handlers. * * Note: It doesn't seem important to disable all events or set the event * enable registers to their original values. The OS should disable @@ -167,11 +216,13 @@ u32 acpi_ev_install_sci_handler(void) * ******************************************************************************/ -acpi_status acpi_ev_remove_sci_handler(void) +acpi_status acpi_ev_remove_all_sci_handlers(void) { + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; acpi_status status; - ACPI_FUNCTION_TRACE(ev_remove_sci_handler); + ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers); /* Just let the OS remove the handler and disable the level */ @@ -179,6 +230,21 @@ acpi_status acpi_ev_remove_sci_handler(void) acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, acpi_ev_sci_xrupt_handler); + if (!acpi_gbl_sci_handler_list) { + return (status); + } + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Free all host-installed SCI handlers */ + + while (acpi_gbl_sci_handler_list) { + sci_handler = acpi_gbl_sci_handler_list; + acpi_gbl_sci_handler_list = sci_handler->next; + ACPI_FREE(sci_handler); + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index ca5fba9..6f56146 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -385,6 +385,144 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) #if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * + * FUNCTION: acpi_install_sci_handler + * + * PARAMETERS: address - Address of the handler + * context - Value passed to the handler on each SCI + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for a System Control Interrupt. + * + ******************************************************************************/ +acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context) +{ + struct acpi_sci_handler_info *new_sci_handler; + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_sci_handler); + + if (!address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Allocate and init a handler object */ + + new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info)); + if (!new_sci_handler) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + new_sci_handler->address = address; + new_sci_handler->context = context; + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Lock list during installation */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + sci_handler = acpi_gbl_sci_handler_list; + + /* Ensure handler does not already exist */ + + while (sci_handler) { + if (address == sci_handler->address) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } + + sci_handler = sci_handler->next; + } + + /* Install the new handler into the global list (at head) */ + + new_sci_handler->next = acpi_gbl_sci_handler_list; + acpi_gbl_sci_handler_list = new_sci_handler; + + unlock_and_exit: + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + + exit: + if (ACPI_FAILURE(status)) { + ACPI_FREE(new_sci_handler); + } + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_remove_sci_handler + * + * PARAMETERS: address - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a handler for a System Control Interrupt. + * + ******************************************************************************/ + +acpi_status acpi_remove_sci_handler(acpi_sci_handler address) +{ + struct acpi_sci_handler_info *prev_sci_handler; + struct acpi_sci_handler_info *next_sci_handler; + acpi_cpu_flags flags; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_remove_sci_handler); + + if (!address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Remove the SCI handler with lock */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + prev_sci_handler = NULL; + next_sci_handler = acpi_gbl_sci_handler_list; + while (next_sci_handler) { + if (next_sci_handler->address == address) { + + /* Unlink and free the SCI handler info block */ + + if (prev_sci_handler) { + prev_sci_handler->next = next_sci_handler->next; + } else { + acpi_gbl_sci_handler_list = + next_sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + ACPI_FREE(next_sci_handler); + goto unlock_and_exit; + } + + prev_sci_handler = next_sci_handler; + next_sci_handler = next_sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + status = AE_NOT_EXIST; + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * * FUNCTION: acpi_install_global_event_handler * * PARAMETERS: handler - Pointer to the global event handler function @@ -398,6 +536,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) * Can be used to update event counters, etc. * ******************************************************************************/ + acpi_status acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) { diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index d6f26bf..046d5b0 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -291,7 +291,7 @@ acpi_status acpi_ut_init_globals(void) #if (!ACPI_REDUCED_HARDWARE) - /* GPE support */ + /* GPE/SCI support */ acpi_gbl_all_gpes_initialized = FALSE; acpi_gbl_gpe_xrupt_list_head = NULL; @@ -300,6 +300,7 @@ acpi_status acpi_ut_init_globals(void) acpi_current_gpe_count = 0; acpi_gbl_global_event_handler = NULL; + acpi_gbl_sci_handler_list = NULL; #endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 85bfdbe..55a4d3a 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -280,9 +280,16 @@ acpi_status acpi_install_initialization_handler(acpi_init_handler handler, u32 function); ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status - acpi_install_global_event_handler - (acpi_gbl_event_handler handler, void *context)) - + acpi_install_sci_handler(acpi_sci_handler + address, + void *context)) +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status + acpi_remove_sci_handler(acpi_sci_handler + address)) +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status + acpi_install_global_event_handler + (acpi_gbl_event_handler handler, + void *context)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_install_fixed_event_handler(u32 acpi_event, diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index b748aef..850f750 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -946,6 +946,9 @@ typedef void * Various handlers and callback procedures */ typedef +u32 (*acpi_sci_handler) (u32 interrupt_number, void *context); + +typedef void (*acpi_gbl_event_handler) (u32 event_type, acpi_handle device, u32 event_number, void *context); -- cgit v0.10.2 From d2e7d079c7f21999e93802351c6ac7b31d266cce Mon Sep 17 00:00:00 2001 From: "David E. Box" Date: Mon, 23 Sep 2013 09:52:12 +0800 Subject: ACPICA: Operation region support: Never free the handler "context" pointer. This change removes some dangerous code that attempts to free the handler context pointer in some (rare) circumstances. The owner of the handler owns this pointer and the ACPICA code should never touch it. Although not seen to be an issue in any kernel, it did show up as a problem under AcpiExec. Also, set the internal storage field for the context pointer to zero when the region is deactivated, simply for sanity. David Box. Signed-off-by: David E. Box Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index cea14d6..6293d6b 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -217,16 +217,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; - if (region_obj2->extra.region_context) { - - /* The handler for this region was already installed */ - - ACPI_FREE(region_context); - } else { - /* - * Save the returned context for use in all accesses to - * this particular region - */ + /* + * Save the returned context for use in all accesses to + * the handler for this particular region + */ + if (!(region_obj2->extra.region_context)) { region_obj2->extra.region_context = region_context; } @@ -402,6 +397,14 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, handler_obj->address_space. context, region_context); + /* + * region_context should have been released by the deactivate + * operation. We don't need access to it anymore here. + */ + if (region_context) { + *region_context = NULL; + } + /* Init routine may fail, Just ignore errors */ if (ACPI_FAILURE(status)) { -- cgit v0.10.2 From 424deb3870580d9afbbb421edfbe30a02ef28056 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:52:19 +0800 Subject: ACPICA: Debugger: Add new command to display full namespace pathnames. Paths command displays the full pathname and object type for the entire namespace. Alternative to the Namespace command. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 30c2d69..27c36a5 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -155,6 +155,8 @@ void acpi_db_set_scope(char *name); void acpi_db_dump_namespace(char *start_arg, char *depth_arg); +void acpi_db_dump_namespace_paths(void); + void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg); acpi_status acpi_db_find_name_in_namespace(char *name_arg); diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 40b04bd..e6138ac 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -213,6 +213,12 @@ acpi_ns_dump_objects(acpi_object_type type, u8 display_type, u32 max_depth, acpi_owner_id owner_id, acpi_handle start_handle); + +void +acpi_ns_dump_object_paths(acpi_object_type type, + u8 display_type, + u32 max_depth, + acpi_owner_id owner_id, acpi_handle start_handle); #endif /* ACPI_FUTURE_USAGE */ /* diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 7418c77..8063385 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -59,6 +59,17 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, #endif #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +#ifdef ACPI_FUTURE_USAGE +static acpi_status +acpi_ns_dump_one_object_path(acpi_handle obj_handle, + u32 level, void *context, void **return_value); + +static acpi_status +acpi_ns_get_max_depth(acpi_handle obj_handle, + u32 level, void *context, void **return_value); +#endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_ns_print_pathname @@ -671,6 +682,129 @@ acpi_ns_dump_objects(acpi_object_type type, } #endif /* ACPI_FUTURE_USAGE */ +#ifdef ACPI_FUTURE_USAGE +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_one_object_path, acpi_ns_get_max_depth + * + * PARAMETERS: obj_handle - Node to be dumped + * level - Nesting level of the handle + * context - Passed into walk_namespace + * return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Dump the full pathname to a namespace object. acp_ns_get_max_depth + * computes the maximum nesting depth in the namespace tree, in + * order to simplify formatting in acpi_ns_dump_one_object_path. + * These procedures are user_functions called by acpi_ns_walk_namespace. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_dump_one_object_path(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + u32 max_level = *((u32 *)context); + char *pathname; + struct acpi_namespace_node *node; + int path_indent; + + if (!obj_handle) { + return (AE_OK); + } + + node = acpi_ns_validate_handle(obj_handle); + pathname = acpi_ns_get_external_pathname(node); + + path_indent = 1; + if (level <= max_level) { + path_indent = max_level - level + 1; + } + + acpi_os_printf("%2d%*s%-12s%*s", + level, level, " ", acpi_ut_get_type_name(node->type), + path_indent, " "); + + acpi_os_printf("%s\n", &pathname[1]); + ACPI_FREE(pathname); + return (AE_OK); +} + +static acpi_status +acpi_ns_get_max_depth(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + u32 *max_level = (u32 *)context; + + if (level > *max_level) { + *max_level = level; + } + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_object_paths + * + * PARAMETERS: type - Object type to be dumped + * display_type - 0 or ACPI_DISPLAY_SUMMARY + * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX + * for an effectively unlimited depth. + * owner_id - Dump only objects owned by this ID. Use + * ACPI_UINT32_MAX to match all owners. + * start_handle - Where in namespace to start/end search + * + * RETURN: None + * + * DESCRIPTION: Dump full object pathnames within the loaded namespace. Uses + * acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object_path. + * + ******************************************************************************/ + +void +acpi_ns_dump_object_paths(acpi_object_type type, + u8 display_type, + u32 max_depth, + acpi_owner_id owner_id, acpi_handle start_handle) +{ + acpi_status status; + u32 max_level = 0; + + ACPI_FUNCTION_ENTRY(); + + /* + * Just lock the entire namespace for the duration of the dump. + * We don't want any changes to the namespace during this time, + * especially the temporary nodes since we are going to display + * them also. + */ + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not acquire namespace mutex\n"); + return; + } + + /* Get the max depth of the namespace tree, for formatting later */ + + (void)acpi_ns_walk_namespace(type, start_handle, max_depth, + ACPI_NS_WALK_NO_UNLOCK | + ACPI_NS_WALK_TEMP_NODES, + acpi_ns_get_max_depth, NULL, + (void *)&max_level, NULL); + + /* Now dump the entire namespace */ + + (void)acpi_ns_walk_namespace(type, start_handle, max_depth, + ACPI_NS_WALK_NO_UNLOCK | + ACPI_NS_WALK_TEMP_NODES, + acpi_ns_dump_one_object_path, NULL, + (void *)&max_level, NULL); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +} +#endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_ns_dump_entry -- cgit v0.10.2 From 94d4be6773e86a0d52d7e200fb3cda2b9013c862 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 23 Sep 2013 09:52:29 +0800 Subject: ACPICA: Tables: Cleanup table checksum verification code. This patch reduces code redundancy by moving the FACS/S3PT checksum verification skip logic into acpi_tb_verify_checksum() and other calls of this function also get benefit from this change. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 42a13c0..9e6788f 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -80,16 +80,10 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) } } - /* FACS is the odd table, has no standard ACPI header and no checksum */ + /* Always calculate checksum, ignore bad checksum if requested */ - if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) { - - /* Always calculate checksum, ignore bad checksum if requested */ - - status = - acpi_tb_verify_checksum(table_desc->pointer, - table_desc->length); - } + status = + acpi_tb_verify_checksum(table_desc->pointer, table_desc->length); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index dc963f8..499759a 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -190,6 +190,16 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) { u8 checksum; + /* + * FACS/S3PT: + * They are the odd tables, have no standard ACPI header and no checksum + */ + + if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_S3PT) || + ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FACS)) { + return (AE_OK); + } + /* Compute the checksum on the table */ checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); -- cgit v0.10.2 From cacba8657351f709ab3cb53a2b207f513f14054c Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 23 Sep 2013 09:52:34 +0800 Subject: ACPICA: Tables: Cleanup RSDP signature codes. This patch introduces new macors to handle RSDP signature and cleans up the affected codes. Lv Zheng. Some updates are only used for ACPICA utilities which are not shipped in the kernel yet. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index 499759a..9a47715 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -138,7 +138,7 @@ acpi_tb_print_table_header(acpi_physical_address address, ACPI_INFO((AE_INFO, "%4.4s %p %05X", header->signature, ACPI_CAST_PTR(void, address), header->length)); - } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { + } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { /* RSDP has no common fields */ diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index 948c95e..1c95fab 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -68,8 +68,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * Note: Sometimes there exists more than one RSDP in memory; the valid * RSDP has a valid checksum, all others have an invalid checksum. */ - if (ACPI_STRNCMP((char *)rsdp->signature, ACPI_SIG_RSDP, - sizeof(ACPI_SIG_RSDP) - 1) != 0) { + if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) { /* Nope, BAD Signature */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 850f750..5400672 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -474,6 +474,11 @@ typedef u64 acpi_integer; #define ACPI_MOVE_NAME(dest,src) (ACPI_STRNCPY (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE)) #endif +/* Support for the special RSDP signature (8 characters) */ + +#define ACPI_VALIDATE_RSDP_SIG(a) (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8)) +#define ACPI_MAKE_RSDP_SIG(dest) (ACPI_MEMCPY (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8)) + /******************************************************************************* * * Miscellaneous constants -- cgit v0.10.2 From 31e93a166c7cfa6d5ff0bae0c19f0541f06f2260 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 23 Sep 2013 09:52:40 +0800 Subject: ACPICA: Cleanup exception codes. This patch adds AE_ACCESS for EACCES or EPERM. Some error prompts are also cleaned up in this patch. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index cf051e0..4e280bd 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -125,8 +125,9 @@ struct acpi_exception_info { #define AE_NO_HANDLER EXCEP_ENV (0x001A) #define AE_OWNER_ID_LIMIT EXCEP_ENV (0x001B) #define AE_NOT_CONFIGURED EXCEP_ENV (0x001C) +#define AE_ACCESS EXCEP_ENV (0x001D) -#define AE_CODE_ENV_MAX 0x001C +#define AE_CODE_ENV_MAX 0x001D /* * Programmer exceptions @@ -227,7 +228,7 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = { EXCEP_TXT("AE_NO_ACPI_TABLES", "ACPI tables could not be found"), EXCEP_TXT("AE_NO_NAMESPACE", "A namespace has not been loaded"), EXCEP_TXT("AE_NO_MEMORY", "Insufficient dynamic memory"), - EXCEP_TXT("AE_NOT_FOUND", "The name was not found in the namespace"), + EXCEP_TXT("AE_NOT_FOUND", "A requested entity is not found"), EXCEP_TXT("AE_NOT_EXIST", "A required entity does not exist"), EXCEP_TXT("AE_ALREADY_EXISTS", "An entity already exists"), EXCEP_TXT("AE_TYPE", "The object type is incorrect"), @@ -259,7 +260,8 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = { EXCEP_TXT("AE_OWNER_ID_LIMIT", "There are no more Owner IDs available for ACPI tables or control methods"), EXCEP_TXT("AE_NOT_CONFIGURED", - "The interface is not part of the current subsystem configuration") + "The interface is not part of the current subsystem configuration"), + EXCEP_TXT("AE_ACCESS", "Permission denied for the requested operation") }; static const struct acpi_exception_info acpi_gbl_exception_names_pgm[] = { -- cgit v0.10.2 From c53ae3a60c2494a160140d09637f543562626365 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:52:45 +0800 Subject: ACPICA: SCI Handlers: Update handler interface, eliminate unnecessary argument. The SCI interrupt number is not needed for the SCI handlers, and was just unnecessary overhead. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index b2f0fb2..94d9ebd 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -87,9 +87,7 @@ u32 acpi_ev_sci_dispatch(void) /* Invoke the installed handler (at interrupt level) */ - int_status |= sci_handler->address((u32)acpi_gbl_FADT. - sci_interrupt, - sci_handler->context); + int_status |= sci_handler->address(sci_handler->context); sci_handler = sci_handler->next; } diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 5400672..f6abf23 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -951,7 +951,7 @@ typedef void * Various handlers and callback procedures */ typedef -u32 (*acpi_sci_handler) (u32 interrupt_number, void *context); +u32 (*acpi_sci_handler) (void *context); typedef void (*acpi_gbl_event_handler) (u32 event_type, -- cgit v0.10.2 From 94d7ba991fe0dd245babc8f227ad5fabe234303f Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Sep 2013 09:52:53 +0800 Subject: ACPICA: Update version to 20130823. Version 20130823. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 55a4d3a..c7b1475 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20130725 +#define ACPI_CA_VERSION 0x20130823 #include #include -- cgit v0.10.2 From f6913f990273a1fbfc0ec501d4998faa4f1ebae6 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Thu, 29 Aug 2013 18:22:06 -0600 Subject: hotplug / x86: Fix online state in cpu0 debug interface _debug_hotplug_cpu() is a debug interface that puts cpu0 offline during boot-up when CONFIG_DEBUG_HOTPLUG_CPU0 is set. After cpu0 is put offline in this interface, however, /sys/devices/system/cpu/cpu0/online still shows 1 (online). This patch fixes _debug_hotplug_cpu() to update dev->offline when CPU online/offline operation succeeded. Signed-off-by: Toshi Kani Acked-by: Yasuaki Ishimatsu Signed-off-by: Rafael J. Wysocki diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c index 6e60b5f..5823bbd 100644 --- a/arch/x86/kernel/topology.c +++ b/arch/x86/kernel/topology.c @@ -72,16 +72,19 @@ int __ref _debug_hotplug_cpu(int cpu, int action) ret = cpu_down(cpu); if (!ret) { pr_info("CPU %u is now offline\n", cpu); + dev->offline = true; kobject_uevent(&dev->kobj, KOBJ_OFFLINE); } else pr_debug("Can't offline CPU%d.\n", cpu); break; case 1: ret = cpu_up(cpu); - if (!ret) + if (!ret) { + dev->offline = false; kobject_uevent(&dev->kobj, KOBJ_ONLINE); - else + } else { pr_debug("Can't online CPU%d.\n", cpu); + } break; default: ret = -EINVAL; -- cgit v0.10.2 From 574b851e99923c884fee4e0d7cf7e7c3dc023ffa Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Thu, 29 Aug 2013 18:22:07 -0600 Subject: hotplug / x86: Add hotplug lock to missing places lock_device_hotplug[_sysfs]() serializes CPU & Memory online/offline and hotplug operations. However, this lock is not held in the debug interfaces below that initiate CPU online/offline operations. - _debug_hotplug_cpu(), cpu0 hotplug test interface enabled by CONFIG_DEBUG_HOTPLUG_CPU0. - cpu_probe_store() and cpu_release_store(), cpu hotplug test interface enabled by CONFIG_ARCH_CPU_PROBE_RELEASE. This patch changes the above interfaces to hold lock_device_hotplug(). Signed-off-by: Toshi Kani Acked-by: Greg Kroah-Hartman Acked-by: Yasuaki Ishimatsu Signed-off-by: Rafael J. Wysocki diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c index 5823bbd..a3f35eb 100644 --- a/arch/x86/kernel/topology.c +++ b/arch/x86/kernel/topology.c @@ -65,6 +65,7 @@ int __ref _debug_hotplug_cpu(int cpu, int action) if (!cpu_is_hotpluggable(cpu)) return -EINVAL; + lock_device_hotplug(); cpu_hotplug_driver_lock(); switch (action) { @@ -91,6 +92,7 @@ int __ref _debug_hotplug_cpu(int cpu, int action) } cpu_hotplug_driver_unlock(); + unlock_device_hotplug(); return ret; } diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 848ebbd..51f5d7f 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -93,7 +93,17 @@ static ssize_t cpu_probe_store(struct device *dev, const char *buf, size_t count) { - return arch_cpu_probe(buf, count); + ssize_t cnt; + int ret; + + ret = lock_device_hotplug_sysfs(); + if (ret) + return ret; + + cnt = arch_cpu_probe(buf, count); + + unlock_device_hotplug(); + return cnt; } static ssize_t cpu_release_store(struct device *dev, @@ -101,7 +111,17 @@ static ssize_t cpu_release_store(struct device *dev, const char *buf, size_t count) { - return arch_cpu_release(buf, count); + ssize_t cnt; + int ret; + + ret = lock_device_hotplug_sysfs(); + if (ret) + return ret; + + cnt = arch_cpu_release(buf, count); + + unlock_device_hotplug(); + return cnt; } static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); -- cgit v0.10.2 From 1cad5e9a3978d182aa9b0e909fb0379da5ba45af Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Thu, 29 Aug 2013 18:22:08 -0600 Subject: hotplug / x86: Disable ARCH_CPU_PROBE_RELEASE on x86 Commit d7c53c9e enabled ARCH_CPU_PROBE_RELEASE on x86 in order to serialize CPU online/offline operations. Although it is the config option to enable CPU hotplug test interfaces, probe & release, it is also the option to enable cpu_hotplug_driver_lock() as well. Therefore, this option had to be enabled on x86 with dummy arch_cpu_probe() and arch_cpu_release(). Since then, lock_device_hotplug() was introduced to serialize CPU online/offline & hotplug operations. Therefore, this config option is no longer required for the serialization. This patch disables this config option on x86 and revert the changes made by commit d7c53c9e. Signed-off-by: Toshi Kani Acked-by: Yasuaki Ishimatsu Signed-off-by: Rafael J. Wysocki diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ee2fb9d..dcdb513 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -254,10 +254,6 @@ config ARCH_HWEIGHT_CFLAGS default "-fcall-saved-ecx -fcall-saved-edx" if X86_32 default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64 -config ARCH_CPU_PROBE_RELEASE - def_bool y - depends on HOTPLUG_CPU - config ARCH_SUPPORTS_UPROBES def_bool y diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6cacab6..e73b3f5 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -82,27 +82,6 @@ /* State of each CPU */ DEFINE_PER_CPU(int, cpu_state) = { 0 }; -#ifdef CONFIG_HOTPLUG_CPU -/* - * We need this for trampoline_base protection from concurrent accesses when - * off- and onlining cores wildly. - */ -static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex); - -void cpu_hotplug_driver_lock(void) -{ - mutex_lock(&x86_cpu_hotplug_driver_mutex); -} - -void cpu_hotplug_driver_unlock(void) -{ - mutex_unlock(&x86_cpu_hotplug_driver_mutex); -} - -ssize_t arch_cpu_probe(const char *buf, size_t count) { return -1; } -ssize_t arch_cpu_release(const char *buf, size_t count) { return -1; } -#endif - /* Number of siblings per CPU package */ int smp_num_siblings = 1; EXPORT_SYMBOL(smp_num_siblings); -- cgit v0.10.2 From bee7f9c83e1d18af6fee06b97b6558cbd1cded45 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 6 Sep 2013 19:08:00 -0700 Subject: ACPI / x86: Increase override tables number limit Current ACPI tables in initrd is limited to 10, that is too small. 64 should be good enough as we have 35 sigs and could have several SSDT. Two problems in current code prevent us from increasing limit: 1. The cpio file info array is put in stack, as every element is 32 bytes, could run out of stack if we have that array size to 64. We can move it out from stack, make it global and put it into the __initdata section. 2. early_ioremap() only can remap 256k one time. Current code maps 10 tables at a time. If we increased that limit, the whole size could be more than 256k, so early_ioremap() would fail with that. We can map chunks one by one during copying, instead of mapping all of them together. Signed-off-by: Yinghai Acked-by: Tejun Heo Tested-by: Thomas Renninger Reviewed-by: Tang Chen Tested-by: Tang Chen Acked-by: Toshi Kani Signed-off-by: Rafael J. Wysocki diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index b1977ba..c8c1e70 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e5f416c..88bb9d0 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -569,8 +569,10 @@ static const char * const table_sigs[] = { #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) -/* Must not increase 10 or needs code modification below */ -#define ACPI_OVERRIDE_TABLES 10 +#define ACPI_OVERRIDE_TABLES 64 +static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES]; + +#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT) void __init acpi_initrd_override(void *data, size_t size) { @@ -579,8 +581,6 @@ void __init acpi_initrd_override(void *data, size_t size) struct acpi_table_header *table; char cpio_path[32] = "kernel/firmware/acpi/"; struct cpio_data file; - struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES]; - char *p; if (data == NULL || size == 0) return; @@ -625,8 +625,8 @@ void __init acpi_initrd_override(void *data, size_t size) table->signature, cpio_path, file.name, table->length); all_tables_size += table->length; - early_initrd_files[table_nr].data = file.data; - early_initrd_files[table_nr].size = file.size; + acpi_initrd_files[table_nr].data = file.data; + acpi_initrd_files[table_nr].size = file.size; table_nr++; } if (table_nr == 0) @@ -652,14 +652,34 @@ void __init acpi_initrd_override(void *data, size_t size) memblock_reserve(acpi_tables_addr, all_tables_size); arch_reserve_mem_area(acpi_tables_addr, all_tables_size); - p = early_ioremap(acpi_tables_addr, all_tables_size); - + /* + * early_ioremap only can remap 256k one time. If we map all + * tables one time, we will hit the limit. Need to map chunks + * one by one during copying the same as that in relocate_initrd(). + */ for (no = 0; no < table_nr; no++) { - memcpy(p + total_offset, early_initrd_files[no].data, - early_initrd_files[no].size); - total_offset += early_initrd_files[no].size; + unsigned char *src_p = acpi_initrd_files[no].data; + phys_addr_t size = acpi_initrd_files[no].size; + phys_addr_t dest_addr = acpi_tables_addr + total_offset; + phys_addr_t slop, clen; + char *dest_p; + + total_offset += size; + + while (size) { + slop = dest_addr & ~PAGE_MASK; + clen = size; + if (clen > MAP_CHUNK_SIZE - slop) + clen = MAP_CHUNK_SIZE - slop; + dest_p = early_ioremap(dest_addr & PAGE_MASK, + clen + slop); + memcpy(dest_p + slop, src_p, clen); + early_iounmap(dest_p, clen + slop); + src_p += clen; + dest_addr += clen; + size -= clen; + } } - early_iounmap(p, all_tables_size); } #endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */ -- cgit v0.10.2 From 302822996fd572676bb66a7c4351f6faa0e4ddfd Mon Sep 17 00:00:00 2001 From: Liu Chuansheng Date: Thu, 12 Sep 2013 01:42:57 +0800 Subject: ACPI / osl: implement acpi_os_sleep() with msleep() Currently, acpi_os_sleep() uses schedule_timeout_interruptible() which can be interrupted by a signal, and that causes the real sleep time to be shorter. According to the ACPI spec: The Sleep term is used to implement long-term timing requirements. Execution is delayed for at least the required number of milliseconds. The sleeping time should be at least the required number msecs, so use msleep() which guarantees that to implement it. Signed-off-by: Liu Chuansheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e5f416c..b1629b5 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -820,7 +820,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) void acpi_os_sleep(u64 ms) { - schedule_timeout_interruptible(msecs_to_jiffies(ms)); + msleep(ms); } void acpi_os_stall(u32 us) -- cgit v0.10.2 From 763f527b68c6b026439f0b12ebe232d96b5563df Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 12 Sep 2013 03:32:03 -0400 Subject: ACPI / button: Using input_set_capability() to mark device's event capability Input layer provides input_set_capability() to set input device's event related bits. This patch is to use it to replace origin code. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index a557738..c971929 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -383,18 +383,15 @@ static int acpi_button_add(struct acpi_device *device) switch (button->type) { case ACPI_BUTTON_TYPE_POWER: - input->evbit[0] = BIT_MASK(EV_KEY); - set_bit(KEY_POWER, input->keybit); + input_set_capability(input, EV_KEY, KEY_POWER); break; case ACPI_BUTTON_TYPE_SLEEP: - input->evbit[0] = BIT_MASK(EV_KEY); - set_bit(KEY_SLEEP, input->keybit); + input_set_capability(input, EV_KEY, KEY_SLEEP); break; case ACPI_BUTTON_TYPE_LID: - input->evbit[0] = BIT_MASK(EV_SW); - set_bit(SW_LID, input->swbit); + input_set_capability(input, EV_SW, SW_LID); break; } -- cgit v0.10.2 From 16a26e85279fd672050ffc3637038366629e8653 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 12 Sep 2013 03:32:04 -0400 Subject: ACPI / EC: Convert all printk() calls to dynamic debug function This patch is to convert all printks in the ec driver to pr_debug/info/err and define pr_fmt macro to replace PREFIX. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index a06d983..d5309fd 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -28,6 +28,7 @@ /* Uncomment next line to get verbose printout */ /* #define DEBUG */ +#define pr_fmt(fmt) "ACPI : EC: " fmt #include #include @@ -49,9 +50,6 @@ #define ACPI_EC_DEVICE_NAME "Embedded Controller" #define ACPI_EC_FILE_INFO "info" -#undef PREFIX -#define PREFIX "ACPI: EC: " - /* EC status register */ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ @@ -131,26 +129,26 @@ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ static inline u8 acpi_ec_read_status(struct acpi_ec *ec) { u8 x = inb(ec->command_addr); - pr_debug(PREFIX "---> status = 0x%2.2x\n", x); + pr_debug("---> status = 0x%2.2x\n", x); return x; } static inline u8 acpi_ec_read_data(struct acpi_ec *ec) { u8 x = inb(ec->data_addr); - pr_debug(PREFIX "---> data = 0x%2.2x\n", x); + pr_debug("---> data = 0x%2.2x\n", x); return x; } static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) { - pr_debug(PREFIX "<--- command = 0x%2.2x\n", command); + pr_debug("<--- command = 0x%2.2x\n", command); outb(command, ec->command_addr); } static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) { - pr_debug(PREFIX "<--- data = 0x%2.2x\n", data); + pr_debug("<--- data = 0x%2.2x\n", data); outb(data, ec->data_addr); } @@ -241,7 +239,7 @@ static int ec_poll(struct acpi_ec *ec) } advance_transaction(ec, acpi_ec_read_status(ec)); } while (time_before(jiffies, delay)); - pr_debug(PREFIX "controller reset, restart transaction\n"); + pr_debug("controller reset, restart transaction\n"); spin_lock_irqsave(&ec->lock, flags); start_transaction(ec); spin_unlock_irqrestore(&ec->lock, flags); @@ -309,12 +307,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) } } if (ec_wait_ibf0(ec)) { - pr_err(PREFIX "input buffer is not empty, " + pr_err("input buffer is not empty, " "aborting transaction\n"); status = -ETIME; goto end; } - pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n", + pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n", t->command, t->wdata ? t->wdata[0] : 0); /* disable GPE during transaction if storm is detected */ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { @@ -331,12 +329,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) /* It is safe to enable the GPE outside of the transaction. */ acpi_enable_gpe(NULL, ec->gpe); } else if (t->irq_count > ec_storm_threshold) { - pr_info(PREFIX "GPE storm detected(%d GPEs), " + pr_info("GPE storm detected(%d GPEs), " "transactions will use polling mode\n", t->irq_count); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } - pr_debug(PREFIX "transaction end\n"); + pr_debug("transaction end\n"); end: if (ec->global_lock) acpi_release_global_lock(glk); @@ -570,12 +568,12 @@ static void acpi_ec_run(void *cxt) struct acpi_ec_query_handler *handler = cxt; if (!handler) return; - pr_debug(PREFIX "start query execution\n"); + pr_debug("start query execution\n"); if (handler->func) handler->func(handler->data); else if (handler->handle) acpi_evaluate_object(handler->handle, NULL, NULL, NULL); - pr_debug(PREFIX "stop query execution\n"); + pr_debug("stop query execution\n"); kfree(handler); } @@ -593,7 +591,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec) if (!copy) return -ENOMEM; memcpy(copy, handler, sizeof(*copy)); - pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); + pr_debug("push query execution (0x%2x) on queue\n", + value); return acpi_os_execute((copy->func) ? OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, acpi_ec_run, copy); @@ -616,7 +615,7 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) { if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { - pr_debug(PREFIX "push gpe query to the queue\n"); + pr_debug("push gpe query to the queue\n"); return acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ec_gpe_query, ec); } @@ -630,7 +629,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, struct acpi_ec *ec = data; u8 status = acpi_ec_read_status(ec); - pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status); + pr_debug("~~~> interrupt, status:0x%02x\n", status); advance_transaction(ec, status); if (ec_transaction_done(ec) && @@ -776,7 +775,7 @@ static int ec_install_handlers(struct acpi_ec *ec) * The AE_NOT_FOUND error will be ignored and OS * continue to initialize EC. */ - printk(KERN_ERR "Fail in evaluating the _REG object" + pr_err("Fail in evaluating the _REG object" " of EC device. Broken bios is suspected.\n"); } else { acpi_remove_gpe_handler(NULL, ec->gpe, @@ -795,10 +794,10 @@ static void ec_remove_handlers(struct acpi_ec *ec) acpi_disable_gpe(NULL, ec->gpe); if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) - pr_err(PREFIX "failed to remove space handler\n"); + pr_err("failed to remove space handler\n"); if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler))) - pr_err(PREFIX "failed to remove gpe handler\n"); + pr_err("failed to remove gpe handler\n"); clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); } @@ -840,7 +839,7 @@ static int acpi_ec_add(struct acpi_device *device) ret = !!request_region(ec->command_addr, 1, "EC cmd"); WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr); - pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", + pr_info("GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", ec->gpe, ec->command_addr, ec->data_addr); ret = ec_install_handlers(ec); @@ -931,7 +930,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id) /* MSI EC needs special treatment, enable it */ static int ec_flag_msi(const struct dmi_system_id *id) { - printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n"); + pr_debug("Detected MSI hardware, enabling workarounds.\n"); EC_FLAGS_MSI = 1; EC_FLAGS_VALIDATE_ECDT = 1; return 0; @@ -1010,7 +1009,7 @@ int __init acpi_ec_ecdt_probe(void) status = acpi_get_table(ACPI_SIG_ECDT, 1, (struct acpi_table_header **)&ecdt_ptr); if (ACPI_SUCCESS(status)) { - pr_info(PREFIX "EC description table is found, configuring boot EC\n"); + pr_info("EC description table is found, configuring boot EC\n"); boot_ec->command_addr = ecdt_ptr->control.address; boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->gpe = ecdt_ptr->gpe; @@ -1030,7 +1029,7 @@ int __init acpi_ec_ecdt_probe(void) /* This workaround is needed only on some broken machines, * which require early EC, but fail to provide ECDT */ - printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); + pr_debug("Look up EC in DSDT\n"); status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, boot_ec, NULL); /* Check that acpi_get_devices actually find something */ @@ -1042,7 +1041,7 @@ int __init acpi_ec_ecdt_probe(void) saved_ec->data_addr != boot_ec->data_addr || saved_ec->gpe != boot_ec->gpe || saved_ec->handle != boot_ec->handle) - pr_info(PREFIX "ASUSTek keeps feeding us with broken " + pr_info("ASUSTek keeps feeding us with broken " "ECDT tables, which are very hard to workaround. " "Trying to use DSDT EC info instead. Please send " "output of acpidump to linux-acpi@vger.kernel.org\n"); -- cgit v0.10.2 From c48b156517348a0130e9e6edbeba95f9b4e50d65 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 12 Sep 2013 03:32:05 -0400 Subject: ACPI / sysfs: make GPE sysfs attributes only accept correct values According to the design, GPE sysfs attributes should accept "disable", "enable", "clear" and integer numbers as params. Current code checks "disable", "enable" and "clear" first. If the param doesn't match, pass it to strtoul() as a string representing an integer number and assign the return value to the given GPE count. It is missing the check of whether or not the param really represents an integer number and strtoul() will return 0 if the string is not a number. This causes any params except for "enable", "disable", "clear" and a number to make the GPE count become 0. This patch is to use kstrtoul() to replace strtoul() and check the return value. If the convertion is successful, use as the new GPE count. If not, return an error. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 05306a5..b557787 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -564,6 +564,7 @@ static ssize_t counter_set(struct kobject *kobj, acpi_event_status status; acpi_handle handle; int result = 0; + unsigned long tmp; if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) { int i; @@ -596,8 +597,10 @@ static ssize_t counter_set(struct kobject *kobj, else if (!strcmp(buf, "clear\n") && (status & ACPI_EVENT_FLAG_SET)) result = acpi_clear_gpe(handle, index); + else if (!kstrtoul(buf, 0, &tmp)) + all_counters[index].count = tmp; else - all_counters[index].count = strtoul(buf, NULL, 0); + result = -EINVAL; } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { int event = index - num_gpes; if (!strcmp(buf, "disable\n") && @@ -609,8 +612,10 @@ static ssize_t counter_set(struct kobject *kobj, else if (!strcmp(buf, "clear\n") && (status & ACPI_EVENT_FLAG_SET)) result = acpi_clear_event(event); + else if (!kstrtoul(buf, 0, &tmp)) + all_counters[index].count = tmp; else - all_counters[index].count = strtoul(buf, NULL, 0); + result = -EINVAL; } else all_counters[index].count = strtoul(buf, NULL, 0); -- cgit v0.10.2 From cc8ef52707341e67a12067d6ead991d56ea017ca Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 25 Sep 2013 20:39:45 +0800 Subject: ACPI / AC: convert ACPI ac driver to platform bus Signed-off-by: Zhang Rui Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index f37beaa3..324b5a0 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -34,6 +34,7 @@ #include #include #endif +#include #include #include #include @@ -61,39 +62,12 @@ extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); static int acpi_ac_open_fs(struct inode *inode, struct file *file); #endif -static int acpi_ac_add(struct acpi_device *device); -static int acpi_ac_remove(struct acpi_device *device); -static void acpi_ac_notify(struct acpi_device *device, u32 event); - -static const struct acpi_device_id ac_device_ids[] = { - {"ACPI0003", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, ac_device_ids); - -#ifdef CONFIG_PM_SLEEP -static int acpi_ac_resume(struct device *dev); -#endif -static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); - static int ac_sleep_before_get_state_ms; -static struct acpi_driver acpi_ac_driver = { - .name = "ac", - .class = ACPI_AC_CLASS, - .ids = ac_device_ids, - .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, - .ops = { - .add = acpi_ac_add, - .remove = acpi_ac_remove, - .notify = acpi_ac_notify, - }, - .drv.pm = &acpi_ac_pm, -}; - struct acpi_ac { struct power_supply charger; - struct acpi_device * device; + struct acpi_device *adev; + struct platform_device *pdev; unsigned long long state; }; @@ -115,15 +89,13 @@ static const struct file_operations acpi_ac_fops = { static int acpi_ac_get_state(struct acpi_ac *ac) { - acpi_status status = AE_OK; - + acpi_status status; - if (!ac) - return -EINVAL; - - status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state); + status = acpi_evaluate_integer(ac->adev->handle, "_PSR", NULL, + &ac->state); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state")); + ACPI_EXCEPTION((AE_INFO, status, + "Error reading AC Adapter state")); ac->state = ACPI_AC_STATUS_UNKNOWN; return -ENODEV; } @@ -201,36 +173,36 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_ac_seq_show, PDE_DATA(inode)); } -static int acpi_ac_add_fs(struct acpi_device *device) +static int acpi_ac_add_fs(struct acpi_ac *ac) { struct proc_dir_entry *entry = NULL; printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded," " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_ac_dir); - if (!acpi_device_dir(device)) + if (!acpi_device_dir(ac->adev)) { + acpi_device_dir(ac->adev) = + proc_mkdir(acpi_device_bid(ac->adev), acpi_ac_dir); + if (!acpi_device_dir(ac->adev)) return -ENODEV; } /* 'state' [R] */ entry = proc_create_data(ACPI_AC_FILE_STATE, - S_IRUGO, acpi_device_dir(device), - &acpi_ac_fops, acpi_driver_data(device)); + S_IRUGO, acpi_device_dir(ac->adev), + &acpi_ac_fops, ac); if (!entry) return -ENODEV; return 0; } -static int acpi_ac_remove_fs(struct acpi_device *device) +static int acpi_ac_remove_fs(struct acpi_ac *ac) { - if (acpi_device_dir(device)) { - remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device)); - - remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); - acpi_device_dir(device) = NULL; + if (acpi_device_dir(ac->adev)) { + remove_proc_entry(ACPI_AC_FILE_STATE, + acpi_device_dir(ac->adev)); + remove_proc_entry(acpi_device_bid(ac->adev), acpi_ac_dir); + acpi_device_dir(ac->adev) = NULL; } return 0; @@ -241,10 +213,9 @@ static int acpi_ac_remove_fs(struct acpi_device *device) Driver Model -------------------------------------------------------------------------- */ -static void acpi_ac_notify(struct acpi_device *device, u32 event) +static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data) { - struct acpi_ac *ac = acpi_driver_data(device); - + struct acpi_ac *ac = data; if (!ac) return; @@ -267,10 +238,10 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event) msleep(ac_sleep_before_get_state_ms); acpi_ac_get_state(ac); - acpi_bus_generate_netlink_event(device->pnp.device_class, - dev_name(&device->dev), event, - (u32) ac->state); - acpi_notifier_call_chain(device, event, (u32) ac->state); + acpi_bus_generate_netlink_event(ac->adev->pnp.device_class, + dev_name(&ac->pdev->dev), + event, (u32) ac->state); + acpi_notifier_call_chain(ac->adev, event, (u32) ac->state); kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); } @@ -295,50 +266,61 @@ static struct dmi_system_id ac_dmi_table[] = { {}, }; -static int acpi_ac_add(struct acpi_device *device) +static int acpi_ac_probe(struct platform_device *pdev) { int result = 0; struct acpi_ac *ac = NULL; + struct acpi_device *adev; - - if (!device) + if (!pdev) return -EINVAL; + result = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev); + if (result) + return -ENODEV; + ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); if (!ac) return -ENOMEM; - ac->device = device; - strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_AC_CLASS); - device->driver_data = ac; + strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME); + strcpy(acpi_device_class(adev), ACPI_AC_CLASS); + ac->adev = adev; + ac->pdev = pdev; + platform_set_drvdata(pdev, ac); result = acpi_ac_get_state(ac); if (result) goto end; #ifdef CONFIG_ACPI_PROCFS_POWER - result = acpi_ac_add_fs(device); -#endif + result = acpi_ac_add_fs(ac); if (result) goto end; - ac->charger.name = acpi_device_bid(device); +#endif + ac->charger.name = acpi_device_bid(adev); ac->charger.type = POWER_SUPPLY_TYPE_MAINS; ac->charger.properties = ac_props; ac->charger.num_properties = ARRAY_SIZE(ac_props); ac->charger.get_property = get_ac_property; - result = power_supply_register(&ac->device->dev, &ac->charger); + result = power_supply_register(&pdev->dev, &ac->charger); if (result) goto end; + result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev), + ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, ac); + if (result) { + power_supply_unregister(&ac->charger); + goto end; + } printk(KERN_INFO PREFIX "%s [%s] (%s)\n", - acpi_device_name(device), acpi_device_bid(device), + acpi_device_name(adev), acpi_device_bid(adev), ac->state ? "on-line" : "off-line"); end: if (result) { #ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_remove_fs(device); + acpi_ac_remove_fs(ac); #endif kfree(ac); } @@ -356,7 +338,7 @@ static int acpi_ac_resume(struct device *dev) if (!dev) return -EINVAL; - ac = acpi_driver_data(to_acpi_device(dev)); + ac = platform_get_drvdata(to_platform_device(dev)); if (!ac) return -EINVAL; @@ -368,21 +350,24 @@ static int acpi_ac_resume(struct device *dev) return 0; } #endif +static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume); -static int acpi_ac_remove(struct acpi_device *device) +static int acpi_ac_remove(struct platform_device *pdev) { - struct acpi_ac *ac = NULL; - + struct acpi_ac *ac; - if (!device || !acpi_driver_data(device)) + if (!pdev) return -EINVAL; - ac = acpi_driver_data(device); + acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev), + ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler); + ac = platform_get_drvdata(pdev); if (ac->charger.dev) power_supply_unregister(&ac->charger); + #ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_remove_fs(device); + acpi_ac_remove_fs(ac); #endif kfree(ac); @@ -390,6 +375,23 @@ static int acpi_ac_remove(struct acpi_device *device) return 0; } +static const struct acpi_device_id acpi_ac_match[] = { + { "ACPI0003", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, acpi_ac_match); + +static struct platform_driver acpi_ac_driver = { + .probe = acpi_ac_probe, + .remove = acpi_ac_remove, + .driver = { + .name = "acpi-ac", + .owner = THIS_MODULE, + .pm = &acpi_ac_pm_ops, + .acpi_match_table = ACPI_PTR(acpi_ac_match), + }, +}; + static int __init acpi_ac_init(void) { int result; @@ -403,7 +405,7 @@ static int __init acpi_ac_init(void) return -ENODEV; #endif - result = acpi_bus_register_driver(&acpi_ac_driver); + result = platform_driver_register(&acpi_ac_driver); if (result < 0) { #ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_ac_dir(acpi_ac_dir); @@ -416,15 +418,10 @@ static int __init acpi_ac_init(void) static void __exit acpi_ac_exit(void) { - - acpi_bus_unregister_driver(&acpi_ac_driver); - + platform_driver_unregister(&acpi_ac_driver); #ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_ac_dir(acpi_ac_dir); #endif - - return; } - module_init(acpi_ac_init); module_exit(acpi_ac_exit); diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 1bde127..6259bc2 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -29,6 +29,7 @@ ACPI_MODULE_NAME("platform"); static const struct acpi_device_id acpi_platform_device_ids[] = { { "PNP0D40" }, + { "ACPI0003" }, { } }; -- cgit v0.10.2 From 11fa8da5fb14b23ff796c09d61a162a27deeb04f Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 25 Sep 2013 20:39:46 +0800 Subject: ideapad_laptop: introduce #ifdef CONFIG_PM_SLEEP for PM specific code ideapad_acpi_resume() and ideapad_pm is meaningful only if CONFIG_PM_SLEEP is set. Thus introduce #ifdef for this piece of code. Signed-off-by: Zhang Rui CC: Matthew Garrett CC: Ike Panhc Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 89c4519..5021c55 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -901,6 +901,7 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) } } +#ifdef CONFIG_PM_SLEEP static int ideapad_acpi_resume(struct device *device) { ideapad_sync_rfk_state(ideapad_priv); @@ -909,6 +910,7 @@ static int ideapad_acpi_resume(struct device *device) } static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); +#endif static struct acpi_driver ideapad_acpi_driver = { .name = "ideapad_acpi", @@ -917,7 +919,9 @@ static struct acpi_driver ideapad_acpi_driver = { .ops.add = ideapad_acpi_add, .ops.remove = ideapad_acpi_remove, .ops.notify = ideapad_acpi_notify, +#ifdef CONFIG_PM_SLEEP .drv.pm = &ideapad_pm, +#endif .owner = THIS_MODULE, }; module_acpi_driver(ideapad_acpi_driver); -- cgit v0.10.2 From 469f64349c5e7bd072d1ca5a72b8f2a80ef118f2 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 25 Sep 2013 20:39:47 +0800 Subject: ideapad_laptop: introduce struct acpi_device pointer to ideapad_private structure Introduce struct acpi_device pointer to ideapad_private structure. At the same time, replace all adevice with adev to be short and consistent. Signed-off-by: Zhang Rui CC: Matthew Garrett CC: Ike Panhc Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 5021c55..edd3656 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -73,6 +73,7 @@ enum { }; struct ideapad_private { + struct acpi_device *adev; struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM]; struct platform_device *platform_device; struct input_dev *inputdev; @@ -468,9 +469,9 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv) rfkill_set_hw_state(priv->rfk[i], hw_blocked); } -static int ideapad_register_rfkill(struct acpi_device *adevice, int dev) +static int ideapad_register_rfkill(struct acpi_device *adev, int dev) { - struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); + struct ideapad_private *priv = dev_get_drvdata(&adev->dev); int ret; unsigned long sw_blocked; @@ -482,7 +483,7 @@ static int ideapad_register_rfkill(struct acpi_device *adevice, int dev) return 0; } - priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adevice->dev, + priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adev->dev, ideapad_rfk_data[dev].type, &ideapad_rfk_ops, (void *)(long)dev); if (!priv->rfk[dev]) @@ -504,9 +505,9 @@ static int ideapad_register_rfkill(struct acpi_device *adevice, int dev) return 0; } -static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev) +static void ideapad_unregister_rfkill(struct acpi_device *adev, int dev) { - struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); + struct ideapad_private *priv = dev_get_drvdata(&adev->dev); if (!priv->rfk[dev]) return; @@ -761,13 +762,13 @@ static const struct acpi_device_id ideapad_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); -static void ideapad_sync_touchpad_state(struct acpi_device *adevice) +static void ideapad_sync_touchpad_state(struct acpi_device *adev) { - struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); + struct ideapad_private *priv = dev_get_drvdata(&adev->dev); unsigned long value; /* Without reading from EC touchpad LED doesn't switch state */ - if (!read_ec_data(adevice->handle, VPCCMD_R_TOUCHPAD, &value)) { + if (!read_ec_data(adev->handle, VPCCMD_R_TOUCHPAD, &value)) { /* Some IdeaPads don't really turn off touchpad - they only * switch the LED state. We (de)activate KBC AUX port to turn * touchpad off and on. We send KEY_TOUCHPAD_OFF and @@ -779,22 +780,23 @@ static void ideapad_sync_touchpad_state(struct acpi_device *adevice) } } -static int ideapad_acpi_add(struct acpi_device *adevice) +static int ideapad_acpi_add(struct acpi_device *adev) { int ret, i; int cfg; struct ideapad_private *priv; - if (read_method_int(adevice->handle, "_CFG", &cfg)) + if (read_method_int(adev->handle, "_CFG", &cfg)) return -ENODEV; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - dev_set_drvdata(&adevice->dev, priv); + dev_set_drvdata(&adev->dev, priv); ideapad_priv = priv; - ideapad_handle = adevice->handle; + ideapad_handle = adev->handle; priv->cfg = cfg; + priv->adev = adev; ret = ideapad_platform_init(priv); if (ret) @@ -810,12 +812,12 @@ static int ideapad_acpi_add(struct acpi_device *adevice) for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) { if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) - ideapad_register_rfkill(adevice, i); + ideapad_register_rfkill(adev, i); else priv->rfk[i] = NULL; } ideapad_sync_rfk_state(priv); - ideapad_sync_touchpad_state(adevice); + ideapad_sync_touchpad_state(adev); if (!acpi_video_backlight_support()) { ret = ideapad_backlight_init(priv); @@ -827,7 +829,7 @@ static int ideapad_acpi_add(struct acpi_device *adevice) backlight_failed: for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) - ideapad_unregister_rfkill(adevice, i); + ideapad_unregister_rfkill(adev, i); ideapad_input_exit(priv); input_failed: ideapad_debugfs_exit(priv); @@ -838,27 +840,27 @@ platform_failed: return ret; } -static int ideapad_acpi_remove(struct acpi_device *adevice) +static int ideapad_acpi_remove(struct acpi_device *adev) { - struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); + struct ideapad_private *priv = dev_get_drvdata(&adev->dev); int i; ideapad_backlight_exit(priv); for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) - ideapad_unregister_rfkill(adevice, i); + ideapad_unregister_rfkill(adev, i); ideapad_input_exit(priv); ideapad_debugfs_exit(priv); ideapad_platform_exit(priv); - dev_set_drvdata(&adevice->dev, NULL); + dev_set_drvdata(&adev->dev, NULL); kfree(priv); return 0; } -static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) +static void ideapad_acpi_notify(struct acpi_device *adev, u32 event) { - struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); - acpi_handle handle = adevice->handle; + struct ideapad_private *priv = dev_get_drvdata(&adev->dev); + acpi_handle handle = adev->handle; unsigned long vpc1, vpc2, vpc_bit; if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) @@ -880,7 +882,7 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) ideapad_input_report(priv, vpc_bit); break; case 5: - ideapad_sync_touchpad_state(adevice); + ideapad_sync_touchpad_state(adev); break; case 4: ideapad_backlight_notify_brightness(priv); -- cgit v0.10.2 From 75a11f11a49da9862ff2fbae75428076571cebe4 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 25 Sep 2013 20:39:48 +0800 Subject: ideapad_laptop: convert internal function calls to use ideapad_private as parameter As struct ideapad_private has all the information needed for any operations, convert ideapad_register_rfkill()/ideapad_unregister_rfkill() and ideapad_sync_touchpad_state() to use struct ideapad_private as the parameter, to be consistent with the others. Signed-off-by: Zhang Rui CC: Matthew Garrett CC: Ike Panhc Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index edd3656..70fb5ba 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -469,9 +469,8 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv) rfkill_set_hw_state(priv->rfk[i], hw_blocked); } -static int ideapad_register_rfkill(struct acpi_device *adev, int dev) +static int ideapad_register_rfkill(struct ideapad_private *priv, int dev) { - struct ideapad_private *priv = dev_get_drvdata(&adev->dev); int ret; unsigned long sw_blocked; @@ -483,8 +482,10 @@ static int ideapad_register_rfkill(struct acpi_device *adev, int dev) return 0; } - priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adev->dev, - ideapad_rfk_data[dev].type, &ideapad_rfk_ops, + priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, + &priv->adev->dev, + ideapad_rfk_data[dev].type, + &ideapad_rfk_ops, (void *)(long)dev); if (!priv->rfk[dev]) return -ENOMEM; @@ -505,10 +506,8 @@ static int ideapad_register_rfkill(struct acpi_device *adev, int dev) return 0; } -static void ideapad_unregister_rfkill(struct acpi_device *adev, int dev) +static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev) { - struct ideapad_private *priv = dev_get_drvdata(&adev->dev); - if (!priv->rfk[dev]) return; @@ -762,13 +761,12 @@ static const struct acpi_device_id ideapad_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); -static void ideapad_sync_touchpad_state(struct acpi_device *adev) +static void ideapad_sync_touchpad_state(struct ideapad_private *priv) { - struct ideapad_private *priv = dev_get_drvdata(&adev->dev); unsigned long value; /* Without reading from EC touchpad LED doesn't switch state */ - if (!read_ec_data(adev->handle, VPCCMD_R_TOUCHPAD, &value)) { + if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) { /* Some IdeaPads don't really turn off touchpad - they only * switch the LED state. We (de)activate KBC AUX port to turn * touchpad off and on. We send KEY_TOUCHPAD_OFF and @@ -812,12 +810,12 @@ static int ideapad_acpi_add(struct acpi_device *adev) for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) { if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) - ideapad_register_rfkill(adev, i); + ideapad_register_rfkill(priv, i); else priv->rfk[i] = NULL; } ideapad_sync_rfk_state(priv); - ideapad_sync_touchpad_state(adev); + ideapad_sync_touchpad_state(priv); if (!acpi_video_backlight_support()) { ret = ideapad_backlight_init(priv); @@ -829,7 +827,7 @@ static int ideapad_acpi_add(struct acpi_device *adev) backlight_failed: for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) - ideapad_unregister_rfkill(adev, i); + ideapad_unregister_rfkill(priv, i); ideapad_input_exit(priv); input_failed: ideapad_debugfs_exit(priv); @@ -847,7 +845,7 @@ static int ideapad_acpi_remove(struct acpi_device *adev) ideapad_backlight_exit(priv); for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) - ideapad_unregister_rfkill(adev, i); + ideapad_unregister_rfkill(priv, i); ideapad_input_exit(priv); ideapad_debugfs_exit(priv); ideapad_platform_exit(priv); @@ -882,7 +880,7 @@ static void ideapad_acpi_notify(struct acpi_device *adev, u32 event) ideapad_input_report(priv, vpc_bit); break; case 5: - ideapad_sync_touchpad_state(adev); + ideapad_sync_touchpad_state(priv); break; case 4: ideapad_backlight_notify_brightness(priv); @@ -906,8 +904,14 @@ static void ideapad_acpi_notify(struct acpi_device *adev, u32 event) #ifdef CONFIG_PM_SLEEP static int ideapad_acpi_resume(struct device *device) { - ideapad_sync_rfk_state(ideapad_priv); - ideapad_sync_touchpad_state(to_acpi_device(device)); + struct ideapad_private *priv; + + if (!device) + return -EINVAL; + priv = dev_get_drvdata(device); + + ideapad_sync_rfk_state(priv); + ideapad_sync_touchpad_state(priv); return 0; } -- cgit v0.10.2 From 331e0ea243ed15bbf0958f46861505f2065e99f8 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 25 Sep 2013 20:39:49 +0800 Subject: ideapad_laptop: remove ideapad_handle and ideapad_priv The current code use ideapad_handle and ideapad_priv to store some information for the ideapad device. But as they are global/static variables, the driver will be broken if there are more than one ideapad ACPI device node on a platform. Although this does not happen for now and may not happen in the future, but still, this is a software bug. Remove these two variables in this patch. Signed-off-by: Zhang Rui CC: Matthew Garrett CC: Ike Panhc Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 70fb5ba..cad48b5 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -72,9 +72,15 @@ enum { VPCCMD_W_BL_POWER = 0x33, }; +struct ideapad_rfk_priv { + int dev; + struct ideapad_private *priv; +}; + struct ideapad_private { struct acpi_device *adev; struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM]; + struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM]; struct platform_device *platform_device; struct input_dev *inputdev; struct backlight_device *blightdev; @@ -82,8 +88,6 @@ struct ideapad_private { unsigned long cfg; }; -static acpi_handle ideapad_handle; -static struct ideapad_private *ideapad_priv; static bool no_bt_rfkill; module_param(no_bt_rfkill, bool, 0444); MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth."); @@ -201,34 +205,38 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data) */ static int debugfs_status_show(struct seq_file *s, void *data) { + struct ideapad_private *priv = s->private; unsigned long value; - if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &value)) + if (!priv) + return -EINVAL; + + if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value)) seq_printf(s, "Backlight max:\t%lu\n", value); - if (!read_ec_data(ideapad_handle, VPCCMD_R_BL, &value)) + if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value)) seq_printf(s, "Backlight now:\t%lu\n", value); - if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &value)) + if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value)) seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off"); seq_printf(s, "=====================\n"); - if (!read_ec_data(ideapad_handle, VPCCMD_R_RF, &value)) + if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value)) seq_printf(s, "Radio status:\t%s(%lu)\n", value ? "On" : "Off", value); - if (!read_ec_data(ideapad_handle, VPCCMD_R_WIFI, &value)) + if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value)) seq_printf(s, "Wifi status:\t%s(%lu)\n", value ? "On" : "Off", value); - if (!read_ec_data(ideapad_handle, VPCCMD_R_BT, &value)) + if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value)) seq_printf(s, "BT status:\t%s(%lu)\n", value ? "On" : "Off", value); - if (!read_ec_data(ideapad_handle, VPCCMD_R_3G, &value)) + if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value)) seq_printf(s, "3G status:\t%s(%lu)\n", value ? "On" : "Off", value); seq_printf(s, "=====================\n"); - if (!read_ec_data(ideapad_handle, VPCCMD_R_TOUCHPAD, &value)) + if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) seq_printf(s, "Touchpad status:%s(%lu)\n", value ? "On" : "Off", value); - if (!read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &value)) + if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value)) seq_printf(s, "Camera status:\t%s(%lu)\n", value ? "On" : "Off", value); @@ -237,7 +245,7 @@ static int debugfs_status_show(struct seq_file *s, void *data) static int debugfs_status_open(struct inode *inode, struct file *file) { - return single_open(file, debugfs_status_show, NULL); + return single_open(file, debugfs_status_show, inode->i_private); } static const struct file_operations debugfs_status_fops = { @@ -250,21 +258,23 @@ static const struct file_operations debugfs_status_fops = { static int debugfs_cfg_show(struct seq_file *s, void *data) { - if (!ideapad_priv) { + struct ideapad_private *priv = s->private; + + if (!priv) { seq_printf(s, "cfg: N/A\n"); } else { seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ", - ideapad_priv->cfg); - if (test_bit(CFG_BT_BIT, &ideapad_priv->cfg)) + priv->cfg); + if (test_bit(CFG_BT_BIT, &priv->cfg)) seq_printf(s, "Bluetooth "); - if (test_bit(CFG_3G_BIT, &ideapad_priv->cfg)) + if (test_bit(CFG_3G_BIT, &priv->cfg)) seq_printf(s, "3G "); - if (test_bit(CFG_WIFI_BIT, &ideapad_priv->cfg)) + if (test_bit(CFG_WIFI_BIT, &priv->cfg)) seq_printf(s, "Wireless "); - if (test_bit(CFG_CAMERA_BIT, &ideapad_priv->cfg)) + if (test_bit(CFG_CAMERA_BIT, &priv->cfg)) seq_printf(s, "Camera "); seq_printf(s, "\nGraphic: "); - switch ((ideapad_priv->cfg)&0x700) { + switch ((priv->cfg)&0x700) { case 0x100: seq_printf(s, "Intel"); break; @@ -288,7 +298,7 @@ static int debugfs_cfg_show(struct seq_file *s, void *data) static int debugfs_cfg_open(struct inode *inode, struct file *file) { - return single_open(file, debugfs_cfg_show, NULL); + return single_open(file, debugfs_cfg_show, inode->i_private); } static const struct file_operations debugfs_cfg_fops = { @@ -309,14 +319,14 @@ static int ideapad_debugfs_init(struct ideapad_private *priv) goto errout; } - node = debugfs_create_file("cfg", S_IRUGO, priv->debug, NULL, + node = debugfs_create_file("cfg", S_IRUGO, priv->debug, priv, &debugfs_cfg_fops); if (!node) { pr_err("failed to create cfg in debugfs"); goto errout; } - node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL, + node = debugfs_create_file("status", S_IRUGO, priv->debug, priv, &debugfs_status_fops); if (!node) { pr_err("failed to create status in debugfs"); @@ -343,8 +353,9 @@ static ssize_t show_ideapad_cam(struct device *dev, char *buf) { unsigned long result; + struct ideapad_private *priv = dev_get_drvdata(dev); - if (read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &result)) + if (read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result)) return sprintf(buf, "-1\n"); return sprintf(buf, "%lu\n", result); } @@ -354,12 +365,13 @@ static ssize_t store_ideapad_cam(struct device *dev, const char *buf, size_t count) { int ret, state; + struct ideapad_private *priv = dev_get_drvdata(dev); if (!count) return 0; if (sscanf(buf, "%i", &state) != 1) return -EINVAL; - ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state); + ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state); if (ret < 0) return -EIO; return count; @@ -372,8 +384,9 @@ static ssize_t show_ideapad_fan(struct device *dev, char *buf) { unsigned long result; + struct ideapad_private *priv = dev_get_drvdata(dev); - if (read_ec_data(ideapad_handle, VPCCMD_R_FAN, &result)) + if (read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result)) return sprintf(buf, "-1\n"); return sprintf(buf, "%lu\n", result); } @@ -383,6 +396,7 @@ static ssize_t store_ideapad_fan(struct device *dev, const char *buf, size_t count) { int ret, state; + struct ideapad_private *priv = dev_get_drvdata(dev); if (!count) return 0; @@ -390,7 +404,7 @@ static ssize_t store_ideapad_fan(struct device *dev, return -EINVAL; if (state < 0 || state > 4 || state == 3) return -EINVAL; - ret = write_ec_cmd(ideapad_handle, VPCCMD_W_FAN, state); + ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state); if (ret < 0) return -EIO; return count; @@ -416,7 +430,8 @@ static umode_t ideapad_is_visible(struct kobject *kobj, supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg)); else if (attr == &dev_attr_fan_mode.attr) { unsigned long value; - supported = !read_ec_data(ideapad_handle, VPCCMD_R_FAN, &value); + supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN, + &value); } else supported = true; @@ -446,9 +461,9 @@ const struct ideapad_rfk_data ideapad_rfk_data[] = { static int ideapad_rfk_set(void *data, bool blocked) { - unsigned long opcode = (unsigned long)data; + struct ideapad_rfk_priv *priv = data; - return write_ec_cmd(ideapad_handle, opcode, !blocked); + return write_ec_cmd(priv->priv->adev->handle, priv->dev, !blocked); } static struct rfkill_ops ideapad_rfk_ops = { @@ -460,7 +475,7 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv) unsigned long hw_blocked; int i; - if (read_ec_data(ideapad_handle, VPCCMD_R_RF, &hw_blocked)) + if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) return; hw_blocked = !hw_blocked; @@ -477,20 +492,22 @@ static int ideapad_register_rfkill(struct ideapad_private *priv, int dev) if (no_bt_rfkill && (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) { /* Force to enable bluetooth when no_bt_rfkill=1 */ - write_ec_cmd(ideapad_handle, + write_ec_cmd(priv->adev->handle, ideapad_rfk_data[dev].opcode, 1); return 0; } + priv->rfk_priv[dev].dev = dev; + priv->rfk_priv[dev].priv = priv; priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &priv->adev->dev, ideapad_rfk_data[dev].type, &ideapad_rfk_ops, - (void *)(long)dev); + &priv->rfk_priv[dev]); if (!priv->rfk[dev]) return -ENOMEM; - if (read_ec_data(ideapad_handle, ideapad_rfk_data[dev].opcode-1, + if (read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1, &sw_blocked)) { rfkill_init_sw_state(priv->rfk[dev], 0); } else { @@ -623,7 +640,7 @@ static void ideapad_input_novokey(struct ideapad_private *priv) { unsigned long long_pressed; - if (read_ec_data(ideapad_handle, VPCCMD_R_NOVO, &long_pressed)) + if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed)) return; if (long_pressed) ideapad_input_report(priv, 17); @@ -635,7 +652,7 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv) { unsigned long bit, value; - read_ec_data(ideapad_handle, VPCCMD_R_SPECIAL_BUTTONS, &value); + read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value); for (bit = 0; bit < 16; bit++) { if (test_bit(bit, &value)) { @@ -662,19 +679,28 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv) */ static int ideapad_backlight_get_brightness(struct backlight_device *blightdev) { + struct ideapad_private *priv = bl_get_data(blightdev); unsigned long now; - if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now)) + if (!priv) + return -EINVAL; + + if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now)) return -EIO; return now; } static int ideapad_backlight_update_status(struct backlight_device *blightdev) { - if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL, + struct ideapad_private *priv = bl_get_data(blightdev); + + if (!priv) + return -EINVAL; + + if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL, blightdev->props.brightness)) return -EIO; - if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL_POWER, + if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER, blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1)) return -EIO; @@ -692,11 +718,11 @@ static int ideapad_backlight_init(struct ideapad_private *priv) struct backlight_properties props; unsigned long max, now, power; - if (read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &max)) + if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max)) return -EIO; - if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now)) + if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now)) return -EIO; - if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power)) + if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power)) return -EIO; memset(&props, 0, sizeof(struct backlight_properties)); @@ -734,7 +760,7 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv) if (!blightdev) return; - if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power)) + if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power)) return; blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; } @@ -745,7 +771,7 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) /* if we control brightness via acpi video driver */ if (priv->blightdev == NULL) { - read_ec_data(ideapad_handle, VPCCMD_R_BL, &now); + read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); return; } @@ -791,8 +817,6 @@ static int ideapad_acpi_add(struct acpi_device *adev) if (!priv) return -ENOMEM; dev_set_drvdata(&adev->dev, priv); - ideapad_priv = priv; - ideapad_handle = adev->handle; priv->cfg = cfg; priv->adev = adev; -- cgit v0.10.2 From b5c37b798f2d29b9b2926e0abf008a13ce6c91fe Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 25 Sep 2013 20:39:50 +0800 Subject: ideapad_laptop: convert ideapad device/driver to platform bus This patch does two things, 1. enumerate the ideapad device node to platform bus. 2. convert the current driver from ACPI bus to platform bus. Note, with this patch, the platform device node created by ACPI, with the name VPC2004:00, is used as the parent device of the input, backlight, rfkill sysfs class device. Plus the ideapad_platform private sysfs attributes, i.e. camera_power and fan_mode, are also moved to the new platform device node. The previous platform device node "ideapad" is removed. Signed-off-by: Zhang Rui CC: Matthew Garrett CC: Ike Panhc Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 6259bc2..c20b02b 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -30,7 +30,7 @@ static const struct acpi_device_id acpi_platform_device_ids[] = { { "PNP0D40" }, { "ACPI0003" }, - + { "VPC2004" }, { } }; diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index cad48b5..6788acc 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -500,7 +500,7 @@ static int ideapad_register_rfkill(struct ideapad_private *priv, int dev) priv->rfk_priv[dev].priv = priv; priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, - &priv->adev->dev, + &priv->platform_device->dev, ideapad_rfk_data[dev].type, &ideapad_rfk_ops, &priv->rfk_priv[dev]); @@ -535,37 +535,16 @@ static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev) /* * Platform device */ -static int ideapad_platform_init(struct ideapad_private *priv) +static int ideapad_sysfs_init(struct ideapad_private *priv) { - int result; - - priv->platform_device = platform_device_alloc("ideapad", -1); - if (!priv->platform_device) - return -ENOMEM; - platform_set_drvdata(priv->platform_device, priv); - - result = platform_device_add(priv->platform_device); - if (result) - goto fail_platform_device; - - result = sysfs_create_group(&priv->platform_device->dev.kobj, + return sysfs_create_group(&priv->platform_device->dev.kobj, &ideapad_attribute_group); - if (result) - goto fail_sysfs; - return 0; - -fail_sysfs: - platform_device_del(priv->platform_device); -fail_platform_device: - platform_device_put(priv->platform_device); - return result; } -static void ideapad_platform_exit(struct ideapad_private *priv) +static void ideapad_sysfs_exit(struct ideapad_private *priv) { sysfs_remove_group(&priv->platform_device->dev.kobj, &ideapad_attribute_group); - platform_device_unregister(priv->platform_device); } /* @@ -781,12 +760,6 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) /* * module init/exit */ -static const struct acpi_device_id ideapad_device_ids[] = { - { "VPC2004", 0}, - { "", 0}, -}; -MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); - static void ideapad_sync_touchpad_state(struct ideapad_private *priv) { unsigned long value; @@ -804,11 +777,61 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv) } } -static int ideapad_acpi_add(struct acpi_device *adev) +static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) +{ + struct ideapad_private *priv = data; + unsigned long vpc1, vpc2, vpc_bit; + + if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) + return; + if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) + return; + + vpc1 = (vpc2 << 8) | vpc1; + for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) { + if (test_bit(vpc_bit, &vpc1)) { + switch (vpc_bit) { + case 9: + ideapad_sync_rfk_state(priv); + break; + case 13: + case 11: + case 7: + case 6: + ideapad_input_report(priv, vpc_bit); + break; + case 5: + ideapad_sync_touchpad_state(priv); + break; + case 4: + ideapad_backlight_notify_brightness(priv); + break; + case 3: + ideapad_input_novokey(priv); + break; + case 2: + ideapad_backlight_notify_power(priv); + break; + case 0: + ideapad_check_special_buttons(priv); + break; + default: + pr_info("Unknown event: %lu\n", vpc_bit); + } + } + } +} + +static int ideapad_acpi_add(struct platform_device *pdev) { int ret, i; int cfg; struct ideapad_private *priv; + struct acpi_device *adev; + + ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev); + if (ret) + return -ENODEV; if (read_method_int(adev->handle, "_CFG", &cfg)) return -ENODEV; @@ -816,13 +839,15 @@ static int ideapad_acpi_add(struct acpi_device *adev) priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - dev_set_drvdata(&adev->dev, priv); + + dev_set_drvdata(&pdev->dev, priv); priv->cfg = cfg; priv->adev = adev; + priv->platform_device = pdev; - ret = ideapad_platform_init(priv); + ret = ideapad_sysfs_init(priv); if (ret) - goto platform_failed; + goto sysfs_failed; ret = ideapad_debugfs_init(priv); if (ret) @@ -846,9 +871,14 @@ static int ideapad_acpi_add(struct acpi_device *adev) if (ret && ret != -ENODEV) goto backlight_failed; } + ret = acpi_install_notify_handler(adev->handle, + ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv); + if (ret) + goto notification_failed; return 0; - +notification_failed: + ideapad_backlight_exit(priv); backlight_failed: for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) ideapad_unregister_rfkill(priv, i); @@ -856,75 +886,31 @@ backlight_failed: input_failed: ideapad_debugfs_exit(priv); debugfs_failed: - ideapad_platform_exit(priv); -platform_failed: + ideapad_sysfs_exit(priv); +sysfs_failed: kfree(priv); return ret; } -static int ideapad_acpi_remove(struct acpi_device *adev) +static int ideapad_acpi_remove(struct platform_device *pdev) { - struct ideapad_private *priv = dev_get_drvdata(&adev->dev); + struct ideapad_private *priv = dev_get_drvdata(&pdev->dev); int i; + acpi_remove_notify_handler(priv->adev->handle, + ACPI_DEVICE_NOTIFY, ideapad_acpi_notify); ideapad_backlight_exit(priv); for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) ideapad_unregister_rfkill(priv, i); ideapad_input_exit(priv); ideapad_debugfs_exit(priv); - ideapad_platform_exit(priv); - dev_set_drvdata(&adev->dev, NULL); + ideapad_sysfs_exit(priv); + dev_set_drvdata(&pdev->dev, NULL); kfree(priv); return 0; } -static void ideapad_acpi_notify(struct acpi_device *adev, u32 event) -{ - struct ideapad_private *priv = dev_get_drvdata(&adev->dev); - acpi_handle handle = adev->handle; - unsigned long vpc1, vpc2, vpc_bit; - - if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) - return; - if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) - return; - - vpc1 = (vpc2 << 8) | vpc1; - for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) { - if (test_bit(vpc_bit, &vpc1)) { - switch (vpc_bit) { - case 9: - ideapad_sync_rfk_state(priv); - break; - case 13: - case 11: - case 7: - case 6: - ideapad_input_report(priv, vpc_bit); - break; - case 5: - ideapad_sync_touchpad_state(priv); - break; - case 4: - ideapad_backlight_notify_brightness(priv); - break; - case 3: - ideapad_input_novokey(priv); - break; - case 2: - ideapad_backlight_notify_power(priv); - break; - case 0: - ideapad_check_special_buttons(priv); - break; - default: - pr_info("Unknown event: %lu\n", vpc_bit); - } - } - } -} - #ifdef CONFIG_PM_SLEEP static int ideapad_acpi_resume(struct device *device) { @@ -938,23 +924,27 @@ static int ideapad_acpi_resume(struct device *device) ideapad_sync_touchpad_state(priv); return 0; } - -static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); #endif +static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); -static struct acpi_driver ideapad_acpi_driver = { - .name = "ideapad_acpi", - .class = "IdeaPad", - .ids = ideapad_device_ids, - .ops.add = ideapad_acpi_add, - .ops.remove = ideapad_acpi_remove, - .ops.notify = ideapad_acpi_notify, -#ifdef CONFIG_PM_SLEEP - .drv.pm = &ideapad_pm, -#endif - .owner = THIS_MODULE, +static const struct acpi_device_id ideapad_device_ids[] = { + { "VPC2004", 0}, + { "", 0}, }; -module_acpi_driver(ideapad_acpi_driver); +MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); + +static struct platform_driver ideapad_acpi_driver = { + .probe = ideapad_acpi_add, + .remove = ideapad_acpi_remove, + .driver = { + .name = "ideapad_acpi", + .owner = THIS_MODULE, + .pm = &ideapad_pm, + .acpi_match_table = ACPI_PTR(ideapad_device_ids), + }, +}; + +module_platform_driver(ideapad_acpi_driver); MODULE_AUTHOR("David Woodhouse "); MODULE_DESCRIPTION("IdeaPad ACPI Extras"); -- cgit v0.10.2 From 6b68f03f95e3f0aeea0c47799aecb296276a7cd6 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:13:30 +0800 Subject: ACPI / IPMI: Fix potential response buffer overflow This patch enhances sanity checks on message size to avoid potential buffer overflow. The kernel IPMI message size is IPMI_MAX_MSG_LENGTH(272 bytes) while the ACPI specification defined IPMI message size is 64 bytes. The difference is not handled by the original codes. This may cause crash in the response handling codes. This patch closes this gap and also combines rx_data/tx_data to use single data/len pair since they need not be seperate. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index a6977e1..7397135 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -52,6 +52,7 @@ MODULE_LICENSE("GPL"); #define ACPI_IPMI_UNKNOWN 0x07 /* the IPMI timeout is 5s */ #define IPMI_TIMEOUT (5 * HZ) +#define ACPI_IPMI_MAX_MSG_LENGTH 64 struct acpi_ipmi_device { /* the device list attached to driver_data.ipmi_devices */ @@ -90,11 +91,9 @@ struct acpi_ipmi_msg { struct completion tx_complete; struct kernel_ipmi_msg tx_message; int msg_done; - /* tx data . And copy it from ACPI object buffer */ - u8 tx_data[64]; - int tx_len; - u8 rx_data[64]; - int rx_len; + /* tx/rx data . And copy it from/to ACPI object buffer */ + u8 data[ACPI_IPMI_MAX_MSG_LENGTH]; + u8 rx_len; struct acpi_ipmi_device *device; }; @@ -102,7 +101,7 @@ struct acpi_ipmi_msg { struct acpi_ipmi_buffer { u8 status; u8 length; - u8 data[64]; + u8 data[ACPI_IPMI_MAX_MSG_LENGTH]; }; static void ipmi_register_bmc(int iface, struct device *dev); @@ -141,7 +140,7 @@ static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) #define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff) #define IPMI_OP_RGN_CMD(offset) (offset & 0xff) -static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, +static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, acpi_physical_address address, acpi_integer *value) { @@ -157,15 +156,21 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, */ msg->netfn = IPMI_OP_RGN_NETFN(address); msg->cmd = IPMI_OP_RGN_CMD(address); - msg->data = tx_msg->tx_data; + msg->data = tx_msg->data; /* * value is the parameter passed by the IPMI opregion space handler. * It points to the IPMI request message buffer */ buffer = (struct acpi_ipmi_buffer *)value; /* copy the tx message data */ + if (buffer->length > ACPI_IPMI_MAX_MSG_LENGTH) { + dev_WARN_ONCE(&tx_msg->device->pnp_dev->dev, true, + "Unexpected request (msg len %d).\n", + buffer->length); + return -EINVAL; + } msg->data_len = buffer->length; - memcpy(tx_msg->tx_data, buffer->data, msg->data_len); + memcpy(tx_msg->data, buffer->data, msg->data_len); /* * now the default type is SYSTEM_INTERFACE and channel type is BMC. * If the netfn is APP_REQUEST and the cmd is SEND_MESSAGE, @@ -183,6 +188,7 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, device->curr_msgid++; tx_msg->tx_msgid = device->curr_msgid; spin_unlock_irqrestore(&device->tx_msg_lock, flags); + return 0; } static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, @@ -214,7 +220,7 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, */ buffer->status = ACPI_IPMI_OK; buffer->length = msg->rx_len; - memcpy(buffer->data, msg->rx_data, msg->rx_len); + memcpy(buffer->data, msg->data, msg->rx_len); } static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) @@ -250,8 +256,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) dev_warn(&pnp_dev->dev, "Unexpected response is returned. " "returned user %p, expected user %p\n", msg->user, ipmi_device->user_interface); - ipmi_free_recv_msg(msg); - return; + goto out_msg; } spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) { @@ -265,17 +270,21 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) if (!msg_found) { dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " "returned.\n", msg->msgid); - ipmi_free_recv_msg(msg); - return; + goto out_msg; } - if (msg->msg.data_len) { - /* copy the response data to Rx_data buffer */ - memcpy(tx_msg->rx_data, msg->msg_data, msg->msg.data_len); + /* copy the response data to Rx_data buffer */ + if (msg->msg.data_len > ACPI_IPMI_MAX_MSG_LENGTH) { + dev_WARN_ONCE(&pnp_dev->dev, true, + "Unexpected response (msg len %d).\n", + msg->msg.data_len); + } else { tx_msg->rx_len = msg->msg.data_len; + memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len); tx_msg->msg_done = 1; } complete(&tx_msg->tx_complete); +out_msg: ipmi_free_recv_msg(msg); }; @@ -398,7 +407,10 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, if (!tx_msg) return AE_NO_MEMORY; - acpi_format_ipmi_msg(tx_msg, address, value); + if (acpi_format_ipmi_request(tx_msg, address, value) != 0) { + status = AE_TYPE; + goto out_msg; + } spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); @@ -409,17 +421,18 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, NULL, 0, 0, 0); if (err) { status = AE_ERROR; - goto end_label; + goto out_list; } rem_time = wait_for_completion_timeout(&tx_msg->tx_complete, IPMI_TIMEOUT); acpi_format_ipmi_response(tx_msg, value, rem_time); status = AE_OK; -end_label: +out_list: spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_del(&tx_msg->head); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); +out_msg: kfree(tx_msg); return status; } -- cgit v0.10.2 From 5ac557ef4951ea4b131ae45b08434546cb386ac5 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:13:39 +0800 Subject: ACPI / IPMI: Fix race caused by the unprotected ACPI IPMI transfers This patch fixes races caused by unprotected ACPI IPMI transfers. We can see that the following crashes may occur: 1. There is no tx_msg_lock held for iterating tx_msg_list in ipmi_flush_tx_msg() while it may be unlinked on failure in parallel in acpi_ipmi_space_handler() under tx_msg_lock. 2. There is no lock held for freeing tx_msg in acpi_ipmi_space_handler() while it may be accessed in parallel in ipmi_flush_tx_msg() and ipmi_msg_handler(). This patch enhances tx_msg_lock to protect all tx_msg accesses to solve this issue. Then tx_msg_lock is always held around complete() and tx_msg accesses. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 7397135..87307ba 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -228,11 +228,14 @@ static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) struct acpi_ipmi_msg *tx_msg, *temp; int count = HZ / 10; struct pnp_dev *pnp_dev = ipmi->pnp_dev; + unsigned long flags; + spin_lock_irqsave(&ipmi->tx_msg_lock, flags); list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) { /* wake up the sleep thread on the Tx msg */ complete(&tx_msg->tx_complete); } + spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags); /* wait for about 100ms to flush the tx message list */ while (count--) { @@ -266,11 +269,10 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) } } - spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); if (!msg_found) { dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " "returned.\n", msg->msgid); - goto out_msg; + goto out_lock; } /* copy the response data to Rx_data buffer */ @@ -284,6 +286,8 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) tx_msg->msg_done = 1; } complete(&tx_msg->tx_complete); +out_lock: + spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); out_msg: ipmi_free_recv_msg(msg); }; -- cgit v0.10.2 From 8584ec6ae9cc386de344e0d33b60f76368bb73ab Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:13:47 +0800 Subject: ACPI / IPMI: Fix race caused by the timed out ACPI IPMI transfers This patch fixes races caused by timed out ACPI IPMI transfers. This patch uses timeout mechanism provided by ipmi_si to avoid the race that the msg_done flag is set but without any protection, its content can be invalid. Thanks for the suggestion of Corey Minyard. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 87307ba..9171a1a 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -51,7 +51,7 @@ MODULE_LICENSE("GPL"); #define ACPI_IPMI_TIMEOUT 0x10 #define ACPI_IPMI_UNKNOWN 0x07 /* the IPMI timeout is 5s */ -#define IPMI_TIMEOUT (5 * HZ) +#define IPMI_TIMEOUT (5000) #define ACPI_IPMI_MAX_MSG_LENGTH 64 struct acpi_ipmi_device { @@ -135,6 +135,7 @@ static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) init_completion(&ipmi_msg->tx_complete); INIT_LIST_HEAD(&ipmi_msg->head); ipmi_msg->device = ipmi; + ipmi_msg->msg_done = ACPI_IPMI_UNKNOWN; return ipmi_msg; } @@ -192,7 +193,7 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, } static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, - acpi_integer *value, int rem_time) + acpi_integer *value) { struct acpi_ipmi_buffer *buffer; @@ -201,24 +202,17 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, * IPMI message returned by IPMI command. */ buffer = (struct acpi_ipmi_buffer *)value; - if (!rem_time && !msg->msg_done) { - buffer->status = ACPI_IPMI_TIMEOUT; - return; - } /* - * If the flag of msg_done is not set or the recv length is zero, it - * means that the IPMI command is not executed correctly. - * The status code will be ACPI_IPMI_UNKNOWN. + * If the flag of msg_done is not set, it means that the IPMI command is + * not executed correctly. */ - if (!msg->msg_done || !msg->rx_len) { - buffer->status = ACPI_IPMI_UNKNOWN; + buffer->status = msg->msg_done; + if (msg->msg_done != ACPI_IPMI_OK) return; - } /* * If the IPMI response message is obtained correctly, the status code * will be ACPI_IPMI_OK */ - buffer->status = ACPI_IPMI_OK; buffer->length = msg->rx_len; memcpy(buffer->data, msg->data, msg->rx_len); } @@ -280,11 +274,23 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) dev_WARN_ONCE(&pnp_dev->dev, true, "Unexpected response (msg len %d).\n", msg->msg.data_len); - } else { - tx_msg->rx_len = msg->msg.data_len; - memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len); - tx_msg->msg_done = 1; + goto out_comp; } + /* response msg is an error msg */ + msg->recv_type = IPMI_RESPONSE_RECV_TYPE; + if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE && + msg->msg.data_len == 1) { + if (msg->msg.data[0] == IPMI_TIMEOUT_COMPLETION_CODE) { + dev_WARN_ONCE(&pnp_dev->dev, true, + "Unexpected response (timeout).\n"); + tx_msg->msg_done = ACPI_IPMI_TIMEOUT; + } + goto out_comp; + } + tx_msg->rx_len = msg->msg.data_len; + memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len); + tx_msg->msg_done = ACPI_IPMI_OK; +out_comp: complete(&tx_msg->tx_complete); out_lock: spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); @@ -392,7 +398,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, { struct acpi_ipmi_msg *tx_msg; struct acpi_ipmi_device *ipmi_device = handler_context; - int err, rem_time; + int err; acpi_status status; unsigned long flags; /* @@ -422,14 +428,13 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, &tx_msg->addr, tx_msg->tx_msgid, &tx_msg->tx_message, - NULL, 0, 0, 0); + NULL, 0, 0, IPMI_TIMEOUT); if (err) { status = AE_ERROR; goto out_list; } - rem_time = wait_for_completion_timeout(&tx_msg->tx_complete, - IPMI_TIMEOUT); - acpi_format_ipmi_response(tx_msg, value, rem_time); + wait_for_completion(&tx_msg->tx_complete); + acpi_format_ipmi_response(tx_msg, value); status = AE_OK; out_list: -- cgit v0.10.2 From a1a69b297e4775298d6407357332ea1adc218396 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:13:54 +0800 Subject: ACPI / IPMI: Fix race caused by the unprotected ACPI IPMI user This patch uses reference counting to fix the race caused by the unprotected ACPI IPMI user. There are two rules for using the ipmi_si APIs: 1. In ipmi_si, ipmi_destroy_user() can ensure that no ipmi_recv_msg will be passed to ipmi_msg_handler(), but ipmi_request_settime() can not use an invalid ipmi_user_t. This means the ipmi_si users must ensure that there won't be any local references on ipmi_user_t before invoking ipmi_destroy_user(). 2. In ipmi_si, the smi_gone()/new_smi() callbacks are protected by smi_watchers_mutex, so their execution is serialized. But as a new smi can re-use a freed intf_num, it requires that the callback implementation must not use intf_num as an identification mean or it must ensure all references to the previous smi are all dropped before exiting smi_gone() callback. As the acpi_ipmi_device->user_interface check in acpi_ipmi_space_handler() can happen before setting user_interface to NULL and codes after the check in acpi_ipmi_space_handler() can happen after user_interface becomes NULL, the on-going acpi_ipmi_space_handler() still can pass an invalid acpi_ipmi_device->user_interface to ipmi_request_settime(). Such race conditions are not allowed by the IPMI layer's API design as a crash will happen in ipmi_request_settime() if something like that happens. This patch follows the ipmi_devintf.c design: 1. Invoke ipmi_destroy_user() after the reference count of acpi_ipmi_device drops to 0. References of acpi_ipmi_device dropping to 0 also means tx_msg related to this acpi_ipmi_device are all freed. This matches the IPMI layer's API calling rule on ipmi_destroy_user() and ipmi_request_settime(). 2. ipmi_flush_tx_msg() is performed so that no on-going tx_msg can still be running in acpi_ipmi_space_handler(). And it is invoked after invoking __ipmi_dev_kill() where acpi_ipmi_device is deleted from the list with a "dead" flag set, and the "dead" flag check is also introduced to the point where a tx_msg is going to be added to the tx_msg_list so that no new tx_msg can be created after returning from the __ipmi_dev_kill(). 3. The waiting codes in ipmi_flush_tx_msg() is deleted because it is not required since this patch ensures no acpi_ipmi reference is still held for ipmi_user_t before calling ipmi_destroy_user() and ipmi_destroy_user() can ensure no more ipmi_msg_handler() can happen after returning from ipmi_destroy_user(). 4. The flushing of tx_msg is also moved out of ipmi_lock in this patch. The forthcoming IPMI operation region handler installation changes also requires acpi_ipmi_device be handled in this style. The header comment of the file is also updated due to this design change. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 9171a1a..b285386 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -1,8 +1,9 @@ /* * acpi_ipmi.c - ACPI IPMI opregion * - * Copyright (C) 2010 Intel Corporation - * Copyright (C) 2010 Zhao Yakui + * Copyright (C) 2010, 2013 Intel Corporation + * Author: Zhao Yakui + * Lv Zheng * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -67,6 +68,8 @@ struct acpi_ipmi_device { long curr_msgid; unsigned long flags; struct ipmi_smi_info smi_data; + bool dead; + struct kref kref; }; struct ipmi_driver_data { @@ -107,8 +110,8 @@ struct acpi_ipmi_buffer { static void ipmi_register_bmc(int iface, struct device *dev); static void ipmi_bmc_gone(int iface); static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); -static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device); -static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device); +static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi); +static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi); static struct ipmi_driver_data driver_data = { .ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices), @@ -122,6 +125,88 @@ static struct ipmi_driver_data driver_data = { }, }; +static struct acpi_ipmi_device * +ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle) +{ + struct acpi_ipmi_device *ipmi_device; + int err; + ipmi_user_t user; + + ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL); + if (!ipmi_device) + return NULL; + + kref_init(&ipmi_device->kref); + INIT_LIST_HEAD(&ipmi_device->head); + INIT_LIST_HEAD(&ipmi_device->tx_msg_list); + spin_lock_init(&ipmi_device->tx_msg_lock); + + ipmi_device->handle = handle; + ipmi_device->pnp_dev = to_pnp_dev(get_device(smi_data->dev)); + memcpy(&ipmi_device->smi_data, smi_data, sizeof(struct ipmi_smi_info)); + ipmi_device->ipmi_ifnum = iface; + + err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs, + ipmi_device, &user); + if (err) { + put_device(smi_data->dev); + kfree(ipmi_device); + return NULL; + } + ipmi_device->user_interface = user; + ipmi_install_space_handler(ipmi_device); + + return ipmi_device; +} + +static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device) +{ + ipmi_remove_space_handler(ipmi_device); + ipmi_destroy_user(ipmi_device->user_interface); + put_device(ipmi_device->smi_data.dev); + kfree(ipmi_device); +} + +static void ipmi_dev_release_kref(struct kref *kref) +{ + struct acpi_ipmi_device *ipmi = + container_of(kref, struct acpi_ipmi_device, kref); + + ipmi_dev_release(ipmi); +} + +static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device) +{ + list_del(&ipmi_device->head); + /* + * Always setting dead flag after deleting from the list or + * list_for_each_entry() codes must get changed. + */ + ipmi_device->dead = true; +} + +static struct acpi_ipmi_device *acpi_ipmi_dev_get(int iface) +{ + struct acpi_ipmi_device *temp, *ipmi_device = NULL; + + mutex_lock(&driver_data.ipmi_lock); + list_for_each_entry(temp, &driver_data.ipmi_devices, head) { + if (temp->ipmi_ifnum == iface) { + ipmi_device = temp; + kref_get(&ipmi_device->kref); + break; + } + } + mutex_unlock(&driver_data.ipmi_lock); + + return ipmi_device; +} + +static void acpi_ipmi_dev_put(struct acpi_ipmi_device *ipmi_device) +{ + kref_put(&ipmi_device->kref, ipmi_dev_release_kref); +} + static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) { struct acpi_ipmi_msg *ipmi_msg; @@ -220,25 +305,22 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) { struct acpi_ipmi_msg *tx_msg, *temp; - int count = HZ / 10; - struct pnp_dev *pnp_dev = ipmi->pnp_dev; unsigned long flags; + /* + * NOTE: On-going ipmi_recv_msg + * ipmi_msg_handler() may still be invoked by ipmi_si after + * flushing. But it is safe to do a fast flushing on module_exit() + * without waiting for all ipmi_recv_msg(s) to complete from + * ipmi_msg_handler() as it is ensured by ipmi_si that all + * ipmi_recv_msg(s) are freed after invoking ipmi_destroy_user(). + */ spin_lock_irqsave(&ipmi->tx_msg_lock, flags); list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) { /* wake up the sleep thread on the Tx msg */ complete(&tx_msg->tx_complete); } spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags); - - /* wait for about 100ms to flush the tx message list */ - while (count--) { - if (list_empty(&ipmi->tx_msg_list)) - break; - schedule_timeout(1); - } - if (!list_empty(&ipmi->tx_msg_list)) - dev_warn(&pnp_dev->dev, "tx msg list is not NULL\n"); } static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) @@ -302,7 +384,6 @@ static void ipmi_register_bmc(int iface, struct device *dev) { struct acpi_ipmi_device *ipmi_device, *temp; struct pnp_dev *pnp_dev; - ipmi_user_t user; int err; struct ipmi_smi_info smi_data; acpi_handle handle; @@ -312,12 +393,18 @@ static void ipmi_register_bmc(int iface, struct device *dev) if (err) return; - if (smi_data.addr_src != SI_ACPI) { - put_device(smi_data.dev); - return; - } - + if (smi_data.addr_src != SI_ACPI) + goto err_ref; handle = smi_data.addr_info.acpi_info.acpi_handle; + if (!handle) + goto err_ref; + pnp_dev = to_pnp_dev(smi_data.dev); + + ipmi_device = ipmi_dev_alloc(iface, &smi_data, handle); + if (!ipmi_device) { + dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n"); + goto err_ref; + } mutex_lock(&driver_data.ipmi_lock); list_for_each_entry(temp, &driver_data.ipmi_devices, head) { @@ -326,34 +413,18 @@ static void ipmi_register_bmc(int iface, struct device *dev) * to the device list, don't add it again. */ if (temp->handle == handle) - goto out; + goto err_lock; } - ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL); - - if (!ipmi_device) - goto out; - - pnp_dev = to_pnp_dev(smi_data.dev); - ipmi_device->handle = handle; - ipmi_device->pnp_dev = pnp_dev; - - err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs, - ipmi_device, &user); - if (err) { - dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n"); - kfree(ipmi_device); - goto out; - } - acpi_add_ipmi_device(ipmi_device); - ipmi_device->user_interface = user; - ipmi_device->ipmi_ifnum = iface; + list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); mutex_unlock(&driver_data.ipmi_lock); - memcpy(&ipmi_device->smi_data, &smi_data, sizeof(struct ipmi_smi_info)); + put_device(smi_data.dev); return; -out: +err_lock: mutex_unlock(&driver_data.ipmi_lock); + ipmi_dev_release(ipmi_device); +err_ref: put_device(smi_data.dev); return; } @@ -361,19 +432,22 @@ out: static void ipmi_bmc_gone(int iface) { struct acpi_ipmi_device *ipmi_device, *temp; + bool dev_found = false; mutex_lock(&driver_data.ipmi_lock); list_for_each_entry_safe(ipmi_device, temp, &driver_data.ipmi_devices, head) { - if (ipmi_device->ipmi_ifnum != iface) - continue; - - acpi_remove_ipmi_device(ipmi_device); - put_device(ipmi_device->smi_data.dev); - kfree(ipmi_device); - break; + if (ipmi_device->ipmi_ifnum != iface) { + dev_found = true; + __ipmi_dev_kill(ipmi_device); + break; + } } mutex_unlock(&driver_data.ipmi_lock); + if (dev_found) { + ipmi_flush_tx_msg(ipmi_device); + acpi_ipmi_dev_put(ipmi_device); + } } /* -------------------------------------------------------------------------- * Address Space Management @@ -397,7 +471,8 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, void *handler_context, void *region_context) { struct acpi_ipmi_msg *tx_msg; - struct acpi_ipmi_device *ipmi_device = handler_context; + int iface = (long)handler_context; + struct acpi_ipmi_device *ipmi_device; int err; acpi_status status; unsigned long flags; @@ -410,20 +485,31 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, if ((function & ACPI_IO_MASK) == ACPI_READ) return AE_TYPE; - if (!ipmi_device->user_interface) + ipmi_device = acpi_ipmi_dev_get(iface); + if (!ipmi_device) return AE_NOT_EXIST; tx_msg = acpi_alloc_ipmi_msg(ipmi_device); - if (!tx_msg) - return AE_NO_MEMORY; + if (!tx_msg) { + status = AE_NO_MEMORY; + goto out_ref; + } if (acpi_format_ipmi_request(tx_msg, address, value) != 0) { status = AE_TYPE; goto out_msg; } + mutex_lock(&driver_data.ipmi_lock); + /* Do not add a tx_msg that can not be flushed. */ + if (ipmi_device->dead) { + status = AE_NOT_EXIST; + mutex_unlock(&driver_data.ipmi_lock); + goto out_msg; + } spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); + mutex_unlock(&driver_data.ipmi_lock); err = ipmi_request_settime(ipmi_device->user_interface, &tx_msg->addr, tx_msg->tx_msgid, @@ -443,6 +529,8 @@ out_list: spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); out_msg: kfree(tx_msg); +out_ref: + acpi_ipmi_dev_put(ipmi_device); return status; } @@ -465,9 +553,8 @@ static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi) return 0; status = acpi_install_address_space_handler(ipmi->handle, - ACPI_ADR_SPACE_IPMI, - &acpi_ipmi_space_handler, - NULL, ipmi); + ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, + NULL, (void *)((long)ipmi->ipmi_ifnum)); if (ACPI_FAILURE(status)) { struct pnp_dev *pnp_dev = ipmi->pnp_dev; dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space " @@ -478,36 +565,6 @@ static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi) return 0; } -static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device) -{ - - INIT_LIST_HEAD(&ipmi_device->head); - - spin_lock_init(&ipmi_device->tx_msg_lock); - INIT_LIST_HEAD(&ipmi_device->tx_msg_list); - ipmi_install_space_handler(ipmi_device); - - list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); -} - -static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device) -{ - /* - * If the IPMI user interface is created, it should be - * destroyed. - */ - if (ipmi_device->user_interface) { - ipmi_destroy_user(ipmi_device->user_interface); - ipmi_device->user_interface = NULL; - } - /* flush the Tx_msg list */ - if (!list_empty(&ipmi_device->tx_msg_list)) - ipmi_flush_tx_msg(ipmi_device); - - list_del(&ipmi_device->head); - ipmi_remove_space_handler(ipmi_device); -} - static int __init acpi_ipmi_init(void) { int result = 0; @@ -524,7 +581,7 @@ static int __init acpi_ipmi_init(void) static void __exit acpi_ipmi_exit(void) { - struct acpi_ipmi_device *ipmi_device, *temp; + struct acpi_ipmi_device *ipmi_device; if (acpi_disabled) return; @@ -538,11 +595,17 @@ static void __exit acpi_ipmi_exit(void) * handler and free it. */ mutex_lock(&driver_data.ipmi_lock); - list_for_each_entry_safe(ipmi_device, temp, - &driver_data.ipmi_devices, head) { - acpi_remove_ipmi_device(ipmi_device); - put_device(ipmi_device->smi_data.dev); - kfree(ipmi_device); + while (!list_empty(&driver_data.ipmi_devices)) { + ipmi_device = list_first_entry(&driver_data.ipmi_devices, + struct acpi_ipmi_device, + head); + __ipmi_dev_kill(ipmi_device); + mutex_unlock(&driver_data.ipmi_lock); + + ipmi_flush_tx_msg(ipmi_device); + acpi_ipmi_dev_put(ipmi_device); + + mutex_lock(&driver_data.ipmi_lock); } mutex_unlock(&driver_data.ipmi_lock); } -- cgit v0.10.2 From e96a94edd7ae302168e17daa0198b9ef08b2109d Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:02 +0800 Subject: ACPI / IPMI: Use global IPMI operation region handler It is found on a real machine, in its ACPI namespace, the IPMI OperationRegions (in the ACPI000D - ACPI power meter) are not defined under the IPMI system interface device (the IPI0001 with KCS type returned from _IFT control method): Device (PMI0) { Name (_HID, "ACPI000D") // _HID: Hardware ID OperationRegion (SYSI, IPMI, 0x0600, 0x0100) Field (SYSI, BufferAcc, Lock, Preserve) { AccessAs (BufferAcc, 0x01), Offset (0x58), SCMD, 8, GCMD, 8 } OperationRegion (POWR, IPMI, 0x3000, 0x0100) Field (POWR, BufferAcc, Lock, Preserve) { AccessAs (BufferAcc, 0x01), Offset (0xB3), GPMM, 8 } } Device (PCI0) { Device (ISA) { Device (NIPM) { Name (_HID, EisaId ("IPI0001")) // _HID: Hardware ID Method (_IFT, 0, NotSerialized) // _IFT: IPMI Interface Type { Return (0x01) } } } } Current ACPI_IPMI code registers IPMI operation region handler on a per-device basis, so for the above namespace the IPMI operation region handler is registered only under the scope of \_SB.PCI0.ISA.NIPM. Thus when an IPMI operation region field of \PMI0 is accessed, there are errors reported on such platform: ACPI Error: No handlers for Region [IPMI] ACPI Error: Region IPMI(7) has no handler The solution is to install an IPMI operation region handler from root node so that every object that defines IPMI OperationRegion can get an address space handler registered. When an IPMI operation region field is accessed, the Network Function (0x06 for SYSI and 0x30 for POWR) and the Command (SCMD, GCMD, GPMM) are passed to the operation region handler, there is no system interface specified by the BIOS. The patch tries to select one system interface by monitoring the system interface notification. IPMI messages passed from the ACPI codes are sent to this selected global IPMI system interface. The ACPI_IPMI will always select the first registered IPMI interface with an ACPI handle (i.e., defined in the ACPI namespace). It's hard to determine the selection when there are multiple IPMI system interfaces defined in the ACPI namespace. According to the IPMI specification: A BMC device may make available multiple system interfaces, but only one management controller is allowed to be 'active' BMC that provides BMC functionality for the system (in case of a 'partitioned' system, there can be only one active BMC per partition). Only the system interface(s) for the active BMC allowed to respond to the 'Get Device Id' command. According to the ipmi_si desigin: The ipmi_si registeration notifications can only happen after a successful "Get Device ID" command. Thus it should be OK for non-partitioned systems to do such selection. However, we do not have much knowledge on 'partitioned' systems. References: https://bugzilla.kernel.org/show_bug.cgi?id=46741 Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index b285386..7ec4cd1 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -46,7 +46,6 @@ MODULE_AUTHOR("Zhao Yakui"); MODULE_DESCRIPTION("ACPI IPMI Opregion driver"); MODULE_LICENSE("GPL"); -#define IPMI_FLAGS_HANDLER_INSTALL 0 #define ACPI_IPMI_OK 0 #define ACPI_IPMI_TIMEOUT 0x10 @@ -66,7 +65,6 @@ struct acpi_ipmi_device { ipmi_user_t user_interface; int ipmi_ifnum; /* IPMI interface number */ long curr_msgid; - unsigned long flags; struct ipmi_smi_info smi_data; bool dead; struct kref kref; @@ -77,6 +75,14 @@ struct ipmi_driver_data { struct ipmi_smi_watcher bmc_events; struct ipmi_user_hndl ipmi_hndlrs; struct mutex ipmi_lock; + /* + * NOTE: IPMI System Interface Selection + * There is no system interface specified by the IPMI operation + * region access. We try to select one system interface with ACPI + * handle set. IPMI messages passed from the ACPI codes are sent + * to this selected global IPMI system interface. + */ + struct acpi_ipmi_device *selected_smi; }; struct acpi_ipmi_msg { @@ -110,8 +116,6 @@ struct acpi_ipmi_buffer { static void ipmi_register_bmc(int iface, struct device *dev); static void ipmi_bmc_gone(int iface); static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); -static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi); -static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi); static struct ipmi_driver_data driver_data = { .ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices), @@ -154,14 +158,12 @@ ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle) return NULL; } ipmi_device->user_interface = user; - ipmi_install_space_handler(ipmi_device); return ipmi_device; } static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device) { - ipmi_remove_space_handler(ipmi_device); ipmi_destroy_user(ipmi_device->user_interface); put_device(ipmi_device->smi_data.dev); kfree(ipmi_device); @@ -178,6 +180,8 @@ static void ipmi_dev_release_kref(struct kref *kref) static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device) { list_del(&ipmi_device->head); + if (driver_data.selected_smi == ipmi_device) + driver_data.selected_smi = NULL; /* * Always setting dead flag after deleting from the list or * list_for_each_entry() codes must get changed. @@ -185,17 +189,14 @@ static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device) ipmi_device->dead = true; } -static struct acpi_ipmi_device *acpi_ipmi_dev_get(int iface) +static struct acpi_ipmi_device *acpi_ipmi_dev_get(void) { - struct acpi_ipmi_device *temp, *ipmi_device = NULL; + struct acpi_ipmi_device *ipmi_device = NULL; mutex_lock(&driver_data.ipmi_lock); - list_for_each_entry(temp, &driver_data.ipmi_devices, head) { - if (temp->ipmi_ifnum == iface) { - ipmi_device = temp; - kref_get(&ipmi_device->kref); - break; - } + if (driver_data.selected_smi) { + ipmi_device = driver_data.selected_smi; + kref_get(&ipmi_device->kref); } mutex_unlock(&driver_data.ipmi_lock); @@ -416,6 +417,8 @@ static void ipmi_register_bmc(int iface, struct device *dev) goto err_lock; } + if (!driver_data.selected_smi) + driver_data.selected_smi = ipmi_device; list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); mutex_unlock(&driver_data.ipmi_lock); put_device(smi_data.dev); @@ -443,6 +446,10 @@ static void ipmi_bmc_gone(int iface) break; } } + if (!driver_data.selected_smi) + driver_data.selected_smi = list_first_entry_or_null( + &driver_data.ipmi_devices, + struct acpi_ipmi_device, head); mutex_unlock(&driver_data.ipmi_lock); if (dev_found) { ipmi_flush_tx_msg(ipmi_device); @@ -471,7 +478,6 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, void *handler_context, void *region_context) { struct acpi_ipmi_msg *tx_msg; - int iface = (long)handler_context; struct acpi_ipmi_device *ipmi_device; int err; acpi_status status; @@ -485,7 +491,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, if ((function & ACPI_IO_MASK) == ACPI_READ) return AE_TYPE; - ipmi_device = acpi_ipmi_dev_get(iface); + ipmi_device = acpi_ipmi_dev_get(); if (!ipmi_device) return AE_NOT_EXIST; @@ -534,47 +540,26 @@ out_ref: return status; } -static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi) -{ - if (!test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags)) - return; - - acpi_remove_address_space_handler(ipmi->handle, - ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler); - - clear_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags); -} - -static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi) -{ - acpi_status status; - - if (test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags)) - return 0; - - status = acpi_install_address_space_handler(ipmi->handle, - ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, - NULL, (void *)((long)ipmi->ipmi_ifnum)); - if (ACPI_FAILURE(status)) { - struct pnp_dev *pnp_dev = ipmi->pnp_dev; - dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space " - "handle\n"); - return -EINVAL; - } - set_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags); - return 0; -} - static int __init acpi_ipmi_init(void) { int result = 0; + acpi_status status; if (acpi_disabled) return result; mutex_init(&driver_data.ipmi_lock); + status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, + NULL, NULL); + if (ACPI_FAILURE(status)) { + pr_warn("Can't register IPMI opregion space handle\n"); + return -EINVAL; + } result = ipmi_smi_watcher_register(&driver_data.bmc_events); + if (result) + pr_err("Can't register IPMI system interface watcher\n"); return result; } @@ -608,6 +593,8 @@ static void __exit acpi_ipmi_exit(void) mutex_lock(&driver_data.ipmi_lock); } mutex_unlock(&driver_data.ipmi_lock); + acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler); } module_init(acpi_ipmi_init); -- cgit v0.10.2 From 7b9844772237e34968ffd4b086d7b5ed36b30856 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:11 +0800 Subject: ACPI / IPMI: Add reference counting for ACPI IPMI transfers This patch adds reference counting for ACPI IPMI transfers to tune the locking granularity of tx_msg_lock. This patch also makes the whole acpi_ipmi module's coding style consistent by using reference counting for all its objects (i.e., acpi_ipmi_device and acpi_ipmi_msg). The acpi_ipmi_msg handling is re-designed using referece counting. 1. tx_msg is always unlinked before complete(), so that it is safe to put complete() out side of tx_msg_lock. 2. tx_msg reference counters are incremented before calling ipmi_request_settime() and tx_msg_lock protection is added to ipmi_cancel_tx_msg() so that a complete() can be safely called in parellel with tx_msg unlinking in failure cases. 3. tx_msg holds a reference to acpi_ipmi_device so that it can be flushed and freed in the contexts other than acpi_ipmi_space_handler(). The lockdep_chains shows all acpi_ipmi locks are leaf locks after the tuning: 1. ipmi_lock is always leaf: irq_context: 0 [ffffffff81a943f8] smi_watchers_mutex [ffffffffa06eca60] driver_data.ipmi_lock irq_context: 0 [ffffffff82767b40] &buffer->mutex [ffffffffa00a6678] s_active#103 [ffffffffa06eca60] driver_data.ipmi_lock 2. without this patch applied, lock used by complete() is held after holding tx_msg_lock: irq_context: 0 [ffffffff82767b40] &buffer->mutex [ffffffffa00a6678] s_active#103 [ffffffffa06ecce8] &(&ipmi_device->tx_msg_lock)->rlock irq_context: 1 [ffffffffa06ecce8] &(&ipmi_device->tx_msg_lock)->rlock irq_context: 1 [ffffffffa06ecce8] &(&ipmi_device->tx_msg_lock)->rlock [ffffffffa06eccf0] &x->wait#25 irq_context: 1 [ffffffffa06ecce8] &(&ipmi_device->tx_msg_lock)->rlock [ffffffffa06eccf0] &x->wait#25 [ffffffff81e36620] &p->pi_lock irq_context: 1 [ffffffffa06ecce8] &(&ipmi_device->tx_msg_lock)->rlock [ffffffffa06eccf0] &x->wait#25 [ffffffff81e36620] &p->pi_lock [ffffffff81e5d0a8] &rq->lock 3. with this patch applied, tx_msg_lock is always leaf: irq_context: 0 [ffffffff82767b40] &buffer->mutex [ffffffffa00a66d8] s_active#107 [ffffffffa07ecdc8] &(&ipmi_device->tx_msg_lock)->rlock irq_context: 1 [ffffffffa07ecdc8] &(&ipmi_device->tx_msg_lock)->rlock Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 7ec4cd1..b9da5ef 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -104,6 +104,7 @@ struct acpi_ipmi_msg { u8 data[ACPI_IPMI_MAX_MSG_LENGTH]; u8 rx_len; struct acpi_ipmi_device *device; + struct kref kref; }; /* IPMI request/response buffer per ACPI 4.0, sec 5.5.2.4.3.2 */ @@ -208,16 +209,20 @@ static void acpi_ipmi_dev_put(struct acpi_ipmi_device *ipmi_device) kref_put(&ipmi_device->kref, ipmi_dev_release_kref); } -static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) +static struct acpi_ipmi_msg *ipmi_msg_alloc(void) { + struct acpi_ipmi_device *ipmi; struct acpi_ipmi_msg *ipmi_msg; - struct pnp_dev *pnp_dev = ipmi->pnp_dev; + ipmi = acpi_ipmi_dev_get(); + if (!ipmi) + return NULL; ipmi_msg = kzalloc(sizeof(struct acpi_ipmi_msg), GFP_KERNEL); - if (!ipmi_msg) { - dev_warn(&pnp_dev->dev, "Can't allocate memory for ipmi_msg\n"); + if (!ipmi_msg) { + acpi_ipmi_dev_put(ipmi); return NULL; } + kref_init(&ipmi_msg->kref); init_completion(&ipmi_msg->tx_complete); INIT_LIST_HEAD(&ipmi_msg->head); ipmi_msg->device = ipmi; @@ -225,6 +230,32 @@ static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi) return ipmi_msg; } +static void ipmi_msg_release(struct acpi_ipmi_msg *tx_msg) +{ + acpi_ipmi_dev_put(tx_msg->device); + kfree(tx_msg); +} + +static void ipmi_msg_release_kref(struct kref *kref) +{ + struct acpi_ipmi_msg *tx_msg = + container_of(kref, struct acpi_ipmi_msg, kref); + + ipmi_msg_release(tx_msg); +} + +static struct acpi_ipmi_msg *acpi_ipmi_msg_get(struct acpi_ipmi_msg *tx_msg) +{ + kref_get(&tx_msg->kref); + + return tx_msg; +} + +static void acpi_ipmi_msg_put(struct acpi_ipmi_msg *tx_msg) +{ + kref_put(&tx_msg->kref, ipmi_msg_release_kref); +} + #define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff) #define IPMI_OP_RGN_CMD(offset) (offset & 0xff) static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, @@ -305,7 +336,7 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) { - struct acpi_ipmi_msg *tx_msg, *temp; + struct acpi_ipmi_msg *tx_msg; unsigned long flags; /* @@ -317,18 +348,47 @@ static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi) * ipmi_recv_msg(s) are freed after invoking ipmi_destroy_user(). */ spin_lock_irqsave(&ipmi->tx_msg_lock, flags); - list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) { + while (!list_empty(&ipmi->tx_msg_list)) { + tx_msg = list_first_entry(&ipmi->tx_msg_list, + struct acpi_ipmi_msg, + head); + list_del(&tx_msg->head); + spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags); + /* wake up the sleep thread on the Tx msg */ complete(&tx_msg->tx_complete); + acpi_ipmi_msg_put(tx_msg); + spin_lock_irqsave(&ipmi->tx_msg_lock, flags); + } + spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags); +} + +static void ipmi_cancel_tx_msg(struct acpi_ipmi_device *ipmi, + struct acpi_ipmi_msg *msg) +{ + struct acpi_ipmi_msg *tx_msg, *temp; + bool msg_found = false; + unsigned long flags; + + spin_lock_irqsave(&ipmi->tx_msg_lock, flags); + list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) { + if (msg == tx_msg) { + msg_found = true; + list_del(&tx_msg->head); + break; + } } spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags); + + if (msg_found) + acpi_ipmi_msg_put(tx_msg); } static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) { struct acpi_ipmi_device *ipmi_device = user_msg_data; - int msg_found = 0; - struct acpi_ipmi_msg *tx_msg; + bool msg_found = false; + struct acpi_ipmi_msg *tx_msg, *temp; struct pnp_dev *pnp_dev = ipmi_device->pnp_dev; unsigned long flags; @@ -339,17 +399,19 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) goto out_msg; } spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); - list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) { + list_for_each_entry_safe(tx_msg, temp, &ipmi_device->tx_msg_list, head) { if (msg->msgid == tx_msg->tx_msgid) { - msg_found = 1; + msg_found = true; + list_del(&tx_msg->head); break; } } + spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); if (!msg_found) { dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " "returned.\n", msg->msgid); - goto out_lock; + goto out_msg; } /* copy the response data to Rx_data buffer */ @@ -375,8 +437,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) tx_msg->msg_done = ACPI_IPMI_OK; out_comp: complete(&tx_msg->tx_complete); -out_lock: - spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); + acpi_ipmi_msg_put(tx_msg); out_msg: ipmi_free_recv_msg(msg); }; @@ -491,26 +552,23 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, if ((function & ACPI_IO_MASK) == ACPI_READ) return AE_TYPE; - ipmi_device = acpi_ipmi_dev_get(); - if (!ipmi_device) + tx_msg = ipmi_msg_alloc(); + if (!tx_msg) return AE_NOT_EXIST; - tx_msg = acpi_alloc_ipmi_msg(ipmi_device); - if (!tx_msg) { - status = AE_NO_MEMORY; - goto out_ref; - } + ipmi_device = tx_msg->device; if (acpi_format_ipmi_request(tx_msg, address, value) != 0) { - status = AE_TYPE; - goto out_msg; + ipmi_msg_release(tx_msg); + return AE_TYPE; } + acpi_ipmi_msg_get(tx_msg); mutex_lock(&driver_data.ipmi_lock); /* Do not add a tx_msg that can not be flushed. */ if (ipmi_device->dead) { - status = AE_NOT_EXIST; mutex_unlock(&driver_data.ipmi_lock); - goto out_msg; + ipmi_msg_release(tx_msg); + return AE_NOT_EXIST; } spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); @@ -523,20 +581,15 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, NULL, 0, 0, IPMI_TIMEOUT); if (err) { status = AE_ERROR; - goto out_list; + goto out_msg; } wait_for_completion(&tx_msg->tx_complete); acpi_format_ipmi_response(tx_msg, value); status = AE_OK; -out_list: - spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); - list_del(&tx_msg->head); - spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); out_msg: - kfree(tx_msg); -out_ref: - acpi_ipmi_dev_put(ipmi_device); + ipmi_cancel_tx_msg(ipmi_device, tx_msg); + acpi_ipmi_msg_put(tx_msg); return status; } -- cgit v0.10.2 From 2fb037b89a3125627f02c40af3e3d38c3228184b Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:21 +0800 Subject: ACPI / IPMI: Cleanup several acpi_ipmi_device members This (trivial) patch: 1. Deletes a member of the acpi_ipmi_device, smi_data, which is not actually used. 2. Updates a member of the acpi_ipmi_device, pnp_dev, which is only used by dev_warn() invocations, so changes it to a struct device. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index b9da5ef..90d57c8 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -61,11 +61,10 @@ struct acpi_ipmi_device { struct list_head tx_msg_list; spinlock_t tx_msg_lock; acpi_handle handle; - struct pnp_dev *pnp_dev; + struct device *dev; ipmi_user_t user_interface; int ipmi_ifnum; /* IPMI interface number */ long curr_msgid; - struct ipmi_smi_info smi_data; bool dead; struct kref kref; }; @@ -131,7 +130,7 @@ static struct ipmi_driver_data driver_data = { }; static struct acpi_ipmi_device * -ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle) +ipmi_dev_alloc(int iface, struct device *dev, acpi_handle handle) { struct acpi_ipmi_device *ipmi_device; int err; @@ -147,14 +146,13 @@ ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle) spin_lock_init(&ipmi_device->tx_msg_lock); ipmi_device->handle = handle; - ipmi_device->pnp_dev = to_pnp_dev(get_device(smi_data->dev)); - memcpy(&ipmi_device->smi_data, smi_data, sizeof(struct ipmi_smi_info)); + ipmi_device->dev = get_device(dev); ipmi_device->ipmi_ifnum = iface; err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs, ipmi_device, &user); if (err) { - put_device(smi_data->dev); + put_device(dev); kfree(ipmi_device); return NULL; } @@ -166,7 +164,7 @@ ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle) static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device) { ipmi_destroy_user(ipmi_device->user_interface); - put_device(ipmi_device->smi_data.dev); + put_device(ipmi_device->dev); kfree(ipmi_device); } @@ -282,7 +280,7 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, buffer = (struct acpi_ipmi_buffer *)value; /* copy the tx message data */ if (buffer->length > ACPI_IPMI_MAX_MSG_LENGTH) { - dev_WARN_ONCE(&tx_msg->device->pnp_dev->dev, true, + dev_WARN_ONCE(tx_msg->device->dev, true, "Unexpected request (msg len %d).\n", buffer->length); return -EINVAL; @@ -389,11 +387,11 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) struct acpi_ipmi_device *ipmi_device = user_msg_data; bool msg_found = false; struct acpi_ipmi_msg *tx_msg, *temp; - struct pnp_dev *pnp_dev = ipmi_device->pnp_dev; + struct device *dev = ipmi_device->dev; unsigned long flags; if (msg->user != ipmi_device->user_interface) { - dev_warn(&pnp_dev->dev, "Unexpected response is returned. " + dev_warn(dev, "Unexpected response is returned. " "returned user %p, expected user %p\n", msg->user, ipmi_device->user_interface); goto out_msg; @@ -409,14 +407,14 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); if (!msg_found) { - dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " + dev_warn(dev, "Unexpected response (msg id %ld) is " "returned.\n", msg->msgid); goto out_msg; } /* copy the response data to Rx_data buffer */ if (msg->msg.data_len > ACPI_IPMI_MAX_MSG_LENGTH) { - dev_WARN_ONCE(&pnp_dev->dev, true, + dev_WARN_ONCE(dev, true, "Unexpected response (msg len %d).\n", msg->msg.data_len); goto out_comp; @@ -426,7 +424,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE && msg->msg.data_len == 1) { if (msg->msg.data[0] == IPMI_TIMEOUT_COMPLETION_CODE) { - dev_WARN_ONCE(&pnp_dev->dev, true, + dev_WARN_ONCE(dev, true, "Unexpected response (timeout).\n"); tx_msg->msg_done = ACPI_IPMI_TIMEOUT; } @@ -445,7 +443,6 @@ out_msg: static void ipmi_register_bmc(int iface, struct device *dev) { struct acpi_ipmi_device *ipmi_device, *temp; - struct pnp_dev *pnp_dev; int err; struct ipmi_smi_info smi_data; acpi_handle handle; @@ -460,11 +457,10 @@ static void ipmi_register_bmc(int iface, struct device *dev) handle = smi_data.addr_info.acpi_info.acpi_handle; if (!handle) goto err_ref; - pnp_dev = to_pnp_dev(smi_data.dev); - ipmi_device = ipmi_dev_alloc(iface, &smi_data, handle); + ipmi_device = ipmi_dev_alloc(iface, smi_data.dev, handle); if (!ipmi_device) { - dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n"); + dev_warn(smi_data.dev, "Can't create IPMI user interface\n"); goto err_ref; } -- cgit v0.10.2 From a194aa43272d22f035e6f862db2d714658a02b36 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:31 +0800 Subject: ACPI / IPMI: Cleanup some initialization codes This (trivial) patch. 1. Changes dynamic mutex initialization to static initialization. 2. Removes one acpi_ipmi_init() variable initialization as it is not needed. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 90d57c8..f7b6598 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -127,6 +127,7 @@ static struct ipmi_driver_data driver_data = { .ipmi_hndlrs = { .ipmi_recv_hndl = ipmi_msg_handler, }, + .ipmi_lock = __MUTEX_INITIALIZER(driver_data.ipmi_lock) }; static struct acpi_ipmi_device * @@ -591,13 +592,11 @@ out_msg: static int __init acpi_ipmi_init(void) { - int result = 0; + int result; acpi_status status; if (acpi_disabled) - return result; - - mutex_init(&driver_data.ipmi_lock); + return 0; status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, -- cgit v0.10.2 From 935a9e3f9d57be122013113318e30e68530b474d Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:41 +0800 Subject: ACPI / IPMI: Cleanup some inclusion codes This (trivial) patch: 1. Deletes several useless header inclusions. 2. Kernel codes should always include instead of or where many conditional declarations are handled. Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index f7b6598..9d187fd 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -24,22 +24,9 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include #include MODULE_AUTHOR("Zhao Yakui"); -- cgit v0.10.2 From 4b88e330914941c86198ca0b48f4ce16f112bbf0 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:14:51 +0800 Subject: ACPI / IPMI: Cleanup some Kconfig codes This (trivial) patch: 1. Deletes duplicate Kconfig dependency as there is "if IPMI_HANDLER" around "IPMI_SI". Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 22327e6..d130e2c 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -175,9 +175,10 @@ config ACPI_PROCESSOR To compile this driver as a module, choose M here: the module will be called processor. + config ACPI_IPMI tristate "IPMI" - depends on IPMI_SI && IPMI_HANDLER + depends on IPMI_SI default n help This driver enables the ACPI to access the BMC controller. And it -- cgit v0.10.2 From 50065300314e95c945665a17febc0c4e02941b06 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 13 Sep 2013 13:15:00 +0800 Subject: ACPI / IPMI: Cleanup coding styles This patch only introduces indentation cleanups. No functional changes. Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index 9d187fd..ac0f52f 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -33,7 +33,6 @@ MODULE_AUTHOR("Zhao Yakui"); MODULE_DESCRIPTION("ACPI IPMI Opregion driver"); MODULE_LICENSE("GPL"); - #define ACPI_IPMI_OK 0 #define ACPI_IPMI_TIMEOUT 0x10 #define ACPI_IPMI_UNKNOWN 0x07 @@ -44,12 +43,14 @@ MODULE_LICENSE("GPL"); struct acpi_ipmi_device { /* the device list attached to driver_data.ipmi_devices */ struct list_head head; + /* the IPMI request message list */ struct list_head tx_msg_list; - spinlock_t tx_msg_lock; + + spinlock_t tx_msg_lock; acpi_handle handle; struct device *dev; - ipmi_user_t user_interface; + ipmi_user_t user_interface; int ipmi_ifnum; /* IPMI interface number */ long curr_msgid; bool dead; @@ -57,10 +58,11 @@ struct acpi_ipmi_device { }; struct ipmi_driver_data { - struct list_head ipmi_devices; - struct ipmi_smi_watcher bmc_events; - struct ipmi_user_hndl ipmi_hndlrs; - struct mutex ipmi_lock; + struct list_head ipmi_devices; + struct ipmi_smi_watcher bmc_events; + struct ipmi_user_hndl ipmi_hndlrs; + struct mutex ipmi_lock; + /* * NOTE: IPMI System Interface Selection * There is no system interface specified by the IPMI operation @@ -73,6 +75,7 @@ struct ipmi_driver_data { struct acpi_ipmi_msg { struct list_head head; + /* * General speaking the addr type should be SI_ADDR_TYPE. And * the addr channel should be BMC. @@ -82,15 +85,19 @@ struct acpi_ipmi_msg { */ struct ipmi_addr addr; long tx_msgid; + /* it is used to track whether the IPMI message is finished */ struct completion tx_complete; + struct kernel_ipmi_msg tx_message; - int msg_done; + int msg_done; + /* tx/rx data . And copy it from/to ACPI object buffer */ - u8 data[ACPI_IPMI_MAX_MSG_LENGTH]; - u8 rx_len; + u8 data[ACPI_IPMI_MAX_MSG_LENGTH]; + u8 rx_len; + struct acpi_ipmi_device *device; - struct kref kref; + struct kref kref; }; /* IPMI request/response buffer per ACPI 4.0, sec 5.5.2.4.3.2 */ @@ -132,7 +139,6 @@ ipmi_dev_alloc(int iface, struct device *dev, acpi_handle handle) INIT_LIST_HEAD(&ipmi_device->head); INIT_LIST_HEAD(&ipmi_device->tx_msg_list); spin_lock_init(&ipmi_device->tx_msg_lock); - ipmi_device->handle = handle; ipmi_device->dev = get_device(dev); ipmi_device->ipmi_ifnum = iface; @@ -169,6 +175,7 @@ static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device) list_del(&ipmi_device->head); if (driver_data.selected_smi == ipmi_device) driver_data.selected_smi = NULL; + /* * Always setting dead flag after deleting from the list or * list_for_each_entry() codes must get changed. @@ -203,16 +210,19 @@ static struct acpi_ipmi_msg *ipmi_msg_alloc(void) ipmi = acpi_ipmi_dev_get(); if (!ipmi) return NULL; + ipmi_msg = kzalloc(sizeof(struct acpi_ipmi_msg), GFP_KERNEL); if (!ipmi_msg) { acpi_ipmi_dev_put(ipmi); return NULL; } + kref_init(&ipmi_msg->kref); init_completion(&ipmi_msg->tx_complete); INIT_LIST_HEAD(&ipmi_msg->head); ipmi_msg->device = ipmi; ipmi_msg->msg_done = ACPI_IPMI_UNKNOWN; + return ipmi_msg; } @@ -242,11 +252,11 @@ static void acpi_ipmi_msg_put(struct acpi_ipmi_msg *tx_msg) kref_put(&tx_msg->kref, ipmi_msg_release_kref); } -#define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff) -#define IPMI_OP_RGN_CMD(offset) (offset & 0xff) +#define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff) +#define IPMI_OP_RGN_CMD(offset) (offset & 0xff) static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, - acpi_physical_address address, - acpi_integer *value) + acpi_physical_address address, + acpi_integer *value) { struct kernel_ipmi_msg *msg; struct acpi_ipmi_buffer *buffer; @@ -254,6 +264,7 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, unsigned long flags; msg = &tx_msg->tx_message; + /* * IPMI network function and command are encoded in the address * within the IPMI OpRegion; see ACPI 4.0, sec 5.5.2.4.3. @@ -261,11 +272,13 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, msg->netfn = IPMI_OP_RGN_NETFN(address); msg->cmd = IPMI_OP_RGN_CMD(address); msg->data = tx_msg->data; + /* * value is the parameter passed by the IPMI opregion space handler. * It points to the IPMI request message buffer */ buffer = (struct acpi_ipmi_buffer *)value; + /* copy the tx message data */ if (buffer->length > ACPI_IPMI_MAX_MSG_LENGTH) { dev_WARN_ONCE(tx_msg->device->dev, true, @@ -275,6 +288,7 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, } msg->data_len = buffer->length; memcpy(tx_msg->data, buffer->data, msg->data_len); + /* * now the default type is SYSTEM_INTERFACE and channel type is BMC. * If the netfn is APP_REQUEST and the cmd is SEND_MESSAGE, @@ -288,15 +302,17 @@ static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg, /* Get the msgid */ device = tx_msg->device; + spin_lock_irqsave(&device->tx_msg_lock, flags); device->curr_msgid++; tx_msg->tx_msgid = device->curr_msgid; spin_unlock_irqrestore(&device->tx_msg_lock, flags); + return 0; } static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, - acpi_integer *value) + acpi_integer *value) { struct acpi_ipmi_buffer *buffer; @@ -305,6 +321,7 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, * IPMI message returned by IPMI command. */ buffer = (struct acpi_ipmi_buffer *)value; + /* * If the flag of msg_done is not set, it means that the IPMI command is * not executed correctly. @@ -312,6 +329,7 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, buffer->status = msg->msg_done; if (msg->msg_done != ACPI_IPMI_OK) return; + /* * If the IPMI response message is obtained correctly, the status code * will be ACPI_IPMI_OK @@ -379,11 +397,12 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) unsigned long flags; if (msg->user != ipmi_device->user_interface) { - dev_warn(dev, "Unexpected response is returned. " - "returned user %p, expected user %p\n", - msg->user, ipmi_device->user_interface); + dev_warn(dev, + "Unexpected response is returned. returned user %p, expected user %p\n", + msg->user, ipmi_device->user_interface); goto out_msg; } + spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_for_each_entry_safe(tx_msg, temp, &ipmi_device->tx_msg_list, head) { if (msg->msgid == tx_msg->tx_msgid) { @@ -395,8 +414,9 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); if (!msg_found) { - dev_warn(dev, "Unexpected response (msg id %ld) is " - "returned.\n", msg->msgid); + dev_warn(dev, + "Unexpected response (msg id %ld) is returned.\n", + msg->msgid); goto out_msg; } @@ -407,6 +427,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) msg->msg.data_len); goto out_comp; } + /* response msg is an error msg */ msg->recv_type = IPMI_RESPONSE_RECV_TYPE; if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE && @@ -418,15 +439,17 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) } goto out_comp; } + tx_msg->rx_len = msg->msg.data_len; memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len); tx_msg->msg_done = ACPI_IPMI_OK; + out_comp: complete(&tx_msg->tx_complete); acpi_ipmi_msg_put(tx_msg); out_msg: ipmi_free_recv_msg(msg); -}; +} static void ipmi_register_bmc(int iface, struct device *dev) { @@ -436,7 +459,6 @@ static void ipmi_register_bmc(int iface, struct device *dev) acpi_handle handle; err = ipmi_get_smi_info(iface, &smi_data); - if (err) return; @@ -461,11 +483,11 @@ static void ipmi_register_bmc(int iface, struct device *dev) if (temp->handle == handle) goto err_lock; } - if (!driver_data.selected_smi) driver_data.selected_smi = ipmi_device; list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); mutex_unlock(&driver_data.ipmi_lock); + put_device(smi_data.dev); return; @@ -484,7 +506,7 @@ static void ipmi_bmc_gone(int iface) mutex_lock(&driver_data.ipmi_lock); list_for_each_entry_safe(ipmi_device, temp, - &driver_data.ipmi_devices, head) { + &driver_data.ipmi_devices, head) { if (ipmi_device->ipmi_ifnum != iface) { dev_found = true; __ipmi_dev_kill(ipmi_device); @@ -496,14 +518,13 @@ static void ipmi_bmc_gone(int iface) &driver_data.ipmi_devices, struct acpi_ipmi_device, head); mutex_unlock(&driver_data.ipmi_lock); + if (dev_found) { ipmi_flush_tx_msg(ipmi_device); acpi_ipmi_dev_put(ipmi_device); } } -/* -------------------------------------------------------------------------- - * Address Space Management - * -------------------------------------------------------------------------- */ + /* * This is the IPMI opregion space handler. * @function: indicates the read/write. In fact as the IPMI message is driven @@ -516,17 +537,17 @@ static void ipmi_bmc_gone(int iface) * the response IPMI message returned by IPMI command. * @handler_context: IPMI device context. */ - static acpi_status acpi_ipmi_space_handler(u32 function, acpi_physical_address address, - u32 bits, acpi_integer *value, - void *handler_context, void *region_context) + u32 bits, acpi_integer *value, + void *handler_context, void *region_context) { struct acpi_ipmi_msg *tx_msg; struct acpi_ipmi_device *ipmi_device; int err; acpi_status status; unsigned long flags; + /* * IPMI opregion message. * IPMI message is firstly written to the BMC and system software @@ -539,13 +560,13 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, tx_msg = ipmi_msg_alloc(); if (!tx_msg) return AE_NOT_EXIST; - ipmi_device = tx_msg->device; if (acpi_format_ipmi_request(tx_msg, address, value) != 0) { ipmi_msg_release(tx_msg); return AE_TYPE; } + acpi_ipmi_msg_get(tx_msg); mutex_lock(&driver_data.ipmi_lock); /* Do not add a tx_msg that can not be flushed. */ @@ -558,16 +579,18 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); mutex_unlock(&driver_data.ipmi_lock); + err = ipmi_request_settime(ipmi_device->user_interface, - &tx_msg->addr, - tx_msg->tx_msgid, - &tx_msg->tx_message, - NULL, 0, 0, IPMI_TIMEOUT); + &tx_msg->addr, + tx_msg->tx_msgid, + &tx_msg->tx_message, + NULL, 0, 0, IPMI_TIMEOUT); if (err) { status = AE_ERROR; goto out_msg; } wait_for_completion(&tx_msg->tx_complete); + acpi_format_ipmi_response(tx_msg, value); status = AE_OK; @@ -586,8 +609,9 @@ static int __init acpi_ipmi_init(void) return 0; status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, - ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler, - NULL, NULL); + ACPI_ADR_SPACE_IPMI, + &acpi_ipmi_space_handler, + NULL, NULL); if (ACPI_FAILURE(status)) { pr_warn("Can't register IPMI opregion space handle\n"); return -EINVAL; @@ -629,7 +653,8 @@ static void __exit acpi_ipmi_exit(void) } mutex_unlock(&driver_data.ipmi_lock); acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, - ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler); + ACPI_ADR_SPACE_IPMI, + &acpi_ipmi_space_handler); } module_init(acpi_ipmi_init); -- cgit v0.10.2 From 6dedcca610c6d6189b4a54d32118d1654adb73d2 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 25 Sep 2013 15:08:27 -0600 Subject: hotplug, powerpc, x86: Remove cpu_hotplug_driver_lock() cpu_hotplug_driver_lock() serializes CPU online/offline operations when ARCH_CPU_PROBE_RELEASE is set. This lock interface is no longer necessary with the following reason: - lock_device_hotplug() now protects CPU online/offline operations, including the probe & release interfaces enabled by ARCH_CPU_PROBE_RELEASE. The use of cpu_hotplug_driver_lock() is redundant. - cpu_hotplug_driver_lock() is only valid when ARCH_CPU_PROBE_RELEASE is defined, which is misleading and is only enabled on powerpc. This patch removes the cpu_hotplug_driver_lock() interface. As a result, ARCH_CPU_PROBE_RELEASE only enables / disables the cpu probe & release interface as intended. There is no functional change in this patch. Signed-off-by: Toshi Kani Reviewed-by: Nathan Fontenot Signed-off-by: Rafael J. Wysocki diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 8e59abc..930cd8a 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -844,18 +844,6 @@ void __cpu_die(unsigned int cpu) smp_ops->cpu_die(cpu); } -static DEFINE_MUTEX(powerpc_cpu_hotplug_driver_mutex); - -void cpu_hotplug_driver_lock() -{ - mutex_lock(&powerpc_cpu_hotplug_driver_mutex); -} - -void cpu_hotplug_driver_unlock() -{ - mutex_unlock(&powerpc_cpu_hotplug_driver_mutex); -} - void cpu_die(void) { if (ppc_md.cpu_die) diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 7cfdaae..a8fe5aa 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -404,46 +404,38 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count) unsigned long drc_index; int rc; - cpu_hotplug_driver_lock(); rc = strict_strtoul(buf, 0, &drc_index); - if (rc) { - rc = -EINVAL; - goto out; - } + if (rc) + return -EINVAL; parent = of_find_node_by_path("/cpus"); - if (!parent) { - rc = -ENODEV; - goto out; - } + if (!parent) + return -ENODEV; dn = dlpar_configure_connector(drc_index, parent); - if (!dn) { - rc = -EINVAL; - goto out; - } + if (!dn) + return -EINVAL; of_node_put(parent); rc = dlpar_acquire_drc(drc_index); if (rc) { dlpar_free_cc_nodes(dn); - rc = -EINVAL; - goto out; + return -EINVAL; } rc = dlpar_attach_node(dn); if (rc) { dlpar_release_drc(drc_index); dlpar_free_cc_nodes(dn); - goto out; + return rc; } rc = dlpar_online_cpu(dn); -out: - cpu_hotplug_driver_unlock(); + if (rc) + return rc; - return rc ? rc : count; + return count; } static int dlpar_offline_cpu(struct device_node *dn) @@ -516,30 +508,27 @@ static ssize_t dlpar_cpu_release(const char *buf, size_t count) return -EINVAL; } - cpu_hotplug_driver_lock(); rc = dlpar_offline_cpu(dn); if (rc) { of_node_put(dn); - rc = -EINVAL; - goto out; + return -EINVAL; } rc = dlpar_release_drc(*drc_index); if (rc) { of_node_put(dn); - goto out; + return rc; } rc = dlpar_detach_node(dn); if (rc) { dlpar_acquire_drc(*drc_index); - goto out; + return rc; } of_node_put(dn); -out: - cpu_hotplug_driver_unlock(); - return rc ? rc : count; + + return count; } static int __init pseries_dlpar_init(void) diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c index a3f35eb..649b010 100644 --- a/arch/x86/kernel/topology.c +++ b/arch/x86/kernel/topology.c @@ -66,7 +66,6 @@ int __ref _debug_hotplug_cpu(int cpu, int action) return -EINVAL; lock_device_hotplug(); - cpu_hotplug_driver_lock(); switch (action) { case 0: @@ -91,7 +90,6 @@ int __ref _debug_hotplug_cpu(int cpu, int action) ret = -EINVAL; } - cpu_hotplug_driver_unlock(); unlock_device_hotplug(); return ret; diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 51f5d7f..f48370d 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -44,13 +44,11 @@ static int __ref cpu_subsys_online(struct device *dev) struct cpu *cpu = container_of(dev, struct cpu, dev); int cpuid = dev->id; int from_nid, to_nid; - int ret = -ENODEV; - - cpu_hotplug_driver_lock(); + int ret; from_nid = cpu_to_node(cpuid); if (from_nid == NUMA_NO_NODE) - goto out; + return -ENODEV; ret = cpu_up(cpuid); /* @@ -61,19 +59,12 @@ static int __ref cpu_subsys_online(struct device *dev) if (from_nid != to_nid) change_cpu_under_node(cpu, from_nid, to_nid); - out: - cpu_hotplug_driver_unlock(); return ret; } static int cpu_subsys_offline(struct device *dev) { - int ret; - - cpu_hotplug_driver_lock(); - ret = cpu_down(dev->id); - cpu_hotplug_driver_unlock(); - return ret; + return cpu_down(dev->id); } void unregister_cpu(struct cpu *cpu) diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 801ff9e..3434ef7 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -185,19 +185,6 @@ extern void cpu_hotplug_enable(void); void clear_tasks_mm_cpumask(int cpu); int cpu_down(unsigned int cpu); -#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE -extern void cpu_hotplug_driver_lock(void); -extern void cpu_hotplug_driver_unlock(void); -#else -static inline void cpu_hotplug_driver_lock(void) -{ -} - -static inline void cpu_hotplug_driver_unlock(void) -{ -} -#endif - #else /* CONFIG_HOTPLUG_CPU */ static inline void cpu_hotplug_begin(void) {} -- cgit v0.10.2 From 9b5b06740194c8fa1cddb3aa5fe69fd6f5199bc4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 25 Sep 2013 14:23:04 -0600 Subject: ACPI / hotplug: Set kobject name via kobject_add(), not kobject_set_name() Set the kobject name via kobject_add() instead of using kobject_set_name(), which is deprecated per Documentation/kobject.txt. Signed-off-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 05306a5..ea68583 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -763,12 +763,9 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, goto err_out; kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype); - error = kobject_set_name(&hotplug->kobj, "%s", name); - if (error) - goto err_out; hotplug->kobj.parent = hotplug_kobj; - error = kobject_add(&hotplug->kobj, hotplug_kobj, NULL); + error = kobject_add(&hotplug->kobj, hotplug_kobj, "%s", name); if (error) goto err_out; -- cgit v0.10.2 From cae712724161c27f5e8c39bb3946449e1c179881 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 25 Sep 2013 14:23:12 -0600 Subject: ACPI / hotplug: Don't set kobject parent pointer explicitly kobject_add() sets the parent pointer, so we don't need to do it explicitly. Signed-off-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index ea68583..7543281 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -764,7 +764,6 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype); - hotplug->kobj.parent = hotplug_kobj; error = kobject_add(&hotplug->kobj, hotplug_kobj, "%s", name); if (error) goto err_out; -- cgit v0.10.2 From acd3e2c99464c0391885d58dbe7c99a11d4c0289 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 25 Sep 2013 14:23:20 -0600 Subject: ACPI / hotplug: Use kobject_init_and_add() instead of _init() and _add() Use kobject_init_and_add() since we have nothing special to do between kobject_init() and kobject_add(). Signed-off-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 7543281..bb6045c 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -762,9 +762,8 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, if (!hotplug_kobj) goto err_out; - kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype); - - error = kobject_add(&hotplug->kobj, hotplug_kobj, "%s", name); + error = kobject_init_and_add(&hotplug->kobj, + &acpi_hotplug_profile_ktype, hotplug_kobj, "%s", name); if (error) goto err_out; -- cgit v0.10.2 From 27047a603645d0885bcd72d7a0b6cce6e3c94ca7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:03 +0530 Subject: cpufreq: Add new helper cpufreq_table_validate_and_show() Almost every cpufreq driver is required to validate its frequency table with: cpufreq_frequency_table_cpuinfo() and then expose it to cpufreq core with: cpufreq_frequency_table_get_attr(). This patch creates another helper routine cpufreq_table_validate_and_show() that will do both these steps in a single call and will return 0 for success, error otherwise. This also fixes potential bugs in cpufreq drivers where people have called cpufreq_frequency_table_get_attr() before calling cpufreq_frequency_table_cpuinfo(), as the later may fail. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index f111454a..11f6fa9 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -219,6 +219,18 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu) } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr); +int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table) +{ + int ret = cpufreq_frequency_table_cpuinfo(policy, table); + + if (!ret) + cpufreq_frequency_table_get_attr(table, policy->cpu); + + return ret; +} +EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); + void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy) { pr_debug("Updating show_table for new_cpu %u from last_cpu %u\n", diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index fcabc42..6b199ed 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -410,5 +410,7 @@ extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs; void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, unsigned int cpu); void cpufreq_frequency_table_put_attr(unsigned int cpu); +int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table); #endif /* _LINUX_CPUFREQ_H */ -- cgit v0.10.2 From 6a77a1e6429c96be0dab06660b137847e2802806 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:04 +0530 Subject: cpufreq: pxa: call cpufreq_frequency_table_get_attr() This exposes frequency table of driver to cpufreq core and is required for core to guess what the index for a target frequency is, when it calls cpufreq_frequency_table_target(). And so this driver needs to expose it. Cc: Eric Miao Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index 8749eaf..b004cf1 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -453,20 +453,31 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) find_freq_tables(&pxa255_freq_table, &pxa255_freqs); pr_info("PXA255 cpufreq using %s frequency table\n", pxa255_turbo_table ? "turbo" : "run"); + cpufreq_frequency_table_cpuinfo(policy, pxa255_freq_table); + cpufreq_frequency_table_get_attr(pxa255_freq_table, policy->cpu); } - else if (cpu_is_pxa27x()) + else if (cpu_is_pxa27x()) { cpufreq_frequency_table_cpuinfo(policy, pxa27x_freq_table); + cpufreq_frequency_table_get_attr(pxa27x_freq_table, policy->cpu); + } printk(KERN_INFO "PXA CPU frequency change support initialized\n"); return 0; } +static int pxa_cpufreq_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + static struct cpufreq_driver pxa_cpufreq_driver = { .verify = pxa_verify_policy, .target = pxa_set_target, .init = pxa_cpufreq_init, + .exit = pxa_cpufreq_exit, .get = pxa_cpufreq_get, .name = "PXA2xx", }; diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c index d26306f..cebbed1 100644 --- a/drivers/cpufreq/pxa3xx-cpufreq.c +++ b/drivers/cpufreq/pxa3xx-cpufreq.c @@ -91,7 +91,7 @@ static int setup_freqs_table(struct cpufreq_policy *policy, struct pxa3xx_freq_info *freqs, int num) { struct cpufreq_frequency_table *table; - int i; + int i, ret; table = kzalloc((num + 1) * sizeof(*table), GFP_KERNEL); if (table == NULL) @@ -108,7 +108,11 @@ static int setup_freqs_table(struct cpufreq_policy *policy, pxa3xx_freqs_num = num; pxa3xx_freqs_table = table; - return cpufreq_frequency_table_cpuinfo(policy, table); + ret = cpufreq_frequency_table_cpuinfo(policy, table); + if (!ret) + cpufreq_frequency_table_get_attr(table, policy->cpu); + + return ret; } static void __update_core_freq(struct pxa3xx_freq_info *info) @@ -229,10 +233,17 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy) return 0; } +static int pxa3xx_cpufreq_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + static struct cpufreq_driver pxa3xx_cpufreq_driver = { .verify = pxa3xx_cpufreq_verify, .target = pxa3xx_cpufreq_set, .init = pxa3xx_cpufreq_init, + .exit = pxa3xx_cpufreq_exit, .get = pxa3xx_cpufreq_get, .name = "pxa3xx-cpufreq", }; -- cgit v0.10.2 From 5c40e052bb04381302c748497076b5b4526ed6cb Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:05 +0530 Subject: cpufreq: s3cx4xx: call cpufreq_frequency_table_get_attr() This exposes frequency table of driver to cpufreq core and is required for core to guess what the index for a target frequency is, when it calls cpufreq_frequency_table_target(). And so this driver needs to expose it. Cc: Kukjin Kim Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index b0f343f..f2c872c 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -386,8 +386,10 @@ static int s3c_cpufreq_init(struct cpufreq_policy *policy) /* feed the latency information from the cpu driver */ policy->cpuinfo.transition_latency = cpu_cur.info->latency; - if (ftab) + if (ftab) { cpufreq_frequency_table_cpuinfo(policy, ftab); + cpufreq_frequency_table_get_attr(ftab, policy->cpu); + } return 0; } diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c index 8a72b0c..9024043 100644 --- a/drivers/cpufreq/s3c64xx-cpufreq.c +++ b/drivers/cpufreq/s3c64xx-cpufreq.c @@ -257,6 +257,9 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) ret); regulator_put(vddarm); clk_put(armclk); + } else { + cpufreq_frequency_table_get_attr(s3c64xx_freq_table, + policy->cpu); } return ret; -- cgit v0.10.2 From 18f130ed75ab98573694fa6d8542c7891ccc9447 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:06 +0530 Subject: cpufreq: sparc: call cpufreq_frequency_table_get_attr() This exposes frequency table of driver to cpufreq core and is required for core to guess what the index for a target frequency is, when it calls cpufreq_frequency_table_target(). And so this driver needs to expose it. Cc: David S. Miller Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c index cf5bc2c..63b3eae 100644 --- a/drivers/cpufreq/sparc-us2e-cpufreq.c +++ b/drivers/cpufreq/sparc-us2e-cpufreq.c @@ -307,6 +307,7 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; struct cpufreq_frequency_table *table = &us2e_freq_table[cpu].table[0]; + int ret; table[0].driver_data = 0; table[0].frequency = clock_tick / 1; @@ -324,13 +325,18 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 0; policy->cur = clock_tick; - return cpufreq_frequency_table_cpuinfo(policy, table); + ret = cpufreq_frequency_table_cpuinfo(policy, table); + if (!ret) + cpufreq_frequency_table_get_attr(table, policy->cpu); + return ret; } static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) { - if (cpufreq_us2e_driver) + if (cpufreq_us2e_driver) { + cpufreq_frequency_table_put_attr(policy->cpu); us2e_set_cpu_divider_index(policy, 0); + } return 0; } diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c index ac76b48..985bc56 100644 --- a/drivers/cpufreq/sparc-us3-cpufreq.c +++ b/drivers/cpufreq/sparc-us3-cpufreq.c @@ -168,6 +168,7 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; struct cpufreq_frequency_table *table = &us3_freq_table[cpu].table[0]; + int ret; table[0].driver_data = 0; table[0].frequency = clock_tick / 1; @@ -181,13 +182,19 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 0; policy->cur = clock_tick; - return cpufreq_frequency_table_cpuinfo(policy, table); + ret = cpufreq_frequency_table_cpuinfo(policy, table); + if (!ret) + cpufreq_frequency_table_get_attr(table, policy->cpu); + + return ret; } static int us3_freq_cpu_exit(struct cpufreq_policy *policy) { - if (cpufreq_us3_driver) + if (cpufreq_us3_driver) { + cpufreq_frequency_table_put_attr(policy->cpu); us3_set_cpu_divider_index(policy, 0); + } return 0; } -- cgit v0.10.2 From 776b57be6581528125a076cbae5c0b75c50909f5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:07 +0530 Subject: cpufreq: acpi-cpufreq: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index d2c3253..d993211 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -837,7 +837,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END; perf->state = 0; - result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table); + result = cpufreq_table_validate_and_show(policy, data->freq_table); if (result) goto err_freqfree; @@ -868,8 +868,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) (u32) perf->states[i].power, (u32) perf->states[i].transition_latency); - cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); - /* * the first call to ->target() should result in us actually * writing something to the appropriate registers. -- cgit v0.10.2 From 39b10ebe5d30ef46ddea1daa89ca55bd2c817d7b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:08 +0530 Subject: cpufreq: arm_big_little: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 3549f07..5070273 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -165,7 +165,7 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy) if (ret) return ret; - ret = cpufreq_frequency_table_cpuinfo(policy, freq_table[cur_cluster]); + ret = cpufreq_table_validate_and_show(policy, freq_table[cur_cluster]); if (ret) { dev_err(cpu_dev, "CPU %d, cluster: %d invalid freq table\n", policy->cpu, cur_cluster); @@ -173,8 +173,6 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy) return ret; } - cpufreq_frequency_table_get_attr(freq_table[cur_cluster], policy->cpu); - if (arm_bL_ops->get_transition_latency) policy->cpuinfo.transition_latency = arm_bL_ops->get_transition_latency(cpu_dev); -- cgit v0.10.2 From e2889e2cb8986d6e2d9f8f078249f6dfed5bf605 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:09 +0530 Subject: cpufreq: blackfin: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Steven Miao Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c index ef05978..54c0a0c 100644 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ b/drivers/cpufreq/blackfin-cpufreq.c @@ -210,8 +210,7 @@ static int __bfin_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 50000; /* 50us assumed */ policy->cur = cclk; - cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu); - return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table); + return cpufreq_table_validate_and_show(policy, bfin_freq_table); } static struct freq_attr *bfin_freq_attr[] = { -- cgit v0.10.2 From 7a90684956135b3d59fab75166e6ce21e39e532c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:10 +0530 Subject: cpufreq: cpufreq-cpu0: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Acked-by: Shawn Guo Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 78c49d8..fd031ec 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -129,7 +129,7 @@ static int cpu0_cpufreq_init(struct cpufreq_policy *policy) { int ret; - ret = cpufreq_frequency_table_cpuinfo(policy, freq_table); + ret = cpufreq_table_validate_and_show(policy, freq_table); if (ret) { pr_err("invalid frequency table: %d\n", ret); return ret; @@ -145,8 +145,6 @@ static int cpu0_cpufreq_init(struct cpufreq_policy *policy) */ cpumask_setall(policy->cpus); - cpufreq_frequency_table_get_attr(freq_table, policy->cpu); - return 0; } -- cgit v0.10.2 From ae24b5cda83cd496c72acd9fcd97a5748aaeec22 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:11 +0530 Subject: cpufreq: cris: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Jesper Nilsson Cc: Mikael Starvik Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c index cb8276d..444fd96 100644 --- a/drivers/cpufreq/cris-artpec3-cpufreq.c +++ b/drivers/cpufreq/cris-artpec3-cpufreq.c @@ -76,19 +76,11 @@ static int cris_freq_target(struct cpufreq_policy *policy, static int cris_freq_cpu_init(struct cpufreq_policy *policy) { - int result; - /* cpuinfo and default policy values */ policy->cpuinfo.transition_latency = 1000000; /* 1ms */ policy->cur = cris_freq_get_cpu_frequency(0); - result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table); - if (result) - return (result); - - cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu); - - return 0; + return cpufreq_table_validate_and_show(policy, cris_freq_table); } diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c index 72328f7..428395e 100644 --- a/drivers/cpufreq/cris-etraxfs-cpufreq.c +++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c @@ -75,19 +75,11 @@ static int cris_freq_target(struct cpufreq_policy *policy, static int cris_freq_cpu_init(struct cpufreq_policy *policy) { - int result; - /* cpuinfo and default policy values */ policy->cpuinfo.transition_latency = 1000000; /* 1ms */ policy->cur = cris_freq_get_cpu_frequency(0); - result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table); - if (result) - return (result); - - cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu); - - return 0; + return cpufreq_table_validate_and_show(policy, cris_freq_table); } static int cris_freq_cpu_exit(struct cpufreq_policy *policy) -- cgit v0.10.2 From e873c5b217634976778bdbf0b88cfded427f545c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:12 +0530 Subject: cpufreq: davinci: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Sekhar Nori Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c index 551dd65..f67196e 100644 --- a/drivers/cpufreq/davinci-cpufreq.c +++ b/drivers/cpufreq/davinci-cpufreq.c @@ -140,15 +140,13 @@ static int davinci_cpu_init(struct cpufreq_policy *policy) policy->cur = davinci_getspeed(0); - result = cpufreq_frequency_table_cpuinfo(policy, freq_table); + result = cpufreq_table_validate_and_show(policy, freq_table); if (result) { - pr_err("%s: cpufreq_frequency_table_cpuinfo() failed", + pr_err("%s: cpufreq_table_validate_and_show() failed", __func__); return result; } - cpufreq_frequency_table_get_attr(freq_table, policy->cpu); - /* * Time measurement across the target() function yields ~1500-1800us * time taken with no drivers on notification list. -- cgit v0.10.2 From 025829e4a49df6ec860bf69edd2fcfe1db66798d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:13 +0530 Subject: cpufreq: dbx500: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Acked-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c index 26321cd..8a484e9 100644 --- a/drivers/cpufreq/dbx500-cpufreq.c +++ b/drivers/cpufreq/dbx500-cpufreq.c @@ -87,10 +87,8 @@ static int dbx500_cpufreq_init(struct cpufreq_policy *policy) int res; /* get policy fields based on the table */ - res = cpufreq_frequency_table_cpuinfo(policy, freq_table); - if (!res) - cpufreq_frequency_table_get_attr(freq_table, policy->cpu); - else { + res = cpufreq_table_validate_and_show(policy, freq_table); + if (res) { pr_err("dbx500-cpufreq: Failed to read policy table\n"); return res; } -- cgit v0.10.2 From 7813ed7ec1597b002eebf9be19edd1283dbcc6fe Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:14 +0530 Subject: cpufreq: e_powersaver: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index 09f64cc..c1b7c99 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -403,13 +403,12 @@ static int eps_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */ policy->cur = fsb * current_multiplier; - ret = cpufreq_frequency_table_cpuinfo(policy, ¢aur->freq_table[0]); + ret = cpufreq_table_validate_and_show(policy, ¢aur->freq_table[0]); if (ret) { kfree(centaur); return ret; } - cpufreq_frequency_table_get_attr(¢aur->freq_table[0], policy->cpu); return 0; } -- cgit v0.10.2 From 55bb85b7aeca1e4a689764cb9f53727313130c7f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:15 +0530 Subject: cpufreq: elanfreq: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index 823a400..4000c34 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c @@ -202,7 +202,6 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = &cpu_data(0); unsigned int i; - int result; /* capability check */ if ((c->x86_vendor != X86_VENDOR_AMD) || @@ -223,12 +222,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = elanfreq_get_cpu_frequency(0); - result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table); - if (result) - return result; - - cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu); - return 0; + return cpufreq_table_validate_and_show(policy, elanfreq_table); } -- cgit v0.10.2 From bc574ce9acb476cdd6622c196a81685b8e907de5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:16 +0530 Subject: cpufreq: exynos: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Kukjin Kim Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index 0fac344..954baed 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -249,14 +249,12 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) { policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu); - cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu); - /* set the transition latency value */ policy->cpuinfo.transition_latency = 100000; cpumask_setall(policy->cpus); - return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table); + return cpufreq_table_validate_and_show(policy, exynos_info->freq_table); } static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy) diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index be5380e..b629671 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -326,7 +326,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) { int ret; - ret = cpufreq_frequency_table_cpuinfo(policy, dvfs_info->freq_table); + ret = cpufreq_table_validate_and_show(policy, dvfs_info->freq_table); if (ret) { dev_err(dvfs_info->dev, "Invalid frequency table: %d\n", ret); return ret; @@ -336,8 +336,6 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = dvfs_info->latency; cpumask_setall(policy->cpus); - cpufreq_frequency_table_get_attr(dvfs_info->freq_table, policy->cpu); - return 0; } -- cgit v0.10.2 From bbe2c1703d493dddc07abc579f6da239a2317cfa Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:17 +0530 Subject: cpufreq: ia64-acpi: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Tony Luck Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index 3e14f03..6cfad51 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -335,7 +335,7 @@ acpi_cpufreq_cpu_init ( } } - result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table); + result = cpufreq_table_validate_and_show(policy, data->freq_table); if (result) { goto err_freqfree; } @@ -356,8 +356,6 @@ acpi_cpufreq_cpu_init ( (u32) data->acpi_data.states[i].status, (u32) data->acpi_data.states[i].control); - cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); - /* the first call to ->target() should result in us actually * writing something to the appropriate registers. */ data->resume = 1; -- cgit v0.10.2 From 9ff4a80b2551d43f92c3d9a7a11e406ce7aa47f3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:18 +0530 Subject: cpufreq: imx6q: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Shawn Guo Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index c3fd2a1..af0e202 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -161,7 +161,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy) { int ret; - ret = cpufreq_frequency_table_cpuinfo(policy, freq_table); + ret = cpufreq_table_validate_and_show(policy, freq_table); if (ret) { dev_err(cpu_dev, "invalid frequency table: %d\n", ret); return ret; @@ -170,7 +170,6 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = transition_latency; policy->cur = clk_get_rate(arm_clk) / 1000; cpumask_setall(policy->cpus); - cpufreq_frequency_table_get_attr(freq_table, policy->cpu); return 0; } -- cgit v0.10.2 From 6efbc777b9cf4af5efdd06e8365639cacbc65b7b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:19 +0530 Subject: cpufreq: kirkwood: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Reviewed-by: Andrew Lunn Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index ba10658..59cbb35 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -125,19 +125,11 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy, /* Module init and exit code */ static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy) { - int result; - /* cpuinfo and default policy values */ policy->cpuinfo.transition_latency = 5000; /* 5uS */ policy->cur = kirkwood_cpufreq_get_cpu_frequency(0); - result = cpufreq_frequency_table_cpuinfo(policy, kirkwood_freq_table); - if (result) - return result; - - cpufreq_frequency_table_get_attr(kirkwood_freq_table, policy->cpu); - - return 0; + return cpufreq_table_validate_and_show(policy, kirkwood_freq_table); } static int kirkwood_cpufreq_cpu_exit(struct cpufreq_policy *policy) -- cgit v0.10.2 From 30aa53412797a45b0b21da332e7a0fc6a74bb061 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:20 +0530 Subject: cpufreq: longhaul: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 4ada1cc..70b66fd 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -921,13 +921,7 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 200000; /* nsec */ policy->cur = calc_speed(longhaul_get_cpu_mult()); - ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); - if (ret) - return ret; - - cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu); - - return 0; + return cpufreq_table_validate_and_show(policy, longhaul_table); } static int longhaul_cpu_exit(struct cpufreq_policy *policy) -- cgit v0.10.2 From f71123522468805b3b4fe510172b7a46e046d89a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:21 +0530 Subject: cpufreq: loongson2: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: John Crispin Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index 7bc3c44..5dd3692 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -133,10 +133,7 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cur = loongson2_cpufreq_get(policy->cpu); - cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0], - policy->cpu); - - return cpufreq_frequency_table_cpuinfo(policy, + return cpufreq_table_validate_and_show(policy, &loongson2_clockmod_table[0]); } -- cgit v0.10.2 From 05b1621cb5134b89b6ab36e9b82bea32283c7c50 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:22 +0530 Subject: cpufreq: maple: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Dmitry Eremin-Solenikov Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c index 6168d77..b3fb661 100644 --- a/drivers/cpufreq/maple-cpufreq.c +++ b/drivers/cpufreq/maple-cpufreq.c @@ -181,10 +181,8 @@ static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy) * cpufreq core if in the secondary policy we tell it that * it actually must be one policy together with all others. */ cpumask_setall(policy->cpus); - cpufreq_frequency_table_get_attr(maple_cpu_freqs, policy->cpu); - return cpufreq_frequency_table_cpuinfo(policy, - maple_cpu_freqs); + return cpufreq_table_validate_and_show(policy, maple_cpu_freqs); } -- cgit v0.10.2 From aca71cf06792eadebd3f3df58e3c1af364ae0e8b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:23 +0530 Subject: cpufreq: omap: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Acked-by: Santosh Shilimkar Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index f31fcfc..b68ce4e 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -191,12 +191,10 @@ static int omap_cpu_init(struct cpufreq_policy *policy) atomic_inc_return(&freq_table_users); - result = cpufreq_frequency_table_cpuinfo(policy, freq_table); + result = cpufreq_table_validate_and_show(policy, freq_table); if (result) goto fail_table; - cpufreq_frequency_table_get_attr(freq_table, policy->cpu); - policy->cur = omap_getspeed(policy->cpu); /* -- cgit v0.10.2 From 719ffe495cfb86492ab47b05fde55fd5eafec159 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:24 +0530 Subject: cpufreq: p4-clockmod: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: David S. Miller Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 2f0a2a6..03478bf 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -230,7 +230,6 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) else p4clockmod_table[i].frequency = (stock_freq * i)/8; } - cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); /* cpuinfo and default policy values */ @@ -239,7 +238,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 10000001; policy->cur = stock_freq; - return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]); + return cpufreq_table_validate_and_show(policy, &p4clockmod_table[0]); } -- cgit v0.10.2 From 2e4633e4c15b92ffc05e030907ebdb9404d5554c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:25 +0530 Subject: cpufreq: pasemi: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index 534e43a..23bc8a82 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c @@ -219,12 +219,10 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) ppc_proc_freq = policy->cur * 1000ul; - cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu); - /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max * are set correctly */ - return cpufreq_frequency_table_cpuinfo(policy, pas_freqs); + return cpufreq_table_validate_and_show(policy, pas_freqs); out_unmap_sdcpwr: iounmap(sdcpwr_mapbase); -- cgit v0.10.2 From 0e645df9c481b932c99cf1fd38c568b42c705408 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:26 +0530 Subject: cpufreq: pmac: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index a096cd3..470b555 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -408,8 +408,7 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = transition_latency; policy->cur = cur_freq; - cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu); - return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); + return cpufreq_table_validate_and_show(policy, pmac_cpu_freqs); } static u32 read_gpio(struct device_node *np) diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 3a51ad7..41fa89e 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -363,10 +363,8 @@ static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) * cpufreq core if in the secondary policy we tell it that * it actually must be one policy together with all others. */ cpumask_copy(policy->cpus, cpu_online_mask); - cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); - return cpufreq_frequency_table_cpuinfo(policy, - g5_cpu_freqs); + return cpufreq_table_validate_and_show(policy, g5_cpu_freqs); } -- cgit v0.10.2 From b147405aa8e568750bfa99501c7fa831edef47c9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:27 +0530 Subject: cpufreq: powernow: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index 85f1c8c..ab1de0d 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c @@ -145,7 +145,6 @@ static int powernow_k6_target(struct cpufreq_policy *policy, static int powernow_k6_cpu_init(struct cpufreq_policy *policy) { unsigned int i, f; - int result; if (policy->cpu != 0) return -ENODEV; @@ -167,13 +166,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 200000; policy->cur = busfreq * max_multiplier; - result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio); - if (result) - return result; - - cpufreq_frequency_table_get_attr(clock_ratio, policy->cpu); - - return 0; + return cpufreq_table_validate_and_show(policy, clock_ratio); } diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index 14ce480..c863c13 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -680,9 +680,7 @@ static int powernow_cpu_init(struct cpufreq_policy *policy) policy->cur = powernow_get(0); - cpufreq_frequency_table_get_attr(powernow_table, policy->cpu); - - return cpufreq_frequency_table_cpuinfo(policy, powernow_table); + return cpufreq_table_validate_and_show(policy, powernow_table); } static int powernow_cpu_exit(struct cpufreq_policy *policy) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 2344a9e..8d4114a 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1156,7 +1156,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) pr_debug("policy current frequency %d kHz\n", pol->cur); /* min/max the cpu is capable of */ - if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table)) { + if (cpufreq_table_validate_and_show(pol, data->powernow_table)) { printk(KERN_ERR FW_BUG PFX "invalid powernow_table\n"); powernow_k8_cpu_exit_acpi(data); kfree(data->powernow_table); @@ -1164,8 +1164,6 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) return -EINVAL; } - cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); - pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n", data->currfid, data->currvid); -- cgit v0.10.2 From 6b4147db3de33b49a5c6a88736e9322936672dc4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:28 +0530 Subject: cpufreq: ppc: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c index 60e81d5..5716b44 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/ppc-corenet-cpufreq.c @@ -202,7 +202,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) table[i].frequency = CPUFREQ_TABLE_END; /* set the min and max frequency properly */ - ret = cpufreq_frequency_table_cpuinfo(policy, table); + ret = cpufreq_table_validate_and_show(policy, table); if (ret) { pr_err("invalid frequency table: %d\n", ret); goto err_nomem1; @@ -219,7 +219,6 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = corenet_cpufreq_get_speed(policy->cpu); - cpufreq_frequency_table_get_attr(table, cpu); of_node_put(np); return 0; diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c index 2e448f0..6c5be63 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq.c @@ -123,11 +123,9 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu)); #endif - cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu); - /* this ensures that policy->cpuinfo_min * and policy->cpuinfo_max are set correctly */ - return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs); + return cpufreq_table_validate_and_show(policy, cbe_freqs); } static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy) -- cgit v0.10.2 From 15cc921b97f1c0aac38edfe7c796bfb5d5f4676b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:29 +0530 Subject: cpufreq: pxa: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Eric Miao Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index b004cf1..236531a 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -454,12 +454,10 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) pr_info("PXA255 cpufreq using %s frequency table\n", pxa255_turbo_table ? "turbo" : "run"); - cpufreq_frequency_table_cpuinfo(policy, pxa255_freq_table); - cpufreq_frequency_table_get_attr(pxa255_freq_table, policy->cpu); + cpufreq_table_validate_and_show(policy, pxa255_freq_table); } else if (cpu_is_pxa27x()) { - cpufreq_frequency_table_cpuinfo(policy, pxa27x_freq_table); - cpufreq_frequency_table_get_attr(pxa27x_freq_table, policy->cpu); + cpufreq_table_validate_and_show(policy, pxa27x_freq_table); } printk(KERN_INFO "PXA CPU frequency change support initialized\n"); diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c index cebbed1..65fd01e 100644 --- a/drivers/cpufreq/pxa3xx-cpufreq.c +++ b/drivers/cpufreq/pxa3xx-cpufreq.c @@ -91,7 +91,7 @@ static int setup_freqs_table(struct cpufreq_policy *policy, struct pxa3xx_freq_info *freqs, int num) { struct cpufreq_frequency_table *table; - int i, ret; + int i; table = kzalloc((num + 1) * sizeof(*table), GFP_KERNEL); if (table == NULL) @@ -108,11 +108,7 @@ static int setup_freqs_table(struct cpufreq_policy *policy, pxa3xx_freqs_num = num; pxa3xx_freqs_table = table; - ret = cpufreq_frequency_table_cpuinfo(policy, table); - if (!ret) - cpufreq_frequency_table_get_attr(table, policy->cpu); - - return ret; + return cpufreq_table_validate_and_show(policy, table); } static void __update_core_freq(struct pxa3xx_freq_info *info) -- cgit v0.10.2 From 4974b8ea4add1ae5e3123fe734deb12859da725b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:30 +0530 Subject: cpufreq: s3cx4xx: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Kukjin Kim Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index 22dcb81..a7a4c61 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -494,12 +494,10 @@ static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = (500 * 1000) + s3c_freq->regulator_latency; - ret = cpufreq_frequency_table_cpuinfo(policy, s3c_freq->freq_table); + ret = cpufreq_table_validate_and_show(policy, s3c_freq->freq_table); if (ret) goto err_freq_table; - cpufreq_frequency_table_get_attr(s3c_freq->freq_table, 0); - register_reboot_notifier(&s3c2416_cpufreq_reboot_notifier); return 0; diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index f2c872c..73856d1 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -386,10 +386,8 @@ static int s3c_cpufreq_init(struct cpufreq_policy *policy) /* feed the latency information from the cpu driver */ policy->cpuinfo.transition_latency = cpu_cur.info->latency; - if (ftab) { - cpufreq_frequency_table_cpuinfo(policy, ftab); - cpufreq_frequency_table_get_attr(ftab, policy->cpu); - } + if (ftab) + return cpufreq_table_validate_and_show(policy, ftab); return 0; } diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c index 9024043..872f74d 100644 --- a/drivers/cpufreq/s3c64xx-cpufreq.c +++ b/drivers/cpufreq/s3c64xx-cpufreq.c @@ -251,15 +251,12 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) */ policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency; - ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table); + ret = cpufreq_table_validate_and_show(policy, s3c64xx_freq_table); if (ret != 0) { pr_err("Failed to configure frequency table: %d\n", ret); regulator_put(vddarm); clk_put(armclk); - } else { - cpufreq_frequency_table_get_attr(s3c64xx_freq_table, - policy->cpu); } return ret; -- cgit v0.10.2 From 291e8fb1a320ef9bce679dba9d6c6892e5e2c774 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:31 +0530 Subject: cpufreq: s5pv210: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Kukjin Kim Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 5c77570..c266a7e 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -553,11 +553,9 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) policy->cur = policy->min = policy->max = s5pv210_getspeed(0); - cpufreq_frequency_table_get_attr(s5pv210_freq_table, policy->cpu); - policy->cpuinfo.transition_latency = 40000; - return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table); + return cpufreq_table_validate_and_show(policy, s5pv210_freq_table); out_dmc1: clk_put(dmc0_clk); -- cgit v0.10.2 From 22c8b4f1409097c073a0f894406c8bb9525bfb68 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:32 +0530 Subject: cpufreq: sa11x0: Expose frequency table This patch exposes sa11x0's frequency table to cpufreq core. It always existed but not as an array frequencies and not in the format cpufreq core wants it to. Also it was present in the unit of 100kHz earlier which is made consistent with cpufreq core now, i.e. kHz. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index f25b611..5c8167b 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -42,23 +42,24 @@ EXPORT_SYMBOL(reset_status); /* * This table is setup for a 3.6864MHz Crystal. */ -static const unsigned short cclk_frequency_100khz[NR_FREQS] = { - 590, /* 59.0 MHz */ - 737, /* 73.7 MHz */ - 885, /* 88.5 MHz */ - 1032, /* 103.2 MHz */ - 1180, /* 118.0 MHz */ - 1327, /* 132.7 MHz */ - 1475, /* 147.5 MHz */ - 1622, /* 162.2 MHz */ - 1769, /* 176.9 MHz */ - 1917, /* 191.7 MHz */ - 2064, /* 206.4 MHz */ - 2212, /* 221.2 MHz */ - 2359, /* 235.9 MHz */ - 2507, /* 250.7 MHz */ - 2654, /* 265.4 MHz */ - 2802 /* 280.2 MHz */ +struct cpufreq_frequency_table sa11x0_freq_table[NR_FREQS+1] = { + { .frequency = 59000, /* 59.0 MHz */}, + { .frequency = 73700, /* 73.7 MHz */}, + { .frequency = 88500, /* 88.5 MHz */}, + { .frequency = 103200, /* 103.2 MHz */}, + { .frequency = 118000, /* 118.0 MHz */}, + { .frequency = 132700, /* 132.7 MHz */}, + { .frequency = 147500, /* 147.5 MHz */}, + { .frequency = 162200, /* 162.2 MHz */}, + { .frequency = 176900, /* 176.9 MHz */}, + { .frequency = 191700, /* 191.7 MHz */}, + { .frequency = 206400, /* 206.4 MHz */}, + { .frequency = 221200, /* 221.2 MHz */}, + { .frequency = 235900, /* 235.9 MHz */}, + { .frequency = 250700, /* 250.7 MHz */}, + { .frequency = 265400, /* 265.4 MHz */}, + { .frequency = 280200, /* 280.2 MHz */}, + { .frequency = CPUFREQ_TABLE_END, }, }; /* rounds up(!) */ @@ -66,10 +67,8 @@ unsigned int sa11x0_freq_to_ppcr(unsigned int khz) { int i; - khz /= 100; - for (i = 0; i < NR_FREQS; i++) - if (cclk_frequency_100khz[i] >= khz) + if (sa11x0_freq_table[i].frequency >= khz) break; return i; @@ -79,7 +78,7 @@ unsigned int sa11x0_ppcr_to_freq(unsigned int idx) { unsigned int freq = 0; if (idx < NR_FREQS) - freq = cclk_frequency_100khz[idx] * 100; + freq = sa11x0_freq_table[idx].frequency; return freq; } @@ -96,7 +95,7 @@ int sa11x0_verify_speed(struct cpufreq_policy *policy) cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); /* make sure that at least one frequency is within the policy */ - tmp = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->min)] * 100; + tmp = sa11x0_freq_table[sa11x0_freq_to_ppcr(policy->min)].frequency; if (tmp > policy->max) policy->max = tmp; @@ -109,7 +108,7 @@ unsigned int sa11x0_getspeed(unsigned int cpu) { if (cpu) return 0; - return cclk_frequency_100khz[PPCR & 0xf] * 100; + return sa11x0_freq_table[PPCR & 0xf].frequency; } /* diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index 9a33695..f5214ce 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h @@ -21,6 +21,7 @@ extern void sa1110_mb_disable(void); struct cpufreq_policy; +extern struct cpufreq_frequency_table sa11x0_freq_table[]; extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); extern int sa11x0_verify_speed(struct cpufreq_policy *policy); extern unsigned int sa11x0_getspeed(unsigned int cpu); diff --git a/drivers/cpufreq/sa1100-cpufreq.c b/drivers/cpufreq/sa1100-cpufreq.c index cff18e8..1323a69 100644 --- a/drivers/cpufreq/sa1100-cpufreq.c +++ b/drivers/cpufreq/sa1100-cpufreq.c @@ -224,7 +224,8 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.min_freq = 59000; policy->cpuinfo.max_freq = 287000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - return 0; + + return cpufreq_table_validate_and_show(policy, sa11x0_freq_table); } static struct cpufreq_driver sa1100_driver __refdata = { diff --git a/drivers/cpufreq/sa1110-cpufreq.c b/drivers/cpufreq/sa1110-cpufreq.c index 39c90b6..adb0524 100644 --- a/drivers/cpufreq/sa1110-cpufreq.c +++ b/drivers/cpufreq/sa1110-cpufreq.c @@ -338,7 +338,8 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.min_freq = 59000; policy->cpuinfo.max_freq = 287000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - return 0; + + return cpufreq_table_validate_and_show(policy, sa11x0_freq_table); } /* sa1110_driver needs __refdata because it must remain after init registers -- cgit v0.10.2 From 53862f7a0b75f3d8e7445b864aa45cfa4aa49570 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:33 +0530 Subject: cpufreq: sa11x0: let cpufreq core initialize struct policy fields Many fields of struct policy are filled by cpufreq core when we call cpufreq_table_validate_and_show() and so cpufreq driver doesn't need to set them anymore. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sa1100-cpufreq.c b/drivers/cpufreq/sa1100-cpufreq.c index 1323a69..37fce2f 100644 --- a/drivers/cpufreq/sa1100-cpufreq.c +++ b/drivers/cpufreq/sa1100-cpufreq.c @@ -220,9 +220,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy) { if (policy->cpu != 0) return -EINVAL; - policy->cur = policy->min = policy->max = sa11x0_getspeed(0); - policy->cpuinfo.min_freq = 59000; - policy->cpuinfo.max_freq = 287000; + policy->cur = sa11x0_getspeed(0); policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; return cpufreq_table_validate_and_show(policy, sa11x0_freq_table); diff --git a/drivers/cpufreq/sa1110-cpufreq.c b/drivers/cpufreq/sa1110-cpufreq.c index adb0524..13760fc 100644 --- a/drivers/cpufreq/sa1110-cpufreq.c +++ b/drivers/cpufreq/sa1110-cpufreq.c @@ -334,9 +334,7 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy) { if (policy->cpu != 0) return -EINVAL; - policy->cur = policy->min = policy->max = sa11x0_getspeed(0); - policy->cpuinfo.min_freq = 59000; - policy->cpuinfo.max_freq = 287000; + policy->cur = sa11x0_getspeed(0); policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; return cpufreq_table_validate_and_show(policy, sa11x0_freq_table); -- cgit v0.10.2 From ae025193d3b811e1cd6bdfa7dc4940ae9e2739d1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:34 +0530 Subject: cpufreq: sc520: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index d6f6c6f..bb9c0de 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c @@ -106,7 +106,6 @@ static int sc520_freq_target(struct cpufreq_policy *policy, static int sc520_freq_cpu_init(struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = &cpu_data(0); - int result; /* capability check */ if (c->x86_vendor != X86_VENDOR_AMD || @@ -117,13 +116,7 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 1000000; /* 1ms */ policy->cur = sc520_freq_get_cpu_frequency(0); - result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table); - if (result) - return result; - - cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu); - - return 0; + return cpufreq_table_validate_and_show(policy, sc520_freq_table); } -- cgit v0.10.2 From c25d01b3e2407ac536bcd40f2d23fc5c5019fa23 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:35 +0530 Subject: cpufreq: sh: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: Paul Mundt Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c index ffc6d24..1362e88 100644 --- a/drivers/cpufreq/sh-cpufreq.c +++ b/drivers/cpufreq/sh-cpufreq.c @@ -120,9 +120,9 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) if (freq_table) { int result; - result = cpufreq_frequency_table_cpuinfo(policy, freq_table); - if (!result) - cpufreq_frequency_table_get_attr(freq_table, cpu); + result = cpufreq_table_validate_and_show(policy, freq_table); + if (result) + return result; } else { dev_notice(dev, "no frequency table found, falling back " "to rate rounding.\n"); -- cgit v0.10.2 From f1a707c023a9029487ad8f4f6afd1a953a2e31ff Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:36 +0530 Subject: cpufreq: sparc: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: David S. Miller Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c index 63b3eae..8db0c18 100644 --- a/drivers/cpufreq/sparc-us2e-cpufreq.c +++ b/drivers/cpufreq/sparc-us2e-cpufreq.c @@ -307,7 +307,6 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; struct cpufreq_frequency_table *table = &us2e_freq_table[cpu].table[0]; - int ret; table[0].driver_data = 0; table[0].frequency = clock_tick / 1; @@ -325,10 +324,7 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 0; policy->cur = clock_tick; - ret = cpufreq_frequency_table_cpuinfo(policy, table); - if (!ret) - cpufreq_frequency_table_get_attr(table, policy->cpu); - return ret; + return cpufreq_table_validate_and_show(policy, table); } static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c index 985bc56..120a2df 100644 --- a/drivers/cpufreq/sparc-us3-cpufreq.c +++ b/drivers/cpufreq/sparc-us3-cpufreq.c @@ -168,7 +168,6 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; struct cpufreq_frequency_table *table = &us3_freq_table[cpu].table[0]; - int ret; table[0].driver_data = 0; table[0].frequency = clock_tick / 1; @@ -182,11 +181,7 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 0; policy->cur = clock_tick; - ret = cpufreq_frequency_table_cpuinfo(policy, table); - if (!ret) - cpufreq_frequency_table_get_attr(table, policy->cpu); - - return ret; + return cpufreq_table_validate_and_show(policy, table); } static int us3_freq_cpu_exit(struct cpufreq_policy *policy) -- cgit v0.10.2 From 4a1fe2bfc9e49c48a166d0229e09d3069893a8fa Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:37 +0530 Subject: cpufreq: spear: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index 19e364fa..b86be6b 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -178,13 +178,12 @@ static int spear_cpufreq_init(struct cpufreq_policy *policy) { int ret; - ret = cpufreq_frequency_table_cpuinfo(policy, spear_cpufreq.freq_tbl); + ret = cpufreq_table_validate_and_show(policy, spear_cpufreq.freq_tbl); if (ret) { - pr_err("cpufreq_frequency_table_cpuinfo() failed"); + pr_err("cpufreq_table_validate_and_show() failed"); return ret; } - cpufreq_frequency_table_get_attr(spear_cpufreq.freq_tbl, policy->cpu); policy->cpuinfo.transition_latency = spear_cpufreq.transition_latency; policy->cur = spear_cpufreq_get(0); -- cgit v0.10.2 From 5f3a2d39bb9dd4372c52fb2568c4520bcc91c8c4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:38 +0530 Subject: cpufreq: speedstep: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Cc: David S. Miller Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index f897d51..f180561 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -345,7 +345,6 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu); unsigned freq; unsigned l, h; - int ret; int i; /* Only Intel makes Enhanced Speedstep-capable CPUs */ @@ -402,15 +401,8 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) pr_debug("centrino_cpu_init: cur=%dkHz\n", policy->cur); - ret = cpufreq_frequency_table_cpuinfo(policy, + return cpufreq_table_validate_and_show(policy, per_cpu(centrino_model, policy->cpu)->op_points); - if (ret) - return (ret); - - cpufreq_frequency_table_get_attr( - per_cpu(centrino_model, policy->cpu)->op_points, policy->cpu); - - return 0; } static int centrino_cpu_exit(struct cpufreq_policy *policy) diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index 5355abb..86a184e 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -320,7 +320,6 @@ static void get_freqs_on_cpu(void *_get_freqs) static int speedstep_cpu_init(struct cpufreq_policy *policy) { - int result; unsigned int policy_cpu, speed; struct get_freqs gf; @@ -349,13 +348,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) /* cpuinfo and default policy values */ policy->cur = speed; - result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); - if (result) - return result; - - cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu); - - return 0; + return cpufreq_table_validate_and_show(policy, speedstep_freqs); } diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index abfba4f..f4d0318 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -329,13 +329,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = speed; - result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); - if (result) - return result; - - cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu); - - return 0; + return cpufreq_table_validate_and_show(policy, speedstep_freqs); } static int speedstep_cpu_exit(struct cpufreq_policy *policy) -- cgit v0.10.2 From 2338799f3247ec19447a201baea8cf55bdc071d9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:39 +0530 Subject: cpufreq: tegra: use cpufreq_table_validate_and_show() Lets use cpufreq_table_validate_and_show() instead of calling cpufreq_frequency_table_cpuinfo() and cpufreq_frequency_table_get_attr(). Acked-by: Stephen Warren Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra-cpufreq.c index a7b876f..d45c1d8 100644 --- a/drivers/cpufreq/tegra-cpufreq.c +++ b/drivers/cpufreq/tegra-cpufreq.c @@ -215,8 +215,7 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) clk_prepare_enable(emc_clk); clk_prepare_enable(cpu_clk); - cpufreq_frequency_table_cpuinfo(policy, freq_table); - cpufreq_frequency_table_get_attr(freq_table, policy->cpu); + cpufreq_table_validate_and_show(policy, freq_table); policy->cur = tegra_getspeed(policy->cpu); target_cpu_speed[policy->cpu] = policy->cur; -- cgit v0.10.2 From 2e6a5c80e6fa8fd3af6c2ffc5ad6073e798a1690 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:40 +0530 Subject: cpufreq: tegra: fix implementation of ->exit() ->exit() of drivers should call cpufreq_frequency_table_put_attr() if they have called cpufreq_frequency_table_get_attr() earlier in init() and they aren't required to validate their cpufreq table in exit by calling cpufreq_frequency_table_cpuinfo(). Tegra's driver wasn't calling cpufreq_frequency_table_put_attr() and was calling cpufreq_frequency_table_cpuinfo() in exit. Fix both these issues in it. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra-cpufreq.c index d45c1d8..e014077 100644 --- a/drivers/cpufreq/tegra-cpufreq.c +++ b/drivers/cpufreq/tegra-cpufreq.c @@ -232,7 +232,7 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) static int tegra_cpu_exit(struct cpufreq_policy *policy) { - cpufreq_frequency_table_cpuinfo(policy, freq_table); + cpufreq_frequency_table_put_attr(policy->cpu); clk_disable_unprepare(emc_clk); return 0; } -- cgit v0.10.2 From 848cb944213e88e4929a7efcc1c92bb6b6445353 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Mon, 16 Sep 2013 18:56:41 +0530 Subject: cpufreq: at32ap: add frequency table This patch adds a dynamically calculated frequency table to the at32ap driver. In short the architecture can scale in power of two between a maximum and minimum frequency. Min, max, and the steps in between are added to the table. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c index e0c38d9..1d19fa5 100644 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ b/drivers/cpufreq/at32ap-cpufreq.c @@ -19,8 +19,10 @@ #include #include #include +#include static struct clk *cpuclk; +static struct cpufreq_frequency_table *freq_table; static int at32_verify_speed(struct cpufreq_policy *policy) { @@ -85,13 +87,17 @@ static int at32_set_target(struct cpufreq_policy *policy, static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) { + unsigned int frequency, rate; + int retval, steps, i; + if (policy->cpu != 0) return -EINVAL; cpuclk = clk_get(NULL, "cpu"); if (IS_ERR(cpuclk)) { pr_debug("cpufreq: could not get CPU clk\n"); - return PTR_ERR(cpuclk); + retval = PTR_ERR(cpuclk); + goto out_err; } policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000; @@ -101,9 +107,46 @@ static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) policy->min = policy->cpuinfo.min_freq; policy->max = policy->cpuinfo.max_freq; - printk("cpufreq: AT32AP CPU frequency driver\n"); + /* + * AVR32 CPU frequency rate scales in power of two between maximum and + * minimum, also add space for the table end marker. + * + * Further validate that the frequency is usable, and append it to the + * frequency table. + */ + steps = fls(policy->cpuinfo.max_freq / policy->cpuinfo.min_freq) + 1; + freq_table = kzalloc(steps * sizeof(struct cpufreq_frequency_table), + GFP_KERNEL); + if (!freq_table) { + retval = -ENOMEM; + goto out_err_put_clk; + } - return 0; + frequency = policy->cpuinfo.max_freq; + for (i = 0; i < (steps - 1); i++) { + rate = clk_round_rate(cpuclk, frequency * 1000) / 1000; + + if (rate != frequency) + freq_table[i].frequency = CPUFREQ_ENTRY_INVALID; + else + freq_table[i].frequency = frequency; + + frequency /= 2; + } + + freq_table[steps - 1].frequency = CPUFREQ_TABLE_END; + + retval = cpufreq_table_validate_and_show(policy, freq_table); + if (!retval) { + printk("cpufreq: AT32AP CPU frequency driver\n"); + return 0; + } + + kfree(freq_table); +out_err_put_clk: + clk_put(cpuclk); +out_err: + return retval; } static struct cpufreq_driver at32_driver = { -- cgit v0.10.2 From 2457dac670f287b260d50792988f4788f403ca32 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:42 +0530 Subject: cpufreq: arm_big_little: call cpufreq_frequency_table_put_attr() Drivers which have an exit path must call cpufreq_frequency_table_put_attr() if they have called cpufreq_frequency_table_get_attr() in their init path. This driver was missing this part and is fixed with this patch. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 5070273..9acfb82 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -198,6 +198,7 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy) return -ENODEV; } + cpufreq_frequency_table_put_attr(policy->cpu); put_cluster_clk_and_freq_table(cpu_dev); dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu); -- cgit v0.10.2 From 52bcd9986ae6adc69b5e986c09da6fede8ed8119 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:43 +0530 Subject: cpufreq: blackfin: call cpufreq_frequency_table_put_attr() Drivers which have an exit path must call cpufreq_frequency_table_put_attr() if they have called cpufreq_frequency_table_get_attr() in their init path. This driver was missing this part and is fixed with this patch. Cc: Steven Miao Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c index 54c0a0c..0e76c09 100644 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ b/drivers/cpufreq/blackfin-cpufreq.c @@ -213,6 +213,13 @@ static int __bfin_cpu_init(struct cpufreq_policy *policy) return cpufreq_table_validate_and_show(policy, bfin_freq_table); } +static int __bfin_cpu_exit(struct cpufreq_policy *policy) +{ + + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + static struct freq_attr *bfin_freq_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, @@ -223,6 +230,7 @@ static struct cpufreq_driver bfin_driver = { .target = bfin_target, .get = bfin_getfreq_khz, .init = __bfin_cpu_init, + .exit = __bfin_cpu_exit, .name = "bfin cpufreq", .attr = bfin_freq_attr, }; -- cgit v0.10.2 From 724b9ea0e2ebdef35c05fb19ab3690edf52d8708 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:44 +0530 Subject: cpufreq: exynos: call cpufreq_frequency_table_put_attr() Drivers which have an exit path must call cpufreq_frequency_table_put_attr() if they have called cpufreq_frequency_table_get_attr() in their init path. This driver was missing this part and is fixed with this patch. Acked-by: Amit Daniel Kachhap Acked-by: Kukjin Kim Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index b629671..24df155 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -339,12 +339,19 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) return 0; } +static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + static struct cpufreq_driver exynos_driver = { .flags = CPUFREQ_STICKY, .verify = exynos_verify_speed, .target = exynos_target, .get = exynos_getspeed, .init = exynos_cpufreq_cpu_init, + .exit = exynos_cpufreq_cpu_exit, .name = CPUFREQ_NAME, }; -- cgit v0.10.2 From 999fe7951a49fa885f52df85c4f91c913858a232 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:45 +0530 Subject: cpufreq: loongson2: call cpufreq_frequency_table_put_attr() Drivers which have an exit path must call cpufreq_frequency_table_put_attr() if they have called cpufreq_frequency_table_get_attr() in their init path. This driver was missing this part and is fixed with this patch. Cc: John Crispin Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index 5dd3692..cec4e72 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -145,6 +145,7 @@ static int loongson2_cpufreq_verify(struct cpufreq_policy *policy) static int loongson2_cpufreq_exit(struct cpufreq_policy *policy) { + cpufreq_frequency_table_put_attr(policy->cpu); clk_put(cpuclk); return 0; } -- cgit v0.10.2 From 42a4df0026b36d2a8fcfb6a3e79a3d0e1b05714d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Sep 2013 18:56:46 +0530 Subject: cpufreq: omap: call cpufreq_frequency_table_put_attr() Drivers which have an exit path must call cpufreq_frequency_table_put_attr() if they have called cpufreq_frequency_table_get_attr() in their init path. This driver was missing this part and is fixed with this patch. Cc: Santosh Shilimkar Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index b68ce4e..091f233 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -221,6 +221,7 @@ fail_ck: static int omap_cpu_exit(struct cpufreq_policy *policy) { + cpufreq_frequency_table_put_attr(policy->cpu); freq_table_free(); clk_put(mpu_clk); return 0; -- cgit v0.10.2 From 766a8a6dd89268107df1f6783f6a6338efcbf07e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 13 Sep 2013 18:15:46 +0300 Subject: ACPI / thermal: convert printk(LEVEL...) to pr_ Convert printks to pr_* format. Additionally re-use PREFIX constant instead of hardcoded strings. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 6a03293..e600b5d 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -299,8 +299,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No critical threshold\n")); } else if (tmp <= 2732) { - printk(KERN_WARNING FW_BUG "Invalid critical threshold " - "(%llu)\n", tmp); + pr_warn(FW_BUG "Invalid critical threshold (%llu)\n", + tmp); tz->trips.critical.flags.valid = 0; } else { tz->trips.critical.flags.valid = 1; @@ -317,8 +317,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) * Allow override critical threshold */ if (crt_k > tz->trips.critical.temperature) - printk(KERN_WARNING PREFIX - "Critical threshold %d C\n", crt); + pr_warn(PREFIX "Critical threshold %d C\n", + crt); tz->trips.critical.temperature = crt_k; } } @@ -390,8 +390,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) status = acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, &devices); if (ACPI_FAILURE(status)) { - printk(KERN_WARNING PREFIX - "Invalid passive threshold\n"); + pr_warn(PREFIX "Invalid passive threshold\n"); tz->trips.passive.flags.valid = 0; } else @@ -453,8 +452,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) status = acpi_evaluate_reference(tz->device->handle, name, NULL, &devices); if (ACPI_FAILURE(status)) { - printk(KERN_WARNING PREFIX - "Invalid active%d threshold\n", i); + pr_warn(PREFIX "Invalid active%d threshold\n", + i); tz->trips.active[i].flags.valid = 0; } else @@ -505,7 +504,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) valid |= tz->trips.active[i].flags.valid; if (!valid) { - printk(KERN_WARNING FW_BUG "No valid trip found\n"); + pr_warn(FW_BUG "No valid trip found\n"); return -ENODEV; } return 0; @@ -923,8 +922,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) acpi_bus_private_data_handler, tz->thermal_zone); if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Error attaching device data\n"); + pr_err(PREFIX "Error attaching device data\n"); return -ENODEV; } @@ -1094,9 +1092,8 @@ static int acpi_thermal_add(struct acpi_device *device) if (result) goto free_memory; - printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", - acpi_device_name(device), acpi_device_bid(device), - KELVIN_TO_CELSIUS(tz->temperature)); + pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), + acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature)); goto end; free_memory: @@ -1159,24 +1156,24 @@ static int acpi_thermal_resume(struct device *dev) static int thermal_act(const struct dmi_system_id *d) { if (act == 0) { - printk(KERN_NOTICE "ACPI: %s detected: " - "disabling all active thermal trip points\n", d->ident); + pr_notice(PREFIX "%s detected: " + "disabling all active thermal trip points\n", d->ident); act = -1; } return 0; } static int thermal_nocrt(const struct dmi_system_id *d) { - printk(KERN_NOTICE "ACPI: %s detected: " - "disabling all critical thermal trip point actions.\n", d->ident); + pr_notice(PREFIX "%s detected: " + "disabling all critical thermal trip point actions.\n", d->ident); nocrt = 1; return 0; } static int thermal_tzp(const struct dmi_system_id *d) { if (tzp == 0) { - printk(KERN_NOTICE "ACPI: %s detected: " - "enabling thermal zone polling\n", d->ident); + pr_notice(PREFIX "%s detected: " + "enabling thermal zone polling\n", d->ident); tzp = 300; /* 300 dS = 30 Seconds */ } return 0; @@ -1184,8 +1181,8 @@ static int thermal_tzp(const struct dmi_system_id *d) { static int thermal_psv(const struct dmi_system_id *d) { if (psv == 0) { - printk(KERN_NOTICE "ACPI: %s detected: " - "disabling all passive thermal trip points\n", d->ident); + pr_notice(PREFIX "%s detected: " + "disabling all passive thermal trip points\n", d->ident); psv = -1; } return 0; @@ -1238,7 +1235,7 @@ static int __init acpi_thermal_init(void) dmi_check_system(thermal_dmi_table); if (off) { - printk(KERN_NOTICE "ACPI: thermal control disabled\n"); + pr_notice(PREFIX "thermal control disabled\n"); return -ENODEV; } -- cgit v0.10.2 From dd96dc32d59bdf620670a4a527ed9916796f654e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 30 Sep 2013 17:29:43 +0200 Subject: x86 / ACPI: fix incorrect placement of __initdata tag __initdata tag should not be placed between "struct" and "resource" because it prevents the variable from being placed in the intended .init.data section. Fix it. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Signed-off-by: Rafael J. Wysocki diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 40c7660..d00db60 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -745,7 +745,7 @@ static int __init acpi_parse_sbf(struct acpi_table_header *table) #ifdef CONFIG_HPET_TIMER #include -static struct __initdata resource *hpet_res; +static struct resource *hpet_res __initdata; static int __init acpi_parse_hpet(struct acpi_table_header *table) { -- cgit v0.10.2 From 764d022133979f9d9a179152cd89717e9752c61a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Rh=C3=A9aume?= Date: Tue, 1 Oct 2013 05:29:39 -0400 Subject: ACPI / processor: fixed a brace coding style issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed a brace coding style issue. (Brace not on the good line) Signed-off-by: Mathieu Rhéaume Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index e534ba6..40fc773 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -153,8 +153,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __refdata acpi_cpu_notifier = -{ +static struct notifier_block __refdata acpi_cpu_notifier = { .notifier_call = acpi_cpu_soft_notify, }; -- cgit v0.10.2 From 3880d21450b3413c1b30440e8aca6e7dad7d9876 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 13 Sep 2013 16:38:41 +0100 Subject: drivers: cpuidle: rename ARM big.LITTLE driver config and makefile entries Following the reorganization of CPU idle drivers configurations into an ARM specific Kconfig, the existing idle drivers Kconfig entries were renamed and moved to the Kconfig.arm file. Makefile entries were updated accordingly. This patch renames the entries in Kconfig.arm and makefile to make the newly added big.LITTLE CPUidle driver compliant with the new naming convention. Signed-off-by: Lorenzo Pieralisi Acked-by: Kevin Hilman Signed-off-by: Daniel Lezcano diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 8e36603..6a7e6f2 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -2,6 +2,17 @@ # ARM CPU Idle drivers # +config ARM_BIG_LITTLE_CPUIDLE + bool "Support for ARM big.LITTLE processors" + depends on ARCH_VEXPRESS_TC2_PM + select ARM_CPU_SUSPEND + select CPU_IDLE_MULTIPLE_DRIVERS + help + Select this option to enable CPU idle driver for big.LITTLE based + ARM systems. Driver manages CPUs coordination through MCPM and + define different C-states for little and big cores through the + multiple CPU idle drivers infrastructure. + config ARM_HIGHBANK_CPUIDLE bool "CPU Idle Driver for Calxeda processors" depends on ARCH_HIGHBANK @@ -26,14 +37,3 @@ config ARM_U8500_CPUIDLE depends on ARCH_U8500 help Select this to enable cpuidle for ST-E u8500 processors - -config CPU_IDLE_BIG_LITTLE - bool "Support for ARM big.LITTLE processors" - depends on ARCH_VEXPRESS_TC2_PM - select ARM_CPU_SUSPEND - select CPU_IDLE_MULTIPLE_DRIVERS - help - Select this option to enable CPU idle driver for big.LITTLE based - ARM systems. Driver manages CPUs coordination through MCPM and - define different C-states for little and big cores through the - multiple CPU idle drivers infrastructure. diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index cea5ef5..d08bd40 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -7,8 +7,8 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o ################################################################################## # ARM SoC drivers +obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE) += cpuidle-big_little.o obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o -obj-$(CONFIG_CPU_IDLE_BIG_LITTLE) += cpuidle-big_little.o -- cgit v0.10.2 From 4aa88fbe6d6f78a8a464445eb6b55a360e3d3733 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 27 Sep 2013 09:46:09 +0200 Subject: ARM: zynq: cpuidle: Remove useless compatibility string All zynq platforms have this compatibility string and there is no any other clone. Signed-off-by: Daniel Lezcano Acked-by: Michal Simek diff --git a/drivers/cpuidle/cpuidle-zynq.c b/drivers/cpuidle/cpuidle-zynq.c index 38e03a1..ab6c4b4 100644 --- a/drivers/cpuidle/cpuidle-zynq.c +++ b/drivers/cpuidle/cpuidle-zynq.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -72,9 +71,6 @@ static struct cpuidle_driver zynq_idle_driver = { /* Initialize CPU idle by registering the idle states */ static int __init zynq_cpuidle_init(void) { - if (!of_machine_is_compatible("xlnx,zynq-7000")) - return -ENODEV; - pr_info("Xilinx Zynq CpuIdle Driver started\n"); return cpuidle_register(&zynq_idle_driver, NULL); -- cgit v0.10.2 From 3e8ceca6c76ec2d5ee47ece0420cf10d041cf58f Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sat, 21 Sep 2013 18:41:02 +0200 Subject: ARM: zynq: cpuidle: convert to platform driver As the ux500 and the kirkwood driver, make the zynq driver a platform driver Signed-off-by: Daniel Lezcano Acked-by: Michal Simek Tested-by: Soren Brinkmann diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 5f25256..9a7bd13 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -44,6 +44,10 @@ static struct of_device_id zynq_of_bus_ids[] __initdata = { {} }; +static struct platform_device zynq_cpuidle_device = { + .name = "cpuidle-zynq", +}; + /** * zynq_init_machine - System specific initialization, intended to be * called from board specific initialization. @@ -56,6 +60,8 @@ static void __init zynq_init_machine(void) l2x0_of_init(0x02060000, 0xF0F0FFFF); of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL); + + platform_device_register(&zynq_cpuidle_device); } static void __init zynq_timer_init(void) diff --git a/drivers/cpuidle/cpuidle-zynq.c b/drivers/cpuidle/cpuidle-zynq.c index ab6c4b4..aded759 100644 --- a/drivers/cpuidle/cpuidle-zynq.c +++ b/drivers/cpuidle/cpuidle-zynq.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -69,11 +70,19 @@ static struct cpuidle_driver zynq_idle_driver = { }; /* Initialize CPU idle by registering the idle states */ -static int __init zynq_cpuidle_init(void) +static int zynq_cpuidle_probe(struct platform_device *pdev) { pr_info("Xilinx Zynq CpuIdle Driver started\n"); return cpuidle_register(&zynq_idle_driver, NULL); } -device_initcall(zynq_cpuidle_init); +static struct platform_driver zynq_cpuidle_driver = { + .driver = { + .name = "cpuidle-zynq", + .owner = THIS_MODULE, + }, + .probe = zynq_cpuidle_probe, +}; + +module_platform_driver(zynq_cpuidle_driver); -- cgit v0.10.2 From 2c2b24d9c3e96d5cf974be4559a936e7f3b50225 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 27 Sep 2013 18:57:07 +0200 Subject: ARM: ux500: cpuidle: fix section mismatch The dbx500_cpuidle_probe is tagged as an __init section but the variable dbx500_cpuidle_plat_driver is not. The dbx500_cpuidle_probe could not be declared as __init because of macro module_platform_driver builds the exit function, tags as __exit and this one refers to the dbx500_cpuidle_plat_driver which is an __initdata. That leads to a section mismatch. Fix it by removing the __init tag for the probe function. Signed-off-by: Daniel Lezcano Acked-by: Linus Walleij diff --git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c index e056465..5e35804 100644 --- a/drivers/cpuidle/cpuidle-ux500.c +++ b/drivers/cpuidle/cpuidle-ux500.c @@ -111,7 +111,7 @@ static struct cpuidle_driver ux500_idle_driver = { .state_count = 2, }; -static int __init dbx500_cpuidle_probe(struct platform_device *pdev) +static int dbx500_cpuidle_probe(struct platform_device *pdev) { /* Configure wake up reasons */ prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | -- cgit v0.10.2 From b4cb9244a544a1623305eb58267a90418268d31e Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Thu, 3 Oct 2013 12:13:03 -0500 Subject: ACPI: update win8 OSI blacklist More people have reported they need this for their machines to work correctly. References: https://bugzilla.kernel.org/show_bug.cgi?id=60682 Reported-by: Stefan Hellermann Reported-by: Benedikt Sauer Reported-by: Erno Kuusela Reported-by: Jonathan Doman Reported-by: Christoph Klaffl Reported-by: Jan Hendrik Nielsen Signed-off-by: Felipe Contreras Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 9515f18..f37dec5 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -297,6 +297,54 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), }, }, + { + .callback = dmi_disable_osi_win8, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Acer Aspire V5-573G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), + DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Acer Aspire V5-572G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), + DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "ThinkPad T431s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "ThinkPad T430", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. -- cgit v0.10.2 From 068aab7766cf968a8ddb86a6d7c6bbed9d61e353 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Sun, 6 Oct 2013 20:59:55 -0500 Subject: ACPI: add missing win8 OSI comment to blacklist In my original patch[1] I wrote a comment describing the reason for disabling Windows 2012 OSI mode for a group of machines, however, due to unknown reasons (probably a conflict resolution mismatch), the comment was dropped in 94fb982 (ACPI: blacklist win8 OSI for buggy laptops). Since Matthew Garrett is making a big deal out of the lack of comments in a separate patch[2], it might make sense to re-introduce the missing comment so that other patch is not blocked and users don't suffer. [1] http://article.gmane.org/gmane.linux.acpi.devel/63427 [2] http://thread.gmane.org/gmane.linux.kernel/1572459 Signed-off-by: Felipe Contreras Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index f37dec5..aa4d874 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -273,6 +273,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), }, }, + + /* + * The following machines have broken backlight support when reporting + * the Windows 2012 OSI, so disable it until their support is fixed. + */ { .callback = dmi_disable_osi_win8, .ident = "ASUS Zenbook Prime UX31A", -- cgit v0.10.2 From 16ff816d3b5d2b81fcff5ca44eb9a98ac3b604b4 Mon Sep 17 00:00:00 2001 From: Zhang Yanfei Date: Wed, 2 Oct 2013 16:27:37 +0800 Subject: ACPI / memhotplug: Use defined marco METHOD_NAME__STA We already have predefined marco for method name "_STA', so using the marco instead of directly using the string. Signed-off-by: Zhang Yanfei Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 999adb5..dc0880d 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -152,8 +152,9 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device) unsigned long long current_status; /* Get device present/absent information from the _STA */ - if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA", - NULL, ¤t_status))) + if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, + METHOD_NAME__STA, NULL, + ¤t_status))) return -ENODEV; /* * Check for device status. Device should be -- cgit v0.10.2 From 1b750e3bdae5b2d0f3d377b0c56e7465f85b67f2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Oct 2013 14:13:09 +0530 Subject: cpufreq: make return type of lock_policy_rwsem_{read|write}() as void lock_policy_rwsem_{read|write}() currently has return type of int, but it always returns zero and hence its return type should be void instead. This patch makes that change and modifies all of the users accordingly. Reported-by: Jon Medhurst Signed-off-by: Viresh Kumar Reviewed-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 04548f7..eb993d9 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -67,13 +67,11 @@ static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem); #define lock_policy_rwsem(mode, cpu) \ -static int lock_policy_rwsem_##mode(int cpu) \ +static void lock_policy_rwsem_##mode(int cpu) \ { \ struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); \ BUG_ON(!policy); \ down_##mode(&per_cpu(cpu_policy_rwsem, policy->cpu)); \ - \ - return 0; \ } lock_policy_rwsem(read, cpu); @@ -653,13 +651,12 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) { struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); - ssize_t ret = -EINVAL; + ssize_t ret; if (!down_read_trylock(&cpufreq_rwsem)) - goto exit; + return -EINVAL; - if (lock_policy_rwsem_read(policy->cpu) < 0) - goto up_read; + lock_policy_rwsem_read(policy->cpu); if (fattr->show) ret = fattr->show(policy, buf); @@ -667,10 +664,8 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) ret = -EIO; unlock_policy_rwsem_read(policy->cpu); - -up_read: up_read(&cpufreq_rwsem); -exit: + return ret; } @@ -689,8 +684,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, if (!down_read_trylock(&cpufreq_rwsem)) goto unlock; - if (lock_policy_rwsem_write(policy->cpu) < 0) - goto up_read; + lock_policy_rwsem_write(policy->cpu); if (fattr->store) ret = fattr->store(policy, buf, count); @@ -699,7 +693,6 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, unlock_policy_rwsem_write(policy->cpu); -up_read: up_read(&cpufreq_rwsem); unlock: put_online_cpus(); @@ -1147,7 +1140,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, if (ret) { pr_err("%s: Failed to move kobj: %d", __func__, ret); - WARN_ON(lock_policy_rwsem_write(old_cpu)); + lock_policy_rwsem_write(old_cpu); cpumask_set_cpu(old_cpu, policy->cpus); unlock_policy_rwsem_write(old_cpu); @@ -1243,7 +1236,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev, return -EINVAL; } - WARN_ON(lock_policy_rwsem_write(cpu)); + lock_policy_rwsem_write(cpu); cpus = cpumask_weight(policy->cpus); if (cpus > 1) @@ -1466,14 +1459,11 @@ unsigned int cpufreq_get(unsigned int cpu) if (!down_read_trylock(&cpufreq_rwsem)) return 0; - if (unlikely(lock_policy_rwsem_read(cpu))) - goto out_policy; + lock_policy_rwsem_read(cpu); ret_freq = __cpufreq_get(cpu); unlock_policy_rwsem_read(cpu); - -out_policy: up_read(&cpufreq_rwsem); return ret_freq; @@ -1697,14 +1687,12 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, { int ret = -EINVAL; - if (unlikely(lock_policy_rwsem_write(policy->cpu))) - goto fail; + lock_policy_rwsem_write(policy->cpu); ret = __cpufreq_driver_target(policy, target_freq, relation); unlock_policy_rwsem_write(policy->cpu); -fail: return ret; } EXPORT_SYMBOL_GPL(cpufreq_driver_target); @@ -1995,10 +1983,7 @@ int cpufreq_update_policy(unsigned int cpu) goto no_policy; } - if (unlikely(lock_policy_rwsem_write(cpu))) { - ret = -EINVAL; - goto fail; - } + lock_policy_rwsem_write(cpu); pr_debug("updating policy for CPU %u\n", cpu); memcpy(&new_policy, policy, sizeof(*policy)); @@ -2027,7 +2012,6 @@ int cpufreq_update_policy(unsigned int cpu) unlock_policy_rwsem_write(cpu); -fail: cpufreq_cpu_put(policy); no_policy: return ret; -- cgit v0.10.2 From e54968ca1eaa78749d7a7fc20227639a31dff629 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 7 Oct 2013 17:12:21 +0300 Subject: ACPI / platform: Add ACPI IDs for Intel SST audio device This adds ACPI IDs for Intel Smart Sound Technology (SST) device found in Intel Haswell and BayTrail platforms. Signed-off-by: Jarkko Nikula Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 1bde127..ed0f063 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -30,6 +30,9 @@ static const struct acpi_device_id acpi_platform_device_ids[] = { { "PNP0D40" }, + /* Intel Smart Sound Technology */ + { "INT33C8" }, + { "80860F28" }, { } }; -- cgit v0.10.2 From 088f1fd267c7f43b5d87850a0fa0c7e851ecae97 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 9 Oct 2013 09:49:20 +0300 Subject: ACPI / LPSS: fix UART Auto Flow Control There is an additional bit in the GENERAL register on newer silicon that needs to be set or UART's RTS pin fails to reflect the flow control settings in the Modem Control Register. This will fix an issue where the RTS pin of the UART stays always at 1.8V, regardless of the register settings. Signed-off-by: Heikki Krogerus Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index fb78bb9..d396101 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -30,6 +30,7 @@ ACPI_MODULE_NAME("acpi_lpss"); /* Offsets relative to LPSS_PRIVATE_OFFSET */ #define LPSS_GENERAL 0x08 #define LPSS_GENERAL_LTR_MODE_SW BIT(2) +#define LPSS_GENERAL_UART_RTS_OVRD BIT(3) #define LPSS_SW_LTR 0x10 #define LPSS_AUTO_LTR 0x14 #define LPSS_TX_INT 0x20 @@ -68,11 +69,16 @@ struct lpss_private_data { static void lpss_uart_setup(struct lpss_private_data *pdata) { - unsigned int tx_int_offset = pdata->dev_desc->prv_offset + LPSS_TX_INT; + unsigned int offset; u32 reg; - reg = readl(pdata->mmio_base + tx_int_offset); - writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + tx_int_offset); + offset = pdata->dev_desc->prv_offset + LPSS_TX_INT; + reg = readl(pdata->mmio_base + offset); + writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + offset); + + offset = pdata->dev_desc->prv_offset + LPSS_GENERAL; + reg = readl(pdata->mmio_base + offset); + writel(reg | LPSS_GENERAL_UART_RTS_OVRD, pdata->mmio_base + offset); } static struct lpss_device_desc lpt_dev_desc = { -- cgit v0.10.2 From e83dda06242073b1c7f9a88f1001e32a4b9fcd1d Mon Sep 17 00:00:00 2001 From: Al Stone Date: Wed, 9 Oct 2013 14:21:10 -0600 Subject: ACPI: improve acpi_extract_package() utility The current version requires one to know the size of the package a priori; this is almost impossible if the package is composed of strings of variable length. This change allows the utility to allocate a buffer of the proper size if asked. Signed-off-by: Al Stone Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 552248b..fc2cd32 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -169,11 +169,20 @@ acpi_extract_package(union acpi_object *package, /* * Validate output buffer. */ - if (buffer->length < size_required) { + if (buffer->length == ACPI_ALLOCATE_BUFFER) { + buffer->pointer = ACPI_ALLOCATE(size_required); + if (!buffer->pointer) + return AE_NO_MEMORY; buffer->length = size_required; - return AE_BUFFER_OVERFLOW; - } else if (buffer->length != size_required || !buffer->pointer) { - return AE_BAD_PARAMETER; + memset(buffer->pointer, 0, size_required); + } else { + if (buffer->length < size_required) { + buffer->length = size_required; + return AE_BUFFER_OVERFLOW; + } else if (buffer->length != size_required || + !buffer->pointer) { + return AE_BAD_PARAMETER; + } } head = buffer->pointer; -- cgit v0.10.2 From 644f17ad7fc12768cd619532383343e514eab2ac Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 10 Oct 2013 13:28:46 +0300 Subject: ACPI / PM: allow child devices to ignore parent power state Some serial buses like I2C and SPI don't require that the parent device is in D0 before any of its children transitions to D0, but instead the parent device can control its own power independently from the children. This does not follow the ACPI specification as it requires the parent to be powered on before its children. However, Windows seems to ignore this requirement so I think we can do the same in Linux. Implement this by adding a new power flag 'ignore_parent' to struct acpi_device. If this flag is set the ACPI core ignores checking of the parent device power state when the device is powered on/off. Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 59d3202f..ca723a4 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -118,9 +118,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state) /* * If we were unsure about the device parent's power state up to this * point, the fact that the device is in D0 implies that the parent has - * to be in D0 too. + * to be in D0 too, except if ignore_parent is set. */ - if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN + if (!device->power.flags.ignore_parent && device->parent + && device->parent->power.state == ACPI_STATE_UNKNOWN && result == ACPI_STATE_D0) device->parent->power.state = ACPI_STATE_D0; @@ -177,7 +178,8 @@ int acpi_device_set_power(struct acpi_device *device, int state) acpi_power_state_string(state)); return -ENODEV; } - if (device->parent && (state < device->parent->power.state)) { + if (!device->power.flags.ignore_parent && + device->parent && (state < device->parent->power.state)) { dev_warn(&device->dev, "Cannot transition to power state %s for parent in %s\n", acpi_power_state_string(state), diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 02e113b..e830ab0 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -222,7 +222,8 @@ struct acpi_device_power_flags { u32 power_resources:1; /* Power resources */ u32 inrush_current:1; /* Serialize Dx->D0 */ u32 power_removed:1; /* Optimize Dx->D0 */ - u32 reserved:28; + u32 ignore_parent:1; /* Power is independent of parent power state */ + u32 reserved:27; }; struct acpi_device_power_state { -- cgit v0.10.2 From a76e9bd89ae70fdfff5fd1ca47756a35d10c5f3f Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 10 Oct 2013 13:28:47 +0300 Subject: i2c: attach/detach I2C client device to the ACPI power domain If the I2C client device is enumerated from ACPI namespace it might have ACPI methods that needs to be called in order to transition the device to different power states (such as _PSx). Implement this for I2C client devices by checking if the device has an ACPI handle and if that's the case, attach it to the ACPI power domain. In addition we make sure that the device is fully powered when its ->probe() function gets called. For non-ACPI devices this patch is a no-op. Signed-off-by: Lv Zheng Signed-off-by: Mika Westerberg Acked-by: Wolfram Sang Signed-off-by: Rafael J. Wysocki diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 29d3f04..03a8ae6 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -254,10 +254,12 @@ static int i2c_device_probe(struct device *dev) client->flags & I2C_CLIENT_WAKE); dev_dbg(dev, "probe\n"); + acpi_dev_pm_attach(&client->dev, true); status = driver->probe(client, i2c_match_id(driver->id_table, client)); if (status) { client->driver = NULL; i2c_set_clientdata(client, NULL); + acpi_dev_pm_detach(&client->dev, true); } return status; } @@ -283,6 +285,7 @@ static int i2c_device_remove(struct device *dev) client->driver = NULL; i2c_set_clientdata(client, NULL); } + acpi_dev_pm_detach(&client->dev, true); return status; } @@ -1111,8 +1114,10 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, if (ret < 0 || !info.addr) return AE_OK; + adev->power.flags.ignore_parent = true; strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); if (!i2c_new_device(adapter, &info)) { + adev->power.flags.ignore_parent = false; dev_err(&adapter->dev, "failed to add I2C device %s from ACPI\n", dev_name(&adev->dev)); -- cgit v0.10.2 From 33cf00e5708290f7e57d949219ef443a2aef34e0 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 10 Oct 2013 13:28:48 +0300 Subject: spi: attach/detach SPI device to the ACPI power domain If the SPI device is enumerated from ACPI namespace (it has an ACPI handle) it might have ACPI methods that needs to be called in order to transition the device to different power states (such as _PSx). We follow what has been done for platform and I2C buses here and attach the SPI device to the ACPI power domain if the device has an ACPI handle. This makes sure that the device is powered on when its ->probe() is called. For non-ACPI devices this patch is a no-op. Signed-off-by: Mika Westerberg Acked-by: Mark Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9e039c6..740f9dd 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -240,15 +240,27 @@ EXPORT_SYMBOL_GPL(spi_bus_type); static int spi_drv_probe(struct device *dev) { const struct spi_driver *sdrv = to_spi_driver(dev->driver); + struct spi_device *spi = to_spi_device(dev); + int ret; + + acpi_dev_pm_attach(&spi->dev, true); + ret = sdrv->probe(spi); + if (ret) + acpi_dev_pm_detach(&spi->dev, true); - return sdrv->probe(to_spi_device(dev)); + return ret; } static int spi_drv_remove(struct device *dev) { const struct spi_driver *sdrv = to_spi_driver(dev->driver); + struct spi_device *spi = to_spi_device(dev); + int ret; + + ret = sdrv->remove(spi); + acpi_dev_pm_detach(&spi->dev, true); - return sdrv->remove(to_spi_device(dev)); + return ret; } static void spi_drv_shutdown(struct device *dev) @@ -1025,8 +1037,10 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level, return AE_OK; } + adev->power.flags.ignore_parent = true; strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias)); if (spi_add_device(spi)) { + adev->power.flags.ignore_parent = false; dev_err(&master->dev, "failed to add SPI device %s from ACPI\n", dev_name(&adev->dev)); spi_dev_put(spi); -- cgit v0.10.2 From 1e2d9cdfb4494fce682b4ae010d86a2766816d36 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 11 Oct 2013 09:54:08 +0800 Subject: ACPI / Battery: Remove battery's proc directory The battery's proc directory isn't useded and remove it. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 2c9958c..fbf1ace 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -36,12 +36,6 @@ #include #include -#ifdef CONFIG_ACPI_PROCFS_POWER -#include -#include -#include -#endif - #include #include #include @@ -72,19 +66,6 @@ static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); -#ifdef CONFIG_ACPI_PROCFS_POWER -extern struct proc_dir_entry *acpi_lock_battery_dir(void); -extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); - -enum acpi_battery_files { - info_tag = 0, - state_tag, - alarm_tag, - ACPI_BATTERY_NUMFILES, -}; - -#endif - static const struct acpi_device_id battery_device_ids[] = { {"PNP0C0A", 0}, {"", 0}, @@ -320,14 +301,6 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_SERIAL_NUMBER, }; -#ifdef CONFIG_ACPI_PROCFS_POWER -inline char *acpi_battery_units(struct acpi_battery *battery) -{ - return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ? - "mA" : "mW"; -} -#endif - /* -------------------------------------------------------------------------- Battery Management -------------------------------------------------------------------------- */ @@ -741,279 +714,6 @@ static void acpi_battery_refresh(struct acpi_battery *battery) } /* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_PROCFS_POWER -static struct proc_dir_entry *acpi_battery_dir; - -static int acpi_battery_print_info(struct seq_file *seq, int result) -{ - struct acpi_battery *battery = seq->private; - - if (result) - goto end; - - seq_printf(seq, "present: %s\n", - acpi_battery_present(battery) ? "yes" : "no"); - if (!acpi_battery_present(battery)) - goto end; - if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "design capacity: unknown\n"); - else - seq_printf(seq, "design capacity: %d %sh\n", - battery->design_capacity, - acpi_battery_units(battery)); - - if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "last full capacity: unknown\n"); - else - seq_printf(seq, "last full capacity: %d %sh\n", - battery->full_charge_capacity, - acpi_battery_units(battery)); - - seq_printf(seq, "battery technology: %srechargeable\n", - (!battery->technology)?"non-":""); - - if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "design voltage: unknown\n"); - else - seq_printf(seq, "design voltage: %d mV\n", - battery->design_voltage); - seq_printf(seq, "design capacity warning: %d %sh\n", - battery->design_capacity_warning, - acpi_battery_units(battery)); - seq_printf(seq, "design capacity low: %d %sh\n", - battery->design_capacity_low, - acpi_battery_units(battery)); - seq_printf(seq, "cycle count: %i\n", battery->cycle_count); - seq_printf(seq, "capacity granularity 1: %d %sh\n", - battery->capacity_granularity_1, - acpi_battery_units(battery)); - seq_printf(seq, "capacity granularity 2: %d %sh\n", - battery->capacity_granularity_2, - acpi_battery_units(battery)); - seq_printf(seq, "model number: %s\n", battery->model_number); - seq_printf(seq, "serial number: %s\n", battery->serial_number); - seq_printf(seq, "battery type: %s\n", battery->type); - seq_printf(seq, "OEM info: %s\n", battery->oem_info); - end: - if (result) - seq_printf(seq, "ERROR: Unable to read battery info\n"); - return result; -} - -static int acpi_battery_print_state(struct seq_file *seq, int result) -{ - struct acpi_battery *battery = seq->private; - - if (result) - goto end; - - seq_printf(seq, "present: %s\n", - acpi_battery_present(battery) ? "yes" : "no"); - if (!acpi_battery_present(battery)) - goto end; - - seq_printf(seq, "capacity state: %s\n", - (battery->state & 0x04) ? "critical" : "ok"); - if ((battery->state & 0x01) && (battery->state & 0x02)) - seq_printf(seq, - "charging state: charging/discharging\n"); - else if (battery->state & 0x01) - seq_printf(seq, "charging state: discharging\n"); - else if (battery->state & 0x02) - seq_printf(seq, "charging state: charging\n"); - else - seq_printf(seq, "charging state: charged\n"); - - if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "present rate: unknown\n"); - else - seq_printf(seq, "present rate: %d %s\n", - battery->rate_now, acpi_battery_units(battery)); - - if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "remaining capacity: unknown\n"); - else - seq_printf(seq, "remaining capacity: %d %sh\n", - battery->capacity_now, acpi_battery_units(battery)); - if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) - seq_printf(seq, "present voltage: unknown\n"); - else - seq_printf(seq, "present voltage: %d mV\n", - battery->voltage_now); - end: - if (result) - seq_printf(seq, "ERROR: Unable to read battery state\n"); - - return result; -} - -static int acpi_battery_print_alarm(struct seq_file *seq, int result) -{ - struct acpi_battery *battery = seq->private; - - if (result) - goto end; - - if (!acpi_battery_present(battery)) { - seq_printf(seq, "present: no\n"); - goto end; - } - seq_printf(seq, "alarm: "); - if (!battery->alarm) - seq_printf(seq, "unsupported\n"); - else - seq_printf(seq, "%u %sh\n", battery->alarm, - acpi_battery_units(battery)); - end: - if (result) - seq_printf(seq, "ERROR: Unable to read battery alarm\n"); - return result; -} - -static ssize_t acpi_battery_write_alarm(struct file *file, - const char __user * buffer, - size_t count, loff_t * ppos) -{ - int result = 0; - char alarm_string[12] = { '\0' }; - struct seq_file *m = file->private_data; - struct acpi_battery *battery = m->private; - - if (!battery || (count > sizeof(alarm_string) - 1)) - return -EINVAL; - if (!acpi_battery_present(battery)) { - result = -ENODEV; - goto end; - } - if (copy_from_user(alarm_string, buffer, count)) { - result = -EFAULT; - goto end; - } - alarm_string[count] = '\0'; - battery->alarm = simple_strtol(alarm_string, NULL, 0); - result = acpi_battery_set_alarm(battery); - end: - if (!result) - return count; - return result; -} - -typedef int(*print_func)(struct seq_file *seq, int result); - -static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = { - acpi_battery_print_info, - acpi_battery_print_state, - acpi_battery_print_alarm, -}; - -static int acpi_battery_read(int fid, struct seq_file *seq) -{ - struct acpi_battery *battery = seq->private; - int result = acpi_battery_update(battery); - return acpi_print_funcs[fid](seq, result); -} - -#define DECLARE_FILE_FUNCTIONS(_name) \ -static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \ -{ \ - return acpi_battery_read(_name##_tag, seq); \ -} \ -static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \ -} - -DECLARE_FILE_FUNCTIONS(info); -DECLARE_FILE_FUNCTIONS(state); -DECLARE_FILE_FUNCTIONS(alarm); - -#undef DECLARE_FILE_FUNCTIONS - -#define FILE_DESCRIPTION_RO(_name) \ - { \ - .name = __stringify(_name), \ - .mode = S_IRUGO, \ - .ops = { \ - .open = acpi_battery_##_name##_open_fs, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = single_release, \ - .owner = THIS_MODULE, \ - }, \ - } - -#define FILE_DESCRIPTION_RW(_name) \ - { \ - .name = __stringify(_name), \ - .mode = S_IFREG | S_IRUGO | S_IWUSR, \ - .ops = { \ - .open = acpi_battery_##_name##_open_fs, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .write = acpi_battery_write_##_name, \ - .release = single_release, \ - .owner = THIS_MODULE, \ - }, \ - } - -static const struct battery_file { - struct file_operations ops; - umode_t mode; - const char *name; -} acpi_battery_file[] = { - FILE_DESCRIPTION_RO(info), - FILE_DESCRIPTION_RO(state), - FILE_DESCRIPTION_RW(alarm), -}; - -#undef FILE_DESCRIPTION_RO -#undef FILE_DESCRIPTION_RW - -static int acpi_battery_add_fs(struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - int i; - - printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded," - " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_battery_dir); - if (!acpi_device_dir(device)) - return -ENODEV; - } - - for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { - entry = proc_create_data(acpi_battery_file[i].name, - acpi_battery_file[i].mode, - acpi_device_dir(device), - &acpi_battery_file[i].ops, - acpi_driver_data(device)); - if (!entry) - return -ENODEV; - } - return 0; -} - -static void acpi_battery_remove_fs(struct acpi_device *device) -{ - int i; - if (!acpi_device_dir(device)) - return; - for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) - remove_proc_entry(acpi_battery_file[i].name, - acpi_device_dir(device)); - - remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); - acpi_device_dir(device) = NULL; -} - -#endif - -/* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -1075,15 +775,6 @@ static int acpi_battery_add(struct acpi_device *device) result = acpi_battery_update(battery); if (result) goto fail; -#ifdef CONFIG_ACPI_PROCFS_POWER - result = acpi_battery_add_fs(device); -#endif - if (result) { -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_battery_remove_fs(device); -#endif - goto fail; - } printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), @@ -1110,9 +801,6 @@ static int acpi_battery_remove(struct acpi_device *device) return -EINVAL; battery = acpi_driver_data(device); unregister_pm_notifier(&battery->pm_nb); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_battery_remove_fs(device); -#endif sysfs_remove_battery(battery); mutex_destroy(&battery->lock); mutex_destroy(&battery->sysfs_lock); @@ -1158,18 +846,7 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie) { if (acpi_disabled) return; -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_battery_dir = acpi_lock_battery_dir(); - if (!acpi_battery_dir) - return; -#endif - if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_unlock_battery_dir(acpi_battery_dir); -#endif - return; - } - return; + acpi_bus_register_driver(&acpi_battery_driver); } static int __init acpi_battery_init(void) @@ -1181,9 +858,6 @@ static int __init acpi_battery_init(void) static void __exit acpi_battery_exit(void) { acpi_bus_unregister_driver(&acpi_battery_driver); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_unlock_battery_dir(acpi_battery_dir); -#endif } module_init(acpi_battery_init); -- cgit v0.10.2 From 2a68b995c8d5d36de50fd2a7c9c594d986f04c87 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 11 Oct 2013 09:54:09 +0800 Subject: ACPI / SBS: Remove SBS's proc directory SBS's proc directory isn't useded and so remove it. Prepare for removing /proc/acpi directory. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index aef7e1c..d465ae6 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -30,12 +30,6 @@ #include #include -#ifdef CONFIG_ACPI_PROCFS_POWER -#include -#include -#include -#endif - #include #include #include @@ -67,11 +61,6 @@ static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); -extern struct proc_dir_entry *acpi_lock_ac_dir(void); -extern struct proc_dir_entry *acpi_lock_battery_dir(void); -extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); -extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); - #define MAX_SBS_BAT 4 #define ACPI_SBS_BLOCK_MAX 32 @@ -84,9 +73,6 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids); struct acpi_battery { struct power_supply bat; struct acpi_sbs *sbs; -#ifdef CONFIG_ACPI_PROCFS_POWER - struct proc_dir_entry *proc_entry; -#endif unsigned long update_time; char name[8]; char manufacturer_name[ACPI_SBS_BLOCK_MAX]; @@ -119,9 +105,6 @@ struct acpi_sbs { struct acpi_device *device; struct acpi_smb_hc *hc; struct mutex lock; -#ifdef CONFIG_ACPI_PROCFS_POWER - struct proc_dir_entry *charger_entry; -#endif struct acpi_battery battery[MAX_SBS_BAT]; u8 batteries_supported:4; u8 manager_present:1; @@ -482,261 +465,6 @@ static struct device_attribute alarm_attr = { }; /* -------------------------------------------------------------------------- - FS Interface (/proc/acpi) - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_PROCFS_POWER -/* Generic Routines */ -static int -acpi_sbs_add_fs(struct proc_dir_entry **dir, - struct proc_dir_entry *parent_dir, - char *dir_name, - const struct file_operations *info_fops, - const struct file_operations *state_fops, - const struct file_operations *alarm_fops, void *data) -{ - printk(KERN_WARNING PREFIX "Deprecated procfs I/F for SBS is loaded," - " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); - if (!*dir) { - *dir = proc_mkdir(dir_name, parent_dir); - if (!*dir) { - return -ENODEV; - } - } - - /* 'info' [R] */ - if (info_fops) - proc_create_data(ACPI_SBS_FILE_INFO, S_IRUGO, *dir, - info_fops, data); - - /* 'state' [R] */ - if (state_fops) - proc_create_data(ACPI_SBS_FILE_STATE, S_IRUGO, *dir, - state_fops, data); - - /* 'alarm' [R/W] */ - if (alarm_fops) - proc_create_data(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir, - alarm_fops, data); - return 0; -} - -/* Smart Battery Interface */ -static struct proc_dir_entry *acpi_battery_dir = NULL; - -static inline char *acpi_battery_units(struct acpi_battery *battery) -{ - return acpi_battery_mode(battery) ? " mW" : " mA"; -} - - -static int acpi_battery_read_info(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - int result = 0; - - mutex_lock(&sbs->lock); - - seq_printf(seq, "present: %s\n", - (battery->present) ? "yes" : "no"); - if (!battery->present) - goto end; - - seq_printf(seq, "design capacity: %i%sh\n", - battery->design_capacity * acpi_battery_scale(battery), - acpi_battery_units(battery)); - seq_printf(seq, "last full capacity: %i%sh\n", - battery->full_charge_capacity * acpi_battery_scale(battery), - acpi_battery_units(battery)); - seq_printf(seq, "battery technology: rechargeable\n"); - seq_printf(seq, "design voltage: %i mV\n", - battery->design_voltage * acpi_battery_vscale(battery)); - seq_printf(seq, "design capacity warning: unknown\n"); - seq_printf(seq, "design capacity low: unknown\n"); - seq_printf(seq, "cycle count: %i\n", battery->cycle_count); - seq_printf(seq, "capacity granularity 1: unknown\n"); - seq_printf(seq, "capacity granularity 2: unknown\n"); - seq_printf(seq, "model number: %s\n", battery->device_name); - seq_printf(seq, "serial number: %i\n", - battery->serial_number); - seq_printf(seq, "battery type: %s\n", - battery->device_chemistry); - seq_printf(seq, "OEM info: %s\n", - battery->manufacturer_name); - end: - mutex_unlock(&sbs->lock); - return result; -} - -static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_info, PDE_DATA(inode)); -} - -static int acpi_battery_read_state(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - int rate; - - mutex_lock(&sbs->lock); - seq_printf(seq, "present: %s\n", - (battery->present) ? "yes" : "no"); - if (!battery->present) - goto end; - - acpi_battery_get_state(battery); - seq_printf(seq, "capacity state: %s\n", - (battery->state & 0x0010) ? "critical" : "ok"); - seq_printf(seq, "charging state: %s\n", - (battery->rate_now < 0) ? "discharging" : - ((battery->rate_now > 0) ? "charging" : "charged")); - rate = abs(battery->rate_now) * acpi_battery_ipscale(battery); - rate *= (acpi_battery_mode(battery))?(battery->voltage_now * - acpi_battery_vscale(battery)/1000):1; - seq_printf(seq, "present rate: %d%s\n", rate, - acpi_battery_units(battery)); - seq_printf(seq, "remaining capacity: %i%sh\n", - battery->capacity_now * acpi_battery_scale(battery), - acpi_battery_units(battery)); - seq_printf(seq, "present voltage: %i mV\n", - battery->voltage_now * acpi_battery_vscale(battery)); - - end: - mutex_unlock(&sbs->lock); - return 0; -} - -static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_state, PDE_DATA(inode)); -} - -static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - int result = 0; - - mutex_lock(&sbs->lock); - - if (!battery->present) { - seq_printf(seq, "present: no\n"); - goto end; - } - - acpi_battery_get_alarm(battery); - seq_printf(seq, "alarm: "); - if (battery->alarm_capacity) - seq_printf(seq, "%i%sh\n", - battery->alarm_capacity * - acpi_battery_scale(battery), - acpi_battery_units(battery)); - else - seq_printf(seq, "disabled\n"); - end: - mutex_unlock(&sbs->lock); - return result; -} - -static ssize_t -acpi_battery_write_alarm(struct file *file, const char __user * buffer, - size_t count, loff_t * ppos) -{ - struct seq_file *seq = file->private_data; - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - char alarm_string[12] = { '\0' }; - int result = 0; - mutex_lock(&sbs->lock); - if (!battery->present) { - result = -ENODEV; - goto end; - } - if (count > sizeof(alarm_string) - 1) { - result = -EINVAL; - goto end; - } - if (copy_from_user(alarm_string, buffer, count)) { - result = -EFAULT; - goto end; - } - alarm_string[count] = 0; - battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) / - acpi_battery_scale(battery); - acpi_battery_set_alarm(battery); - end: - mutex_unlock(&sbs->lock); - if (result) - return result; - return count; -} - -static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_alarm, PDE_DATA(inode)); -} - -static const struct file_operations acpi_battery_info_fops = { - .open = acpi_battery_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations acpi_battery_state_fops = { - .open = acpi_battery_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations acpi_battery_alarm_fops = { - .open = acpi_battery_alarm_open_fs, - .read = seq_read, - .write = acpi_battery_write_alarm, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -/* Legacy AC Adapter Interface */ - -static struct proc_dir_entry *acpi_ac_dir = NULL; - -static int acpi_ac_read_state(struct seq_file *seq, void *offset) -{ - - struct acpi_sbs *sbs = seq->private; - - mutex_lock(&sbs->lock); - - seq_printf(seq, "state: %s\n", - sbs->charger_present ? "on-line" : "off-line"); - - mutex_unlock(&sbs->lock); - return 0; -} - -static int acpi_ac_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_ac_read_state, PDE_DATA(inode)); -} - -static const struct file_operations acpi_ac_state_fops = { - .open = acpi_ac_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -#endif - -/* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ static int acpi_battery_read(struct acpi_battery *battery) @@ -781,12 +509,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) return result; sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, - battery->name, &acpi_battery_info_fops, - &acpi_battery_state_fops, &acpi_battery_alarm_fops, - battery); -#endif battery->bat.name = battery->name; battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; if (!acpi_battery_mode(battery)) { @@ -822,10 +544,6 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id) device_remove_file(battery->bat.dev, &alarm_attr); power_supply_unregister(&battery->bat); } -#ifdef CONFIG_ACPI_PROCFS_POWER - proc_remove(battery->proc_entry); - battery->proc_entry = NULL; -#endif } static int acpi_charger_add(struct acpi_sbs *sbs) @@ -835,13 +553,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs) result = acpi_ac_get_present(sbs); if (result) goto end; -#ifdef CONFIG_ACPI_PROCFS_POWER - result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, - ACPI_AC_DIR_NAME, NULL, - &acpi_ac_state_fops, NULL, sbs); - if (result) - goto end; -#endif + sbs->charger.name = "sbs-charger"; sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; sbs->charger.properties = sbs_ac_props; @@ -859,10 +571,6 @@ static void acpi_charger_remove(struct acpi_sbs *sbs) { if (sbs->charger.dev) power_supply_unregister(&sbs->charger); -#ifdef CONFIG_ACPI_PROCFS_POWER - proc_remove(sbs->charger_entry); - sbs->charger_entry = NULL; -#endif } static void acpi_sbs_callback(void *context) @@ -950,20 +658,6 @@ static int acpi_sbs_remove(struct acpi_device *device) return 0; } -static void acpi_sbs_rmdirs(void) -{ -#ifdef CONFIG_ACPI_PROCFS_POWER - if (acpi_ac_dir) { - acpi_unlock_ac_dir(acpi_ac_dir); - acpi_ac_dir = NULL; - } - if (acpi_battery_dir) { - acpi_unlock_battery_dir(acpi_battery_dir); - acpi_battery_dir = NULL; - } -#endif -} - #ifdef CONFIG_PM_SLEEP static int acpi_sbs_resume(struct device *dev) { @@ -995,28 +689,17 @@ static int __init acpi_sbs_init(void) if (acpi_disabled) return -ENODEV; -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_dir = acpi_lock_ac_dir(); - if (!acpi_ac_dir) - return -ENODEV; - acpi_battery_dir = acpi_lock_battery_dir(); - if (!acpi_battery_dir) { - acpi_sbs_rmdirs(); - return -ENODEV; - } -#endif + result = acpi_bus_register_driver(&acpi_sbs_driver); - if (result < 0) { - acpi_sbs_rmdirs(); + if (result < 0) return -ENODEV; - } + return 0; } static void __exit acpi_sbs_exit(void) { acpi_bus_unregister_driver(&acpi_sbs_driver); - acpi_sbs_rmdirs(); return; } -- cgit v0.10.2 From 7d7ee958867ad3c9c829a36c56e870879e83391f Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 11 Oct 2013 09:54:10 +0800 Subject: ACPI: Remove CONFIG_ACPI_PROCFS_POWER and cm_sbsc.c There is no user of cm_sbs.c and CONFIG_ACPI_PROCFS_POWER. So remove them. Prepare for removing /proc/acpi Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 22327e6..76f9ebd 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -56,23 +56,6 @@ config ACPI_PROCFS Say N to delete /proc/acpi/ files that have moved to /sys/ -config ACPI_PROCFS_POWER - bool "Deprecated power /proc/acpi directories" - depends on PROC_FS - help - For backwards compatibility, this option allows - deprecated power /proc/acpi/ directories to exist, even when - they have been replaced by functions in /sys. - The deprecated directories (and their replacements) include: - /proc/acpi/battery/* (/sys/class/power_supply/*) - /proc/acpi/ac_adapter/* (sys/class/power_supply/*) - This option has no effect on /proc/acpi/ directories - and functions, which do not yet exist in /sys - This option, together with the proc directories, will be - deleted in 2.6.39. - - Say N to delete power /proc/acpi/ directories that have moved to /sys/ - config ACPI_EC_DEBUGFS tristate "EC read/write access through /sys/kernel/debug/ec" default n diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index cdaf68b..a55fc06 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -47,7 +47,6 @@ acpi-y += sysfs.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-$(CONFIG_ACPI_NUMA) += numa.o -acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o ifdef CONFIG_ACPI_VIDEO acpi-y += video_detect.o endif diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c deleted file mode 100644 index 6c9ee68..0000000 --- a/drivers/acpi/cm_sbs.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PREFIX "ACPI: " - -ACPI_MODULE_NAME("cm_sbs"); -#define ACPI_AC_CLASS "ac_adapter" -#define ACPI_BATTERY_CLASS "battery" -#define _COMPONENT ACPI_SBS_COMPONENT -static struct proc_dir_entry *acpi_ac_dir; -static struct proc_dir_entry *acpi_battery_dir; - -static DEFINE_MUTEX(cm_sbs_mutex); - -static int lock_ac_dir_cnt; -static int lock_battery_dir_cnt; - -struct proc_dir_entry *acpi_lock_ac_dir(void) -{ - mutex_lock(&cm_sbs_mutex); - if (!acpi_ac_dir) - acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); - if (acpi_ac_dir) { - lock_ac_dir_cnt++; - } else { - printk(KERN_ERR PREFIX - "Cannot create %s\n", ACPI_AC_CLASS); - } - mutex_unlock(&cm_sbs_mutex); - return acpi_ac_dir; -} -EXPORT_SYMBOL(acpi_lock_ac_dir); - -void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param) -{ - mutex_lock(&cm_sbs_mutex); - if (acpi_ac_dir_param) - lock_ac_dir_cnt--; - if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) { - remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); - acpi_ac_dir = NULL; - } - mutex_unlock(&cm_sbs_mutex); -} -EXPORT_SYMBOL(acpi_unlock_ac_dir); - -struct proc_dir_entry *acpi_lock_battery_dir(void) -{ - mutex_lock(&cm_sbs_mutex); - if (!acpi_battery_dir) { - acpi_battery_dir = - proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); - } - if (acpi_battery_dir) { - lock_battery_dir_cnt++; - } else { - printk(KERN_ERR PREFIX - "Cannot create %s\n", ACPI_BATTERY_CLASS); - } - mutex_unlock(&cm_sbs_mutex); - return acpi_battery_dir; -} -EXPORT_SYMBOL(acpi_lock_battery_dir); - -void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param) -{ - mutex_lock(&cm_sbs_mutex); - if (acpi_battery_dir_param) - lock_battery_dir_cnt--; - if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param - && acpi_battery_dir) { - remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); - acpi_battery_dir = NULL; - } - mutex_unlock(&cm_sbs_mutex); - return; -} -EXPORT_SYMBOL(acpi_unlock_battery_dir); -- cgit v0.10.2 From 7744da5e90a2782ff0d48628c2cb120efcd300f3 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 11 Oct 2013 09:54:11 +0800 Subject: ACPI / proc: Remove alarm proc file Alarm proc file provides the info and control of RTC-CMOS alarm and RTC CMOS driver provides wakealarm sysfs attribute for the same purpose. The alarm file isn't compiled into kernel when RTC CMOS driver is selected. The driver is default to be selected for x86 platform. So alarm file is default not to include. This patch is to remove it to prepare remove /proc/acpi directory. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 04a1378..6a5b152 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c @@ -8,289 +8,17 @@ #include #include -#ifdef CONFIG_X86 -#include -#endif - #include "sleep.h" #define _COMPONENT ACPI_SYSTEM_COMPONENT /* * this file provides support for: - * /proc/acpi/alarm * /proc/acpi/wakeup */ ACPI_MODULE_NAME("sleep") -#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86) -/* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ -#else -#define HAVE_ACPI_LEGACY_ALARM -#endif - -#ifdef HAVE_ACPI_LEGACY_ALARM - -static u32 cmos_bcd_read(int offset, int rtc_control); - -static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) -{ - u32 sec, min, hr; - u32 day, mo, yr, cent = 0; - u32 today = 0; - unsigned char rtc_control = 0; - unsigned long flags; - - spin_lock_irqsave(&rtc_lock, flags); - - rtc_control = CMOS_READ(RTC_CONTROL); - sec = cmos_bcd_read(RTC_SECONDS_ALARM, rtc_control); - min = cmos_bcd_read(RTC_MINUTES_ALARM, rtc_control); - hr = cmos_bcd_read(RTC_HOURS_ALARM, rtc_control); - - /* If we ever get an FACP with proper values... */ - if (acpi_gbl_FADT.day_alarm) { - /* ACPI spec: only low 6 its should be cared */ - day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F; - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - day = bcd2bin(day); - } else - day = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); - if (acpi_gbl_FADT.month_alarm) - mo = cmos_bcd_read(acpi_gbl_FADT.month_alarm, rtc_control); - else { - mo = cmos_bcd_read(RTC_MONTH, rtc_control); - today = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); - } - if (acpi_gbl_FADT.century) - cent = cmos_bcd_read(acpi_gbl_FADT.century, rtc_control); - - yr = cmos_bcd_read(RTC_YEAR, rtc_control); - - spin_unlock_irqrestore(&rtc_lock, flags); - - /* we're trusting the FADT (see above) */ - if (!acpi_gbl_FADT.century) - /* If we're not trusting the FADT, we should at least make it - * right for _this_ century... ehm, what is _this_ century? - * - * TBD: - * ASAP: find piece of code in the kernel, e.g. star tracker driver, - * which we can trust to determine the century correctly. Atom - * watch driver would be nice, too... - * - * if that has not happened, change for first release in 2050: - * if (yr<50) - * yr += 2100; - * else - * yr += 2000; // current line of code - * - * if that has not happened either, please do on 2099/12/31:23:59:59 - * s/2000/2100 - * - */ - yr += 2000; - else - yr += cent * 100; - - /* - * Show correct dates for alarms up to a month into the future. - * This solves issues for nearly all situations with the common - * 30-day alarm clocks in PC hardware. - */ - if (day < today) { - if (mo < 12) { - mo += 1; - } else { - mo = 1; - yr += 1; - } - } - - seq_printf(seq, "%4.4u-", yr); - (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo); - (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day); - (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr); - (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min); - (sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec); - - return 0; -} - -static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_system_alarm_seq_show, PDE_DATA(inode)); -} - -static int get_date_field(char **p, u32 * value) -{ - char *next = NULL; - char *string_end = NULL; - int result = -EINVAL; - - /* - * Try to find delimeter, only to insert null. The end of the - * string won't have one, but is still valid. - */ - if (*p == NULL) - return result; - - next = strpbrk(*p, "- :"); - if (next) - *next++ = '\0'; - - *value = simple_strtoul(*p, &string_end, 10); - - /* Signal success if we got a good digit */ - if (string_end != *p) - result = 0; - - if (next) - *p = next; - else - *p = NULL; - - return result; -} - -/* Read a possibly BCD register, always return binary */ -static u32 cmos_bcd_read(int offset, int rtc_control) -{ - u32 val = CMOS_READ(offset); - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - val = bcd2bin(val); - return val; -} - -/* Write binary value into possibly BCD register */ -static void cmos_bcd_write(u32 val, int offset, int rtc_control) -{ - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - val = bin2bcd(val); - CMOS_WRITE(val, offset); -} - -static ssize_t -acpi_system_write_alarm(struct file *file, - const char __user * buffer, size_t count, loff_t * ppos) -{ - int result = 0; - char alarm_string[30] = { '\0' }; - char *p = alarm_string; - u32 sec, min, hr, day, mo, yr; - int adjust = 0; - unsigned char rtc_control = 0; - - if (count > sizeof(alarm_string) - 1) - return -EINVAL; - - if (copy_from_user(alarm_string, buffer, count)) - return -EFAULT; - - alarm_string[count] = '\0'; - - /* check for time adjustment */ - if (alarm_string[0] == '+') { - p++; - adjust = 1; - } - - if ((result = get_date_field(&p, &yr))) - goto end; - if ((result = get_date_field(&p, &mo))) - goto end; - if ((result = get_date_field(&p, &day))) - goto end; - if ((result = get_date_field(&p, &hr))) - goto end; - if ((result = get_date_field(&p, &min))) - goto end; - if ((result = get_date_field(&p, &sec))) - goto end; - - spin_lock_irq(&rtc_lock); - - rtc_control = CMOS_READ(RTC_CONTROL); - - if (adjust) { - yr += cmos_bcd_read(RTC_YEAR, rtc_control); - mo += cmos_bcd_read(RTC_MONTH, rtc_control); - day += cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); - hr += cmos_bcd_read(RTC_HOURS, rtc_control); - min += cmos_bcd_read(RTC_MINUTES, rtc_control); - sec += cmos_bcd_read(RTC_SECONDS, rtc_control); - } - - spin_unlock_irq(&rtc_lock); - - if (sec > 59) { - min += sec/60; - sec = sec%60; - } - if (min > 59) { - hr += min/60; - min = min%60; - } - if (hr > 23) { - day += hr/24; - hr = hr%24; - } - if (day > 31) { - mo += day/32; - day = day%32; - } - if (mo > 12) { - yr += mo/13; - mo = mo%13; - } - - spin_lock_irq(&rtc_lock); - /* - * Disable alarm interrupt before setting alarm timer or else - * when ACPI_EVENT_RTC is enabled, a spurious ACPI interrupt occurs - */ - rtc_control &= ~RTC_AIE; - CMOS_WRITE(rtc_control, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - - /* write the fields the rtc knows about */ - cmos_bcd_write(hr, RTC_HOURS_ALARM, rtc_control); - cmos_bcd_write(min, RTC_MINUTES_ALARM, rtc_control); - cmos_bcd_write(sec, RTC_SECONDS_ALARM, rtc_control); - - /* - * If the system supports an enhanced alarm it will have non-zero - * offsets into the CMOS RAM here -- which for some reason are pointing - * to the RTC area of memory. - */ - if (acpi_gbl_FADT.day_alarm) - cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control); - if (acpi_gbl_FADT.month_alarm) - cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control); - if (acpi_gbl_FADT.century) { - if (adjust) - yr += cmos_bcd_read(acpi_gbl_FADT.century, rtc_control) * 100; - cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control); - } - /* enable the rtc alarm interrupt */ - rtc_control |= RTC_AIE; - CMOS_WRITE(rtc_control, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - - spin_unlock_irq(&rtc_lock); - - acpi_clear_event(ACPI_EVENT_RTC); - acpi_enable_event(ACPI_EVENT_RTC, 0); - - *ppos += count; - - result = 0; - end: - return result ? result : count; -} -#endif /* HAVE_ACPI_LEGACY_ALARM */ - static int acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) { @@ -417,41 +145,8 @@ static const struct file_operations acpi_system_wakeup_device_fops = { .release = single_release, }; -#ifdef HAVE_ACPI_LEGACY_ALARM -static const struct file_operations acpi_system_alarm_fops = { - .owner = THIS_MODULE, - .open = acpi_system_alarm_open_fs, - .read = seq_read, - .write = acpi_system_write_alarm, - .llseek = seq_lseek, - .release = single_release, -}; - -static u32 rtc_handler(void *context) -{ - acpi_clear_event(ACPI_EVENT_RTC); - acpi_disable_event(ACPI_EVENT_RTC, 0); - - return ACPI_INTERRUPT_HANDLED; -} -#endif /* HAVE_ACPI_LEGACY_ALARM */ - int __init acpi_sleep_proc_init(void) { -#ifdef HAVE_ACPI_LEGACY_ALARM - /* 'alarm' [R/W] */ - proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR, - acpi_root_dir, &acpi_system_alarm_fops); - - acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); - /* - * Disable the RTC event after installing RTC handler. - * Only when RTC alarm is set will it be enabled. - */ - acpi_clear_event(ACPI_EVENT_RTC); - acpi_disable_event(ACPI_EVENT_RTC, 0); -#endif /* HAVE_ACPI_LEGACY_ALARM */ - /* 'wakeup device' [R/W] */ proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR, acpi_root_dir, &acpi_system_wakeup_device_fops); -- cgit v0.10.2 From 3774929d2ac6213a78068a33660d3402f2334d60 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 9 Oct 2013 01:48:35 +0200 Subject: MAINTAINERS / ACPICA: Add ACPICA information to MAINTAINERS ACPICA (ACPI Component Architecture) is an external project that some ACPI kernel code, including the AML interpreter, is derived from. That kernel code is generated automatically out of the original upstream ACPICA sources and therefore, as a general rule, all changes to it have to go through the ACPICA upstream. Add ACPICA information to MAINTAINERS to provide the upstream ACPICA maintainers contact information and pointers to the original ACPICA Web site and source code. Signed-off-by: Rafael J. Wysocki diff --git a/MAINTAINERS b/MAINTAINERS index e61c2e8..2cafc0b8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -253,6 +253,20 @@ F: drivers/pci/*acpi* F: drivers/pci/*/*acpi* F: drivers/pci/*/*/*acpi* +ACPI COMPONENT ARCHITECTURE (ACPICA) +M: Robert Moore +M: Lv Zheng +M: Rafael J. Wysocki +L: linux-acpi@vger.kernel.org +L: devel@acpica.org +W: https://acpica.org/ +W: https://github.com/acpica/acpica/ +Q: https://patchwork.kernel.org/project/linux-acpi/list/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm +S: Supported +F: drivers/acpi/acpica/ +F: include/acpi/ + ACPI FAN DRIVER M: Zhang Rui L: linux-acpi@vger.kernel.org -- cgit v0.10.2 From 67a29e558b17a923c3a53c348315c572b8ca261a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Oct 2013 14:13:11 +0530 Subject: cpufreq: remove invalid comment from __cpufreq_remove_dev() Some section of kerneldoc comment for __cpufreq_remove_dev() is invalid now. Remove it. Suggested-by: Srivatsa S. Bhat Signed-off-by: Viresh Kumar Reviewed-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index eb993d9..c4d3d76 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1306,8 +1306,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev, * __cpufreq_remove_dev - remove a CPU device * * Removes the cpufreq interface for a CPU device. - * Caller should already have policy_rwsem in write mode for this CPU. - * This routine frees the rwsem before returning. */ static inline int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif, -- cgit v0.10.2 From bbdd04ab1f375ef46a0e2d98de439863d35e4d3e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Oct 2013 14:13:12 +0530 Subject: cpufreq: Remove extra blank line We don't need a blank line just at start of a block, lets remove it. Signed-off-by: Viresh Kumar Reviewed-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index c4d3d76..c71a879 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1201,7 +1201,6 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, if (!frozen) sysfs_remove_link(&dev->kobj, "cpufreq"); } else if (cpus > 1) { - new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen); if (new_cpu >= 0) { update_policy_cpu(policy, new_cpu); -- cgit v0.10.2 From 75949c9a1fe0fd07983788449059337edac2b9f6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Oct 2013 14:13:13 +0530 Subject: cpufreq: don't break string in print statements As a rule its better not to break string (quoted inside "") in a print statement even if it crosses 80 column boundary as that may introduce bugs and so this patch rewrites one of the print statements.. Signed-off-by: Viresh Kumar Reviewed-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index c71a879..0255c08 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1206,8 +1206,8 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, update_policy_cpu(policy, new_cpu); if (!frozen) { - pr_debug("%s: policy Kobject moved to cpu: %d " - "from: %d\n",__func__, new_cpu, cpu); + pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n", + __func__, new_cpu, cpu); } } } -- cgit v0.10.2 From 27a862e98341226a50835f29aa26ffa528215ecc Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Oct 2013 14:13:14 +0530 Subject: cpufreq: remove __cpufreq_remove_dev() Nobody except cpufreq_remove_dev() calls __cpufreq_remove_dev() and so we don't need two separate routines here. Merge code from __cpufreq_remove_dev() into cpufreq_remove_dev() and get rid of __cpufreq_remove_dev(). Signed-off-by: Viresh Kumar Reviewed-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0255c08..b04a5d6 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1302,34 +1302,24 @@ static int __cpufreq_remove_dev_finish(struct device *dev, } /** - * __cpufreq_remove_dev - remove a CPU device + * cpufreq_remove_dev - remove a CPU device * * Removes the cpufreq interface for a CPU device. */ -static inline int __cpufreq_remove_dev(struct device *dev, - struct subsys_interface *sif, - bool frozen) -{ - int ret; - - ret = __cpufreq_remove_dev_prepare(dev, sif, frozen); - - if (!ret) - ret = __cpufreq_remove_dev_finish(dev, sif, frozen); - - return ret; -} - static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) { unsigned int cpu = dev->id; - int retval; + int ret; if (cpu_is_offline(cpu)) return 0; - retval = __cpufreq_remove_dev(dev, sif, false); - return retval; + ret = __cpufreq_remove_dev_prepare(dev, sif, false); + + if (!ret) + ret = __cpufreq_remove_dev_finish(dev, sif, false); + + return ret; } static void handle_update(struct work_struct *work) -- cgit v0.10.2 From 77db50c4eb1991d6e88254390ec368e1d23a8fa5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Oct 2013 14:13:15 +0530 Subject: cpufreq: Optimize cpufreq_frequency_table_verify() cpufreq_frequency_table_verify() is rewritten here to make it more logical and efficient. - merge multiple lines for variable declarations together. - quit early if any frequency between min/max is found. - don't call cpufreq_verify_within_limits() in case any valid freq is found as it is of no use. - rename the count variable as found and change its type to boolean. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 11f6fa9..10f3cfb 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -54,9 +54,8 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo); int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table) { - unsigned int next_larger = ~0; - unsigned int i; - unsigned int count = 0; + unsigned int next_larger = ~0, freq, i = 0; + bool found = false; pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu); @@ -64,21 +63,23 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { - unsigned int freq = table[i].frequency; + for (; freq = table[i].frequency, freq != CPUFREQ_TABLE_END; i++) { if (freq == CPUFREQ_ENTRY_INVALID) continue; - if ((freq >= policy->min) && (freq <= policy->max)) - count++; - else if ((next_larger > freq) && (freq > policy->max)) + if ((freq >= policy->min) && (freq <= policy->max)) { + found = true; + break; + } + + if ((next_larger > freq) && (freq > policy->max)) next_larger = freq; } - if (!count) + if (!found) { policy->max = next_larger; - - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + } pr_debug("verification lead to (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu); -- cgit v0.10.2 From 037ce8397d23b2f84ccfb879cf4b43277b0454e3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Oct 2013 14:13:16 +0530 Subject: cpufreq: rename __cpufreq_set_policy() as cpufreq_set_policy() Earlier there used to be two functions named __cpufreq_set_policy() and cpufreq_set_policy(), but now we only have a single routine lets name it cpufreq_set_policy() instead of __cpufreq_set_policy(). This also removes some invalid comments or fixes some incorrect comments. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b04a5d6..3a811df 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -412,7 +412,7 @@ show_one(scaling_min_freq, min); show_one(scaling_max_freq, max); show_one(scaling_cur_freq, cur); -static int __cpufreq_set_policy(struct cpufreq_policy *policy, +static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_policy *new_policy); /** @@ -433,7 +433,7 @@ static ssize_t store_##file_name \ if (ret != 1) \ return -EINVAL; \ \ - ret = __cpufreq_set_policy(policy, &new_policy); \ + ret = cpufreq_set_policy(policy, &new_policy); \ policy->user_policy.object = policy->object; \ \ return ret ? ret : count; \ @@ -491,11 +491,7 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy, &new_policy.governor)) return -EINVAL; - /* - * Do not use cpufreq_set_policy here or the user_policy.max - * will be wrongly overridden - */ - ret = __cpufreq_set_policy(policy, &new_policy); + ret = cpufreq_set_policy(policy, &new_policy); policy->user_policy.policy = policy->policy; policy->user_policy.governor = policy->governor; @@ -837,11 +833,11 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy) int ret = 0; memcpy(&new_policy, policy, sizeof(*policy)); - /* assure that the starting sequence is run in __cpufreq_set_policy */ + /* assure that the starting sequence is run in cpufreq_set_policy */ policy->governor = NULL; /* set default policy */ - ret = __cpufreq_set_policy(policy, &new_policy); + ret = cpufreq_set_policy(policy, &new_policy); policy->user_policy.policy = policy->policy; policy->user_policy.governor = policy->governor; @@ -1846,10 +1842,10 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) EXPORT_SYMBOL(cpufreq_get_policy); /* - * data : current policy. - * policy : policy to be set. + * policy : current policy. + * new_policy: policy to be set. */ -static int __cpufreq_set_policy(struct cpufreq_policy *policy, +static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_policy *new_policy) { int ret = 0, failed = 1; @@ -1995,7 +1991,7 @@ int cpufreq_update_policy(unsigned int cpu) } } - ret = __cpufreq_set_policy(policy, &new_policy); + ret = cpufreq_set_policy(policy, &new_policy); unlock_policy_rwsem_write(cpu); -- cgit v0.10.2 From 6461f018e7ad08863b55c386bf694683e4e2e86e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Oct 2013 14:13:17 +0530 Subject: cpufreq: rewrite cpufreq_driver->flags using shift operator Currently cpufreq_driver's flags are defined directly using 0x1, 0x2, 0x4, 0x8, etc.. As the list grows it becomes less readable.. Use bitwise shift operator << to generate these numbers for respective positions. Signed-off-by: Viresh Kumar Reviewed-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 6b199ed..00c80a5 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -211,13 +211,14 @@ struct cpufreq_driver { }; /* flags */ -#define CPUFREQ_STICKY 0x01 /* the driver isn't removed even if - * all ->init() calls failed */ -#define CPUFREQ_CONST_LOOPS 0x02 /* loops_per_jiffy or other kernel - * "constants" aren't affected by - * frequency transitions */ -#define CPUFREQ_PM_NO_WARN 0x04 /* don't warn on suspend/resume speed - * mismatches */ +#define CPUFREQ_STICKY (1 << 0) /* driver isn't removed even if + all ->init() calls failed */ +#define CPUFREQ_CONST_LOOPS (1 << 1) /* loops_per_jiffy or other + kernel "constants" aren't + affected by frequency + transitions */ +#define CPUFREQ_PM_NO_WARN (1 << 2) /* don't warn on suspend/resume + speed mismatches */ int cpufreq_register_driver(struct cpufreq_driver *driver_data); int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); -- cgit v0.10.2 From 0b981e70748861a3e10ea2e2a689bdcee3e15085 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Oct 2013 14:13:18 +0530 Subject: cpufreq: use cpufreq_driver->flags to mark CPUFREQ_HAVE_GOVERNOR_PER_POLICY Use cpufreq_driver->flags to mark CPUFREQ_HAVE_GOVERNOR_PER_POLICY instead of a separate field within cpufreq_driver. This will save some bytes of memory. Signed-off-by: Viresh Kumar Reviewed-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 9acfb82..2c7c134 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -213,13 +213,13 @@ static struct freq_attr *bL_cpufreq_attr[] = { static struct cpufreq_driver bL_cpufreq_driver = { .name = "arm-big-little", - .flags = CPUFREQ_STICKY, + .flags = CPUFREQ_STICKY | + CPUFREQ_HAVE_GOVERNOR_PER_POLICY, .verify = bL_cpufreq_verify_policy, .target = bL_cpufreq_set_target, .get = bL_cpufreq_get, .init = bL_cpufreq_init, .exit = bL_cpufreq_exit, - .have_governor_per_policy = true, .attr = bL_cpufreq_attr, }; diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 3a811df..fc9110c 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -133,7 +133,7 @@ static DEFINE_MUTEX(cpufreq_governor_mutex); bool have_governor_per_policy(void) { - return cpufreq_driver->have_governor_per_policy; + return !!(cpufreq_driver->flags & CPUFREQ_HAVE_GOVERNOR_PER_POLICY); } EXPORT_SYMBOL_GPL(have_governor_per_policy); diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 88cd39f..b5f2b86 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -191,7 +191,10 @@ struct common_dbs_data { struct attribute_group *attr_group_gov_sys; /* one governor - system */ struct attribute_group *attr_group_gov_pol; /* one governor - policy */ - /* Common data for platforms that don't set have_governor_per_policy */ + /* + * Common data for platforms that don't set + * CPUFREQ_HAVE_GOVERNOR_PER_POLICY + */ struct dbs_data *gdbs_data; struct cpu_dbs_common_info *(*get_cpu_cdbs)(int cpu); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 00c80a5..24b84f7 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -180,13 +180,6 @@ __ATTR(_name, 0644, show_##_name, store_##_name) struct cpufreq_driver { char name[CPUFREQ_NAME_LEN]; u8 flags; - /* - * This should be set by platforms having multiple clock-domains, i.e. - * supporting multiple policies. With this sysfs directories of governor - * would be created in cpu/cpu/cpufreq/ directory and so they can - * use the same governor with different tunables for different clusters. - */ - bool have_governor_per_policy; /* needed by all drivers */ int (*init) (struct cpufreq_policy *policy); @@ -220,6 +213,14 @@ struct cpufreq_driver { #define CPUFREQ_PM_NO_WARN (1 << 2) /* don't warn on suspend/resume speed mismatches */ +/* + * This should be set by platforms having multiple clock-domains, i.e. + * supporting multiple policies. With this sysfs directories of governor would + * be created in cpu/cpu/cpufreq/ directory and so they can use the same + * governor with different tunables for different clusters. + */ +#define CPUFREQ_HAVE_GOVERNOR_PER_POLICY (1 << 3) + int cpufreq_register_driver(struct cpufreq_driver *driver_data); int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); -- cgit v0.10.2 From be49e3465f222b4b796be8a21d14afbfd8f5d20f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Oct 2013 14:13:19 +0530 Subject: cpufreq: add new routine cpufreq_verify_within_cpu_limits() Most of the users of cpufreq_verify_within_limits() calls it for limiting with min/max from policy->cpuinfo. We can make that code simple by introducing another routine which will do this for them automatically. This patch adds another routine cpufreq_verify_within_cpu_limits() and updates others to use it. Signed-off-by: Viresh Kumar Acked-by: Dirk Brandewie Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c index b83d45f6..56c964c 100644 --- a/drivers/cpufreq/cpufreq-nforce2.c +++ b/drivers/cpufreq/cpufreq-nforce2.c @@ -303,9 +303,7 @@ static int nforce2_verify(struct cpufreq_policy *policy) if (policy->min < (fsb_pol_max * fid * 100)) policy->max = (fsb_pol_max + 1) * fid * 100; - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_cpu_limits(policy); return 0; } diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c index f67196e..ba03e6f 100644 --- a/drivers/cpufreq/davinci-cpufreq.c +++ b/drivers/cpufreq/davinci-cpufreq.c @@ -50,9 +50,7 @@ static int davinci_verify_speed(struct cpufreq_policy *policy) if (policy->cpu) return -EINVAL; - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); - + cpufreq_verify_within_cpu_limits(policy); policy->min = clk_round_rate(armclk, policy->min * 1000) / 1000; policy->max = clk_round_rate(armclk, policy->max * 1000) / 1000; cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 10f3cfb..b9336ed 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -60,8 +60,7 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu); - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_cpu_limits(policy); for (; freq = table[i].frequency, freq != CPUFREQ_TABLE_END; i++) { if (freq == CPUFREQ_ENTRY_INVALID) @@ -77,8 +76,7 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, if (!found) { policy->max = next_larger; - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_cpu_limits(policy); } pr_debug("verification lead to (%u - %u kHz) for cpu %u\n", diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c index f7c99df..8152a9b 100644 --- a/drivers/cpufreq/integrator-cpufreq.c +++ b/drivers/cpufreq/integrator-cpufreq.c @@ -59,9 +59,7 @@ static int integrator_verify_policy(struct cpufreq_policy *policy) { struct icst_vco vco; - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_cpu_limits(policy); vco = icst_hz_to_vco(&cclk_params, policy->max * 1000); policy->max = icst_hz(&cclk_params, vco) / 1000; @@ -69,10 +67,7 @@ static int integrator_verify_policy(struct cpufreq_policy *policy) vco = icst_hz_to_vco(&cclk_params, policy->min * 1000); policy->min = icst_hz(&cclk_params, vco) / 1000; - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); - + cpufreq_verify_within_cpu_limits(policy); return 0; } diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 9733f29..a02bd77 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -611,9 +611,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) static int intel_pstate_verify_policy(struct cpufreq_policy *policy) { - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_cpu_limits(policy); if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) && (policy->policy != CPUFREQ_POLICY_PERFORMANCE)) diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c index 5aa0316..074971b 100644 --- a/drivers/cpufreq/longrun.c +++ b/drivers/cpufreq/longrun.c @@ -129,9 +129,7 @@ static int longrun_verify_policy(struct cpufreq_policy *policy) return -EINVAL; policy->cpu = 0; - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_cpu_limits(policy); if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) && (policy->policy != CPUFREQ_POLICY_PERFORMANCE)) diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index d81c4e5..78787e9 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -111,8 +111,7 @@ static struct pcc_cpu __percpu *pcc_cpu_info; static int pcc_cpufreq_verify(struct cpufreq_policy *policy) { - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_cpu_limits(policy); return 0; } diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c index 1362e88..f1fb944 100644 --- a/drivers/cpufreq/sh-cpufreq.c +++ b/drivers/cpufreq/sh-cpufreq.c @@ -87,15 +87,12 @@ static int sh_cpufreq_verify(struct cpufreq_policy *policy) if (freq_table) return cpufreq_frequency_table_verify(policy, freq_table); - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_cpu_limits(policy); policy->min = (clk_round_rate(cpuclk, 1) + 500) / 1000; policy->max = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); - + cpufreq_verify_within_cpu_limits(policy); return 0; } diff --git a/drivers/cpufreq/unicore2-cpufreq.c b/drivers/cpufreq/unicore2-cpufreq.c index b225f04..14e6d31 100644 --- a/drivers/cpufreq/unicore2-cpufreq.c +++ b/drivers/cpufreq/unicore2-cpufreq.c @@ -29,9 +29,7 @@ static int ucv2_verify_speed(struct cpufreq_policy *policy) if (policy->cpu) return -EINVAL; - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - + cpufreq_verify_within_cpu_limits(policy); return 0; } diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 24b84f7..c749591 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -242,6 +242,13 @@ static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, return; } +static inline void +cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy) +{ + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); +} + /********************************************************************* * CPUFREQ NOTIFIER INTERFACE * *********************************************************************/ -- cgit v0.10.2 From 184345129c53e76069c209f9912ed7c457eceb31 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:27:55 +0530 Subject: cpufreq: define generic .attr, .exit() and .verify() routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch introduces generic .attr, .exit() and .verify() cpufreq drivers. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index b9336ed..3458d27 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -86,6 +86,20 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); +/* + * Generic routine to verify policy & frequency table, requires driver to call + * cpufreq_frequency_table_get_attr() prior to it. + */ +int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy) +{ + struct cpufreq_frequency_table *table = + cpufreq_frequency_get_table(policy->cpu); + if (!table) + return -ENODEV; + + return cpufreq_frequency_table_verify(policy, table); +} +EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify); int cpufreq_frequency_table_target(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table, @@ -199,6 +213,12 @@ struct freq_attr cpufreq_freq_attr_scaling_available_freqs = { }; EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); +struct freq_attr *cpufreq_generic_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; +EXPORT_SYMBOL_GPL(cpufreq_generic_attr); + /* * if you use these, you must assure that the frequency table is valid * all the time between get_attr and put_attr! diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index c749591..36ccd0b 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -401,6 +401,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table); +int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy); int cpufreq_frequency_table_target(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table, @@ -416,10 +417,17 @@ struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu); /* the following are really really optional */ extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs; +extern struct freq_attr *cpufreq_generic_attr[]; void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, unsigned int cpu); void cpufreq_frequency_table_put_attr(unsigned int cpu); int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table); +static inline int cpufreq_generic_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + #endif /* _LINUX_CPUFREQ_H */ -- cgit v0.10.2 From db9be2194a829b26d66a2a25e590d2fc39179ba3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:27:56 +0530 Subject: cpufreq: acpi: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses the generic verify routine in the ACPI driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index d993211..94a5a1d 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -516,15 +516,6 @@ out: return result; } -static int acpi_cpufreq_verify(struct cpufreq_policy *policy) -{ - struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); - - pr_debug("acpi_cpufreq_verify\n"); - - return cpufreq_frequency_table_verify(policy, data->freq_table); -} - static unsigned long acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu) { @@ -927,7 +918,7 @@ static struct freq_attr *acpi_cpufreq_attr[] = { }; static struct cpufreq_driver acpi_cpufreq_driver = { - .verify = acpi_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = acpi_cpufreq_target, .bios_limit = acpi_processor_get_bios_limit, .init = acpi_cpufreq_cpu_init, -- cgit v0.10.2 From 3c75a1503f2c5ca91279436b1f573002c869ef06 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:27:57 +0530 Subject: cpufreq: arm_big_little: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the arm_big_little driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 2c7c134..132c966 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -47,14 +47,6 @@ static unsigned int bL_cpufreq_get(unsigned int cpu) return clk_get_rate(clk[cur_cluster]) / 1000; } -/* Validate policy frequency range */ -static int bL_cpufreq_verify_policy(struct cpufreq_policy *policy) -{ - u32 cur_cluster = cpu_to_cluster(policy->cpu); - - return cpufreq_frequency_table_verify(policy, freq_table[cur_cluster]); -} - /* Set clock frequency */ static int bL_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -205,22 +197,16 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy) return 0; } -/* Export freq_table to sysfs */ -static struct freq_attr *bL_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver bL_cpufreq_driver = { .name = "arm-big-little", .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY, - .verify = bL_cpufreq_verify_policy, + .verify = cpufreq_generic_frequency_table_verify, .target = bL_cpufreq_set_target, .get = bL_cpufreq_get, .init = bL_cpufreq_init, .exit = bL_cpufreq_exit, - .attr = bL_cpufreq_attr, + .attr = cpufreq_generic_attr, }; int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) -- cgit v0.10.2 From 5ae68f4737cec20505f3bb0a99bcb2efcfd66792 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:27:58 +0530 Subject: cpufreq: at32ap: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the at32ap driver. Acked-by: Hans-Christian Egtvedt Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c index 1d19fa5..788f7e7 100644 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ b/drivers/cpufreq/at32ap-cpufreq.c @@ -24,16 +24,6 @@ static struct clk *cpuclk; static struct cpufreq_frequency_table *freq_table; -static int at32_verify_speed(struct cpufreq_policy *policy) -{ - if (policy->cpu != 0) - return -EINVAL; - - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); - return 0; -} - static unsigned int at32_get_speed(unsigned int cpu) { /* No SMP support */ @@ -152,7 +142,7 @@ out_err: static struct cpufreq_driver at32_driver = { .name = "at32ap", .init = at32_cpufreq_driver_init, - .verify = at32_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = at32_set_target, .get = at32_get_speed, .flags = CPUFREQ_STICKY, -- cgit v0.10.2 From 00ff424caa68f0d880e3593554ed0aefb52a84a3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:27:59 +0530 Subject: cpufreq: blackfin: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the blackfin driver. Cc: Steven Miao Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c index 0e76c09..48888cf 100644 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ b/drivers/cpufreq/blackfin-cpufreq.c @@ -191,11 +191,6 @@ static int bfin_target(struct cpufreq_policy *policy, return ret; } -static int bfin_verify_speed(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, bfin_freq_table); -} - static int __bfin_cpu_init(struct cpufreq_policy *policy) { @@ -213,26 +208,14 @@ static int __bfin_cpu_init(struct cpufreq_policy *policy) return cpufreq_table_validate_and_show(policy, bfin_freq_table); } -static int __bfin_cpu_exit(struct cpufreq_policy *policy) -{ - - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static struct freq_attr *bfin_freq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver bfin_driver = { - .verify = bfin_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = bfin_target, .get = bfin_getfreq_khz, .init = __bfin_cpu_init, - .exit = __bfin_cpu_exit, + .exit = cpufreq_generic_exit, .name = "bfin cpufreq", - .attr = bfin_freq_attr, + .attr = cpufreq_generic_attr, }; static int __init bfin_cpu_init(void) -- cgit v0.10.2 From f793d79f08d1b44fcad60869fdadd556da780304 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:00 +0530 Subject: cpufreq: cpufreq-cpu0: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the cpufreq-cpu0 driver. Signed-off-by: Viresh Kumar Acked-by: Shawn Guo Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index fd031ec..c4a7514 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -30,11 +30,6 @@ static struct clk *cpu_clk; static struct regulator *cpu_reg; static struct cpufreq_frequency_table *freq_table; -static int cpu0_verify_speed(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, freq_table); -} - static unsigned int cpu0_get_speed(unsigned int cpu) { return clk_get_rate(cpu_clk) / 1000; @@ -148,27 +143,15 @@ static int cpu0_cpufreq_init(struct cpufreq_policy *policy) return 0; } -static int cpu0_cpufreq_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - - return 0; -} - -static struct freq_attr *cpu0_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver cpu0_cpufreq_driver = { .flags = CPUFREQ_STICKY, - .verify = cpu0_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = cpu0_set_target, .get = cpu0_get_speed, .init = cpu0_cpufreq_init, - .exit = cpu0_cpufreq_exit, + .exit = cpufreq_generic_exit, .name = "generic_cpu0", - .attr = cpu0_cpufreq_attr, + .attr = cpufreq_generic_attr, }; static int cpu0_cpufreq_probe(struct platform_device *pdev) -- cgit v0.10.2 From 361db10f61b1d113eadd1b7b1db5f16f63c4eb49 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:01 +0530 Subject: cpufreq: cris: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the cris driver. Cc: Jesper Nilsson Cc: Mikael Starvik Signed-off-by: Viresh Kumar Acked-by: Jesper Nilsson Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c index 444fd96..d26f4e4 100644 --- a/drivers/cpufreq/cris-artpec3-cpufreq.c +++ b/drivers/cpufreq/cris-artpec3-cpufreq.c @@ -54,11 +54,6 @@ static void cris_freq_set_cpu_state(struct cpufreq_policy *policy, cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); }; -static int cris_freq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]); -} - static int cris_freq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -84,26 +79,14 @@ static int cris_freq_cpu_init(struct cpufreq_policy *policy) } -static int cris_freq_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - - -static struct freq_attr *cris_freq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver cris_freq_driver = { .get = cris_freq_get_cpu_frequency, - .verify = cris_freq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = cris_freq_target, .init = cris_freq_cpu_init, - .exit = cris_freq_cpu_exit, + .exit = cpufreq_generic_exit, .name = "cris_freq", - .attr = cris_freq_attr, + .attr = cpufreq_generic_attr, }; static int __init cris_freq_init(void) diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c index 428395e..d384e63 100644 --- a/drivers/cpufreq/cris-etraxfs-cpufreq.c +++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c @@ -54,11 +54,6 @@ static void cris_freq_set_cpu_state(struct cpufreq_policy *policy, cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); }; -static int cris_freq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]); -} - static int cris_freq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -82,25 +77,14 @@ static int cris_freq_cpu_init(struct cpufreq_policy *policy) return cpufreq_table_validate_and_show(policy, cris_freq_table); } -static int cris_freq_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static struct freq_attr *cris_freq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver cris_freq_driver = { .get = cris_freq_get_cpu_frequency, - .verify = cris_freq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = cris_freq_target, .init = cris_freq_cpu_init, - .exit = cris_freq_cpu_exit, + .exit = cpufreq_generic_exit, .name = "cris_freq", - .attr = cris_freq_attr, + .attr = cpufreq_generic_attr, }; static int __init cris_freq_init(void) -- cgit v0.10.2 From 39d0c362b4f808484985a9ffd899c784ee8fca4d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:02 +0530 Subject: cpufreq: davinci: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the davinci driver. Cc: Sekhar Nori Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c index ba03e6f..f228642 100644 --- a/drivers/cpufreq/davinci-cpufreq.c +++ b/drivers/cpufreq/davinci-cpufreq.c @@ -155,26 +155,15 @@ static int davinci_cpu_init(struct cpufreq_policy *policy) return 0; } -static int davinci_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static struct freq_attr *davinci_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver davinci_driver = { .flags = CPUFREQ_STICKY, .verify = davinci_verify_speed, .target = davinci_target, .get = davinci_getspeed, .init = davinci_cpu_init, - .exit = davinci_cpu_exit, + .exit = cpufreq_generic_exit, .name = "davinci", - .attr = davinci_cpufreq_attr, + .attr = cpufreq_generic_attr, }; static int __init davinci_cpufreq_probe(struct platform_device *pdev) -- cgit v0.10.2 From 47150e985cf99578bb1cd76a8cb60b18403c4b30 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:03 +0530 Subject: cpufreq: dbx500: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines for in the dbx500 driver. Cc: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c index 8a484e9..2d70637 100644 --- a/drivers/cpufreq/dbx500-cpufreq.c +++ b/drivers/cpufreq/dbx500-cpufreq.c @@ -19,16 +19,6 @@ static struct cpufreq_frequency_table *freq_table; static struct clk *armss_clk; -static struct freq_attr *dbx500_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - -static int dbx500_cpufreq_verify_speed(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, freq_table); -} - static int dbx500_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -113,12 +103,12 @@ static int dbx500_cpufreq_init(struct cpufreq_policy *policy) static struct cpufreq_driver dbx500_cpufreq_driver = { .flags = CPUFREQ_STICKY | CPUFREQ_CONST_LOOPS, - .verify = dbx500_cpufreq_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = dbx500_cpufreq_target, .get = dbx500_cpufreq_getspeed, .init = dbx500_cpufreq_init, .name = "DBX500", - .attr = dbx500_cpufreq_attr, + .attr = cpufreq_generic_attr, }; static int dbx500_cpufreq_probe(struct platform_device *pdev) -- cgit v0.10.2 From f51d2ac3267b7898fc3f8e8b0af33ffc24823190 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:04 +0530 Subject: cpufreq: e_powersaver: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the e_powersaver driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index c1b7c99..a8cbbd0 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -198,12 +198,6 @@ static int eps_target(struct cpufreq_policy *policy, return ret; } -static int eps_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, - &eps_cpu[policy->cpu]->freq_table[0]); -} - static int eps_cpu_init(struct cpufreq_policy *policy) { unsigned int i; @@ -423,19 +417,14 @@ static int eps_cpu_exit(struct cpufreq_policy *policy) return 0; } -static struct freq_attr *eps_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver eps_driver = { - .verify = eps_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = eps_target, .init = eps_cpu_init, .exit = eps_cpu_exit, .get = eps_get, .name = "e_powersaver", - .attr = eps_attr, + .attr = cpufreq_generic_attr, }; -- cgit v0.10.2 From 06494eb783cf34fa1d67b77fa597b656b6ad07fe Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:05 +0530 Subject: cpufreq: elanfreq: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the elanfreq driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index 4000c34..fe7053c 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c @@ -165,19 +165,6 @@ static void elanfreq_set_cpu_state(struct cpufreq_policy *policy, }; -/** - * elanfreq_validatespeed: test if frequency range is valid - * @policy: the policy to validate - * - * This function checks if a given frequency range in kHz is valid - * for the hardware supported by the driver. - */ - -static int elanfreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]); -} - static int elanfreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -226,13 +213,6 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) } -static int elanfreq_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - - #ifndef MODULE /** * elanfreq_setup - elanfreq command line parameter parsing @@ -255,20 +235,14 @@ __setup("elanfreq=", elanfreq_setup); #endif -static struct freq_attr *elanfreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - - static struct cpufreq_driver elanfreq_driver = { .get = elanfreq_get_cpu_frequency, - .verify = elanfreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = elanfreq_target, .init = elanfreq_cpu_init, - .exit = elanfreq_cpu_exit, + .exit = cpufreq_generic_exit, .name = "elanfreq", - .attr = elanfreq_attr, + .attr = cpufreq_generic_attr, }; static const struct x86_cpu_id elan_id[] = { -- cgit v0.10.2 From eea6181ed2904f379497918a032588f5e74566e4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:06 +0530 Subject: cpufreq: exynos: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the exynos driver. Signed-off-by: Viresh Kumar Acked-By: Amit Daniel Kachhap Acked-by: Kukjin Kim Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index 954baed..08338d4 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -31,12 +31,6 @@ static unsigned int locking_frequency; static bool frequency_locked; static DEFINE_MUTEX(cpufreq_lock); -static int exynos_verify_speed(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, - exynos_info->freq_table); -} - static unsigned int exynos_getspeed(unsigned int cpu) { return clk_get_rate(exynos_info->cpu_clk) / 1000; @@ -257,26 +251,15 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) return cpufreq_table_validate_and_show(policy, exynos_info->freq_table); } -static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static struct freq_attr *exynos_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver exynos_driver = { .flags = CPUFREQ_STICKY, - .verify = exynos_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = exynos_target, .get = exynos_getspeed, .init = exynos_cpufreq_cpu_init, - .exit = exynos_cpufreq_cpu_exit, + .exit = cpufreq_generic_exit, .name = "exynos_cpufreq", - .attr = exynos_cpufreq_attr, + .attr = cpufreq_generic_attr, #ifdef CONFIG_PM .suspend = exynos_cpufreq_suspend, .resume = exynos_cpufreq_resume, diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index 24df155..bce6f74 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -209,12 +209,6 @@ static void exynos_enable_dvfs(void) dvfs_info->base + XMU_DVFS_CTRL); } -static int exynos_verify_speed(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, - dvfs_info->freq_table); -} - static unsigned int exynos_getspeed(unsigned int cpu) { return dvfs_info->cur_frequency; @@ -339,19 +333,13 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) return 0; } -static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - static struct cpufreq_driver exynos_driver = { .flags = CPUFREQ_STICKY, - .verify = exynos_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = exynos_target, .get = exynos_getspeed, .init = exynos_cpufreq_cpu_init, - .exit = exynos_cpufreq_cpu_exit, + .exit = cpufreq_generic_exit, .name = CPUFREQ_NAME, }; -- cgit v0.10.2 From 59b2413bfe51925858148a9d86ffe6b5bbf68a1a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:07 +0530 Subject: cpufreq: ia64-acpi: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the ia64-acpi driver. Cc: Tony Luck Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index 6cfad51..b958bdb 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -248,22 +248,6 @@ acpi_cpufreq_target ( static int -acpi_cpufreq_verify ( - struct cpufreq_policy *policy) -{ - unsigned int result = 0; - struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; - - pr_debug("acpi_cpufreq_verify\n"); - - result = cpufreq_frequency_table_verify(policy, - data->freq_table); - - return (result); -} - - -static int acpi_cpufreq_cpu_init ( struct cpufreq_policy *policy) { @@ -394,20 +378,14 @@ acpi_cpufreq_cpu_exit ( } -static struct freq_attr* acpi_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - - static struct cpufreq_driver acpi_cpufreq_driver = { - .verify = acpi_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = acpi_cpufreq_target, .get = acpi_cpufreq_get, .init = acpi_cpufreq_cpu_init, .exit = acpi_cpufreq_cpu_exit, .name = "acpi-cpufreq", - .attr = acpi_cpufreq_attr, + .attr = cpufreq_generic_attr, }; -- cgit v0.10.2 From 4f6ba385e9db26536e5dbee81a3ae83ec126fa07 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:08 +0530 Subject: cpufreq: imx6q: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines for in the imx6q driver. Signed-off-by: Viresh Kumar Acked-by: Shawn Guo Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index af0e202..d839657 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -35,11 +35,6 @@ static struct device *cpu_dev; static struct cpufreq_frequency_table *freq_table; static unsigned int transition_latency; -static int imx6q_verify_speed(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, freq_table); -} - static unsigned int imx6q_get_speed(unsigned int cpu) { return clk_get_rate(arm_clk) / 1000; @@ -174,25 +169,14 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy) return 0; } -static int imx6q_cpufreq_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static struct freq_attr *imx6q_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver imx6q_cpufreq_driver = { - .verify = imx6q_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = imx6q_set_target, .get = imx6q_get_speed, .init = imx6q_cpufreq_init, - .exit = imx6q_cpufreq_exit, + .exit = cpufreq_generic_exit, .name = "imx6q-cpufreq", - .attr = imx6q_cpufreq_attr, + .attr = cpufreq_generic_attr, }; static int imx6q_cpufreq_probe(struct platform_device *pdev) -- cgit v0.10.2 From a86a41a13e7971c85a6dc2c6865ff7747397ef21 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:09 +0530 Subject: cpufreq: kirkwood: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the kirkwood driver. Tested-by: Andrew Lunn Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index 59cbb35..1a4e4f4 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -102,11 +102,6 @@ static void kirkwood_cpufreq_set_cpu_state(struct cpufreq_policy *policy, cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); }; -static int kirkwood_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, kirkwood_freq_table); -} - static int kirkwood_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -132,25 +127,14 @@ static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy) return cpufreq_table_validate_and_show(policy, kirkwood_freq_table); } -static int kirkwood_cpufreq_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static struct freq_attr *kirkwood_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver kirkwood_cpufreq_driver = { .get = kirkwood_cpufreq_get_cpu_frequency, - .verify = kirkwood_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = kirkwood_cpufreq_target, .init = kirkwood_cpufreq_cpu_init, - .exit = kirkwood_cpufreq_cpu_exit, + .exit = cpufreq_generic_exit, .name = "kirkwood-cpufreq", - .attr = kirkwood_cpufreq_attr, + .attr = cpufreq_generic_attr, }; static int kirkwood_cpufreq_probe(struct platform_device *pdev) -- cgit v0.10.2 From 3a4d0342ebada05810a2400ef1db3c66d88ef22c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:10 +0530 Subject: cpufreq: longhaul: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the longhaul driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 70b66fd..57d7b02 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -625,12 +625,6 @@ static void longhaul_setup_voltagescaling(void) } -static int longhaul_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, longhaul_table); -} - - static int longhaul_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -924,25 +918,14 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) return cpufreq_table_validate_and_show(policy, longhaul_table); } -static int longhaul_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static struct freq_attr *longhaul_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver longhaul_driver = { - .verify = longhaul_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = longhaul_target, .get = longhaul_get, .init = longhaul_cpu_init, - .exit = longhaul_cpu_exit, + .exit = cpufreq_generic_exit, .name = "longhaul", - .attr = longhaul_attr, + .attr = cpufreq_generic_attr, }; static const struct x86_cpu_id longhaul_id[] = { -- cgit v0.10.2 From 6b0f8d737b703f99baf5240d281c28430ed7e775 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:11 +0530 Subject: cpufreq: loongson2: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the loongson2 driver. Cc: John Crispin Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index cec4e72..ed7fbe2 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -137,12 +137,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) &loongson2_clockmod_table[0]); } -static int loongson2_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, - &loongson2_clockmod_table[0]); -} - static int loongson2_cpufreq_exit(struct cpufreq_policy *policy) { cpufreq_frequency_table_put_attr(policy->cpu); @@ -150,19 +144,14 @@ static int loongson2_cpufreq_exit(struct cpufreq_policy *policy) return 0; } -static struct freq_attr *loongson2_table_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver loongson2_cpufreq_driver = { .name = "loongson2", .init = loongson2_cpufreq_cpu_init, - .verify = loongson2_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = loongson2_cpufreq_target, .get = loongson2_cpufreq_get, .exit = loongson2_cpufreq_exit, - .attr = loongson2_table_attr, + .attr = cpufreq_generic_attr, }; static struct platform_device_id platform_device_ids[] = { -- cgit v0.10.2 From b766b90896203e39c833ec9f76babd5ccb1303b1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:12 +0530 Subject: cpufreq: maple: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the maple driver. Cc: Dmitry Eremin-Solenikov Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c index b3fb661..b23d1d8 100644 --- a/drivers/cpufreq/maple-cpufreq.c +++ b/drivers/cpufreq/maple-cpufreq.c @@ -64,11 +64,6 @@ static struct cpufreq_frequency_table maple_cpu_freqs[] = { {0, CPUFREQ_TABLE_END}, }; -static struct freq_attr *maple_cpu_freqs_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - /* Power mode data is an array of the 32 bits PCR values to use for * the various frequencies, retrieved from the device-tree */ @@ -135,11 +130,6 @@ static int maple_scom_query_freq(void) * Common interface to the cpufreq core */ -static int maple_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, maple_cpu_freqs); -} - static int maple_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -190,10 +180,10 @@ static struct cpufreq_driver maple_cpufreq_driver = { .name = "maple", .flags = CPUFREQ_CONST_LOOPS, .init = maple_cpufreq_cpu_init, - .verify = maple_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = maple_cpufreq_target, .get = maple_cpufreq_get_speed, - .attr = maple_cpu_freqs_attr, + .attr = cpufreq_generic_attr, }; static int __init maple_cpufreq_init(void) -- cgit v0.10.2 From d5ca1649c1aebf1e5c95a33fdd80ad415f41dd1d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:13 +0530 Subject: cpufreq: omap: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the OMAP driver. Cc: Santosh Shilimkar Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 091f233..48020b5 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -40,13 +40,6 @@ static struct clk *mpu_clk; static struct device *mpu_dev; static struct regulator *mpu_reg; -static int omap_verify_speed(struct cpufreq_policy *policy) -{ - if (!freq_table) - return -EINVAL; - return cpufreq_frequency_table_verify(policy, freq_table); -} - static unsigned int omap_getspeed(unsigned int cpu) { unsigned long rate; @@ -227,20 +220,15 @@ static int omap_cpu_exit(struct cpufreq_policy *policy) return 0; } -static struct freq_attr *omap_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver omap_driver = { .flags = CPUFREQ_STICKY, - .verify = omap_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = omap_target, .get = omap_getspeed, .init = omap_cpu_init, .exit = omap_cpu_exit, .name = "omap", - .attr = omap_cpufreq_attr, + .attr = cpufreq_generic_attr, }; static int omap_cpufreq_probe(struct platform_device *pdev) -- cgit v0.10.2 From 522f70cefaedf414d8856677f46836f262572a35 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:14 +0530 Subject: cpufreq: p4-clockmod: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the p4-clockmod driver. Cc: David S. Miller Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 03478bf..4fe6d4c 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -140,12 +140,6 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, } -static int cpufreq_p4_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]); -} - - static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) { if (c->x86 == 0x06) { @@ -242,12 +236,6 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) } -static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - static unsigned int cpufreq_p4_get(unsigned int cpu) { u32 l, h; @@ -266,19 +254,14 @@ static unsigned int cpufreq_p4_get(unsigned int cpu) return stock_freq; } -static struct freq_attr *p4clockmod_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver p4clockmod_driver = { - .verify = cpufreq_p4_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = cpufreq_p4_target, .init = cpufreq_p4_cpu_init, - .exit = cpufreq_p4_cpu_exit, + .exit = cpufreq_generic_exit, .get = cpufreq_p4_get, .name = "p4-clockmod", - .attr = p4clockmod_attr, + .attr = cpufreq_generic_attr, }; static const struct x86_cpu_id cpufreq_p4_id[] = { -- cgit v0.10.2 From 571743107dff548ca9dd24d6e6ec2dac2f5424a1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:15 +0530 Subject: cpufreq: pasemi: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the pasemi driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index 23bc8a82..16f2508 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c @@ -69,11 +69,6 @@ static struct cpufreq_frequency_table pas_freqs[] = { {0, CPUFREQ_TABLE_END}, }; -static struct freq_attr *pas_cpu_freqs_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - /* * hardware specific functions */ @@ -251,11 +246,6 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy) return 0; } -static int pas_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, pas_freqs); -} - static int pas_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -298,9 +288,9 @@ static struct cpufreq_driver pas_cpufreq_driver = { .flags = CPUFREQ_CONST_LOOPS, .init = pas_cpufreq_cpu_init, .exit = pas_cpufreq_cpu_exit, - .verify = pas_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = pas_cpufreq_target, - .attr = pas_cpu_freqs_attr, + .attr = cpufreq_generic_attr, }; /* -- cgit v0.10.2 From 2633a46c581baa2a9bc33737dfbc792745e30554 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:16 +0530 Subject: cpufreq: pmac: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the pmac driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index 470b555..8715ab9 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -86,11 +86,6 @@ static struct cpufreq_frequency_table pmac_cpu_freqs[] = { {0, CPUFREQ_TABLE_END}, }; -static struct freq_attr* pmac_cpu_freqs_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static inline void local_delay(unsigned long ms) { if (no_schedule) @@ -378,11 +373,6 @@ static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) return cur_freq; } -static int pmac_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); -} - static int pmac_cpufreq_target( struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -468,14 +458,14 @@ static int pmac_cpufreq_resume(struct cpufreq_policy *policy) } static struct cpufreq_driver pmac_cpufreq_driver = { - .verify = pmac_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = pmac_cpufreq_target, .get = pmac_cpufreq_get_speed, .init = pmac_cpufreq_cpu_init, .suspend = pmac_cpufreq_suspend, .resume = pmac_cpufreq_resume, .flags = CPUFREQ_PM_NO_WARN, - .attr = pmac_cpu_freqs_attr, + .attr = cpufreq_generic_attr, .name = "powermac", }; diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 41fa89e..e853b85 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -70,11 +70,6 @@ static struct cpufreq_frequency_table g5_cpu_freqs[] = { {0, CPUFREQ_TABLE_END}, }; -static struct freq_attr* g5_cpu_freqs_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - /* Power mode data is an array of the 32 bits PCR values to use for * the various frequencies, retrieved from the device-tree */ @@ -317,11 +312,6 @@ static int g5_pfunc_query_freq(void) * Common interface to the cpufreq core */ -static int g5_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, g5_cpu_freqs); -} - static int g5_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -372,10 +362,10 @@ static struct cpufreq_driver g5_cpufreq_driver = { .name = "powermac", .flags = CPUFREQ_CONST_LOOPS, .init = g5_cpufreq_cpu_init, - .verify = g5_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = g5_cpufreq_target, .get = g5_cpufreq_get_speed, - .attr = g5_cpu_freqs_attr, + .attr = cpufreq_generic_attr, }; -- cgit v0.10.2 From d63bd27fe953daa402a108e141c36dcc59c6931c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:17 +0530 Subject: cpufreq: powernow: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the powernow driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index ab1de0d..ff05d28 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c @@ -105,19 +105,6 @@ static void powernow_k6_set_state(struct cpufreq_policy *policy, /** - * powernow_k6_verify - verifies a new CPUfreq policy - * @policy: new policy - * - * Policy must be within lowest and highest possible CPU Frequency, - * and at least one possible state must be within min and max. - */ -static int powernow_k6_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, &clock_ratio[0]); -} - - -/** * powernow_k6_setpolicy - sets a new CPUFreq policy * @policy: new policy * @target_freq: the target frequency @@ -188,19 +175,14 @@ static unsigned int powernow_k6_get(unsigned int cpu) return ret; } -static struct freq_attr *powernow_k6_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver powernow_k6_driver = { - .verify = powernow_k6_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = powernow_k6_target, .init = powernow_k6_cpu_init, .exit = powernow_k6_cpu_exit, .get = powernow_k6_get, .name = "powernow-k6", - .attr = powernow_k6_attr, + .attr = cpufreq_generic_attr, }; static const struct x86_cpu_id powernow_k6_ids[] = { diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index c863c13..14cd98f 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -549,11 +549,6 @@ static int powernow_target(struct cpufreq_policy *policy, } -static int powernow_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, powernow_table); -} - /* * We use the fact that the bus frequency is somehow * a multiple of 100000/3 khz, then we compute sgtc according @@ -699,13 +694,8 @@ static int powernow_cpu_exit(struct cpufreq_policy *policy) return 0; } -static struct freq_attr *powernow_table_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver powernow_driver = { - .verify = powernow_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = powernow_target, .get = powernow_get, #ifdef CONFIG_X86_POWERNOW_K7_ACPI @@ -714,7 +704,7 @@ static struct cpufreq_driver powernow_driver = { .init = powernow_cpu_init, .exit = powernow_cpu_exit, .name = "powernow-k7", - .attr = powernow_table_attr, + .attr = cpufreq_generic_attr, }; static int __init powernow_init(void) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 8d4114a..1e6f68a 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1053,17 +1053,6 @@ static int powernowk8_target(struct cpufreq_policy *pol, return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); } -/* Driver entry point to verify the policy and range of frequencies */ -static int powernowk8_verify(struct cpufreq_policy *pol) -{ - struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); - - if (!data) - return -EINVAL; - - return cpufreq_frequency_table_verify(pol, data->powernow_table); -} - struct init_on_cpu { struct powernow_k8_data *data; int rc; @@ -1225,20 +1214,15 @@ out: return khz; } -static struct freq_attr *powernow_k8_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver cpufreq_amd64_driver = { - .verify = powernowk8_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = powernowk8_target, .bios_limit = acpi_processor_get_bios_limit, .init = powernowk8_cpu_init, .exit = powernowk8_cpu_exit, .get = powernowk8_get, .name = "powernow-k8", - .attr = powernow_k8_attr, + .attr = cpufreq_generic_attr, }; static void __request_acpi_cpufreq(void) -- cgit v0.10.2 From dc2398d7ff282bce5a348481024e41f96e40e854 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:18 +0530 Subject: cpufreq: ppc-corenet: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the ppc-corenet driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c index 5716b44..befd489 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/ppc-corenet-cpufreq.c @@ -252,14 +252,6 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy) return 0; } -static int corenet_cpufreq_verify(struct cpufreq_policy *policy) -{ - struct cpufreq_frequency_table *table = - per_cpu(cpu_data, policy->cpu)->table; - - return cpufreq_frequency_table_verify(policy, table); -} - static int corenet_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -292,20 +284,15 @@ static int corenet_cpufreq_target(struct cpufreq_policy *policy, return ret; } -static struct freq_attr *corenet_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver ppc_corenet_cpufreq_driver = { .name = "ppc_cpufreq", .flags = CPUFREQ_CONST_LOOPS, .init = corenet_cpufreq_cpu_init, .exit = __exit_p(corenet_cpufreq_cpu_exit), - .verify = corenet_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = corenet_cpufreq_target, .get = corenet_cpufreq_get_speed, - .attr = corenet_cpufreq_attr, + .attr = cpufreq_generic_attr, }; static const struct of_device_id node_matches[] __initdata = { -- cgit v0.10.2 From c3bc3d67ff07c1986e8ededc14e3fbdd26528f17 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:19 +0530 Subject: cpufreq: ppc_cbe: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the ppc_cbe driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c index 6c5be63..38540d1 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq.c @@ -128,17 +128,6 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) return cpufreq_table_validate_and_show(policy, cbe_freqs); } -static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static int cbe_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, cbe_freqs); -} - static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -174,10 +163,10 @@ static int cbe_cpufreq_target(struct cpufreq_policy *policy, } static struct cpufreq_driver cbe_cpufreq_driver = { - .verify = cbe_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = cbe_cpufreq_target, .init = cbe_cpufreq_cpu_init, - .exit = cbe_cpufreq_cpu_exit, + .exit = cpufreq_generic_exit, .name = "cbe-cpufreq", .flags = CPUFREQ_CONST_LOOPS, }; -- cgit v0.10.2 From bf36e48d737ebcb2282f51c08e9c7667e30ed3b6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:20 +0530 Subject: cpufreq: pxa: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the PXA driver. Cc: Eric Miao Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index 236531a..82905fe 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -262,23 +262,6 @@ static u32 mdrefr_dri(unsigned int freq) return (interval - (cpu_is_pxa27x() ? 31 : 0)) / 32; } -/* find a valid frequency point */ -static int pxa_verify_policy(struct cpufreq_policy *policy) -{ - struct cpufreq_frequency_table *pxa_freqs_table; - pxa_freqs_t *pxa_freqs; - int ret; - - find_freq_tables(&pxa_freqs_table, &pxa_freqs); - ret = cpufreq_frequency_table_verify(policy, pxa_freqs_table); - - if (freq_debug) - pr_debug("Verified CPU policy: %dKhz min to %dKhz max\n", - policy->min, policy->max); - - return ret; -} - static unsigned int pxa_cpufreq_get(unsigned int cpu) { return get_clk_frequency_khz(0); @@ -465,17 +448,11 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) return 0; } -static int pxa_cpufreq_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - static struct cpufreq_driver pxa_cpufreq_driver = { - .verify = pxa_verify_policy, + .verify = cpufreq_generic_frequency_table_verify, .target = pxa_set_target, .init = pxa_cpufreq_init, - .exit = pxa_cpufreq_exit, + .exit = cpufreq_generic_exit, .get = pxa_cpufreq_get, .name = "PXA2xx", }; diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c index 65fd01e..ae3ac08 100644 --- a/drivers/cpufreq/pxa3xx-cpufreq.c +++ b/drivers/cpufreq/pxa3xx-cpufreq.c @@ -150,11 +150,6 @@ static void __update_bus_freq(struct pxa3xx_freq_info *info) cpu_relax(); } -static int pxa3xx_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, pxa3xx_freqs_table); -} - static unsigned int pxa3xx_cpufreq_get(unsigned int cpu) { return pxa3xx_get_clk_frequency_khz(0); @@ -229,17 +224,11 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy) return 0; } -static int pxa3xx_cpufreq_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - static struct cpufreq_driver pxa3xx_cpufreq_driver = { - .verify = pxa3xx_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = pxa3xx_cpufreq_set, .init = pxa3xx_cpufreq_init, - .exit = pxa3xx_cpufreq_exit, + .exit = cpufreq_generic_exit, .get = pxa3xx_cpufreq_get, .name = "pxa3xx-cpufreq", }; -- cgit v0.10.2 From e96a410540764c21464c22660f7da9d3bfede815 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:21 +0530 Subject: cpufreq: s3cx4xx: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the s3cx4xx driver. Signed-off-by: Viresh Kumar Acked-by: Kukjin Kim Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index a7a4c61..8c57f10 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -87,16 +87,6 @@ static struct cpufreq_frequency_table s3c2450_freq_table[] = { { 0, CPUFREQ_TABLE_END }, }; -static int s3c2416_cpufreq_verify_speed(struct cpufreq_policy *policy) -{ - struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; - - if (policy->cpu != 0) - return -EINVAL; - - return cpufreq_frequency_table_verify(policy, s3c_freq->freq_table); -} - static unsigned int s3c2416_cpufreq_get_speed(unsigned int cpu) { struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; @@ -516,19 +506,14 @@ err_hclk: return ret; } -static struct freq_attr *s3c2416_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver s3c2416_cpufreq_driver = { .flags = 0, - .verify = s3c2416_cpufreq_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = s3c2416_cpufreq_set_target, .get = s3c2416_cpufreq_get_speed, .init = s3c2416_cpufreq_driver_init, .name = "s3c2416", - .attr = s3c2416_cpufreq_attr, + .attr = cpufreq_generic_attr, }; static int __init s3c2416_cpufreq_init(void) diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index 73856d1..027dec1c 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -416,14 +416,6 @@ static int __init s3c_cpufreq_initclks(void) return 0; } -static int s3c_cpufreq_verify(struct cpufreq_policy *policy) -{ - if (policy->cpu != 0) - return -EINVAL; - - return 0; -} - #ifdef CONFIG_PM static struct cpufreq_frequency_table suspend_pll; static unsigned int suspend_freq; @@ -473,7 +465,6 @@ static int s3c_cpufreq_resume(struct cpufreq_policy *policy) static struct cpufreq_driver s3c24xx_driver = { .flags = CPUFREQ_STICKY, - .verify = s3c_cpufreq_verify, .target = s3c_cpufreq_target, .get = s3c_cpufreq_get, .init = s3c_cpufreq_init, diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c index 872f74d..99fbc49 100644 --- a/drivers/cpufreq/s3c64xx-cpufreq.c +++ b/drivers/cpufreq/s3c64xx-cpufreq.c @@ -54,14 +54,6 @@ static struct cpufreq_frequency_table s3c64xx_freq_table[] = { }; #endif -static int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy *policy) -{ - if (policy->cpu != 0) - return -EINVAL; - - return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table); -} - static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu) { if (cpu != 0) @@ -264,7 +256,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) static struct cpufreq_driver s3c64xx_cpufreq_driver = { .flags = 0, - .verify = s3c64xx_cpufreq_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = s3c64xx_cpufreq_set_target, .get = s3c64xx_cpufreq_get_speed, .init = s3c64xx_cpufreq_driver_init, -- cgit v0.10.2 From 9c3c6e337d022291da119c9b5a210eae93884ec4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:22 +0530 Subject: cpufreq: s5pv210: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the s5pv210 driver. Signed-off-by: Viresh Kumar Acked-by: Kukjin Kim Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index c266a7e..0eafc52 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -174,14 +174,6 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq) __raw_writel(tmp1, reg); } -static int s5pv210_verify_speed(struct cpufreq_policy *policy) -{ - if (policy->cpu) - return -EINVAL; - - return cpufreq_frequency_table_verify(policy, s5pv210_freq_table); -} - static unsigned int s5pv210_getspeed(unsigned int cpu) { if (cpu) @@ -603,7 +595,7 @@ static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this, static struct cpufreq_driver s5pv210_driver = { .flags = CPUFREQ_STICKY, - .verify = s5pv210_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = s5pv210_target, .get = s5pv210_getspeed, .init = s5pv210_cpu_init, -- cgit v0.10.2 From dd9f263956727320a2bcba8ffae7e9ab4a5be8a6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:23 +0530 Subject: cpufreq: sa11x0: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the sa11x0 driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 5c8167b..cb4b2ca 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -82,28 +82,6 @@ unsigned int sa11x0_ppcr_to_freq(unsigned int idx) return freq; } - -/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on - * this platform, anyway. - */ -int sa11x0_verify_speed(struct cpufreq_policy *policy) -{ - unsigned int tmp; - if (policy->cpu) - return -EINVAL; - - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - - /* make sure that at least one frequency is within the policy */ - tmp = sa11x0_freq_table[sa11x0_freq_to_ppcr(policy->min)].frequency; - if (tmp > policy->max) - policy->max = tmp; - - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - - return 0; -} - unsigned int sa11x0_getspeed(unsigned int cpu) { if (cpu) diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index f5214ce..39d56a67 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h @@ -23,7 +23,6 @@ struct cpufreq_policy; extern struct cpufreq_frequency_table sa11x0_freq_table[]; extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); -extern int sa11x0_verify_speed(struct cpufreq_policy *policy); extern unsigned int sa11x0_getspeed(unsigned int cpu); extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx); diff --git a/drivers/cpufreq/sa1100-cpufreq.c b/drivers/cpufreq/sa1100-cpufreq.c index 37fce2f..80a4fde 100644 --- a/drivers/cpufreq/sa1100-cpufreq.c +++ b/drivers/cpufreq/sa1100-cpufreq.c @@ -228,7 +228,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver sa1100_driver __refdata = { .flags = CPUFREQ_STICKY, - .verify = sa11x0_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = sa1100_target, .get = sa11x0_getspeed, .init = sa1100_cpu_init, diff --git a/drivers/cpufreq/sa1110-cpufreq.c b/drivers/cpufreq/sa1110-cpufreq.c index 13760fc..a38d904 100644 --- a/drivers/cpufreq/sa1110-cpufreq.c +++ b/drivers/cpufreq/sa1110-cpufreq.c @@ -344,7 +344,7 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy) * it with cpufreq_register_driver() */ static struct cpufreq_driver sa1110_driver __refdata = { .flags = CPUFREQ_STICKY, - .verify = sa11x0_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = sa1110_target, .get = sa11x0_getspeed, .init = sa1110_cpu_init, -- cgit v0.10.2 From a823c4aecdcdc0ead1a80f280cb2baa31d118462 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:24 +0530 Subject: cpufreq: sc520: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the sc520 driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index bb9c0de..8556225 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c @@ -78,11 +78,6 @@ static void sc520_freq_set_cpu_state(struct cpufreq_policy *policy, cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); }; -static int sc520_freq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]); -} - static int sc520_freq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -120,27 +115,14 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy) } -static int sc520_freq_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - - -static struct freq_attr *sc520_freq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - - static struct cpufreq_driver sc520_freq_driver = { .get = sc520_freq_get_cpu_frequency, - .verify = sc520_freq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = sc520_freq_target, .init = sc520_freq_cpu_init, - .exit = sc520_freq_cpu_exit, + .exit = cpufreq_generic_exit, .name = "sc520_freq", - .attr = sc520_freq_attr, + .attr = cpufreq_generic_attr, }; static const struct x86_cpu_id sc520_ids[] = { -- cgit v0.10.2 From a8f64decf383aaf16fd4698f753d3a4c26fbba7d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:25 +0530 Subject: cpufreq: sh: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the sh driver. Cc: Paul Mundt Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c index f1fb944..c681b86 100644 --- a/drivers/cpufreq/sh-cpufreq.c +++ b/drivers/cpufreq/sh-cpufreq.c @@ -151,11 +151,6 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy) return 0; } -static struct freq_attr *sh_freq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver sh_cpufreq_driver = { .name = "sh", .get = sh_cpufreq_get, @@ -163,7 +158,7 @@ static struct cpufreq_driver sh_cpufreq_driver = { .verify = sh_cpufreq_verify, .init = sh_cpufreq_cpu_init, .exit = sh_cpufreq_cpu_exit, - .attr = sh_freq_attr, + .attr = cpufreq_generic_attr, }; static int __init sh_cpufreq_module_init(void) -- cgit v0.10.2 From 7a1874a0645b7cefd80c379db6d78916dd0788a1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:26 +0530 Subject: cpufreq: sparc: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the sparc driver. Cc: David S. Miller Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c index 8db0c18..291688c 100644 --- a/drivers/cpufreq/sparc-us2e-cpufreq.c +++ b/drivers/cpufreq/sparc-us2e-cpufreq.c @@ -295,12 +295,6 @@ static int us2e_freq_target(struct cpufreq_policy *policy, return 0; } -static int us2e_freq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, - &us2e_freq_table[policy->cpu].table[0]); -} - static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) { unsigned int cpu = policy->cpu; @@ -363,7 +357,7 @@ static int __init us2e_freq_init(void) goto err_out; driver->init = us2e_freq_cpu_init; - driver->verify = us2e_freq_verify; + driver->verify = cpufreq_generic_frequency_table_verify; driver->target = us2e_freq_target; driver->get = us2e_freq_get; driver->exit = us2e_freq_cpu_exit; diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c index 120a2df..9b3dbd3 100644 --- a/drivers/cpufreq/sparc-us3-cpufreq.c +++ b/drivers/cpufreq/sparc-us3-cpufreq.c @@ -156,12 +156,6 @@ static int us3_freq_target(struct cpufreq_policy *policy, return 0; } -static int us3_freq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, - &us3_freq_table[policy->cpu].table[0]); -} - static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) { unsigned int cpu = policy->cpu; @@ -224,7 +218,7 @@ static int __init us3_freq_init(void) goto err_out; driver->init = us3_freq_cpu_init; - driver->verify = us3_freq_verify; + driver->verify = cpufreq_generic_frequency_table_verify; driver->target = us3_freq_target; driver->get = us3_freq_get; driver->exit = us3_freq_cpu_exit; -- cgit v0.10.2 From e2132fa66d1ee74a975fd6c42c0aa2fe91e3fc75 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:27 +0530 Subject: cpufreq: spear: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the spear driver. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index b86be6b..e9657e3 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -30,11 +30,6 @@ static struct { u32 cnt; } spear_cpufreq; -static int spear_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, spear_cpufreq.freq_tbl); -} - static unsigned int spear_cpufreq_get(unsigned int cpu) { return clk_get_rate(spear_cpufreq.clk) / 1000; @@ -192,26 +187,15 @@ static int spear_cpufreq_init(struct cpufreq_policy *policy) return 0; } -static int spear_cpufreq_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static struct freq_attr *spear_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver spear_cpufreq_driver = { .name = "cpufreq-spear", .flags = CPUFREQ_STICKY, - .verify = spear_cpufreq_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = spear_cpufreq_target, .get = spear_cpufreq_get, .init = spear_cpufreq_init, - .exit = spear_cpufreq_exit, - .attr = spear_cpufreq_attr, + .exit = cpufreq_generic_exit, + .attr = cpufreq_generic_attr, }; static int spear_cpufreq_driver_init(void) -- cgit v0.10.2 From 3be1394a6873496c36d99899fb6ba76ff03a2e96 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:28 +0530 Subject: cpufreq: speedstep: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the speedstep driver. Cc: David S. Miller Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index f180561..c7c14ae 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -420,19 +420,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) } /** - * centrino_verify - verifies a new CPUFreq policy - * @policy: new policy - * - * Limit must be within this model's frequency range at least one - * border included. - */ -static int centrino_verify (struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, - per_cpu(centrino_model, policy->cpu)->op_points); -} - -/** * centrino_setpolicy - set a new CPUFreq policy * @policy: new policy * @target_freq: the target frequency @@ -553,20 +540,15 @@ out: return retval; } -static struct freq_attr* centrino_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver centrino_driver = { .name = "centrino", /* should be speedstep-centrino, but there's a 16 char limit */ .init = centrino_cpu_init, .exit = centrino_cpu_exit, - .verify = centrino_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = centrino_target, .get = get_cur_freq, - .attr = centrino_attr, + .attr = cpufreq_generic_attr, }; /* diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index 86a184e..929a4f0 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -289,18 +289,6 @@ static int speedstep_target(struct cpufreq_policy *policy, } -/** - * speedstep_verify - verifies a new CPUFreq policy - * @policy: new policy - * - * Limit must be within speedstep_low_freq and speedstep_high_freq, with - * at least one border included. - */ -static int speedstep_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]); -} - struct get_freqs { struct cpufreq_policy *policy; int ret; @@ -352,26 +340,14 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) } -static int speedstep_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - -static struct freq_attr *speedstep_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - - static struct cpufreq_driver speedstep_driver = { .name = "speedstep-ich", - .verify = speedstep_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = speedstep_target, .init = speedstep_cpu_init, - .exit = speedstep_cpu_exit, + .exit = cpufreq_generic_exit, .get = speedstep_get, - .attr = speedstep_attr, + .attr = cpufreq_generic_attr, }; static const struct x86_cpu_id ss_smi_ids[] = { diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index f4d0318..b3dfba0 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -264,19 +264,6 @@ static int speedstep_target(struct cpufreq_policy *policy, } -/** - * speedstep_verify - verifies a new CPUFreq policy - * @policy: new policy - * - * Limit must be within speedstep_low_freq and speedstep_high_freq, with - * at least one border included. - */ -static int speedstep_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]); -} - - static int speedstep_cpu_init(struct cpufreq_policy *policy) { int result; @@ -332,12 +319,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) return cpufreq_table_validate_and_show(policy, speedstep_freqs); } -static int speedstep_cpu_exit(struct cpufreq_policy *policy) -{ - cpufreq_frequency_table_put_attr(policy->cpu); - return 0; -} - static unsigned int speedstep_get(unsigned int cpu) { if (cpu) @@ -356,20 +337,15 @@ static int speedstep_resume(struct cpufreq_policy *policy) return result; } -static struct freq_attr *speedstep_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver speedstep_driver = { .name = "speedstep-smi", - .verify = speedstep_verify, + .verify = cpufreq_generic_frequency_table_verify, .target = speedstep_target, .init = speedstep_cpu_init, - .exit = speedstep_cpu_exit, + .exit = cpufreq_generic_exit, .get = speedstep_get, .resume = speedstep_resume, - .attr = speedstep_attr, + .attr = cpufreq_generic_attr, }; static const struct x86_cpu_id ss_smi_ids[] = { -- cgit v0.10.2 From 8e08cf03a46299bc1ebf9dbd2ebe7d3093f89541 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:29 +0530 Subject: cpufreq: tegra: Use generic cpufreq routines Most of the CPUFreq drivers do similar things in .exit() and .verify() routines and .attr. So its better if we have generic routines for them which can be used by cpufreq drivers then. This patch uses these generic routines in the Tegra driver. Cc: Stephen Warren Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra-cpufreq.c index e014077..c36a8e7 100644 --- a/drivers/cpufreq/tegra-cpufreq.c +++ b/drivers/cpufreq/tegra-cpufreq.c @@ -51,11 +51,6 @@ static unsigned long target_cpu_speed[NUM_CPUS]; static DEFINE_MUTEX(tegra_cpu_lock); static bool is_suspended; -static int tegra_verify_speed(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, freq_table); -} - static unsigned int tegra_getspeed(unsigned int cpu) { unsigned long rate; @@ -237,19 +232,14 @@ static int tegra_cpu_exit(struct cpufreq_policy *policy) return 0; } -static struct freq_attr *tegra_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - static struct cpufreq_driver tegra_cpufreq_driver = { - .verify = tegra_verify_speed, + .verify = cpufreq_generic_frequency_table_verify, .target = tegra_target, .get = tegra_getspeed, .init = tegra_cpu_init, .exit = tegra_cpu_exit, .name = "tegra", - .attr = tegra_cpufreq_attr, + .attr = cpufreq_generic_attr, }; static int __init tegra_cpufreq_init(void) -- cgit v0.10.2 From da60ce9f2faca87013fd3cab1c3bed5183608c3d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:30 +0530 Subject: cpufreq: call cpufreq_driver->get() after calling ->init() Almost all drivers set policy->cur with current CPU frequency in their ->init() part. This can be done for all of them at core level and so they wouldn't need to do it. This patch adds supporting code in cpufreq core for calling get() after we have called init() for a policy. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index fc9110c..f033adf 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1042,6 +1042,14 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, goto err_set_policy_cpu; } + if (cpufreq_driver->get) { + policy->cur = cpufreq_driver->get(policy->cpu); + if (!policy->cur) { + pr_err("%s: ->get() failed\n", __func__); + goto err_get_freq; + } + } + /* related cpus should atleast have policy->cpus */ cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus); @@ -1096,6 +1104,9 @@ err_out_unregister: per_cpu(cpufreq_cpu_data, j) = NULL; write_unlock_irqrestore(&cpufreq_driver_lock, flags); +err_get_freq: + if (cpufreq_driver->exit) + cpufreq_driver->exit(policy); err_set_policy_cpu: cpufreq_policy_free(policy); nomem_out: -- cgit v0.10.2 From 2f75db781b88df2ee4bd62254efbb2768e3619bd Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:31 +0530 Subject: cpufreq: acpi-cpufreq: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 94a5a1d..a8dac7b 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -842,7 +842,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) break; case ACPI_ADR_SPACE_FIXED_HARDWARE: acpi_cpufreq_driver.get = get_cur_freq_on_cpu; - policy->cur = get_cur_freq_on_cpu(cpu); break; default: break; -- cgit v0.10.2 From e4c8afe3a06c682e215c3e38240126b652fa98d0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:32 +0530 Subject: cpufreq: arm_big_little: don't initialize part of policy is set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 132c966..f7717ef 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -171,8 +171,6 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy) else policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = bL_cpufreq_get(policy->cpu); - cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu)); dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu); -- cgit v0.10.2 From 017189b51e0eecd58cf4f65f6f16d59dae6c1368 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:33 +0530 Subject: cpufreq: at32ap: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Acked-by: Hans-Christian Egtvedt Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c index 788f7e7..7439ded 100644 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ b/drivers/cpufreq/at32ap-cpufreq.c @@ -77,7 +77,7 @@ static int at32_set_target(struct cpufreq_policy *policy, static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) { - unsigned int frequency, rate; + unsigned int frequency, rate, min_freq; int retval, steps, i; if (policy->cpu != 0) @@ -90,12 +90,9 @@ static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) goto out_err; } - policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000; - policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; + min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000; + frequency = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; policy->cpuinfo.transition_latency = 0; - policy->cur = at32_get_speed(0); - policy->min = policy->cpuinfo.min_freq; - policy->max = policy->cpuinfo.max_freq; /* * AVR32 CPU frequency rate scales in power of two between maximum and @@ -104,7 +101,7 @@ static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) * Further validate that the frequency is usable, and append it to the * frequency table. */ - steps = fls(policy->cpuinfo.max_freq / policy->cpuinfo.min_freq) + 1; + steps = fls(frequency / min_freq) + 1; freq_table = kzalloc(steps * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); if (!freq_table) { @@ -112,7 +109,6 @@ static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) goto out_err_put_clk; } - frequency = policy->cpuinfo.max_freq; for (i = 0; i < (steps - 1); i++) { rate = clk_round_rate(cpuclk, frequency * 1000) / 1000; -- cgit v0.10.2 From 49ad1eabb6b46bc9d5b4f6c21bf0a555f35905d5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:34 +0530 Subject: cpufreq: blackfin: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Steven Miao Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c index 48888cf..0bc9e8c 100644 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ b/drivers/cpufreq/blackfin-cpufreq.c @@ -204,7 +204,6 @@ static int __bfin_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 50000; /* 50us assumed */ - policy->cur = cclk; return cpufreq_table_validate_and_show(policy, bfin_freq_table); } -- cgit v0.10.2 From 179b889f7c5e6221a9fbf60cf4ef5e55be45cf34 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:35 +0530 Subject: cpufreq: cpu0: don't initialize part of policy set by core too Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Acked-by: Shawn Guo Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index c4a7514..3c09a26 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -131,7 +131,6 @@ static int cpu0_cpufreq_init(struct cpufreq_policy *policy) } policy->cpuinfo.transition_latency = transition_latency; - policy->cur = clk_get_rate(cpu_clk) / 1000; /* * The driver only supports the SMP configuartion where all processors -- cgit v0.10.2 From 43d864066fdb55fe6f914e07862d600d9c48e455 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:36 +0530 Subject: cpufreq: nforce2: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c index 56c964c..a05b876 100644 --- a/drivers/cpufreq/cpufreq-nforce2.c +++ b/drivers/cpufreq/cpufreq-nforce2.c @@ -360,7 +360,6 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy) policy->min = policy->cpuinfo.min_freq = min_fsb * fid * 100; policy->max = policy->cpuinfo.max_freq = max_fsb * fid * 100; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = nforce2_get(policy->cpu); return 0; } -- cgit v0.10.2 From 0a7485e19d7dded0c8cd2e309b5ff72b6e8ab3ce Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:37 +0530 Subject: cpufreq: cris: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Mikael Starvik Signed-off-by: Viresh Kumar Acked-by: Jesper Nilsson Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c index d26f4e4..4d88e4f 100644 --- a/drivers/cpufreq/cris-artpec3-cpufreq.c +++ b/drivers/cpufreq/cris-artpec3-cpufreq.c @@ -73,7 +73,6 @@ static int cris_freq_cpu_init(struct cpufreq_policy *policy) { /* cpuinfo and default policy values */ policy->cpuinfo.transition_latency = 1000000; /* 1ms */ - policy->cur = cris_freq_get_cpu_frequency(0); return cpufreq_table_validate_and_show(policy, cris_freq_table); } diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c index d384e63..f7d2d49 100644 --- a/drivers/cpufreq/cris-etraxfs-cpufreq.c +++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c @@ -72,7 +72,6 @@ static int cris_freq_cpu_init(struct cpufreq_policy *policy) { /* cpuinfo and default policy values */ policy->cpuinfo.transition_latency = 1000000; /* 1ms */ - policy->cur = cris_freq_get_cpu_frequency(0); return cpufreq_table_validate_and_show(policy, cris_freq_table); } -- cgit v0.10.2 From b31c95d72d40b5b0cac318d17c69c69582b55a98 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:38 +0530 Subject: cpufreq: davinci: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Sekhar Nori Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c index f228642..55cf094 100644 --- a/drivers/cpufreq/davinci-cpufreq.c +++ b/drivers/cpufreq/davinci-cpufreq.c @@ -136,8 +136,6 @@ static int davinci_cpu_init(struct cpufreq_policy *policy) return result; } - policy->cur = davinci_getspeed(0); - result = cpufreq_table_validate_and_show(policy, freq_table); if (result) { pr_err("%s: cpufreq_table_validate_and_show() failed", -- cgit v0.10.2 From ceb7682ee313e353ea34fec80727fe7f986f0be1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:39 +0530 Subject: cpufreq: dbx500: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c index 2d70637..ae1aa60 100644 --- a/drivers/cpufreq/dbx500-cpufreq.c +++ b/drivers/cpufreq/dbx500-cpufreq.c @@ -83,11 +83,6 @@ static int dbx500_cpufreq_init(struct cpufreq_policy *policy) return res; } - policy->min = policy->cpuinfo.min_freq; - policy->max = policy->cpuinfo.max_freq; - policy->cur = dbx500_cpufreq_getspeed(policy->cpu); - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - /* * FIXME : Need to take time measurement across the target() * function with no/some/all drivers in the notification -- cgit v0.10.2 From 18bb6de7c475f4a2299b35d7f34d72be10c71466 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:40 +0530 Subject: cpufreq: e_powersaver: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index a8cbbd0..2c11ce3 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -395,7 +395,6 @@ static int eps_cpu_init(struct cpufreq_policy *policy) } policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */ - policy->cur = fsb * current_multiplier; ret = cpufreq_table_validate_and_show(policy, ¢aur->freq_table[0]); if (ret) { -- cgit v0.10.2 From daaf2a46c5f77120ce3cb92fb548972ee5db74bc Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:41 +0530 Subject: cpufreq: elanfreq: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index fe7053c..d91a645 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c @@ -207,7 +207,6 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) /* cpuinfo and default policy values */ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = elanfreq_get_cpu_frequency(0); return cpufreq_table_validate_and_show(policy, elanfreq_table); } -- cgit v0.10.2 From 77fa10501861a141492a5cca6a62af14a7a5b2dc Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:42 +0530 Subject: cpufreq: exynos: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Acked-By: Amit Daniel Kachhap Acked-by: Kukjin Kim Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index 08338d4..5244086 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -241,8 +241,6 @@ static struct notifier_block exynos_cpufreq_nb = { static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) { - policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu); - /* set the transition latency value */ policy->cpuinfo.transition_latency = 100000; diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index bce6f74..9b7fdec 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -326,7 +326,6 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) return ret; } - policy->cur = dvfs_info->cur_frequency; policy->cpuinfo.transition_latency = dvfs_info->latency; cpumask_setall(policy->cpus); -- cgit v0.10.2 From cd59064372bef595709a85ae18fae159803aa791 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:43 +0530 Subject: cpufreq: gx: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c index 70442c7..d83e826 100644 --- a/drivers/cpufreq/gx-suspmod.c +++ b/drivers/cpufreq/gx-suspmod.c @@ -401,7 +401,7 @@ static int cpufreq_gx_target(struct cpufreq_policy *policy, static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy) { - unsigned int maxfreq, curfreq; + unsigned int maxfreq; if (!policy || policy->cpu != 0) return -ENODEV; @@ -415,10 +415,8 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy) maxfreq = 30000 * gx_freq_mult[getCx86(CX86_DIR1) & 0x0f]; stock_freq = maxfreq; - curfreq = gx_get_cpuspeed(0); pr_debug("cpu max frequency is %d.\n", maxfreq); - pr_debug("cpu current frequency is %dkHz.\n", curfreq); /* setup basic struct for cpufreq API */ policy->cpu = 0; @@ -428,7 +426,6 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy) else policy->min = maxfreq / POLICY_MIN_DIV; policy->max = maxfreq; - policy->cur = curfreq; policy->cpuinfo.min_freq = maxfreq / max_duration; policy->cpuinfo.max_freq = maxfreq; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; -- cgit v0.10.2 From 34a2548890ccccd9c9a3c7ad3d610ad133a6c04a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:44 +0530 Subject: cpufreq: ia64-acpi: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Tony Luck Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index b958bdb..90c6598 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -305,7 +305,6 @@ acpi_cpufreq_cpu_init ( data->acpi_data.states[i].transition_latency * 1000; } } - policy->cur = processor_get_freq(data, policy->cpu); /* table init */ for (i = 0; i <= data->acpi_data.state_count; i++) -- cgit v0.10.2 From 5e62178cb9088edc002c848912f8610b159d57a8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:45 +0530 Subject: cpufreq: imx6q: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Shawn Guo Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index d839657..9d22dfa 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -163,7 +163,6 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy) } policy->cpuinfo.transition_latency = transition_latency; - policy->cur = clk_get_rate(arm_clk) / 1000; cpumask_setall(policy->cpus); return 0; -- cgit v0.10.2 From ab537016e86467bd2b9a5d091e24ca563d0d7dc6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:46 +0530 Subject: cpufreq: integrator: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). And so we don't need to set policy->cur from driver anymore. Over that it sets policy->min and max correctly. They were earlier set to current frequency of CPU but they should be set to max and min freq of cpu. Cc: Russell King Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c index 8152a9b..babf3e4 100644 --- a/drivers/cpufreq/integrator-cpufreq.c +++ b/drivers/cpufreq/integrator-cpufreq.c @@ -181,10 +181,9 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy) { /* set default policy and cpuinfo */ - policy->cpuinfo.max_freq = 160000; - policy->cpuinfo.min_freq = 12000; + policy->max = policy->cpuinfo.max_freq = 160000; + policy->min = policy->cpuinfo.min_freq = 12000; policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */ - policy->cur = policy->min = policy->max = integrator_get(policy->cpu); return 0; } -- cgit v0.10.2 From 1cdf547790db07db200516ebd0d427e20eb37f69 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:47 +0530 Subject: cpufreq: kirkwood: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Tested-by: Andrew Lunn Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index 1a4e4f4..dc434c4 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -122,7 +122,6 @@ static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy) { /* cpuinfo and default policy values */ policy->cpuinfo.transition_latency = 5000; /* 5uS */ - policy->cur = kirkwood_cpufreq_get_cpu_frequency(0); return cpufreq_table_validate_and_show(policy, kirkwood_freq_table); } -- cgit v0.10.2 From b1123ea3c3e4874c03daaf8b742f2a12ada5d548 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:48 +0530 Subject: cpufreq: longhaul: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 57d7b02..14df497 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -913,7 +913,6 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) longhaul_setup_voltagescaling(); policy->cpuinfo.transition_latency = 200000; /* nsec */ - policy->cur = calc_speed(longhaul_get_cpu_mult()); return cpufreq_table_validate_and_show(policy, longhaul_table); } -- cgit v0.10.2 From adbed6e8473db90b18ef1cc3bf6f7f87e6cc46b7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:49 +0530 Subject: cpufreq: loongson2: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: John Crispin Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index ed7fbe2..dd4f3e4 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -131,8 +131,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) return ret; } - policy->cur = loongson2_cpufreq_get(policy->cpu); - return cpufreq_table_validate_and_show(policy, &loongson2_clockmod_table[0]); } -- cgit v0.10.2 From d31a4a9ae0d09a56154c7408406efd2ffbc23985 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:50 +0530 Subject: cpufreq: maple: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Dmitry Eremin-Solenikov Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c index b23d1d8..1c0cec1 100644 --- a/drivers/cpufreq/maple-cpufreq.c +++ b/drivers/cpufreq/maple-cpufreq.c @@ -166,7 +166,6 @@ static unsigned int maple_cpufreq_get_speed(unsigned int cpu) static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy) { policy->cpuinfo.transition_latency = 12000; - policy->cur = maple_cpu_freqs[maple_scom_query_freq()].frequency; /* secondary CPUs are tied to the primary one by the * cpufreq core if in the secondary policy we tell it that * it actually must be one policy together with all others. */ -- cgit v0.10.2 From 1857a25cd3f0827f413be3328490dc5dc56e0f10 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:51 +0530 Subject: cpufreq: omap: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Santosh Shilimkar Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 48020b5..a8c3f90 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -171,8 +171,6 @@ static int omap_cpu_init(struct cpufreq_policy *policy) goto fail_ck; } - policy->cur = omap_getspeed(policy->cpu); - if (!freq_table) result = opp_init_cpufreq_table(mpu_dev, &freq_table); @@ -188,8 +186,6 @@ static int omap_cpu_init(struct cpufreq_policy *policy) if (result) goto fail_table; - policy->cur = omap_getspeed(policy->cpu); - /* * On OMAP SMP configuartion, both processors share the voltage * and clock. So both CPUs needs to be scaled together and hence -- cgit v0.10.2 From c8fb6e9a906c97d86c9d7dda20e0141f952db678 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:52 +0530 Subject: cpufreq: p4: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: David S. Miller Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 4fe6d4c..6164c1c 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -230,7 +230,6 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) /* the transition latency is set to be 1 higher than the maximum * transition latency of the ondemand governor */ policy->cpuinfo.transition_latency = 10000001; - policy->cur = stock_freq; return cpufreq_table_validate_and_show(policy, &p4clockmod_table[0]); } -- cgit v0.10.2 From 6b67ca322d409003c29e119f8c8beeecd5785e20 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:53 +0530 Subject: cpufreq: pcc: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 78787e9..ef66347 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -559,13 +559,6 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy) ioread32(&pcch_hdr->nominal) * 1000; policy->min = policy->cpuinfo.min_freq = ioread32(&pcch_hdr->minimum_frequency) * 1000; - policy->cur = pcc_get_freq(cpu); - - if (!policy->cur) { - pr_debug("init: Unable to get current CPU frequency\n"); - result = -EINVAL; - goto out; - } pr_debug("init: policy->max is %d, policy->min is %d\n", policy->max, policy->min); -- cgit v0.10.2 From cb8bd497a61adea2ccb937e3181408fb95c78b52 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:54 +0530 Subject: cpufreq: pmac: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index 8715ab9..672b7f4 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -396,7 +396,6 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) return -ENODEV; policy->cpuinfo.transition_latency = transition_latency; - policy->cur = cur_freq; return cpufreq_table_validate_and_show(policy, pmac_cpu_freqs); } diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index e853b85..79e40c9 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -348,7 +348,6 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu) static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) { policy->cpuinfo.transition_latency = transition_latency; - policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; /* secondary CPUs are tied to the primary one by the * cpufreq core if in the secondary policy we tell it that * it actually must be one policy together with all others. */ -- cgit v0.10.2 From eaf8120e8f9c4efc71475b1e08b8e2d3e421e6ca Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:55 +0530 Subject: cpufreq: powernow: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index ff05d28..eda1702 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c @@ -151,7 +151,6 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) /* cpuinfo and default policy values */ policy->cpuinfo.transition_latency = 200000; - policy->cur = busfreq * max_multiplier; return cpufreq_table_validate_and_show(policy, clock_ratio); } diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index 14cd98f..44d345b 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -673,8 +673,6 @@ static int powernow_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency); - policy->cur = powernow_get(0); - return cpufreq_table_validate_and_show(policy, powernow_table); } diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 1e6f68a..298beb7 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1141,9 +1141,6 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) cpumask_copy(pol->cpus, cpu_core_mask(pol->cpu)); data->available_cores = pol->cpus; - pol->cur = find_khz_freq_from_fid(data->currfid); - pr_debug("policy current frequency %d kHz\n", pol->cur); - /* min/max the cpu is capable of */ if (cpufreq_table_validate_and_show(pol, data->powernow_table)) { printk(KERN_ERR FW_BUG PFX "invalid powernow_table\n"); -- cgit v0.10.2 From 0bcc9d9a3e680ebf7717f1aa8caeee45048ebae3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:56 +0530 Subject: cpufreq: ppc: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c index befd489..a0f562c 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/ppc-corenet-cpufreq.c @@ -217,8 +217,6 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) per_cpu(cpu_data, i) = data; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = corenet_cpufreq_get_speed(policy->cpu); - of_node_put(np); return 0; -- cgit v0.10.2 From 200ea8e2c28c1cca4f3faf1e15da78539ecaf835 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:57 +0530 Subject: cpufreq: pxa: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Eric Miao Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index 82905fe..29aca57 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -397,8 +397,6 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) /* set default policy and cpuinfo */ policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ - policy->cur = get_clk_frequency_khz(0); /* current freq */ - policy->min = policy->max = policy->cur; /* Generate pxa25x the run cpufreq_frequency_table struct */ for (i = 0; i < NUM_PXA25x_RUN_FREQS; i++) { diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c index ae3ac08..47fbee4 100644 --- a/drivers/cpufreq/pxa3xx-cpufreq.c +++ b/drivers/cpufreq/pxa3xx-cpufreq.c @@ -201,11 +201,10 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy) int ret = -EINVAL; /* set default policy and cpuinfo */ - policy->cpuinfo.min_freq = 104000; - policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000; + policy->min = policy->cpuinfo.min_freq = 104000; + policy->max = policy->cpuinfo.max_freq = + (cpu_is_pxa320()) ? 806000 : 624000; policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ - policy->max = pxa3xx_get_clk_frequency_khz(0); - policy->cur = policy->min = policy->max; if (cpu_is_pxa300() || cpu_is_pxa310()) ret = setup_freqs_table(policy, pxa300_freqs, -- cgit v0.10.2 From 0ecc402e0f1f8cc55000c75cb216615d0bee62a6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:58 +0530 Subject: cpufreq: s3c: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Kukjin Kim Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index 8c57f10..22c4c2d 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -476,8 +476,6 @@ static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) freq++; } - policy->cur = clk_get_rate(s3c_freq->armclk) / 1000; - /* Datasheet says PLL stabalisation time must be at least 300us, * so but add some fudge. (reference in LOCKCON0 register description) */ diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index 027dec1c..e0fbaef 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -378,11 +378,6 @@ static int s3c_cpufreq_init(struct cpufreq_policy *policy) if (policy->cpu != 0) return -EINVAL; - policy->cur = s3c_cpufreq_get(0); - policy->min = policy->cpuinfo.min_freq = 0; - policy->max = policy->cpuinfo.max_freq = cpu_cur.info->max.fclk / 1000; - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - /* feed the latency information from the cpu driver */ policy->cpuinfo.transition_latency = cpu_cur.info->latency; diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c index 99fbc49..a66cfa3 100644 --- a/drivers/cpufreq/s3c64xx-cpufreq.c +++ b/drivers/cpufreq/s3c64xx-cpufreq.c @@ -235,8 +235,6 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) freq++; } - policy->cur = clk_get_rate(armclk) / 1000; - /* Datasheet says PLL stabalisation time (if we were to use * the PLLs, which we don't currently) is ~300us worst case, * but add some fudge. -- cgit v0.10.2 From da9cbb9e284bde07ad4c0506aa4cb8ae6a6973f6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:28:59 +0530 Subject: cpufreq: s5pv210: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Kukjin Kim Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 0eafc52..30d9bb7 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -543,8 +543,6 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000); s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk); - policy->cur = policy->min = policy->max = s5pv210_getspeed(0); - policy->cpuinfo.transition_latency = 40000; return cpufreq_table_validate_and_show(policy, s5pv210_freq_table); -- cgit v0.10.2 From b256888fd0c3d5cd109798a0d32d47f665339695 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:00 +0530 Subject: cpufreq: sa11x0: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Russell King Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sa1100-cpufreq.c b/drivers/cpufreq/sa1100-cpufreq.c index 80a4fde..a1d1bb7 100644 --- a/drivers/cpufreq/sa1100-cpufreq.c +++ b/drivers/cpufreq/sa1100-cpufreq.c @@ -220,7 +220,6 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy) { if (policy->cpu != 0) return -EINVAL; - policy->cur = sa11x0_getspeed(0); policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; return cpufreq_table_validate_and_show(policy, sa11x0_freq_table); diff --git a/drivers/cpufreq/sa1110-cpufreq.c b/drivers/cpufreq/sa1110-cpufreq.c index a38d904..9da940e 100644 --- a/drivers/cpufreq/sa1110-cpufreq.c +++ b/drivers/cpufreq/sa1110-cpufreq.c @@ -334,7 +334,6 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy) { if (policy->cpu != 0) return -EINVAL; - policy->cur = sa11x0_getspeed(0); policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; return cpufreq_table_validate_and_show(policy, sa11x0_freq_table); -- cgit v0.10.2 From df38a23b7e51e9d8940714a39cf122966d55d882 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:01 +0530 Subject: cpufreq: sc520_freq: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index 8556225..9047ab1 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c @@ -109,7 +109,6 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy) /* cpuinfo and default policy values */ policy->cpuinfo.transition_latency = 1000000; /* 1ms */ - policy->cur = sc520_freq_get_cpu_frequency(0); return cpufreq_table_validate_and_show(policy, sc520_freq_table); } -- cgit v0.10.2 From 0ff12b6f487cbf01c47c551f8614f06c0dfd6a7a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:02 +0530 Subject: cpufreq: sh: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Paul Mundt Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c index c681b86..387af12 100644 --- a/drivers/cpufreq/sh-cpufreq.c +++ b/drivers/cpufreq/sh-cpufreq.c @@ -111,8 +111,6 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) return PTR_ERR(cpuclk); } - policy->cur = sh_cpufreq_get(cpu); - freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL; if (freq_table) { int result; -- cgit v0.10.2 From 1812136ec9adca227b185305b538a8a2065038d2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:03 +0530 Subject: cpufreq: spear: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index e9657e3..aacdb61 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -180,8 +180,6 @@ static int spear_cpufreq_init(struct cpufreq_policy *policy) } policy->cpuinfo.transition_latency = spear_cpufreq.transition_latency; - policy->cur = spear_cpufreq_get(0); - cpumask_setall(policy->cpus); return 0; -- cgit v0.10.2 From 4b15768325afe81057e3e71ae8b896d5ea657c30 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:04 +0530 Subject: cpufreq: speedstep: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: David S. Miller Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index c7c14ae..6b882c7 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -343,7 +343,6 @@ static unsigned int get_cur_freq(unsigned int cpu) static int centrino_cpu_init(struct cpufreq_policy *policy) { struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu); - unsigned freq; unsigned l, h; int i; @@ -394,12 +393,8 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) } } - freq = get_cur_freq(policy->cpu); policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */ - policy->cur = freq; - - pr_debug("centrino_cpu_init: cur=%dkHz\n", policy->cur); return cpufreq_table_validate_and_show(policy, per_cpu(centrino_model, policy->cpu)->op_points); diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index 929a4f0..1a8b01b 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -308,7 +308,7 @@ static void get_freqs_on_cpu(void *_get_freqs) static int speedstep_cpu_init(struct cpufreq_policy *policy) { - unsigned int policy_cpu, speed; + unsigned int policy_cpu; struct get_freqs gf; /* only run on CPU to be set, or on its sibling */ @@ -323,19 +323,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) if (gf.ret) return gf.ret; - /* get current speed setting */ - speed = speedstep_get(policy_cpu); - if (!speed) - return -EIO; - - pr_debug("currently at %s speed setting - %i MHz\n", - (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) - ? "low" : "high", - (speed / 1000)); - - /* cpuinfo and default policy values */ - policy->cur = speed; - return cpufreq_table_validate_and_show(policy, speedstep_freqs); } diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index b3dfba0..a02b649 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -267,7 +267,6 @@ static int speedstep_target(struct cpufreq_policy *policy, static int speedstep_cpu_init(struct cpufreq_policy *policy) { int result; - unsigned int speed, state; unsigned int *low, *high; /* capability check */ @@ -303,19 +302,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) pr_debug("workaround worked.\n"); } - /* get current speed setting */ - state = speedstep_get_state(); - speed = speedstep_freqs[state].frequency; - - pr_debug("currently at %s speed setting - %i MHz\n", - (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) - ? "low" : "high", - (speed / 1000)); - - /* cpuinfo and default policy values */ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = speed; - return cpufreq_table_validate_and_show(policy, speedstep_freqs); } -- cgit v0.10.2 From 21c895ce7172b21fed5f10e17b4b276962fa7f32 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:05 +0530 Subject: cpufreq: tegra: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Cc: Stephen Warren Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra-cpufreq.c index c36a8e7..9c32b23 100644 --- a/drivers/cpufreq/tegra-cpufreq.c +++ b/drivers/cpufreq/tegra-cpufreq.c @@ -211,8 +211,7 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) clk_prepare_enable(cpu_clk); cpufreq_table_validate_and_show(policy, freq_table); - policy->cur = tegra_getspeed(policy->cpu); - target_cpu_speed[policy->cpu] = policy->cur; + target_cpu_speed[policy->cpu] = tegra_getspeed(policy->cpu); /* FIXME: what's the actual transition time? */ policy->cpuinfo.transition_latency = 300 * 1000; -- cgit v0.10.2 From 9909aa1e3b69eb05201bdbd2b9bde00c50c1723a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:06 +0530 Subject: cpufreq: unicore2: don't initialize part of policy set by core Many common initializations of struct policy are moved to core now and hence this driver doesn't need to do it. This patch removes such code. Most recent of those changes is to call ->get() in the core after calling ->init(). Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/unicore2-cpufreq.c b/drivers/cpufreq/unicore2-cpufreq.c index 14e6d31..653ae29 100644 --- a/drivers/cpufreq/unicore2-cpufreq.c +++ b/drivers/cpufreq/unicore2-cpufreq.c @@ -66,7 +66,6 @@ static int __init ucv2_cpu_init(struct cpufreq_policy *policy) { if (policy->cpu != 0) return -EINVAL; - policy->cur = ucv2_getspeed(0); policy->min = policy->cpuinfo.min_freq = 250000; policy->max = policy->cpuinfo.max_freq = 1000000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; -- cgit v0.10.2 From 70e9e778337973d5bf57004092b360bd3f3c412f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:07 +0530 Subject: cpufreq: create cpufreq_generic_init() routine Many CPUFreq drivers for SMP system (where all cores share same clock lines), do similar stuff in their ->init() part. This patch creates a generic routine in cpufreq core which can be used by these so that we can remove some redundant code. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 534fcb8..2d06754 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -2,6 +2,7 @@ menu "CPU Frequency scaling" config CPU_FREQ bool "CPU Frequency scaling" + select CPU_FREQ_TABLE help CPU Frequency scaling allows you to change the clock speed of CPUs on the fly. This is a nice method to save power, because diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index f033adf..985f325 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -181,6 +181,37 @@ u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy) } EXPORT_SYMBOL_GPL(get_cpu_idle_time); +/* + * This is a generic cpufreq init() routine which can be used by cpufreq + * drivers of SMP systems. It will do following: + * - validate & show freq table passed + * - set policies transition latency + * - policy->cpus with all possible CPUs + */ +int cpufreq_generic_init(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table, + unsigned int transition_latency) +{ + int ret; + + ret = cpufreq_table_validate_and_show(policy, table); + if (ret) { + pr_err("%s: invalid frequency table: %d\n", __func__, ret); + return ret; + } + + policy->cpuinfo.transition_latency = transition_latency; + + /* + * The driver only supports the SMP configuartion where all processors + * share the clock and voltage and clock. + */ + cpumask_setall(policy->cpus); + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_generic_init); + struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) { struct cpufreq_policy *policy = NULL; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 36ccd0b..0aba2a6 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -424,6 +424,9 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu); int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table); +int cpufreq_generic_init(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table, + unsigned int transition_latency); static inline int cpufreq_generic_exit(struct cpufreq_policy *policy) { cpufreq_frequency_table_put_attr(policy->cpu); -- cgit v0.10.2 From 3bc28ab6da039f8020bbcea8e832b63a900bdb66 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:08 +0530 Subject: cpufreq: remove CONFIG_CPU_FREQ_TABLE CONFIG_CPU_FREQ_TABLE will be always enabled when cpufreq framework is used, as cpufreq core depends on it. So, we don't need this CONFIG option anymore as it is not configurable. Remove CONFIG_CPU_FREQ_TABLE and update its users. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index e026b19..a075b3e 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -40,7 +40,6 @@ config ARCH_DAVINCI_DA850 bool "DA850/OMAP-L138/AM18x based system" select ARCH_DAVINCI_DA8XX select ARCH_HAS_CPUFREQ - select CPU_FREQ_TABLE select CP_INTC config ARCH_DAVINCI_DA8XX diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index a842711..96100db 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -615,14 +615,12 @@ endmenu config PXA25x bool select CPU_XSCALE - select CPU_FREQ_TABLE if CPU_FREQ help Select code specific to PXA21x/25x/26x variants config PXA27x bool select CPU_XSCALE - select CPU_FREQ_TABLE if CPU_FREQ help Select code specific to PXA27x variants @@ -635,7 +633,6 @@ config CPU_PXA26x config PXA3xx bool select CPU_XSC3 - select CPU_FREQ_TABLE if CPU_FREQ help Select code specific to PXA3xx variants diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 99a28d6..7a3fc1a 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -34,7 +34,6 @@ config UX500_SOC_COMMON config UX500_SOC_DB8500 bool - select CPU_FREQ_TABLE if CPU_FREQ select MFD_DB8500_PRCMU select PINCTRL_DB8500 select PINCTRL_DB8540 diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index f78c9a2..eb382ae 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -1429,7 +1429,6 @@ source "drivers/cpufreq/Kconfig" config BFIN_CPU_FREQ bool depends on CPU_FREQ - select CPU_FREQ_TABLE default y config CPU_VOLTAGE diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index 02380be..9c957c8 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -130,13 +130,11 @@ config SVINTO_SIM config ETRAXFS bool "ETRAX-FS-V32" - select CPU_FREQ_TABLE if CPU_FREQ help Support CRIS V32. config CRIS_MACH_ARTPEC3 bool "ARTPEC-3" - select CPU_FREQ_TABLE if CPU_FREQ help Support Axis ARTPEC-3. diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 2d06754..38093e2 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -2,7 +2,6 @@ menu "CPU Frequency scaling" config CPU_FREQ bool "CPU Frequency scaling" - select CPU_FREQ_TABLE help CPU Frequency scaling allows you to change the clock speed of CPUs on the fly. This is a nice method to save power, because @@ -18,15 +17,11 @@ config CPU_FREQ if CPU_FREQ -config CPU_FREQ_TABLE - tristate - config CPU_FREQ_GOV_COMMON bool config CPU_FREQ_STAT tristate "CPU frequency translation statistics" - select CPU_FREQ_TABLE default y help This driver exports CPU frequency statistics information through sysfs @@ -144,7 +139,6 @@ config CPU_FREQ_GOV_USERSPACE config CPU_FREQ_GOV_ONDEMAND tristate "'ondemand' cpufreq policy governor" - select CPU_FREQ_TABLE select CPU_FREQ_GOV_COMMON help 'ondemand' - This driver adds a dynamic cpufreq policy governor. @@ -188,7 +182,6 @@ config CPU_FREQ_GOV_CONSERVATIVE config GENERIC_CPUFREQ_CPU0 tristate "Generic CPU0 cpufreq driver" depends on HAVE_CLK && REGULATOR && PM_OPP && OF - select CPU_FREQ_TABLE help This adds a generic cpufreq driver for CPU0 frequency management. It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) @@ -224,7 +217,6 @@ depends on IA64 config IA64_ACPI_CPUFREQ tristate "ACPI Processor P-States driver" - select CPU_FREQ_TABLE depends on ACPI_PROCESSOR help This driver adds a CPUFreq driver which utilizes the ACPI @@ -241,7 +233,6 @@ depends on MIPS config LOONGSON2_CPUFREQ tristate "Loongson2 CPUFreq Driver" - select CPU_FREQ_TABLE help This option adds a CPUFreq driver for loongson processors which support software configurable cpu frequency. @@ -263,7 +254,6 @@ menu "SPARC CPU frequency scaling drivers" depends on SPARC64 config SPARC_US3_CPUFREQ tristate "UltraSPARC-III CPU Frequency driver" - select CPU_FREQ_TABLE help This adds the CPUFreq driver for UltraSPARC-III processors. @@ -273,7 +263,6 @@ config SPARC_US3_CPUFREQ config SPARC_US2E_CPUFREQ tristate "UltraSPARC-IIe CPU Frequency driver" - select CPU_FREQ_TABLE help This adds the CPUFreq driver for UltraSPARC-IIe processors. @@ -286,7 +275,6 @@ menu "SH CPU Frequency scaling" depends on SUPERH config SH_CPU_FREQ tristate "SuperH CPU Frequency driver" - select CPU_FREQ_TABLE help This adds the cpufreq driver for SuperH. Any CPU that supports clock rate rounding through the clock framework can use this diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 0fa204b..701ec95 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -5,7 +5,6 @@ config ARM_BIG_LITTLE_CPUFREQ tristate "Generic ARM big LITTLE CPUfreq driver" depends on ARM_CPU_TOPOLOGY && PM_OPP && HAVE_CLK - select CPU_FREQ_TABLE help This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. @@ -18,7 +17,6 @@ config ARM_DT_BL_CPUFREQ config ARM_EXYNOS_CPUFREQ bool - select CPU_FREQ_TABLE config ARM_EXYNOS4210_CPUFREQ bool "SAMSUNG EXYNOS4210" @@ -58,7 +56,6 @@ config ARM_EXYNOS5440_CPUFREQ depends on SOC_EXYNOS5440 depends on HAVE_CLK && PM_OPP && OF default y - select CPU_FREQ_TABLE help This adds the CPUFreq driver for Samsung EXYNOS5440 SoC. The nature of exynos5440 clock controller is @@ -85,7 +82,6 @@ config ARM_IMX6Q_CPUFREQ tristate "Freescale i.MX6Q cpufreq support" depends on SOC_IMX6Q depends on REGULATOR_ANATOP - select CPU_FREQ_TABLE help This adds cpufreq driver support for Freescale i.MX6Q SOC. @@ -101,7 +97,6 @@ config ARM_INTEGRATOR config ARM_KIRKWOOD_CPUFREQ def_bool ARCH_KIRKWOOD && OF - select CPU_FREQ_TABLE help This adds the CPUFreq driver for Marvell Kirkwood SoCs. @@ -110,7 +105,6 @@ config ARM_OMAP2PLUS_CPUFREQ bool "TI OMAP2+" depends on ARCH_OMAP2PLUS default ARCH_OMAP2PLUS - select CPU_FREQ_TABLE config ARM_S3C_CPUFREQ bool @@ -165,7 +159,6 @@ config ARM_S3C2412_CPUFREQ config ARM_S3C2416_CPUFREQ bool "S3C2416 CPU Frequency scaling support" depends on CPU_S3C2416 - select CPU_FREQ_TABLE help This adds the CPUFreq driver for the Samsung S3C2416 and S3C2450 SoC. The S3C2416 supports changing the rate of the @@ -196,7 +189,6 @@ config ARM_S3C2440_CPUFREQ config ARM_S3C64XX_CPUFREQ bool "Samsung S3C64XX" depends on CPU_S3C6410 - select CPU_FREQ_TABLE default y help This adds the CPUFreq driver for Samsung S3C6410 SoC. @@ -206,7 +198,6 @@ config ARM_S3C64XX_CPUFREQ config ARM_S5PV210_CPUFREQ bool "Samsung S5PV210 and S5PC110" depends on CPU_S5PV210 - select CPU_FREQ_TABLE default y help This adds the CPUFreq driver for Samsung S5PV210 and @@ -223,7 +214,6 @@ config ARM_SA1110_CPUFREQ config ARM_SPEAR_CPUFREQ bool "SPEAr CPUFreq support" depends on PLAT_SPEAR - select CPU_FREQ_TABLE default y help This adds the CPUFreq driver support for SPEAr SOCs. @@ -231,7 +221,6 @@ config ARM_SPEAR_CPUFREQ config ARM_TEGRA_CPUFREQ bool "TEGRA CPUFreq support" depends on ARCH_TEGRA - select CPU_FREQ_TABLE default y help This adds the CPUFreq driver support for TEGRA SOCs. diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc index 25ca9db..ca0021a 100644 --- a/drivers/cpufreq/Kconfig.powerpc +++ b/drivers/cpufreq/Kconfig.powerpc @@ -1,7 +1,6 @@ config CPU_FREQ_CBE tristate "CBE frequency scaling" depends on CBE_RAS && PPC_CELL - select CPU_FREQ_TABLE default m help This adds the cpufreq driver for Cell BE processors. @@ -20,7 +19,6 @@ config CPU_FREQ_CBE_PMI config CPU_FREQ_MAPLE bool "Support for Maple 970FX Evaluation Board" depends on PPC_MAPLE - select CPU_FREQ_TABLE help This adds support for frequency switching on Maple 970FX Evaluation Board and compatible boards (IBM JS2x blades). @@ -28,7 +26,6 @@ config CPU_FREQ_MAPLE config PPC_CORENET_CPUFREQ tristate "CPU frequency scaling driver for Freescale E500MC SoCs" depends on PPC_E500MC && OF && COMMON_CLK - select CPU_FREQ_TABLE select CLK_PPC_CORENET help This adds the CPUFreq driver support for Freescale e500mc, @@ -38,7 +35,6 @@ config PPC_CORENET_CPUFREQ config CPU_FREQ_PMAC bool "Support for Apple PowerBooks" depends on ADB_PMU && PPC32 - select CPU_FREQ_TABLE help This adds support for frequency switching on Apple PowerBooks, this currently includes some models of iBook & Titanium @@ -47,7 +43,6 @@ config CPU_FREQ_PMAC config CPU_FREQ_PMAC64 bool "Support for some Apple G5s" depends on PPC_PMAC && PPC64 - select CPU_FREQ_TABLE help This adds support for frequency switching on Apple iMac G5, and some of the more recent desktop G5 machines as well. @@ -55,7 +50,6 @@ config CPU_FREQ_PMAC64 config PPC_PASEMI_CPUFREQ bool "Support for PA Semi PWRficient" depends on PPC_PASEMI - select CPU_FREQ_TABLE default y help This adds the support for frequency switching on PA Semi diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index e2b6eab..6897ad8 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 @@ -31,7 +31,6 @@ config X86_PCC_CPUFREQ config X86_ACPI_CPUFREQ tristate "ACPI Processor P-States driver" - select CPU_FREQ_TABLE depends on ACPI_PROCESSOR help This driver adds a CPUFreq driver which utilizes the ACPI @@ -60,7 +59,6 @@ config X86_ACPI_CPUFREQ_CPB config ELAN_CPUFREQ tristate "AMD Elan SC400 and SC410" - select CPU_FREQ_TABLE depends on MELAN ---help--- This adds the CPUFreq driver for AMD Elan SC400 and SC410 @@ -76,7 +74,6 @@ config ELAN_CPUFREQ config SC520_CPUFREQ tristate "AMD Elan SC520" - select CPU_FREQ_TABLE depends on MELAN ---help--- This adds the CPUFreq driver for AMD Elan SC520 processor. @@ -88,7 +85,6 @@ config SC520_CPUFREQ config X86_POWERNOW_K6 tristate "AMD Mobile K6-2/K6-3 PowerNow!" - select CPU_FREQ_TABLE depends on X86_32 help This adds the CPUFreq driver for mobile AMD K6-2+ and mobile @@ -100,7 +96,6 @@ config X86_POWERNOW_K6 config X86_POWERNOW_K7 tristate "AMD Mobile Athlon/Duron PowerNow!" - select CPU_FREQ_TABLE depends on X86_32 help This adds the CPUFreq driver for mobile AMD K7 mobile processors. @@ -118,7 +113,6 @@ config X86_POWERNOW_K7_ACPI config X86_POWERNOW_K8 tristate "AMD Opteron/Athlon64 PowerNow!" - select CPU_FREQ_TABLE depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ help This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors. @@ -132,7 +126,6 @@ config X86_POWERNOW_K8 config X86_AMD_FREQ_SENSITIVITY tristate "AMD frequency sensitivity feedback powersave bias" depends on CPU_FREQ_GOV_ONDEMAND && X86_ACPI_CPUFREQ && CPU_SUP_AMD - select CPU_FREQ_TABLE help This adds AMD-specific powersave bias function to the ondemand governor, which allows it to make more power-conscious frequency @@ -160,7 +153,6 @@ config X86_GX_SUSPMOD config X86_SPEEDSTEP_CENTRINO tristate "Intel Enhanced SpeedStep (deprecated)" - select CPU_FREQ_TABLE select X86_SPEEDSTEP_CENTRINO_TABLE if X86_32 depends on X86_32 || (X86_64 && ACPI_PROCESSOR) help @@ -190,7 +182,6 @@ config X86_SPEEDSTEP_CENTRINO_TABLE config X86_SPEEDSTEP_ICH tristate "Intel Speedstep on ICH-M chipsets (ioport interface)" - select CPU_FREQ_TABLE depends on X86_32 help This adds the CPUFreq driver for certain mobile Intel Pentium III @@ -204,7 +195,6 @@ config X86_SPEEDSTEP_ICH config X86_SPEEDSTEP_SMI tristate "Intel SpeedStep on 440BX/ZX/MX chipsets (SMI interface)" - select CPU_FREQ_TABLE depends on X86_32 help This adds the CPUFreq driver for certain mobile Intel Pentium III @@ -217,7 +207,6 @@ config X86_SPEEDSTEP_SMI config X86_P4_CLOCKMOD tristate "Intel Pentium 4 clock modulation" - select CPU_FREQ_TABLE help This adds the CPUFreq driver for Intel Pentium 4 / XEON processors. When enabled it will lower CPU temperature by skipping @@ -259,7 +248,6 @@ config X86_LONGRUN config X86_LONGHAUL tristate "VIA Cyrix III Longhaul" - select CPU_FREQ_TABLE depends on X86_32 && ACPI_PROCESSOR help This adds the CPUFreq driver for VIA Samuel/CyrixIII, @@ -272,7 +260,6 @@ config X86_LONGHAUL config X86_E_POWERSAVER tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)" - select CPU_FREQ_TABLE depends on X86_32 && ACPI_PROCESSOR help This adds the CPUFreq driver for VIA C7 processors. However, this driver diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index ad5866c..b7948bb 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -1,5 +1,5 @@ # CPUfreq core -obj-$(CONFIG_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_CPU_FREQ) += cpufreq.o freq_table.o # CPUfreq stats obj-$(CONFIG_CPU_FREQ_STAT) += cpufreq_stats.o @@ -11,9 +11,6 @@ obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o -# CPUfreq cross-arch helpers -obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o - obj-$(CONFIG_GENERIC_CPUFREQ_CPU0) += cpufreq-cpu0.o ################################################################################## diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 985f325..f0897c7 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -986,9 +986,7 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) up_write(&per_cpu(cpu_policy_rwsem, policy->last_cpu)); -#ifdef CONFIG_CPU_FREQ_TABLE cpufreq_frequency_table_update_policy_cpu(policy); -#endif blocking_notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_UPDATE_POLICY_CPU, policy); } diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index dbfc390..5ef5967 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -78,7 +78,6 @@ config THERMAL_GOV_USER_SPACE config CPU_THERMAL bool "generic cpu cooling support" depends on CPU_FREQ - select CPU_FREQ_TABLE help This implements the generic cpu cooling mechanism through frequency reduction. An ACPI version of this already exists -- cgit v0.10.2 From 78b3d1093626f8536a089b0490127b47131bd327 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:09 +0530 Subject: cpufreq: cpufreq-cpu0: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Cc: Shawn Guo Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 3c09a26..582888d 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -122,24 +122,7 @@ post_notify: static int cpu0_cpufreq_init(struct cpufreq_policy *policy) { - int ret; - - ret = cpufreq_table_validate_and_show(policy, freq_table); - if (ret) { - pr_err("invalid frequency table: %d\n", ret); - return ret; - } - - policy->cpuinfo.transition_latency = transition_latency; - - /* - * The driver only supports the SMP configuartion where all processors - * share the clock and voltage and clock. Use cpufreq affected_cpus - * interface to have all CPUs scaled together. - */ - cpumask_setall(policy->cpus); - - return 0; + return cpufreq_generic_init(policy, freq_table, transition_latency); } static struct cpufreq_driver cpu0_cpufreq_driver = { -- cgit v0.10.2 From 1870e11193925c87f9b3a647ef26531277530136 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:10 +0530 Subject: cpufreq: cris: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Cc: Mikael Starvik Signed-off-by: Viresh Kumar Acked-by: Jesper Nilsson Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c index 4d88e4f..05fdc7e 100644 --- a/drivers/cpufreq/cris-artpec3-cpufreq.c +++ b/drivers/cpufreq/cris-artpec3-cpufreq.c @@ -71,13 +71,9 @@ static int cris_freq_target(struct cpufreq_policy *policy, static int cris_freq_cpu_init(struct cpufreq_policy *policy) { - /* cpuinfo and default policy values */ - policy->cpuinfo.transition_latency = 1000000; /* 1ms */ - - return cpufreq_table_validate_and_show(policy, cris_freq_table); + return cpufreq_generic_init(policy, cris_freq_table, 1000000); } - static struct cpufreq_driver cris_freq_driver = { .get = cris_freq_get_cpu_frequency, .verify = cpufreq_generic_frequency_table_verify, diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c index f7d2d49..fac2b26 100644 --- a/drivers/cpufreq/cris-etraxfs-cpufreq.c +++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c @@ -70,10 +70,7 @@ static int cris_freq_target(struct cpufreq_policy *policy, static int cris_freq_cpu_init(struct cpufreq_policy *policy) { - /* cpuinfo and default policy values */ - policy->cpuinfo.transition_latency = 1000000; /* 1ms */ - - return cpufreq_table_validate_and_show(policy, cris_freq_table); + return cpufreq_generic_init(policy, cris_freq_table, 1000000); } static struct cpufreq_driver cris_freq_driver = { -- cgit v0.10.2 From af8c4cfabea88b441282dff26ef08d52a90d653c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:11 +0530 Subject: cpufreq: davinci: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Cc: Sekhar Nori Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c index 55cf094..972583b 100644 --- a/drivers/cpufreq/davinci-cpufreq.c +++ b/drivers/cpufreq/davinci-cpufreq.c @@ -136,21 +136,13 @@ static int davinci_cpu_init(struct cpufreq_policy *policy) return result; } - result = cpufreq_table_validate_and_show(policy, freq_table); - if (result) { - pr_err("%s: cpufreq_table_validate_and_show() failed", - __func__); - return result; - } - /* * Time measurement across the target() function yields ~1500-1800us * time taken with no drivers on notification list. * Setting the latency to 2000 us to accommodate addition of drivers * to pre/post change notification list. */ - policy->cpuinfo.transition_latency = 2000 * 1000; - return 0; + return cpufreq_generic_init(policy, freq_table, 2000 * 1000); } static struct cpufreq_driver davinci_driver = { -- cgit v0.10.2 From 2b3dc761cf2cfaf773ebec5c169494c4a670a419 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:12 +0530 Subject: cpufreq: dbx500: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Acked-by: Linus Walleij Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c index ae1aa60..a60f769 100644 --- a/drivers/cpufreq/dbx500-cpufreq.c +++ b/drivers/cpufreq/dbx500-cpufreq.c @@ -74,26 +74,7 @@ static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu) static int dbx500_cpufreq_init(struct cpufreq_policy *policy) { - int res; - - /* get policy fields based on the table */ - res = cpufreq_table_validate_and_show(policy, freq_table); - if (res) { - pr_err("dbx500-cpufreq: Failed to read policy table\n"); - return res; - } - - /* - * FIXME : Need to take time measurement across the target() - * function with no/some/all drivers in the notification - * list. - */ - policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */ - - /* policy sharing between dual CPUs */ - cpumask_setall(policy->cpus); - - return 0; + return cpufreq_generic_init(policy, freq_table, 20 * 1000); } static struct cpufreq_driver dbx500_cpufreq_driver = { -- cgit v0.10.2 From b249abaebfc2ce5cfac4cdb454a64ce6273aba2a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:13 +0530 Subject: cpufreq: exynos: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index 5244086..b96fcc8 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -241,12 +241,7 @@ static struct notifier_block exynos_cpufreq_nb = { static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) { - /* set the transition latency value */ - policy->cpuinfo.transition_latency = 100000; - - cpumask_setall(policy->cpus); - - return cpufreq_table_validate_and_show(policy, exynos_info->freq_table); + return cpufreq_generic_init(policy, exynos_info->freq_table, 100000); } static struct cpufreq_driver exynos_driver = { diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index 9b7fdec..06b73e8 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -318,18 +318,8 @@ static void exynos_sort_descend_freq_table(void) static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) { - int ret; - - ret = cpufreq_table_validate_and_show(policy, dvfs_info->freq_table); - if (ret) { - dev_err(dvfs_info->dev, "Invalid frequency table: %d\n", ret); - return ret; - } - - policy->cpuinfo.transition_latency = dvfs_info->latency; - cpumask_setall(policy->cpus); - - return 0; + return cpufreq_generic_init(policy, dvfs_info->freq_table, + dvfs_info->latency); } static struct cpufreq_driver exynos_driver = { -- cgit v0.10.2 From 17922ddd8eeb0d6474fbeb32a5366bb82d4273fa Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:14 +0530 Subject: cpufreq: imx6q: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 9d22dfa..d81062f 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -154,18 +154,7 @@ post_notify: static int imx6q_cpufreq_init(struct cpufreq_policy *policy) { - int ret; - - ret = cpufreq_table_validate_and_show(policy, freq_table); - if (ret) { - dev_err(cpu_dev, "invalid frequency table: %d\n", ret); - return ret; - } - - policy->cpuinfo.transition_latency = transition_latency; - cpumask_setall(policy->cpus); - - return 0; + return cpufreq_generic_init(policy, freq_table, transition_latency); } static struct cpufreq_driver imx6q_cpufreq_driver = { -- cgit v0.10.2 From fa6fa663b61929fbd9a83765aaa1996d65246167 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:15 +0530 Subject: cpufreq: kirkwood: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index dc434c4..fff8653 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -120,10 +120,7 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy, /* Module init and exit code */ static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy) { - /* cpuinfo and default policy values */ - policy->cpuinfo.transition_latency = 5000; /* 5uS */ - - return cpufreq_table_validate_and_show(policy, kirkwood_freq_table); + return cpufreq_generic_init(policy, kirkwood_freq_table, 5000); } static struct cpufreq_driver kirkwood_cpufreq_driver = { -- cgit v0.10.2 From e0b2da585f286ffa86cd24c0df1c1440d9dae19f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:16 +0530 Subject: cpufreq: loongson2: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. This driver wasn't setting transition_latency and so is getting set to 0 by default. Lets mark it explicitly by calling the generic routine with transition_latency as 0. Signed-off-by: Viresh Kumar Acked-by: Aaro Koskinen Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index dd4f3e4..2c8ec8e 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -131,8 +131,7 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) return ret; } - return cpufreq_table_validate_and_show(policy, - &loongson2_clockmod_table[0]); + return cpufreq_generic_init(policy, &loongson2_clockmod_table[0], 0); } static int loongson2_cpufreq_exit(struct cpufreq_policy *policy) -- cgit v0.10.2 From 7bfd24835697376bebb6f4dd88fa7ebc42937f99 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:17 +0530 Subject: cpufreq: maple: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c index 1c0cec1..eb1e176 100644 --- a/drivers/cpufreq/maple-cpufreq.c +++ b/drivers/cpufreq/maple-cpufreq.c @@ -165,16 +165,9 @@ static unsigned int maple_cpufreq_get_speed(unsigned int cpu) static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy) { - policy->cpuinfo.transition_latency = 12000; - /* secondary CPUs are tied to the primary one by the - * cpufreq core if in the secondary policy we tell it that - * it actually must be one policy together with all others. */ - cpumask_setall(policy->cpus); - - return cpufreq_table_validate_and_show(policy, maple_cpu_freqs); + return cpufreq_generic_init(policy, maple_cpu_freqs, 12000); } - static struct cpufreq_driver maple_cpufreq_driver = { .name = "maple", .flags = CPUFREQ_CONST_LOOPS, -- cgit v0.10.2 From 982bce112f48e588bdf8b588dc57c1755fe58805 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:18 +0530 Subject: cpufreq: omap: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. This also rearranges the code a bit to make it more sensible. Also removes some unnecessary checks. Cc: Santosh Shilimkar Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index a8c3f90..58b2200 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -160,50 +160,31 @@ static inline void freq_table_free(void) static int omap_cpu_init(struct cpufreq_policy *policy) { - int result = 0; + int result; mpu_clk = clk_get(NULL, "cpufreq_ck"); if (IS_ERR(mpu_clk)) return PTR_ERR(mpu_clk); - if (policy->cpu >= NR_CPUS) { - result = -EINVAL; - goto fail_ck; - } - - if (!freq_table) + if (!freq_table) { result = opp_init_cpufreq_table(mpu_dev, &freq_table); - - if (result) { - dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n", + if (result) { + dev_err(mpu_dev, + "%s: cpu%d: failed creating freq table[%d]\n", __func__, policy->cpu, result); - goto fail_ck; + goto fail; + } } atomic_inc_return(&freq_table_users); - result = cpufreq_table_validate_and_show(policy, freq_table); - if (result) - goto fail_table; - - /* - * On OMAP SMP configuartion, both processors share the voltage - * and clock. So both CPUs needs to be scaled together and hence - * needs software co-ordination. Use cpufreq affected_cpus - * interface to handle this scenario. Additional is_smp() check - * is to keep SMP_ON_UP build working. - */ - if (is_smp()) - cpumask_setall(policy->cpus); - /* FIXME: what's the actual transition time? */ - policy->cpuinfo.transition_latency = 300 * 1000; - - return 0; + result = cpufreq_generic_init(policy, freq_table, 300 * 1000); + if (!result) + return 0; -fail_table: freq_table_free(); -fail_ck: +fail: clk_put(mpu_clk); return result; } -- cgit v0.10.2 From e315bb738c618d5a60073ba885c586a874f8deda Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:19 +0530 Subject: cpufreq: pasemi: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index 16f2508..1cca332 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c @@ -204,20 +204,13 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) pr_debug("%d: %d\n", i, pas_freqs[i].frequency); } - policy->cpuinfo.transition_latency = get_gizmo_latency(); - cur_astate = get_cur_astate(policy->cpu); pr_debug("current astate is at %d\n",cur_astate); policy->cur = pas_freqs[cur_astate].frequency; - cpumask_copy(policy->cpus, cpu_online_mask); - ppc_proc_freq = policy->cur * 1000ul; - /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max - * are set correctly - */ - return cpufreq_table_validate_and_show(policy, pas_freqs); + return cpufreq_generic_init(policy, pas_freqs, get_gizmo_latency()); out_unmap_sdcpwr: iounmap(sdcpwr_mapbase); -- cgit v0.10.2 From 5465e7be76cc75c7dcb08801fa5b7add28d8d3a9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:20 +0530 Subject: cpufreq: pmac32: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Cc: Benjamin Herrenschmidt Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index 672b7f4..6eac1e2 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -392,12 +392,7 @@ static int pmac_cpufreq_target( struct cpufreq_policy *policy, static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) { - if (policy->cpu != 0) - return -ENODEV; - - policy->cpuinfo.transition_latency = transition_latency; - - return cpufreq_table_validate_and_show(policy, pmac_cpu_freqs); + return cpufreq_generic_init(policy, pmac_cpu_freqs, transition_latency); } static u32 read_gpio(struct device_node *np) -- cgit v0.10.2 From 8ce6f9de9785857669d39e061c9d2e87d1c516d7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:21 +0530 Subject: cpufreq: pmac64: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 79e40c9..b977b9a 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -347,16 +347,9 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu) static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) { - policy->cpuinfo.transition_latency = transition_latency; - /* secondary CPUs are tied to the primary one by the - * cpufreq core if in the secondary policy we tell it that - * it actually must be one policy together with all others. */ - cpumask_copy(policy->cpus, cpu_online_mask); - - return cpufreq_table_validate_and_show(policy, g5_cpu_freqs); + return cpufreq_generic_init(policy, g5_cpu_freqs, transition_latency); } - static struct cpufreq_driver g5_cpufreq_driver = { .name = "powermac", .flags = CPUFREQ_CONST_LOOPS, -- cgit v0.10.2 From a307a1e6bc0da1ea1e5960fb386b2bbc3587e808 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:22 +0530 Subject: cpufreq: s3c: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index 22c4c2d..26a35d1 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -479,10 +479,8 @@ static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) /* Datasheet says PLL stabalisation time must be at least 300us, * so but add some fudge. (reference in LOCKCON0 register description) */ - policy->cpuinfo.transition_latency = (500 * 1000) + - s3c_freq->regulator_latency; - - ret = cpufreq_table_validate_and_show(policy, s3c_freq->freq_table); + ret = cpufreq_generic_init(policy, s3c_freq->freq_table, + (500 * 1000) + s3c_freq->regulator_latency); if (ret) goto err_freq_table; diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index e0fbaef..4850882 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -373,18 +373,7 @@ struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name) static int s3c_cpufreq_init(struct cpufreq_policy *policy) { - printk(KERN_INFO "%s: initialising policy %p\n", __func__, policy); - - if (policy->cpu != 0) - return -EINVAL; - - /* feed the latency information from the cpu driver */ - policy->cpuinfo.transition_latency = cpu_cur.info->latency; - - if (ftab) - return cpufreq_table_validate_and_show(policy, ftab); - - return 0; + return cpufreq_generic_init(policy, ftab, cpu_cur.info->latency); } static int __init s3c_cpufreq_initclks(void) diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c index a66cfa3..16dc315 100644 --- a/drivers/cpufreq/s3c64xx-cpufreq.c +++ b/drivers/cpufreq/s3c64xx-cpufreq.c @@ -239,9 +239,8 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) * the PLLs, which we don't currently) is ~300us worst case, * but add some fudge. */ - policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency; - - ret = cpufreq_table_validate_and_show(policy, s3c64xx_freq_table); + ret = cpufreq_generic_init(policy, s3c64xx_freq_table, + (500 * 1000) + regulator_latency); if (ret != 0) { pr_err("Failed to configure frequency table: %d\n", ret); -- cgit v0.10.2 From c3d7d87d7f6fc35f1a97b628229e06bb0dffa0bf Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:29:23 +0530 Subject: cpufreq: s5pv210: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 30d9bb7..600b4f4 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -543,9 +543,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000); s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk); - policy->cpuinfo.transition_latency = 40000; - - return cpufreq_table_validate_and_show(policy, s5pv210_freq_table); + return cpufreq_generic_init(policy, s5pv210_freq_table, 40000); out_dmc1: clk_put(dmc0_clk); -- cgit v0.10.2 From 9b30367bbf3353a7dfc34ed800b7ff03cb35252b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:42:09 +0530 Subject: cpufreq: sa11x0: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/sa1100-cpufreq.c b/drivers/cpufreq/sa1100-cpufreq.c index a1d1bb7..b282cea 100644 --- a/drivers/cpufreq/sa1100-cpufreq.c +++ b/drivers/cpufreq/sa1100-cpufreq.c @@ -218,11 +218,7 @@ static int sa1100_target(struct cpufreq_policy *policy, static int __init sa1100_cpu_init(struct cpufreq_policy *policy) { - if (policy->cpu != 0) - return -EINVAL; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - - return cpufreq_table_validate_and_show(policy, sa11x0_freq_table); + return cpufreq_generic_init(policy, sa11x0_freq_table, CPUFREQ_ETERNAL); } static struct cpufreq_driver sa1100_driver __refdata = { diff --git a/drivers/cpufreq/sa1110-cpufreq.c b/drivers/cpufreq/sa1110-cpufreq.c index 9da940e..bca04c0 100644 --- a/drivers/cpufreq/sa1110-cpufreq.c +++ b/drivers/cpufreq/sa1110-cpufreq.c @@ -332,11 +332,7 @@ static int sa1110_target(struct cpufreq_policy *policy, static int __init sa1110_cpu_init(struct cpufreq_policy *policy) { - if (policy->cpu != 0) - return -EINVAL; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - - return cpufreq_table_validate_and_show(policy, sa11x0_freq_table); + return cpufreq_generic_init(policy, sa11x0_freq_table, CPUFREQ_ETERNAL); } /* sa1110_driver needs __refdata because it must remain after init registers -- cgit v0.10.2 From 7a936bd085372842fd1c9397a80b74e62026c89e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:42:10 +0530 Subject: cpufreq: spear: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index aacdb61..2a03158 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -171,18 +171,8 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy, static int spear_cpufreq_init(struct cpufreq_policy *policy) { - int ret; - - ret = cpufreq_table_validate_and_show(policy, spear_cpufreq.freq_tbl); - if (ret) { - pr_err("cpufreq_table_validate_and_show() failed"); - return ret; - } - - policy->cpuinfo.transition_latency = spear_cpufreq.transition_latency; - cpumask_setall(policy->cpus); - - return 0; + return cpufreq_generic_init(policy, spear_cpufreq.freq_tbl, + spear_cpufreq.transition_latency); } static struct cpufreq_driver spear_cpufreq_driver = { -- cgit v0.10.2 From 99d428cf0bcdbbbdeb622c338cd5ab72189e8d22 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 20:42:11 +0530 Subject: cpufreq: tegra: use cpufreq_generic_init() Use generic cpufreq_generic_init() routine instead of replicating the same code here. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra-cpufreq.c index 9c32b23..32483ef 100644 --- a/drivers/cpufreq/tegra-cpufreq.c +++ b/drivers/cpufreq/tegra-cpufreq.c @@ -204,19 +204,23 @@ static struct notifier_block tegra_cpu_pm_notifier = { static int tegra_cpu_init(struct cpufreq_policy *policy) { + int ret; + if (policy->cpu >= NUM_CPUS) return -EINVAL; clk_prepare_enable(emc_clk); clk_prepare_enable(cpu_clk); - cpufreq_table_validate_and_show(policy, freq_table); target_cpu_speed[policy->cpu] = tegra_getspeed(policy->cpu); /* FIXME: what's the actual transition time? */ - policy->cpuinfo.transition_latency = 300 * 1000; - - cpumask_copy(policy->cpus, cpu_possible_mask); + ret = cpufreq_generic_init(policy, freq_table, 300 * 1000); + if (ret) { + clk_disable_unprepare(cpu_clk); + clk_disable_unprepare(emc_clk); + return ret; + } if (policy->cpu == 0) register_pm_notifier(&tegra_cpu_pm_notifier); @@ -227,6 +231,7 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) static int tegra_cpu_exit(struct cpufreq_policy *policy) { cpufreq_frequency_table_put_attr(policy->cpu); + clk_disable_unprepare(cpu_clk); clk_disable_unprepare(emc_clk); return 0; } -- cgit v0.10.2 From e50322a59a3fc42245ae6159095d9ba635da1a03 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 12 Oct 2013 22:16:05 +0200 Subject: cpufreq: sa11x0: Fix build breakage after "Expose frequency table" Fix build breakage introduced by commit 22c8b4f (cpufreq: sa11x0: Expose frequency table). [rjw: Changelog] Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index 39d56a67..cbdfae7 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h @@ -3,6 +3,7 @@ * * Author: Nicolas Pitre */ +#include #include extern void sa1100_timer_init(void); @@ -19,8 +20,6 @@ extern void sa11x0_init_late(void); extern void sa1110_mb_enable(void); extern void sa1110_mb_disable(void); -struct cpufreq_policy; - extern struct cpufreq_frequency_table sa11x0_freq_table[]; extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); extern unsigned int sa11x0_getspeed(unsigned int cpu); -- cgit v0.10.2 From 5915a3db0c3983f1cd5e046bf70086c7d0c686d2 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 11 Oct 2013 21:27:43 +0800 Subject: backlight: introduce backlight_device_registered Introduce a new API for modules to query if a specific type of backlight device has been registered. This is useful for some backlight device provider module (e.g. ACPI video) to know if a native control interface(e.g. the interface created by i915) is available and then do things accordingly (e.g. avoid registering its own on Win8 systems). Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 94a403a..5d05555 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -21,6 +21,9 @@ #include #endif +static struct list_head backlight_dev_list; +static struct mutex backlight_dev_list_mutex; + static const char *const backlight_types[] = { [BACKLIGHT_RAW] = "raw", [BACKLIGHT_PLATFORM] = "platform", @@ -349,10 +352,32 @@ struct backlight_device *backlight_device_register(const char *name, mutex_unlock(&pmac_backlight_mutex); #endif + mutex_lock(&backlight_dev_list_mutex); + list_add(&new_bd->entry, &backlight_dev_list); + mutex_unlock(&backlight_dev_list_mutex); + return new_bd; } EXPORT_SYMBOL(backlight_device_register); +bool backlight_device_registered(enum backlight_type type) +{ + bool found = false; + struct backlight_device *bd; + + mutex_lock(&backlight_dev_list_mutex); + list_for_each_entry(bd, &backlight_dev_list, entry) { + if (bd->props.type == type) { + found = true; + break; + } + } + mutex_unlock(&backlight_dev_list_mutex); + + return found; +} +EXPORT_SYMBOL(backlight_device_registered); + /** * backlight_device_unregister - unregisters a backlight device object. * @bd: the backlight device object to be unregistered and freed. @@ -364,6 +389,10 @@ void backlight_device_unregister(struct backlight_device *bd) if (!bd) return; + mutex_lock(&backlight_dev_list_mutex); + list_del(&bd->entry); + mutex_unlock(&backlight_dev_list_mutex); + #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); if (pmac_backlight == bd) @@ -499,6 +528,8 @@ static int __init backlight_class_init(void) backlight_class->dev_groups = bl_device_groups; backlight_class->pm = &backlight_class_dev_pm_ops; + INIT_LIST_HEAD(&backlight_dev_list); + mutex_init(&backlight_dev_list_mutex); return 0; } diff --git a/include/linux/backlight.h b/include/linux/backlight.h index 53b7794..5f9cd96 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h @@ -100,6 +100,9 @@ struct backlight_device { /* The framebuffer notifier block */ struct notifier_block fb_notif; + /* list entry of all registered backlight devices */ + struct list_head entry; + struct device dev; }; @@ -123,6 +126,7 @@ extern void devm_backlight_device_unregister(struct device *dev, struct backlight_device *bd); extern void backlight_force_update(struct backlight_device *bd, enum backlight_update_reason reason); +extern bool backlight_device_registered(enum backlight_type type); #define to_backlight_device(obj) container_of(obj, struct backlight_device, dev) -- cgit v0.10.2 From 67b662e189f469c6d373f81d76b0ef0495940e99 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 11 Oct 2013 21:27:44 +0800 Subject: ACPI / video: seperate backlight control and event interface The backlight control and event delivery functionality provided by ACPI video module is mixed together and registered all during video device enumeration time. As a result, the two functionality are also removed together on module unload time or by the acpi_video_unregister function. The two functionalities are actually independent and one may be useful while the other one may be broken, so it is desirable to seperate the two functionalities such that it is clear and easy to disable one functionality without affecting the other one. APIs to selectively remove backlight control interface and/or event delivery functionality can be easily added once needed. Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index aebcf63..3bd1eaa 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -89,6 +89,8 @@ static bool use_bios_initial_backlight = 1; module_param(use_bios_initial_backlight, bool, 0644); static int register_count; +static struct mutex video_list_lock; +static struct list_head video_bus_head; static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device); static void acpi_video_bus_notify(struct acpi_device *device, u32 event); @@ -157,6 +159,7 @@ struct acpi_video_bus { struct acpi_video_bus_flags flags; struct list_head video_device_list; struct mutex device_list_lock; /* protects video_device_list */ + struct list_head entry; struct input_dev *input; char phys[32]; /* for input device */ struct notifier_block pm_nb; @@ -884,79 +887,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) if (acpi_has_method(device->dev->handle, "_DDC")) device->cap._DDC = 1; - - if (acpi_video_backlight_support()) { - struct backlight_properties props; - struct pci_dev *pdev; - acpi_handle acpi_parent; - struct device *parent = NULL; - int result; - static int count; - char *name; - - result = acpi_video_init_brightness(device); - if (result) - return; - name = kasprintf(GFP_KERNEL, "acpi_video%d", count); - if (!name) - return; - count++; - - acpi_get_parent(device->dev->handle, &acpi_parent); - - pdev = acpi_get_pci_dev(acpi_parent); - if (pdev) { - parent = &pdev->dev; - pci_dev_put(pdev); - } - - memset(&props, 0, sizeof(struct backlight_properties)); - props.type = BACKLIGHT_FIRMWARE; - props.max_brightness = device->brightness->count - 3; - device->backlight = backlight_device_register(name, - parent, - device, - &acpi_backlight_ops, - &props); - kfree(name); - if (IS_ERR(device->backlight)) - return; - - /* - * Save current brightness level in case we have to restore it - * before acpi_video_device_lcd_set_level() is called next time. - */ - device->backlight->props.brightness = - acpi_video_get_brightness(device->backlight); - - device->cooling_dev = thermal_cooling_device_register("LCD", - device->dev, &video_cooling_ops); - if (IS_ERR(device->cooling_dev)) { - /* - * Set cooling_dev to NULL so we don't crash trying to - * free it. - * Also, why the hell we are returning early and - * not attempt to register video output if cooling - * device registration failed? - * -- dtor - */ - device->cooling_dev = NULL; - return; - } - - dev_info(&device->dev->dev, "registered as cooling_device%d\n", - device->cooling_dev->id); - result = sysfs_create_link(&device->dev->dev.kobj, - &device->cooling_dev->device.kobj, - "thermal_cooling"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - result = sysfs_create_link(&device->cooling_dev->device.kobj, - &device->dev->dev.kobj, "device"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - - } } /* @@ -1143,13 +1073,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device, acpi_video_device_bind(video, data); acpi_video_device_find_cap(data); - status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, - acpi_video_device_notify, data); - if (ACPI_FAILURE(status)) - dev_err(&device->dev, "Error installing notify handler\n"); - else - data->flags.notify = 1; - mutex_lock(&video->device_list_lock); list_add_tail(&data->entry, &video->video_device_list); mutex_unlock(&video->device_list_lock); @@ -1454,64 +1377,6 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, return status; } -static int acpi_video_bus_put_one_device(struct acpi_video_device *device) -{ - acpi_status status; - - if (!device || !device->video) - return -ENOENT; - - if (device->flags.notify) { - status = acpi_remove_notify_handler(device->dev->handle, - ACPI_DEVICE_NOTIFY, acpi_video_device_notify); - if (ACPI_FAILURE(status)) - dev_err(&device->dev->dev, - "Can't remove video notify handler\n"); - } - - if (device->backlight) { - backlight_device_unregister(device->backlight); - device->backlight = NULL; - } - if (device->cooling_dev) { - sysfs_remove_link(&device->dev->dev.kobj, - "thermal_cooling"); - sysfs_remove_link(&device->cooling_dev->device.kobj, - "device"); - thermal_cooling_device_unregister(device->cooling_dev); - device->cooling_dev = NULL; - } - - return 0; -} - -static int acpi_video_bus_put_devices(struct acpi_video_bus *video) -{ - int status; - struct acpi_video_device *dev, *next; - - mutex_lock(&video->device_list_lock); - - list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { - - status = acpi_video_bus_put_one_device(dev); - if (ACPI_FAILURE(status)) - printk(KERN_WARNING PREFIX - "hhuuhhuu bug in acpi video driver.\n"); - - if (dev->brightness) { - kfree(dev->brightness->levels); - kfree(dev->brightness); - } - list_del(&dev->entry); - kfree(dev); - } - - mutex_unlock(&video->device_list_lock); - - return 0; -} - /* acpi_video interface */ /* @@ -1536,7 +1401,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) struct input_dev *input; int keycode = 0; - if (!video) + if (!video || !video->input) return; input = video->input; @@ -1691,12 +1556,236 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context, return AE_OK; } +static void acpi_video_dev_register_backlight(struct acpi_video_device *device) +{ + if (acpi_video_backlight_support()) { + struct backlight_properties props; + struct pci_dev *pdev; + acpi_handle acpi_parent; + struct device *parent = NULL; + int result; + static int count; + char *name; + + result = acpi_video_init_brightness(device); + if (result) + return; + name = kasprintf(GFP_KERNEL, "acpi_video%d", count); + if (!name) + return; + count++; + + acpi_get_parent(device->dev->handle, &acpi_parent); + + pdev = acpi_get_pci_dev(acpi_parent); + if (pdev) { + parent = &pdev->dev; + pci_dev_put(pdev); + } + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_FIRMWARE; + props.max_brightness = device->brightness->count - 3; + device->backlight = backlight_device_register(name, + parent, + device, + &acpi_backlight_ops, + &props); + kfree(name); + if (IS_ERR(device->backlight)) + return; + + /* + * Save current brightness level in case we have to restore it + * before acpi_video_device_lcd_set_level() is called next time. + */ + device->backlight->props.brightness = + acpi_video_get_brightness(device->backlight); + + device->cooling_dev = thermal_cooling_device_register("LCD", + device->dev, &video_cooling_ops); + if (IS_ERR(device->cooling_dev)) { + /* + * Set cooling_dev to NULL so we don't crash trying to + * free it. + * Also, why the hell we are returning early and + * not attempt to register video output if cooling + * device registration failed? + * -- dtor + */ + device->cooling_dev = NULL; + return; + } + + dev_info(&device->dev->dev, "registered as cooling_device%d\n", + device->cooling_dev->id); + result = sysfs_create_link(&device->dev->dev.kobj, + &device->cooling_dev->device.kobj, + "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + result = sysfs_create_link(&device->cooling_dev->device.kobj, + &device->dev->dev.kobj, "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + } +} + +static int acpi_video_bus_register_backlight(struct acpi_video_bus *video) +{ + struct acpi_video_device *dev; + + mutex_lock(&video->device_list_lock); + list_for_each_entry(dev, &video->video_device_list, entry) + acpi_video_dev_register_backlight(dev); + mutex_unlock(&video->device_list_lock); + + video->pm_nb.notifier_call = acpi_video_resume; + video->pm_nb.priority = 0; + return register_pm_notifier(&video->pm_nb); +} + +static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device) +{ + if (device->backlight) { + backlight_device_unregister(device->backlight); + device->backlight = NULL; + } + if (device->brightness) { + kfree(device->brightness->levels); + kfree(device->brightness); + device->brightness = NULL; + } + if (device->cooling_dev) { + sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling"); + sysfs_remove_link(&device->cooling_dev->device.kobj, "device"); + thermal_cooling_device_unregister(device->cooling_dev); + device->cooling_dev = NULL; + } +} + +static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video) +{ + struct acpi_video_device *dev; + int error = unregister_pm_notifier(&video->pm_nb); + + mutex_lock(&video->device_list_lock); + list_for_each_entry(dev, &video->video_device_list, entry) + acpi_video_dev_unregister_backlight(dev); + mutex_unlock(&video->device_list_lock); + + return error; +} + +static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device) +{ + acpi_status status; + struct acpi_device *adev = device->dev; + + status = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, + acpi_video_device_notify, device); + if (ACPI_FAILURE(status)) + dev_err(&adev->dev, "Error installing notify handler\n"); + else + device->flags.notify = 1; +} + +static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video) +{ + struct input_dev *input; + struct acpi_video_device *dev; + int error; + + video->input = input = input_allocate_device(); + if (!input) { + error = -ENOMEM; + goto out; + } + + error = acpi_video_bus_start_devices(video); + if (error) + goto err_free_input; + + snprintf(video->phys, sizeof(video->phys), + "%s/video/input0", acpi_device_hid(video->device)); + + input->name = acpi_device_name(video->device); + input->phys = video->phys; + input->id.bustype = BUS_HOST; + input->id.product = 0x06; + input->dev.parent = &video->device->dev; + input->evbit[0] = BIT(EV_KEY); + set_bit(KEY_SWITCHVIDEOMODE, input->keybit); + set_bit(KEY_VIDEO_NEXT, input->keybit); + set_bit(KEY_VIDEO_PREV, input->keybit); + set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); + set_bit(KEY_BRIGHTNESSUP, input->keybit); + set_bit(KEY_BRIGHTNESSDOWN, input->keybit); + set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); + set_bit(KEY_DISPLAY_OFF, input->keybit); + + error = input_register_device(input); + if (error) + goto err_stop_dev; + + mutex_lock(&video->device_list_lock); + list_for_each_entry(dev, &video->video_device_list, entry) + acpi_video_dev_add_notify_handler(dev); + mutex_unlock(&video->device_list_lock); + + return 0; + +err_stop_dev: + acpi_video_bus_stop_devices(video); +err_free_input: + input_free_device(input); + video->input = NULL; +out: + return error; +} + +static void acpi_video_dev_remove_notify_handler(struct acpi_video_device *dev) +{ + if (dev->flags.notify) { + acpi_remove_notify_handler(dev->dev->handle, ACPI_DEVICE_NOTIFY, + acpi_video_device_notify); + dev->flags.notify = 0; + } +} + +static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video) +{ + struct acpi_video_device *dev; + + mutex_lock(&video->device_list_lock); + list_for_each_entry(dev, &video->video_device_list, entry) + acpi_video_dev_remove_notify_handler(dev); + mutex_unlock(&video->device_list_lock); + + acpi_video_bus_stop_devices(video); + input_unregister_device(video->input); + video->input = NULL; +} + +static int acpi_video_bus_put_devices(struct acpi_video_bus *video) +{ + struct acpi_video_device *dev, *next; + + mutex_lock(&video->device_list_lock); + list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { + list_del(&dev->entry); + kfree(dev); + } + mutex_unlock(&video->device_list_lock); + + return 0; +} + static int instance; static int acpi_video_bus_add(struct acpi_device *device) { struct acpi_video_bus *video; - struct input_dev *input; int error; acpi_status status; @@ -1748,62 +1837,24 @@ static int acpi_video_bus_add(struct acpi_device *device) if (error) goto err_put_video; - video->input = input = input_allocate_device(); - if (!input) { - error = -ENOMEM; - goto err_put_video; - } - - error = acpi_video_bus_start_devices(video); - if (error) - goto err_free_input_dev; - - snprintf(video->phys, sizeof(video->phys), - "%s/video/input0", acpi_device_hid(video->device)); - - input->name = acpi_device_name(video->device); - input->phys = video->phys; - input->id.bustype = BUS_HOST; - input->id.product = 0x06; - input->dev.parent = &device->dev; - input->evbit[0] = BIT(EV_KEY); - set_bit(KEY_SWITCHVIDEOMODE, input->keybit); - set_bit(KEY_VIDEO_NEXT, input->keybit); - set_bit(KEY_VIDEO_PREV, input->keybit); - set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); - set_bit(KEY_BRIGHTNESSUP, input->keybit); - set_bit(KEY_BRIGHTNESSDOWN, input->keybit); - set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); - set_bit(KEY_DISPLAY_OFF, input->keybit); - printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), video->flags.multihead ? "yes" : "no", video->flags.rom ? "yes" : "no", video->flags.post ? "yes" : "no"); + mutex_lock(&video_list_lock); + list_add_tail(&video->entry, &video_bus_head); + mutex_unlock(&video_list_lock); - video->pm_nb.notifier_call = acpi_video_resume; - video->pm_nb.priority = 0; - error = register_pm_notifier(&video->pm_nb); - if (error) - goto err_stop_video; - - error = input_register_device(input); - if (error) - goto err_unregister_pm_notifier; + acpi_video_bus_register_backlight(video); + acpi_video_bus_add_notify_handler(video); return 0; - err_unregister_pm_notifier: - unregister_pm_notifier(&video->pm_nb); - err_stop_video: - acpi_video_bus_stop_devices(video); - err_free_input_dev: - input_free_device(input); - err_put_video: +err_put_video: acpi_video_bus_put_devices(video); kfree(video->attached_array); - err_free_video: +err_free_video: kfree(video); device->driver_data = NULL; @@ -1820,12 +1871,14 @@ static int acpi_video_bus_remove(struct acpi_device *device) video = acpi_driver_data(device); - unregister_pm_notifier(&video->pm_nb); - - acpi_video_bus_stop_devices(video); + acpi_video_bus_remove_notify_handler(video); + acpi_video_bus_unregister_backlight(video); acpi_video_bus_put_devices(video); - input_unregister_device(video->input); + mutex_lock(&video_list_lock); + list_del(&video->entry); + mutex_unlock(&video_list_lock); + kfree(video->attached_array); kfree(video); @@ -1874,6 +1927,9 @@ int acpi_video_register(void) return 0; } + mutex_init(&video_list_lock); + INIT_LIST_HEAD(&video_bus_head); + result = acpi_bus_register_driver(&acpi_video_bus); if (result < 0) return -ENODEV; -- cgit v0.10.2 From fbc9fe1b4f222a7c575e3bd8e9defe59c6190a04 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 11 Oct 2013 21:27:45 +0800 Subject: ACPI / video: Do not register backlight if win8 and native interface exists According to Matthew Garrett, "Windows 8 leaves backlight control up to individual graphics drivers rather than making ACPI calls itself. There's plenty of evidence to suggest that the Intel driver for Windows [8] doesn't use the ACPI interface, including the fact that it's broken on a bunch of machines when the OS claims to support Windows 8. The simplest thing to do appears to be to disable the ACPI backlight interface on these systems". So for Win8 systems, if there is native backlight control interface registered by GPU driver, ACPI video does not need to register its own. Since there are systems that don't work well with this approach, a parameter for video module named use_native_backlight is introduced and has the value of false by default. For users who have a broken ACPI video backlight interface, video.use_native_backlight=1 is needed in kernel cmdline. Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 20f4233..e9304dc 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -169,9 +169,7 @@ int acpi_create_platform_device(struct acpi_device *adev, Video -------------------------------------------------------------------------- */ #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) -bool acpi_video_backlight_quirks(void); -#else -static inline bool acpi_video_backlight_quirks(void) { return false; } +bool acpi_osi_is_win8(void); #endif #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 3bd1eaa..d020df5 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -88,6 +88,13 @@ module_param(allow_duplicates, bool, 0644); static bool use_bios_initial_backlight = 1; module_param(use_bios_initial_backlight, bool, 0644); +/* + * For Windows 8 systems: if set ture and the GPU driver has + * registered a backlight interface, skip registering ACPI video's. + */ +static bool use_native_backlight = false; +module_param(use_native_backlight, bool, 0644); + static int register_count; static struct mutex video_list_lock; static struct list_head video_bus_head; @@ -232,6 +239,14 @@ static int acpi_video_get_next_level(struct acpi_video_device *device, static int acpi_video_switch_brightness(struct acpi_video_device *device, int event); +static bool acpi_video_verify_backlight_support(void) +{ + if (acpi_osi_is_win8() && use_native_backlight && + backlight_device_registered(BACKLIGHT_RAW)) + return false; + return acpi_video_backlight_support(); +} + /* backlight device sysfs support */ static int acpi_video_get_brightness(struct backlight_device *bd) { @@ -1256,8 +1271,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) unsigned long long level_current, level_next; int result = -EINVAL; - /* no warning message if acpi_backlight=vendor is used */ - if (!acpi_video_backlight_support()) + /* no warning message if acpi_backlight=vendor or a quirk is used */ + if (!acpi_video_verify_backlight_support()) return 0; if (!device->brightness) @@ -1386,13 +1401,13 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, static int acpi_video_bus_start_devices(struct acpi_video_bus *video) { return acpi_video_bus_DOS(video, 0, - acpi_video_backlight_quirks() ? 1 : 0); + acpi_osi_is_win8() ? 1 : 0); } static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) { return acpi_video_bus_DOS(video, 0, - acpi_video_backlight_quirks() ? 0 : 1); + acpi_osi_is_win8() ? 0 : 1); } static void acpi_video_bus_notify(struct acpi_device *device, u32 event) @@ -1558,7 +1573,7 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context, static void acpi_video_dev_register_backlight(struct acpi_video_device *device) { - if (acpi_video_backlight_support()) { + if (acpi_video_verify_backlight_support()) { struct backlight_properties props; struct pci_dev *pdev; acpi_handle acpi_parent; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 940edbf..b639934 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -233,11 +233,11 @@ static void acpi_video_caps_check(void) acpi_video_get_capabilities(NULL); } -bool acpi_video_backlight_quirks(void) +bool acpi_osi_is_win8(void) { return acpi_gbl_osi_data >= ACPI_OSI_WIN_8; } -EXPORT_SYMBOL(acpi_video_backlight_quirks); +EXPORT_SYMBOL(acpi_osi_is_win8); /* Promote the vendor interface instead of the generic video module. * This function allow DMI blacklists to be implemented by externals -- cgit v0.10.2 From 46445b6b896fd6b9fd8261f1747801dc520d2968 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 11 Oct 2013 21:27:46 +0800 Subject: thinkpad-acpi: fix handle locate for video and query of _BCL The tpacpi_acpi_handle_locate function makes use of acpi_get_devices to locate handle for ACPI video by HID, the problem is, ACPI video node doesn't really have HID defined(i.e. no _HID control method is defined for video device), so.. that function would fail. This can be solved by enhancing the callback function for acpi_get_devices, where we can use acpi_device_hid function to check if the ACPI node corresponds to a video controller. In addition to that, the _BCL control method only exists under a video output device node, not a video controller device node. So to evaluate _BCL, we need the handle of a video output device node, which is child of the located video controller node from tpacpi_acpi_handle_locate. The two fix are necessary for some Thinkpad models to emit notification on backlight hotkey press as a result of evaluation of _BCL. Signed-off-by: Aaron Lu Tested-by: Igor Gnatenko Acked-by: Henrique de Moraes Holschuh Signed-off-by: Rafael J. Wysocki diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 03ca6c1..170f278 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -700,6 +700,14 @@ static void __init drv_acpi_handle_init(const char *name, static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle, u32 level, void *context, void **return_value) { + struct acpi_device *dev; + if (!strcmp(context, "video")) { + if (acpi_bus_get_device(handle, &dev)) + return AE_OK; + if (strcmp(ACPI_VIDEO_HID, acpi_device_hid(dev))) + return AE_OK; + } + *(acpi_handle *)return_value = handle; return AE_CTRL_TERMINATE; @@ -712,10 +720,10 @@ static void __init tpacpi_acpi_handle_locate(const char *name, acpi_status status; acpi_handle device_found; - BUG_ON(!name || !hid || !handle); + BUG_ON(!name || !handle); vdbg_printk(TPACPI_DBG_INIT, "trying to locate ACPI handle for %s, using HID %s\n", - name, hid); + name, hid ? hid : "NULL"); memset(&device_found, 0, sizeof(device_found)); status = acpi_get_devices(hid, tpacpi_acpi_handle_locate_callback, @@ -6090,19 +6098,28 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; + struct acpi_device *device, *child; int rc; - if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) { + if (acpi_bus_get_device(handle, &device)) + return 0; + + rc = 0; + list_for_each_entry(child, &device->children, node) { + acpi_status status = acpi_evaluate_object(child->handle, "_BCL", + NULL, &buffer); + if (ACPI_FAILURE(status)) + continue; + obj = (union acpi_object *)buffer.pointer; if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { pr_err("Unknown _BCL data, please report this to %s\n", - TPACPI_MAIL); + TPACPI_MAIL); rc = 0; } else { rc = obj->package.count; } - } else { - return 0; + break; } kfree(buffer.pointer); @@ -6118,7 +6135,7 @@ static unsigned int __init tpacpi_check_std_acpi_brightness_support(void) acpi_handle video_device; int bcl_levels = 0; - tpacpi_acpi_handle_locate("video", ACPI_VIDEO_HID, &video_device); + tpacpi_acpi_handle_locate("video", NULL, &video_device); if (video_device) bcl_levels = tpacpi_query_bcl_levels(video_device); -- cgit v0.10.2 From ab0fd674d6cef0904baa511f22613ef6474f8169 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Sat, 12 Oct 2013 21:04:48 +0800 Subject: ACPI / AC: Remove AC's proc directory. AC's proc directory is not used and so remove it. Prepare for removing /proc/acpi directory. Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 324b5a0..b9f0d5f 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -30,10 +30,6 @@ #include #include #include -#ifdef CONFIG_ACPI_PROCFS_POWER -#include -#include -#endif #include #include #include @@ -56,12 +52,6 @@ MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_LICENSE("GPL"); -#ifdef CONFIG_ACPI_PROCFS_POWER -extern struct proc_dir_entry *acpi_lock_ac_dir(void); -extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); -static int acpi_ac_open_fs(struct inode *inode, struct file *file); -#endif - static int ac_sleep_before_get_state_ms; struct acpi_ac { @@ -73,16 +63,6 @@ struct acpi_ac { #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) -#ifdef CONFIG_ACPI_PROCFS_POWER -static const struct file_operations acpi_ac_fops = { - .owner = THIS_MODULE, - .open = acpi_ac_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - /* -------------------------------------------------------------------------- AC Adapter Management -------------------------------------------------------------------------- */ @@ -132,83 +112,6 @@ static enum power_supply_property ac_props[] = { POWER_SUPPLY_PROP_ONLINE, }; -#ifdef CONFIG_ACPI_PROCFS_POWER -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -static struct proc_dir_entry *acpi_ac_dir; - -static int acpi_ac_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_ac *ac = seq->private; - - - if (!ac) - return 0; - - if (acpi_ac_get_state(ac)) { - seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); - return 0; - } - - seq_puts(seq, "state: "); - switch (ac->state) { - case ACPI_AC_STATUS_OFFLINE: - seq_puts(seq, "off-line\n"); - break; - case ACPI_AC_STATUS_ONLINE: - seq_puts(seq, "on-line\n"); - break; - default: - seq_puts(seq, "unknown\n"); - break; - } - - return 0; -} - -static int acpi_ac_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_ac_seq_show, PDE_DATA(inode)); -} - -static int acpi_ac_add_fs(struct acpi_ac *ac) -{ - struct proc_dir_entry *entry = NULL; - - printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded," - " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); - if (!acpi_device_dir(ac->adev)) { - acpi_device_dir(ac->adev) = - proc_mkdir(acpi_device_bid(ac->adev), acpi_ac_dir); - if (!acpi_device_dir(ac->adev)) - return -ENODEV; - } - - /* 'state' [R] */ - entry = proc_create_data(ACPI_AC_FILE_STATE, - S_IRUGO, acpi_device_dir(ac->adev), - &acpi_ac_fops, ac); - if (!entry) - return -ENODEV; - return 0; -} - -static int acpi_ac_remove_fs(struct acpi_ac *ac) -{ - - if (acpi_device_dir(ac->adev)) { - remove_proc_entry(ACPI_AC_FILE_STATE, - acpi_device_dir(ac->adev)); - remove_proc_entry(acpi_device_bid(ac->adev), acpi_ac_dir); - acpi_device_dir(ac->adev) = NULL; - } - - return 0; -} -#endif - /* -------------------------------------------------------------------------- Driver Model -------------------------------------------------------------------------- */ @@ -293,11 +196,6 @@ static int acpi_ac_probe(struct platform_device *pdev) if (result) goto end; -#ifdef CONFIG_ACPI_PROCFS_POWER - result = acpi_ac_add_fs(ac); - if (result) - goto end; -#endif ac->charger.name = acpi_device_bid(adev); ac->charger.type = POWER_SUPPLY_TYPE_MAINS; ac->charger.properties = ac_props; @@ -317,13 +215,9 @@ static int acpi_ac_probe(struct platform_device *pdev) acpi_device_name(adev), acpi_device_bid(adev), ac->state ? "on-line" : "off-line"); - end: - if (result) { -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_remove_fs(ac); -#endif +end: + if (result) kfree(ac); - } dmi_check_system(ac_dmi_table); return result; @@ -366,10 +260,6 @@ static int acpi_ac_remove(struct platform_device *pdev) if (ac->charger.dev) power_supply_unregister(&ac->charger); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_remove_fs(ac); -#endif - kfree(ac); return 0; @@ -399,19 +289,9 @@ static int __init acpi_ac_init(void) if (acpi_disabled) return -ENODEV; -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_dir = acpi_lock_ac_dir(); - if (!acpi_ac_dir) - return -ENODEV; -#endif - result = platform_driver_register(&acpi_ac_driver); - if (result < 0) { -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_unlock_ac_dir(acpi_ac_dir); -#endif + if (result < 0) return -ENODEV; - } return 0; } @@ -419,9 +299,6 @@ static int __init acpi_ac_init(void) static void __exit acpi_ac_exit(void) { platform_driver_unregister(&acpi_ac_driver); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_unlock_ac_dir(acpi_ac_dir); -#endif } module_init(acpi_ac_init); module_exit(acpi_ac_exit); -- cgit v0.10.2 From a8d52f4495f21da3f47f7318301abf6823ec6648 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Oct 2013 02:55:05 +0200 Subject: ACPI / video: Add Lenovo IdeaPad Yoga 13 to acpi video detect blacklist On the Yoga 13 the backlight control doesn't work via ACPI. (And doesn't work either with the low-level platform driver ideapad_laptop; but works correctly via the intel video driver). This patch hence adds the Yoga 13 to the ACPI video detect blacklist, to make sure the broken ACPI backlight device is never exposed to userspace. Note that this appears unrelated to the Windows 8 backlight issues tracked here: https://bugzilla.kernel.org/show_bug.cgi?id=51231 https://bugzilla.kernel.org/show_bug.cgi?id=60682 The Yoga's ACPI backlight controls work neither with nor without acpi_osi="!Windows 2012" on the kernel command line. It appears that backlight control via the EC simply is not available at all, regardless whether done via ACPI or via the vendor driver. Signed-off-by: Lennart Poettering Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index b639934..84875fd 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -168,6 +168,14 @@ static struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), }, }, + { + .callback = video_detect_force_vendor, + .ident = "Lenovo Yoga 13", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"), + }, + }, { }, }; -- cgit v0.10.2 From d66e6db28df330c0e5b61f9863754fc2fd37f8ca Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 15 Oct 2013 22:25:08 +0200 Subject: PM / Runtime: Respect autosuspend when idle triggers suspend For devices which don't have a .runtime_idle() callback or if it returns 0, rpm_idle() will end up in triggering a call to rpm_suspend(), thus trying to carry out a runtime suspend directly from runtime_idle(). In the above situation we want to respect devices which has enabled autosuspend, we therfore append the flag sent to rpm_suspend with RPM_AUTO. Do note that drivers still needs to update the device last busy mark, to control the delay for this circumstance. Updated runtime PM documentation accordingly. Signed-off-by: Ulf Hansson Acked-by: Kevin Hilman Acked-by: Alan Stern Signed-off-by: Rafael J. Wysocki diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 71d8fe4..0f54333 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -145,11 +145,13 @@ The action performed by the idle callback is totally dependent on the subsystem if the device can be suspended (i.e. if all of the conditions necessary for suspending the device are satisfied) and to queue up a suspend request for the device in that case. If there is no idle callback, or if the callback returns -0, then the PM core will attempt to carry out a runtime suspend of the device; -in essence, it will call pm_runtime_suspend() directly. To prevent this (for -example, if the callback routine has started a delayed suspend), the routine -should return a non-zero value. Negative error return codes are ignored by the -PM core. +0, then the PM core will attempt to carry out a runtime suspend of the device, +also respecting devices configured for autosuspend. In essence this means a +call to pm_runtime_autosuspend() (do note that drivers needs to update the +device last busy mark, pm_runtime_mark_last_busy(), to control the delay under +this circumstance). To prevent this (for example, if the callback routine has +started a delayed suspend), the routine must return a non-zero value. Negative +error return codes are ignored by the PM core. The helper functions provided by the PM core, described in Section 4, guarantee that the following constraints are met with respect to runtime PM callbacks for @@ -308,7 +310,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: - execute the subsystem-level idle callback for the device; returns an error code on failure, where -EINPROGRESS means that ->runtime_idle() is already being executed; if there is no callback or the callback returns 0 - then run pm_runtime_suspend(dev) and return its result + then run pm_runtime_autosuspend(dev) and return its result int pm_runtime_suspend(struct device *dev); - execute the subsystem-level suspend callback for the device; returns 0 on diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 268a350..72e00e6 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -258,7 +258,8 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev) * Check if the device's runtime PM status allows it to be suspended. If * another idle notification has been started earlier, return immediately. If * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise - * run the ->runtime_idle() callback directly. + * run the ->runtime_idle() callback directly. If the ->runtime_idle callback + * doesn't exist or if it returns 0, call rpm_suspend with the RPM_AUTO flag. * * This function must be called under dev->power.lock with interrupts disabled. */ @@ -331,7 +332,7 @@ static int rpm_idle(struct device *dev, int rpmflags) out: trace_rpm_return_int(dev, _THIS_IP_, retval); - return retval ? retval : rpm_suspend(dev, rpmflags); + return retval ? retval : rpm_suspend(dev, rpmflags | RPM_AUTO); } /** -- cgit v0.10.2 From 9208e3110bf0a6ba4ded56e374857d4b6609c911 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 16 Oct 2013 13:15:14 +0300 Subject: ACPI / platform: add ACPI ID for a Broadcom GPS chip This adds ACPI ID for Broadcom GPS receiver BCM4752. Signed-off-by: Heikki Krogerus Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index aef79db..8a4cfc7 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -31,6 +31,7 @@ static const struct acpi_device_id acpi_platform_device_ids[] = { { "PNP0D40" }, { "ACPI0003" }, { "VPC2004" }, + { "BCM4752" }, /* Intel Smart Sound Technology */ { "INT33C8" }, -- cgit v0.10.2 From 5d7e690d775e59e51caaf03e90811af7729ef278 Mon Sep 17 00:00:00 2001 From: Jungseok Lee Date: Tue, 15 Oct 2013 08:31:13 +0900 Subject: cpufreq: exynos: Show a list of available frequencies This patch adds freq_attr to show a list of exynos5440 scaling available frequencies through sysfs. Common exynos driver already supports this attribute. Signed-off-by: Jungseok Lee Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index 06b73e8..fecc3da 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -330,6 +330,7 @@ static struct cpufreq_driver exynos_driver = { .init = exynos_cpufreq_cpu_init, .exit = cpufreq_generic_exit, .name = CPUFREQ_NAME, + .attr = cpufreq_generic_attr, }; static const struct of_device_id exynos_cpufreq_match[] = { -- cgit v0.10.2 From 076dec90fc32c830184b0f0fa1842a6de1199bc6 Mon Sep 17 00:00:00 2001 From: Sudeep KarkadaNagesha Date: Wed, 16 Oct 2013 14:52:39 +0100 Subject: cpufreq: arm-big-little: use clk_get instead of clk_get_sys Currently clk_get_sys is used with cpu-cluster. as the device id which is incorrect. It should be connection/consumer ID instead. It is possible to specify input clock in the cpu device node along with the optional clock-name. clk_get_sys can't handle that. This patch replaces clk_get_sys with clk_get to extend support for clocks specified in the device tree cpu node. Signed-off-by: Sudeep KarkadaNagesha Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index f7717ef..31b41a4 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -119,7 +119,7 @@ static int get_cluster_clk_and_freq_table(struct device *cpu_dev) } name[12] = cluster + '0'; - clk[cluster] = clk_get_sys(name, NULL); + clk[cluster] = clk_get(cpu_dev, name); if (!IS_ERR(clk[cluster])) { dev_dbg(cpu_dev, "%s: clk: %p & freq table: %p, cluster: %d\n", __func__, clk[cluster], freq_table[cluster], -- cgit v0.10.2 From 5ad945ea58f6cab7490dc149974ccb6514cc569a Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Sun, 22 Sep 2013 22:29:57 +0200 Subject: ARM: at91: cpuidle: Convert to platform driver Using the platform driver model is a good way to separate the cpuidle specific code from the low level pm code. It allows to remove the dependency between these two components. The platform_device is located in the pm code and a 'set' function has been added to set the standby function from the AT91_SOC_START initialization function. Each SoC with a cpuidle driver will set the standby function in the platform_data field at init time. Then pm code will register the cpuidle platform device. The cpuidle driver will register the platform_driver and use the device's platform_data as a standby callback in the idle path. The at91_pm_enter function contains a { if then else } based on cpu_is_xx similar to what was in cpuidle. This is considered dangerous when adding a new SoC. Like the cpuidle driver, a standby ops is defined and assigned when the SoC init function specifies what is its standby function and reused in the at91_pm_enter's 'case' block. Signed-off-by: Daniel Lezcano Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Nicolas Ferre diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index 4aad93d..0d234f2 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -27,6 +27,7 @@ #include "generic.h" #include "clock.h" #include "sam9_smc.h" +#include "pm.h" /* -------------------------------------------------------------------- * Clocks @@ -337,6 +338,8 @@ static void __init at91rm9200_initialize(void) /* Initialize GPIO subsystem */ at91_gpio_init(at91rm9200_gpio, cpu_is_at91rm9200_bga() ? AT91RM9200_BGA : AT91RM9200_PQFP); + + at91_pm_set_standby(at91rm9200_standby); } diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 5de6074..ffe9ce7 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -28,6 +28,7 @@ #include "generic.h" #include "clock.h" #include "sam9_smc.h" +#include "pm.h" /* -------------------------------------------------------------------- * Clocks @@ -351,6 +352,8 @@ static void __init at91sam9260_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9260_gpio, 3); + + at91_pm_set_standby(at91sam9_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 0e07932..1edbb6f 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -27,6 +27,7 @@ #include "generic.h" #include "clock.h" #include "sam9_smc.h" +#include "pm.h" /* -------------------------------------------------------------------- * Clocks @@ -293,6 +294,8 @@ static void __init at91sam9261_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9261_gpio, 3); + + at91_pm_set_sandby(at91sam9_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 6ce7d18..8c81c89 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -26,6 +26,7 @@ #include "generic.h" #include "clock.h" #include "sam9_smc.h" +#include "pm.h" /* -------------------------------------------------------------------- * Clocks @@ -330,6 +331,8 @@ static void __init at91sam9263_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9263_gpio, 5); + + at91_pm_set_standby(at91sam9263_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 474ee04..8460f52 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -26,6 +26,7 @@ #include "generic.h" #include "clock.h" #include "sam9_smc.h" +#include "pm.h" /* -------------------------------------------------------------------- * Clocks @@ -379,6 +380,8 @@ static void __init at91sam9g45_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9g45_gpio, 5); + + at91_pm_set_standby(at91sam9g45_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index d4ec0d9..c7986e4 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -27,6 +27,7 @@ #include "generic.h" #include "clock.h" #include "sam9_smc.h" +#include "pm.h" /* -------------------------------------------------------------------- * Clocks @@ -296,6 +297,8 @@ static void __init at91sam9rl_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9rl_gpio, 4); + + at91_pm_set_standby(at91sam9_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 4ec6a6d..a077437 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -21,26 +21,17 @@ #include #include #include -#include - -#include "pm.h" #define AT91_MAX_STATES 2 +static void (*at91_standby)(void); + /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - if (cpu_is_at91rm9200()) - at91rm9200_standby(); - else if (cpu_is_at91sam9g45()) - at91sam9g45_standby(); - else if (cpu_is_at91sam9263()) - at91sam9263_standby(); - else - at91sam9_standby(); - + at91_standby(); return index; } @@ -60,9 +51,19 @@ static struct cpuidle_driver at91_idle_driver = { }; /* Initialize CPU idle by registering the idle states */ -static int __init at91_init_cpuidle(void) +static int at91_cpuidle_probe(struct platform_device *dev) { + at91_standby = (void *)(dev->dev.platform_data); + return cpuidle_register(&at91_idle_driver, NULL); } -device_initcall(at91_init_cpuidle); +static struct platform_driver at91_cpuidle_driver = { + .driver = { + .name = "cpuidle-at91", + .owner = THIS_MODULE, + }, + .probe = at91_cpuidle_probe, +}; + +module_platform_driver(at91_cpuidle_driver); diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 15afb5d..9986542 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -39,6 +39,8 @@ #include "at91_rstc.h" #include "at91_shdwc.h" +static void (*at91_pm_standby)(void); + static void __init show_reset_status(void) { static char reset[] __initdata = "reset"; @@ -266,14 +268,8 @@ static int at91_pm_enter(suspend_state_t state) * For ARM 926 based chips, this requirement is weaker * as at91sam9 can access a RAM in self-refresh mode. */ - if (cpu_is_at91rm9200()) - at91rm9200_standby(); - else if (cpu_is_at91sam9g45()) - at91sam9g45_standby(); - else if (cpu_is_at91sam9263()) - at91sam9263_standby(); - else - at91sam9_standby(); + if (at91_pm_standby) + at91_pm_standby(); break; case PM_SUSPEND_ON: @@ -314,6 +310,18 @@ static const struct platform_suspend_ops at91_pm_ops = { .end = at91_pm_end, }; +static struct platform_device at91_cpuidle_device = { + .name = "cpuidle-at91", +}; + +void at91_pm_set_standby(void (*at91_standby)(void)) +{ + if (at91_standby) { + at91_cpuidle_device.dev.platform_data = at91_standby; + at91_pm_standby = at91_standby; + } +} + static int __init at91_pm_init(void) { #ifdef CONFIG_AT91_SLOW_CLOCK @@ -325,6 +333,9 @@ static int __init at91_pm_init(void) /* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */ if (cpu_is_at91rm9200()) at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0); + + if (at91_cpuidle_device.dev.platform_data) + platform_device_register(&at91_cpuidle_device); suspend_set_ops(&at91_pm_ops); diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index 2f5908f..76dd1a7 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -11,9 +11,13 @@ #ifndef __ARCH_ARM_MACH_AT91_PM #define __ARCH_ARM_MACH_AT91_PM +#include + #include #include +extern void at91_pm_set_standby(void (*at91_standby)(void)); + /* * The AT91RM9200 goes into self-refresh mode with this command, and will * terminate self-refresh automatically on the next SDRAM access. -- cgit v0.10.2 From 1ce3c48e6c76920fa46bfdde84a69e155f880c32 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 26 Sep 2013 17:34:24 +0200 Subject: ARM: at91: cpuidle: Move driver to drivers/cpuidle As the cpuidle driver code has no more the dependency with the pm code, the 'standby' callback being passed as a parameter to the device's platform data, we can move the cpuidle driver in the drivers/cpuidle directory. Signed-off-by: Daniel Lezcano Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Nicolas Ferre Conflicts: drivers/cpuidle/Kconfig.arm drivers/cpuidle/Makefile diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 3b0a953..c1b7370 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -98,7 +98,6 @@ obj-y += leds.o # Power Management obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_AT91_SLOW_CLOCK) += pm_slowclock.o -obj-$(CONFIG_CPU_IDLE) += cpuidle.o ifeq ($(CONFIG_PM_DEBUG),y) CFLAGS_pm.o += -DDEBUG diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c deleted file mode 100644 index a077437..0000000 --- a/arch/arm/mach-at91/cpuidle.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * based on arch/arm/mach-kirkwood/cpuidle.c - * - * CPU idle support for AT91 SoC - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - * The cpu idle uses wait-for-interrupt and RAM self refresh in order - * to implement two idle states - - * #1 wait-for-interrupt - * #2 wait-for-interrupt and RAM self refresh - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define AT91_MAX_STATES 2 - -static void (*at91_standby)(void); - -/* Actual code that puts the SoC in different idle states */ -static int at91_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) -{ - at91_standby(); - return index; -} - -static struct cpuidle_driver at91_idle_driver = { - .name = "at91_idle", - .owner = THIS_MODULE, - .states[0] = ARM_CPUIDLE_WFI_STATE, - .states[1] = { - .enter = at91_enter_idle, - .exit_latency = 10, - .target_residency = 10000, - .flags = CPUIDLE_FLAG_TIME_VALID, - .name = "RAM_SR", - .desc = "WFI and DDR Self Refresh", - }, - .state_count = AT91_MAX_STATES, -}; - -/* Initialize CPU idle by registering the idle states */ -static int at91_cpuidle_probe(struct platform_device *dev) -{ - at91_standby = (void *)(dev->dev.platform_data); - - return cpuidle_register(&at91_idle_driver, NULL); -} - -static struct platform_driver at91_cpuidle_driver = { - .driver = { - .name = "cpuidle-at91", - .owner = THIS_MODULE, - }, - .probe = at91_cpuidle_probe, -}; - -module_platform_driver(at91_cpuidle_driver); diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 6a7e6f2..f23bd75 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -37,3 +37,10 @@ config ARM_U8500_CPUIDLE depends on ARCH_U8500 help Select this to enable cpuidle for ST-E u8500 processors + +config ARM_AT91_CPUIDLE + bool "Cpu Idle Driver for the AT91 processors" + default y + depends on ARCH_AT91 + help + Select this to enable cpuidle for AT91 processors diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index d08bd40..527be28 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o +obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o diff --git a/drivers/cpuidle/cpuidle-at91.c b/drivers/cpuidle/cpuidle-at91.c new file mode 100644 index 0000000..a077437 --- /dev/null +++ b/drivers/cpuidle/cpuidle-at91.c @@ -0,0 +1,69 @@ +/* + * based on arch/arm/mach-kirkwood/cpuidle.c + * + * CPU idle support for AT91 SoC + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * The cpu idle uses wait-for-interrupt and RAM self refresh in order + * to implement two idle states - + * #1 wait-for-interrupt + * #2 wait-for-interrupt and RAM self refresh + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define AT91_MAX_STATES 2 + +static void (*at91_standby)(void); + +/* Actual code that puts the SoC in different idle states */ +static int at91_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + at91_standby(); + return index; +} + +static struct cpuidle_driver at91_idle_driver = { + .name = "at91_idle", + .owner = THIS_MODULE, + .states[0] = ARM_CPUIDLE_WFI_STATE, + .states[1] = { + .enter = at91_enter_idle, + .exit_latency = 10, + .target_residency = 10000, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "RAM_SR", + .desc = "WFI and DDR Self Refresh", + }, + .state_count = AT91_MAX_STATES, +}; + +/* Initialize CPU idle by registering the idle states */ +static int at91_cpuidle_probe(struct platform_device *dev) +{ + at91_standby = (void *)(dev->dev.platform_data); + + return cpuidle_register(&at91_idle_driver, NULL); +} + +static struct platform_driver at91_cpuidle_driver = { + .driver = { + .name = "cpuidle-at91", + .owner = THIS_MODULE, + }, + .probe = at91_cpuidle_probe, +}; + +module_platform_driver(at91_cpuidle_driver); -- cgit v0.10.2 From 2d2c476f3c075bd2fdfce479245b2bf4d0879ec6 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Wed, 16 Oct 2013 16:24:56 +0200 Subject: ARM: AT91: pm: Factorize standby function Detect presence of second bank. So we do not need to have on function per SoC Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Acked-by: Nicolas Ferre Acked-by: Daniel Lezcano Signed-off-by: Daniel Lezcano diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index ffe9ce7..3b43d56 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -353,7 +353,7 @@ static void __init at91sam9260_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9260_gpio, 3); - at91_pm_set_standby(at91sam9_standby); + at91_pm_set_standby(at91sam9_sdram_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 1edbb6f..a0857c3 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -295,7 +295,7 @@ static void __init at91sam9261_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9261_gpio, 3); - at91_pm_set_sandby(at91sam9_standby); + at91_pm_set_standby(at91sam9_sdram_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 8c81c89..103a95b 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -332,7 +332,7 @@ static void __init at91sam9263_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9263_gpio, 5); - at91_pm_set_standby(at91sam9263_standby); + at91_pm_set_standby(at91sam9_sdram_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 8460f52..f29731e 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -381,7 +381,7 @@ static void __init at91sam9g45_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9g45_gpio, 5); - at91_pm_set_standby(at91sam9g45_standby); + at91_pm_set_standby(at91_ddr_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index c7986e4..9e28f41 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -298,7 +298,7 @@ static void __init at91sam9rl_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9rl_gpio, 4); - at91_pm_set_standby(at91sam9_standby); + at91_pm_set_standby(at91sam9_sdram_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index 76dd1a7..3ed190c 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -49,16 +49,18 @@ static inline void at91rm9200_standby(void) /* We manage both DDRAM/SDRAM controllers, we need more than one value to * remember. */ -static inline void at91sam9g45_standby(void) +static inline void at91_ddr_standby(void) { /* Those two values allow us to delay self-refresh activation * to the maximum. */ - u32 lpr0, lpr1; - u32 saved_lpr0, saved_lpr1; + u32 lpr0, lpr1 = 0; + u32 saved_lpr0, saved_lpr1 = 0; - saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR); - lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB; - lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH; + if (at91_ramc_base[1]) { + saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR); + lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB; + lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH; + } saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR); lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB; @@ -66,25 +68,29 @@ static inline void at91sam9g45_standby(void) /* self-refresh mode now */ at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0); - at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1); + if (at91_ramc_base[1]) + at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1); cpu_do_idle(); at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); - at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); + if (at91_ramc_base[1]) + at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); } /* We manage both DDRAM/SDRAM controllers, we need more than one value to * remember. */ -static inline void at91sam9263_standby(void) +static inline void at91sam9_sdram_standby(void) { - u32 lpr0, lpr1; - u32 saved_lpr0, saved_lpr1; + u32 lpr0, lpr1 = 0; + u32 saved_lpr0, saved_lpr1 = 0; - saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR); - lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB; - lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH; + if (at91_ramc_base[1]) { + saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR); + lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB; + lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH; + } saved_lpr0 = at91_ramc_read(0, AT91_SDRAMC_LPR); lpr0 = saved_lpr0 & ~AT91_SDRAMC_LPCB; @@ -92,27 +98,14 @@ static inline void at91sam9263_standby(void) /* self-refresh mode now */ at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0); - at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1); + if (at91_ramc_base[1]) + at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1); cpu_do_idle(); at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0); - at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); -} - -static inline void at91sam9_standby(void) -{ - u32 saved_lpr, lpr; - - saved_lpr = at91_ramc_read(0, AT91_SDRAMC_LPR); - - lpr = saved_lpr & ~AT91_SDRAMC_LPCB; - at91_ramc_write(0, AT91_SDRAMC_LPR, lpr | - AT91_SDRAMC_LPCB_SELF_REFRESH); - - cpu_do_idle(); - - at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr); + if (at91_ramc_base[1]) + at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); } #endif -- cgit v0.10.2 From 6b625891c6b541080bdaad97bcb82bd9ecd9e44b Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Wed, 16 Oct 2013 16:24:57 +0200 Subject: ARM: AT91: DT: pm: Select ram controller standby based on DT Move non-dt selection to ioremap_registers init which is only called not non-dt board. So we can support sam9n12/sam9x5/sama5d3 too. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Daniel Lezcano Cc: Nicolas Ferre Acked-by: Nicolas Ferre diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index 0d234f2..25805f2 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -328,6 +328,7 @@ static void __init at91rm9200_ioremap_registers(void) { at91rm9200_ioremap_st(AT91RM9200_BASE_ST); at91_ioremap_ramc(0, AT91RM9200_BASE_MC, 256); + at91_pm_set_standby(at91rm9200_standby); } static void __init at91rm9200_initialize(void) @@ -338,8 +339,6 @@ static void __init at91rm9200_initialize(void) /* Initialize GPIO subsystem */ at91_gpio_init(at91rm9200_gpio, cpu_is_at91rm9200_bga() ? AT91RM9200_BGA : AT91RM9200_PQFP); - - at91_pm_set_standby(at91rm9200_standby); } diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 3b43d56..f8629a3 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -343,6 +343,7 @@ static void __init at91sam9260_ioremap_registers(void) at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT); at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC); at91_ioremap_matrix(AT91SAM9260_BASE_MATRIX); + at91_pm_set_standby(at91sam9_sdram_standby); } static void __init at91sam9260_initialize(void) @@ -352,8 +353,6 @@ static void __init at91sam9260_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9260_gpio, 3); - - at91_pm_set_standby(at91sam9_sdram_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index a0857c3..1f3867a 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -285,6 +285,7 @@ static void __init at91sam9261_ioremap_registers(void) at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT); at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC); at91_ioremap_matrix(AT91SAM9261_BASE_MATRIX); + at91_pm_set_standby(at91sam9_sdram_standby); } static void __init at91sam9261_initialize(void) @@ -294,8 +295,6 @@ static void __init at91sam9261_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9261_gpio, 3); - - at91_pm_set_standby(at91sam9_sdram_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 103a95b..90d455d 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -322,6 +322,7 @@ static void __init at91sam9263_ioremap_registers(void) at91sam9_ioremap_smc(0, AT91SAM9263_BASE_SMC0); at91sam9_ioremap_smc(1, AT91SAM9263_BASE_SMC1); at91_ioremap_matrix(AT91SAM9263_BASE_MATRIX); + at91_pm_set_standby(at91sam9_sdram_standby); } static void __init at91sam9263_initialize(void) @@ -331,8 +332,6 @@ static void __init at91sam9263_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9263_gpio, 5); - - at91_pm_set_standby(at91sam9_sdram_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index f29731e..e9bf0b8 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -371,6 +371,7 @@ static void __init at91sam9g45_ioremap_registers(void) at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT); at91sam9_ioremap_smc(0, AT91SAM9G45_BASE_SMC); at91_ioremap_matrix(AT91SAM9G45_BASE_MATRIX); + at91_pm_set_standby(at91_ddr_standby); } static void __init at91sam9g45_initialize(void) @@ -380,8 +381,6 @@ static void __init at91sam9g45_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9g45_gpio, 5); - - at91_pm_set_standby(at91_ddr_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index 9e28f41..88995af 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -288,6 +288,7 @@ static void __init at91sam9rl_ioremap_registers(void) at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT); at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC); at91_ioremap_matrix(AT91SAM9RL_BASE_MATRIX); + at91_pm_set_standby(at91sam9_sdram_standby); } static void __init at91sam9rl_initialize(void) @@ -297,8 +298,6 @@ static void __init at91sam9rl_initialize(void) /* Register GPIO subsystem */ at91_gpio_init(at91sam9rl_gpio, 4); - - at91_pm_set_standby(at91sam9_sdram_standby); } /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index b17fbcf..094b345 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -23,6 +23,7 @@ #include "at91_shdwc.h" #include "soc.h" #include "generic.h" +#include "pm.h" struct at91_init_soc __initdata at91_boot_soc; @@ -376,15 +377,16 @@ static void at91_dt_rstc(void) } static struct of_device_id ramc_ids[] = { - { .compatible = "atmel,at91rm9200-sdramc" }, - { .compatible = "atmel,at91sam9260-sdramc" }, - { .compatible = "atmel,at91sam9g45-ddramc" }, + { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, + { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, + { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, { /*sentinel*/ } }; static void at91_dt_ramc(void) { struct device_node *np; + const struct of_device_id *of_id; np = of_find_matching_node(NULL, ramc_ids); if (!np) @@ -396,6 +398,12 @@ static void at91_dt_ramc(void) /* the controller may have 2 banks */ at91_ramc_base[1] = of_iomap(np, 1); + of_id = of_match_node(ramc_ids, np); + if (!of_id) + pr_warn("AT91: ramc no standby function available\n"); + else + at91_pm_set_standby(of_id->data); + of_node_put(np); } -- cgit v0.10.2 From 1bab64d50e09706ee2e634b2df3c53346f0a0dbb Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 16 Oct 2013 23:58:10 +0200 Subject: acpi-cpufreq: Add comment under ACPI_ADR_SPACE_SYSTEM_IO case policy->cur is now set by cpufreq core when cpufreq_driver->get() is defined and so drivers aren't required to set it. When space_id is ACPI_ADR_SPACE_SYSTEM_IO for acpi cpufreq driver it doesn't set ->get to a valid function pointer and so policy->cur is required to be set by driver. This is already followed in acpi-cpufreq driver. This patch adds a comment describing why we need to set policy->cur from driver. Suggested-by: Rafael J. Wysocki Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index a8dac7b..a1717d7 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -837,7 +837,12 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) switch (perf->control_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: - /* Current speed is unknown and not detectable by IO port */ + /* + * The core will not set policy->cur, because + * cpufreq_driver->get is NULL, so we need to set it here. + * However, we have to guess it, because the current speed is + * unknown and not detectable via IO ports. + */ policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu); break; case ACPI_ADR_SPACE_FIXED_HARDWARE: -- cgit v0.10.2 From 7b6f38f09ebb4b88e8ed7740bcbcc08a8882bbb7 Mon Sep 17 00:00:00 2001 From: Evgeny Kapaev Date: Tue, 15 Oct 2013 21:42:52 +0400 Subject: speedstep-centrino: Remove unnecessary braces As per coding style, braces {} are not necessary for single statement block Signed-off-by: Evgeny Kapaev Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index 6b882c7..25e45f8 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -371,9 +371,8 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) return -ENODEV; } - if (centrino_cpu_init_table(policy)) { + if (centrino_cpu_init_table(policy)) return -ENODEV; - } /* Check to see if Enhanced SpeedStep is enabled, and try to enable it if not. */ -- cgit v0.10.2 From e23feb16685a8d1c62aa5bba7ebcddf4ba57ffcb Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 11 Oct 2013 16:54:55 -0700 Subject: PowerCap: Documentation Added power cap framework documentation. This explains the use of power capping framework, sysfs and programming interface. There are two documents: - Documentation/power/powercap/powercap.txt : Explains use case and APIs. - Documentation/ABI/testing/sysfs-class-powercap: Explains ABIs. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jacob Pan Signed-off-by: Arjan van de Ven Reviewed-by: Rafael J. Wysocki Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/Documentation/ABI/testing/sysfs-class-powercap b/Documentation/ABI/testing/sysfs-class-powercap new file mode 100644 index 0000000..db3b3ff --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-powercap @@ -0,0 +1,152 @@ +What: /sys/class/powercap/ +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + The powercap/ class sub directory belongs to the power cap + subsystem. Refer to + Documentation/power/powercap/powercap.txt for details. + +What: /sys/class/powercap/ +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + A is a unique name under /sys/class/powercap. + Here determines how the power is going to be + controlled. A can contain multiple power zones. + +What: /sys/class/powercap//enabled +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + This allows to enable/disable power capping for a "control type". + This status affects every power zone using this "control_type. + +What: /sys/class/powercap// +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + A power zone is a single or a collection of devices, which can + be independently monitored and controlled. A power zone sysfs + entry is qualified with the name of the . + E.g. intel-rapl:0:1:1. + +What: /sys/class/powercap/// +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Power zones may be organized in a hierarchy in which child + power zones provide monitoring and control for a subset of + devices under the parent. For example, if there is a parent + power zone for a whole CPU package, each CPU core in it can + be a child power zone. + +What: /sys/class/powercap/...//name +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Specifies the name of this power zone. + +What: /sys/class/powercap/...//energy_uj +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Current energy counter in micro-joules. Write "0" to reset. + If the counter can not be reset, then this attribute is + read-only. + +What: /sys/class/powercap/...//max_energy_range_uj +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Range of the above energy counter in micro-joules. + + +What: /sys/class/powercap/...//power_uw +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Current power in micro-watts. + +What: /sys/class/powercap/...//max_power_range_uw +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Range of the above power value in micro-watts. + +What: /sys/class/powercap/...//constraint_X_name +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Each power zone can define one or more constraints. Each + constraint can have an optional name. Here "X" can have values + from 0 to max integer. + +What: /sys/class/powercap/...//constraint_X_power_limit_uw +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Power limit in micro-watts should be applicable for + the time window specified by "constraint_X_time_window_us". + Here "X" can have values from 0 to max integer. + +What: /sys/class/powercap/...//constraint_X_time_window_us +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Time window in micro seconds. This is used along with + constraint_X_power_limit_uw to define a power constraint. + Here "X" can have values from 0 to max integer. + + +What: /sys/class/powercap//.../constraint_X_max_power_uw +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Maximum allowed power in micro watts for this constraint. + Here "X" can have values from 0 to max integer. + +What: /sys/class/powercap//.../constraint_X_min_power_uw +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Minimum allowed power in micro watts for this constraint. + Here "X" can have values from 0 to max integer. + +What: /sys/class/powercap/...//constraint_X_max_time_window_us +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Maximum allowed time window in micro seconds for this + constraint. Here "X" can have values from 0 to max integer. + +What: /sys/class/powercap/...//constraint_X_min_time_window_us +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description: + Minimum allowed time window in micro seconds for this + constraint. Here "X" can have values from 0 to max integer. + +What: /sys/class/powercap/...//enabled +Date: September 2013 +KernelVersion: 3.13 +Contact: linux-pm@vger.kernel.org +Description + This allows to enable/disable power capping at power zone level. + This applies to current power zone and its children. diff --git a/Documentation/power/powercap/powercap.txt b/Documentation/power/powercap/powercap.txt new file mode 100644 index 0000000..1e6ef16 --- /dev/null +++ b/Documentation/power/powercap/powercap.txt @@ -0,0 +1,236 @@ +Power Capping Framework +================================== + +The power capping framework provides a consistent interface between the kernel +and the user space that allows power capping drivers to expose the settings to +user space in a uniform way. + +Terminology +========================= +The framework exposes power capping devices to user space via sysfs in the +form of a tree of objects. The objects at the root level of the tree represent +'control types', which correspond to different methods of power capping. For +example, the intel-rapl control type represents the Intel "Running Average +Power Limit" (RAPL) technology, whereas the 'idle-injection' control type +corresponds to the use of idle injection for controlling power. + +Power zones represent different parts of the system, which can be controlled and +monitored using the power capping method determined by the control type the +given zone belongs to. They each contain attributes for monitoring power, as +well as controls represented in the form of power constraints. If the parts of +the system represented by different power zones are hierarchical (that is, one +bigger part consists of multiple smaller parts that each have their own power +controls), those power zones may also be organized in a hierarchy with one +parent power zone containing multiple subzones and so on to reflect the power +control topology of the system. In that case, it is possible to apply power +capping to a set of devices together using the parent power zone and if more +fine grained control is required, it can be applied through the subzones. + + +Example sysfs interface tree: + +/sys/devices/virtual/powercap +??? intel-rapl + ??? intel-rapl:0 + ?   ??? constraint_0_name + ?   ??? constraint_0_power_limit_uw + ?   ??? constraint_0_time_window_us + ?   ??? constraint_1_name + ?   ??? constraint_1_power_limit_uw + ?   ??? constraint_1_time_window_us + ?   ??? device -> ../../intel-rapl + ?   ??? energy_uj + ?   ??? intel-rapl:0:0 + ?   ?   ??? constraint_0_name + ?   ?   ??? constraint_0_power_limit_uw + ?   ?   ??? constraint_0_time_window_us + ?   ?   ??? constraint_1_name + ?   ?   ??? constraint_1_power_limit_uw + ?   ?   ??? constraint_1_time_window_us + ?   ?   ??? device -> ../../intel-rapl:0 + ?   ?   ??? energy_uj + ?   ?   ??? max_energy_range_uj + ?   ?   ??? name + ?   ?   ??? enabled + ?   ?   ??? power + ?   ?   ?   ??? async + ?   ?   ?   [] + ?   ?   ??? subsystem -> ../../../../../../class/power_cap + ?   ?   ??? uevent + ?   ??? intel-rapl:0:1 + ?   ?   ??? constraint_0_name + ?   ?   ??? constraint_0_power_limit_uw + ?   ?   ??? constraint_0_time_window_us + ?   ?   ??? constraint_1_name + ?   ?   ??? constraint_1_power_limit_uw + ?   ?   ??? constraint_1_time_window_us + ?   ?   ??? device -> ../../intel-rapl:0 + ?   ?   ??? energy_uj + ?   ?   ??? max_energy_range_uj + ?   ?   ??? name + ?   ?   ??? enabled + ?   ?   ??? power + ?   ?   ?   ??? async + ?   ?   ?   [] + ?   ?   ??? subsystem -> ../../../../../../class/power_cap + ?   ?   ??? uevent + ?   ??? max_energy_range_uj + ?   ??? max_power_range_uw + ?   ??? name + ?   ??? enabled + ?   ??? power + ?   ?   ??? async + ?   ?   [] + ?   ??? subsystem -> ../../../../../class/power_cap + ?   ??? enabled + ?   ??? uevent + ??? intel-rapl:1 + ?   ??? constraint_0_name + ?   ??? constraint_0_power_limit_uw + ?   ??? constraint_0_time_window_us + ?   ??? constraint_1_name + ?   ??? constraint_1_power_limit_uw + ?   ??? constraint_1_time_window_us + ?   ??? device -> ../../intel-rapl + ?   ??? energy_uj + ?   ??? intel-rapl:1:0 + ?   ?   ??? constraint_0_name + ?   ?   ??? constraint_0_power_limit_uw + ?   ?   ??? constraint_0_time_window_us + ?   ?   ??? constraint_1_name + ?   ?   ??? constraint_1_power_limit_uw + ?   ?   ??? constraint_1_time_window_us + ?   ?   ??? device -> ../../intel-rapl:1 + ?   ?   ??? energy_uj + ?   ?   ??? max_energy_range_uj + ?   ?   ??? name + ?   ?   ??? enabled + ?   ?   ??? power + ?   ?   ?   ??? async + ?   ?   ?   [] + ?   ?   ??? subsystem -> ../../../../../../class/power_cap + ?   ?   ??? uevent + ?   ??? intel-rapl:1:1 + ?   ?   ??? constraint_0_name + ?   ?   ??? constraint_0_power_limit_uw + ?   ?   ??? constraint_0_time_window_us + ?   ?   ??? constraint_1_name + ?   ?   ??? constraint_1_power_limit_uw + ?   ?   ??? constraint_1_time_window_us + ?   ?   ??? device -> ../../intel-rapl:1 + ?   ?   ??? energy_uj + ?   ?   ??? max_energy_range_uj + ?   ?   ??? name + ?   ?   ??? enabled + ?   ?   ??? power + ?   ?   ?   ??? async + ?   ?   ?   [] + ?   ?   ??? subsystem -> ../../../../../../class/power_cap + ?   ?   ??? uevent + ?   ??? max_energy_range_uj + ?   ??? max_power_range_uw + ?   ??? name + ?   ??? enabled + ?   ??? power + ?   ?   ??? async + ?   ?   [] + ?   ??? subsystem -> ../../../../../class/power_cap + ?   ??? uevent + ??? power + ?   ??? async + ?   [] + ??? subsystem -> ../../../../class/power_cap + ??? enabled + ??? uevent + +The above example illustrates a case in which the Intel RAPL technology, +available in Intel® IA-64 and IA-32 Processor Architectures, is used. There is one +control type called intel-rapl which contains two power zones, intel-rapl:0 and +intel-rapl:1, representing CPU packages. Each of these power zones contains +two subzones, intel-rapl:j:0 and intel-rapl:j:1 (j = 0, 1), representing the +"core" and the "uncore" parts of the given CPU package, respectively. All of +the zones and subzones contain energy monitoring attributes (energy_uj, +max_energy_range_uj) and constraint attributes (constraint_*) allowing controls +to be applied (the constraints in the 'package' power zones apply to the whole +CPU packages and the subzone constraints only apply to the respective parts of +the given package individually). Since Intel RAPL doesn't provide instantaneous +power value, there is no power_uw attribute. + +In addition to that, each power zone contains a name attribute, allowing the +part of the system represented by that zone to be identified. +For example: + +cat /sys/class/power_cap/intel-rapl/intel-rapl:0/name +package-0 + +The Intel RAPL technology allows two constraints, short term and long term, +with two different time windows to be applied to each power zone. Thus for +each zone there are 2 attributes representing the constraint names, 2 power +limits and 2 attributes representing the sizes of the time windows. Such that, +constraint_j_* attributes correspond to the jth constraint (j = 0,1). + +For example: + constraint_0_name + constraint_0_power_limit_uw + constraint_0_time_window_us + constraint_1_name + constraint_1_power_limit_uw + constraint_1_time_window_us + +Power Zone Attributes +================================= +Monitoring attributes +---------------------- + +energy_uj (rw): Current energy counter in micro joules. Write "0" to reset. +If the counter can not be reset, then this attribute is read only. + +max_energy_range_uj (ro): Range of the above energy counter in micro-joules. + +power_uw (ro): Current power in micro watts. + +max_power_range_uw (ro): Range of the above power value in micro-watts. + +name (ro): Name of this power zone. + +It is possible that some domains have both power ranges and energy counter ranges; +however, only one is mandatory. + +Constraints +---------------- +constraint_X_power_limit_uw (rw): Power limit in micro watts, which should be +applicable for the time window specified by "constraint_X_time_window_us". + +constraint_X_time_window_us (rw): Time window in micro seconds. + +constraint_X_name (ro): An optional name of the constraint + +constraint_X_max_power_uw(ro): Maximum allowed power in micro watts. + +constraint_X_min_power_uw(ro): Minimum allowed power in micro watts. + +constraint_X_max_time_window_us(ro): Maximum allowed time window in micro seconds. + +constraint_X_min_time_window_us(ro): Minimum allowed time window in micro seconds. + +Except power_limit_uw and time_window_us other fields are optional. + +Common zone and control type attributes +---------------------------------------- +enabled (rw): Enable/Disable controls at zone level or for all zones using +a control type. + +Power Cap Client Driver Interface +================================== +The API summary: + +Call powercap_register_control_type() to register control type object. +Call powercap_register_zone() to register a power zone (under a given +control type), either as a top-level power zone or as a subzone of another +power zone registered earlier. +The number of constraints in a power zone and the corresponding callbacks have +to be defined prior to calling powercap_register_zone() to register that zone. + +To Free a power zone call powercap_unregister_zone(). +To free a control type object call powercap_unregister_control_type(). +Detailed API can be generated using kernel-doc on include/linux/powercap.h. -- cgit v0.10.2 From 75d2364ea0cab3a95be3f8d1f8dabd20ac4b1b2a Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 11 Oct 2013 16:54:56 -0700 Subject: PowerCap: Add class driver The power capping framework providing a consistent interface between the kernel and user space that allows power capping drivers to expose their settings to user space in a uniform way. The overall design of the framework is described in the documentation added by the previous patch in this series. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jacob Pan Reviewed-by: Rafael J. Wysocki Signed-off-by: Rafael J. Wysocki diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig new file mode 100644 index 0000000..a37055e --- /dev/null +++ b/drivers/powercap/Kconfig @@ -0,0 +1,19 @@ +# +# Generic power capping sysfs interface configuration +# + +menuconfig POWERCAP + bool "Generic powercap sysfs driver" + help + The power capping sysfs interface allows kernel subsystems to expose power + capping settings to user space in a consistent way. Usually, it consists + of multiple control types that determine which settings may be exposed and + power zones representing parts of the system that can be subject to power + capping. + + If you want this code to be compiled in, say Y here. + +if POWERCAP +# Client driver configurations go here. + +endif diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile new file mode 100644 index 0000000..6defbc8 --- /dev/null +++ b/drivers/powercap/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_POWERCAP) += powercap_sys.o diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c new file mode 100644 index 0000000..c22fa4c --- /dev/null +++ b/drivers/powercap/powercap_sys.c @@ -0,0 +1,683 @@ +/* + * Power capping class + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc. + * + */ + +#include +#include +#include +#include +#include + +#define to_powercap_zone(n) container_of(n, struct powercap_zone, dev) +#define to_powercap_control_type(n) \ + container_of(n, struct powercap_control_type, dev) + +/* Power zone show function */ +#define define_power_zone_show(_attr) \ +static ssize_t _attr##_show(struct device *dev, \ + struct device_attribute *dev_attr,\ + char *buf) \ +{ \ + u64 value; \ + ssize_t len = -EINVAL; \ + struct powercap_zone *power_zone = to_powercap_zone(dev); \ + \ + if (power_zone->ops->get_##_attr) { \ + if (!power_zone->ops->get_##_attr(power_zone, &value)) \ + len = sprintf(buf, "%lld\n", value); \ + } \ + \ + return len; \ +} + +/* The only meaningful input is 0 (reset), others are silently ignored */ +#define define_power_zone_store(_attr) \ +static ssize_t _attr##_store(struct device *dev,\ + struct device_attribute *dev_attr, \ + const char *buf, size_t count) \ +{ \ + int err; \ + struct powercap_zone *power_zone = to_powercap_zone(dev); \ + u64 value; \ + \ + err = kstrtoull(buf, 10, &value); \ + if (err) \ + return -EINVAL; \ + if (value) \ + return count; \ + if (power_zone->ops->reset_##_attr) { \ + if (!power_zone->ops->reset_##_attr(power_zone)) \ + return count; \ + } \ + \ + return -EINVAL; \ +} + +/* Power zone constraint show function */ +#define define_power_zone_constraint_show(_attr) \ +static ssize_t show_constraint_##_attr(struct device *dev, \ + struct device_attribute *dev_attr,\ + char *buf) \ +{ \ + u64 value; \ + ssize_t len = -ENODATA; \ + struct powercap_zone *power_zone = to_powercap_zone(dev); \ + int id; \ + struct powercap_zone_constraint *pconst;\ + \ + if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \ + return -EINVAL; \ + if (id >= power_zone->const_id_cnt) \ + return -EINVAL; \ + pconst = &power_zone->constraints[id]; \ + if (pconst && pconst->ops && pconst->ops->get_##_attr) { \ + if (!pconst->ops->get_##_attr(power_zone, id, &value)) \ + len = sprintf(buf, "%lld\n", value); \ + } \ + \ + return len; \ +} + +/* Power zone constraint store function */ +#define define_power_zone_constraint_store(_attr) \ +static ssize_t store_constraint_##_attr(struct device *dev,\ + struct device_attribute *dev_attr, \ + const char *buf, size_t count) \ +{ \ + int err; \ + u64 value; \ + struct powercap_zone *power_zone = to_powercap_zone(dev); \ + int id; \ + struct powercap_zone_constraint *pconst;\ + \ + if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \ + return -EINVAL; \ + if (id >= power_zone->const_id_cnt) \ + return -EINVAL; \ + pconst = &power_zone->constraints[id]; \ + err = kstrtoull(buf, 10, &value); \ + if (err) \ + return -EINVAL; \ + if (pconst && pconst->ops && pconst->ops->set_##_attr) { \ + if (!pconst->ops->set_##_attr(power_zone, id, value)) \ + return count; \ + } \ + \ + return -ENODATA; \ +} + +/* Power zone information callbacks */ +define_power_zone_show(power_uw); +define_power_zone_show(max_power_range_uw); +define_power_zone_show(energy_uj); +define_power_zone_store(energy_uj); +define_power_zone_show(max_energy_range_uj); + +/* Power zone attributes */ +static DEVICE_ATTR_RO(max_power_range_uw); +static DEVICE_ATTR_RO(power_uw); +static DEVICE_ATTR_RO(max_energy_range_uj); +static DEVICE_ATTR_RW(energy_uj); + +/* Power zone constraint attributes callbacks */ +define_power_zone_constraint_show(power_limit_uw); +define_power_zone_constraint_store(power_limit_uw); +define_power_zone_constraint_show(time_window_us); +define_power_zone_constraint_store(time_window_us); +define_power_zone_constraint_show(max_power_uw); +define_power_zone_constraint_show(min_power_uw); +define_power_zone_constraint_show(max_time_window_us); +define_power_zone_constraint_show(min_time_window_us); + +/* For one time seeding of constraint device attributes */ +struct powercap_constraint_attr { + struct device_attribute power_limit_attr; + struct device_attribute time_window_attr; + struct device_attribute max_power_attr; + struct device_attribute min_power_attr; + struct device_attribute max_time_window_attr; + struct device_attribute min_time_window_attr; + struct device_attribute name_attr; +}; + +static struct powercap_constraint_attr + constraint_attrs[MAX_CONSTRAINTS_PER_ZONE]; + +/* A list of powercap control_types */ +static LIST_HEAD(powercap_cntrl_list); +/* Mutex to protect list of powercap control_types */ +static DEFINE_MUTEX(powercap_cntrl_list_lock); + +#define POWERCAP_CONSTRAINT_NAME_LEN 30 /* Some limit to avoid overflow */ +static ssize_t show_constraint_name(struct device *dev, + struct device_attribute *dev_attr, + char *buf) +{ + const char *name; + struct powercap_zone *power_zone = to_powercap_zone(dev); + int id; + ssize_t len = -ENODATA; + struct powercap_zone_constraint *pconst; + + if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) + return -EINVAL; + if (id >= power_zone->const_id_cnt) + return -EINVAL; + pconst = &power_zone->constraints[id]; + + if (pconst && pconst->ops && pconst->ops->get_name) { + name = pconst->ops->get_name(power_zone, id); + if (name) { + snprintf(buf, POWERCAP_CONSTRAINT_NAME_LEN, + "%s\n", name); + buf[POWERCAP_CONSTRAINT_NAME_LEN] = '\0'; + len = strlen(buf); + } + } + + return len; +} + +static int create_constraint_attribute(int id, const char *name, + int mode, + struct device_attribute *dev_attr, + ssize_t (*show)(struct device *, + struct device_attribute *, char *), + ssize_t (*store)(struct device *, + struct device_attribute *, + const char *, size_t) + ) +{ + + dev_attr->attr.name = kasprintf(GFP_KERNEL, "constraint_%d_%s", + id, name); + if (!dev_attr->attr.name) + return -ENOMEM; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; + + return 0; +} + +static void free_constraint_attributes(void) +{ + int i; + + for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) { + kfree(constraint_attrs[i].power_limit_attr.attr.name); + kfree(constraint_attrs[i].time_window_attr.attr.name); + kfree(constraint_attrs[i].name_attr.attr.name); + kfree(constraint_attrs[i].max_power_attr.attr.name); + kfree(constraint_attrs[i].min_power_attr.attr.name); + kfree(constraint_attrs[i].max_time_window_attr.attr.name); + kfree(constraint_attrs[i].min_time_window_attr.attr.name); + } +} + +static int seed_constraint_attributes(void) +{ + int i; + int ret; + + for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) { + ret = create_constraint_attribute(i, "power_limit_uw", + S_IWUSR | S_IRUGO, + &constraint_attrs[i].power_limit_attr, + show_constraint_power_limit_uw, + store_constraint_power_limit_uw); + if (ret) + goto err_alloc; + ret = create_constraint_attribute(i, "time_window_us", + S_IWUSR | S_IRUGO, + &constraint_attrs[i].time_window_attr, + show_constraint_time_window_us, + store_constraint_time_window_us); + if (ret) + goto err_alloc; + ret = create_constraint_attribute(i, "name", S_IRUGO, + &constraint_attrs[i].name_attr, + show_constraint_name, + NULL); + if (ret) + goto err_alloc; + ret = create_constraint_attribute(i, "max_power_uw", S_IRUGO, + &constraint_attrs[i].max_power_attr, + show_constraint_max_power_uw, + NULL); + if (ret) + goto err_alloc; + ret = create_constraint_attribute(i, "min_power_uw", S_IRUGO, + &constraint_attrs[i].min_power_attr, + show_constraint_min_power_uw, + NULL); + if (ret) + goto err_alloc; + ret = create_constraint_attribute(i, "max_time_window_us", + S_IRUGO, + &constraint_attrs[i].max_time_window_attr, + show_constraint_max_time_window_us, + NULL); + if (ret) + goto err_alloc; + ret = create_constraint_attribute(i, "min_time_window_us", + S_IRUGO, + &constraint_attrs[i].min_time_window_attr, + show_constraint_min_time_window_us, + NULL); + if (ret) + goto err_alloc; + + } + + return 0; + +err_alloc: + free_constraint_attributes(); + + return ret; +} + +static int create_constraints(struct powercap_zone *power_zone, + int nr_constraints, + struct powercap_zone_constraint_ops *const_ops) +{ + int i; + int ret = 0; + int count; + struct powercap_zone_constraint *pconst; + + if (!power_zone || !const_ops || !const_ops->get_power_limit_uw || + !const_ops->set_power_limit_uw || + !const_ops->get_time_window_us || + !const_ops->set_time_window_us) + return -EINVAL; + + count = power_zone->zone_attr_count; + for (i = 0; i < nr_constraints; ++i) { + pconst = &power_zone->constraints[i]; + pconst->ops = const_ops; + pconst->id = power_zone->const_id_cnt; + power_zone->const_id_cnt++; + power_zone->zone_dev_attrs[count++] = + &constraint_attrs[i].power_limit_attr.attr; + power_zone->zone_dev_attrs[count++] = + &constraint_attrs[i].time_window_attr.attr; + if (pconst->ops->get_name) + power_zone->zone_dev_attrs[count++] = + &constraint_attrs[i].name_attr.attr; + if (pconst->ops->get_max_power_uw) + power_zone->zone_dev_attrs[count++] = + &constraint_attrs[i].max_power_attr.attr; + if (pconst->ops->get_min_power_uw) + power_zone->zone_dev_attrs[count++] = + &constraint_attrs[i].min_power_attr.attr; + if (pconst->ops->get_max_time_window_us) + power_zone->zone_dev_attrs[count++] = + &constraint_attrs[i].max_time_window_attr.attr; + if (pconst->ops->get_min_time_window_us) + power_zone->zone_dev_attrs[count++] = + &constraint_attrs[i].min_time_window_attr.attr; + } + power_zone->zone_attr_count = count; + + return ret; +} + +static bool control_type_valid(void *control_type) +{ + struct powercap_control_type *pos = NULL; + bool found = false; + + mutex_lock(&powercap_cntrl_list_lock); + + list_for_each_entry(pos, &powercap_cntrl_list, node) { + if (pos == control_type) { + found = true; + break; + } + } + mutex_unlock(&powercap_cntrl_list_lock); + + return found; +} + +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct powercap_zone *power_zone = to_powercap_zone(dev); + + return sprintf(buf, "%s\n", power_zone->name); +} + +static DEVICE_ATTR_RO(name); + +/* Create zone and attributes in sysfs */ +static void create_power_zone_common_attributes( + struct powercap_zone *power_zone) +{ + int count = 0; + + power_zone->zone_dev_attrs[count++] = &dev_attr_name.attr; + if (power_zone->ops->get_max_energy_range_uj) + power_zone->zone_dev_attrs[count++] = + &dev_attr_max_energy_range_uj.attr; + if (power_zone->ops->get_energy_uj) + power_zone->zone_dev_attrs[count++] = + &dev_attr_energy_uj.attr; + if (power_zone->ops->get_power_uw) + power_zone->zone_dev_attrs[count++] = + &dev_attr_power_uw.attr; + if (power_zone->ops->get_max_power_range_uw) + power_zone->zone_dev_attrs[count++] = + &dev_attr_max_power_range_uw.attr; + power_zone->zone_dev_attrs[count] = NULL; + power_zone->zone_attr_count = count; +} + +static void powercap_release(struct device *dev) +{ + bool allocated; + + if (dev->parent) { + struct powercap_zone *power_zone = to_powercap_zone(dev); + + /* Store flag as the release() may free memory */ + allocated = power_zone->allocated; + /* Remove id from parent idr struct */ + idr_remove(power_zone->parent_idr, power_zone->id); + /* Destroy idrs allocated for this zone */ + idr_destroy(&power_zone->idr); + kfree(power_zone->name); + kfree(power_zone->zone_dev_attrs); + kfree(power_zone->constraints); + if (power_zone->ops->release) + power_zone->ops->release(power_zone); + if (allocated) + kfree(power_zone); + } else { + struct powercap_control_type *control_type = + to_powercap_control_type(dev); + + /* Store flag as the release() may free memory */ + allocated = control_type->allocated; + idr_destroy(&control_type->idr); + mutex_destroy(&control_type->lock); + if (control_type->ops && control_type->ops->release) + control_type->ops->release(control_type); + if (allocated) + kfree(control_type); + } +} + +static ssize_t enabled_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + bool mode = true; + + /* Default is enabled */ + if (dev->parent) { + struct powercap_zone *power_zone = to_powercap_zone(dev); + if (power_zone->ops->get_enable) + if (power_zone->ops->get_enable(power_zone, &mode)) + mode = false; + } else { + struct powercap_control_type *control_type = + to_powercap_control_type(dev); + if (control_type->ops && control_type->ops->get_enable) + if (control_type->ops->get_enable(control_type, &mode)) + mode = false; + } + + return sprintf(buf, "%d\n", mode); +} + +static ssize_t enabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + bool mode; + + if (strtobool(buf, &mode)) + return -EINVAL; + if (dev->parent) { + struct powercap_zone *power_zone = to_powercap_zone(dev); + if (power_zone->ops->set_enable) + if (!power_zone->ops->set_enable(power_zone, mode)) + return len; + } else { + struct powercap_control_type *control_type = + to_powercap_control_type(dev); + if (control_type->ops && control_type->ops->set_enable) + if (!control_type->ops->set_enable(control_type, mode)) + return len; + } + + return -ENOSYS; +} + +static struct device_attribute powercap_def_attrs[] = { + __ATTR(enabled, S_IWUSR | S_IRUGO, enabled_show, + enabled_store), + __ATTR_NULL +}; + +static struct class powercap_class = { + .name = "powercap", + .dev_release = powercap_release, + .dev_attrs = powercap_def_attrs, +}; + +struct powercap_zone *powercap_register_zone( + struct powercap_zone *power_zone, + struct powercap_control_type *control_type, + const char *name, + struct powercap_zone *parent, + const struct powercap_zone_ops *ops, + int nr_constraints, + struct powercap_zone_constraint_ops *const_ops) +{ + int result; + int nr_attrs; + + if (!name || !control_type || !ops || + nr_constraints > MAX_CONSTRAINTS_PER_ZONE || + (!ops->get_energy_uj && !ops->get_power_uw) || + !control_type_valid(control_type)) + return ERR_PTR(-EINVAL); + + if (power_zone) { + if (!ops->release) + return ERR_PTR(-EINVAL); + memset(power_zone, 0, sizeof(*power_zone)); + } else { + power_zone = kzalloc(sizeof(*power_zone), GFP_KERNEL); + if (!power_zone) + return ERR_PTR(-ENOMEM); + power_zone->allocated = true; + } + power_zone->ops = ops; + power_zone->control_type_inst = control_type; + if (!parent) { + power_zone->dev.parent = &control_type->dev; + power_zone->parent_idr = &control_type->idr; + } else { + power_zone->dev.parent = &parent->dev; + power_zone->parent_idr = &parent->idr; + } + power_zone->dev.class = &powercap_class; + + mutex_lock(&control_type->lock); + /* Using idr to get the unique id */ + result = idr_alloc(power_zone->parent_idr, NULL, 0, 0, GFP_KERNEL); + if (result < 0) + goto err_idr_alloc; + + power_zone->id = result; + idr_init(&power_zone->idr); + power_zone->name = kstrdup(name, GFP_KERNEL); + if (!power_zone->name) + goto err_name_alloc; + dev_set_name(&power_zone->dev, "%s:%x", + dev_name(power_zone->dev.parent), + power_zone->id); + power_zone->constraints = kzalloc(sizeof(*power_zone->constraints) * + nr_constraints, GFP_KERNEL); + if (!power_zone->constraints) + goto err_const_alloc; + + nr_attrs = nr_constraints * POWERCAP_CONSTRAINTS_ATTRS + + POWERCAP_ZONE_MAX_ATTRS + 1; + power_zone->zone_dev_attrs = kzalloc(sizeof(void *) * + nr_attrs, GFP_KERNEL); + if (!power_zone->zone_dev_attrs) + goto err_attr_alloc; + create_power_zone_common_attributes(power_zone); + result = create_constraints(power_zone, nr_constraints, const_ops); + if (result) + goto err_dev_ret; + + power_zone->zone_dev_attrs[power_zone->zone_attr_count] = NULL; + power_zone->dev_zone_attr_group.attrs = power_zone->zone_dev_attrs; + power_zone->dev_attr_groups[0] = &power_zone->dev_zone_attr_group; + power_zone->dev_attr_groups[1] = NULL; + power_zone->dev.groups = power_zone->dev_attr_groups; + result = device_register(&power_zone->dev); + if (result) + goto err_dev_ret; + + control_type->nr_zones++; + mutex_unlock(&control_type->lock); + + return power_zone; + +err_dev_ret: + kfree(power_zone->zone_dev_attrs); +err_attr_alloc: + kfree(power_zone->constraints); +err_const_alloc: + kfree(power_zone->name); +err_name_alloc: + idr_remove(power_zone->parent_idr, power_zone->id); +err_idr_alloc: + if (power_zone->allocated) + kfree(power_zone); + mutex_unlock(&control_type->lock); + + return ERR_PTR(result); +} +EXPORT_SYMBOL_GPL(powercap_register_zone); + +int powercap_unregister_zone(struct powercap_control_type *control_type, + struct powercap_zone *power_zone) +{ + if (!power_zone || !control_type) + return -EINVAL; + + mutex_lock(&control_type->lock); + control_type->nr_zones--; + mutex_unlock(&control_type->lock); + + device_unregister(&power_zone->dev); + + return 0; +} +EXPORT_SYMBOL_GPL(powercap_unregister_zone); + +struct powercap_control_type *powercap_register_control_type( + struct powercap_control_type *control_type, + const char *name, + const struct powercap_control_type_ops *ops) +{ + int result; + + if (!name) + return ERR_PTR(-EINVAL); + if (control_type) { + if (!ops || !ops->release) + return ERR_PTR(-EINVAL); + memset(control_type, 0, sizeof(*control_type)); + } else { + control_type = kzalloc(sizeof(*control_type), GFP_KERNEL); + if (!control_type) + return ERR_PTR(-ENOMEM); + control_type->allocated = true; + } + mutex_init(&control_type->lock); + control_type->ops = ops; + INIT_LIST_HEAD(&control_type->node); + control_type->dev.class = &powercap_class; + dev_set_name(&control_type->dev, name); + result = device_register(&control_type->dev); + if (result) { + if (control_type->allocated) + kfree(control_type); + return ERR_PTR(result); + } + idr_init(&control_type->idr); + + mutex_lock(&powercap_cntrl_list_lock); + list_add_tail(&control_type->node, &powercap_cntrl_list); + mutex_unlock(&powercap_cntrl_list_lock); + + return control_type; +} +EXPORT_SYMBOL_GPL(powercap_register_control_type); + +int powercap_unregister_control_type(struct powercap_control_type *control_type) +{ + struct powercap_control_type *pos = NULL; + + if (control_type->nr_zones) { + dev_err(&control_type->dev, "Zones of this type still not freed\n"); + return -EINVAL; + } + mutex_lock(&powercap_cntrl_list_lock); + list_for_each_entry(pos, &powercap_cntrl_list, node) { + if (pos == control_type) { + list_del(&control_type->node); + mutex_unlock(&powercap_cntrl_list_lock); + device_unregister(&control_type->dev); + return 0; + } + } + mutex_unlock(&powercap_cntrl_list_lock); + + return -ENODEV; +} +EXPORT_SYMBOL_GPL(powercap_unregister_control_type); + +static int __init powercap_init(void) +{ + int result = 0; + + result = seed_constraint_attributes(); + if (result) + return result; + + result = class_register(&powercap_class); + + return result; +} + +device_initcall(powercap_init); + +MODULE_DESCRIPTION("PowerCap sysfs Driver"); +MODULE_AUTHOR("Srinivas Pandruvada "); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/powercap.h b/include/linux/powercap.h new file mode 100644 index 0000000..4e25041 --- /dev/null +++ b/include/linux/powercap.h @@ -0,0 +1,325 @@ +/* + * powercap.h: Data types and headers for sysfs power capping interface + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc. + * + */ + +#ifndef __POWERCAP_H__ +#define __POWERCAP_H__ + +#include +#include + +/* + * A power cap class device can contain multiple powercap control_types. + * Each control_type can have multiple power zones, which can be independently + * controlled. Each power zone can have one or more constraints. + */ + +struct powercap_control_type; +struct powercap_zone; +struct powercap_zone_constraint; + +/** + * struct powercap_control_type_ops - Define control type callbacks + * @set_enable: Enable/Disable whole control type. + * Default is enabled. But this callback allows all zones + * to be in disable state and remove any applied power + * limits. If disabled power zone can only be monitored + * not controlled. + * @get_enable: get Enable/Disable status. + * @release: Callback to inform that last reference to this + * control type is closed. So it is safe to free data + * structure associated with this control type. + * This callback is mandatory if the client own memory + * for the control type. + * + * This structure defines control type callbacks to be implemented by client + * drivers + */ +struct powercap_control_type_ops { + int (*set_enable) (struct powercap_control_type *, bool mode); + int (*get_enable) (struct powercap_control_type *, bool *mode); + int (*release) (struct powercap_control_type *); +}; + +/** + * struct powercap_control_type- Defines a powercap control_type + * @name: name of control_type + * @dev: device for this control_type + * @idr: idr to have unique id for its child + * @root_node: Root holding power zones for this control_type + * @ops: Pointer to callback struct + * @node_lock: mutex for control type + * @allocated: This is possible that client owns the memory + * used by this structure. In this case + * this flag is set to false by framework to + * prevent deallocation during release process. + * Otherwise this flag is set to true. + * @ctrl_inst: link to the control_type list + * + * Defines powercap control_type. This acts as a container for power + * zones, which use same method to control power. E.g. RAPL, RAPL-PCI etc. + * All fields are private and should not be used by client drivers. + */ +struct powercap_control_type { + struct device dev; + struct idr idr; + int nr_zones; + const struct powercap_control_type_ops *ops; + struct mutex lock; + bool allocated; + struct list_head node; +}; + +/** + * struct powercap_zone_ops - Define power zone callbacks + * @get_max_energy_range_uj: Get maximum range of energy counter in + * micro-joules. + * @get_energy_uj: Get current energy counter in micro-joules. + * @reset_energy_uj: Reset micro-joules energy counter. + * @get_max_power_range_uw: Get maximum range of power counter in + * micro-watts. + * @get_power_uw: Get current power counter in micro-watts. + * @set_enable: Enable/Disable power zone controls. + * Default is enabled. + * @get_enable: get Enable/Disable status. + * @release: Callback to inform that last reference to this + * control type is closed. So it is safe to free + * data structure associated with this + * control type. Mandatory, if client driver owns + * the power_zone memory. + * + * This structure defines zone callbacks to be implemented by client drivers. + * Client drives can define both energy and power related callbacks. But at + * the least one type (either power or energy) is mandatory. Client drivers + * should handle mutual exclusion, if required in callbacks. + */ +struct powercap_zone_ops { + int (*get_max_energy_range_uj) (struct powercap_zone *, u64 *); + int (*get_energy_uj) (struct powercap_zone *, u64 *); + int (*reset_energy_uj) (struct powercap_zone *); + int (*get_max_power_range_uw) (struct powercap_zone *, u64 *); + int (*get_power_uw) (struct powercap_zone *, u64 *); + int (*set_enable) (struct powercap_zone *, bool mode); + int (*get_enable) (struct powercap_zone *, bool *mode); + int (*release) (struct powercap_zone *); +}; + +#define POWERCAP_ZONE_MAX_ATTRS 6 +#define POWERCAP_CONSTRAINTS_ATTRS 8 +#define MAX_CONSTRAINTS_PER_ZONE 10 +/** + * struct powercap_zone- Defines instance of a power cap zone + * @id: Unique id + * @name: Power zone name. + * @control_type_inst: Control type instance for this zone. + * @ops: Pointer to the zone operation structure. + * @dev: Instance of a device. + * @const_id_cnt: Number of constraint defined. + * @idr: Instance to an idr entry for children zones. + * @parent_idr: To remove reference from the parent idr. + * @private_data: Private data pointer if any for this zone. + * @zone_dev_attrs: Attributes associated with this device. + * @zone_attr_count: Attribute count. + * @dev_zone_attr_group: Attribute group for attributes. + * @dev_attr_groups: Attribute group store to register with device. + * @allocated: This is possible that client owns the memory + * used by this structure. In this case + * this flag is set to false by framework to + * prevent deallocation during release process. + * Otherwise this flag is set to true. + * @constraint_ptr: List of constraints for this zone. + * + * This defines a power zone instance. The fields of this structure are + * private, and should not be used by client drivers. + */ +struct powercap_zone { + int id; + char *name; + void *control_type_inst; + const struct powercap_zone_ops *ops; + struct device dev; + int const_id_cnt; + struct idr idr; + struct idr *parent_idr; + void *private_data; + struct attribute **zone_dev_attrs; + int zone_attr_count; + struct attribute_group dev_zone_attr_group; + const struct attribute_group *dev_attr_groups[2]; /* 1 group + NULL */ + bool allocated; + struct powercap_zone_constraint *constraints; +}; + +/** + * struct powercap_zone_constraint_ops - Define constraint callbacks + * @set_power_limit_uw: Set power limit in micro-watts. + * @get_power_limit_uw: Get power limit in micro-watts. + * @set_time_window_us: Set time window in micro-seconds. + * @get_time_window_us: Get time window in micro-seconds. + * @get_max_power_uw: Get max power allowed in micro-watts. + * @get_min_power_uw: Get min power allowed in micro-watts. + * @get_max_time_window_us: Get max time window allowed in micro-seconds. + * @get_min_time_window_us: Get min time window allowed in micro-seconds. + * @get_name: Get the name of constraint + * + * This structure is used to define the constraint callbacks for the client + * drivers. The following callbacks are mandatory and can't be NULL: + * set_power_limit_uw + * get_power_limit_uw + * set_time_window_us + * get_time_window_us + * get_name + * Client drivers should handle mutual exclusion, if required in callbacks. + */ +struct powercap_zone_constraint_ops { + int (*set_power_limit_uw) (struct powercap_zone *, int, u64); + int (*get_power_limit_uw) (struct powercap_zone *, int, u64 *); + int (*set_time_window_us) (struct powercap_zone *, int, u64); + int (*get_time_window_us) (struct powercap_zone *, int, u64 *); + int (*get_max_power_uw) (struct powercap_zone *, int, u64 *); + int (*get_min_power_uw) (struct powercap_zone *, int, u64 *); + int (*get_max_time_window_us) (struct powercap_zone *, int, u64 *); + int (*get_min_time_window_us) (struct powercap_zone *, int, u64 *); + const char *(*get_name) (struct powercap_zone *, int); +}; + +/** + * struct powercap_zone_constraint- Defines instance of a constraint + * @id: Instance Id of this constraint. + * @power_zone: Pointer to the power zone for this constraint. + * @ops: Pointer to the constraint callbacks. + * + * This defines a constraint instance. + */ +struct powercap_zone_constraint { + int id; + struct powercap_zone *power_zone; + struct powercap_zone_constraint_ops *ops; +}; + + +/* For clients to get their device pointer, may be used for dev_dbgs */ +#define POWERCAP_GET_DEV(power_zone) (&power_zone->dev) + +/** +* powercap_set_zone_data() - Set private data for a zone +* @power_zone: A pointer to the valid zone instance. +* @pdata: A pointer to the user private data. +* +* Allows client drivers to associate some private data to zone instance. +*/ +static inline void powercap_set_zone_data(struct powercap_zone *power_zone, + void *pdata) +{ + if (power_zone) + power_zone->private_data = pdata; +} + +/** +* powercap_get_zone_data() - Get private data for a zone +* @power_zone: A pointer to the valid zone instance. +* +* Allows client drivers to get private data associate with a zone, +* using call to powercap_set_zone_data. +*/ +static inline void *powercap_get_zone_data(struct powercap_zone *power_zone) +{ + if (power_zone) + return power_zone->private_data; + return NULL; +} + +/** +* powercap_register_control_type() - Register a control_type with framework +* @control_type: Pointer to client allocated memory for the control type +* structure storage. If this is NULL, powercap framework +* will allocate memory and own it. +* Advantage of this parameter is that client can embed +* this data in its data structures and allocate in a +* single call, preventing multiple allocations. +* @control_type_name: The Name of this control_type, which will be shown +* in the sysfs Interface. +* @ops: Callbacks for control type. This parameter is optional. +* +* Used to create a control_type with the power capping class. Here control_type +* can represent a type of technology, which can control a range of power zones. +* For example a control_type can be RAPL (Running Average Power Limit) +* Intel® 64 and IA-32 Processor Architectures. The name can be any string +* which must be unique, otherwise this function returns NULL. +* A pointer to the control_type instance is returned on success. +*/ +struct powercap_control_type *powercap_register_control_type( + struct powercap_control_type *control_type, + const char *name, + const struct powercap_control_type_ops *ops); + +/** +* powercap_unregister_control_type() - Unregister a control_type from framework +* @instance: A pointer to the valid control_type instance. +* +* Used to unregister a control_type with the power capping class. +* All power zones registered under this control type have to be unregistered +* before calling this function, or it will fail with an error code. +*/ +int powercap_unregister_control_type(struct powercap_control_type *instance); + +/* Zone register/unregister API */ + +/** +* powercap_register_zone() - Register a power zone +* @power_zone: Pointer to client allocated memory for the power zone structure +* storage. If this is NULL, powercap framework will allocate +* memory and own it. Advantage of this parameter is that client +* can embed this data in its data structures and allocate in a +* single call, preventing multiple allocations. +* @control_type: A control_type instance under which this zone operates. +* @name: A name for this zone. +* @parent: A pointer to the parent power zone instance if any or NULL +* @ops: Pointer to zone operation callback structure. +* @no_constraints: Number of constraints for this zone +* @const_ops: Pointer to constraint callback structure +* +* Register a power zone under a given control type. A power zone must register +* a pointer to a structure representing zone callbacks. +* A power zone can be located under a parent power zone, in which case @parent +* should point to it. Otherwise, if @parent is NULL, the new power zone will +* be located directly under the given control type +* For each power zone there may be a number of constraints that appear in the +* sysfs under that zone as attributes with unique numeric IDs. +* Returns pointer to the power_zone on success. +*/ +struct powercap_zone *powercap_register_zone( + struct powercap_zone *power_zone, + struct powercap_control_type *control_type, + const char *name, + struct powercap_zone *parent, + const struct powercap_zone_ops *ops, + int nr_constraints, + struct powercap_zone_constraint_ops *const_ops); + +/** +* powercap_unregister_zone() - Unregister a zone device +* @control_type: A pointer to the valid instance of a control_type. +* @power_zone: A pointer to the valid zone instance for a control_type +* +* Used to unregister a zone device for a control_type. Caller should +* make sure that children for this zone are unregistered first. +*/ +int powercap_unregister_zone(struct powercap_control_type *control_type, + struct powercap_zone *power_zone); + +#endif -- cgit v0.10.2 From 12cc4b3827f8cc5973f86330ccc9d9656a31bfa8 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 11 Oct 2013 16:54:57 -0700 Subject: PowerCap: Add to drivers Kconfig and Makefile Added changes to Makefile and Kconfig to include in driver build. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jacob Pan Signed-off-by: Rafael J. Wysocki diff --git a/drivers/Kconfig b/drivers/Kconfig index aa43b91..969e987 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -166,4 +166,6 @@ source "drivers/reset/Kconfig" source "drivers/fmc/Kconfig" +source "drivers/powercap/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index ab93de8..34c1d55 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -152,3 +152,4 @@ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_IPACK_BUS) += ipack/ obj-$(CONFIG_NTB) += ntb/ obj-$(CONFIG_FMC) += fmc/ +obj-$(CONFIG_POWERCAP) += powercap/ -- cgit v0.10.2 From 1a6b991a9875a4c4811c7baf4058fa17aa1a9d9b Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Fri, 11 Oct 2013 16:54:58 -0700 Subject: x86 / msr: add 64bit _on_cpu access functions Having 64-bit MSR access methods on given CPU can avoid shifting and simplify MSR content manipulation. We already have other combinations of rdmsrl_xxx and wrmsrl_xxx but missing the _on_cpu version. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jacob Pan Reviewed-by: H. Peter Anvin Signed-off-by: Rafael J. Wysocki diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index cb75028..e139b13 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -218,10 +218,14 @@ void msrs_free(struct msr *msrs); #ifdef CONFIG_SMP int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); +int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q); +int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q); void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); +int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q); +int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q); int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); #else /* CONFIG_SMP */ @@ -235,6 +239,16 @@ static inline int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) wrmsr(msr_no, l, h); return 0; } +static inline int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q) +{ + rdmsrl(msr_no, *q); + return 0; +} +static inline int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q) +{ + wrmsrl(msr_no, q); + return 0; +} static inline void rdmsr_on_cpus(const struct cpumask *m, u32 msr_no, struct msr *msrs) { @@ -254,6 +268,14 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) { return wrmsr_safe(msr_no, l, h); } +static inline int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q) +{ + return rdmsrl_safe(msr_no, q); +} +static inline int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q) +{ + return wrmsrl_safe(msr_no, q); +} static inline int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]) { return rdmsr_safe_regs(regs); diff --git a/arch/x86/lib/msr-smp.c b/arch/x86/lib/msr-smp.c index a6b1b86..518532e 100644 --- a/arch/x86/lib/msr-smp.c +++ b/arch/x86/lib/msr-smp.c @@ -47,6 +47,21 @@ int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) } EXPORT_SYMBOL(rdmsr_on_cpu); +int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q) +{ + int err; + struct msr_info rv; + + memset(&rv, 0, sizeof(rv)); + + rv.msr_no = msr_no; + err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); + *q = rv.reg.q; + + return err; +} +EXPORT_SYMBOL(rdmsrl_on_cpu); + int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) { int err; @@ -63,6 +78,22 @@ int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) } EXPORT_SYMBOL(wrmsr_on_cpu); +int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q) +{ + int err; + struct msr_info rv; + + memset(&rv, 0, sizeof(rv)); + + rv.msr_no = msr_no; + rv.reg.q = q; + + err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1); + + return err; +} +EXPORT_SYMBOL(wrmsrl_on_cpu); + static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs, void (*msr_func) (void *info)) @@ -159,6 +190,37 @@ int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) } EXPORT_SYMBOL(wrmsr_safe_on_cpu); +int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q) +{ + int err; + struct msr_info rv; + + memset(&rv, 0, sizeof(rv)); + + rv.msr_no = msr_no; + rv.reg.q = q; + + err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1); + + return err ? err : rv.err; +} +EXPORT_SYMBOL(wrmsrl_safe_on_cpu); + +int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q) +{ + int err; + struct msr_info rv; + + memset(&rv, 0, sizeof(rv)); + + rv.msr_no = msr_no; + err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1); + *q = rv.reg.q; + + return err ? err : rv.err; +} +EXPORT_SYMBOL(rdmsrl_safe_on_cpu); + /* * These variants are significantly slower, but allows control over * the entire 32-bit GPR set. -- cgit v0.10.2 From bfd1ff6375c82930bfb3b401eee2c96720fa8e84 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 11 Oct 2013 16:54:59 -0700 Subject: bitops: Introduce BIT_ULL Adding BIT(x) equivalent for unsigned long long type, BIT_ULL(x). Also added BIT_ULL_MASK and BIT_ULL_WORD. Suggested-by: Joe Perches Signed-off-by: Srinivas Pandruvada Signed-off-by: Jacob Pan Signed-off-by: Rafael J. Wysocki diff --git a/include/linux/bitops.h b/include/linux/bitops.h index a3b6b82..5a1c8b7 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -4,8 +4,11 @@ #ifdef __KERNEL__ #define BIT(nr) (1UL << (nr)) +#define BIT_ULL(nr) (1ULL << (nr)) #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG)) +#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) #define BITS_PER_BYTE 8 #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) #endif -- cgit v0.10.2 From 6bdd326e740fb87a88a49189925ca12a02311c8b Mon Sep 17 00:00:00 2001 From: Manish Badarkhe Date: Wed, 9 Oct 2013 23:35:24 +0530 Subject: PM / devfreq: Remove duplicate include of opp.h Currently, code include opp.h twice. Remove one inclusion of opp.h Signed-off-by: Manish Badarkhe Signed-off-by: Rafael J. Wysocki diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c index 574b16b..93c29f4 100644 --- a/drivers/devfreq/exynos/exynos5_bus.c +++ b/drivers/devfreq/exynos/exynos5_bus.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include -- cgit v0.10.2 From 006454ae779d5d3f6ac518f0903475a5142bef5b Mon Sep 17 00:00:00 2001 From: Manish Badarkhe Date: Wed, 9 Oct 2013 20:43:37 +0530 Subject: exynos-cpufreq: fix false return check from "regulator_set_voltage" Currently, code checks false return value from "regulator_set_voltage" to show failure message. Modify the code to check proper return value from "regulator_set_voltage". Signed-off-by: Manish Badarkhe Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index b96fcc8..3e4af67 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -135,7 +135,7 @@ post_notify: if ((freqs.new < freqs.old) || ((freqs.new > freqs.old) && safe_arm_volt)) { /* down the voltage after frequency change */ - regulator_set_voltage(arm_regulator, arm_volt, + ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt); if (ret) { pr_err("%s: failed to set cpu voltage to %d\n", -- cgit v0.10.2 From fbbc5bfb44a22e7a8ef753a1c8dfb448d7ac8b85 Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Tue, 1 Oct 2013 10:30:24 -0500 Subject: cpufreq: highbank-cpufreq: Enable Midway/ECX-2000 Calxeda's new ECX-2000 part uses the same cpufreq interface as highbank, so add it to the driver's compatibility list. This is a minor change that can safely be applied to the 3.10 and 3.11 stable trees. Signed-off-by: Mark Langsdorf Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c index 794123f..bf8902a 100644 --- a/drivers/cpufreq/highbank-cpufreq.c +++ b/drivers/cpufreq/highbank-cpufreq.c @@ -66,7 +66,8 @@ static int hb_cpufreq_driver_init(void) struct device_node *np; int ret; - if (!of_machine_is_compatible("calxeda,highbank")) + if ((!of_machine_is_compatible("calxeda,highbank")) && + (!of_machine_is_compatible("calxeda,ecx-2000"))) return -ENODEV; cpu_dev = get_cpu_device(0); -- cgit v0.10.2 From 45a428ebbf7d6a4ec77cf02fc706ecd62b261bd9 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 30 Sep 2013 23:44:31 +0300 Subject: cpufreq: pmac64: speed up frequency switch Some functions on switch path use msleep() which is inaccurate, and depends on HZ. With HZ=100 msleep(1) takes actually over ten times longer. Using usleep_range() we get more accurate sleeps. I measured the "pfunc_slewing_done" polling to take 300us at max (on 2.3GHz dual-processor Xserve G5), so using 500us sleep there should be fine. With the patch, g5_switch_freq() duration drops from ~50ms to ~10ms on Xserve with HZ=100. Signed-off-by: Aaro Koskinen Acked-by: Viresh Kumar Acked-by: Benjamin Herrenschmidt Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index b977b9a..889c0d5 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -137,7 +137,7 @@ static void g5_vdnap_switch_volt(int speed_mode) pmf_call_one(pfunc_vdnap0_complete, &args); if (done) break; - msleep(1); + usleep_range(1000, 1000); } if (done == 0) printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n"); @@ -236,7 +236,7 @@ static void g5_pfunc_switch_volt(int speed_mode) if (pfunc_cpu1_volt_low) pmf_call_one(pfunc_cpu1_volt_low, NULL); } - msleep(10); /* should be faster , to fix */ + usleep_range(10000, 10000); /* should be faster , to fix */ } /* @@ -281,7 +281,7 @@ static int g5_pfunc_switch_freq(int speed_mode) pmf_call_one(pfunc_slewing_done, &args); if (done) break; - msleep(1); + usleep_range(500, 500); } if (done == 0) printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n"); -- cgit v0.10.2 From af671d8b2c2ace771e08566b20774cc08ee53316 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 30 Sep 2013 23:44:32 +0300 Subject: cpufreq: pmac64: provide cpufreq transition latency for older G5 models Currently cpufreq ondemand governor cannot used on older G5 models, because the transition latency is set to CPUFREQ_ETERNAL. Provide a value based on a measurement on Xserve G5, which happens to be also the highest allowed latency. Signed-off-by: Aaro Koskinen Acked-by: Benjamin Herrenschmidt Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 889c0d5..db9764e 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -627,8 +627,10 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) g5_cpu_freqs[0].frequency = max_freq; g5_cpu_freqs[1].frequency = min_freq; + /* Based on a measurement on Xserve G5, rounded up. */ + transition_latency = 10 * NSEC_PER_MSEC; + /* Set callbacks */ - transition_latency = CPUFREQ_ETERNAL; g5_switch_volt = g5_pfunc_switch_volt; g5_switch_freq = g5_pfunc_switch_freq; g5_query_freq = g5_pfunc_query_freq; -- cgit v0.10.2 From 891083622621bfe114ec4d40711a7d3a68fdc6fc Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 30 Sep 2013 23:44:33 +0300 Subject: cpufreq: pmac64: enable cpufreq on iMac G5 (iSight) model Enable cpufreq on iMac G5 (iSight) model. Tested with the 2.1 GHz version. Signed-off-by: Aaro Koskinen Acked-by: Viresh Kumar Acked-by: Benjamin Herrenschmidt Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index db9764e..5261b92 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -377,7 +377,8 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpunode) /* Check supported platforms */ if (of_machine_is_compatible("PowerMac8,1") || of_machine_is_compatible("PowerMac8,2") || - of_machine_is_compatible("PowerMac9,1")) + of_machine_is_compatible("PowerMac9,1") || + of_machine_is_compatible("PowerMac12,1")) use_volts_smu = 1; else if (of_machine_is_compatible("PowerMac11,2")) use_volts_vdnap = 1; -- cgit v0.10.2 From 99ec899eafe2ec0a7dd96e9de5fa0a2bea3032ba Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Thu, 12 Sep 2013 17:29:09 +0530 Subject: cpufreq: Detect spurious invocations of update_policy_cpu() The function update_policy_cpu() is expected to be called when the policy->cpu of a cpufreq policy is to be changed: ie., the new CPU nominated to become the policy->cpu is different from the old one. Print a warning if it is invoked with new_cpu == old_cpu, since such an invocation might hint at a faulty logic in the caller. Suggested-by: Viresh Kumar Signed-off-by: Srivatsa S. Bhat Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index f0897c7..ec391d7 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -969,7 +969,7 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy) static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) { - if (cpu == policy->cpu) + if (WARN_ON(cpu == policy->cpu)) return; /* -- cgit v0.10.2 From cf4671559fdc0550de38fc8f6cd0ea6369736f1f Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Wed, 9 Oct 2013 14:08:42 +0200 Subject: cpufreq: exynos4x12: Use the common clock framework to set APLL clock rate In the exynos4x12_set_apll() function, the APLL frequency is set with direct register manipulation. Such approach is not allowed in the common clock framework. The frequency is changed, but the corresponding clock value is not updated. This causes wrong frequency read from cpufreq's cpuinfo_cur_freq sysfs attribute. Also direct manipulation with PLL's S parameter has been removed. It is already done at PLL35xx code. Tested at: - Exynos4412 - Trats2 board (linux 3.12-rc4) Signed-off-by: Lukasz Majewski Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Tomasz Figa Reviewed-by: Yadwinder Singh Brar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c index 08b7477..8683304 100644 --- a/drivers/cpufreq/exynos4x12-cpufreq.c +++ b/drivers/cpufreq/exynos4x12-cpufreq.c @@ -128,9 +128,9 @@ static void exynos4x12_set_clkdiv(unsigned int div_index) static void exynos4x12_set_apll(unsigned int index) { - unsigned int tmp, pdiv; + unsigned int tmp, freq = apll_freq_4x12[index].freq; - /* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */ + /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */ clk_set_parent(moutcore, mout_mpll); do { @@ -140,24 +140,9 @@ static void exynos4x12_set_apll(unsigned int index) tmp &= 0x7; } while (tmp != 0x2); - /* 2. Set APLL Lock time */ - pdiv = ((apll_freq_4x12[index].mps >> 8) & 0x3f); + clk_set_rate(mout_apll, freq * 1000); - __raw_writel((pdiv * 250), EXYNOS4_APLL_LOCK); - - /* 3. Change PLL PMS values */ - tmp = __raw_readl(EXYNOS4_APLL_CON0); - tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0)); - tmp |= apll_freq_4x12[index].mps; - __raw_writel(tmp, EXYNOS4_APLL_CON0); - - /* 4. wait_lock_time */ - do { - cpu_relax(); - tmp = __raw_readl(EXYNOS4_APLL_CON0); - } while (!(tmp & (0x1 << EXYNOS4_APLLCON0_LOCKED_SHIFT))); - - /* 5. MUX_CORE_SEL = APLL */ + /* MUX_CORE_SEL = APLL */ clk_set_parent(moutcore, mout_apll); do { @@ -167,52 +152,15 @@ static void exynos4x12_set_apll(unsigned int index) } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); } -static bool exynos4x12_pms_change(unsigned int old_index, unsigned int new_index) -{ - unsigned int old_pm = apll_freq_4x12[old_index].mps >> 8; - unsigned int new_pm = apll_freq_4x12[new_index].mps >> 8; - - return (old_pm == new_pm) ? 0 : 1; -} - static void exynos4x12_set_frequency(unsigned int old_index, unsigned int new_index) { - unsigned int tmp; - if (old_index > new_index) { - if (!exynos4x12_pms_change(old_index, new_index)) { - /* 1. Change the system clock divider values */ - exynos4x12_set_clkdiv(new_index); - /* 2. Change just s value in apll m,p,s value */ - tmp = __raw_readl(EXYNOS4_APLL_CON0); - tmp &= ~(0x7 << 0); - tmp |= apll_freq_4x12[new_index].mps & 0x7; - __raw_writel(tmp, EXYNOS4_APLL_CON0); - - } else { - /* Clock Configuration Procedure */ - /* 1. Change the system clock divider values */ - exynos4x12_set_clkdiv(new_index); - /* 2. Change the apll m,p,s value */ - exynos4x12_set_apll(new_index); - } + exynos4x12_set_clkdiv(new_index); + exynos4x12_set_apll(new_index); } else if (old_index < new_index) { - if (!exynos4x12_pms_change(old_index, new_index)) { - /* 1. Change just s value in apll m,p,s value */ - tmp = __raw_readl(EXYNOS4_APLL_CON0); - tmp &= ~(0x7 << 0); - tmp |= apll_freq_4x12[new_index].mps & 0x7; - __raw_writel(tmp, EXYNOS4_APLL_CON0); - /* 2. Change the system clock divider values */ - exynos4x12_set_clkdiv(new_index); - } else { - /* Clock Configuration Procedure */ - /* 1. Change the apll m,p,s value */ - exynos4x12_set_apll(new_index); - /* 2. Change the system clock divider values */ - exynos4x12_set_clkdiv(new_index); - } + exynos4x12_set_apll(new_index); + exynos4x12_set_clkdiv(new_index); } } @@ -250,7 +198,6 @@ int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) info->volt_table = exynos4x12_volt_table; info->freq_table = exynos4x12_freq_table; info->set_freq = exynos4x12_set_frequency; - info->need_apll_change = exynos4x12_pms_change; return 0; -- cgit v0.10.2 From 7ad65d592b0a7f70fe21af2e3d4d02c76333d5a0 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Wed, 9 Oct 2013 14:08:43 +0200 Subject: cpufreq: exynos4210: Use the common clock framework to set APLL clock rate In the exynos4210_set_apll() function, the APLL frequency is set with direct register manipulation. Such approach is not allowed in the common clock framework. The frequency is changed, but the corresponding clock value is not updated. This causes wrong frequency read from cpufreq's cpuinfo_cur_freq sysfs attribute. Also direct manipulation with PLL's S parameter has been removed. It is already done at PLL35xx code. Tested at: - Exynos4210 - Trats board (linux 3.12-rc4) Signed-off-by: Lukasz Majewski Reviewed-by: Yadwinder Singh Brar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c index add7fbe..f2c7506 100644 --- a/drivers/cpufreq/exynos4210-cpufreq.c +++ b/drivers/cpufreq/exynos4210-cpufreq.c @@ -81,9 +81,9 @@ static void exynos4210_set_clkdiv(unsigned int div_index) static void exynos4210_set_apll(unsigned int index) { - unsigned int tmp; + unsigned int tmp, freq = apll_freq_4210[index].freq; - /* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */ + /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */ clk_set_parent(moutcore, mout_mpll); do { @@ -92,21 +92,9 @@ static void exynos4210_set_apll(unsigned int index) tmp &= 0x7; } while (tmp != 0x2); - /* 2. Set APLL Lock time */ - __raw_writel(EXYNOS4_APLL_LOCKTIME, EXYNOS4_APLL_LOCK); - - /* 3. Change PLL PMS values */ - tmp = __raw_readl(EXYNOS4_APLL_CON0); - tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0)); - tmp |= apll_freq_4210[index].mps; - __raw_writel(tmp, EXYNOS4_APLL_CON0); + clk_set_rate(mout_apll, freq * 1000); - /* 4. wait_lock_time */ - do { - tmp = __raw_readl(EXYNOS4_APLL_CON0); - } while (!(tmp & (0x1 << EXYNOS4_APLLCON0_LOCKED_SHIFT))); - - /* 5. MUX_CORE_SEL = APLL */ + /* MUX_CORE_SEL = APLL */ clk_set_parent(moutcore, mout_apll); do { @@ -115,53 +103,15 @@ static void exynos4210_set_apll(unsigned int index) } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); } -static bool exynos4210_pms_change(unsigned int old_index, unsigned int new_index) -{ - unsigned int old_pm = apll_freq_4210[old_index].mps >> 8; - unsigned int new_pm = apll_freq_4210[new_index].mps >> 8; - - return (old_pm == new_pm) ? 0 : 1; -} - static void exynos4210_set_frequency(unsigned int old_index, unsigned int new_index) { - unsigned int tmp; - if (old_index > new_index) { - if (!exynos4210_pms_change(old_index, new_index)) { - /* 1. Change the system clock divider values */ - exynos4210_set_clkdiv(new_index); - - /* 2. Change just s value in apll m,p,s value */ - tmp = __raw_readl(EXYNOS4_APLL_CON0); - tmp &= ~(0x7 << 0); - tmp |= apll_freq_4210[new_index].mps & 0x7; - __raw_writel(tmp, EXYNOS4_APLL_CON0); - } else { - /* Clock Configuration Procedure */ - /* 1. Change the system clock divider values */ - exynos4210_set_clkdiv(new_index); - /* 2. Change the apll m,p,s value */ - exynos4210_set_apll(new_index); - } + exynos4210_set_clkdiv(new_index); + exynos4210_set_apll(new_index); } else if (old_index < new_index) { - if (!exynos4210_pms_change(old_index, new_index)) { - /* 1. Change just s value in apll m,p,s value */ - tmp = __raw_readl(EXYNOS4_APLL_CON0); - tmp &= ~(0x7 << 0); - tmp |= apll_freq_4210[new_index].mps & 0x7; - __raw_writel(tmp, EXYNOS4_APLL_CON0); - - /* 2. Change the system clock divider values */ - exynos4210_set_clkdiv(new_index); - } else { - /* Clock Configuration Procedure */ - /* 1. Change the apll m,p,s value */ - exynos4210_set_apll(new_index); - /* 2. Change the system clock divider values */ - exynos4210_set_clkdiv(new_index); - } + exynos4210_set_apll(new_index); + exynos4210_set_clkdiv(new_index); } } @@ -194,7 +144,6 @@ int exynos4210_cpufreq_init(struct exynos_dvfs_info *info) info->volt_table = exynos4210_volt_table; info->freq_table = exynos4210_freq_table; info->set_freq = exynos4210_set_frequency; - info->need_apll_change = exynos4210_pms_change; return 0; -- cgit v0.10.2 From d4f7ecf72819932e0f0a2221328d5eb4e28cc059 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 11 Sep 2013 17:02:38 +0300 Subject: PM / QoS: simplify pm_qos_power_write() Let kstrtos32_from_user() do the necessary calls and checks. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki diff --git a/kernel/power/qos.c b/kernel/power/qos.c index a394297..8dff9b4 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -558,30 +558,12 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, if (count == sizeof(s32)) { if (copy_from_user(&value, buf, sizeof(s32))) return -EFAULT; - } else if (count <= 11) { /* ASCII perhaps? */ - char ascii_value[11]; - unsigned long int ulval; + } else { int ret; - if (copy_from_user(ascii_value, buf, count)) - return -EFAULT; - - if (count > 10) { - if (ascii_value[10] == '\n') - ascii_value[10] = '\0'; - else - return -EINVAL; - } else { - ascii_value[count] = '\0'; - } - ret = kstrtoul(ascii_value, 16, &ulval); - if (ret) { - pr_debug("%s, 0x%lx, 0x%x\n", ascii_value, ulval, ret); - return -EINVAL; - } - value = (s32)lower_32_bits(ulval); - } else { - return -EINVAL; + ret = kstrtos32_from_user(buf, count, 16, &value); + if (ret) + return ret; } req = filp->private_data; -- cgit v0.10.2 From a814613b9a32d9ab9578d9dab396265c826d37f0 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 11 Sep 2013 20:49:57 +0800 Subject: cpufreq / governor: Remove fossil comment cpufreq_set_policy() has been changed to origin __cpufreq_set_policy() and policy->lock has been converted to rewrite lock by commit 5a01f2. So remove the comment. Acked-by: Viresh Kumar Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 0307809..4dbf1db 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -38,18 +38,7 @@ static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq) if (!per_cpu(cpu_is_managed, policy->cpu)) goto err; - /* - * We're safe from concurrent calls to ->target() here - * as we hold the userspace_mutex lock. If we were calling - * cpufreq_driver_target, a deadlock situation might occur: - * A: cpufreq_set (lock userspace_mutex) -> - * cpufreq_driver_target(lock policy->lock) - * B: cpufreq_set_policy(lock policy->lock) -> - * __cpufreq_governor -> - * cpufreq_governor_userspace (lock userspace_mutex) - */ ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); - err: mutex_unlock(&userspace_mutex); return ret; -- cgit v0.10.2 From 2d281d8196e38dd3a4ee9af26621ddde8329f269 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Thu, 17 Oct 2013 10:28:35 -0700 Subject: PowerCap: Introduce Intel RAPL power capping driver The Intel Running Average Power Limit (RAPL) technology provides platform software with the ability to monitor, control, and get notifications on power usage. This feature is present in all Sandy Bridge and later Intel processors. Newer models allow more fine grained controls to be applied. In RAPL, power control is divided into domains, which include package, DRAM controller, CPU core (Power Plane 0), graphics uncore (power plane 1), etc. The purpose of this driver is to expose the RAPL settings to userspace. Overall, RAPL fits in the new powercap class driver in that platform level power capping controls are exposed via this generic interface. This driver is based on an earlier patch from Zhang Rui. However, while the previous work was mainly focused on thermal monitoring the focus here is on the usability from user space perspective. References: https://lkml.org/lkml/2011/5/26/93 Signed-off-by: Srinivas Pandruvada Signed-off-by: Jacob Pan Reviewed-by: Rafael J. Wysocki Signed-off-by: Rafael J. Wysocki diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig index a37055e..a7c81b5 100644 --- a/drivers/powercap/Kconfig +++ b/drivers/powercap/Kconfig @@ -15,5 +15,18 @@ menuconfig POWERCAP if POWERCAP # Client driver configurations go here. +config INTEL_RAPL + tristate "Intel RAPL Support" + depends on X86 + default n + ---help--- + This enables support for the Intel Running Average Power Limit (RAPL) + technology which allows power limits to be enforced and monitored on + modern Intel processors (Sandy Bridge and later). + + In RAPL, the platform level settings are divided into domains for + fine grained control. These domains include processor package, DRAM + controller, CPU core (Power Plance 0), graphics uncore (Power Plane + 1), etc. endif diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile index 6defbc8..0a21ef3 100644 --- a/drivers/powercap/Makefile +++ b/drivers/powercap/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_POWERCAP) += powercap_sys.o +obj-$(CONFIG_INTEL_RAPL) += intel_rapl.o diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c new file mode 100644 index 0000000..2a786c5 --- /dev/null +++ b/drivers/powercap/intel_rapl.c @@ -0,0 +1,1395 @@ +/* + * Intel Running Average Power Limit (RAPL) Driver + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc. + * + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* bitmasks for RAPL MSRs, used by primitive access functions */ +#define ENERGY_STATUS_MASK 0xffffffff + +#define POWER_LIMIT1_MASK 0x7FFF +#define POWER_LIMIT1_ENABLE BIT(15) +#define POWER_LIMIT1_CLAMP BIT(16) + +#define POWER_LIMIT2_MASK (0x7FFFULL<<32) +#define POWER_LIMIT2_ENABLE BIT_ULL(47) +#define POWER_LIMIT2_CLAMP BIT_ULL(48) +#define POWER_PACKAGE_LOCK BIT_ULL(63) +#define POWER_PP_LOCK BIT(31) + +#define TIME_WINDOW1_MASK (0x7FULL<<17) +#define TIME_WINDOW2_MASK (0x7FULL<<49) + +#define POWER_UNIT_OFFSET 0 +#define POWER_UNIT_MASK 0x0F + +#define ENERGY_UNIT_OFFSET 0x08 +#define ENERGY_UNIT_MASK 0x1F00 + +#define TIME_UNIT_OFFSET 0x10 +#define TIME_UNIT_MASK 0xF0000 + +#define POWER_INFO_MAX_MASK (0x7fffULL<<32) +#define POWER_INFO_MIN_MASK (0x7fffULL<<16) +#define POWER_INFO_MAX_TIME_WIN_MASK (0x3fULL<<48) +#define POWER_INFO_THERMAL_SPEC_MASK 0x7fff + +#define PERF_STATUS_THROTTLE_TIME_MASK 0xffffffff +#define PP_POLICY_MASK 0x1F + +/* Non HW constants */ +#define RAPL_PRIMITIVE_DERIVED BIT(1) /* not from raw data */ +#define RAPL_PRIMITIVE_DUMMY BIT(2) + +/* scale RAPL units to avoid floating point math inside kernel */ +#define POWER_UNIT_SCALE (1000000) +#define ENERGY_UNIT_SCALE (1000000) +#define TIME_UNIT_SCALE (1000000) + +#define TIME_WINDOW_MAX_MSEC 40000 +#define TIME_WINDOW_MIN_MSEC 250 + +enum unit_type { + ARBITRARY_UNIT, /* no translation */ + POWER_UNIT, + ENERGY_UNIT, + TIME_UNIT, +}; + +enum rapl_domain_type { + RAPL_DOMAIN_PACKAGE, /* entire package/socket */ + RAPL_DOMAIN_PP0, /* core power plane */ + RAPL_DOMAIN_PP1, /* graphics uncore */ + RAPL_DOMAIN_DRAM,/* DRAM control_type */ + RAPL_DOMAIN_MAX, +}; + +enum rapl_domain_msr_id { + RAPL_DOMAIN_MSR_LIMIT, + RAPL_DOMAIN_MSR_STATUS, + RAPL_DOMAIN_MSR_PERF, + RAPL_DOMAIN_MSR_POLICY, + RAPL_DOMAIN_MSR_INFO, + RAPL_DOMAIN_MSR_MAX, +}; + +/* per domain data, some are optional */ +enum rapl_primitives { + ENERGY_COUNTER, + POWER_LIMIT1, + POWER_LIMIT2, + FW_LOCK, + + PL1_ENABLE, /* power limit 1, aka long term */ + PL1_CLAMP, /* allow frequency to go below OS request */ + PL2_ENABLE, /* power limit 2, aka short term, instantaneous */ + PL2_CLAMP, + + TIME_WINDOW1, /* long term */ + TIME_WINDOW2, /* short term */ + THERMAL_SPEC_POWER, + MAX_POWER, + + MIN_POWER, + MAX_TIME_WINDOW, + THROTTLED_TIME, + PRIORITY_LEVEL, + + /* below are not raw primitive data */ + AVERAGE_POWER, + NR_RAPL_PRIMITIVES, +}; + +#define NR_RAW_PRIMITIVES (NR_RAPL_PRIMITIVES - 2) + +/* Can be expanded to include events, etc.*/ +struct rapl_domain_data { + u64 primitives[NR_RAPL_PRIMITIVES]; + unsigned long timestamp; +}; + + +#define DOMAIN_STATE_INACTIVE BIT(0) +#define DOMAIN_STATE_POWER_LIMIT_SET BIT(1) +#define DOMAIN_STATE_BIOS_LOCKED BIT(2) + +#define NR_POWER_LIMITS (2) +struct rapl_power_limit { + struct powercap_zone_constraint *constraint; + int prim_id; /* primitive ID used to enable */ + struct rapl_domain *domain; + const char *name; +}; + +static const char pl1_name[] = "long_term"; +static const char pl2_name[] = "short_term"; + +struct rapl_domain { + const char *name; + enum rapl_domain_type id; + int msrs[RAPL_DOMAIN_MSR_MAX]; + struct powercap_zone power_zone; + struct rapl_domain_data rdd; + struct rapl_power_limit rpl[NR_POWER_LIMITS]; + u64 attr_map; /* track capabilities */ + unsigned int state; + int package_id; +}; +#define power_zone_to_rapl_domain(_zone) \ + container_of(_zone, struct rapl_domain, power_zone) + + +/* Each physical package contains multiple domains, these are the common + * data across RAPL domains within a package. + */ +struct rapl_package { + unsigned int id; /* physical package/socket id */ + unsigned int nr_domains; + unsigned long domain_map; /* bit map of active domains */ + unsigned int power_unit_divisor; + unsigned int energy_unit_divisor; + unsigned int time_unit_divisor; + struct rapl_domain *domains; /* array of domains, sized at runtime */ + struct powercap_zone *power_zone; /* keep track of parent zone */ + int nr_cpus; /* active cpus on the package, topology info is lost during + * cpu hotplug. so we have to track ourselves. + */ + unsigned long power_limit_irq; /* keep track of package power limit + * notify interrupt enable status. + */ + struct list_head plist; +}; +#define PACKAGE_PLN_INT_SAVED BIT(0) +#define MAX_PRIM_NAME (32) + +/* per domain data. used to describe individual knobs such that access function + * can be consolidated into one instead of many inline functions. + */ +struct rapl_primitive_info { + const char *name; + u64 mask; + int shift; + enum rapl_domain_msr_id id; + enum unit_type unit; + u32 flag; +}; + +#define PRIMITIVE_INFO_INIT(p, m, s, i, u, f) { \ + .name = #p, \ + .mask = m, \ + .shift = s, \ + .id = i, \ + .unit = u, \ + .flag = f \ + } + +static void rapl_init_domains(struct rapl_package *rp); +static int rapl_read_data_raw(struct rapl_domain *rd, + enum rapl_primitives prim, + bool xlate, u64 *data); +static int rapl_write_data_raw(struct rapl_domain *rd, + enum rapl_primitives prim, + unsigned long long value); +static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value, + int to_raw); +static void package_power_limit_irq_save(int package_id); + +static LIST_HEAD(rapl_packages); /* guarded by CPU hotplug lock */ + +static const char * const rapl_domain_names[] = { + "package", + "core", + "uncore", + "dram", +}; + +static struct powercap_control_type *control_type; /* PowerCap Controller */ + +/* caller to ensure CPU hotplug lock is held */ +static struct rapl_package *find_package_by_id(int id) +{ + struct rapl_package *rp; + + list_for_each_entry(rp, &rapl_packages, plist) { + if (rp->id == id) + return rp; + } + + return NULL; +} + +/* caller to ensure CPU hotplug lock is held */ +static int find_active_cpu_on_package(int package_id) +{ + int i; + + for_each_online_cpu(i) { + if (topology_physical_package_id(i) == package_id) + return i; + } + /* all CPUs on this package are offline */ + + return -ENODEV; +} + +/* caller must hold cpu hotplug lock */ +static void rapl_cleanup_data(void) +{ + struct rapl_package *p, *tmp; + + list_for_each_entry_safe(p, tmp, &rapl_packages, plist) { + kfree(p->domains); + list_del(&p->plist); + kfree(p); + } +} + +static int get_energy_counter(struct powercap_zone *power_zone, u64 *energy_raw) +{ + struct rapl_domain *rd; + u64 energy_now; + + /* prevent CPU hotplug, make sure the RAPL domain does not go + * away while reading the counter. + */ + get_online_cpus(); + rd = power_zone_to_rapl_domain(power_zone); + + if (!rapl_read_data_raw(rd, ENERGY_COUNTER, true, &energy_now)) { + *energy_raw = energy_now; + put_online_cpus(); + + return 0; + } + put_online_cpus(); + + return -EIO; +} + +static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy) +{ + *energy = rapl_unit_xlate(0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0); + return 0; +} + +static int release_zone(struct powercap_zone *power_zone) +{ + struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone); + struct rapl_package *rp; + + /* package zone is the last zone of a package, we can free + * memory here since all children has been unregistered. + */ + if (rd->id == RAPL_DOMAIN_PACKAGE) { + rp = find_package_by_id(rd->package_id); + if (!rp) { + dev_warn(&power_zone->dev, "no package id %s\n", + rd->name); + return -ENODEV; + } + kfree(rd); + rp->domains = NULL; + } + + return 0; + +} + +static int find_nr_power_limit(struct rapl_domain *rd) +{ + int i; + + for (i = 0; i < NR_POWER_LIMITS; i++) { + if (rd->rpl[i].name == NULL) + break; + } + + return i; +} + +static int set_domain_enable(struct powercap_zone *power_zone, bool mode) +{ + struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone); + int nr_powerlimit; + + if (rd->state & DOMAIN_STATE_BIOS_LOCKED) + return -EACCES; + get_online_cpus(); + nr_powerlimit = find_nr_power_limit(rd); + /* here we activate/deactivate the hardware for power limiting */ + rapl_write_data_raw(rd, PL1_ENABLE, mode); + /* always enable clamp such that p-state can go below OS requested + * range. power capping priority over guranteed frequency. + */ + rapl_write_data_raw(rd, PL1_CLAMP, mode); + /* some domains have pl2 */ + if (nr_powerlimit > 1) { + rapl_write_data_raw(rd, PL2_ENABLE, mode); + rapl_write_data_raw(rd, PL2_CLAMP, mode); + } + put_online_cpus(); + + return 0; +} + +static int get_domain_enable(struct powercap_zone *power_zone, bool *mode) +{ + struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone); + u64 val; + + if (rd->state & DOMAIN_STATE_BIOS_LOCKED) { + *mode = false; + return 0; + } + get_online_cpus(); + if (rapl_read_data_raw(rd, PL1_ENABLE, true, &val)) { + put_online_cpus(); + return -EIO; + } + *mode = val; + put_online_cpus(); + + return 0; +} + +/* per RAPL domain ops, in the order of rapl_domain_type */ +static struct powercap_zone_ops zone_ops[] = { + /* RAPL_DOMAIN_PACKAGE */ + { + .get_energy_uj = get_energy_counter, + .get_max_energy_range_uj = get_max_energy_counter, + .release = release_zone, + .set_enable = set_domain_enable, + .get_enable = get_domain_enable, + }, + /* RAPL_DOMAIN_PP0 */ + { + .get_energy_uj = get_energy_counter, + .get_max_energy_range_uj = get_max_energy_counter, + .release = release_zone, + .set_enable = set_domain_enable, + .get_enable = get_domain_enable, + }, + /* RAPL_DOMAIN_PP1 */ + { + .get_energy_uj = get_energy_counter, + .get_max_energy_range_uj = get_max_energy_counter, + .release = release_zone, + .set_enable = set_domain_enable, + .get_enable = get_domain_enable, + }, + /* RAPL_DOMAIN_DRAM */ + { + .get_energy_uj = get_energy_counter, + .get_max_energy_range_uj = get_max_energy_counter, + .release = release_zone, + .set_enable = set_domain_enable, + .get_enable = get_domain_enable, + }, +}; + +static int set_power_limit(struct powercap_zone *power_zone, int id, + u64 power_limit) +{ + struct rapl_domain *rd; + struct rapl_package *rp; + int ret = 0; + + get_online_cpus(); + rd = power_zone_to_rapl_domain(power_zone); + rp = find_package_by_id(rd->package_id); + if (!rp) { + ret = -ENODEV; + goto set_exit; + } + + if (rd->state & DOMAIN_STATE_BIOS_LOCKED) { + dev_warn(&power_zone->dev, "%s locked by BIOS, monitoring only\n", + rd->name); + ret = -EACCES; + goto set_exit; + } + + switch (rd->rpl[id].prim_id) { + case PL1_ENABLE: + rapl_write_data_raw(rd, POWER_LIMIT1, power_limit); + break; + case PL2_ENABLE: + rapl_write_data_raw(rd, POWER_LIMIT2, power_limit); + break; + default: + ret = -EINVAL; + } + if (!ret) + package_power_limit_irq_save(rd->package_id); +set_exit: + put_online_cpus(); + return ret; +} + +static int get_current_power_limit(struct powercap_zone *power_zone, int id, + u64 *data) +{ + struct rapl_domain *rd; + u64 val; + int prim; + int ret = 0; + + get_online_cpus(); + rd = power_zone_to_rapl_domain(power_zone); + switch (rd->rpl[id].prim_id) { + case PL1_ENABLE: + prim = POWER_LIMIT1; + break; + case PL2_ENABLE: + prim = POWER_LIMIT2; + break; + default: + put_online_cpus(); + return -EINVAL; + } + if (rapl_read_data_raw(rd, prim, true, &val)) + ret = -EIO; + else + *data = val; + + put_online_cpus(); + + return ret; +} + +static int set_time_window(struct powercap_zone *power_zone, int id, + u64 window) +{ + struct rapl_domain *rd; + int ret = 0; + + get_online_cpus(); + rd = power_zone_to_rapl_domain(power_zone); + switch (rd->rpl[id].prim_id) { + case PL1_ENABLE: + rapl_write_data_raw(rd, TIME_WINDOW1, window); + break; + case PL2_ENABLE: + rapl_write_data_raw(rd, TIME_WINDOW2, window); + break; + default: + ret = -EINVAL; + } + put_online_cpus(); + return ret; +} + +static int get_time_window(struct powercap_zone *power_zone, int id, u64 *data) +{ + struct rapl_domain *rd; + u64 val; + int ret = 0; + + get_online_cpus(); + rd = power_zone_to_rapl_domain(power_zone); + switch (rd->rpl[id].prim_id) { + case PL1_ENABLE: + ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val); + break; + case PL2_ENABLE: + ret = rapl_read_data_raw(rd, TIME_WINDOW2, true, &val); + break; + default: + put_online_cpus(); + return -EINVAL; + } + if (!ret) + *data = val; + put_online_cpus(); + + return ret; +} + +static const char *get_constraint_name(struct powercap_zone *power_zone, int id) +{ + struct rapl_power_limit *rpl; + struct rapl_domain *rd; + + rd = power_zone_to_rapl_domain(power_zone); + rpl = (struct rapl_power_limit *) &rd->rpl[id]; + + return rpl->name; +} + + +static int get_max_power(struct powercap_zone *power_zone, int id, + u64 *data) +{ + struct rapl_domain *rd; + u64 val; + int prim; + int ret = 0; + + get_online_cpus(); + rd = power_zone_to_rapl_domain(power_zone); + switch (rd->rpl[id].prim_id) { + case PL1_ENABLE: + prim = THERMAL_SPEC_POWER; + break; + case PL2_ENABLE: + prim = MAX_POWER; + break; + default: + put_online_cpus(); + return -EINVAL; + } + if (rapl_read_data_raw(rd, prim, true, &val)) + ret = -EIO; + else + *data = val; + + put_online_cpus(); + + return ret; +} + +static struct powercap_zone_constraint_ops constraint_ops = { + .set_power_limit_uw = set_power_limit, + .get_power_limit_uw = get_current_power_limit, + .set_time_window_us = set_time_window, + .get_time_window_us = get_time_window, + .get_max_power_uw = get_max_power, + .get_name = get_constraint_name, +}; + +/* called after domain detection and package level data are set */ +static void rapl_init_domains(struct rapl_package *rp) +{ + int i; + struct rapl_domain *rd = rp->domains; + + for (i = 0; i < RAPL_DOMAIN_MAX; i++) { + unsigned int mask = rp->domain_map & (1 << i); + switch (mask) { + case BIT(RAPL_DOMAIN_PACKAGE): + rd->name = rapl_domain_names[RAPL_DOMAIN_PACKAGE]; + rd->id = RAPL_DOMAIN_PACKAGE; + rd->msrs[0] = MSR_PKG_POWER_LIMIT; + rd->msrs[1] = MSR_PKG_ENERGY_STATUS; + rd->msrs[2] = MSR_PKG_PERF_STATUS; + rd->msrs[3] = 0; + rd->msrs[4] = MSR_PKG_POWER_INFO; + rd->rpl[0].prim_id = PL1_ENABLE; + rd->rpl[0].name = pl1_name; + rd->rpl[1].prim_id = PL2_ENABLE; + rd->rpl[1].name = pl2_name; + break; + case BIT(RAPL_DOMAIN_PP0): + rd->name = rapl_domain_names[RAPL_DOMAIN_PP0]; + rd->id = RAPL_DOMAIN_PP0; + rd->msrs[0] = MSR_PP0_POWER_LIMIT; + rd->msrs[1] = MSR_PP0_ENERGY_STATUS; + rd->msrs[2] = 0; + rd->msrs[3] = MSR_PP0_POLICY; + rd->msrs[4] = 0; + rd->rpl[0].prim_id = PL1_ENABLE; + rd->rpl[0].name = pl1_name; + break; + case BIT(RAPL_DOMAIN_PP1): + rd->name = rapl_domain_names[RAPL_DOMAIN_PP1]; + rd->id = RAPL_DOMAIN_PP1; + rd->msrs[0] = MSR_PP1_POWER_LIMIT; + rd->msrs[1] = MSR_PP1_ENERGY_STATUS; + rd->msrs[2] = 0; + rd->msrs[3] = MSR_PP1_POLICY; + rd->msrs[4] = 0; + rd->rpl[0].prim_id = PL1_ENABLE; + rd->rpl[0].name = pl1_name; + break; + case BIT(RAPL_DOMAIN_DRAM): + rd->name = rapl_domain_names[RAPL_DOMAIN_DRAM]; + rd->id = RAPL_DOMAIN_DRAM; + rd->msrs[0] = MSR_DRAM_POWER_LIMIT; + rd->msrs[1] = MSR_DRAM_ENERGY_STATUS; + rd->msrs[2] = MSR_DRAM_PERF_STATUS; + rd->msrs[3] = 0; + rd->msrs[4] = MSR_DRAM_POWER_INFO; + rd->rpl[0].prim_id = PL1_ENABLE; + rd->rpl[0].name = pl1_name; + break; + } + if (mask) { + rd->package_id = rp->id; + rd++; + } + } +} + +static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value, + int to_raw) +{ + u64 divisor = 1; + int scale = 1; /* scale to user friendly data without floating point */ + u64 f, y; /* fraction and exp. used for time unit */ + struct rapl_package *rp; + + rp = find_package_by_id(package); + if (!rp) + return value; + + switch (type) { + case POWER_UNIT: + divisor = rp->power_unit_divisor; + scale = POWER_UNIT_SCALE; + break; + case ENERGY_UNIT: + scale = ENERGY_UNIT_SCALE; + divisor = rp->energy_unit_divisor; + break; + case TIME_UNIT: + divisor = rp->time_unit_divisor; + scale = TIME_UNIT_SCALE; + /* special processing based on 2^Y*(1+F)/4 = val/divisor, refer + * to Intel Software Developer's manual Vol. 3a, CH 14.7.4. + */ + if (!to_raw) { + f = (value & 0x60) >> 5; + y = value & 0x1f; + value = (1 << y) * (4 + f) * scale / 4; + return div64_u64(value, divisor); + } else { + do_div(value, scale); + value *= divisor; + y = ilog2(value); + f = div64_u64(4 * (value - (1 << y)), 1 << y); + value = (y & 0x1f) | ((f & 0x3) << 5); + return value; + } + break; + case ARBITRARY_UNIT: + default: + return value; + }; + + if (to_raw) + return div64_u64(value * divisor, scale); + else + return div64_u64(value * scale, divisor); +} + +/* in the order of enum rapl_primitives */ +static struct rapl_primitive_info rpi[] = { + /* name, mask, shift, msr index, unit divisor */ + PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0, + RAPL_DOMAIN_MSR_STATUS, ENERGY_UNIT, 0), + PRIMITIVE_INFO_INIT(POWER_LIMIT1, POWER_LIMIT1_MASK, 0, + RAPL_DOMAIN_MSR_LIMIT, POWER_UNIT, 0), + PRIMITIVE_INFO_INIT(POWER_LIMIT2, POWER_LIMIT2_MASK, 32, + RAPL_DOMAIN_MSR_LIMIT, POWER_UNIT, 0), + PRIMITIVE_INFO_INIT(FW_LOCK, POWER_PP_LOCK, 31, + RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0), + PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15, + RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0), + PRIMITIVE_INFO_INIT(PL1_CLAMP, POWER_LIMIT1_CLAMP, 16, + RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0), + PRIMITIVE_INFO_INIT(PL2_ENABLE, POWER_LIMIT2_ENABLE, 47, + RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0), + PRIMITIVE_INFO_INIT(PL2_CLAMP, POWER_LIMIT2_CLAMP, 48, + RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0), + PRIMITIVE_INFO_INIT(TIME_WINDOW1, TIME_WINDOW1_MASK, 17, + RAPL_DOMAIN_MSR_LIMIT, TIME_UNIT, 0), + PRIMITIVE_INFO_INIT(TIME_WINDOW2, TIME_WINDOW2_MASK, 49, + RAPL_DOMAIN_MSR_LIMIT, TIME_UNIT, 0), + PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, POWER_INFO_THERMAL_SPEC_MASK, + 0, RAPL_DOMAIN_MSR_INFO, POWER_UNIT, 0), + PRIMITIVE_INFO_INIT(MAX_POWER, POWER_INFO_MAX_MASK, 32, + RAPL_DOMAIN_MSR_INFO, POWER_UNIT, 0), + PRIMITIVE_INFO_INIT(MIN_POWER, POWER_INFO_MIN_MASK, 16, + RAPL_DOMAIN_MSR_INFO, POWER_UNIT, 0), + PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, POWER_INFO_MAX_TIME_WIN_MASK, 48, + RAPL_DOMAIN_MSR_INFO, TIME_UNIT, 0), + PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0, + RAPL_DOMAIN_MSR_PERF, TIME_UNIT, 0), + PRIMITIVE_INFO_INIT(PRIORITY_LEVEL, PP_POLICY_MASK, 0, + RAPL_DOMAIN_MSR_POLICY, ARBITRARY_UNIT, 0), + /* non-hardware */ + PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0, POWER_UNIT, + RAPL_PRIMITIVE_DERIVED), + {NULL, 0, 0, 0}, +}; + +/* Read primitive data based on its related struct rapl_primitive_info. + * if xlate flag is set, return translated data based on data units, i.e. + * time, energy, and power. + * RAPL MSRs are non-architectual and are laid out not consistently across + * domains. Here we use primitive info to allow writing consolidated access + * functions. + * For a given primitive, it is processed by MSR mask and shift. Unit conversion + * is pre-assigned based on RAPL unit MSRs read at init time. + * 63-------------------------- 31--------------------------- 0 + * | xxxxx (mask) | + * | |<- shift ----------------| + * 63-------------------------- 31--------------------------- 0 + */ +static int rapl_read_data_raw(struct rapl_domain *rd, + enum rapl_primitives prim, + bool xlate, u64 *data) +{ + u64 value, final; + u32 msr; + struct rapl_primitive_info *rp = &rpi[prim]; + int cpu; + + if (!rp->name || rp->flag & RAPL_PRIMITIVE_DUMMY) + return -EINVAL; + + msr = rd->msrs[rp->id]; + if (!msr) + return -EINVAL; + /* use physical package id to look up active cpus */ + cpu = find_active_cpu_on_package(rd->package_id); + if (cpu < 0) + return cpu; + + /* special-case package domain, which uses a different bit*/ + if (prim == FW_LOCK && rd->id == RAPL_DOMAIN_PACKAGE) { + rp->mask = POWER_PACKAGE_LOCK; + rp->shift = 63; + } + /* non-hardware data are collected by the polling thread */ + if (rp->flag & RAPL_PRIMITIVE_DERIVED) { + *data = rd->rdd.primitives[prim]; + return 0; + } + + if (rdmsrl_safe_on_cpu(cpu, msr, &value)) { + pr_debug("failed to read msr 0x%x on cpu %d\n", msr, cpu); + return -EIO; + } + + final = value & rp->mask; + final = final >> rp->shift; + if (xlate) + *data = rapl_unit_xlate(rd->package_id, rp->unit, final, 0); + else + *data = final; + + return 0; +} + +/* Similar use of primitive info in the read counterpart */ +static int rapl_write_data_raw(struct rapl_domain *rd, + enum rapl_primitives prim, + unsigned long long value) +{ + u64 msr_val; + u32 msr; + struct rapl_primitive_info *rp = &rpi[prim]; + int cpu; + + cpu = find_active_cpu_on_package(rd->package_id); + if (cpu < 0) + return cpu; + msr = rd->msrs[rp->id]; + if (rdmsrl_safe_on_cpu(cpu, msr, &msr_val)) { + dev_dbg(&rd->power_zone.dev, + "failed to read msr 0x%x on cpu %d\n", msr, cpu); + return -EIO; + } + value = rapl_unit_xlate(rd->package_id, rp->unit, value, 1); + msr_val &= ~rp->mask; + msr_val |= value << rp->shift; + if (wrmsrl_safe_on_cpu(cpu, msr, msr_val)) { + dev_dbg(&rd->power_zone.dev, + "failed to write msr 0x%x on cpu %d\n", msr, cpu); + return -EIO; + } + + return 0; +} + +static int rapl_check_unit(struct rapl_package *rp, int cpu) +{ + u64 msr_val; + u32 value; + + if (rdmsrl_safe_on_cpu(cpu, MSR_RAPL_POWER_UNIT, &msr_val)) { + pr_err("Failed to read power unit MSR 0x%x on CPU %d, exit.\n", + MSR_RAPL_POWER_UNIT, cpu); + return -ENODEV; + } + + /* Raw RAPL data stored in MSRs are in certain scales. We need to + * convert them into standard units based on the divisors reported in + * the RAPL unit MSRs. + * i.e. + * energy unit: 1/enery_unit_divisor Joules + * power unit: 1/power_unit_divisor Watts + * time unit: 1/time_unit_divisor Seconds + */ + value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET; + rp->energy_unit_divisor = 1 << value; + + + value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET; + rp->power_unit_divisor = 1 << value; + + value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET; + rp->time_unit_divisor = 1 << value; + + pr_debug("Physical package %d units: energy=%d, time=%d, power=%d\n", + rp->id, + rp->energy_unit_divisor, + rp->time_unit_divisor, + rp->power_unit_divisor); + + return 0; +} + +/* REVISIT: + * When package power limit is set artificially low by RAPL, LVT + * thermal interrupt for package power limit should be ignored + * since we are not really exceeding the real limit. The intention + * is to avoid excessive interrupts while we are trying to save power. + * A useful feature might be routing the package_power_limit interrupt + * to userspace via eventfd. once we have a usecase, this is simple + * to do by adding an atomic notifier. + */ + +static void package_power_limit_irq_save(int package_id) +{ + u32 l, h = 0; + int cpu; + struct rapl_package *rp; + + rp = find_package_by_id(package_id); + if (!rp) + return; + + if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN)) + return; + + cpu = find_active_cpu_on_package(package_id); + if (cpu < 0) + return; + /* save the state of PLN irq mask bit before disabling it */ + rdmsr_safe_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h); + if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) { + rp->power_limit_irq = l & PACKAGE_THERM_INT_PLN_ENABLE; + rp->power_limit_irq |= PACKAGE_PLN_INT_SAVED; + } + l &= ~PACKAGE_THERM_INT_PLN_ENABLE; + wrmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); +} + +/* restore per package power limit interrupt enable state */ +static void package_power_limit_irq_restore(int package_id) +{ + u32 l, h; + int cpu; + struct rapl_package *rp; + + rp = find_package_by_id(package_id); + if (!rp) + return; + + if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN)) + return; + + cpu = find_active_cpu_on_package(package_id); + if (cpu < 0) + return; + + /* irq enable state not saved, nothing to restore */ + if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) + return; + rdmsr_safe_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h); + + if (rp->power_limit_irq & PACKAGE_THERM_INT_PLN_ENABLE) + l |= PACKAGE_THERM_INT_PLN_ENABLE; + else + l &= ~PACKAGE_THERM_INT_PLN_ENABLE; + + wrmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); +} + +static const struct x86_cpu_id rapl_ids[] = { + { X86_VENDOR_INTEL, 6, 0x2a},/* SNB */ + { X86_VENDOR_INTEL, 6, 0x2d},/* SNB EP */ + { X86_VENDOR_INTEL, 6, 0x3a},/* IVB */ + { X86_VENDOR_INTEL, 6, 0x45},/* HSW */ + /* TODO: Add more CPU IDs after testing */ + {} +}; +MODULE_DEVICE_TABLE(x86cpu, rapl_ids); + +/* read once for all raw primitive data for all packages, domains */ +static void rapl_update_domain_data(void) +{ + int dmn, prim; + u64 val; + struct rapl_package *rp; + + list_for_each_entry(rp, &rapl_packages, plist) { + for (dmn = 0; dmn < rp->nr_domains; dmn++) { + pr_debug("update package %d domain %s data\n", rp->id, + rp->domains[dmn].name); + /* exclude non-raw primitives */ + for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++) + if (!rapl_read_data_raw(&rp->domains[dmn], prim, + rpi[prim].unit, + &val)) + rp->domains[dmn].rdd.primitives[prim] = + val; + } + } + +} + +static int rapl_unregister_powercap(void) +{ + struct rapl_package *rp; + struct rapl_domain *rd, *rd_package = NULL; + + /* unregister all active rapl packages from the powercap layer, + * hotplug lock held + */ + list_for_each_entry(rp, &rapl_packages, plist) { + package_power_limit_irq_restore(rp->id); + + for (rd = rp->domains; rd < rp->domains + rp->nr_domains; + rd++) { + pr_debug("remove package, undo power limit on %d: %s\n", + rp->id, rd->name); + rapl_write_data_raw(rd, PL1_ENABLE, 0); + rapl_write_data_raw(rd, PL2_ENABLE, 0); + rapl_write_data_raw(rd, PL1_CLAMP, 0); + rapl_write_data_raw(rd, PL2_CLAMP, 0); + if (rd->id == RAPL_DOMAIN_PACKAGE) { + rd_package = rd; + continue; + } + powercap_unregister_zone(control_type, &rd->power_zone); + } + /* do the package zone last */ + if (rd_package) + powercap_unregister_zone(control_type, + &rd_package->power_zone); + } + powercap_unregister_control_type(control_type); + + return 0; +} + +static int rapl_package_register_powercap(struct rapl_package *rp) +{ + struct rapl_domain *rd; + int ret = 0; + char dev_name[17]; /* max domain name = 7 + 1 + 8 for int + 1 for null*/ + struct powercap_zone *power_zone = NULL; + int nr_pl; + + /* first we register package domain as the parent zone*/ + for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) { + if (rd->id == RAPL_DOMAIN_PACKAGE) { + nr_pl = find_nr_power_limit(rd); + pr_debug("register socket %d package domain %s\n", + rp->id, rd->name); + memset(dev_name, 0, sizeof(dev_name)); + snprintf(dev_name, sizeof(dev_name), "%s-%d", + rd->name, rp->id); + power_zone = powercap_register_zone(&rd->power_zone, + control_type, + dev_name, NULL, + &zone_ops[rd->id], + nr_pl, + &constraint_ops); + if (IS_ERR(power_zone)) { + pr_debug("failed to register package, %d\n", + rp->id); + ret = PTR_ERR(power_zone); + goto exit_package; + } + /* track parent zone in per package/socket data */ + rp->power_zone = power_zone; + /* done, only one package domain per socket */ + break; + } + } + if (!power_zone) { + pr_err("no package domain found, unknown topology!\n"); + ret = -ENODEV; + goto exit_package; + } + /* now register domains as children of the socket/package*/ + for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) { + if (rd->id == RAPL_DOMAIN_PACKAGE) + continue; + /* number of power limits per domain varies */ + nr_pl = find_nr_power_limit(rd); + power_zone = powercap_register_zone(&rd->power_zone, + control_type, rd->name, + rp->power_zone, + &zone_ops[rd->id], nr_pl, + &constraint_ops); + + if (IS_ERR(power_zone)) { + pr_debug("failed to register power_zone, %d:%s:%s\n", + rp->id, rd->name, dev_name); + ret = PTR_ERR(power_zone); + goto err_cleanup; + } + } + +exit_package: + return ret; +err_cleanup: + /* clean up previously initialized domains within the package if we + * failed after the first domain setup. + */ + while (--rd >= rp->domains) { + pr_debug("unregister package %d domain %s\n", rp->id, rd->name); + powercap_unregister_zone(control_type, &rd->power_zone); + } + + return ret; +} + +static int rapl_register_powercap(void) +{ + struct rapl_domain *rd; + struct rapl_package *rp; + int ret = 0; + + control_type = powercap_register_control_type(NULL, "intel-rapl", NULL); + if (IS_ERR(control_type)) { + pr_debug("failed to register powercap control_type.\n"); + return PTR_ERR(control_type); + } + /* read the initial data */ + rapl_update_domain_data(); + list_for_each_entry(rp, &rapl_packages, plist) + if (rapl_package_register_powercap(rp)) + goto err_cleanup_package; + return ret; + +err_cleanup_package: + /* clean up previously initialized packages */ + list_for_each_entry_continue_reverse(rp, &rapl_packages, plist) { + for (rd = rp->domains; rd < rp->domains + rp->nr_domains; + rd++) { + pr_debug("unregister zone/package %d, %s domain\n", + rp->id, rd->name); + powercap_unregister_zone(control_type, &rd->power_zone); + } + } + + return ret; +} + +static int rapl_check_domain(int cpu, int domain) +{ + unsigned msr; + u64 val1, val2 = 0; + int retry = 0; + + switch (domain) { + case RAPL_DOMAIN_PACKAGE: + msr = MSR_PKG_ENERGY_STATUS; + break; + case RAPL_DOMAIN_PP0: + msr = MSR_PP0_ENERGY_STATUS; + break; + case RAPL_DOMAIN_PP1: + msr = MSR_PP1_ENERGY_STATUS; + break; + case RAPL_DOMAIN_DRAM: + msr = MSR_DRAM_ENERGY_STATUS; + break; + default: + pr_err("invalid domain id %d\n", domain); + return -EINVAL; + } + if (rdmsrl_safe_on_cpu(cpu, msr, &val1)) + return -ENODEV; + + /* energy counters roll slowly on some domains */ + while (++retry < 10) { + usleep_range(10000, 15000); + rdmsrl_safe_on_cpu(cpu, msr, &val2); + if ((val1 & ENERGY_STATUS_MASK) != (val2 & ENERGY_STATUS_MASK)) + return 0; + } + /* if energy counter does not change, report as bad domain */ + pr_info("domain %s energy ctr %llu:%llu not working, skip\n", + rapl_domain_names[domain], val1, val2); + + return -ENODEV; +} + +/* Detect active and valid domains for the given CPU, caller must + * ensure the CPU belongs to the targeted package and CPU hotlug is disabled. + */ +static int rapl_detect_domains(struct rapl_package *rp, int cpu) +{ + int i; + int ret = 0; + struct rapl_domain *rd; + u64 locked; + + for (i = 0; i < RAPL_DOMAIN_MAX; i++) { + /* use physical package id to read counters */ + if (!rapl_check_domain(cpu, i)) + rp->domain_map |= 1 << i; + } + rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX); + if (!rp->nr_domains) { + pr_err("no valid rapl domains found in package %d\n", rp->id); + ret = -ENODEV; + goto done; + } + pr_debug("found %d domains on package %d\n", rp->nr_domains, rp->id); + + rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain), + GFP_KERNEL); + if (!rp->domains) { + ret = -ENOMEM; + goto done; + } + rapl_init_domains(rp); + + for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) { + /* check if the domain is locked by BIOS */ + if (rapl_read_data_raw(rd, FW_LOCK, false, &locked)) { + pr_info("RAPL package %d domain %s locked by BIOS\n", + rp->id, rd->name); + rd->state |= DOMAIN_STATE_BIOS_LOCKED; + } + } + + +done: + return ret; +} + +static bool is_package_new(int package) +{ + struct rapl_package *rp; + + /* caller prevents cpu hotplug, there will be no new packages added + * or deleted while traversing the package list, no need for locking. + */ + list_for_each_entry(rp, &rapl_packages, plist) + if (package == rp->id) + return false; + + return true; +} + +/* RAPL interface can be made of a two-level hierarchy: package level and domain + * level. We first detect the number of packages then domains of each package. + * We have to consider the possiblity of CPU online/offline due to hotplug and + * other scenarios. + */ +static int rapl_detect_topology(void) +{ + int i; + int phy_package_id; + struct rapl_package *new_package, *rp; + + for_each_online_cpu(i) { + phy_package_id = topology_physical_package_id(i); + if (is_package_new(phy_package_id)) { + new_package = kzalloc(sizeof(*rp), GFP_KERNEL); + if (!new_package) { + rapl_cleanup_data(); + return -ENOMEM; + } + /* add the new package to the list */ + new_package->id = phy_package_id; + new_package->nr_cpus = 1; + + /* check if the package contains valid domains */ + if (rapl_detect_domains(new_package, i) || + rapl_check_unit(new_package, i)) { + kfree(new_package->domains); + kfree(new_package); + /* free up the packages already initialized */ + rapl_cleanup_data(); + return -ENODEV; + } + INIT_LIST_HEAD(&new_package->plist); + list_add(&new_package->plist, &rapl_packages); + } else { + rp = find_package_by_id(phy_package_id); + if (rp) + ++rp->nr_cpus; + } + } + + return 0; +} + +/* called from CPU hotplug notifier, hotplug lock held */ +static void rapl_remove_package(struct rapl_package *rp) +{ + struct rapl_domain *rd, *rd_package = NULL; + + for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) { + if (rd->id == RAPL_DOMAIN_PACKAGE) { + rd_package = rd; + continue; + } + pr_debug("remove package %d, %s domain\n", rp->id, rd->name); + powercap_unregister_zone(control_type, &rd->power_zone); + } + /* do parent zone last */ + powercap_unregister_zone(control_type, &rd_package->power_zone); + list_del(&rp->plist); + kfree(rp); +} + +/* called from CPU hotplug notifier, hotplug lock held */ +static int rapl_add_package(int cpu) +{ + int ret = 0; + int phy_package_id; + struct rapl_package *rp; + + phy_package_id = topology_physical_package_id(cpu); + rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL); + if (!rp) + return -ENOMEM; + + /* add the new package to the list */ + rp->id = phy_package_id; + rp->nr_cpus = 1; + /* check if the package contains valid domains */ + if (rapl_detect_domains(rp, cpu) || + rapl_check_unit(rp, cpu)) { + ret = -ENODEV; + goto err_free_package; + } + if (!rapl_package_register_powercap(rp)) { + INIT_LIST_HEAD(&rp->plist); + list_add(&rp->plist, &rapl_packages); + return ret; + } + +err_free_package: + kfree(rp->domains); + kfree(rp); + + return ret; +} + +/* Handles CPU hotplug on multi-socket systems. + * If a CPU goes online as the first CPU of the physical package + * we add the RAPL package to the system. Similarly, when the last + * CPU of the package is removed, we remove the RAPL package and its + * associated domains. Cooling devices are handled accordingly at + * per-domain level. + */ +static int rapl_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned long cpu = (unsigned long)hcpu; + int phy_package_id; + struct rapl_package *rp; + + phy_package_id = topology_physical_package_id(cpu); + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: + rp = find_package_by_id(phy_package_id); + if (rp) + ++rp->nr_cpus; + else + rapl_add_package(cpu); + break; + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + rp = find_package_by_id(phy_package_id); + if (!rp) + break; + if (--rp->nr_cpus == 0) + rapl_remove_package(rp); + } + + return NOTIFY_OK; +} + +static struct notifier_block rapl_cpu_notifier = { + .notifier_call = rapl_cpu_callback, +}; + +static int __init rapl_init(void) +{ + int ret = 0; + + if (!x86_match_cpu(rapl_ids)) { + pr_err("driver does not support CPU family %d model %d\n", + boot_cpu_data.x86, boot_cpu_data.x86_model); + + return -ENODEV; + } + /* prevent CPU hotplug during detection */ + get_online_cpus(); + ret = rapl_detect_topology(); + if (ret) + goto done; + + if (rapl_register_powercap()) { + rapl_cleanup_data(); + ret = -ENODEV; + goto done; + } + register_hotcpu_notifier(&rapl_cpu_notifier); +done: + put_online_cpus(); + + return ret; +} + +static void __exit rapl_exit(void) +{ + get_online_cpus(); + unregister_hotcpu_notifier(&rapl_cpu_notifier); + rapl_unregister_powercap(); + rapl_cleanup_data(); + put_online_cpus(); +} + +module_init(rapl_init); +module_exit(rapl_exit); + +MODULE_DESCRIPTION("Driver for Intel RAPL (Running Average Power Limit)"); +MODULE_AUTHOR("Jacob Pan "); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 70fea60d888d472ac044910fd0dc46b304419705 Mon Sep 17 00:00:00 2001 From: Benoit Goby Date: Thu, 17 Oct 2013 10:48:46 -0700 Subject: PM / Sleep: Detect device suspend/resume lockup and log event Rather than hard-lock the kernel, dump the suspend/resume thread stack and panic() to capture a message in pstore when a driver takes too long to suspend/resume. Default suspend/resume watchdog timeout is set to 12 seconds to be longer than the usbhid 10 second timeout, but could be changed at compile time. Exclude from the watchdog the time spent waiting for children that are resumed asynchronously and time every device, whether or not they resumed synchronously. This patch is targeted for mobile devices where a suspend/resume lockup could cause a system reboot. Information about failing device can be retrieved in subsequent boot session by mounting pstore and inspecting the log. Laptops with EFI-enabled pstore could also benefit from this feature. The hardware watchdog timer is likely suspended during this time and couldn't be relied upon. The soft-lockup detector would eventually tell that tasks are not scheduled, but would provide little context as to why. The patch hence uses system timer and assumes it is still active while the devices are suspended/resumed. This feature can be enabled/disabled during kernel configuration. This change is based on earlier work by San Mehat. Signed-off-by: Benoit Goby Signed-off-by: Zoran Markovic Acked-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 9f098a8..ee039af 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -30,6 +30,8 @@ #include #include #include +#include + #include "../base.h" #include "power.h" @@ -390,6 +392,71 @@ static int dpm_run_callback(pm_callback_t cb, struct device *dev, return error; } +#ifdef CONFIG_DPM_WATCHDOG +struct dpm_watchdog { + struct device *dev; + struct task_struct *tsk; + struct timer_list timer; +}; + +#define DECLARE_DPM_WATCHDOG_ON_STACK(wd) \ + struct dpm_watchdog wd + +/** + * dpm_watchdog_handler - Driver suspend / resume watchdog handler. + * @data: Watchdog object address. + * + * Called when a driver has timed out suspending or resuming. + * There's not much we can do here to recover so panic() to + * capture a crash-dump in pstore. + */ +static void dpm_watchdog_handler(unsigned long data) +{ + struct dpm_watchdog *wd = (void *)data; + + dev_emerg(wd->dev, "**** DPM device timeout ****\n"); + show_stack(wd->tsk, NULL); + panic("%s %s: unrecoverable failure\n", + dev_driver_string(wd->dev), dev_name(wd->dev)); +} + +/** + * dpm_watchdog_set - Enable pm watchdog for given device. + * @wd: Watchdog. Must be allocated on the stack. + * @dev: Device to handle. + */ +static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev) +{ + struct timer_list *timer = &wd->timer; + + wd->dev = dev; + wd->tsk = current; + + init_timer_on_stack(timer); + /* use same timeout value for both suspend and resume */ + timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_TIMEOUT; + timer->function = dpm_watchdog_handler; + timer->data = (unsigned long)wd; + add_timer(timer); +} + +/** + * dpm_watchdog_clear - Disable suspend/resume watchdog. + * @wd: Watchdog to disable. + */ +static void dpm_watchdog_clear(struct dpm_watchdog *wd) +{ + struct timer_list *timer = &wd->timer; + + del_timer_sync(timer); + destroy_timer_on_stack(timer); +} +#else +#define DECLARE_DPM_WATCHDOG_ON_STACK(wd) +#define dpm_watchdog_set(x, y) +#define dpm_watchdog_clear(x) +#endif + /*------------------------- Resume routines -------------------------*/ /** @@ -576,6 +643,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) pm_callback_t callback = NULL; char *info = NULL; int error = 0; + DECLARE_DPM_WATCHDOG_ON_STACK(wd); TRACE_DEVICE(dev); TRACE_RESUME(0); @@ -584,6 +652,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) goto Complete; dpm_wait(dev->parent, async); + dpm_watchdog_set(&wd, dev); device_lock(dev); /* @@ -642,6 +711,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) Unlock: device_unlock(dev); + dpm_watchdog_clear(&wd); Complete: complete_all(&dev->power.completion); @@ -1060,6 +1130,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) pm_callback_t callback = NULL; char *info = NULL; int error = 0; + DECLARE_DPM_WATCHDOG_ON_STACK(wd); dpm_wait_for_children(dev, async); @@ -1083,6 +1154,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) if (dev->power.syscore) goto Complete; + dpm_watchdog_set(&wd, dev); device_lock(dev); if (dev->pm_domain) { @@ -1139,6 +1211,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) } device_unlock(dev); + dpm_watchdog_clear(&wd); Complete: complete_all(&dev->power.completion); diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index d444c4e..2fac9cc 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -178,6 +178,22 @@ config PM_SLEEP_DEBUG def_bool y depends on PM_DEBUG && PM_SLEEP +config DPM_WATCHDOG + bool "Device suspend/resume watchdog" + depends on PM_DEBUG && PSTORE + ---help--- + Sets up a watchdog timer to capture drivers that are + locked up attempting to suspend/resume a device. + A detected lockup causes system panic with message + captured in pstore device for inspection in subsequent + boot session. + +config DPM_WATCHDOG_TIMEOUT + int "Watchdog timeout in seconds" + range 1 120 + default 12 + depends on DPM_WATCHDOG + config PM_TRACE bool help -- cgit v0.10.2 From 5e2be4e0edff4a1021b6743ca6859129cd8e7067 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 18 Oct 2013 12:01:43 +0300 Subject: ACPI / osl: remove an unneeded NULL check "str" is never NULL here so I have removed the check. There are static checkers which complain about superfluous NULL checks because it may indicate confusion or a bug. Signed-off-by: Dan Carpenter Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b1629b5..4923dd4 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1335,7 +1335,7 @@ static int __init acpi_os_name_setup(char *str) if (!str || !*str) return 0; - for (; count-- && str && *str; str++) { + for (; count-- && *str; str++) { if (isalnum(*str) || *str == ' ' || *str == ':') *p++ = *str; else if (*str == '\'' || *str == '"') -- cgit v0.10.2 From 7bc9b1cffc95675a957e870d258e95d43dcbba0b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 18 Oct 2013 22:20:40 +0200 Subject: PM / Hibernate: Use bool for boolean fields of struct snapshot_data The snapshot_data structure used internally by the hibernate user space interface code in user.c has three char fields that are used to store boolean values. Change their data type to bool and use true and false instead of 1 and 0, respectively, in assignments involving those fields. Signed-off-by: Rafael J. Wysocki diff --git a/kernel/power/user.c b/kernel/power/user.c index 957f061..2485027 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -36,9 +36,9 @@ static struct snapshot_data { struct snapshot_handle handle; int swap; int mode; - char frozen; - char ready; - char platform_support; + bool frozen; + bool ready; + bool platform_support; bool free_bitmaps; } snapshot_state; @@ -93,9 +93,9 @@ static int snapshot_open(struct inode *inode, struct file *filp) if (error) atomic_inc(&snapshot_device_available); - data->frozen = 0; - data->ready = 0; - data->platform_support = 0; + data->frozen = false; + data->ready = false; + data->platform_support = false; Unlock: unlock_system_sleep(); @@ -229,7 +229,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, if (error) thaw_processes(); else - data->frozen = 1; + data->frozen = true; break; @@ -240,7 +240,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, free_basic_memory_bitmaps(); data->free_bitmaps = false; thaw_processes(); - data->frozen = 0; + data->frozen = false; break; case SNAPSHOT_CREATE_IMAGE: @@ -270,7 +270,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, case SNAPSHOT_FREE: swsusp_free(); memset(&data->handle, 0, sizeof(struct snapshot_handle)); - data->ready = 0; + data->ready = false; /* * It is necessary to thaw kernel threads here, because * SNAPSHOT_CREATE_IMAGE may be invoked directly after @@ -334,7 +334,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, * PM_HIBERNATION_PREPARE */ error = suspend_devices_and_enter(PM_SUSPEND_MEM); - data->ready = 0; + data->ready = false; break; case SNAPSHOT_PLATFORM_SUPPORT: -- cgit v0.10.2 From 5d4879cda67b09f086807821cf594ee079d6dfbe Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 19 Sep 2013 16:03:50 -0500 Subject: PM / OPP: rename functions to dev_pm_opp* Since Operating Performance Points (OPP) functions are specific to device specific power management, be specific and rename opp_* accessors in OPP library with dev_pm_opp_* equivalent. Affected functions are: opp_get_voltage opp_get_freq opp_get_opp_count opp_find_freq_exact opp_find_freq_floor opp_find_freq_ceil opp_add opp_enable opp_disable opp_get_notifier opp_init_cpufreq_table opp_free_cpufreq_table Reported-by: Randy Dunlap Signed-off-by: Nishanth Menon Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt index 425c51d..185367b 100644 --- a/Documentation/power/opp.txt +++ b/Documentation/power/opp.txt @@ -71,14 +71,14 @@ operations until that OPP could be re-enabled if possible. OPP library facilitates this concept in it's implementation. The following operational functions operate only on available opps: -opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count -and opp_init_cpufreq_table +opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count +and dev_pm_opp_init_cpufreq_table -opp_find_freq_exact is meant to be used to find the opp pointer which can then -be used for opp_enable/disable functions to make an opp available as required. +dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer which can then +be used for dev_pm_opp_enable/disable functions to make an opp available as required. WARNING: Users of OPP library should refresh their availability count using -get_opp_count if opp_enable/disable functions are invoked for a device, the +get_opp_count if dev_pm_opp_enable/disable functions are invoked for a device, the exact mechanism to trigger these or the notification mechanism to other dependent subsystems such as cpufreq are left to the discretion of the SoC specific framework which uses the OPP library. Similar care needs to be taken @@ -96,24 +96,24 @@ using RCU read locks. The opp_find_freq_{exact,ceil,floor}, opp_get_{voltage, freq, opp_count} fall into this category. opp_{add,enable,disable} are updaters which use mutex and implement it's own -RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses +RCU locking mechanisms. dev_pm_opp_init_cpufreq_table acts as an updater and uses mutex to implment RCU updater strategy. These functions should *NOT* be called under RCU locks and other contexts that prevent blocking functions in RCU or mutex operations from working. 2. Initial OPP List Registration ================================ -The SoC implementation calls opp_add function iteratively to add OPPs per +The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per device. It is expected that the SoC framework will register the OPP entries optimally- typical numbers range to be less than 5. The list generated by registering the OPPs is maintained by OPP library throughout the device operation. The SoC framework can subsequently control the availability of the -OPPs dynamically using the opp_enable / disable functions. +OPPs dynamically using the dev_pm_opp_enable / disable functions. -opp_add - Add a new OPP for a specific domain represented by the device pointer. +dev_pm_opp_add - Add a new OPP for a specific domain represented by the device pointer. The OPP is defined using the frequency and voltage. Once added, the OPP is assumed to be available and control of it's availability can be done - with the opp_enable/disable functions. OPP library internally stores + with the dev_pm_opp_enable/disable functions. OPP library internally stores and manages this information in the opp struct. This function may be used by SoC framework to define a optimal list as per the demands of SoC usage environment. @@ -124,7 +124,7 @@ opp_add - Add a new OPP for a specific domain represented by the device pointer. soc_pm_init() { /* Do things */ - r = opp_add(mpu_dev, 1000000, 900000); + r = dev_pm_opp_add(mpu_dev, 1000000, 900000); if (!r) { pr_err("%s: unable to register mpu opp(%d)\n", r); goto no_cpufreq; @@ -143,44 +143,44 @@ functions return the matching pointer representing the opp if a match is found, else returns error. These errors are expected to be handled by standard error checks such as IS_ERR() and appropriate actions taken by the caller. -opp_find_freq_exact - Search for an OPP based on an *exact* frequency and +dev_pm_opp_find_freq_exact - Search for an OPP based on an *exact* frequency and availability. This function is especially useful to enable an OPP which is not available by default. Example: In a case when SoC framework detects a situation where a higher frequency could be made available, it can use this function to - find the OPP prior to call the opp_enable to actually make it available. + find the OPP prior to call the dev_pm_opp_enable to actually make it available. rcu_read_lock(); - opp = opp_find_freq_exact(dev, 1000000000, false); + opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); rcu_read_unlock(); /* dont operate on the pointer.. just do a sanity check.. */ if (IS_ERR(opp)) { pr_err("frequency not disabled!\n"); /* trigger appropriate actions.. */ } else { - opp_enable(dev,1000000000); + dev_pm_opp_enable(dev,1000000000); } NOTE: This is the only search function that operates on OPPs which are not available. -opp_find_freq_floor - Search for an available OPP which is *at most* the +dev_pm_opp_find_freq_floor - Search for an available OPP which is *at most* the provided frequency. This function is useful while searching for a lesser match OR operating on OPP information in the order of decreasing frequency. Example: To find the highest opp for a device: freq = ULONG_MAX; rcu_read_lock(); - opp_find_freq_floor(dev, &freq); + dev_pm_opp_find_freq_floor(dev, &freq); rcu_read_unlock(); -opp_find_freq_ceil - Search for an available OPP which is *at least* the +dev_pm_opp_find_freq_ceil - Search for an available OPP which is *at least* the provided frequency. This function is useful while searching for a higher match OR operating on OPP information in the order of increasing frequency. Example 1: To find the lowest opp for a device: freq = 0; rcu_read_lock(); - opp_find_freq_ceil(dev, &freq); + dev_pm_opp_find_freq_ceil(dev, &freq); rcu_read_unlock(); Example 2: A simplified implementation of a SoC cpufreq_driver->target: soc_cpufreq_target(..) @@ -188,7 +188,7 @@ opp_find_freq_ceil - Search for an available OPP which is *at least* the /* Do stuff like policy checks etc. */ /* Find the best frequency match for the req */ rcu_read_lock(); - opp = opp_find_freq_ceil(dev, &freq); + opp = dev_pm_opp_find_freq_ceil(dev, &freq); rcu_read_unlock(); if (!IS_ERR(opp)) soc_switch_to_freq_voltage(freq); @@ -208,34 +208,34 @@ as thermal considerations (e.g. don't use OPPx until the temperature drops). WARNING: Do not use these functions in interrupt context. -opp_enable - Make a OPP available for operation. +dev_pm_opp_enable - Make a OPP available for operation. Example: Lets say that 1GHz OPP is to be made available only if the SoC temperature is lower than a certain threshold. The SoC framework implementation might choose to do something as follows: if (cur_temp < temp_low_thresh) { /* Enable 1GHz if it was disabled */ rcu_read_lock(); - opp = opp_find_freq_exact(dev, 1000000000, false); + opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); rcu_read_unlock(); /* just error check */ if (!IS_ERR(opp)) - ret = opp_enable(dev, 1000000000); + ret = dev_pm_opp_enable(dev, 1000000000); else goto try_something_else; } -opp_disable - Make an OPP to be not available for operation +dev_pm_opp_disable - Make an OPP to be not available for operation Example: Lets say that 1GHz OPP is to be disabled if the temperature exceeds a threshold value. The SoC framework implementation might choose to do something as follows: if (cur_temp > temp_high_thresh) { /* Disable 1GHz if it was enabled */ rcu_read_lock(); - opp = opp_find_freq_exact(dev, 1000000000, true); + opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); rcu_read_unlock(); /* just error check */ if (!IS_ERR(opp)) - ret = opp_disable(dev, 1000000000); + ret = dev_pm_opp_disable(dev, 1000000000); else goto try_something_else; } @@ -247,7 +247,7 @@ information from the OPP structure is necessary. Once an OPP pointer is retrieved using the search functions, the following functions can be used by SoC framework to retrieve the information represented inside the OPP layer. -opp_get_voltage - Retrieve the voltage represented by the opp pointer. +dev_pm_opp_get_voltage - Retrieve the voltage represented by the opp pointer. Example: At a cpufreq transition to a different frequency, SoC framework requires to set the voltage represented by the OPP using the regulator framework to the Power Management chip providing the @@ -256,15 +256,15 @@ opp_get_voltage - Retrieve the voltage represented by the opp pointer. { /* do things */ rcu_read_lock(); - opp = opp_find_freq_ceil(dev, &freq); - v = opp_get_voltage(opp); + opp = dev_pm_opp_find_freq_ceil(dev, &freq); + v = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); if (v) regulator_set_voltage(.., v); /* do other things */ } -opp_get_freq - Retrieve the freq represented by the opp pointer. +dev_pm_opp_get_freq - Retrieve the freq represented by the opp pointer. Example: Lets say the SoC framework uses a couple of helper functions we could pass opp pointers instead of doing additional parameters to handle quiet a bit of data parameters. @@ -273,8 +273,8 @@ opp_get_freq - Retrieve the freq represented by the opp pointer. /* do things.. */ max_freq = ULONG_MAX; rcu_read_lock(); - max_opp = opp_find_freq_floor(dev,&max_freq); - requested_opp = opp_find_freq_ceil(dev,&freq); + max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq); + requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq); if (!IS_ERR(max_opp) && !IS_ERR(requested_opp)) r = soc_test_validity(max_opp, requested_opp); rcu_read_unlock(); @@ -282,25 +282,25 @@ opp_get_freq - Retrieve the freq represented by the opp pointer. } soc_test_validity(..) { - if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp)) + if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp)) return -EINVAL; - if(opp_get_freq(max_opp) < opp_get_freq(requested_opp)) + if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp)) return -EINVAL; /* do things.. */ } -opp_get_opp_count - Retrieve the number of available opps for a device +dev_pm_opp_get_opp_count - Retrieve the number of available opps for a device Example: Lets say a co-processor in the SoC needs to know the available frequencies in a table, the main processor can notify as following: soc_notify_coproc_available_frequencies() { /* Do things */ rcu_read_lock(); - num_available = opp_get_opp_count(dev); + num_available = dev_pm_opp_get_opp_count(dev); speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL); /* populate the table in increasing order */ freq = 0; - while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) { + while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) { speeds[i] = freq; freq++; i++; @@ -313,7 +313,7 @@ opp_get_opp_count - Retrieve the number of available opps for a device 6. Cpufreq Table Generation =========================== -opp_init_cpufreq_table - cpufreq framework typically is initialized with +dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with cpufreq_frequency_table_cpuinfo which is provided with the list of frequencies that are available for operation. This function provides a ready to use conversion routine to translate the OPP layer's internal @@ -326,7 +326,7 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with soc_pm_init() { /* Do things */ - r = opp_init_cpufreq_table(dev, &freq_table); + r = dev_pm_opp_init_cpufreq_table(dev, &freq_table); if (!r) cpufreq_frequency_table_cpuinfo(policy, freq_table); /* Do other things */ @@ -336,7 +336,7 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with addition to CONFIG_PM as power management feature is required to dynamically scale voltage and frequency in a system. -opp_free_cpufreq_table - Free up the table allocated by opp_init_cpufreq_table +dev_pm_opp_free_cpufreq_table - Free up the table allocated by dev_pm_opp_init_cpufreq_table 7. Data Structures ================== @@ -366,8 +366,8 @@ struct opp - The internal data structure of OPP library which is used to identifier for OPP in the interactions with OPP layer. WARNING: The struct opp pointer should not be parsed or modified by the - users. The defaults of for an instance is populated by opp_add, but the - availability of the OPP can be modified by opp_enable/disable functions. + users. The defaults of for an instance is populated by dev_pm_opp_add, but the + availability of the OPP can be modified by dev_pm_opp_enable/disable functions. struct device - This is used to identify a domain to the OPP layer. The nature of the device and it's implementation is left to the user of @@ -377,19 +377,19 @@ Overall, in a simplistic view, the data structure operations is represented as following: Initialization / modification: - +-----+ /- opp_enable -opp_add --> | opp | <------- - | +-----+ \- opp_disable + +-----+ /- dev_pm_opp_enable +dev_pm_opp_add --> | opp | <------- + | +-----+ \- dev_pm_opp_disable \-------> domain_info(device) Search functions: - /-- opp_find_freq_ceil ---\ +-----+ -domain_info<---- opp_find_freq_exact -----> | opp | - \-- opp_find_freq_floor ---/ +-----+ + /-- dev_pm_opp_find_freq_ceil ---\ +-----+ +domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | + \-- dev_pm_opp_find_freq_floor ---/ +-----+ Retrieval functions: -+-----+ /- opp_get_voltage ++-----+ /- dev_pm_opp_get_voltage | opp | <--- -+-----+ \- opp_get_freq ++-----+ \- dev_pm_opp_get_freq -domain_info <- opp_get_opp_count +domain_info <- dev_pm_opp_get_opp_count diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 90372a2..d7ecc90 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -226,7 +226,7 @@ static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev) val = readl_relaxed(base + OCOTP_CFG3); val >>= OCOTP_CFG3_SPEED_SHIFT; if ((val & 0x3) != OCOTP_CFG3_SPEED_1P2GHZ) - if (opp_disable(cpu_dev, 1200000000)) + if (dev_pm_opp_disable(cpu_dev, 1200000000)) pr_warn("failed to disable 1.2 GHz OPP\n"); put_node: diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index f269184..33969e5 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -522,11 +522,11 @@ static int __init beagle_opp_init(void) return -ENODEV; } /* Enable MPU 1GHz and lower opps */ - r = opp_enable(mpu_dev, 800000000); + r = dev_pm_opp_enable(mpu_dev, 800000000); /* TODO: MPU 1GHz needs SR and ABB */ /* Enable IVA 800MHz and lower opps */ - r |= opp_enable(iva_dev, 660000000); + r |= dev_pm_opp_enable(iva_dev, 660000000); /* TODO: DSP 800MHz needs SR and ABB */ if (r) { pr_err("%s: failed to enable higher opp %d\n", @@ -535,8 +535,8 @@ static int __init beagle_opp_init(void) * Cleanup - disable the higher freqs - we dont care * about the results */ - opp_disable(mpu_dev, 800000000); - opp_disable(iva_dev, 660000000); + dev_pm_opp_disable(mpu_dev, 800000000); + dev_pm_opp_disable(iva_dev, 660000000); } } return 0; diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c index bd41d59..7b04637 100644 --- a/arch/arm/mach-omap2/opp.c +++ b/arch/arm/mach-omap2/opp.c @@ -81,14 +81,14 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, dev = &oh->od->pdev->dev; } - r = opp_add(dev, opp_def->freq, opp_def->u_volt); + r = dev_pm_opp_add(dev, opp_def->freq, opp_def->u_volt); if (r) { dev_err(dev, "%s: add OPP %ld failed for %s [%d] result=%d\n", __func__, opp_def->freq, opp_def->hwmod_name, i, r); } else { if (!opp_def->default_available) - r = opp_disable(dev, opp_def->freq); + r = dev_pm_opp_disable(dev, opp_def->freq); if (r) dev_err(dev, "%s: disable %ld failed for %s [%d] result=%d\n", __func__, opp_def->freq, diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index e742118..937744c 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -172,7 +172,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, clk_put(clk); rcu_read_lock(); - opp = opp_find_freq_ceil(dev, &freq); + opp = dev_pm_opp_find_freq_ceil(dev, &freq); if (IS_ERR(opp)) { rcu_read_unlock(); pr_err("%s: unable to find boot up OPP for vdd_%s\n", @@ -180,7 +180,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, goto exit; } - bootup_volt = opp_get_voltage(opp); + bootup_volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); if (!bootup_volt) { pr_err("%s: unable to find voltage corresponding to the bootup OPP for vdd_%s\n", diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index ef89897..00c6a44 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c @@ -136,7 +136,7 @@ static struct device_opp *find_device_opp(struct device *dev) } /** - * opp_get_voltage() - Gets the voltage corresponding to an available opp + * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an available opp * @opp: opp for which voltage has to be returned for * * Return voltage in micro volt corresponding to the opp, else @@ -150,7 +150,7 @@ static struct device_opp *find_device_opp(struct device *dev) * prior to unlocking with rcu_read_unlock() to maintain the integrity of the * pointer. */ -unsigned long opp_get_voltage(struct opp *opp) +unsigned long dev_pm_opp_get_voltage(struct opp *opp) { struct opp *tmp_opp; unsigned long v = 0; @@ -163,10 +163,10 @@ unsigned long opp_get_voltage(struct opp *opp) return v; } -EXPORT_SYMBOL_GPL(opp_get_voltage); +EXPORT_SYMBOL_GPL(dev_pm_opp_get_voltage); /** - * opp_get_freq() - Gets the frequency corresponding to an available opp + * dev_pm_opp_get_freq() - Gets the frequency corresponding to an available opp * @opp: opp for which frequency has to be returned for * * Return frequency in hertz corresponding to the opp, else @@ -180,7 +180,7 @@ EXPORT_SYMBOL_GPL(opp_get_voltage); * prior to unlocking with rcu_read_unlock() to maintain the integrity of the * pointer. */ -unsigned long opp_get_freq(struct opp *opp) +unsigned long dev_pm_opp_get_freq(struct opp *opp) { struct opp *tmp_opp; unsigned long f = 0; @@ -193,10 +193,10 @@ unsigned long opp_get_freq(struct opp *opp) return f; } -EXPORT_SYMBOL_GPL(opp_get_freq); +EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq); /** - * opp_get_opp_count() - Get number of opps available in the opp list + * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list * @dev: device for which we do this operation * * This function returns the number of available opps if there are any, @@ -206,7 +206,7 @@ EXPORT_SYMBOL_GPL(opp_get_freq); * internally references two RCU protected structures: device_opp and opp which * are safe as long as we are under a common RCU locked section. */ -int opp_get_opp_count(struct device *dev) +int dev_pm_opp_get_opp_count(struct device *dev) { struct device_opp *dev_opp; struct opp *temp_opp; @@ -226,10 +226,10 @@ int opp_get_opp_count(struct device *dev) return count; } -EXPORT_SYMBOL_GPL(opp_get_opp_count); +EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count); /** - * opp_find_freq_exact() - search for an exact frequency + * dev_pm_opp_find_freq_exact() - search for an exact frequency * @dev: device for which we do this operation * @freq: frequency to search for * @available: true/false - match for available opp @@ -254,7 +254,7 @@ EXPORT_SYMBOL_GPL(opp_get_opp_count); * under the locked area. The pointer returned must be used prior to unlocking * with rcu_read_unlock() to maintain the integrity of the pointer. */ -struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq, +struct opp *dev_pm_opp_find_freq_exact(struct device *dev, unsigned long freq, bool available) { struct device_opp *dev_opp; @@ -277,10 +277,10 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq, return opp; } -EXPORT_SYMBOL_GPL(opp_find_freq_exact); +EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact); /** - * opp_find_freq_ceil() - Search for an rounded ceil freq + * dev_pm_opp_find_freq_ceil() - Search for an rounded ceil freq * @dev: device for which we do this operation * @freq: Start frequency * @@ -300,7 +300,7 @@ EXPORT_SYMBOL_GPL(opp_find_freq_exact); * under the locked area. The pointer returned must be used prior to unlocking * with rcu_read_unlock() to maintain the integrity of the pointer. */ -struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq) +struct opp *dev_pm_opp_find_freq_ceil(struct device *dev, unsigned long *freq) { struct device_opp *dev_opp; struct opp *temp_opp, *opp = ERR_PTR(-ERANGE); @@ -324,10 +324,10 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq) return opp; } -EXPORT_SYMBOL_GPL(opp_find_freq_ceil); +EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil); /** - * opp_find_freq_floor() - Search for a rounded floor freq + * dev_pm_opp_find_freq_floor() - Search for a rounded floor freq * @dev: device for which we do this operation * @freq: Start frequency * @@ -347,7 +347,7 @@ EXPORT_SYMBOL_GPL(opp_find_freq_ceil); * under the locked area. The pointer returned must be used prior to unlocking * with rcu_read_unlock() to maintain the integrity of the pointer. */ -struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq) +struct opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq) { struct device_opp *dev_opp; struct opp *temp_opp, *opp = ERR_PTR(-ERANGE); @@ -375,17 +375,17 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq) return opp; } -EXPORT_SYMBOL_GPL(opp_find_freq_floor); +EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor); /** - * opp_add() - Add an OPP table from a table definitions + * dev_pm_opp_add() - Add an OPP table from a table definitions * @dev: device for which we do this operation * @freq: Frequency in Hz for this OPP * @u_volt: Voltage in uVolts for this OPP * * This function adds an opp definition to the opp list and returns status. * The opp is made available by default and it can be controlled using - * opp_enable/disable functions. + * dev_pm_opp_enable/disable functions. * * Locking: The internal device_opp and opp structures are RCU protected. * Hence this function internally uses RCU updater strategy with mutex locks @@ -393,7 +393,7 @@ EXPORT_SYMBOL_GPL(opp_find_freq_floor); * that this function is *NOT* called under RCU protection or in contexts where * mutex cannot be locked. */ -int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) +int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) { struct device_opp *dev_opp = NULL; struct opp *opp, *new_opp; @@ -460,7 +460,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp); return 0; } -EXPORT_SYMBOL_GPL(opp_add); +EXPORT_SYMBOL_GPL(dev_pm_opp_add); /** * opp_set_availability() - helper to set the availability of an opp @@ -552,13 +552,13 @@ unlock: } /** - * opp_enable() - Enable a specific OPP + * dev_pm_opp_enable() - Enable a specific OPP * @dev: device for which we do this operation * @freq: OPP frequency to enable * * Enables a provided opp. If the operation is valid, this returns 0, else the * corresponding error value. It is meant to be used for users an OPP available - * after being temporarily made unavailable with opp_disable. + * after being temporarily made unavailable with dev_pm_opp_disable. * * Locking: The internal device_opp and opp structures are RCU protected. * Hence this function indirectly uses RCU and mutex locks to keep the @@ -566,21 +566,21 @@ unlock: * this function is *NOT* called under RCU protection or in contexts where * mutex locking or synchronize_rcu() blocking calls cannot be used. */ -int opp_enable(struct device *dev, unsigned long freq) +int dev_pm_opp_enable(struct device *dev, unsigned long freq) { return opp_set_availability(dev, freq, true); } -EXPORT_SYMBOL_GPL(opp_enable); +EXPORT_SYMBOL_GPL(dev_pm_opp_enable); /** - * opp_disable() - Disable a specific OPP + * dev_pm_opp_disable() - Disable a specific OPP * @dev: device for which we do this operation * @freq: OPP frequency to disable * * Disables a provided opp. If the operation is valid, this returns * 0, else the corresponding error value. It is meant to be a temporary * control by users to make this OPP not available until the circumstances are - * right to make it available again (with a call to opp_enable). + * right to make it available again (with a call to dev_pm_opp_enable). * * Locking: The internal device_opp and opp structures are RCU protected. * Hence this function indirectly uses RCU and mutex locks to keep the @@ -588,15 +588,15 @@ EXPORT_SYMBOL_GPL(opp_enable); * this function is *NOT* called under RCU protection or in contexts where * mutex locking or synchronize_rcu() blocking calls cannot be used. */ -int opp_disable(struct device *dev, unsigned long freq) +int dev_pm_opp_disable(struct device *dev, unsigned long freq) { return opp_set_availability(dev, freq, false); } -EXPORT_SYMBOL_GPL(opp_disable); +EXPORT_SYMBOL_GPL(dev_pm_opp_disable); #ifdef CONFIG_CPU_FREQ /** - * opp_init_cpufreq_table() - create a cpufreq table for a device + * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device * @dev: device for which we do this operation * @table: Cpufreq table returned back to caller * @@ -619,7 +619,7 @@ EXPORT_SYMBOL_GPL(opp_disable); * Callers should ensure that this function is *NOT* called under RCU protection * or in contexts where mutex locking cannot be used. */ -int opp_init_cpufreq_table(struct device *dev, +int dev_pm_opp_init_cpufreq_table(struct device *dev, struct cpufreq_frequency_table **table) { struct device_opp *dev_opp; @@ -639,7 +639,7 @@ int opp_init_cpufreq_table(struct device *dev, } freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * - (opp_get_opp_count(dev) + 1), GFP_KERNEL); + (dev_pm_opp_get_opp_count(dev) + 1), GFP_KERNEL); if (!freq_table) { mutex_unlock(&dev_opp_list_lock); dev_warn(dev, "%s: Unable to allocate frequency table\n", @@ -663,16 +663,16 @@ int opp_init_cpufreq_table(struct device *dev, return 0; } -EXPORT_SYMBOL_GPL(opp_init_cpufreq_table); +EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table); /** - * opp_free_cpufreq_table() - free the cpufreq table + * dev_pm_opp_free_cpufreq_table() - free the cpufreq table * @dev: device for which we do this operation * @table: table to free * - * Free up the table allocated by opp_init_cpufreq_table + * Free up the table allocated by dev_pm_opp_init_cpufreq_table */ -void opp_free_cpufreq_table(struct device *dev, +void dev_pm_opp_free_cpufreq_table(struct device *dev, struct cpufreq_frequency_table **table) { if (!table) @@ -681,14 +681,14 @@ void opp_free_cpufreq_table(struct device *dev, kfree(*table); *table = NULL; } -EXPORT_SYMBOL_GPL(opp_free_cpufreq_table); +EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table); #endif /* CONFIG_CPU_FREQ */ /** - * opp_get_notifier() - find notifier_head of the device with opp + * dev_pm_opp_get_notifier() - find notifier_head of the device with opp * @dev: device pointer used to lookup device OPPs. */ -struct srcu_notifier_head *opp_get_notifier(struct device *dev) +struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev) { struct device_opp *dev_opp = find_device_opp(dev); @@ -732,7 +732,7 @@ int of_init_opp_table(struct device *dev) unsigned long freq = be32_to_cpup(val++) * 1000; unsigned long volt = be32_to_cpup(val++); - if (opp_add(dev, freq, volt)) { + if (dev_pm_opp_add(dev, freq, volt)) { dev_warn(dev, "%s: Failed to add OPP %ld\n", __func__, freq); continue; diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 3549f07..9e82a9d 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -98,7 +98,7 @@ static void put_cluster_clk_and_freq_table(struct device *cpu_dev) if (!atomic_dec_return(&cluster_usage[cluster])) { clk_put(clk[cluster]); - opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]); + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]); dev_dbg(cpu_dev, "%s: cluster: %d\n", __func__, cluster); } } @@ -119,7 +119,7 @@ static int get_cluster_clk_and_freq_table(struct device *cpu_dev) goto atomic_dec; } - ret = opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]); + ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]); if (ret) { dev_err(cpu_dev, "%s: failed to init cpufreq table, cpu: %d, err: %d\n", __func__, cpu_dev->id, ret); @@ -138,7 +138,7 @@ static int get_cluster_clk_and_freq_table(struct device *cpu_dev) dev_err(cpu_dev, "%s: Failed to get clk for cpu: %d, cluster: %d\n", __func__, cpu_dev->id, cluster); ret = PTR_ERR(clk[cluster]); - opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]); + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]); atomic_dec: atomic_dec(&cluster_usage[cluster]); diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index c522a95..af951a9 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -72,7 +72,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, if (!IS_ERR(cpu_reg)) { rcu_read_lock(); - opp = opp_find_freq_ceil(cpu_dev, &freq_Hz); + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz); if (IS_ERR(opp)) { rcu_read_unlock(); pr_err("failed to find OPP for %ld\n", freq_Hz); @@ -80,7 +80,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, ret = PTR_ERR(opp); goto post_notify; } - volt = opp_get_voltage(opp); + volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); tol = volt * voltage_tolerance / 100; volt_old = regulator_get_voltage(cpu_reg); @@ -218,7 +218,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) goto out_put_node; } - ret = opp_init_cpufreq_table(cpu_dev, &freq_table); + ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); if (ret) { pr_err("failed to init cpufreq table: %d\n", ret); goto out_put_node; @@ -242,12 +242,12 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) ; rcu_read_lock(); - opp = opp_find_freq_exact(cpu_dev, + opp = dev_pm_opp_find_freq_exact(cpu_dev, freq_table[0].frequency * 1000, true); - min_uV = opp_get_voltage(opp); - opp = opp_find_freq_exact(cpu_dev, + min_uV = dev_pm_opp_get_voltage(opp); + opp = dev_pm_opp_find_freq_exact(cpu_dev, freq_table[i-1].frequency * 1000, true); - max_uV = opp_get_voltage(opp); + max_uV = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); if (ret > 0) @@ -264,7 +264,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) return 0; out_free_table: - opp_free_cpufreq_table(cpu_dev, &freq_table); + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); out_put_node: of_node_put(np); return ret; @@ -273,7 +273,7 @@ out_put_node: static int cpu0_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&cpu0_cpufreq_driver); - opp_free_cpufreq_table(cpu_dev, &freq_table); + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); return 0; } diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index be5380e..444eca7 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -123,7 +123,7 @@ static int init_div_table(void) rcu_read_lock(); for (i = 0; freq_tbl[i].frequency != CPUFREQ_TABLE_END; i++) { - opp = opp_find_freq_exact(dvfs_info->dev, + opp = dev_pm_opp_find_freq_exact(dvfs_info->dev, freq_tbl[i].frequency * 1000, true); if (IS_ERR(opp)) { rcu_read_unlock(); @@ -142,7 +142,7 @@ static int init_div_table(void) << P0_7_CSCLKDEV_SHIFT; /* Calculate EMA */ - volt_id = opp_get_voltage(opp); + volt_id = dev_pm_opp_get_voltage(opp); volt_id = (MAX_VOLTAGE - volt_id) / VOLTAGE_STEP; if (volt_id < PMIC_HIGH_VOLT) { ema_div = (CPUEMA_HIGH << P0_7_CPUEMA_SHIFT) | @@ -399,13 +399,14 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) goto err_put_node; } - ret = opp_init_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table); + ret = dev_pm_opp_init_cpufreq_table(dvfs_info->dev, + &dvfs_info->freq_table); if (ret) { dev_err(dvfs_info->dev, "failed to init cpufreq table: %d\n", ret); goto err_put_node; } - dvfs_info->freq_count = opp_get_opp_count(dvfs_info->dev); + dvfs_info->freq_count = dev_pm_opp_get_opp_count(dvfs_info->dev); exynos_sort_descend_freq_table(); if (of_property_read_u32(np, "clock-latency", &dvfs_info->latency)) @@ -454,7 +455,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) return 0; err_free_table: - opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table); + dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table); err_put_node: of_node_put(np); dev_err(&pdev->dev, "%s: failed initialization\n", __func__); @@ -464,7 +465,7 @@ err_put_node: static int exynos_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&exynos_driver); - opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table); + dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table); return 0; } diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index c3fd2a1..b360549 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -70,14 +70,14 @@ static int imx6q_set_target(struct cpufreq_policy *policy, return 0; rcu_read_lock(); - opp = opp_find_freq_ceil(cpu_dev, &freq_hz); + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); if (IS_ERR(opp)) { rcu_read_unlock(); dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz); return PTR_ERR(opp); } - volt = opp_get_voltage(opp); + volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); volt_old = regulator_get_voltage(arm_reg); @@ -237,14 +237,14 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) } /* We expect an OPP table supplied by platform */ - num = opp_get_opp_count(cpu_dev); + num = dev_pm_opp_get_opp_count(cpu_dev); if (num < 0) { ret = num; dev_err(cpu_dev, "no OPP table is found: %d\n", ret); goto put_node; } - ret = opp_init_cpufreq_table(cpu_dev, &freq_table); + ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); if (ret) { dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); goto put_node; @@ -259,12 +259,12 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) * same order. */ rcu_read_lock(); - opp = opp_find_freq_exact(cpu_dev, + opp = dev_pm_opp_find_freq_exact(cpu_dev, freq_table[0].frequency * 1000, true); - min_volt = opp_get_voltage(opp); - opp = opp_find_freq_exact(cpu_dev, + min_volt = dev_pm_opp_get_voltage(opp); + opp = dev_pm_opp_find_freq_exact(cpu_dev, freq_table[--num].frequency * 1000, true); - max_volt = opp_get_voltage(opp); + max_volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt); if (ret > 0) @@ -292,7 +292,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) return 0; free_freq_table: - opp_free_cpufreq_table(cpu_dev, &freq_table); + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); put_node: of_node_put(np); return ret; @@ -301,7 +301,7 @@ put_node: static int imx6q_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&imx6q_cpufreq_driver); - opp_free_cpufreq_table(cpu_dev, &freq_table); + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); return 0; } diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index f31fcfc..c5e31d2 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -105,14 +105,14 @@ static int omap_target(struct cpufreq_policy *policy, if (mpu_reg) { rcu_read_lock(); - opp = opp_find_freq_ceil(mpu_dev, &freq); + opp = dev_pm_opp_find_freq_ceil(mpu_dev, &freq); if (IS_ERR(opp)) { rcu_read_unlock(); dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", __func__, freqs.new); return -EINVAL; } - volt = opp_get_voltage(opp); + volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); tol = volt * OPP_TOLERANCE / 100; volt_old = regulator_get_voltage(mpu_reg); @@ -162,7 +162,7 @@ done: static inline void freq_table_free(void) { if (atomic_dec_and_test(&freq_table_users)) - opp_free_cpufreq_table(mpu_dev, &freq_table); + dev_pm_opp_free_cpufreq_table(mpu_dev, &freq_table); } static int omap_cpu_init(struct cpufreq_policy *policy) @@ -181,7 +181,7 @@ static int omap_cpu_init(struct cpufreq_policy *policy) policy->cur = omap_getspeed(policy->cpu); if (!freq_table) - result = opp_init_cpufreq_table(mpu_dev, &freq_table); + result = dev_pm_opp_init_cpufreq_table(mpu_dev, &freq_table); if (result) { dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n", diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index c99c00d..f798edc 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -908,7 +908,7 @@ static ssize_t available_frequencies_show(struct device *d, rcu_read_lock(); do { - opp = opp_find_freq_ceil(dev, &freq); + opp = dev_pm_opp_find_freq_ceil(dev, &freq); if (IS_ERR(opp)) break; @@ -1036,18 +1036,18 @@ struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) { /* The freq is an upper bound. opp should be lower */ - opp = opp_find_freq_floor(dev, freq); + opp = dev_pm_opp_find_freq_floor(dev, freq); /* If not available, use the closest opp */ if (opp == ERR_PTR(-ERANGE)) - opp = opp_find_freq_ceil(dev, freq); + opp = dev_pm_opp_find_freq_ceil(dev, freq); } else { /* The freq is an lower bound. opp should be higher */ - opp = opp_find_freq_ceil(dev, freq); + opp = dev_pm_opp_find_freq_ceil(dev, freq); /* If not available, use the closest opp */ if (opp == ERR_PTR(-ERANGE)) - opp = opp_find_freq_floor(dev, freq); + opp = dev_pm_opp_find_freq_floor(dev, freq); } return opp; @@ -1066,7 +1066,7 @@ int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq) int ret = 0; rcu_read_lock(); - nh = opp_get_notifier(dev); + nh = dev_pm_opp_get_notifier(dev); if (IS_ERR(nh)) ret = PTR_ERR(nh); rcu_read_unlock(); @@ -1092,7 +1092,7 @@ int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq) int ret = 0; rcu_read_lock(); - nh = opp_get_notifier(dev); + nh = dev_pm_opp_get_notifier(dev); if (IS_ERR(nh)) ret = PTR_ERR(nh); rcu_read_unlock(); diff --git a/drivers/devfreq/exynos/exynos4_bus.c b/drivers/devfreq/exynos/exynos4_bus.c index c5f86d8..33c0e05 100644 --- a/drivers/devfreq/exynos/exynos4_bus.c +++ b/drivers/devfreq/exynos/exynos4_bus.c @@ -650,8 +650,8 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, rcu_read_unlock(); return PTR_ERR(opp); } - new_oppinfo.rate = opp_get_freq(opp); - new_oppinfo.volt = opp_get_voltage(opp); + new_oppinfo.rate = dev_pm_opp_get_freq(opp); + new_oppinfo.volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); freq = new_oppinfo.rate; @@ -873,7 +873,7 @@ static int exynos4210_init_tables(struct busfreq_data *data) exynos4210_busclk_table[i].volt = exynos4210_asv_volt[mgrp][i]; for (i = LV_0; i < EX4210_LV_NUM; i++) { - err = opp_add(data->dev, exynos4210_busclk_table[i].clk, + err = dev_pm_opp_add(data->dev, exynos4210_busclk_table[i].clk, exynos4210_busclk_table[i].volt); if (err) { dev_err(data->dev, "Cannot add opp entries.\n"); @@ -940,7 +940,7 @@ static int exynos4x12_init_tables(struct busfreq_data *data) } for (i = 0; i < EX4x12_LV_NUM; i++) { - ret = opp_add(data->dev, exynos4x12_mifclk_table[i].clk, + ret = dev_pm_opp_add(data->dev, exynos4x12_mifclk_table[i].clk, exynos4x12_mifclk_table[i].volt); if (ret) { dev_err(data->dev, "Fail to add opp entries.\n"); @@ -969,7 +969,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, data->disabled = true; rcu_read_lock(); - opp = opp_find_freq_floor(data->dev, &maxfreq); + opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq); if (IS_ERR(opp)) { rcu_read_unlock(); dev_err(data->dev, "%s: unable to find a min freq\n", @@ -977,8 +977,8 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, mutex_unlock(&data->lock); return PTR_ERR(opp); } - new_oppinfo.rate = opp_get_freq(opp); - new_oppinfo.volt = opp_get_voltage(opp); + new_oppinfo.rate = dev_pm_opp_get_freq(opp); + new_oppinfo.volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); err = exynos4_bus_setvolt(data, &new_oppinfo, @@ -1065,15 +1065,16 @@ static int exynos4_busfreq_probe(struct platform_device *pdev) } rcu_read_lock(); - opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); + opp = dev_pm_opp_find_freq_floor(dev, + &exynos4_devfreq_profile.initial_freq); if (IS_ERR(opp)) { rcu_read_unlock(); dev_err(dev, "Invalid initial frequency %lu kHz.\n", exynos4_devfreq_profile.initial_freq); return PTR_ERR(opp); } - data->curr_oppinfo.rate = opp_get_freq(opp); - data->curr_oppinfo.volt = opp_get_voltage(opp); + data->curr_oppinfo.rate = dev_pm_opp_get_freq(opp); + data->curr_oppinfo.volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); platform_set_drvdata(pdev, data); diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c index 574b16b..b0e4592 100644 --- a/drivers/devfreq/exynos/exynos5_bus.c +++ b/drivers/devfreq/exynos/exynos5_bus.c @@ -144,8 +144,8 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq, return PTR_ERR(opp); } - freq = opp_get_freq(opp); - volt = opp_get_voltage(opp); + freq = dev_pm_opp_get_freq(opp); + volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); old_freq = data->curr_freq; @@ -246,7 +246,7 @@ static int exynos5250_init_int_tables(struct busfreq_data_int *data) int i, err = 0; for (i = LV_0; i < _LV_END; i++) { - err = opp_add(data->dev, exynos5_int_opp_table[i].clk, + err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk, exynos5_int_opp_table[i].volt); if (err) { dev_err(data->dev, "Cannot add opp entries.\n"); @@ -276,14 +276,14 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this, data->disabled = true; rcu_read_lock(); - opp = opp_find_freq_floor(data->dev, &maxfreq); + opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq); if (IS_ERR(opp)) { rcu_read_unlock(); err = PTR_ERR(opp); goto unlock; } - freq = opp_get_freq(opp); - volt = opp_get_voltage(opp); + freq = dev_pm_opp_get_freq(opp); + volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); err = exynos5_int_setvolt(data, volt); @@ -368,7 +368,7 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev) } rcu_read_lock(); - opp = opp_find_freq_floor(dev, + opp = dev_pm_opp_find_freq_floor(dev, &exynos5_devfreq_int_profile.initial_freq); if (IS_ERR(opp)) { rcu_read_unlock(); @@ -377,8 +377,8 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev) err = PTR_ERR(opp); goto err_opp_add; } - initial_freq = opp_get_freq(opp); - initial_volt = opp_get_voltage(opp); + initial_freq = dev_pm_opp_get_freq(opp); + initial_volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); data->curr_freq = initial_freq; diff --git a/include/linux/opp.h b/include/linux/opp.h index 3aca2b8..2066ae5 100644 --- a/include/linux/opp.h +++ b/include/linux/opp.h @@ -27,77 +27,79 @@ enum opp_event { #if defined(CONFIG_PM_OPP) -unsigned long opp_get_voltage(struct opp *opp); +unsigned long dev_pm_opp_get_voltage(struct opp *opp); -unsigned long opp_get_freq(struct opp *opp); +unsigned long dev_pm_opp_get_freq(struct opp *opp); -int opp_get_opp_count(struct device *dev); +int dev_pm_opp_get_opp_count(struct device *dev); -struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq, +struct opp *dev_pm_opp_find_freq_exact(struct device *dev, unsigned long freq, bool available); -struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq); +struct opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq); -struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq); +struct opp *dev_pm_opp_find_freq_ceil(struct device *dev, unsigned long *freq); -int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt); +int dev_pm_opp_add(struct device *dev, unsigned long freq, + unsigned long u_volt); -int opp_enable(struct device *dev, unsigned long freq); +int dev_pm_opp_enable(struct device *dev, unsigned long freq); -int opp_disable(struct device *dev, unsigned long freq); +int dev_pm_opp_disable(struct device *dev, unsigned long freq); -struct srcu_notifier_head *opp_get_notifier(struct device *dev); +struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev); #else -static inline unsigned long opp_get_voltage(struct opp *opp) +static inline unsigned long dev_pm_opp_get_voltage(struct opp *opp) { return 0; } -static inline unsigned long opp_get_freq(struct opp *opp) +static inline unsigned long dev_pm_opp_get_freq(struct opp *opp) { return 0; } -static inline int opp_get_opp_count(struct device *dev) +static inline int dev_pm_opp_get_opp_count(struct device *dev) { return 0; } -static inline struct opp *opp_find_freq_exact(struct device *dev, +static inline struct opp *dev_pm_opp_find_freq_exact(struct device *dev, unsigned long freq, bool available) { return ERR_PTR(-EINVAL); } -static inline struct opp *opp_find_freq_floor(struct device *dev, +static inline struct opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq) { return ERR_PTR(-EINVAL); } -static inline struct opp *opp_find_freq_ceil(struct device *dev, +static inline struct opp *dev_pm_opp_find_freq_ceil(struct device *dev, unsigned long *freq) { return ERR_PTR(-EINVAL); } -static inline int opp_add(struct device *dev, unsigned long freq, +static inline int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) { return -EINVAL; } -static inline int opp_enable(struct device *dev, unsigned long freq) +static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq) { return 0; } -static inline int opp_disable(struct device *dev, unsigned long freq) +static inline int dev_pm_opp_disable(struct device *dev, unsigned long freq) { return 0; } -static inline struct srcu_notifier_head *opp_get_notifier(struct device *dev) +static inline struct srcu_notifier_head *dev_pm_opp_get_notifier( + struct device *dev) { return ERR_PTR(-EINVAL); } @@ -113,19 +115,19 @@ static inline int of_init_opp_table(struct device *dev) #endif #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP) -int opp_init_cpufreq_table(struct device *dev, +int dev_pm_opp_init_cpufreq_table(struct device *dev, struct cpufreq_frequency_table **table); -void opp_free_cpufreq_table(struct device *dev, +void dev_pm_opp_free_cpufreq_table(struct device *dev, struct cpufreq_frequency_table **table); #else -static inline int opp_init_cpufreq_table(struct device *dev, +static inline int dev_pm_opp_init_cpufreq_table(struct device *dev, struct cpufreq_frequency_table **table) { return -EINVAL; } static inline -void opp_free_cpufreq_table(struct device *dev, +void dev_pm_opp_free_cpufreq_table(struct device *dev, struct cpufreq_frequency_table **table) { } -- cgit v0.10.2 From 47d43ba73eb98d8ba731208735c899129d9849e1 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 19 Sep 2013 16:03:51 -0500 Subject: PM / OPP: rename data structures to dev_pm equivalents Since Operating Performance Points (OPP) data structures are specific to device specific power management, be specific and rename opp_* data structures in OPP library with dev_pm_opp_* equivalent. Affected structures are: struct opp enum opp_event Minor checkpatch warning resulting of this change was fixed as well. Reported-by: Randy Dunlap Signed-off-by: Nishanth Menon Signed-off-by: Rafael J. Wysocki diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt index 185367b..7f67e3d 100644 --- a/Documentation/power/opp.txt +++ b/Documentation/power/opp.txt @@ -358,14 +358,14 @@ accessed by various functions as described above. However, the structures representing the actual OPPs and domains are internal to the OPP library itself to allow for suitable abstraction reusable across systems. -struct opp - The internal data structure of OPP library which is used to +struct dev_pm_opp - The internal data structure of OPP library which is used to represent an OPP. In addition to the freq, voltage, availability information, it also contains internal book keeping information required for the OPP library to operate on. Pointer to this structure is provided back to the users such as SoC framework to be used as a identifier for OPP in the interactions with OPP layer. - WARNING: The struct opp pointer should not be parsed or modified by the + WARNING: The struct dev_pm_opp pointer should not be parsed or modified by the users. The defaults of for an instance is populated by dev_pm_opp_add, but the availability of the OPP can be modified by dev_pm_opp_enable/disable functions. diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 937744c..92901bd 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -131,7 +131,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, { struct voltagedomain *voltdm; struct clk *clk; - struct opp *opp; + struct dev_pm_opp *opp; unsigned long freq, bootup_volt; struct device *dev; diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index 00c6a44..693e14a 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c @@ -42,7 +42,7 @@ */ /** - * struct opp - Generic OPP description structure + * struct dev_pm_opp - Generic OPP description structure * @node: opp list node. The nodes are maintained throughout the lifetime * of boot. It is expected only an optimal set of OPPs are * added to the library by the SoC framework. @@ -59,7 +59,7 @@ * * This structure stores the OPP information for a given device. */ -struct opp { +struct dev_pm_opp { struct list_head node; bool available; @@ -150,9 +150,9 @@ static struct device_opp *find_device_opp(struct device *dev) * prior to unlocking with rcu_read_unlock() to maintain the integrity of the * pointer. */ -unsigned long dev_pm_opp_get_voltage(struct opp *opp) +unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) { - struct opp *tmp_opp; + struct dev_pm_opp *tmp_opp; unsigned long v = 0; tmp_opp = rcu_dereference(opp); @@ -180,9 +180,9 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_voltage); * prior to unlocking with rcu_read_unlock() to maintain the integrity of the * pointer. */ -unsigned long dev_pm_opp_get_freq(struct opp *opp) +unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp) { - struct opp *tmp_opp; + struct dev_pm_opp *tmp_opp; unsigned long f = 0; tmp_opp = rcu_dereference(opp); @@ -209,7 +209,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq); int dev_pm_opp_get_opp_count(struct device *dev) { struct device_opp *dev_opp; - struct opp *temp_opp; + struct dev_pm_opp *temp_opp; int count = 0; dev_opp = find_device_opp(dev); @@ -254,11 +254,12 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count); * under the locked area. The pointer returned must be used prior to unlocking * with rcu_read_unlock() to maintain the integrity of the pointer. */ -struct opp *dev_pm_opp_find_freq_exact(struct device *dev, unsigned long freq, - bool available) +struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, + unsigned long freq, + bool available) { struct device_opp *dev_opp; - struct opp *temp_opp, *opp = ERR_PTR(-ERANGE); + struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); dev_opp = find_device_opp(dev); if (IS_ERR(dev_opp)) { @@ -300,10 +301,11 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact); * under the locked area. The pointer returned must be used prior to unlocking * with rcu_read_unlock() to maintain the integrity of the pointer. */ -struct opp *dev_pm_opp_find_freq_ceil(struct device *dev, unsigned long *freq) +struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, + unsigned long *freq) { struct device_opp *dev_opp; - struct opp *temp_opp, *opp = ERR_PTR(-ERANGE); + struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); if (!dev || !freq) { dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); @@ -347,10 +349,11 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil); * under the locked area. The pointer returned must be used prior to unlocking * with rcu_read_unlock() to maintain the integrity of the pointer. */ -struct opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq) +struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, + unsigned long *freq) { struct device_opp *dev_opp; - struct opp *temp_opp, *opp = ERR_PTR(-ERANGE); + struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); if (!dev || !freq) { dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); @@ -396,11 +399,11 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor); int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) { struct device_opp *dev_opp = NULL; - struct opp *opp, *new_opp; + struct dev_pm_opp *opp, *new_opp; struct list_head *head; /* allocate new OPP node */ - new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL); + new_opp = kzalloc(sizeof(*new_opp), GFP_KERNEL); if (!new_opp) { dev_warn(dev, "%s: Unable to create new OPP node\n", __func__); return -ENOMEM; @@ -485,11 +488,11 @@ static int opp_set_availability(struct device *dev, unsigned long freq, bool availability_req) { struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV); - struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV); + struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV); int r = 0; /* keep the node allocated */ - new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL); + new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL); if (!new_opp) { dev_warn(dev, "%s: Unable to create OPP\n", __func__); return -ENOMEM; @@ -623,7 +626,7 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev, struct cpufreq_frequency_table **table) { struct device_opp *dev_opp; - struct opp *opp; + struct dev_pm_opp *opp; struct cpufreq_frequency_table *freq_table; int i = 0; diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index af951a9..d731078 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -44,7 +44,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { struct cpufreq_freqs freqs; - struct opp *opp; + struct dev_pm_opp *opp; unsigned long volt = 0, volt_old = 0, tol = 0; long freq_Hz, freq_exact; unsigned int index; @@ -230,7 +230,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) transition_latency = CPUFREQ_ETERNAL; if (!IS_ERR(cpu_reg)) { - struct opp *opp; + struct dev_pm_opp *opp; unsigned long min_uV, max_uV; int i; diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index 444eca7..c8b3d39 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -118,7 +118,7 @@ static int init_div_table(void) struct cpufreq_frequency_table *freq_tbl = dvfs_info->freq_table; unsigned int tmp, clk_div, ema_div, freq, volt_id; int i = 0; - struct opp *opp; + struct dev_pm_opp *opp; rcu_read_lock(); for (i = 0; freq_tbl[i].frequency != CPUFREQ_TABLE_END; i++) { diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index b360549..84e993d 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -49,7 +49,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { struct cpufreq_freqs freqs; - struct opp *opp; + struct dev_pm_opp *opp; unsigned long freq_hz, volt, volt_old; unsigned int index; int ret; @@ -199,7 +199,7 @@ static struct cpufreq_driver imx6q_cpufreq_driver = { static int imx6q_cpufreq_probe(struct platform_device *pdev) { struct device_node *np; - struct opp *opp; + struct dev_pm_opp *opp; unsigned long min_volt, max_volt; int num, ret; diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index c5e31d2..f057d42 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -65,7 +65,7 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int i; int r, ret = 0; struct cpufreq_freqs freqs; - struct opp *opp; + struct dev_pm_opp *opp; unsigned long freq, volt = 0, volt_old = 0, tol = 0; if (!freq_table) { diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index f798edc..03530a0 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -902,7 +902,7 @@ static ssize_t available_frequencies_show(struct device *d, { struct devfreq *df = to_devfreq(d); struct device *dev = df->dev.parent; - struct opp *opp; + struct dev_pm_opp *opp; ssize_t count = 0; unsigned long freq = 0; @@ -1029,10 +1029,11 @@ module_exit(devfreq_exit); * under the locked area. The pointer returned must be used prior to unlocking * with rcu_read_unlock() to maintain the integrity of the pointer. */ -struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, - u32 flags) +struct dev_pm_opp *devfreq_recommended_opp(struct device *dev, + unsigned long *freq, + u32 flags) { - struct opp *opp; + struct dev_pm_opp *opp; if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) { /* The freq is an upper bound. opp should be lower */ diff --git a/drivers/devfreq/exynos/exynos4_bus.c b/drivers/devfreq/exynos/exynos4_bus.c index 33c0e05..891becd 100644 --- a/drivers/devfreq/exynos/exynos4_bus.c +++ b/drivers/devfreq/exynos/exynos4_bus.c @@ -639,7 +639,7 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, struct platform_device *pdev = container_of(dev, struct platform_device, dev); struct busfreq_data *data = platform_get_drvdata(pdev); - struct opp *opp; + struct dev_pm_opp *opp; unsigned long freq; unsigned long old_freq = data->curr_oppinfo.rate; struct busfreq_opp_info new_oppinfo; @@ -956,7 +956,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, { struct busfreq_data *data = container_of(this, struct busfreq_data, pm_notifier); - struct opp *opp; + struct dev_pm_opp *opp; struct busfreq_opp_info new_oppinfo; unsigned long maxfreq = ULONG_MAX; int err = 0; @@ -1020,7 +1020,7 @@ unlock: static int exynos4_busfreq_probe(struct platform_device *pdev) { struct busfreq_data *data; - struct opp *opp; + struct dev_pm_opp *opp; struct device *dev = &pdev->dev; int err = 0; diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c index b0e4592..d06232a 100644 --- a/drivers/devfreq/exynos/exynos5_bus.c +++ b/drivers/devfreq/exynos/exynos5_bus.c @@ -132,7 +132,7 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq, struct platform_device *pdev = container_of(dev, struct platform_device, dev); struct busfreq_data_int *data = platform_get_drvdata(pdev); - struct opp *opp; + struct dev_pm_opp *opp; unsigned long old_freq, freq; unsigned long volt; @@ -262,7 +262,7 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this, { struct busfreq_data_int *data = container_of(this, struct busfreq_data_int, pm_notifier); - struct opp *opp; + struct dev_pm_opp *opp; unsigned long maxfreq = ULONG_MAX; unsigned long freq; unsigned long volt; @@ -316,7 +316,7 @@ unlock: static int exynos5_busfreq_int_probe(struct platform_device *pdev) { struct busfreq_data_int *data; - struct opp *opp; + struct dev_pm_opp *opp; struct device *dev = &pdev->dev; struct device_node *np; unsigned long initial_freq; diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index 5f1ab92..c8c9953 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -187,7 +187,7 @@ extern int devfreq_suspend_device(struct devfreq *devfreq); extern int devfreq_resume_device(struct devfreq *devfreq); /* Helper functions for devfreq user device driver with OPP. */ -extern struct opp *devfreq_recommended_opp(struct device *dev, +extern struct dev_pm_opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, u32 flags); extern int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq); @@ -238,7 +238,7 @@ static inline int devfreq_resume_device(struct devfreq *devfreq) return 0; } -static inline struct opp *devfreq_recommended_opp(struct device *dev, +static inline struct dev_pm_opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, u32 flags) { return ERR_PTR(-EINVAL); diff --git a/include/linux/opp.h b/include/linux/opp.h index 2066ae5..5151b00 100644 --- a/include/linux/opp.h +++ b/include/linux/opp.h @@ -18,27 +18,30 @@ #include #include -struct opp; +struct dev_pm_opp; struct device; -enum opp_event { +enum dev_pm_opp_event { OPP_EVENT_ADD, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE, }; #if defined(CONFIG_PM_OPP) -unsigned long dev_pm_opp_get_voltage(struct opp *opp); +unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp); -unsigned long dev_pm_opp_get_freq(struct opp *opp); +unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp); int dev_pm_opp_get_opp_count(struct device *dev); -struct opp *dev_pm_opp_find_freq_exact(struct device *dev, unsigned long freq, - bool available); +struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, + unsigned long freq, + bool available); -struct opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq); +struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, + unsigned long *freq); -struct opp *dev_pm_opp_find_freq_ceil(struct device *dev, unsigned long *freq); +struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, + unsigned long *freq); int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt); @@ -49,12 +52,12 @@ int dev_pm_opp_disable(struct device *dev, unsigned long freq); struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev); #else -static inline unsigned long dev_pm_opp_get_voltage(struct opp *opp) +static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) { return 0; } -static inline unsigned long dev_pm_opp_get_freq(struct opp *opp) +static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp) { return 0; } @@ -64,19 +67,19 @@ static inline int dev_pm_opp_get_opp_count(struct device *dev) return 0; } -static inline struct opp *dev_pm_opp_find_freq_exact(struct device *dev, +static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, unsigned long freq, bool available) { return ERR_PTR(-EINVAL); } -static inline struct opp *dev_pm_opp_find_freq_floor(struct device *dev, +static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq) { return ERR_PTR(-EINVAL); } -static inline struct opp *dev_pm_opp_find_freq_ceil(struct device *dev, +static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, unsigned long *freq) { return ERR_PTR(-EINVAL); -- cgit v0.10.2 From e4db1c7439b31993a4886b273bb9235a8eea82bf Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 19 Sep 2013 16:03:52 -0500 Subject: PM / OPP: rename header to linux/pm_opp.h Since Operating Performance Points (OPP) functions are specific to device specific power management, be specific and rename opp.h to pm_opp.h Reported-by: Randy Dunlap Signed-off-by: Nishanth Menon Signed-off-by: Rafael J. Wysocki diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt index 7f67e3d..b8a907d 100644 --- a/Documentation/power/opp.txt +++ b/Documentation/power/opp.txt @@ -42,7 +42,7 @@ We can represent these as three OPPs as the following {Hz, uV} tuples: OPP library provides a set of helper functions to organize and query the OPP information. The library is located in drivers/base/power/opp.c and the header -is located in include/linux/opp.h. OPP library can be enabled by enabling +is located in include/linux/pm_opp.h. OPP library can be enabled by enabling CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to optionally boot at a certain OPP without needing cpufreq. diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index d7ecc90..699aabe 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 33969e5..6432ab8 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/arm/mach-omap2/omap-pm.h b/arch/arm/mach-omap2/omap-pm.h index 67faa7b..1d777e6 100644 --- a/arch/arm/mach-omap2/omap-pm.h +++ b/arch/arm/mach-omap2/omap-pm.h @@ -17,7 +17,7 @@ #include #include #include -#include +#include /* * agent_id values for use with omap_pm_set_min_bus_tput(): diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c index 7b04637..ec21e6e 100644 --- a/arch/arm/mach-omap2/opp.c +++ b/arch/arm/mach-omap2/opp.c @@ -17,7 +17,7 @@ * GNU General Public License for more details. */ #include -#include +#include #include #include "omap_device.h" diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 92901bd..2f569b3 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index 693e14a..fa41874 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 9e82a9d..e010fb7 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c index 480c0bd..8d9d591 100644 --- a/drivers/cpufreq/arm_big_little_dt.c +++ b/drivers/cpufreq/arm_big_little_dt.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index d731078..242d490 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index c8b3d39..d41e777 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 84e993d..e4c9140 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index f057d42..20190f5 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 03530a0..2e23b12 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/devfreq/exynos/exynos4_bus.c b/drivers/devfreq/exynos/exynos4_bus.c index 891becd..cede6f7 100644 --- a/drivers/devfreq/exynos/exynos4_bus.c +++ b/drivers/devfreq/exynos/exynos4_bus.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c index d06232a..52835f12 100644 --- a/drivers/devfreq/exynos/exynos5_bus.c +++ b/drivers/devfreq/exynos/exynos5_bus.c @@ -15,10 +15,10 @@ #include #include #include -#include +#include #include #include -#include +#include #include #include #include diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index c8c9953..7a7cc74 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -15,7 +15,7 @@ #include #include -#include +#include #define DEVFREQ_NAME_LEN 16 diff --git a/include/linux/opp.h b/include/linux/opp.h deleted file mode 100644 index 5151b00..0000000 --- a/include/linux/opp.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Generic OPP Interface - * - * Copyright (C) 2009-2010 Texas Instruments Incorporated. - * Nishanth Menon - * Romit Dasgupta - * Kevin Hilman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __LINUX_OPP_H__ -#define __LINUX_OPP_H__ - -#include -#include -#include - -struct dev_pm_opp; -struct device; - -enum dev_pm_opp_event { - OPP_EVENT_ADD, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE, -}; - -#if defined(CONFIG_PM_OPP) - -unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp); - -unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp); - -int dev_pm_opp_get_opp_count(struct device *dev); - -struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, - unsigned long freq, - bool available); - -struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, - unsigned long *freq); - -struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, - unsigned long *freq); - -int dev_pm_opp_add(struct device *dev, unsigned long freq, - unsigned long u_volt); - -int dev_pm_opp_enable(struct device *dev, unsigned long freq); - -int dev_pm_opp_disable(struct device *dev, unsigned long freq); - -struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev); -#else -static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) -{ - return 0; -} - -static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp) -{ - return 0; -} - -static inline int dev_pm_opp_get_opp_count(struct device *dev) -{ - return 0; -} - -static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, - unsigned long freq, bool available) -{ - return ERR_PTR(-EINVAL); -} - -static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, - unsigned long *freq) -{ - return ERR_PTR(-EINVAL); -} - -static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, - unsigned long *freq) -{ - return ERR_PTR(-EINVAL); -} - -static inline int dev_pm_opp_add(struct device *dev, unsigned long freq, - unsigned long u_volt) -{ - return -EINVAL; -} - -static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq) -{ - return 0; -} - -static inline int dev_pm_opp_disable(struct device *dev, unsigned long freq) -{ - return 0; -} - -static inline struct srcu_notifier_head *dev_pm_opp_get_notifier( - struct device *dev) -{ - return ERR_PTR(-EINVAL); -} -#endif /* CONFIG_PM_OPP */ - -#if defined(CONFIG_PM_OPP) && defined(CONFIG_OF) -int of_init_opp_table(struct device *dev); -#else -static inline int of_init_opp_table(struct device *dev) -{ - return -EINVAL; -} -#endif - -#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP) -int dev_pm_opp_init_cpufreq_table(struct device *dev, - struct cpufreq_frequency_table **table); -void dev_pm_opp_free_cpufreq_table(struct device *dev, - struct cpufreq_frequency_table **table); -#else -static inline int dev_pm_opp_init_cpufreq_table(struct device *dev, - struct cpufreq_frequency_table **table) -{ - return -EINVAL; -} - -static inline -void dev_pm_opp_free_cpufreq_table(struct device *dev, - struct cpufreq_frequency_table **table) -{ -} -#endif /* CONFIG_CPU_FREQ */ - -#endif /* __LINUX_OPP_H__ */ diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h new file mode 100644 index 0000000..5151b00 --- /dev/null +++ b/include/linux/pm_opp.h @@ -0,0 +1,139 @@ +/* + * Generic OPP Interface + * + * Copyright (C) 2009-2010 Texas Instruments Incorporated. + * Nishanth Menon + * Romit Dasgupta + * Kevin Hilman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __LINUX_OPP_H__ +#define __LINUX_OPP_H__ + +#include +#include +#include + +struct dev_pm_opp; +struct device; + +enum dev_pm_opp_event { + OPP_EVENT_ADD, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE, +}; + +#if defined(CONFIG_PM_OPP) + +unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp); + +unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp); + +int dev_pm_opp_get_opp_count(struct device *dev); + +struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, + unsigned long freq, + bool available); + +struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, + unsigned long *freq); + +struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, + unsigned long *freq); + +int dev_pm_opp_add(struct device *dev, unsigned long freq, + unsigned long u_volt); + +int dev_pm_opp_enable(struct device *dev, unsigned long freq); + +int dev_pm_opp_disable(struct device *dev, unsigned long freq); + +struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev); +#else +static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) +{ + return 0; +} + +static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp) +{ + return 0; +} + +static inline int dev_pm_opp_get_opp_count(struct device *dev) +{ + return 0; +} + +static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, + unsigned long freq, bool available) +{ + return ERR_PTR(-EINVAL); +} + +static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, + unsigned long *freq) +{ + return ERR_PTR(-EINVAL); +} + +static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, + unsigned long *freq) +{ + return ERR_PTR(-EINVAL); +} + +static inline int dev_pm_opp_add(struct device *dev, unsigned long freq, + unsigned long u_volt) +{ + return -EINVAL; +} + +static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq) +{ + return 0; +} + +static inline int dev_pm_opp_disable(struct device *dev, unsigned long freq) +{ + return 0; +} + +static inline struct srcu_notifier_head *dev_pm_opp_get_notifier( + struct device *dev) +{ + return ERR_PTR(-EINVAL); +} +#endif /* CONFIG_PM_OPP */ + +#if defined(CONFIG_PM_OPP) && defined(CONFIG_OF) +int of_init_opp_table(struct device *dev); +#else +static inline int of_init_opp_table(struct device *dev) +{ + return -EINVAL; +} +#endif + +#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP) +int dev_pm_opp_init_cpufreq_table(struct device *dev, + struct cpufreq_frequency_table **table); +void dev_pm_opp_free_cpufreq_table(struct device *dev, + struct cpufreq_frequency_table **table); +#else +static inline int dev_pm_opp_init_cpufreq_table(struct device *dev, + struct cpufreq_frequency_table **table) +{ + return -EINVAL; +} + +static inline +void dev_pm_opp_free_cpufreq_table(struct device *dev, + struct cpufreq_frequency_table **table) +{ +} +#endif /* CONFIG_CPU_FREQ */ + +#endif /* __LINUX_OPP_H__ */ -- cgit v0.10.2 From 9c0ebcf78fde0ffa348a95a544c6d3f2dac5af65 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 25 Oct 2013 19:45:48 +0530 Subject: cpufreq: Implement light weight ->target_index() routine Currently, the prototype of cpufreq_drivers target routines is: int target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); And most of the drivers call cpufreq_frequency_table_target() to get a valid index of their frequency table which is closest to the target_freq. And they don't use target_freq and relation after that. So, it makes sense to just do this work in cpufreq core before calling cpufreq_frequency_table_target() and simply pass index instead. But this can be done only with drivers which expose their frequency table with cpufreq core. For others we need to stick with the old prototype of target() until those drivers are converted to expose frequency tables. This patch implements the new light weight prototype for target_index() routine. It looks like this: int target_index(struct cpufreq_policy *policy, unsigned int index); CPUFreq core will call cpufreq_frequency_table_target() before calling this routine and pass index to it. Because CPUFreq core now requires to call routines present in freq_table.c CONFIG_CPU_FREQ_TABLE must be enabled all the time. This also marks target() interface as deprecated. So, that new drivers avoid using it. And Documentation is updated accordingly. It also converts existing .target() to newly defined light weight .target_index() routine for many driver. Acked-by: Hans-Christian Egtvedt Acked-by: Jesper Nilsson Acked-by: Linus Walleij Acked-by: Russell King Acked-by: David S. Miller Tested-by: Andrew Lunn Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index 40282e6..8b1a445 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt @@ -23,8 +23,8 @@ Contents: 1.1 Initialization 1.2 Per-CPU Initialization 1.3 verify -1.4 target or setpolicy? -1.5 target +1.4 target/target_index or setpolicy? +1.5 target/target_index 1.6 setpolicy 2. Frequency Table Helpers @@ -56,7 +56,8 @@ cpufreq_driver.init - A pointer to the per-CPU initialization cpufreq_driver.verify - A pointer to a "verification" function. cpufreq_driver.setpolicy _or_ -cpufreq_driver.target - See below on the differences. +cpufreq_driver.target/ +target_index - See below on the differences. And optionally @@ -66,7 +67,7 @@ cpufreq_driver.resume - A pointer to a per-CPU resume function which is called with interrupts disabled and _before_ the pre-suspend frequency and/or policy is restored by a call to - ->target or ->setpolicy. + ->target/target_index or ->setpolicy. cpufreq_driver.attr - A pointer to a NULL-terminated list of "struct freq_attr" which allow to @@ -103,8 +104,8 @@ policy->governor must contain the "default policy" for this CPU. A few moments later, cpufreq_driver.verify and either cpufreq_driver.setpolicy or - cpufreq_driver.target is called with - these values. + cpufreq_driver.target/target_index is called + with these values. For setting some of these values (cpuinfo.min[max]_freq, policy->min[max]), the frequency table helpers might be helpful. See the section 2 for more information @@ -133,20 +134,28 @@ range) is within policy->min and policy->max. If necessary, increase policy->max first, and only if this is no solution, decrease policy->min. -1.4 target or setpolicy? +1.4 target/target_index or setpolicy? ---------------------------- Most cpufreq drivers or even most cpu frequency scaling algorithms only allow the CPU to be set to one frequency. For these, you use the -->target call. +->target/target_index call. Some cpufreq-capable processors switch the frequency between certain limits on their own. These shall use the ->setpolicy call -1.4. target +1.4. target/target_index ------------- +The target_index call has two arguments: struct cpufreq_policy *policy, +and unsigned int index (into the exposed frequency table). + +The CPUfreq driver must set the new frequency when called here. The +actual frequency must be determined by freq_table[index].frequency. + +Deprecated: +---------- The target call has three arguments: struct cpufreq_policy *policy, unsigned int target_frequency, unsigned int relation. diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt index 219970b..77ec215 100644 --- a/Documentation/cpu-freq/governors.txt +++ b/Documentation/cpu-freq/governors.txt @@ -40,7 +40,7 @@ Most cpufreq drivers (in fact, all except one, longrun) or even most cpu frequency scaling algorithms only offer the CPU to be set to one frequency. In order to offer dynamic frequency scaling, the cpufreq core must be able to tell these drivers of a "target frequency". So -these specific drivers will be transformed to offer a "->target" +these specific drivers will be transformed to offer a "->target/target_index" call instead of the existing "->setpolicy" call. For "longrun", all stays the same, though. @@ -71,7 +71,7 @@ CPU can be set to switch independently | CPU can only be set / the limits of policy->{min,max} / \ / \ - Using the ->setpolicy call, Using the ->target call, + Using the ->setpolicy call, Using the ->target/target_index call, the limits and the the frequency closest "policy" is set. to target_freq is set. It is assured that it diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index cb4b2ca..d4ea142 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -62,26 +62,6 @@ struct cpufreq_frequency_table sa11x0_freq_table[NR_FREQS+1] = { { .frequency = CPUFREQ_TABLE_END, }, }; -/* rounds up(!) */ -unsigned int sa11x0_freq_to_ppcr(unsigned int khz) -{ - int i; - - for (i = 0; i < NR_FREQS; i++) - if (sa11x0_freq_table[i].frequency >= khz) - break; - - return i; -} - -unsigned int sa11x0_ppcr_to_freq(unsigned int idx) -{ - unsigned int freq = 0; - if (idx < NR_FREQS) - freq = sa11x0_freq_table[idx].frequency; - return freq; -} - unsigned int sa11x0_getspeed(unsigned int cpu) { if (cpu) diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index cbdfae7..0d92e11 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h @@ -21,9 +21,7 @@ extern void sa1110_mb_enable(void); extern void sa1110_mb_disable(void); extern struct cpufreq_frequency_table sa11x0_freq_table[]; -extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); extern unsigned int sa11x0_getspeed(unsigned int cpu); -extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx); struct flash_platform_data; struct resource; diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index a1717d7..889cec0 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -424,17 +424,17 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq, } static int acpi_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) + unsigned int index) { struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); struct acpi_processor_performance *perf; struct cpufreq_freqs freqs; struct drv_cmd cmd; - unsigned int next_state = 0; /* Index into freq_table */ unsigned int next_perf_state = 0; /* Index into perf table */ int result = 0; - pr_debug("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu); + pr_debug("acpi_cpufreq_target %d (%d)\n", + data->freq_table[index].frequency, policy->cpu); if (unlikely(data == NULL || data->acpi_data == NULL || data->freq_table == NULL)) { @@ -442,16 +442,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, } perf = data->acpi_data; - result = cpufreq_frequency_table_target(policy, - data->freq_table, - target_freq, - relation, &next_state); - if (unlikely(result)) { - result = -ENODEV; - goto out; - } - - next_perf_state = data->freq_table[next_state].driver_data; + next_perf_state = data->freq_table[index].driver_data; if (perf->state == next_perf_state) { if (unlikely(data->resume)) { pr_debug("Called after resume, resetting to P%d\n", @@ -493,7 +484,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, cmd.mask = cpumask_of(policy->cpu); freqs.old = perf->states[perf->state].core_frequency * 1000; - freqs.new = data->freq_table[next_state].frequency; + freqs.new = data->freq_table[index].frequency; cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); drv_write(&cmd); @@ -923,7 +914,7 @@ static struct freq_attr *acpi_cpufreq_attr[] = { static struct cpufreq_driver acpi_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = acpi_cpufreq_target, + .target_index = acpi_cpufreq_target, .bios_limit = acpi_processor_get_bios_limit, .init = acpi_cpufreq_cpu_init, .exit = acpi_cpufreq_cpu_exit, diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 086f7c1..163e337 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -49,28 +49,21 @@ static unsigned int bL_cpufreq_get(unsigned int cpu) /* Set clock frequency */ static int bL_cpufreq_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) + unsigned int index) { struct cpufreq_freqs freqs; - u32 cpu = policy->cpu, freq_tab_idx, cur_cluster; + u32 cpu = policy->cpu, cur_cluster; int ret = 0; cur_cluster = cpu_to_cluster(policy->cpu); freqs.old = bL_cpufreq_get(policy->cpu); - - /* Determine valid target frequency using freq_table */ - cpufreq_frequency_table_target(policy, freq_table[cur_cluster], - target_freq, relation, &freq_tab_idx); - freqs.new = freq_table[cur_cluster][freq_tab_idx].frequency; + freqs.new = freq_table[cur_cluster][index].frequency; pr_debug("%s: cpu: %d, cluster: %d, oldfreq: %d, target freq: %d, new freq: %d\n", - __func__, cpu, cur_cluster, freqs.old, target_freq, + __func__, cpu, cur_cluster, freqs.old, freqs.new, freqs.new); - if (freqs.old == freqs.new) - return 0; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); ret = clk_set_rate(clk[cur_cluster], freqs.new * 1000); @@ -200,7 +193,7 @@ static struct cpufreq_driver bL_cpufreq_driver = { .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY, .verify = cpufreq_generic_frequency_table_verify, - .target = bL_cpufreq_set_target, + .target_index = bL_cpufreq_set_target, .get = bL_cpufreq_get, .init = bL_cpufreq_init, .exit = bL_cpufreq_exit, diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c index 7439ded..81d0752 100644 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ b/drivers/cpufreq/at32ap-cpufreq.c @@ -35,25 +35,12 @@ static unsigned int at32_get_speed(unsigned int cpu) static unsigned int ref_freq; static unsigned long loops_per_jiffy_ref; -static int at32_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int at32_set_target(struct cpufreq_policy *policy, unsigned int index) { struct cpufreq_freqs freqs; - long freq; - - /* Convert target_freq from kHz to Hz */ - freq = clk_round_rate(cpuclk, target_freq * 1000); - - /* Check if policy->min <= new_freq <= policy->max */ - if(freq < (policy->min * 1000) || freq > (policy->max * 1000)) - return -EINVAL; - - pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000); freqs.old = at32_get_speed(0); - freqs.new = (freq + 500) / 1000; - freqs.flags = 0; + freqs.new = freq_table[index].frequency; if (!ref_freq) { ref_freq = freqs.old; @@ -64,13 +51,13 @@ static int at32_set_target(struct cpufreq_policy *policy, if (freqs.old < freqs.new) boot_cpu_data.loops_per_jiffy = cpufreq_scale( loops_per_jiffy_ref, ref_freq, freqs.new); - clk_set_rate(cpuclk, freq); + clk_set_rate(cpuclk, freqs.new * 1000); if (freqs.new < freqs.old) boot_cpu_data.loops_per_jiffy = cpufreq_scale( loops_per_jiffy_ref, ref_freq, freqs.new); cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - pr_debug("cpufreq: set frequency %lu Hz\n", freq); + pr_debug("cpufreq: set frequency %u Hz\n", freqs.new * 1000); return 0; } @@ -139,7 +126,7 @@ static struct cpufreq_driver at32_driver = { .name = "at32ap", .init = at32_cpufreq_driver_init, .verify = cpufreq_generic_frequency_table_verify, - .target = at32_set_target, + .target_index = at32_set_target, .get = at32_get_speed, .flags = CPUFREQ_STICKY, }; diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c index 0bc9e8c..12528b2 100644 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ b/drivers/cpufreq/blackfin-cpufreq.c @@ -127,14 +127,11 @@ unsigned long cpu_set_cclk(int cpu, unsigned long new) } #endif -static int bfin_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) +static int bfin_target(struct cpufreq_policy *policy, unsigned int index) { #ifndef CONFIG_BF60x unsigned int plldiv; #endif - unsigned int index; - unsigned long cclk_hz; struct cpufreq_freqs freqs; static unsigned long lpj_ref; static unsigned int lpj_ref_freq; @@ -144,17 +141,11 @@ static int bfin_target(struct cpufreq_policy *policy, cycles_t cycles; #endif - if (cpufreq_frequency_table_target(policy, bfin_freq_table, target_freq, - relation, &index)) - return -EINVAL; - - cclk_hz = bfin_freq_table[index].frequency; - freqs.old = bfin_getfreq_khz(0); - freqs.new = cclk_hz; + freqs.new = bfin_freq_table[index].frequency; pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n", - cclk_hz, target_freq, freqs.old); + freqs.new, freqs.new, freqs.old); cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); #ifndef CONFIG_BF60x @@ -209,7 +200,7 @@ static int __bfin_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver bfin_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = bfin_target, + .target_index = bfin_target, .get = bfin_getfreq_khz, .init = __bfin_cpu_init, .exit = cpufreq_generic_exit, diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 33ab650..4dbe7ef 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -35,24 +35,14 @@ static unsigned int cpu0_get_speed(unsigned int cpu) return clk_get_rate(cpu_clk) / 1000; } -static int cpu0_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) +static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index) { struct cpufreq_freqs freqs; struct dev_pm_opp *opp; unsigned long volt = 0, volt_old = 0, tol = 0; long freq_Hz, freq_exact; - unsigned int index; int ret; - ret = cpufreq_frequency_table_target(policy, freq_table, target_freq, - relation, &index); - if (ret) { - pr_err("failed to match target freqency %d: %d\n", - target_freq, ret); - return ret; - } - freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); if (freq_Hz < 0) freq_Hz = freq_table[index].frequency * 1000; @@ -60,9 +50,6 @@ static int cpu0_set_target(struct cpufreq_policy *policy, freqs.new = freq_Hz / 1000; freqs.old = clk_get_rate(cpu_clk) / 1000; - if (freqs.old == freqs.new) - return 0; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); if (!IS_ERR(cpu_reg)) { @@ -128,7 +115,7 @@ static int cpu0_cpufreq_init(struct cpufreq_policy *policy) static struct cpufreq_driver cpu0_cpufreq_driver = { .flags = CPUFREQ_STICKY, .verify = cpufreq_generic_frequency_table_verify, - .target = cpu0_set_target, + .target_index = cpu0_set_target, .get = cpu0_get_speed, .init = cpu0_cpufreq_init, .exit = cpufreq_generic_exit, diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index ec391d7..87ed83a 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -47,6 +47,11 @@ static LIST_HEAD(cpufreq_policy_list); static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); #endif +static inline bool has_target(void) +{ + return cpufreq_driver->target_index || cpufreq_driver->target; +} + /* * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure * all cpufreq/hotplug/workqueue/etc related lock issues. @@ -392,7 +397,7 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, *policy = CPUFREQ_POLICY_POWERSAVE; err = 0; } - } else if (cpufreq_driver->target) { + } else if (has_target()) { struct cpufreq_governor *t; mutex_lock(&cpufreq_governor_mutex); @@ -550,7 +555,7 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy, ssize_t i = 0; struct cpufreq_governor *t; - if (!cpufreq_driver->target) { + if (!has_target()) { i += sprintf(buf, "performance powersave"); goto out; } @@ -835,7 +840,7 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy, if (ret) goto err_out_kobj_put; } - if (cpufreq_driver->target) { + if (has_target()) { ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); if (ret) goto err_out_kobj_put; @@ -884,10 +889,10 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu, struct device *dev, bool frozen) { - int ret = 0, has_target = !!cpufreq_driver->target; + int ret = 0; unsigned long flags; - if (has_target) { + if (has_target()) { ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP); if (ret) { pr_err("%s: Failed to stop governor\n", __func__); @@ -905,7 +910,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unlock_policy_rwsem_write(policy->cpu); - if (has_target) { + if (has_target()) { if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) || (ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) { pr_err("%s: Failed to start governor\n", __func__); @@ -1215,7 +1220,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, return -EINVAL; } - if (cpufreq_driver->target) { + if (has_target()) { ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP); if (ret) { pr_err("%s: Failed to stop governor\n", __func__); @@ -1280,7 +1285,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev, /* If cpu is last user of policy, free policy */ if (cpus == 1) { - if (cpufreq_driver->target) { + if (has_target()) { ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); if (ret) { @@ -1323,7 +1328,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev, if (!frozen) cpufreq_policy_free(policy); } else { - if (cpufreq_driver->target) { + if (has_target()) { if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) || (ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) { pr_err("%s: Failed to start governor\n", @@ -1694,12 +1699,41 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n", policy->cpu, target_freq, relation, old_target_freq); + /* + * This might look like a redundant call as we are checking it again + * after finding index. But it is left intentionally for cases where + * exactly same freq is called again and so we can save on few function + * calls. + */ if (target_freq == policy->cur) return 0; if (cpufreq_driver->target) retval = cpufreq_driver->target(policy, target_freq, relation); + else if (cpufreq_driver->target_index) { + struct cpufreq_frequency_table *freq_table; + int index; + freq_table = cpufreq_frequency_get_table(policy->cpu); + if (unlikely(!freq_table)) { + pr_err("%s: Unable to find freq_table\n", __func__); + goto out; + } + + retval = cpufreq_frequency_table_target(policy, freq_table, + target_freq, relation, &index); + if (unlikely(retval)) { + pr_err("%s: Unable to find matching freq\n", __func__); + goto out; + } + + if (freq_table[index].frequency == policy->cur) + retval = 0; + else + retval = cpufreq_driver->target_index(policy, index); + } + +out: return retval; } EXPORT_SYMBOL_GPL(__cpufreq_driver_target); @@ -2025,7 +2059,7 @@ int cpufreq_update_policy(unsigned int cpu) pr_debug("Driver did not initialize current freq"); policy->cur = new_policy.cur; } else { - if (policy->cur != new_policy.cur && cpufreq_driver->target) + if (policy->cur != new_policy.cur && has_target()) cpufreq_out_of_sync(cpu, policy->cur, new_policy.cur); } @@ -2103,7 +2137,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) return -ENODEV; if (!driver_data || !driver_data->verify || !driver_data->init || - ((!driver_data->setpolicy) && (!driver_data->target))) + !(driver_data->setpolicy || driver_data->target_index || + driver_data->target)) return -EINVAL; pr_debug("trying to register driver %s\n", driver_data->name); diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c index 05fdc7e..841857c 100644 --- a/drivers/cpufreq/cris-artpec3-cpufreq.c +++ b/drivers/cpufreq/cris-artpec3-cpufreq.c @@ -27,8 +27,7 @@ static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu) return clk_ctrl.pll ? 200000 : 6000; } -static void cris_freq_set_cpu_state(struct cpufreq_policy *policy, - unsigned int state) +static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state) { struct cpufreq_freqs freqs; reg_clkgen_rw_clk_ctrl clk_ctrl; @@ -52,19 +51,6 @@ static void cris_freq_set_cpu_state(struct cpufreq_policy *policy, local_irq_enable(); cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); -}; - -static int cris_freq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int newstate = 0; - - if (cpufreq_frequency_table_target(policy, cris_freq_table, - target_freq, relation, &newstate)) - return -EINVAL; - - cris_freq_set_cpu_state(policy, newstate); return 0; } @@ -77,7 +63,7 @@ static int cris_freq_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver cris_freq_driver = { .get = cris_freq_get_cpu_frequency, .verify = cpufreq_generic_frequency_table_verify, - .target = cris_freq_target, + .target_index = cris_freq_target, .init = cris_freq_cpu_init, .exit = cpufreq_generic_exit, .name = "cris_freq", diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c index fac2b26..c58811a 100644 --- a/drivers/cpufreq/cris-etraxfs-cpufreq.c +++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c @@ -27,8 +27,7 @@ static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu) return clk_ctrl.pll ? 200000 : 6000; } -static void cris_freq_set_cpu_state(struct cpufreq_policy *policy, - unsigned int state) +static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state) { struct cpufreq_freqs freqs; reg_config_rw_clk_ctrl clk_ctrl; @@ -52,18 +51,6 @@ static void cris_freq_set_cpu_state(struct cpufreq_policy *policy, local_irq_enable(); cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); -}; - -static int cris_freq_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) -{ - unsigned int newstate = 0; - - if (cpufreq_frequency_table_target - (policy, cris_freq_table, target_freq, relation, &newstate)) - return -EINVAL; - - cris_freq_set_cpu_state(policy, newstate); return 0; } @@ -76,7 +63,7 @@ static int cris_freq_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver cris_freq_driver = { .get = cris_freq_get_cpu_frequency, .verify = cpufreq_generic_frequency_table_verify, - .target = cris_freq_target, + .target_index = cris_freq_target, .init = cris_freq_cpu_init, .exit = cpufreq_generic_exit, .name = "cris_freq", diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c index 972583b..1f5d8a5 100644 --- a/drivers/cpufreq/davinci-cpufreq.c +++ b/drivers/cpufreq/davinci-cpufreq.c @@ -66,28 +66,18 @@ static unsigned int davinci_getspeed(unsigned int cpu) return clk_get_rate(cpufreq.armclk) / 1000; } -static int davinci_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) +static int davinci_target(struct cpufreq_policy *policy, unsigned int idx) { int ret = 0; - unsigned int idx; struct cpufreq_freqs freqs; struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; struct clk *armclk = cpufreq.armclk; freqs.old = davinci_getspeed(0); - freqs.new = clk_round_rate(armclk, target_freq * 1000) / 1000; - - if (freqs.old == freqs.new) - return ret; + freqs.new = pdata->freq_table[idx].frequency; dev_dbg(cpufreq.dev, "transition: %u --> %u\n", freqs.old, freqs.new); - ret = cpufreq_frequency_table_target(policy, pdata->freq_table, - freqs.new, relation, &idx); - if (ret) - return -EINVAL; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); /* if moving to higher frequency, up the voltage beforehand */ @@ -148,7 +138,7 @@ static int davinci_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver davinci_driver = { .flags = CPUFREQ_STICKY, .verify = davinci_verify_speed, - .target = davinci_target, + .target_index = davinci_target, .get = davinci_getspeed, .init = davinci_cpu_init, .exit = cpufreq_generic_exit, diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c index a60f769..238b169 100644 --- a/drivers/cpufreq/dbx500-cpufreq.c +++ b/drivers/cpufreq/dbx500-cpufreq.c @@ -20,23 +20,13 @@ static struct cpufreq_frequency_table *freq_table; static struct clk *armss_clk; static int dbx500_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int index) { struct cpufreq_freqs freqs; - unsigned int idx; int ret; - /* Lookup the next frequency */ - if (cpufreq_frequency_table_target(policy, freq_table, target_freq, - relation, &idx)) - return -EINVAL; - freqs.old = policy->cur; - freqs.new = freq_table[idx].frequency; - - if (freqs.old == freqs.new) - return 0; + freqs.new = freq_table[index].frequency; /* pre-change notification */ cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); @@ -80,7 +70,7 @@ static int dbx500_cpufreq_init(struct cpufreq_policy *policy) static struct cpufreq_driver dbx500_cpufreq_driver = { .flags = CPUFREQ_STICKY | CPUFREQ_CONST_LOOPS, .verify = cpufreq_generic_frequency_table_verify, - .target = dbx500_cpufreq_target, + .target_index = dbx500_cpufreq_target, .get = dbx500_cpufreq_getspeed, .init = dbx500_cpufreq_init, .name = "DBX500", diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index 2c11ce3..b39c4ef 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -168,12 +168,9 @@ postchange: return err; } -static int eps_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int eps_target(struct cpufreq_policy *policy, unsigned int index) { struct eps_cpu_data *centaur; - unsigned int newstate = 0; unsigned int cpu = policy->cpu; unsigned int dest_state; int ret; @@ -182,16 +179,8 @@ static int eps_target(struct cpufreq_policy *policy, return -ENODEV; centaur = eps_cpu[cpu]; - if (unlikely(cpufreq_frequency_table_target(policy, - &eps_cpu[cpu]->freq_table[0], - target_freq, - relation, - &newstate))) { - return -EINVAL; - } - /* Make frequency transition */ - dest_state = centaur->freq_table[newstate].driver_data & 0xffff; + dest_state = centaur->freq_table[index].driver_data & 0xffff; ret = eps_set_state(centaur, policy, dest_state); if (ret) printk(KERN_ERR "eps: Timeout!\n"); @@ -418,7 +407,7 @@ static int eps_cpu_exit(struct cpufreq_policy *policy) static struct cpufreq_driver eps_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = eps_target, + .target_index = eps_target, .init = eps_cpu_init, .exit = eps_cpu_exit, .get = eps_get, diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index d91a645..4ab4153 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c @@ -105,20 +105,8 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu) } -/** - * elanfreq_set_cpu_frequency: Change the CPU core frequency - * @cpu: cpu number - * @freq: frequency in kHz - * - * This function takes a frequency value and changes the CPU frequency - * according to this. Note that the frequency has to be checked by - * elanfreq_validatespeed() for correctness! - * - * There is no return value. - */ - -static void elanfreq_set_cpu_state(struct cpufreq_policy *policy, - unsigned int state) +static int elanfreq_target(struct cpufreq_policy *policy, + unsigned int state) { struct cpufreq_freqs freqs; @@ -162,25 +150,9 @@ static void elanfreq_set_cpu_state(struct cpufreq_policy *policy, local_irq_enable(); cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); -}; - - -static int elanfreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int newstate = 0; - - if (cpufreq_frequency_table_target(policy, &elanfreq_table[0], - target_freq, relation, &newstate)) - return -EINVAL; - - elanfreq_set_cpu_state(policy, newstate); return 0; } - - /* * Module init and exit code */ @@ -237,7 +209,7 @@ __setup("elanfreq=", elanfreq_setup); static struct cpufreq_driver elanfreq_driver = { .get = elanfreq_get_cpu_frequency, .verify = cpufreq_generic_frequency_table_verify, - .target = elanfreq_target, + .target_index = elanfreq_target, .init = elanfreq_cpu_init, .exit = cpufreq_generic_exit, .name = "elanfreq", diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index 3e4af67..9982fcb 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -65,9 +65,6 @@ static int exynos_cpufreq_scale(unsigned int target_freq) freqs.old = policy->cur; freqs.new = target_freq; - if (freqs.new == freqs.old) - goto out; - /* * The policy max have been changed so that we cannot get proper * old_index with cpufreq_frequency_table_target(). Thus, ignore @@ -151,13 +148,9 @@ out: return ret; } -static int exynos_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int exynos_target(struct cpufreq_policy *policy, unsigned int index) { struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; - unsigned int index; - unsigned int new_freq; int ret = 0; mutex_lock(&cpufreq_lock); @@ -165,15 +158,7 @@ static int exynos_target(struct cpufreq_policy *policy, if (frequency_locked) goto out; - if (cpufreq_frequency_table_target(policy, freq_table, - target_freq, relation, &index)) { - ret = -EINVAL; - goto out; - } - - new_freq = freq_table[index].frequency; - - ret = exynos_cpufreq_scale(new_freq); + ret = exynos_cpufreq_scale(freq_table[index].frequency); out: mutex_unlock(&cpufreq_lock); @@ -247,7 +232,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver exynos_driver = { .flags = CPUFREQ_STICKY, .verify = cpufreq_generic_frequency_table_verify, - .target = exynos_target, + .target_index = exynos_target, .get = exynos_getspeed, .init = exynos_cpufreq_cpu_init, .exit = cpufreq_generic_exit, diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index 8ae5e29..1bf9b06 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -214,27 +214,17 @@ static unsigned int exynos_getspeed(unsigned int cpu) return dvfs_info->cur_frequency; } -static int exynos_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int exynos_target(struct cpufreq_policy *policy, unsigned int index) { - unsigned int index, tmp; - int ret = 0, i; + unsigned int tmp; + int i; struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table; mutex_lock(&cpufreq_lock); - ret = cpufreq_frequency_table_target(policy, freq_table, - target_freq, relation, &index); - if (ret) - goto out; - freqs.old = dvfs_info->cur_frequency; freqs.new = freq_table[index].frequency; - if (freqs.old == freqs.new) - goto out; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); /* Set the target frequency in all C0_3_PSTATE register */ @@ -245,9 +235,8 @@ static int exynos_target(struct cpufreq_policy *policy, __raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + i * 4); } -out: mutex_unlock(&cpufreq_lock); - return ret; + return 0; } static void exynos_cpufreq_work(struct work_struct *work) @@ -325,7 +314,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver exynos_driver = { .flags = CPUFREQ_STICKY, .verify = cpufreq_generic_frequency_table_verify, - .target = exynos_target, + .target_index = exynos_target, .get = exynos_getspeed, .init = exynos_cpufreq_cpu_init, .exit = cpufreq_generic_exit, diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index 90c6598..4695fa2 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -227,26 +227,11 @@ acpi_cpufreq_get ( static int acpi_cpufreq_target ( struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int index) { - struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; - unsigned int next_state = 0; - unsigned int result = 0; - - pr_debug("acpi_cpufreq_setpolicy\n"); - - result = cpufreq_frequency_table_target(policy, - data->freq_table, target_freq, relation, &next_state); - if (result) - return (result); - - result = processor_set_freq(data, policy, next_state); - - return (result); + return processor_set_freq(acpi_io_data[policy->cpu], policy, index); } - static int acpi_cpufreq_cpu_init ( struct cpufreq_policy *policy) @@ -379,7 +364,7 @@ acpi_cpufreq_cpu_exit ( static struct cpufreq_driver acpi_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = acpi_cpufreq_target, + .target_index = acpi_cpufreq_target, .get = acpi_cpufreq_get, .init = acpi_cpufreq_cpu_init, .exit = acpi_cpufreq_cpu_exit, diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index be23892..07af3b0 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -40,30 +40,17 @@ static unsigned int imx6q_get_speed(unsigned int cpu) return clk_get_rate(arm_clk) / 1000; } -static int imx6q_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) +static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) { struct cpufreq_freqs freqs; struct dev_pm_opp *opp; unsigned long freq_hz, volt, volt_old; - unsigned int index; int ret; - ret = cpufreq_frequency_table_target(policy, freq_table, target_freq, - relation, &index); - if (ret) { - dev_err(cpu_dev, "failed to match target frequency %d: %d\n", - target_freq, ret); - return ret; - } - freqs.new = freq_table[index].frequency; freq_hz = freqs.new * 1000; freqs.old = clk_get_rate(arm_clk) / 1000; - if (freqs.old == freqs.new) - return 0; - rcu_read_lock(); opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); if (IS_ERR(opp)) { @@ -159,7 +146,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy) static struct cpufreq_driver imx6q_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = imx6q_set_target, + .target_index = imx6q_set_target, .get = imx6q_get_speed, .init = imx6q_cpufreq_init, .exit = cpufreq_generic_exit, diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index fff8653..0ae4dd7 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -55,8 +55,8 @@ static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu) return kirkwood_freq_table[0].frequency; } -static void kirkwood_cpufreq_set_cpu_state(struct cpufreq_policy *policy, - unsigned int index) +static int kirkwood_cpufreq_target(struct cpufreq_policy *policy, + unsigned int index) { struct cpufreq_freqs freqs; unsigned int state = kirkwood_freq_table[index].driver_data; @@ -100,19 +100,6 @@ static void kirkwood_cpufreq_set_cpu_state(struct cpufreq_policy *policy, local_irq_enable(); } cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); -}; - -static int kirkwood_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int index = 0; - - if (cpufreq_frequency_table_target(policy, kirkwood_freq_table, - target_freq, relation, &index)) - return -EINVAL; - - kirkwood_cpufreq_set_cpu_state(policy, index); return 0; } @@ -126,7 +113,7 @@ static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver kirkwood_cpufreq_driver = { .get = kirkwood_cpufreq_get_cpu_frequency, .verify = cpufreq_generic_frequency_table_verify, - .target = kirkwood_cpufreq_target, + .target_index = kirkwood_cpufreq_target, .init = kirkwood_cpufreq_cpu_init, .exit = cpufreq_generic_exit, .name = "kirkwood-cpufreq", diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 14df497..45bafdd 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -626,21 +626,12 @@ static void longhaul_setup_voltagescaling(void) static int longhaul_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) + unsigned int table_index) { - unsigned int table_index = 0; unsigned int i; unsigned int dir = 0; u8 vid, current_vid; - if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, - relation, &table_index)) - return -EINVAL; - - /* Don't set same frequency again */ - if (longhaul_index == table_index) - return 0; - if (!can_scale_voltage) longhaul_setstate(policy, table_index); else { @@ -919,7 +910,7 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver longhaul_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = longhaul_target, + .target_index = longhaul_target, .get = longhaul_get, .init = longhaul_cpu_init, .exit = cpufreq_generic_exit, diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index 2c8ec8e..41a8e2c 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -53,11 +53,9 @@ static unsigned int loongson2_cpufreq_get(unsigned int cpu) * Here we notify other drivers of the proposed change and the final change. */ static int loongson2_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int index) { unsigned int cpu = policy->cpu; - unsigned int newstate = 0; cpumask_t cpus_allowed; struct cpufreq_freqs freqs; unsigned int freq; @@ -65,26 +63,17 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy, cpus_allowed = current->cpus_allowed; set_cpus_allowed_ptr(current, cpumask_of(cpu)); - if (cpufreq_frequency_table_target - (policy, &loongson2_clockmod_table[0], target_freq, relation, - &newstate)) - return -EINVAL; - freq = ((cpu_clock_freq / 1000) * - loongson2_clockmod_table[newstate].driver_data) / 8; - if (freq < policy->min || freq > policy->max) - return -EINVAL; + loongson2_clockmod_table[index].driver_data) / 8; - pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000); + pr_debug("cpufreq: requested frequency %u Hz\n", + loongson2_clockmod_table[index].frequency * 1000); freqs.old = loongson2_cpufreq_get(cpu); freqs.new = freq; freqs.flags = 0; - if (freqs.new == freqs.old) - return 0; - /* notifiers */ cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); @@ -145,7 +134,7 @@ static struct cpufreq_driver loongson2_cpufreq_driver = { .name = "loongson2", .init = loongson2_cpufreq_cpu_init, .verify = cpufreq_generic_frequency_table_verify, - .target = loongson2_cpufreq_target, + .target_index = loongson2_cpufreq_target, .get = loongson2_cpufreq_get, .exit = loongson2_cpufreq_exit, .attr = cpufreq_generic_attr, diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c index eb1e176..4e2da08 100644 --- a/drivers/cpufreq/maple-cpufreq.c +++ b/drivers/cpufreq/maple-cpufreq.c @@ -131,26 +131,18 @@ static int maple_scom_query_freq(void) */ static int maple_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) + unsigned int index) { - unsigned int newstate = 0; struct cpufreq_freqs freqs; int rc; - if (cpufreq_frequency_table_target(policy, maple_cpu_freqs, - target_freq, relation, &newstate)) - return -EINVAL; - - if (maple_pmode_cur == newstate) - return 0; - mutex_lock(&maple_switch_mutex); freqs.old = maple_cpu_freqs[maple_pmode_cur].frequency; - freqs.new = maple_cpu_freqs[newstate].frequency; + freqs.new = maple_cpu_freqs[index].frequency; cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - rc = maple_scom_switch_freq(newstate); + rc = maple_scom_switch_freq(index); cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); mutex_unlock(&maple_switch_mutex); @@ -173,7 +165,7 @@ static struct cpufreq_driver maple_cpufreq_driver = { .flags = CPUFREQ_CONST_LOOPS, .init = maple_cpufreq_cpu_init, .verify = cpufreq_generic_frequency_table_verify, - .target = maple_cpufreq_target, + .target_index = maple_cpufreq_target, .get = maple_cpufreq_get_speed, .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index ac552d0..b551271 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -51,40 +51,15 @@ static unsigned int omap_getspeed(unsigned int cpu) return rate; } -static int omap_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int omap_target(struct cpufreq_policy *policy, unsigned int index) { - unsigned int i; int r, ret = 0; struct cpufreq_freqs freqs; struct dev_pm_opp *opp; unsigned long freq, volt = 0, volt_old = 0, tol = 0; - if (!freq_table) { - dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__, - policy->cpu); - return -EINVAL; - } - - ret = cpufreq_frequency_table_target(policy, freq_table, target_freq, - relation, &i); - if (ret) { - dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n", - __func__, policy->cpu, target_freq, ret); - return ret; - } - freqs.new = freq_table[i].frequency; - if (!freqs.new) { - dev_err(mpu_dev, "%s: cpu%d: no match for freq %d\n", __func__, - policy->cpu, target_freq); - return -EINVAL; - } - freqs.old = omap_getspeed(policy->cpu); - - if (freqs.old == freqs.new && policy->cur == freqs.new) - return ret; + freqs.new = freq_table[index].frequency; freq = freqs.new * 1000; ret = clk_round_rate(mpu_clk, freq); @@ -200,7 +175,7 @@ static int omap_cpu_exit(struct cpufreq_policy *policy) static struct cpufreq_driver omap_driver = { .flags = CPUFREQ_STICKY, .verify = cpufreq_generic_frequency_table_verify, - .target = omap_target, + .target_index = omap_target, .get = omap_getspeed, .init = omap_cpu_init, .exit = omap_cpu_exit, diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 6164c1c..3c23053 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -105,23 +105,13 @@ static struct cpufreq_frequency_table p4clockmod_table[] = { }; -static int cpufreq_p4_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int cpufreq_p4_target(struct cpufreq_policy *policy, unsigned int index) { - unsigned int newstate = DC_RESV; struct cpufreq_freqs freqs; int i; - if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], - target_freq, relation, &newstate)) - return -EINVAL; - freqs.old = cpufreq_p4_get(policy->cpu); - freqs.new = stock_freq * p4clockmod_table[newstate].driver_data / 8; - - if (freqs.new == freqs.old) - return 0; + freqs.new = stock_freq * p4clockmod_table[index].driver_data / 8; /* notifiers */ cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); @@ -131,7 +121,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, * Developer's Manual, Volume 3 */ for_each_cpu(i, policy->cpus) - cpufreq_p4_setdc(i, p4clockmod_table[newstate].driver_data); + cpufreq_p4_setdc(i, p4clockmod_table[index].driver_data); /* notifiers */ cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); @@ -255,7 +245,7 @@ static unsigned int cpufreq_p4_get(unsigned int cpu) static struct cpufreq_driver p4clockmod_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = cpufreq_p4_target, + .target_index = cpufreq_p4_target, .init = cpufreq_p4_cpu_init, .exit = cpufreq_generic_exit, .get = cpufreq_p4_get, diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index 1cca332..17424dd 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c @@ -240,19 +240,11 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy) } static int pas_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int pas_astate_new) { struct cpufreq_freqs freqs; - int pas_astate_new; int i; - cpufreq_frequency_table_target(policy, - pas_freqs, - target_freq, - relation, - &pas_astate_new); - freqs.old = policy->cur; freqs.new = pas_freqs[pas_astate_new].frequency; @@ -282,7 +274,7 @@ static struct cpufreq_driver pas_cpufreq_driver = { .init = pas_cpufreq_cpu_init, .exit = pas_cpufreq_cpu_exit, .verify = cpufreq_generic_frequency_table_verify, - .target = pas_cpufreq_target, + .target_index = pas_cpufreq_target, .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index 6eac1e2..05f705e1 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -374,17 +374,11 @@ static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) } static int pmac_cpufreq_target( struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int index) { - unsigned int newstate = 0; int rc; - if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs, - target_freq, relation, &newstate)) - return -EINVAL; - - rc = do_set_cpu_speed(policy, newstate, 1); + rc = do_set_cpu_speed(policy, index, 1); ppc_proc_freq = cur_freq * 1000ul; return rc; @@ -453,7 +447,7 @@ static int pmac_cpufreq_resume(struct cpufreq_policy *policy) static struct cpufreq_driver pmac_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = pmac_cpufreq_target, + .target_index = pmac_cpufreq_target, .get = pmac_cpufreq_get_speed, .init = pmac_cpufreq_cpu_init, .suspend = pmac_cpufreq_suspend, diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 5261b92..234b598 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -312,27 +312,18 @@ static int g5_pfunc_query_freq(void) * Common interface to the cpufreq core */ -static int g5_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) +static int g5_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { - unsigned int newstate = 0; struct cpufreq_freqs freqs; int rc; - if (cpufreq_frequency_table_target(policy, g5_cpu_freqs, - target_freq, relation, &newstate)) - return -EINVAL; - - if (g5_pmode_cur == newstate) - return 0; - mutex_lock(&g5_switch_mutex); freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; - freqs.new = g5_cpu_freqs[newstate].frequency; + freqs.new = g5_cpu_freqs[index].frequency; cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - rc = g5_switch_freq(newstate); + rc = g5_switch_freq(index); cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); mutex_unlock(&g5_switch_mutex); @@ -355,7 +346,7 @@ static struct cpufreq_driver g5_cpufreq_driver = { .flags = CPUFREQ_CONST_LOOPS, .init = g5_cpufreq_cpu_init, .verify = cpufreq_generic_frequency_table_verify, - .target = g5_cpufreq_target, + .target_index = g5_cpufreq_target, .get = g5_cpufreq_get_speed, .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index eda1702..643e795 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c @@ -63,12 +63,12 @@ static int powernow_k6_get_cpu_multiplier(void) /** - * powernow_k6_set_state - set the PowerNow! multiplier + * powernow_k6_target - set the PowerNow! multiplier * @best_i: clock_ratio[best_i] is the target multiplier * * Tries to change the PowerNow! multiplier */ -static void powernow_k6_set_state(struct cpufreq_policy *policy, +static int powernow_k6_target(struct cpufreq_policy *policy, unsigned int best_i) { unsigned long outvalue = 0, invalue = 0; @@ -77,7 +77,7 @@ static void powernow_k6_set_state(struct cpufreq_policy *policy, if (clock_ratio[best_i].driver_data > max_multiplier) { printk(KERN_ERR PFX "invalid target frequency\n"); - return; + return -EINVAL; } freqs.old = busfreq * powernow_k6_get_cpu_multiplier(); @@ -100,31 +100,6 @@ static void powernow_k6_set_state(struct cpufreq_policy *policy, cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return; -} - - -/** - * powernow_k6_setpolicy - sets a new CPUFreq policy - * @policy: new policy - * @target_freq: the target frequency - * @relation: how that frequency relates to achieved frequency - * (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H) - * - * sets a new CPUFreq policy - */ -static int powernow_k6_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int newstate = 0; - - if (cpufreq_frequency_table_target(policy, &clock_ratio[0], - target_freq, relation, &newstate)) - return -EINVAL; - - powernow_k6_set_state(policy, newstate); - return 0; } @@ -161,7 +136,7 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy) unsigned int i; for (i = 0; i < 8; i++) { if (i == max_multiplier) - powernow_k6_set_state(policy, i); + powernow_k6_target(policy, i); } cpufreq_frequency_table_put_attr(policy->cpu); return 0; @@ -176,7 +151,7 @@ static unsigned int powernow_k6_get(unsigned int cpu) static struct cpufreq_driver powernow_k6_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = powernow_k6_target, + .target_index = powernow_k6_target, .init = powernow_k6_cpu_init, .exit = powernow_k6_cpu_exit, .get = powernow_k6_get, diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index 44d345b..946708a 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -248,7 +248,7 @@ static void change_VID(int vid) } -static void change_speed(struct cpufreq_policy *policy, unsigned int index) +static int powernow_target(struct cpufreq_policy *policy, unsigned int index) { u8 fid, vid; struct cpufreq_freqs freqs; @@ -291,6 +291,8 @@ static void change_speed(struct cpufreq_policy *policy, unsigned int index) local_irq_enable(); cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); + + return 0; } @@ -533,22 +535,6 @@ static int powernow_decode_bios(int maxfid, int startvid) } -static int powernow_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int newstate; - - if (cpufreq_frequency_table_target(policy, powernow_table, target_freq, - relation, &newstate)) - return -EINVAL; - - change_speed(policy, newstate); - - return 0; -} - - /* * We use the fact that the bus frequency is somehow * a multiple of 100000/3 khz, then we compute sgtc according @@ -694,7 +680,7 @@ static int powernow_cpu_exit(struct cpufreq_policy *policy) static struct cpufreq_driver powernow_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = powernow_target, + .target_index = powernow_target, .get = powernow_get, #ifdef CONFIG_X86_POWERNOW_K7_ACPI .bios_limit = acpi_processor_get_bios_limit, diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 298beb7..62a1ce4 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -977,20 +977,17 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, struct powernowk8_target_arg { struct cpufreq_policy *pol; - unsigned targfreq; - unsigned relation; + unsigned newstate; }; static long powernowk8_target_fn(void *arg) { struct powernowk8_target_arg *pta = arg; struct cpufreq_policy *pol = pta->pol; - unsigned targfreq = pta->targfreq; - unsigned relation = pta->relation; + unsigned newstate = pta->newstate; struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); u32 checkfid; u32 checkvid; - unsigned int newstate; int ret; if (!data) @@ -1004,8 +1001,9 @@ static long powernowk8_target_fn(void *arg) return -EIO; } - pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", - pol->cpu, targfreq, pol->min, pol->max, relation); + pr_debug("targ: cpu %d, %d kHz, min %d, max %d\n", + pol->cpu, data->powernow_table[newstate].frequency, pol->min, + pol->max); if (query_current_values_with_pending_wait(data)) return -EIO; @@ -1021,10 +1019,6 @@ static long powernowk8_target_fn(void *arg) checkvid, data->currvid); } - if (cpufreq_frequency_table_target(pol, data->powernow_table, - targfreq, relation, &newstate)) - return -EIO; - mutex_lock(&fidvid_mutex); powernow_k8_acpi_pst_values(data, newstate); @@ -1044,11 +1038,9 @@ static long powernowk8_target_fn(void *arg) } /* Driver entry point to switch to the target frequency */ -static int powernowk8_target(struct cpufreq_policy *pol, - unsigned targfreq, unsigned relation) +static int powernowk8_target(struct cpufreq_policy *pol, unsigned index) { - struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, - .relation = relation }; + struct powernowk8_target_arg pta = { .pol = pol, .newstate = index }; return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); } @@ -1213,7 +1205,7 @@ out: static struct cpufreq_driver cpufreq_amd64_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = powernowk8_target, + .target_index = powernowk8_target, .bios_limit = acpi_processor_get_bios_limit, .init = powernowk8_cpu_init, .exit = powernowk8_cpu_exit, diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c index a0f562c..79d8e9c 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/ppc-corenet-cpufreq.c @@ -251,27 +251,20 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy) } static int corenet_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) + unsigned int index) { struct cpufreq_freqs freqs; - unsigned int new; struct clk *parent; int ret; struct cpu_data *data = per_cpu(cpu_data, policy->cpu); - cpufreq_frequency_table_target(policy, data->table, - target_freq, relation, &new); - - if (policy->cur == data->table[new].frequency) - return 0; - freqs.old = policy->cur; - freqs.new = data->table[new].frequency; + freqs.new = data->table[index].frequency; mutex_lock(&cpufreq_lock); cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - parent = of_clk_get(data->parent, data->table[new].driver_data); + parent = of_clk_get(data->parent, data->table[index].driver_data); ret = clk_set_parent(data->clk, parent); if (ret) freqs.new = freqs.old; @@ -288,7 +281,7 @@ static struct cpufreq_driver ppc_corenet_cpufreq_driver = { .init = corenet_cpufreq_cpu_init, .exit = __exit_p(corenet_cpufreq_cpu_exit), .verify = cpufreq_generic_frequency_table_verify, - .target = corenet_cpufreq_target, + .target_index = corenet_cpufreq_target, .get = corenet_cpufreq_get_speed, .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c index 38540d1..52f707d 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq.c @@ -129,18 +129,10 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) } static int cbe_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int cbe_pmode_new) { int rc; struct cpufreq_freqs freqs; - unsigned int cbe_pmode_new; - - cpufreq_frequency_table_target(policy, - cbe_freqs, - target_freq, - relation, - &cbe_pmode_new); freqs.old = policy->cur; freqs.new = cbe_freqs[cbe_pmode_new].frequency; @@ -164,7 +156,7 @@ static int cbe_cpufreq_target(struct cpufreq_policy *policy, static struct cpufreq_driver cbe_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = cbe_cpufreq_target, + .target_index = cbe_cpufreq_target, .init = cbe_cpufreq_cpu_init, .exit = cpufreq_generic_exit, .name = "cbe-cpufreq", diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index 29aca57..183bc13 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -267,14 +267,11 @@ static unsigned int pxa_cpufreq_get(unsigned int cpu) return get_clk_frequency_khz(0); } -static int pxa_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx) { struct cpufreq_frequency_table *pxa_freqs_table; pxa_freqs_t *pxa_freq_settings; struct cpufreq_freqs freqs; - unsigned int idx; unsigned long flags; unsigned int new_freq_cpu, new_freq_mem; unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg; @@ -283,12 +280,6 @@ static int pxa_set_target(struct cpufreq_policy *policy, /* Get the current policy */ find_freq_tables(&pxa_freqs_table, &pxa_freq_settings); - /* Lookup the next frequency */ - if (cpufreq_frequency_table_target(policy, pxa_freqs_table, - target_freq, relation, &idx)) { - return -EINVAL; - } - new_freq_cpu = pxa_freq_settings[idx].khz; new_freq_mem = pxa_freq_settings[idx].membus; freqs.old = policy->cur; @@ -448,7 +439,7 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) static struct cpufreq_driver pxa_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = pxa_set_target, + .target_index = pxa_set_target, .init = pxa_cpufreq_init, .exit = cpufreq_generic_exit, .get = pxa_cpufreq_get, diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c index 47fbee4..132e37d 100644 --- a/drivers/cpufreq/pxa3xx-cpufreq.c +++ b/drivers/cpufreq/pxa3xx-cpufreq.c @@ -155,24 +155,16 @@ static unsigned int pxa3xx_cpufreq_get(unsigned int cpu) return pxa3xx_get_clk_frequency_khz(0); } -static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, unsigned int index) { struct pxa3xx_freq_info *next; struct cpufreq_freqs freqs; unsigned long flags; - int idx; if (policy->cpu != 0) return -EINVAL; - /* Lookup the next frequency */ - if (cpufreq_frequency_table_target(policy, pxa3xx_freqs_table, - target_freq, relation, &idx)) - return -EINVAL; - - next = &pxa3xx_freqs[idx]; + next = &pxa3xx_freqs[index]; freqs.old = policy->cur; freqs.new = next->cpufreq_mhz * 1000; @@ -181,9 +173,6 @@ static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, freqs.old / 1000, freqs.new / 1000, (freqs.old == freqs.new) ? " (skipped)" : ""); - if (freqs.old == target_freq) - return 0; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); local_irq_save(flags); @@ -225,7 +214,7 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy) static struct cpufreq_driver pxa3xx_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = pxa3xx_cpufreq_set, + .target_index = pxa3xx_cpufreq_set, .init = pxa3xx_cpufreq_init, .exit = cpufreq_generic_exit, .get = pxa3xx_cpufreq_get, diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index 26a35d1..4188acc 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -217,24 +217,15 @@ static int s3c2416_cpufreq_leave_dvs(struct s3c2416_data *s3c_freq, int idx) } static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int index) { struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; struct cpufreq_freqs freqs; int idx, ret, to_dvs = 0; - unsigned int i; mutex_lock(&cpufreq_lock); - pr_debug("cpufreq: to %dKHz, relation %d\n", target_freq, relation); - - ret = cpufreq_frequency_table_target(policy, s3c_freq->freq_table, - target_freq, relation, &i); - if (ret != 0) - goto out; - - idx = s3c_freq->freq_table[i].driver_data; + idx = s3c_freq->freq_table[index].driver_data; if (idx == SOURCE_HCLK) to_dvs = 1; @@ -256,7 +247,7 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy, */ freqs.new = (s3c_freq->is_dvs && !to_dvs) ? clk_get_rate(s3c_freq->hclk) / 1000 - : s3c_freq->freq_table[i].frequency; + : s3c_freq->freq_table[index].frequency; pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new); @@ -505,7 +496,7 @@ err_hclk: static struct cpufreq_driver s3c2416_cpufreq_driver = { .flags = 0, .verify = cpufreq_generic_frequency_table_verify, - .target = s3c2416_cpufreq_set_target, + .target_index = s3c2416_cpufreq_set_target, .get = s3c2416_cpufreq_get_speed, .init = s3c2416_cpufreq_driver_init, .name = "s3c2416", diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c index 4616173..8bdcf32 100644 --- a/drivers/cpufreq/s3c64xx-cpufreq.c +++ b/drivers/cpufreq/s3c64xx-cpufreq.c @@ -63,26 +63,16 @@ static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu) } static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int index) { int ret; - unsigned int i; struct cpufreq_freqs freqs; struct s3c64xx_dvfs *dvfs; - ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table, - target_freq, relation, &i); - if (ret != 0) - return ret; - freqs.old = clk_get_rate(armclk) / 1000; - freqs.new = s3c64xx_freq_table[i].frequency; + freqs.new = s3c64xx_freq_table[index].frequency; freqs.flags = 0; - dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].driver_data]; - - if (freqs.old == freqs.new) - return 0; + dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[index].driver_data]; pr_debug("Transition %d-%dkHz\n", freqs.old, freqs.new); @@ -254,7 +244,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) static struct cpufreq_driver s3c64xx_cpufreq_driver = { .flags = 0, .verify = cpufreq_generic_frequency_table_verify, - .target = s3c64xx_cpufreq_set_target, + .target_index = s3c64xx_cpufreq_set_target, .get = s3c64xx_cpufreq_get_speed, .init = s3c64xx_cpufreq_driver_init, .name = "s3c", diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 600b4f4..5978b94 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -36,16 +36,7 @@ static DEFINE_MUTEX(set_freq_lock); /* Use 800MHz when entering sleep mode */ #define SLEEP_FREQ (800 * 1000) -/* - * relation has an additional symantics other than the standard of cpufreq - * DISALBE_FURTHER_CPUFREQ: disable further access to target - * ENABLE_FURTUER_CPUFREQ: enable access to target - */ -enum cpufreq_access { - DISABLE_FURTHER_CPUFREQ = 0x10, - ENABLE_FURTHER_CPUFREQ = 0x20, -}; - +/* Tracks if cpu freqency can be updated anymore */ static bool no_cpufreq_access; /* @@ -182,12 +173,10 @@ static unsigned int s5pv210_getspeed(unsigned int cpu) return clk_get_rate(cpu_clk) / 1000; } -static int s5pv210_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) { unsigned long reg; - unsigned int index, priv_index; + unsigned int priv_index; unsigned int pll_changing = 0; unsigned int bus_speed_changing = 0; int arm_volt, int_volt; @@ -195,9 +184,6 @@ static int s5pv210_target(struct cpufreq_policy *policy, mutex_lock(&set_freq_lock); - if (relation & ENABLE_FURTHER_CPUFREQ) - no_cpufreq_access = false; - if (no_cpufreq_access) { #ifdef CONFIG_PM_VERBOSE pr_err("%s:%d denied access to %s as it is disabled" @@ -207,27 +193,13 @@ static int s5pv210_target(struct cpufreq_policy *policy, goto exit; } - if (relation & DISABLE_FURTHER_CPUFREQ) - no_cpufreq_access = true; - - relation &= ~(ENABLE_FURTHER_CPUFREQ | DISABLE_FURTHER_CPUFREQ); - freqs.old = s5pv210_getspeed(0); - - if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, - target_freq, relation, &index)) { - ret = -EINVAL; - goto exit; - } - freqs.new = s5pv210_freq_table[index].frequency; - if (freqs.new == freqs.old) - goto exit; - /* Finding current running level index */ if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, - freqs.old, relation, &priv_index)) { + freqs.old, CPUFREQ_RELATION_H, + &priv_index)) { ret = -EINVAL; goto exit; } @@ -559,16 +531,18 @@ static int s5pv210_cpufreq_notifier_event(struct notifier_block *this, switch (event) { case PM_SUSPEND_PREPARE: - ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, - DISABLE_FURTHER_CPUFREQ); + ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0); if (ret < 0) return NOTIFY_BAD; + /* Disable updation of cpu frequency */ + no_cpufreq_access = true; return NOTIFY_OK; case PM_POST_RESTORE: case PM_POST_SUSPEND: - cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, - ENABLE_FURTHER_CPUFREQ); + /* Enable updation of cpu frequency */ + no_cpufreq_access = false; + cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0); return NOTIFY_OK; } @@ -581,18 +555,18 @@ static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this, { int ret; - ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, - DISABLE_FURTHER_CPUFREQ); + ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0); if (ret < 0) return NOTIFY_BAD; + no_cpufreq_access = true; return NOTIFY_DONE; } static struct cpufreq_driver s5pv210_driver = { .flags = CPUFREQ_STICKY, .verify = cpufreq_generic_frequency_table_verify, - .target = s5pv210_target, + .target_index = s5pv210_target, .get = s5pv210_getspeed, .init = s5pv210_cpu_init, .name = "s5pv210", diff --git a/drivers/cpufreq/sa1100-cpufreq.c b/drivers/cpufreq/sa1100-cpufreq.c index b282cea..b0da1fe 100644 --- a/drivers/cpufreq/sa1100-cpufreq.c +++ b/drivers/cpufreq/sa1100-cpufreq.c @@ -177,36 +177,20 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed) } } -static int sa1100_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int sa1100_target(struct cpufreq_policy *policy, unsigned int ppcr) { unsigned int cur = sa11x0_getspeed(0); - unsigned int new_ppcr; struct cpufreq_freqs freqs; - new_ppcr = sa11x0_freq_to_ppcr(target_freq); - switch (relation) { - case CPUFREQ_RELATION_L: - if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max) - new_ppcr--; - break; - case CPUFREQ_RELATION_H: - if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) && - (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min)) - new_ppcr--; - break; - } - freqs.old = cur; - freqs.new = sa11x0_ppcr_to_freq(new_ppcr); + freqs.new = sa11x0_freq_table[ppcr].frequency; cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); if (freqs.new > cur) sa1100_update_dram_timings(cur, freqs.new); - PPCR = new_ppcr; + PPCR = ppcr; if (freqs.new < cur) sa1100_update_dram_timings(cur, freqs.new); @@ -224,7 +208,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver sa1100_driver __refdata = { .flags = CPUFREQ_STICKY, .verify = cpufreq_generic_frequency_table_verify, - .target = sa1100_target, + .target_index = sa1100_target, .get = sa11x0_getspeed, .init = sa1100_cpu_init, .name = "sa1100", diff --git a/drivers/cpufreq/sa1110-cpufreq.c b/drivers/cpufreq/sa1110-cpufreq.c index bca04c0..55b1818c 100644 --- a/drivers/cpufreq/sa1110-cpufreq.c +++ b/drivers/cpufreq/sa1110-cpufreq.c @@ -229,34 +229,16 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram) /* * Ok, set the CPU frequency. */ -static int sa1110_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr) { struct sdram_params *sdram = &sdram_params; struct cpufreq_freqs freqs; struct sdram_info sd; unsigned long flags; - unsigned int ppcr, unused; - - switch (relation) { - case CPUFREQ_RELATION_L: - ppcr = sa11x0_freq_to_ppcr(target_freq); - if (sa11x0_ppcr_to_freq(ppcr) > policy->max) - ppcr--; - break; - case CPUFREQ_RELATION_H: - ppcr = sa11x0_freq_to_ppcr(target_freq); - if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) && - (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min)) - ppcr--; - break; - default: - return -EINVAL; - } + unsigned int unused; freqs.old = sa11x0_getspeed(0); - freqs.new = sa11x0_ppcr_to_freq(ppcr); + freqs.new = sa11x0_freq_table[ppcr].frequency; sdram_calculate_timing(&sd, freqs.new, sdram); @@ -340,7 +322,7 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver sa1110_driver __refdata = { .flags = CPUFREQ_STICKY, .verify = cpufreq_generic_frequency_table_verify, - .target = sa1110_target, + .target_index = sa1110_target, .get = sa11x0_getspeed, .init = sa1110_cpu_init, .name = "sa1110", diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index 9047ab1..6c86452 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c @@ -53,8 +53,7 @@ static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu) } } -static void sc520_freq_set_cpu_state(struct cpufreq_policy *policy, - unsigned int state) +static int sc520_freq_target(struct cpufreq_policy *policy, unsigned int state) { struct cpufreq_freqs freqs; @@ -76,24 +75,10 @@ static void sc520_freq_set_cpu_state(struct cpufreq_policy *policy, local_irq_enable(); cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); -}; - -static int sc520_freq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int newstate = 0; - - if (cpufreq_frequency_table_target(policy, sc520_freq_table, - target_freq, relation, &newstate)) - return -EINVAL; - - sc520_freq_set_cpu_state(policy, newstate); return 0; } - /* * Module init and exit code */ @@ -117,7 +102,7 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver sc520_freq_driver = { .get = sc520_freq_get_cpu_frequency, .verify = cpufreq_generic_frequency_table_verify, - .target = sc520_freq_target, + .target_index = sc520_freq_target, .init = sc520_freq_cpu_init, .exit = cpufreq_generic_exit, .name = "sc520_freq", diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c index 291688c..3bf5b8f 100644 --- a/drivers/cpufreq/sparc-us2e-cpufreq.c +++ b/drivers/cpufreq/sparc-us2e-cpufreq.c @@ -245,8 +245,7 @@ static unsigned int us2e_freq_get(unsigned int cpu) return clock_tick / estar_to_divisor(estar); } -static void us2e_set_cpu_divider_index(struct cpufreq_policy *policy, - unsigned int index) +static int us2e_freq_target(struct cpufreq_policy *policy, unsigned int index) { unsigned int cpu = policy->cpu; unsigned long new_bits, new_freq; @@ -277,20 +276,6 @@ static void us2e_set_cpu_divider_index(struct cpufreq_policy *policy, cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); set_cpus_allowed_ptr(current, &cpus_allowed); -} - -static int us2e_freq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int new_index = 0; - - if (cpufreq_frequency_table_target(policy, - &us2e_freq_table[policy->cpu].table[0], - target_freq, relation, &new_index)) - return -EINVAL; - - us2e_set_cpu_divider_index(policy, new_index); return 0; } @@ -325,7 +310,7 @@ static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) { if (cpufreq_us2e_driver) { cpufreq_frequency_table_put_attr(policy->cpu); - us2e_set_cpu_divider_index(policy, 0); + us2e_freq_target(policy, 0); } return 0; @@ -358,7 +343,7 @@ static int __init us2e_freq_init(void) driver->init = us2e_freq_cpu_init; driver->verify = cpufreq_generic_frequency_table_verify; - driver->target = us2e_freq_target; + driver->target_index = us2e_freq_target; driver->get = us2e_freq_get; driver->exit = us2e_freq_cpu_exit; strcpy(driver->name, "UltraSPARC-IIe"); diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c index 9b3dbd3..2e54d55 100644 --- a/drivers/cpufreq/sparc-us3-cpufreq.c +++ b/drivers/cpufreq/sparc-us3-cpufreq.c @@ -93,8 +93,7 @@ static unsigned int us3_freq_get(unsigned int cpu) return ret; } -static void us3_set_cpu_divider_index(struct cpufreq_policy *policy, - unsigned int index) +static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index) { unsigned int cpu = policy->cpu; unsigned long new_bits, new_freq, reg; @@ -136,22 +135,6 @@ static void us3_set_cpu_divider_index(struct cpufreq_policy *policy, cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); set_cpus_allowed_ptr(current, &cpus_allowed); -} - -static int us3_freq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int new_index = 0; - - if (cpufreq_frequency_table_target(policy, - &us3_freq_table[policy->cpu].table[0], - target_freq, - relation, - &new_index)) - return -EINVAL; - - us3_set_cpu_divider_index(policy, new_index); return 0; } @@ -182,7 +165,7 @@ static int us3_freq_cpu_exit(struct cpufreq_policy *policy) { if (cpufreq_us3_driver) { cpufreq_frequency_table_put_attr(policy->cpu); - us3_set_cpu_divider_index(policy, 0); + us3_freq_target(policy, 0); } return 0; @@ -219,7 +202,7 @@ static int __init us3_freq_init(void) driver->init = us3_freq_cpu_init; driver->verify = cpufreq_generic_frequency_table_verify; - driver->target = us3_freq_target; + driver->target_index = us3_freq_target; driver->get = us3_freq_get; driver->exit = us3_freq_cpu_exit; strcpy(driver->name, "UltraSPARC-III"); diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index 8841366..11a65be 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -105,20 +105,16 @@ static int spear1340_set_cpu_rate(struct clk *sys_pclk, unsigned long newfreq) } static int spear_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) + unsigned int index) { struct cpufreq_freqs freqs; long newfreq; struct clk *srcclk; - int index, ret, mult = 1; - - if (cpufreq_frequency_table_target(policy, spear_cpufreq.freq_tbl, - target_freq, relation, &index)) - return -EINVAL; + int ret, mult = 1; freqs.old = spear_cpufreq_get(0); - newfreq = spear_cpufreq.freq_tbl[index].frequency * 1000; + if (of_machine_is_compatible("st,spear1340")) { /* * SPEAr1340 is special in the sense that due to the possibility @@ -179,7 +175,7 @@ static struct cpufreq_driver spear_cpufreq_driver = { .name = "cpufreq-spear", .flags = CPUFREQ_STICKY, .verify = cpufreq_generic_frequency_table_verify, - .target = spear_cpufreq_target, + .target_index = spear_cpufreq_target, .get = spear_cpufreq_get, .init = spear_cpufreq_init, .exit = cpufreq_generic_exit, diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index 25e45f8..c51ec8c 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -416,21 +416,17 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) /** * centrino_setpolicy - set a new CPUFreq policy * @policy: new policy - * @target_freq: the target frequency - * @relation: how that frequency relates to achieved frequency - * (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H) + * @index: index of target frequency * * Sets a new CPUFreq policy. */ -static int centrino_target (struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int centrino_target(struct cpufreq_policy *policy, unsigned int index) { - unsigned int newstate = 0; unsigned int msr, oldmsr = 0, h = 0, cpu = policy->cpu; struct cpufreq_freqs freqs; int retval = 0; unsigned int j, first_cpu, tmp; + struct cpufreq_frequency_table *op_points; cpumask_var_t covered_cpus; if (unlikely(!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL))) @@ -441,16 +437,8 @@ static int centrino_target (struct cpufreq_policy *policy, goto out; } - if (unlikely(cpufreq_frequency_table_target(policy, - per_cpu(centrino_model, cpu)->op_points, - target_freq, - relation, - &newstate))) { - retval = -EINVAL; - goto out; - } - first_cpu = 1; + op_points = &per_cpu(centrino_model, cpu)->op_points[index]; for_each_cpu(j, policy->cpus) { int good_cpu; @@ -474,7 +462,7 @@ static int centrino_target (struct cpufreq_policy *policy, break; } - msr = per_cpu(centrino_model, cpu)->op_points[newstate].driver_data; + msr = op_points->driver_data; if (first_cpu) { rdmsr_on_cpu(good_cpu, MSR_IA32_PERF_CTL, &oldmsr, &h); @@ -489,7 +477,8 @@ static int centrino_target (struct cpufreq_policy *policy, freqs.new = extract_clock(msr, cpu, 0); pr_debug("target=%dkHz old=%d new=%d msr=%04x\n", - target_freq, freqs.old, freqs.new, msr); + op_points->frequency, freqs.old, freqs.new, + msr); cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); @@ -540,7 +529,7 @@ static struct cpufreq_driver centrino_driver = { .init = centrino_cpu_init, .exit = centrino_cpu_exit, .verify = cpufreq_generic_frequency_table_verify, - .target = centrino_target, + .target_index = centrino_target, .get = get_cur_freq, .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index 1a8b01b..707721e 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -251,36 +251,24 @@ static unsigned int speedstep_get(unsigned int cpu) /** * speedstep_target - set a new CPUFreq policy * @policy: new policy - * @target_freq: the target frequency - * @relation: how that frequency relates to achieved frequency - * (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H) + * @index: index of target frequency * * Sets a new CPUFreq policy. */ -static int speedstep_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int speedstep_target(struct cpufreq_policy *policy, unsigned int index) { - unsigned int newstate = 0, policy_cpu; + unsigned int policy_cpu; struct cpufreq_freqs freqs; - if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], - target_freq, relation, &newstate)) - return -EINVAL; - policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask); freqs.old = speedstep_get(policy_cpu); - freqs.new = speedstep_freqs[newstate].frequency; + freqs.new = speedstep_freqs[index].frequency; pr_debug("transiting from %u to %u kHz\n", freqs.old, freqs.new); - /* no transition necessary */ - if (freqs.old == freqs.new) - return 0; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - smp_call_function_single(policy_cpu, _speedstep_set_state, &newstate, + smp_call_function_single(policy_cpu, _speedstep_set_state, &index, true); cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); @@ -330,7 +318,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver speedstep_driver = { .name = "speedstep-ich", .verify = cpufreq_generic_frequency_table_verify, - .target = speedstep_target, + .target_index = speedstep_target, .init = speedstep_cpu_init, .exit = cpufreq_generic_exit, .get = speedstep_get, diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index a02b649..19446e4 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -235,29 +235,19 @@ static void speedstep_set_state(unsigned int state) /** * speedstep_target - set a new CPUFreq policy * @policy: new policy - * @target_freq: new freq - * @relation: + * @index: index of new freq * * Sets a new CPUFreq policy/freq. */ -static int speedstep_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) +static int speedstep_target(struct cpufreq_policy *policy, unsigned int index) { - unsigned int newstate = 0; struct cpufreq_freqs freqs; - if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], - target_freq, relation, &newstate)) - return -EINVAL; - freqs.old = speedstep_freqs[speedstep_get_state()].frequency; - freqs.new = speedstep_freqs[newstate].frequency; - - if (freqs.old == freqs.new) - return 0; + freqs.new = speedstep_freqs[index].frequency; cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - speedstep_set_state(newstate); + speedstep_set_state(index); cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); return 0; @@ -327,7 +317,7 @@ static int speedstep_resume(struct cpufreq_policy *policy) static struct cpufreq_driver speedstep_driver = { .name = "speedstep-smi", .verify = cpufreq_generic_frequency_table_verify, - .target = speedstep_target, + .target_index = speedstep_target, .init = speedstep_cpu_init, .exit = cpufreq_generic_exit, .get = speedstep_get, diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra-cpufreq.c index 32483ef..bd7d89c 100644 --- a/drivers/cpufreq/tegra-cpufreq.c +++ b/drivers/cpufreq/tegra-cpufreq.c @@ -150,11 +150,8 @@ static unsigned long tegra_cpu_highest_speed(void) return rate; } -static int tegra_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int tegra_target(struct cpufreq_policy *policy, unsigned int index) { - unsigned int idx; unsigned int freq; int ret = 0; @@ -165,10 +162,7 @@ static int tegra_target(struct cpufreq_policy *policy, goto out; } - cpufreq_frequency_table_target(policy, freq_table, target_freq, - relation, &idx); - - freq = freq_table[idx].frequency; + freq = freq_table[index].frequency; target_cpu_speed[policy->cpu] = freq; @@ -238,7 +232,7 @@ static int tegra_cpu_exit(struct cpufreq_policy *policy) static struct cpufreq_driver tegra_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, - .target = tegra_target, + .target_index = tegra_target, .get = tegra_getspeed, .init = tegra_cpu_init, .exit = tegra_cpu_exit, diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 0aba2a6..e8c77d3 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -187,9 +187,11 @@ struct cpufreq_driver { /* define one out of two */ int (*setpolicy) (struct cpufreq_policy *policy); - int (*target) (struct cpufreq_policy *policy, + int (*target) (struct cpufreq_policy *policy, /* Deprecated */ unsigned int target_freq, unsigned int relation); + int (*target_index) (struct cpufreq_policy *policy, + unsigned int index); /* should be defined, if possible */ unsigned int (*get) (unsigned int cpu); -- cgit v0.10.2 From 9e3410b764b79670a59d6c1ccdcad483b92c058c Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 23 Oct 2013 13:37:35 +0200 Subject: PowerCap: Convert class code to use dev_groups The newly added power capping framework uses the obsolete .dev_attrs field of struct class. However this field will be removed in 3.13, so convert the code to use the .dev_groups field instead. Signed-off-by: Thierry Reding Acked-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c index c22fa4c..21814f9 100644 --- a/drivers/powercap/powercap_sys.c +++ b/drivers/powercap/powercap_sys.c @@ -472,16 +472,18 @@ static ssize_t enabled_store(struct device *dev, return -ENOSYS; } -static struct device_attribute powercap_def_attrs[] = { - __ATTR(enabled, S_IWUSR | S_IRUGO, enabled_show, - enabled_store), - __ATTR_NULL +static DEVICE_ATTR_RW(enabled); + +static struct attribute *powercap_attrs[] = { + &dev_attr_enabled.attr, + NULL, }; +ATTRIBUTE_GROUPS(powercap); static struct class powercap_class = { .name = "powercap", .dev_release = powercap_release, - .dev_attrs = powercap_def_attrs, + .dev_groups = powercap_groups, }; struct powercap_zone *powercap_register_zone( -- cgit v0.10.2 From e37f14a5fb85522f3bbf88ece6134c4e610ed598 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Fri, 18 Oct 2013 15:56:44 +0400 Subject: ACPI / video: Ignore BIOS initial backlight value for HP 250 G1 On HP 250 G1 laptops, BIOS reports minimum backlight on boot and causes backlight to dim completely. This ignores the initial backlight values and set to max brightness. References: https://bugzilla.kernel.org/show_bug.cgi?id=63111 Signed-off-by: Kirill Tkhai Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index d020df5..38c3a28 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -504,6 +504,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion m4 Notebook PC"), }, }, + { + .callback = video_ignore_initial_backlight, + .ident = "HP 250 G1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G1 Notebook PC"), + }, + }, {} }; -- cgit v0.10.2 From 1bdb71af7f1388fd4b305134035008a81f2032b8 Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Tue, 22 Oct 2013 16:53:35 +0200 Subject: ACPI: Add Toshiba NB100 to Vista _OSI blacklist This patch adds Toshiba NB100 to the Vista _OSI blacklist. The _OSI(Windows 2006) method is bugged on the netbook resulting in messed up PCI IRQ Routing information. This was observed on a netbook whose SATA controller mode was set to Compatibility mode. The controller would then issue IRQs to IRQ#16 instead of IRQ#20, where it should have been. No side-effects were found during testing, everything is working as it did before. References: http://marc.info/?t=137862230200001&r=1&w=2 References: http://www.spinics.net/lists/linux-ide/msg46173.html Signed-off-by: Levente Kurusa Reviewed-by: Robert Hancock Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index aa4d874..b7fd1ae 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -273,6 +273,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), }, }, + { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba NB100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "NB100"), + }, + }, /* * The following machines have broken backlight support when reporting -- cgit v0.10.2 From b042453f3892465e8372b95a0f42c0890df03445 Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Tue, 22 Oct 2013 16:53:35 +0200 Subject: ACPI: Add Toshiba NB100 to Vista _OSI blacklist This patch adds Toshiba NB100 to the Vista _OSI blacklist. The _OSI(Windows 2006) method is bugged on the netbook resulting in messed up PCI IRQ Routing information. This was observed on a netbook whose SATA controller mode was set to Compatibility mode. The controller would then issue IRQs to IRQ#16 instead of IRQ#20, where it should have been. No side-effects were found during testing, everything is working as it did before. References: http://marc.info/?t=137862230200001&r=1&w=2 References: http://www.spinics.net/lists/linux-ide/msg46173.html Signed-off-by: Levente Kurusa Reviewed-by: Robert Hancock Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index aa4d874..b7fd1ae 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -273,6 +273,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), }, }, + { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba NB100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "NB100"), + }, + }, /* * The following machines have broken backlight support when reporting -- cgit v0.10.2 From 016c815084d5b89f7c1a24b1a3a0b796512a91bc Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Mon, 21 Oct 2013 09:20:34 -0700 Subject: intel_pstate: Refactor driver to support CPUs with different MSR layouts Non-core processors have a different MSR layout to commumicate P state information. Refactor the driver to use CPU dependent accessors to P state information. Signed-off-by: Dirk Brandewie Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index d576489..6b37c9f 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -78,7 +78,6 @@ struct cpudata { struct timer_list timer; - struct pstate_adjust_policy *pstate_policy; struct pstate_data pstate; struct _pid pid; @@ -100,15 +99,21 @@ struct pstate_adjust_policy { int i_gain_pct; }; -static struct pstate_adjust_policy default_policy = { - .sample_rate_ms = 10, - .deadband = 0, - .setpoint = 97, - .p_gain_pct = 20, - .d_gain_pct = 0, - .i_gain_pct = 0, +struct pstate_funcs { + int (*get_max)(void); + int (*get_min)(void); + int (*get_turbo)(void); + void (*set)(int pstate); }; +struct cpu_defaults { + struct pstate_adjust_policy pid_policy; + struct pstate_funcs funcs; +}; + +static struct pstate_adjust_policy pid_params; +static struct pstate_funcs pstate_funcs; + struct perf_limits { int no_turbo; int max_perf_pct; @@ -186,14 +191,14 @@ static signed int pid_calc(struct _pid *pid, int busy) static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu) { - pid_p_gain_set(&cpu->pid, cpu->pstate_policy->p_gain_pct); - pid_d_gain_set(&cpu->pid, cpu->pstate_policy->d_gain_pct); - pid_i_gain_set(&cpu->pid, cpu->pstate_policy->i_gain_pct); + pid_p_gain_set(&cpu->pid, pid_params.p_gain_pct); + pid_d_gain_set(&cpu->pid, pid_params.d_gain_pct); + pid_i_gain_set(&cpu->pid, pid_params.i_gain_pct); pid_reset(&cpu->pid, - cpu->pstate_policy->setpoint, + pid_params.setpoint, 100, - cpu->pstate_policy->deadband, + pid_params.deadband, 0); } @@ -227,12 +232,12 @@ struct pid_param { }; static struct pid_param pid_files[] = { - {"sample_rate_ms", &default_policy.sample_rate_ms}, - {"d_gain_pct", &default_policy.d_gain_pct}, - {"i_gain_pct", &default_policy.i_gain_pct}, - {"deadband", &default_policy.deadband}, - {"setpoint", &default_policy.setpoint}, - {"p_gain_pct", &default_policy.p_gain_pct}, + {"sample_rate_ms", &pid_params.sample_rate_ms}, + {"d_gain_pct", &pid_params.d_gain_pct}, + {"i_gain_pct", &pid_params.i_gain_pct}, + {"deadband", &pid_params.deadband}, + {"setpoint", &pid_params.setpoint}, + {"p_gain_pct", &pid_params.p_gain_pct}, {NULL, NULL} }; @@ -337,33 +342,60 @@ static void intel_pstate_sysfs_expose_params(void) } /************************** sysfs end ************************/ - -static int intel_pstate_min_pstate(void) +static int core_get_min_pstate(void) { u64 value; rdmsrl(MSR_PLATFORM_INFO, value); return (value >> 40) & 0xFF; } -static int intel_pstate_max_pstate(void) +static int core_get_max_pstate(void) { u64 value; rdmsrl(MSR_PLATFORM_INFO, value); return (value >> 8) & 0xFF; } -static int intel_pstate_turbo_pstate(void) +static int core_get_turbo_pstate(void) { u64 value; int nont, ret; rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value); - nont = intel_pstate_max_pstate(); + nont = core_get_max_pstate(); ret = ((value) & 255); if (ret <= nont) ret = nont; return ret; } +static void core_set_pstate(int pstate) +{ + u64 val; + + val = pstate << 8; + if (limits.no_turbo) + val |= (u64)1 << 32; + + wrmsrl(MSR_IA32_PERF_CTL, val); +} + +static struct cpu_defaults core_params = { + .pid_policy = { + .sample_rate_ms = 10, + .deadband = 0, + .setpoint = 97, + .p_gain_pct = 20, + .d_gain_pct = 0, + .i_gain_pct = 0, + }, + .funcs = { + .get_max = core_get_max_pstate, + .get_min = core_get_min_pstate, + .get_turbo = core_get_turbo_pstate, + .set = core_set_pstate, + }, +}; + static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) { int max_perf = cpu->pstate.turbo_pstate; @@ -383,7 +415,6 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) { int max_perf, min_perf; - u64 val; intel_pstate_get_min_max(cpu, &min_perf, &max_perf); @@ -395,11 +426,8 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) trace_cpu_frequency(pstate * 100000, cpu->cpu); cpu->pstate.current_pstate = pstate; - val = pstate << 8; - if (limits.no_turbo) - val |= (u64)1 << 32; - wrmsrl(MSR_IA32_PERF_CTL, val); + pstate_funcs.set(pstate); } static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) @@ -421,9 +449,9 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) { sprintf(cpu->name, "Intel 2nd generation core"); - cpu->pstate.min_pstate = intel_pstate_min_pstate(); - cpu->pstate.max_pstate = intel_pstate_max_pstate(); - cpu->pstate.turbo_pstate = intel_pstate_turbo_pstate(); + cpu->pstate.min_pstate = pstate_funcs.get_min(); + cpu->pstate.max_pstate = pstate_funcs.get_max(); + cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); /* * goto max pstate so we don't slow up boot if we are built-in if we are @@ -464,7 +492,7 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu) { int sample_time, delay; - sample_time = cpu->pstate_policy->sample_rate_ms; + sample_time = pid_params.sample_rate_ms; delay = msecs_to_jiffies(sample_time); mod_timer_pinned(&cpu->timer, jiffies + delay); } @@ -523,14 +551,14 @@ static void intel_pstate_timer_func(unsigned long __data) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&policy } static const struct x86_cpu_id intel_pstate_cpu_ids[] = { - ICPU(0x2a, default_policy), - ICPU(0x2d, default_policy), - ICPU(0x3a, default_policy), - ICPU(0x3c, default_policy), - ICPU(0x3e, default_policy), - ICPU(0x3f, default_policy), - ICPU(0x45, default_policy), - ICPU(0x46, default_policy), + ICPU(0x2a, core_params), + ICPU(0x2d, core_params), + ICPU(0x3a, core_params), + ICPU(0x3c, core_params), + ICPU(0x3e, core_params), + ICPU(0x3f, core_params), + ICPU(0x45, core_params), + ICPU(0x46, core_params), {} }; MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); @@ -554,8 +582,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum) intel_pstate_get_cpu_pstates(cpu); cpu->cpu = cpunum; - cpu->pstate_policy = - (struct pstate_adjust_policy *)id->driver_data; + init_timer_deferrable(&cpu->timer); cpu->timer.function = intel_pstate_timer_func; cpu->timer.data = @@ -683,9 +710,9 @@ static int intel_pstate_msrs_not_valid(void) rdmsrl(MSR_IA32_APERF, aperf); rdmsrl(MSR_IA32_MPERF, mperf); - if (!intel_pstate_min_pstate() || - !intel_pstate_max_pstate() || - !intel_pstate_turbo_pstate()) + if (!pstate_funcs.get_max() || + !pstate_funcs.get_min() || + !pstate_funcs.get_turbo()) return -ENODEV; rdmsrl(MSR_IA32_APERF, tmp); @@ -698,10 +725,30 @@ static int intel_pstate_msrs_not_valid(void) return 0; } + +void copy_pid_params(struct pstate_adjust_policy *policy) +{ + pid_params.sample_rate_ms = policy->sample_rate_ms; + pid_params.p_gain_pct = policy->p_gain_pct; + pid_params.i_gain_pct = policy->i_gain_pct; + pid_params.d_gain_pct = policy->d_gain_pct; + pid_params.deadband = policy->deadband; + pid_params.setpoint = policy->setpoint; +} + +void copy_cpu_funcs(struct pstate_funcs *funcs) +{ + pstate_funcs.get_max = funcs->get_max; + pstate_funcs.get_min = funcs->get_min; + pstate_funcs.get_turbo = funcs->get_turbo; + pstate_funcs.set = funcs->set; +} + static int __init intel_pstate_init(void) { int cpu, rc = 0; const struct x86_cpu_id *id; + struct cpu_defaults *cpu_info; if (no_load) return -ENODEV; @@ -710,6 +757,11 @@ static int __init intel_pstate_init(void) if (!id) return -ENODEV; + cpu_info = (struct cpu_defaults *)id->driver_data; + + copy_pid_params(&cpu_info->pid_policy); + copy_cpu_funcs(&cpu_info->funcs); + if (intel_pstate_msrs_not_valid()) return -ENODEV; -- cgit v0.10.2 From 19e77c28dbf1972305da0dfeb92a62f83df3a91d Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Mon, 21 Oct 2013 09:20:35 -0700 Subject: intel_pstate: Add Baytrail support Add support for the Baytrail processor. Signed-off-by: Dirk Brandewie Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 6b37c9f..27c2753 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -33,6 +33,8 @@ #define SAMPLE_COUNT 3 +#define BYT_RATIOS 0x66a + #define FRAC_BITS 8 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) #define fp_toint(X) ((X) >> FRAC_BITS) @@ -342,6 +344,20 @@ static void intel_pstate_sysfs_expose_params(void) } /************************** sysfs end ************************/ +static int byt_get_min_pstate(void) +{ + u64 value; + rdmsrl(BYT_RATIOS, value); + return value & 0xFF; +} + +static int byt_get_max_pstate(void) +{ + u64 value; + rdmsrl(BYT_RATIOS, value); + return (value >> 16) & 0xFF; +} + static int core_get_min_pstate(void) { u64 value; @@ -396,6 +412,24 @@ static struct cpu_defaults core_params = { }, }; +static struct cpu_defaults byt_params = { + .pid_policy = { + .sample_rate_ms = 10, + .deadband = 0, + .setpoint = 97, + .p_gain_pct = 14, + .d_gain_pct = 0, + .i_gain_pct = 4, + }, + .funcs = { + .get_max = byt_get_max_pstate, + .get_min = byt_get_min_pstate, + .get_turbo = byt_get_max_pstate, + .set = core_set_pstate, + }, +}; + + static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) { int max_perf = cpu->pstate.turbo_pstate; @@ -553,6 +587,7 @@ static void intel_pstate_timer_func(unsigned long __data) static const struct x86_cpu_id intel_pstate_cpu_ids[] = { ICPU(0x2a, core_params), ICPU(0x2d, core_params), + ICPU(0x37, byt_params), ICPU(0x3a, core_params), ICPU(0x3c, core_params), ICPU(0x3e, core_params), -- cgit v0.10.2 From ad7722dab7292dbc1c4586d701ac226b68122d39 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Fri, 18 Oct 2013 19:10:15 +0530 Subject: cpufreq: create per policy rwsem instead of per CPU cpu_policy_rwsem We have per-CPU cpu_policy_rwsem for cpufreq core, but we never use all of them. We always use rwsem of policy->cpu and so we can actually make this rwsem per policy instead. This patch does this change. With this change other tricky situations are also avoided now, like which lock to take while we are changing policy->cpu, etc. Suggested-by: Srivatsa S. Bhat Signed-off-by: Viresh Kumar Reviewed-by: Srivatsa S. Bhat Tested-by: Andrew Lunn Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 87ed83a..6c9cbb9 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -53,47 +53,6 @@ static inline bool has_target(void) } /* - * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure - * all cpufreq/hotplug/workqueue/etc related lock issues. - * - * The rules for this semaphore: - * - Any routine that wants to read from the policy structure will - * do a down_read on this semaphore. - * - Any routine that will write to the policy structure and/or may take away - * the policy altogether (eg. CPU hotplug), will hold this lock in write - * mode before doing so. - * - * Additional rules: - * - Governor routines that can be called in cpufreq hotplug path should not - * take this sem as top level hotplug notifier handler takes this. - * - Lock should not be held across - * __cpufreq_governor(data, CPUFREQ_GOV_STOP); - */ -static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem); - -#define lock_policy_rwsem(mode, cpu) \ -static void lock_policy_rwsem_##mode(int cpu) \ -{ \ - struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); \ - BUG_ON(!policy); \ - down_##mode(&per_cpu(cpu_policy_rwsem, policy->cpu)); \ -} - -lock_policy_rwsem(read, cpu); -lock_policy_rwsem(write, cpu); - -#define unlock_policy_rwsem(mode, cpu) \ -static void unlock_policy_rwsem_##mode(int cpu) \ -{ \ - struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); \ - BUG_ON(!policy); \ - up_##mode(&per_cpu(cpu_policy_rwsem, policy->cpu)); \ -} - -unlock_policy_rwsem(read, cpu); -unlock_policy_rwsem(write, cpu); - -/* * rwsem to guarantee that cpufreq driver module doesn't unload during critical * sections */ @@ -688,14 +647,14 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) if (!down_read_trylock(&cpufreq_rwsem)) return -EINVAL; - lock_policy_rwsem_read(policy->cpu); + down_read(&policy->rwsem); if (fattr->show) ret = fattr->show(policy, buf); else ret = -EIO; - unlock_policy_rwsem_read(policy->cpu); + up_read(&policy->rwsem); up_read(&cpufreq_rwsem); return ret; @@ -716,14 +675,14 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, if (!down_read_trylock(&cpufreq_rwsem)) goto unlock; - lock_policy_rwsem_write(policy->cpu); + down_write(&policy->rwsem); if (fattr->store) ret = fattr->store(policy, buf, count); else ret = -EIO; - unlock_policy_rwsem_write(policy->cpu); + up_write(&policy->rwsem); up_read(&cpufreq_rwsem); unlock: @@ -900,7 +859,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, } } - lock_policy_rwsem_write(policy->cpu); + down_write(&policy->rwsem); write_lock_irqsave(&cpufreq_driver_lock, flags); @@ -908,7 +867,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, per_cpu(cpufreq_cpu_data, cpu) = policy; write_unlock_irqrestore(&cpufreq_driver_lock, flags); - unlock_policy_rwsem_write(policy->cpu); + up_write(&policy->rwsem); if (has_target()) { if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) || @@ -955,6 +914,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(void) goto err_free_cpumask; INIT_LIST_HEAD(&policy->policy_list); + init_rwsem(&policy->rwsem); + return policy; err_free_cpumask: @@ -977,19 +938,12 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) if (WARN_ON(cpu == policy->cpu)) return; - /* - * Take direct locks as lock_policy_rwsem_write wouldn't work here. - * Also lock for last cpu is enough here as contention will happen only - * after policy->cpu is changed and after it is changed, other threads - * will try to acquire lock for new cpu. And policy is already updated - * by then. - */ - down_write(&per_cpu(cpu_policy_rwsem, policy->cpu)); + down_write(&policy->rwsem); policy->last_cpu = policy->cpu; policy->cpu = cpu; - up_write(&per_cpu(cpu_policy_rwsem, policy->last_cpu)); + up_write(&policy->rwsem); cpufreq_frequency_table_update_policy_cpu(policy); blocking_notifier_call_chain(&cpufreq_policy_notifier_list, @@ -1181,9 +1135,9 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, if (ret) { pr_err("%s: Failed to move kobj: %d", __func__, ret); - lock_policy_rwsem_write(old_cpu); + down_write(&policy->rwsem); cpumask_set_cpu(old_cpu, policy->cpus); - unlock_policy_rwsem_write(old_cpu); + up_write(&policy->rwsem); ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj, "cpufreq"); @@ -1234,9 +1188,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, policy->governor->name, CPUFREQ_NAME_LEN); #endif - lock_policy_rwsem_read(cpu); + down_read(&policy->rwsem); cpus = cpumask_weight(policy->cpus); - unlock_policy_rwsem_read(cpu); + up_read(&policy->rwsem); if (cpu != policy->cpu) { if (!frozen) @@ -1276,12 +1230,12 @@ static int __cpufreq_remove_dev_finish(struct device *dev, return -EINVAL; } - lock_policy_rwsem_write(cpu); + down_write(&policy->rwsem); cpus = cpumask_weight(policy->cpus); if (cpus > 1) cpumask_clear_cpu(cpu, policy->cpus); - unlock_policy_rwsem_write(cpu); + up_write(&policy->rwsem); /* If cpu is last user of policy, free policy */ if (cpus == 1) { @@ -1296,10 +1250,10 @@ static int __cpufreq_remove_dev_finish(struct device *dev, } if (!frozen) { - lock_policy_rwsem_read(cpu); + down_read(&policy->rwsem); kobj = &policy->kobj; cmp = &policy->kobj_unregister; - unlock_policy_rwsem_read(cpu); + up_read(&policy->rwsem); kobject_put(kobj); /* @@ -1479,19 +1433,22 @@ static unsigned int __cpufreq_get(unsigned int cpu) */ unsigned int cpufreq_get(unsigned int cpu) { + struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); unsigned int ret_freq = 0; if (cpufreq_disabled() || !cpufreq_driver) return -ENOENT; + BUG_ON(!policy); + if (!down_read_trylock(&cpufreq_rwsem)) return 0; - lock_policy_rwsem_read(cpu); + down_read(&policy->rwsem); ret_freq = __cpufreq_get(cpu); - unlock_policy_rwsem_read(cpu); + up_read(&policy->rwsem); up_read(&cpufreq_rwsem); return ret_freq; @@ -1744,11 +1701,11 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, { int ret = -EINVAL; - lock_policy_rwsem_write(policy->cpu); + down_write(&policy->rwsem); ret = __cpufreq_driver_target(policy, target_freq, relation); - unlock_policy_rwsem_write(policy->cpu); + up_write(&policy->rwsem); return ret; } @@ -1979,10 +1936,10 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, /* end old governor */ if (policy->governor) { __cpufreq_governor(policy, CPUFREQ_GOV_STOP); - unlock_policy_rwsem_write(new_policy->cpu); + up_write(&policy->rwsem); __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); - lock_policy_rwsem_write(new_policy->cpu); + down_write(&policy->rwsem); } /* start new governor */ @@ -1991,10 +1948,10 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) { failed = 0; } else { - unlock_policy_rwsem_write(new_policy->cpu); + up_write(&policy->rwsem); __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); - lock_policy_rwsem_write(new_policy->cpu); + down_write(&policy->rwsem); } } @@ -2040,7 +1997,7 @@ int cpufreq_update_policy(unsigned int cpu) goto no_policy; } - lock_policy_rwsem_write(cpu); + down_write(&policy->rwsem); pr_debug("updating policy for CPU %u\n", cpu); memcpy(&new_policy, policy, sizeof(*policy)); @@ -2067,7 +2024,7 @@ int cpufreq_update_policy(unsigned int cpu) ret = cpufreq_set_policy(policy, &new_policy); - unlock_policy_rwsem_write(cpu); + up_write(&policy->rwsem); cpufreq_cpu_put(policy); no_policy: @@ -2225,14 +2182,9 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); static int __init cpufreq_core_init(void) { - int cpu; - if (cpufreq_disabled()) return -ENODEV; - for_each_possible_cpu(cpu) - init_rwsem(&per_cpu(cpu_policy_rwsem, cpu)); - cpufreq_global_kobject = kobject_create(); BUG_ON(!cpufreq_global_kobject); register_syscore_ops(&cpufreq_syscore_ops); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index e8c77d3..93a8c34 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -85,6 +85,20 @@ struct cpufreq_policy { struct list_head policy_list; struct kobject kobj; struct completion kobj_unregister; + + /* + * The rules for this semaphore: + * - Any routine that wants to read from the policy structure will + * do a down_read on this semaphore. + * - Any routine that will write to the policy structure and/or may take away + * the policy altogether (eg. CPU hotplug), will hold this lock in write + * mode before doing so. + * + * Additional rules: + * - Lock should not be held across + * __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); + */ + struct rw_semaphore rwsem; }; /* Only for ACPI */ -- cgit v0.10.2 From 8ab8831a503e8996edd727d98ec5be62b8d799d9 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 5 Jun 2013 11:42:59 +0530 Subject: PM / devfreq: Fix incorrect usage of IS_ERR_OR_NULL in exynos5_bus.c platform_device_register_simple does not return NULL. Hence NULL check is not required. Signed-off-by: Sachin Kamat Acked-by: MyungJoo Ham Signed-off-by: MyungJoo Ham diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c index 574b16b..cd1e630 100644 --- a/drivers/devfreq/exynos/exynos5_bus.c +++ b/drivers/devfreq/exynos/exynos5_bus.c @@ -479,7 +479,7 @@ static int __init exynos5_busfreq_int_init(void) exynos5_devfreq_pdev = platform_device_register_simple("exynos5-bus-int", -1, NULL, 0); - if (IS_ERR_OR_NULL(exynos5_devfreq_pdev)) { + if (IS_ERR(exynos5_devfreq_pdev)) { ret = PTR_ERR(exynos5_devfreq_pdev); goto out1; } -- cgit v0.10.2 From 81c12a0a79575a22b64f050ea2e626f12d124841 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 5 Jun 2013 11:43:00 +0530 Subject: PM / devfreq: Remove redundant platform_set_drvdata() in exynos5_bus.c Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Acked-by: MyungJoo Ham Signed-off-by: MyungJoo Ham diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c index cd1e630..9a82419 100644 --- a/drivers/devfreq/exynos/exynos5_bus.c +++ b/drivers/devfreq/exynos/exynos5_bus.c @@ -419,7 +419,6 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev) err_devfreq_add: devfreq_remove_device(data->devfreq); - platform_set_drvdata(pdev, NULL); err_opp_add: clk_put(data->int_clk); err_clock: @@ -437,7 +436,6 @@ static int exynos5_busfreq_int_remove(struct platform_device *pdev) devfreq_remove_device(data->devfreq); regulator_put(data->vdd_int); clk_put(data->int_clk); - platform_set_drvdata(pdev, NULL); return 0; } -- cgit v0.10.2 From 02844f747e72186f7d3f34d6f78de90cb8eb2139 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 5 Jun 2013 11:43:01 +0530 Subject: PM / devfreq: Use devm_* APIs in exynos5_bus.c devm_* APIs are device managed and make clean up and exit codes simpler. Signed-off-by: Sachin Kamat Signed-off-by: MyungJoo Ham diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c index 9a82419..102d1f0 100644 --- a/drivers/devfreq/exynos/exynos5_bus.c +++ b/drivers/devfreq/exynos/exynos5_bus.c @@ -351,20 +351,18 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev) err = exynos5250_init_int_tables(data); if (err) - goto err_regulator; + return err; - data->vdd_int = regulator_get(dev, "vdd_int"); + data->vdd_int = devm_regulator_get(dev, "vdd_int"); if (IS_ERR(data->vdd_int)) { dev_err(dev, "Cannot get the regulator \"vdd_int\"\n"); - err = PTR_ERR(data->vdd_int); - goto err_regulator; + return PTR_ERR(data->vdd_int); } - data->int_clk = clk_get(dev, "int_clk"); + data->int_clk = devm_clk_get(dev, "int_clk"); if (IS_ERR(data->int_clk)) { dev_err(dev, "Cannot get clock \"int_clk\"\n"); - err = PTR_ERR(data->int_clk); - goto err_clock; + return PTR_ERR(data->int_clk); } rcu_read_lock(); @@ -374,8 +372,7 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev) rcu_read_unlock(); dev_err(dev, "Invalid initial frequency %lu kHz.\n", exynos5_devfreq_int_profile.initial_freq); - err = PTR_ERR(opp); - goto err_opp_add; + return PTR_ERR(opp); } initial_freq = opp_get_freq(opp); initial_volt = opp_get_voltage(opp); @@ -385,12 +382,12 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev) err = clk_set_rate(data->int_clk, initial_freq * 1000); if (err) { dev_err(dev, "Failed to set initial frequency\n"); - goto err_opp_add; + return err; } err = exynos5_int_setvolt(data, initial_volt); if (err) - goto err_opp_add; + return err; platform_set_drvdata(pdev, data); @@ -419,11 +416,6 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev) err_devfreq_add: devfreq_remove_device(data->devfreq); -err_opp_add: - clk_put(data->int_clk); -err_clock: - regulator_put(data->vdd_int); -err_regulator: return err; } @@ -434,8 +426,6 @@ static int exynos5_busfreq_int_remove(struct platform_device *pdev) pm_qos_remove_request(&data->int_req); unregister_pm_notifier(&data->pm_notifier); devfreq_remove_device(data->devfreq); - regulator_put(data->vdd_int); - clk_put(data->int_clk); return 0; } -- cgit v0.10.2 From 9671dc7935722a911262cade5c594315540628f2 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 7 Jun 2013 14:25:49 +0530 Subject: PM / devfreq: Remove duplicate header file inclusion in exynos5_bus.c linux/opp.h was included twice. Signed-off-by: Sachin Kamat Signed-off-by: MyungJoo Ham diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c index 102d1f0..04c164e 100644 --- a/drivers/devfreq/exynos/exynos5_bus.c +++ b/drivers/devfreq/exynos/exynos5_bus.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include -- cgit v0.10.2 From ea7f4548c93aacbac5fe3e1b4eb273d3df5f16e3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 15 Aug 2013 10:55:10 +0300 Subject: PM / devfreq: create_freezable_workqueue() doesn't return an ERR_PTR The create_freezable_workqueue() function returns a NULL on error and not an ERR_PTR. Signed-off-by: Dan Carpenter Signed-off-by: MyungJoo Ham diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index c99c00d..22e5d2f 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -993,10 +993,10 @@ static int __init devfreq_init(void) } devfreq_wq = create_freezable_workqueue("devfreq_wq"); - if (IS_ERR(devfreq_wq)) { + if (!devfreq_wq) { class_destroy(devfreq_class); pr_err("%s: couldn't create workqueue\n", __FILE__); - return PTR_ERR(devfreq_wq); + return -ENOMEM; } devfreq_class->dev_groups = devfreq_groups; -- cgit v0.10.2 From 34411a69a4925dd6de8e1069956f59d758da3ce9 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 30 Oct 2013 00:00:30 +0100 Subject: ACPI / processor: Do not request ACPI cpufreq module directly Function acpi_processor_load_module() used by the ACPI processor driver can only really work if the acpi-cpufreq module is available when acpi_processor_start() is executed which usually is not the case for systems loading the processor driver module from an initramfs. Moreover, that used to be a hackish workaround for module autoloading issues, but udev loads acpi-cpufreq just fine nowadays, so that function isn't really necessary any more. For this reason, drop acpi_processor_load_module() entirely. Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 40fc773..146ab7e 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -171,7 +171,6 @@ static int __acpi_processor_start(struct acpi_device *device) #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); - acpi_processor_load_module(pr); #endif acpi_processor_get_throttling_info(pr); diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 51d7948..60a7c28 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -235,28 +235,6 @@ void acpi_processor_ppc_exit(void) acpi_processor_ppc_status &= ~PPC_REGISTERED; } -/* - * Do a quick check if the systems looks like it should use ACPI - * cpufreq. We look at a _PCT method being available, but don't - * do a whole lot of sanity checks. - */ -void acpi_processor_load_module(struct acpi_processor *pr) -{ - static int requested; - acpi_status status = 0; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - - if (!arch_has_acpi_pdc() || requested) - return; - status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer); - if (!ACPI_FAILURE(status)) { - printk(KERN_INFO PREFIX "Requesting acpi_cpufreq\n"); - request_module_nowait("acpi_cpufreq"); - requested = 1; - } - kfree(buffer.pointer); -} - static int acpi_processor_get_performance_control(struct acpi_processor *pr) { int result = 0; diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 7816e45..6eb1d3c 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -225,7 +225,6 @@ struct acpi_processor_errata { } piix4; }; -extern void acpi_processor_load_module(struct acpi_processor *pr); extern int acpi_processor_preregister_performance(struct acpi_processor_performance __percpu *performance); -- cgit v0.10.2 From e7e92ec93f218085e37ded8338f717ffd49eed1d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 29 Oct 2013 10:34:19 +0000 Subject: ACPI: Fix spelling mistake in error messages Fix spelling mistake "expecing" --> "expecting" Signed-off-by: Colin Ian King Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index fc2cd32..6d408bf 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -121,7 +121,7 @@ acpi_extract_package(union acpi_object *package, break; default: printk(KERN_WARNING PREFIX "Invalid package element" - " [%d]: got number, expecing" + " [%d]: got number, expecting" " [%c]\n", i, format_string[i]); return AE_BAD_DATA; @@ -148,7 +148,7 @@ acpi_extract_package(union acpi_object *package, default: printk(KERN_WARNING PREFIX "Invalid package element" " [%d] got string/buffer," - " expecing [%c]\n", + " expecting [%c]\n", i, format_string[i]); return AE_BAD_DATA; break; -- cgit v0.10.2 From f7cd2d835e0f17cde2e5cead92be0099d7e92a7c Mon Sep 17 00:00:00 2001 From: Sudeep KarkadaNagesha Date: Tue, 29 Oct 2013 12:18:37 +0000 Subject: ARM: vexpress/TC2: add support for CPU DVFS SPC(Serial Power Controller) on TC2 also controls the CPU performance operating points which is essential to provide CPU DVFS. The M3 microcontroller provides two sets of eight performance values, one set for each cluster (CA15 or CA7). Each of this value contains the frequency(kHz) and voltage(mV) at that performance level. It expects these performance level to be passed through the SPC PERF_LVL registers. This patch adds support to populate these performance levels from M3, build the mapping to CPU OPPs at the boot and then use it to get and set the CPU performance level runtime. Signed-off-by: Sudeep KarkadaNagesha Acked-by: Nicolas Pitre Acked-by: Pawel Moll Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig index 3657954..c77170c 100644 --- a/arch/arm/mach-vexpress/Kconfig +++ b/arch/arm/mach-vexpress/Kconfig @@ -66,10 +66,22 @@ config ARCH_VEXPRESS_DCSCB This is needed to provide CPU and cluster power management on RTSM implementing big.LITTLE. +config ARCH_VEXPRESS_SPC + bool "Versatile Express Serial Power Controller (SPC)" + select ARCH_HAS_CPUFREQ + select ARCH_HAS_OPP + select PM_OPP + help + The TC2 (A15x2 A7x3) versatile express core tile integrates a logic + block called Serial Power Controller (SPC) that provides the interface + between the dual cluster test-chip and the M3 microcontroller that + carries out power management. + config ARCH_VEXPRESS_TC2_PM bool "Versatile Express TC2 power management" depends on MCPM select ARM_CCI + select ARCH_VEXPRESS_SPC help Support for CPU and cluster power management on Versatile Express with a TC2 (A15x2 A7x3) big.LITTLE core tile. diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index 505e64a..0997e0b 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile @@ -8,7 +8,8 @@ obj-y := v2m.o obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o CFLAGS_dcscb.o += -march=armv7-a -obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o spc.o +obj-$(CONFIG_ARCH_VEXPRESS_SPC) += spc.o +obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o CFLAGS_tc2_pm.o += -march=armv7-a obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c index eefb029..de0ca36 100644 --- a/arch/arm/mach-vexpress/spc.c +++ b/arch/arm/mach-vexpress/spc.c @@ -17,14 +17,27 @@ * GNU General Public License for more details. */ +#include #include +#include #include +#include #include +#include #include #define SPCLOG "vexpress-spc: " +#define PERF_LVL_A15 0x00 +#define PERF_REQ_A15 0x04 +#define PERF_LVL_A7 0x08 +#define PERF_REQ_A7 0x0c +#define COMMS 0x10 +#define COMMS_REQ 0x14 +#define PWC_STATUS 0x18 +#define PWC_FLAG 0x1c + /* SPC wake-up IRQs status and mask */ #define WAKE_INT_MASK 0x24 #define WAKE_INT_RAW 0x28 @@ -36,12 +49,45 @@ #define A15_BX_ADDR0 0x68 #define A7_BX_ADDR0 0x78 +/* SPC system config interface registers */ +#define SYSCFG_WDATA 0x70 +#define SYSCFG_RDATA 0x74 + +/* A15/A7 OPP virtual register base */ +#define A15_PERFVAL_BASE 0xC10 +#define A7_PERFVAL_BASE 0xC30 + +/* Config interface control bits */ +#define SYSCFG_START (1 << 31) +#define SYSCFG_SCC (6 << 20) +#define SYSCFG_STAT (14 << 20) + /* wake-up interrupt masks */ #define GBL_WAKEUP_INT_MSK (0x3 << 10) /* TC2 static dual-cluster configuration */ #define MAX_CLUSTERS 2 +/* + * Even though the SPC takes max 3-5 ms to complete any OPP/COMMS + * operation, the operation could start just before jiffie is about + * to be incremented. So setting timeout value of 20ms = 2jiffies@100Hz + */ +#define TIMEOUT_US 20000 + +#define MAX_OPPS 8 +#define CA15_DVFS 0 +#define CA7_DVFS 1 +#define SPC_SYS_CFG 2 +#define STAT_COMPLETE(type) ((1 << 0) << (type << 2)) +#define STAT_ERR(type) ((1 << 1) << (type << 2)) +#define RESPONSE_MASK(type) (STAT_COMPLETE(type) | STAT_ERR(type)) + +struct ve_spc_opp { + unsigned long freq; + unsigned long u_volt; +}; + struct ve_spc_drvdata { void __iomem *baseaddr; /* @@ -49,6 +95,12 @@ struct ve_spc_drvdata { * It corresponds to A15 processors MPIDR[15:8] bitfield */ u32 a15_clusid; + uint32_t cur_rsp_mask; + uint32_t cur_rsp_stat; + struct semaphore sem; + struct completion done; + struct ve_spc_opp *opps[MAX_CLUSTERS]; + int num_opps[MAX_CLUSTERS]; }; static struct ve_spc_drvdata *info; @@ -157,8 +209,197 @@ void ve_spc_powerdown(u32 cluster, bool enable) writel_relaxed(enable, info->baseaddr + pwdrn_reg); } -int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid) +static int ve_spc_get_performance(int cluster, u32 *freq) +{ + struct ve_spc_opp *opps = info->opps[cluster]; + u32 perf_cfg_reg = 0; + u32 perf; + + perf_cfg_reg = cluster_is_a15(cluster) ? PERF_LVL_A15 : PERF_LVL_A7; + + perf = readl_relaxed(info->baseaddr + perf_cfg_reg); + if (perf >= info->num_opps[cluster]) + return -EINVAL; + + opps += perf; + *freq = opps->freq; + + return 0; +} + +/* find closest match to given frequency in OPP table */ +static int ve_spc_round_performance(int cluster, u32 freq) +{ + int idx, max_opp = info->num_opps[cluster]; + struct ve_spc_opp *opps = info->opps[cluster]; + u32 fmin = 0, fmax = ~0, ftmp; + + freq /= 1000; /* OPP entries in kHz */ + for (idx = 0; idx < max_opp; idx++, opps++) { + ftmp = opps->freq; + if (ftmp >= freq) { + if (ftmp <= fmax) + fmax = ftmp; + } else { + if (ftmp >= fmin) + fmin = ftmp; + } + } + if (fmax != ~0) + return fmax * 1000; + else + return fmin * 1000; +} + +static int ve_spc_find_performance_index(int cluster, u32 freq) +{ + int idx, max_opp = info->num_opps[cluster]; + struct ve_spc_opp *opps = info->opps[cluster]; + + for (idx = 0; idx < max_opp; idx++, opps++) + if (opps->freq == freq) + break; + return (idx == max_opp) ? -EINVAL : idx; +} + +static int ve_spc_waitforcompletion(int req_type) +{ + int ret = wait_for_completion_interruptible_timeout( + &info->done, usecs_to_jiffies(TIMEOUT_US)); + if (ret == 0) + ret = -ETIMEDOUT; + else if (ret > 0) + ret = info->cur_rsp_stat & STAT_COMPLETE(req_type) ? 0 : -EIO; + return ret; +} + +static int ve_spc_set_performance(int cluster, u32 freq) +{ + u32 perf_cfg_reg, perf_stat_reg; + int ret, perf, req_type; + + if (cluster_is_a15(cluster)) { + req_type = CA15_DVFS; + perf_cfg_reg = PERF_LVL_A15; + perf_stat_reg = PERF_REQ_A15; + } else { + req_type = CA7_DVFS; + perf_cfg_reg = PERF_LVL_A7; + perf_stat_reg = PERF_REQ_A7; + } + + perf = ve_spc_find_performance_index(cluster, freq); + + if (perf < 0) + return perf; + + if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US))) + return -ETIME; + + init_completion(&info->done); + info->cur_rsp_mask = RESPONSE_MASK(req_type); + + writel(perf, info->baseaddr + perf_cfg_reg); + ret = ve_spc_waitforcompletion(req_type); + + info->cur_rsp_mask = 0; + up(&info->sem); + + return ret; +} + +static int ve_spc_read_sys_cfg(int func, int offset, uint32_t *data) +{ + int ret; + + if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US))) + return -ETIME; + + init_completion(&info->done); + info->cur_rsp_mask = RESPONSE_MASK(SPC_SYS_CFG); + + /* Set the control value */ + writel(SYSCFG_START | func | offset >> 2, info->baseaddr + COMMS); + ret = ve_spc_waitforcompletion(SPC_SYS_CFG); + + if (ret == 0) + *data = readl(info->baseaddr + SYSCFG_RDATA); + + info->cur_rsp_mask = 0; + up(&info->sem); + + return ret; +} + +static irqreturn_t ve_spc_irq_handler(int irq, void *data) +{ + struct ve_spc_drvdata *drv_data = data; + uint32_t status = readl_relaxed(drv_data->baseaddr + PWC_STATUS); + + if (info->cur_rsp_mask & status) { + info->cur_rsp_stat = status; + complete(&drv_data->done); + } + + return IRQ_HANDLED; +} + +/* + * +--------------------------+ + * | 31 20 | 19 0 | + * +--------------------------+ + * | u_volt | freq(kHz) | + * +--------------------------+ + */ +#define MULT_FACTOR 20 +#define VOLT_SHIFT 20 +#define FREQ_MASK (0xFFFFF) +static int ve_spc_populate_opps(uint32_t cluster) +{ + uint32_t data = 0, off, ret, idx; + struct ve_spc_opp *opps; + + opps = kzalloc(sizeof(*opps) * MAX_OPPS, GFP_KERNEL); + if (!opps) + return -ENOMEM; + + info->opps[cluster] = opps; + + off = cluster_is_a15(cluster) ? A15_PERFVAL_BASE : A7_PERFVAL_BASE; + for (idx = 0; idx < MAX_OPPS; idx++, off += 4, opps++) { + ret = ve_spc_read_sys_cfg(SYSCFG_SCC, off, &data); + if (!ret) { + opps->freq = (data & FREQ_MASK) * MULT_FACTOR; + opps->u_volt = data >> VOLT_SHIFT; + } else { + break; + } + } + info->num_opps[cluster] = idx; + + return ret; +} + +static int ve_init_opp_table(struct device *cpu_dev) +{ + int cluster = topology_physical_package_id(cpu_dev->id); + int idx, ret = 0, max_opp = info->num_opps[cluster]; + struct ve_spc_opp *opps = info->opps[cluster]; + + for (idx = 0; idx < max_opp; idx++, opps++) { + ret = dev_pm_opp_add(cpu_dev, opps->freq * 1000, opps->u_volt); + if (ret) { + dev_warn(cpu_dev, "failed to add opp %lu %lu\n", + opps->freq, opps->u_volt); + return ret; + } + } + return ret; +} + +int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid, int irq) { + int ret; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { pr_err(SPCLOG "unable to allocate mem\n"); @@ -168,6 +409,25 @@ int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid) info->baseaddr = baseaddr; info->a15_clusid = a15_clusid; + if (irq <= 0) { + pr_err(SPCLOG "Invalid IRQ %d\n", irq); + kfree(info); + return -EINVAL; + } + + init_completion(&info->done); + + readl_relaxed(info->baseaddr + PWC_STATUS); + + ret = request_irq(irq, ve_spc_irq_handler, IRQF_TRIGGER_HIGH + | IRQF_ONESHOT, "vexpress-spc", info); + if (ret) { + pr_err(SPCLOG "IRQ %d request failed\n", irq); + kfree(info); + return -ENODEV; + } + + sema_init(&info->sem, 1); /* * Multi-cluster systems may need this data when non-coherent, during * cluster power-up/power-down. Make sure driver info reaches main diff --git a/arch/arm/mach-vexpress/spc.h b/arch/arm/mach-vexpress/spc.h index 5f7e4a4..dbd44c3 100644 --- a/arch/arm/mach-vexpress/spc.h +++ b/arch/arm/mach-vexpress/spc.h @@ -15,7 +15,7 @@ #ifndef __SPC_H_ #define __SPC_H_ -int __init ve_spc_init(void __iomem *base, u32 a15_clusid); +int __init ve_spc_init(void __iomem *base, u32 a15_clusid, int irq); void ve_spc_global_wakeup_irq(bool set); void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set); void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr); diff --git a/arch/arm/mach-vexpress/tc2_pm.c b/arch/arm/mach-vexpress/tc2_pm.c index e6eb481..d38130a 100644 --- a/arch/arm/mach-vexpress/tc2_pm.c +++ b/arch/arm/mach-vexpress/tc2_pm.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -311,7 +312,7 @@ static void __naked tc2_pm_power_up_setup(unsigned int affinity_level) static int __init tc2_pm_init(void) { - int ret; + int ret, irq; void __iomem *scc; u32 a15_cluster_id, a7_cluster_id, sys_info; struct device_node *np; @@ -336,13 +337,15 @@ static int __init tc2_pm_init(void) tc2_nr_cpus[a15_cluster_id] = (sys_info >> 16) & 0xf; tc2_nr_cpus[a7_cluster_id] = (sys_info >> 20) & 0xf; + irq = irq_of_parse_and_map(np, 0); + /* * A subset of the SCC registers is also used to communicate * with the SPC (power controller). We need to be able to * drive it very early in the boot process to power up * processors, so we initialize the SPC driver here. */ - ret = ve_spc_init(scc + SPC_BASE, a15_cluster_id); + ret = ve_spc_init(scc + SPC_BASE, a15_cluster_id, irq); if (ret) return ret; -- cgit v0.10.2 From 4d910d5bb56c870e5a737b71d4130ec38dc4faea Mon Sep 17 00:00:00 2001 From: Sudeep KarkadaNagesha Date: Tue, 29 Oct 2013 12:18:38 +0000 Subject: ARM: vexpress/TC2: add cpu clock support On TC2, the cpu clocks are controlled by the external M3 microcontroller and SPC provides the interface between the CPU and the power controller. The generic cpufreq drivers use the clock APIs to get the cpu clocks. This patch add virtual spc clocks for all the cpus to control the cpu operating frequency via the clock framework. Signed-off-by: Sudeep KarkadaNagesha Acked-by: Nicolas Pitre Acked-by: Pawel Moll Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c index de0ca36..3532e26 100644 --- a/arch/arm/mach-vexpress/spc.c +++ b/arch/arm/mach-vexpress/spc.c @@ -17,6 +17,9 @@ * GNU General Public License for more details. */ +#include +#include +#include #include #include #include @@ -438,3 +441,102 @@ int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid, int irq) return 0; } + +struct clk_spc { + struct clk_hw hw; + int cluster; +}; + +#define to_clk_spc(spc) container_of(spc, struct clk_spc, hw) +static unsigned long spc_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_spc *spc = to_clk_spc(hw); + u32 freq; + + if (ve_spc_get_performance(spc->cluster, &freq)) + return -EIO; + + return freq * 1000; +} + +static long spc_round_rate(struct clk_hw *hw, unsigned long drate, + unsigned long *parent_rate) +{ + struct clk_spc *spc = to_clk_spc(hw); + + return ve_spc_round_performance(spc->cluster, drate); +} + +static int spc_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_spc *spc = to_clk_spc(hw); + + return ve_spc_set_performance(spc->cluster, rate / 1000); +} + +static struct clk_ops clk_spc_ops = { + .recalc_rate = spc_recalc_rate, + .round_rate = spc_round_rate, + .set_rate = spc_set_rate, +}; + +static struct clk *ve_spc_clk_register(struct device *cpu_dev) +{ + struct clk_init_data init; + struct clk_spc *spc; + + spc = kzalloc(sizeof(*spc), GFP_KERNEL); + if (!spc) { + pr_err("could not allocate spc clk\n"); + return ERR_PTR(-ENOMEM); + } + + spc->hw.init = &init; + spc->cluster = topology_physical_package_id(cpu_dev->id); + + init.name = dev_name(cpu_dev); + init.ops = &clk_spc_ops; + init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE; + init.num_parents = 0; + + return devm_clk_register(cpu_dev, &spc->hw); +} + +static int __init ve_spc_clk_init(void) +{ + int cpu; + struct clk *clk; + + if (!info) + return 0; /* Continue only if SPC is initialised */ + + if (ve_spc_populate_opps(0) || ve_spc_populate_opps(1)) { + pr_err("failed to build OPP table\n"); + return -ENODEV; + } + + for_each_possible_cpu(cpu) { + struct device *cpu_dev = get_cpu_device(cpu); + if (!cpu_dev) { + pr_warn("failed to get cpu%d device\n", cpu); + continue; + } + clk = ve_spc_clk_register(cpu_dev); + if (IS_ERR(clk)) { + pr_warn("failed to register cpu%d clock\n", cpu); + continue; + } + if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) { + pr_warn("failed to register cpu%d clock lookup\n", cpu); + continue; + } + + if (ve_init_opp_table(cpu_dev)) + pr_warn("failed to initialise cpu%d opp table\n", cpu); + } + + return 0; +} +module_init(ve_spc_clk_init); -- cgit v0.10.2 From 47ac9aa165540b43deb3582f186073884de1cf3b Mon Sep 17 00:00:00 2001 From: Sudeep KarkadaNagesha Date: Tue, 29 Oct 2013 12:18:39 +0000 Subject: cpufreq: arm_big_little: add vexpress SPC interface driver The TC2(i.e. CA15_A7) Versatile Express has external Cortex M3 based power controller which is responsible for CPU DVFS and SPC provides the interface for the same. This patch adds a tiny interface driver to check if OPPs are initialised by SPC platform code and register the arm_big_little cpufreq driver. Signed-off-by: Sudeep KarkadaNagesha Acked-by: Nicolas Pitre Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 701ec95..ce52ed9 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -224,3 +224,11 @@ config ARM_TEGRA_CPUFREQ default y help This adds the CPUFreq driver support for TEGRA SOCs. + +config ARM_VEXPRESS_SPC_CPUFREQ + tristate "Versatile Express SPC based CPUfreq driver" + select ARM_BIG_LITTLE_CPUFREQ + depends on ARCH_VEXPRESS_SPC + help + This add the CPUfreq driver support for Versatile Express + big.LITTLE platforms using SPC for power management. diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index b7948bb..7494565 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -74,6 +74,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o +obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o ################################################################################## # PowerPC platform drivers diff --git a/drivers/cpufreq/vexpress-spc-cpufreq.c b/drivers/cpufreq/vexpress-spc-cpufreq.c new file mode 100644 index 0000000..7f7c9c0 --- /dev/null +++ b/drivers/cpufreq/vexpress-spc-cpufreq.c @@ -0,0 +1,70 @@ +/* + * Versatile Express SPC CPUFreq Interface driver + * + * It provides necessary ops to arm_big_little cpufreq driver. + * + * Copyright (C) 2013 ARM Ltd. + * Sudeep KarkadaNagesha + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +#include "arm_big_little.h" + +static int ve_spc_init_opp_table(struct device *cpu_dev) +{ + /* + * platform specific SPC code must initialise the opp table + * so just check if the OPP count is non-zero + */ + return dev_pm_opp_get_opp_count(cpu_dev) <= 0; +} + +static int ve_spc_get_transition_latency(struct device *cpu_dev) +{ + return 1000000; /* 1 ms */ +} + +static struct cpufreq_arm_bL_ops ve_spc_cpufreq_ops = { + .name = "vexpress-spc", + .get_transition_latency = ve_spc_get_transition_latency, + .init_opp_table = ve_spc_init_opp_table, +}; + +static int ve_spc_cpufreq_probe(struct platform_device *pdev) +{ + return bL_cpufreq_register(&ve_spc_cpufreq_ops); +} + +static int ve_spc_cpufreq_remove(struct platform_device *pdev) +{ + bL_cpufreq_unregister(&ve_spc_cpufreq_ops); + return 0; +} + +static struct platform_driver ve_spc_cpufreq_platdrv = { + .driver = { + .name = "vexpress-spc-cpufreq", + .owner = THIS_MODULE, + }, + .probe = ve_spc_cpufreq_probe, + .remove = ve_spc_cpufreq_remove, +}; +module_platform_driver(ve_spc_cpufreq_platdrv); + +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 9e941b6f42cc2b0d53011d62d639140c84116f59 Mon Sep 17 00:00:00 2001 From: Sudeep KarkadaNagesha Date: Tue, 29 Oct 2013 12:18:40 +0000 Subject: ARM: vexpress/TC2: register vexpress-spc cpufreq device This patch adds vexpress-spc platform device to enables the vexpress SPC cpufreq interface driver. Signed-off-by: Sudeep KarkadaNagesha Acked-by: Pawel Moll Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c index 3532e26..033d34d 100644 --- a/arch/arm/mach-vexpress/spc.c +++ b/arch/arm/mach-vexpress/spc.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -537,6 +538,7 @@ static int __init ve_spc_clk_init(void) pr_warn("failed to initialise cpu%d opp table\n", cpu); } + platform_device_register_simple("vexpress-spc-cpufreq", -1, NULL, 0); return 0; } module_init(ve_spc_clk_init); -- cgit v0.10.2 From 6587fca23001c33813d56309faf41188b5fbdb70 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:40 +0530 Subject: cpuidle: fix indentation of cpumask Use tabs for cpumask indentation in struct cpuidle_driver. [rjw: Changelog] Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 781addc..c082425 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -114,7 +114,7 @@ struct cpuidle_driver { int safe_state_index; /* the driver handles the cpus in cpumask */ - struct cpumask *cpumask; + struct cpumask *cpumask; }; #ifdef CONFIG_CPU_IDLE -- cgit v0.10.2 From caf4a36e818ba8df4e002b7dfa4eff5b8384dda0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:41 +0530 Subject: cpuidle: Fix comments in cpuidle core Some comments in cpuidle core files contain trivial mistakes. This patch fixes them. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c index f8a8636..e952936 100644 --- a/drivers/cpuidle/coupled.c +++ b/drivers/cpuidle/coupled.c @@ -147,7 +147,7 @@ static cpumask_t cpuidle_coupled_poked; * has returned from this function, the barrier is immediately available for * reuse. * - * The atomic variable a must be initialized to 0 before any cpu calls + * The atomic variable must be initialized to 0 before any cpu calls * this function, will be reset to 0 before any cpu returns from this function. * * Must only be called from within a coupled idle state handler diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index d75040d..8827c02 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -516,7 +516,7 @@ int cpuidle_register(struct cpuidle_driver *drv, #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED /* - * On multiplatform for ARM, the coupled idle states could + * On multiplatform for ARM, the coupled idle states could be * enabled in the kernel even if the cpuidle driver does not * use it. Note, coupled_cpus is a struct copy. */ diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 6e11701..ced1df6 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -56,7 +56,7 @@ static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) } /** - * __cpuidle_set_driver - set per CPU driver variables the the given driver. + * __cpuidle_set_driver - set per CPU driver variables for the given driver. * @drv: a valid pointer to a struct cpuidle_driver * * For each CPU in the driver's cpumask, unset the registered driver per CPU @@ -132,7 +132,7 @@ static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) * cpuidle_setup_broadcast_timer - enable/disable the broadcast timer * @arg: a void pointer used to match the SMP cross call API * - * @arg is used as a value of type 'long' with on of the two values: + * @arg is used as a value of type 'long' with one of the two values: * - CLOCK_EVT_NOTIFY_BROADCAST_ON * - CLOCK_EVT_NOTIFY_BROADCAST_OFF * @@ -169,7 +169,7 @@ static int __cpuidle_driver_init(struct cpuidle_driver *drv) /* * Look for the timer stop flag in the different states, so that we know * if the broadcast timer has to be set up. The loop is in the reverse - * order, because usually on of the the deeper states has this flag set. + * order, because usually one of the deeper states have this flag set. */ for (i = drv->state_count - 1; i >= 0 ; i--) { -- cgit v0.10.2 From 267d4bf8ee6dbde889f4c55d0188f561616dbc7a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:43 +0530 Subject: cpuidle: make __cpuidle_device_init() return void The only value returned by __cpuidle_device_init() is 0, so it very well may be a void function. Make that happen. [rjw: Changelog] Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 8827c02..211e504 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -358,12 +358,10 @@ static void __cpuidle_unregister_device(struct cpuidle_device *dev) module_put(drv->owner); } -static int __cpuidle_device_init(struct cpuidle_device *dev) +static void __cpuidle_device_init(struct cpuidle_device *dev) { memset(dev->states_usage, 0, sizeof(dev->states_usage)); dev->last_residency = 0; - - return 0; } /** @@ -410,9 +408,7 @@ int cpuidle_register_device(struct cpuidle_device *dev) if (dev->registered) goto out_unlock; - ret = __cpuidle_device_init(dev); - if (ret) - goto out_unlock; + __cpuidle_device_init(dev); ret = __cpuidle_register_device(dev); if (ret) -- cgit v0.10.2 From e437f3e37369606bf1a340e0504554d6530abc51 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:44 +0530 Subject: cpuidle: make __cpuidle_driver_init() return void The only value returned by __cpuidle_driver_init() is 0, so it very well may be a void function. [rjw: Changelog] Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index ced1df6..d97d072 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -149,10 +149,8 @@ static void cpuidle_setup_broadcast_timer(void *arg) /** * __cpuidle_driver_init - initialize the driver's internal data * @drv: a valid pointer to a struct cpuidle_driver - * - * Returns 0 on success, a negative error code otherwise. */ -static int __cpuidle_driver_init(struct cpuidle_driver *drv) +static void __cpuidle_driver_init(struct cpuidle_driver *drv) { int i; @@ -179,8 +177,6 @@ static int __cpuidle_driver_init(struct cpuidle_driver *drv) drv->bctimer = 1; break; } - - return 0; } /** @@ -206,9 +202,7 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv) if (cpuidle_disabled()) return -ENODEV; - ret = __cpuidle_driver_init(drv); - if (ret) - return ret; + __cpuidle_driver_init(drv); ret = __cpuidle_set_driver(drv); if (ret) -- cgit v0.10.2 From b171a85648e7055c6680c259a9a87806a56a24c3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:45 +0530 Subject: cpuidle: rearrange code in __cpuidle_driver_init() This is trivial patch that just reorders a few statements in __cpuidle_driver_init() routine so that we don't need both 'continue' and 'break' in the for loop. Functionally it shouldn't change anything. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index d97d072..a930005 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -170,12 +170,10 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv) * order, because usually one of the deeper states have this flag set. */ for (i = drv->state_count - 1; i >= 0 ; i--) { - - if (!(drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP)) - continue; - - drv->bctimer = 1; - break; + if (drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP) { + drv->bctimer = 1; + break; + } } } -- cgit v0.10.2 From 47182668ca140ae067d5961ec8c59edf646b36c7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:46 +0530 Subject: cpuidle: rearrange __cpuidle_register_device() to keep minimal exit points This patch rearranges __cpuidle_register_device() a bit in order to reduce the number of exit points in that function. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 211e504..8c91bad 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -383,13 +383,12 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) list_add(&dev->device_list, &cpuidle_detected_devices); ret = cpuidle_coupled_register_device(dev); - if (ret) { + if (ret) __cpuidle_unregister_device(dev); - return ret; - } + else + dev->registered = 1; - dev->registered = 1; - return 0; + return ret; } /** -- cgit v0.10.2 From 9b29a86f04f87cdb9eaacadf2e2d33a55af1c7cc Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:47 +0530 Subject: cpuidle: merge two if() statements for checking error cases Two checks cpuidle_idle_call() cause the same error code to be returned if they fail, so merge them for clarity. [rjw: Changelog] Acked-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 8c91bad..518b542 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -119,10 +119,7 @@ int cpuidle_idle_call(void) struct cpuidle_driver *drv; int next_state, entered_state; - if (off) - return -ENODEV; - - if (!initialized) + if (off || !initialized) return -ENODEV; /* check if the device is ready */ -- cgit v0.10.2 From fb11c9c63f995afbe0e909f061d9866a722cb4bf Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:48 +0530 Subject: cpuidle: reduce code duplication inside cpuidle_idle_call() We are doing this twice in cpuidle_idle_call() routine: drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP Would be better if we actually store this in a local variable and use that. That reduces code duplication and likely makes this piece of code run faster (in case the compiler wasn't able to optimize it earlier) [rjw: Cast the result of bitwise AND to bool explicitly using !!] Acked-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 518b542..86e8059 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -118,6 +118,7 @@ int cpuidle_idle_call(void) struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); struct cpuidle_driver *drv; int next_state, entered_state; + bool broadcast; if (off || !initialized) return -ENODEV; @@ -141,7 +142,9 @@ int cpuidle_idle_call(void) trace_cpu_idle_rcuidle(next_state, dev->cpu); - if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP) + broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP); + + if (broadcast) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); @@ -151,7 +154,7 @@ int cpuidle_idle_call(void) else entered_state = cpuidle_enter_state(dev, drv, next_state); - if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP) + if (broadcast) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); -- cgit v0.10.2 From 6d281e97a1c53abb73477a34806c1a000409c4b9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:49 +0530 Subject: cpuidle: replace multiline statements with single line in cpuidle_idle_call() Few statements in cpuidle_idle_call() are broken into multiple lines, although that isn't really necessary. Convert those to single line. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 86e8059..039a807 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -145,8 +145,7 @@ int cpuidle_idle_call(void) broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP); if (broadcast) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, - &dev->cpu); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); if (cpuidle_state_is_coupled(dev, drv, next_state)) entered_state = cpuidle_enter_state_coupled(dev, drv, @@ -155,8 +154,7 @@ int cpuidle_idle_call(void) entered_state = cpuidle_enter_state(dev, drv, next_state); if (broadcast) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, - &dev->cpu); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); -- cgit v0.10.2 From 0d09d3125642ac1f02937e577819dbc515291d93 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:50 +0530 Subject: cpuidle: call cpuidle_get_driver() from after taking cpuidle_driver_lock There are a few cpuidle_get_driver() calls that aren't made under cpuidle_driver_lock which is incorrect. Fix them by calling cpuidle_get_driver() after taking cpuidle_driver_lock. Acked-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index a930005..2458a74 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -338,10 +338,11 @@ struct cpuidle_driver *cpuidle_driver_ref(void) */ void cpuidle_driver_unref(void) { - struct cpuidle_driver *drv = cpuidle_get_driver(); + struct cpuidle_driver *drv; spin_lock(&cpuidle_driver_lock); + drv = cpuidle_get_driver(); if (drv && !WARN_ON(drv->refcnt <= 0)) drv->refcnt--; diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 8739cc0..a022393 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -52,9 +52,10 @@ static ssize_t show_current_driver(struct device *dev, char *buf) { ssize_t ret; - struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); + struct cpuidle_driver *cpuidle_driver; spin_lock(&cpuidle_driver_lock); + cpuidle_driver = cpuidle_get_driver(); if (cpuidle_driver) ret = sprintf(buf, "%s\n", cpuidle_driver->name); else -- cgit v0.10.2 From 1f6b9f74ee3d96909e5e70d4207b4b6740d4db62 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:51 +0530 Subject: cpuidle: use drv instead of cpuidle_driver in show_current_driver() Instances of "struct cpuidle_driver *" are consistently named as "drv" in the cpuidle core except in show_current_driver(). Make that function use variable naming consistent with the rest of the code. [rjw: Changelog] Acked-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index a022393..e918b6d 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -52,12 +52,12 @@ static ssize_t show_current_driver(struct device *dev, char *buf) { ssize_t ret; - struct cpuidle_driver *cpuidle_driver; + struct cpuidle_driver *drv; spin_lock(&cpuidle_driver_lock); - cpuidle_driver = cpuidle_get_driver(); - if (cpuidle_driver) - ret = sprintf(buf, "%s\n", cpuidle_driver->name); + drv = cpuidle_get_driver(); + if (drv) + ret = sprintf(buf, "%s\n", drv->name); else ret = sprintf(buf, "none\n"); spin_unlock(&cpuidle_driver_lock); -- cgit v0.10.2 From d7c7f103262bc2248548ed0e113e916e843c4eeb Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:54 +0530 Subject: cpuidle: don't call poll_idle_init() for every cpu poll_idle_init() just initializes drv->states[0] and so that is required to be done only once for each driver. Currently, it is called from cpuidle_enable_device() which is called for every CPU that the driver supports. That is not required, so move it to a better place and call it from __cpuidle_register_driver() so that the initialization is carried out only once. Acked-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 039a807..2a991e4 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -226,45 +226,6 @@ void cpuidle_resume(void) mutex_unlock(&cpuidle_lock); } -#ifdef CONFIG_ARCH_HAS_CPU_RELAX -static int poll_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) -{ - ktime_t t1, t2; - s64 diff; - - t1 = ktime_get(); - local_irq_enable(); - while (!need_resched()) - cpu_relax(); - - t2 = ktime_get(); - diff = ktime_to_us(ktime_sub(t2, t1)); - if (diff > INT_MAX) - diff = INT_MAX; - - dev->last_residency = (int) diff; - - return index; -} - -static void poll_idle_init(struct cpuidle_driver *drv) -{ - struct cpuidle_state *state = &drv->states[0]; - - snprintf(state->name, CPUIDLE_NAME_LEN, "POLL"); - snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); - state->exit_latency = 0; - state->target_residency = 0; - state->power_usage = -1; - state->flags = 0; - state->enter = poll_idle; - state->disabled = false; -} -#else -static void poll_idle_init(struct cpuidle_driver *drv) {} -#endif /* CONFIG_ARCH_HAS_CPU_RELAX */ - /** * cpuidle_enable_device - enables idle PM for a CPU * @dev: the CPU @@ -294,8 +255,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev) if (!dev->state_count) dev->state_count = drv->state_count; - poll_idle_init(drv); - ret = cpuidle_add_device_sysfs(dev); if (ret) return ret; diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 2458a74..06dbe7c 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -177,6 +178,45 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv) } } +#ifdef CONFIG_ARCH_HAS_CPU_RELAX +static int poll_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + ktime_t t1, t2; + s64 diff; + + t1 = ktime_get(); + local_irq_enable(); + while (!need_resched()) + cpu_relax(); + + t2 = ktime_get(); + diff = ktime_to_us(ktime_sub(t2, t1)); + if (diff > INT_MAX) + diff = INT_MAX; + + dev->last_residency = (int) diff; + + return index; +} + +static void poll_idle_init(struct cpuidle_driver *drv) +{ + struct cpuidle_state *state = &drv->states[0]; + + snprintf(state->name, CPUIDLE_NAME_LEN, "POLL"); + snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); + state->exit_latency = 0; + state->target_residency = 0; + state->power_usage = -1; + state->flags = 0; + state->enter = poll_idle; + state->disabled = false; +} +#else +static void poll_idle_init(struct cpuidle_driver *drv) {} +#endif /* !CONFIG_ARCH_HAS_CPU_RELAX */ + /** * __cpuidle_register_driver: register the driver * @drv: a valid pointer to a struct cpuidle_driver @@ -210,6 +250,8 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv) on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1); + poll_idle_init(drv); + return 0; } -- cgit v0.10.2 From f60e230f6be5672241e48434a6c2a417d9674d42 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Oct 2013 21:26:55 +0530 Subject: cpuidle: remove cpuidle_unregister_governor() cpuidle_unregister_governor() and cpuidle_replace_governor() aren't used anymore and can be removed. They were used by cpufreq governors earlier, but since the governors can't be compiled as modules any more, these two functions aren't necessary. Suggested-by: Daniel Lezcano Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/Documentation/cpuidle/governor.txt b/Documentation/cpuidle/governor.txt index 12c6bd5..d9020f5 100644 --- a/Documentation/cpuidle/governor.txt +++ b/Documentation/cpuidle/governor.txt @@ -25,5 +25,4 @@ kernel configuration and platform will be selected by cpuidle. Interfaces: extern int cpuidle_register_governor(struct cpuidle_governor *gov); -extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); struct cpuidle_governor diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c index ea2f8e7..ca89412 100644 --- a/drivers/cpuidle/governor.c +++ b/drivers/cpuidle/governor.c @@ -96,46 +96,3 @@ int cpuidle_register_governor(struct cpuidle_governor *gov) return ret; } - -/** - * cpuidle_replace_governor - find a replacement governor - * @exclude_rating: the rating that will be skipped while looking for - * new governor. - */ -static struct cpuidle_governor *cpuidle_replace_governor(int exclude_rating) -{ - struct cpuidle_governor *gov; - struct cpuidle_governor *ret_gov = NULL; - unsigned int max_rating = 0; - - list_for_each_entry(gov, &cpuidle_governors, governor_list) { - if (gov->rating == exclude_rating) - continue; - if (gov->rating > max_rating) { - max_rating = gov->rating; - ret_gov = gov; - } - } - - return ret_gov; -} - -/** - * cpuidle_unregister_governor - unregisters a governor - * @gov: the governor - */ -void cpuidle_unregister_governor(struct cpuidle_governor *gov) -{ - if (!gov) - return; - - mutex_lock(&cpuidle_lock); - if (gov == cpuidle_curr_governor) { - struct cpuidle_governor *new_gov; - new_gov = cpuidle_replace_governor(gov->rating); - cpuidle_switch_governor(new_gov); - } - list_del(&gov->governor_list); - mutex_unlock(&cpuidle_lock); -} - diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index c082425..50fcbb0 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -195,16 +195,10 @@ struct cpuidle_governor { }; #ifdef CONFIG_CPU_IDLE - extern int cpuidle_register_governor(struct cpuidle_governor *gov); -extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); - #else - static inline int cpuidle_register_governor(struct cpuidle_governor *gov) {return 0;} -static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { } - #endif #ifdef CONFIG_ARCH_HAS_CPU_RELAX -- cgit v0.10.2 From e2401453111dd84da377e4e84740ab643885f95a Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Wed, 23 Oct 2013 09:44:51 -0400 Subject: intel_idle: use CPU_TASKS_FROZEN instead of a numeric constant Small fixup to use CPU_TASKS_FROZEN instead of 0xf. Signed-off-by: Prarit Bhargava Signed-off-by: Rafael J. Wysocki diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 33e599e..3f95a53 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -390,7 +390,7 @@ static int cpu_hotplug_notify(struct notifier_block *n, int hotcpu = (unsigned long)hcpu; struct cpuidle_device *dev; - switch (action & 0xf) { + switch (action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) -- cgit v0.10.2 From 1b673f23d95f0bbc7e3c95321864b727ea75704b Mon Sep 17 00:00:00 2001 From: Tomasz Nowicki Date: Tue, 29 Oct 2013 09:28:49 +0800 Subject: ACPICA: Ensure that debug output is immediately disabled on termination. Set the global debug flag to "no output" when the debugger is shutdown. ACPICA BZ 1011. Tomasz Nowicki. Since the debugger is not shipped in the Linux kernel upstream, this change doesn't affect Linux kernel's behavior. References: https://bugs.acpica.org/show_bug.cgi?id=1011 Signed-off-by: Tomasz Nowicki Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index be9e30e..dafa0f6 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -1094,6 +1094,7 @@ struct acpi_integrity_info { u32 objects; }; +#define ACPI_DB_DISABLE_OUTPUT 0x00 #define ACPI_DB_REDIRECTABLE_OUTPUT 0x01 #define ACPI_DB_CONSOLE_OUTPUT 0x02 #define ACPI_DB_DUPLICATE_OUTPUT 0x03 -- cgit v0.10.2 From d7da179423a506e8033a376547a375c0c9ec7671 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:28:56 +0800 Subject: ACPICA: Table print header function: Increase default width for table length. This change increases the default width for the length of tables from 5 to 6, to improve alignment/readability on systems with large tables. These are being seen more frequently, especially large DSDTs (greater than 1 MB). Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index 9a47715..6866e76 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -135,7 +135,7 @@ acpi_tb_print_table_header(acpi_physical_address address, /* FACS only has signature and length fields */ - ACPI_INFO((AE_INFO, "%4.4s %p %05X", + ACPI_INFO((AE_INFO, "%4.4s %p %06X", header->signature, ACPI_CAST_PTR(void, address), header->length)); } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { @@ -147,7 +147,7 @@ acpi_tb_print_table_header(acpi_physical_address address, header)->oem_id, ACPI_OEM_ID_SIZE); acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); - ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", + ACPI_INFO((AE_INFO, "RSDP %p %06X (v%.2d %6.6s)", ACPI_CAST_PTR(void, address), (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> revision > @@ -162,7 +162,7 @@ acpi_tb_print_table_header(acpi_physical_address address, acpi_tb_cleanup_table_header(&local_header, header); ACPI_INFO((AE_INFO, - "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", + "%4.4s %p %06X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", local_header.signature, ACPI_CAST_PTR(void, address), local_header.length, local_header.revision, local_header.oem_id, local_header.oem_table_id, -- cgit v0.10.2 From 48961ce62787502fe2afce2aeeb0ec306757a2bb Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:04 +0800 Subject: ACPICA: Add a check for a null node during namespace walk. Mostly for consistency. ACPICA BZ 1042. Actually, currently no one is experiencing problem without this check as the obj_handle is guaranteed to be valid. References: https://bugs.acpica.org/show_bug.cgi?id=1042 Reported-by: Colin Ian King Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 8063385..c634854 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -715,6 +715,13 @@ acpi_ns_dump_one_object_path(acpi_handle obj_handle, } node = acpi_ns_validate_handle(obj_handle); + if (!node) { + + /* Ignore bad node during namespace walk */ + + return (AE_OK); + } + pathname = acpi_ns_get_external_pathname(node); path_indent = 1; -- cgit v0.10.2 From 1d98e9e0bb8815072a0d2d04dc3f0e2c51029e61 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:09 +0800 Subject: ACPICA: Add history/line-editing for Unix/Linux systems. The original upstream ACPICA change added full history and limited line editing to the debugger: This change adds full history and limited line editing for Unix and Linux systems. It does not use readline() because of portability issues. Instead it uses the POSIX termio interface to put the terminal in raw input mode so that the various special keys can be trapped (such as up-arrow and down-arrow for history support). Since the debugger is not shipped in the kernel, it only is necessary to update one header file to keep the kernel source in sync with the upstream. [rjw: Changelog] Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 27c36a5..57cdc77 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -243,6 +243,8 @@ void acpi_db_display_history(void); char *acpi_db_get_from_history(char *command_num_arg); +char *acpi_db_get_history_by_index(u32 commandd_num); + /* * dbinput - user front-end to the AML debugger */ -- cgit v0.10.2 From c26f3c908091294e5909f5459b6682e10922c824 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:16 +0800 Subject: ACPICA: Fix a macro for the hardware-reduced case This fix repairs a version of a macro that is used for the hardware reduced case only. It adds a return statement to the macro definition so that the translation into the Linux kernel source will not completely delete the second line of the macro because it thinks that it is an empty block. It actually clarifies the use of the macro anyway. Reported-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index c7b1475..ebab0d8 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -106,7 +106,7 @@ extern u8 acpi_gbl_disable_ssdt_table_load; static ACPI_INLINE prototype {return(AE_OK);} #define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ - static ACPI_INLINE prototype {} + static ACPI_INLINE prototype {return;} #endif /* !ACPI_REDUCED_HARDWARE */ -- cgit v0.10.2 From 73424473d0801f7079258897901ba1edc660dbd3 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:21 +0800 Subject: ACPICA: Add safe versions of common string functions. This change adds and deploys "safe" versions of strcpy and strcat that ensure that the target buffer does not overflow. These safe functions are only helpful for processing user input and command lines. For most ACPICA code however, the required buffer length is precisely calculated before buffer allocation, so the use of these functions is unnecessary. ACPICA BZ 1043. This change only applies to the ACPICA utilities and the debugger, none of which are not shipped with the kernel yet, so the kernel's behavior remains unchanged after it. References: https://bugs.acpica.org/show_bug.cgi?id=1043 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index dafa0f6..53ed1a8 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -1072,7 +1072,7 @@ struct acpi_db_method_info { char *name; u32 flags; u32 num_loops; - char pathname[128]; + char pathname[ACPI_DB_LINE_BUFFER_SIZE]; char **args; acpi_object_type *types; diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index d5a62a6..4f25e8f 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -628,6 +628,17 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position); void acpi_ut_repair_name(char *name); +#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) +u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source); + +u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source); + +u8 +acpi_ut_safe_strncat(char *dest, + acpi_size dest_size, + char *source, acpi_size max_transfer_length); +#endif + /* * utmutex - mutex support */ diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index cb1e9cc..5ef41ff 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -584,3 +584,65 @@ void ut_convert_backslashes(char *pathname) } } #endif + +#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) +/******************************************************************************* + * + * FUNCTION: acpi_ut_safe_strcpy, acpi_ut_safe_strcat, acpi_ut_safe_strncat + * + * PARAMETERS: Adds a "DestSize" parameter to each of the standard string + * functions. This is the size of the Destination buffer. + * + * RETURN: TRUE if the operation would overflow the destination buffer. + * + * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that + * the result of the operation will not overflow the output string + * buffer. + * + * NOTE: These functions are typically only helpful for processing + * user input and command lines. For most ACPICA code, the + * required buffer length is precisely calculated before buffer + * allocation, so the use of these functions is unnecessary. + * + ******************************************************************************/ + +u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source) +{ + + if (ACPI_STRLEN(source) >= dest_size) { + return (TRUE); + } + + ACPI_STRCPY(dest, source); + return (FALSE); +} + +u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source) +{ + + if ((ACPI_STRLEN(dest) + ACPI_STRLEN(source)) >= dest_size) { + return (TRUE); + } + + ACPI_STRCAT(dest, source); + return (FALSE); +} + +u8 +acpi_ut_safe_strncat(char *dest, + acpi_size dest_size, + char *source, acpi_size max_transfer_length) +{ + acpi_size actual_transfer_length; + + actual_transfer_length = + ACPI_MIN(max_transfer_length, ACPI_STRLEN(source)); + + if ((ACPI_STRLEN(dest) + actual_transfer_length) >= dest_size) { + return (TRUE); + } + + ACPI_STRNCAT(dest, source, max_transfer_length); + return (FALSE); +} +#endif -- cgit v0.10.2 From b3c86c30efd83ebfa7010c5890e2ebf2678e49f8 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:29:27 +0800 Subject: ACPICA: Cleanup memory allocation macros and configurability. In the common case, the ACPI_ALLOCATE and related macros now resolve directly to their respective acpi_os* OSL interfaces. Two options: 1) The ACPI_ALLOCATE_ZEROED macro defaults to a simple local implementation by default, unless overridden by the USE_NATIVE_ALLOCATE_ZEROED define. 2) For ACPI execution simulation environment (AcpiExec) which is not shipped with the Linux kernel, the macros can optionally be resolved to the local interfaces that track each allocation (used to immediately detect memory leaks). Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 530a2f8..2a86c65 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -410,37 +410,6 @@ #endif /* - * Memory allocation tracking (DEBUG ONLY) - */ -#define ACPI_MEM_PARAMETERS _COMPONENT, _acpi_module_name, __LINE__ - -#ifndef ACPI_DBG_TRACK_ALLOCATIONS - -/* Memory allocation */ - -#ifndef ACPI_ALLOCATE -#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size) (a), ACPI_MEM_PARAMETERS) -#endif -#ifndef ACPI_ALLOCATE_ZEROED -#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size) (a), ACPI_MEM_PARAMETERS) -#endif -#ifndef ACPI_FREE -#define ACPI_FREE(a) acpi_os_free(a) -#endif -#define ACPI_MEM_TRACKING(a) - -#else - -/* Memory allocation */ - -#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS) -#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS) -#define ACPI_FREE(a) acpi_ut_free_and_track(a, ACPI_MEM_PARAMETERS) -#define ACPI_MEM_TRACKING(a) a - -#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ - -/* * Macros used for ACPICA utilities only */ diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 4f25e8f..be8180c 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -663,12 +663,6 @@ acpi_status acpi_ut_initialize_buffer(struct acpi_buffer *buffer, acpi_size required_length); -void *acpi_ut_allocate(acpi_size size, - u32 component, const char *module, u32 line); - -void *acpi_ut_allocate_zeroed(acpi_size size, - u32 component, const char *module, u32 line); - #ifdef ACPI_DBG_TRACK_ALLOCATIONS void *acpi_ut_allocate_and_track(acpi_size size, u32 component, const char *module, u32 line); diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index e0ffb58..d844796 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c @@ -48,6 +48,39 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utalloc") +#if !defined (USE_NATIVE_ALLOCATE_ZEROED) +/******************************************************************************* + * + * FUNCTION: acpi_os_allocate_zeroed + * + * PARAMETERS: size - Size of the allocation + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. + * This is the default implementation. Can be overridden via the + * USE_NATIVE_ALLOCATE_ZEROED flag. + * + ******************************************************************************/ +void *acpi_os_allocate_zeroed(acpi_size size) +{ + void *allocation; + + ACPI_FUNCTION_ENTRY(); + + allocation = acpi_os_allocate(size); + if (allocation) { + + /* Clear the memory block */ + + ACPI_MEMSET(allocation, 0, size); + } + + return (allocation); +} + +#endif /* !USE_NATIVE_ALLOCATE_ZEROED */ + /******************************************************************************* * * FUNCTION: acpi_ut_create_caches @@ -59,6 +92,7 @@ ACPI_MODULE_NAME("utalloc") * DESCRIPTION: Create all local caches * ******************************************************************************/ + acpi_status acpi_ut_create_caches(void) { acpi_status status; @@ -302,82 +336,3 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, ACPI_MEMSET(buffer->pointer, 0, required_length); return (AE_OK); } - -#ifdef NOT_USED_BY_LINUX -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate - * - * PARAMETERS: size - Size of the allocation - * component - Component type of caller - * module - Source file name of caller - * line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of malloc. - * - ******************************************************************************/ - -void *acpi_ut_allocate(acpi_size size, - u32 component, const char *module, u32 line) -{ - void *allocation; - - ACPI_FUNCTION_TRACE_U32(ut_allocate, size); - - /* Check for an inadvertent size of zero bytes */ - - if (!size) { - ACPI_WARNING((module, line, - "Attempt to allocate zero bytes, allocating 1 byte")); - size = 1; - } - - allocation = acpi_os_allocate(size); - if (!allocation) { - - /* Report allocation error */ - - ACPI_WARNING((module, line, - "Could not allocate size %u", (u32) size)); - - return_PTR(NULL); - } - - return_PTR(allocation); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate_zeroed - * - * PARAMETERS: size - Size of the allocation - * component - Component type of caller - * module - Source file name of caller - * line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. - * - ******************************************************************************/ - -void *acpi_ut_allocate_zeroed(acpi_size size, - u32 component, const char *module, u32 line) -{ - void *allocation; - - ACPI_FUNCTION_ENTRY(); - - allocation = acpi_ut_allocate(size, component, module, line); - if (allocation) { - - /* Clear the memory block */ - - ACPI_MEMSET(allocation, 0, size); - } - - return (allocation); -} -#endif diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index 160f13f..77e3eb7 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -130,10 +130,23 @@ void *acpi_ut_allocate_and_track(acpi_size size, struct acpi_debug_mem_block *allocation; acpi_status status; + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + ACPI_WARNING((module, line, + "Attempt to allocate zero bytes, allocating 1 byte")); + size = 1; + } + allocation = - acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header), - component, module, line); + acpi_os_allocate(size + sizeof(struct acpi_debug_mem_header)); if (!allocation) { + + /* Report allocation error */ + + ACPI_WARNING((module, line, + "Could not allocate size %u", (u32)size)); + return (NULL); } @@ -179,9 +192,17 @@ void *acpi_ut_allocate_zeroed_and_track(acpi_size size, struct acpi_debug_mem_block *allocation; acpi_status status; + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + ACPI_WARNING((module, line, + "Attempt to allocate zero bytes, allocating 1 byte")); + size = 1; + } + allocation = - acpi_ut_allocate_zeroed(size + sizeof(struct acpi_debug_mem_header), - component, module, line); + acpi_os_allocate_zeroed(size + + sizeof(struct acpi_debug_mem_header)); if (!allocation) { /* Report allocation error */ diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 64b8c76..7f95215 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -146,6 +146,8 @@ void acpi_os_release_mutex(acpi_mutex handle); */ void *acpi_os_allocate(acpi_size size); +void *acpi_os_allocate_zeroed(acpi_size size); + void acpi_os_free(void *memory); void __iomem *acpi_os_map_memory(acpi_physical_address where, diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index ebab0d8..ddde61b 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -159,15 +159,6 @@ acpi_decode_pld_buffer(u8 *in_buffer, acpi_size length, struct acpi_pld_info **return_buffer); /* - * ACPI Memory management - */ -void *acpi_allocate(u32 size); - -void *acpi_callocate(u32 size); - -void acpi_free(void *address); - -/* * ACPI table load/unload interfaces */ acpi_status acpi_load_table(struct acpi_table_header *table); diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index f6abf23..fed5af2 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -306,6 +306,33 @@ typedef u32 acpi_physical_address; #define ACPI_EXPORT_SYMBOL(symbol) #endif +/******************************************************************************* + * + * Configuration + * + ******************************************************************************/ + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS +/* + * Memory allocation tracking (used by acpi_exec to detect memory leaks) + */ +#define ACPI_MEM_PARAMETERS _COMPONENT, _acpi_module_name, __LINE__ +#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track ((acpi_size) (a), ACPI_MEM_PARAMETERS) +#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track ((acpi_size) (a), ACPI_MEM_PARAMETERS) +#define ACPI_FREE(a) acpi_ut_free_and_track (a, ACPI_MEM_PARAMETERS) +#define ACPI_MEM_TRACKING(a) a + +#else +/* + * Normal memory allocation directly via the OS services layer + */ +#define ACPI_ALLOCATE(a) acpi_os_allocate ((acpi_size) (a)) +#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed ((acpi_size) (a)) +#define ACPI_FREE(a) acpi_os_free (a) +#define ACPI_MEM_TRACKING(a) + +#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ + /****************************************************************************** * * ACPI Specification constants (Do not change unless the specification changes) diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index fda0f3e..7346a92 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -119,6 +119,14 @@ static inline acpi_thread_id acpi_os_get_thread_id(void) } /* + * Memory allocation/deallocation + */ + +/* Use native linux version of acpi_os_allocate_zeroed */ + +#define USE_NATIVE_ALLOCATE_ZEROED + +/* * The irqs_disabled() check is for resume from RAM. * Interrupts are off during resume, just like they are for boot. * However, boot has (system_state != SYSTEM_RUNNING) @@ -140,9 +148,10 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache) irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL); } -#define ACPI_ALLOCATE(a) acpi_os_allocate(a) -#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a) -#define ACPI_FREE(a) kfree(a) +static inline void acpi_os_free(void *a) +{ + kfree(a); +} #ifndef CONFIG_PREEMPT /* -- cgit v0.10.2 From bf4994aca7c62b62b0a85a28476ef3a69ea8970f Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:34 +0800 Subject: ACPICA: Predefine name macros: Sort list. Sort the method names in acnames.h. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h index ce08ef7..1f36777 100644 --- a/include/acpi/acnames.h +++ b/include/acpi/acnames.h @@ -46,25 +46,25 @@ /* Method names - these methods can appear anywhere in the namespace */ -#define METHOD_NAME__SB_ "_SB_" -#define METHOD_NAME__HID "_HID" -#define METHOD_NAME__CID "_CID" -#define METHOD_NAME__UID "_UID" -#define METHOD_NAME__SUB "_SUB" #define METHOD_NAME__ADR "_ADR" -#define METHOD_NAME__INI "_INI" -#define METHOD_NAME__STA "_STA" -#define METHOD_NAME__REG "_REG" -#define METHOD_NAME__SEG "_SEG" +#define METHOD_NAME__AEI "_AEI" #define METHOD_NAME__BBN "_BBN" -#define METHOD_NAME__PRT "_PRT" +#define METHOD_NAME__CBA "_CBA" +#define METHOD_NAME__CID "_CID" #define METHOD_NAME__CRS "_CRS" +#define METHOD_NAME__HID "_HID" +#define METHOD_NAME__INI "_INI" +#define METHOD_NAME__PLD "_PLD" #define METHOD_NAME__PRS "_PRS" -#define METHOD_NAME__AEI "_AEI" +#define METHOD_NAME__PRT "_PRT" #define METHOD_NAME__PRW "_PRW" +#define METHOD_NAME__REG "_REG" +#define METHOD_NAME__SB_ "_SB_" +#define METHOD_NAME__SEG "_SEG" #define METHOD_NAME__SRS "_SRS" -#define METHOD_NAME__CBA "_CBA" -#define METHOD_NAME__PLD "_PLD" +#define METHOD_NAME__STA "_STA" +#define METHOD_NAME__SUB "_SUB" +#define METHOD_NAME__UID "_UID" /* Method names - these methods must appear at the namespace root */ -- cgit v0.10.2 From ab3b24807adabdc32f8a9d5d7d3902e1e744d139 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:29:40 +0800 Subject: ACPICA: Fix possible memory leaks in the GPE handling. This change fixes potential memory leaks in the error paths of the GPE handling code. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index c8a1f7d..1979a25 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -522,6 +522,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { + ACPI_FREE(local_gpe_event_info); return_VOID; } -- cgit v0.10.2 From e07fcfd89f9bbbc5f655b85b70e6f9b0bb626bac Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:45 +0800 Subject: ACPICA: Hardcode access width for the reset register. The ACPI spec requires the reset register width to be 8, so we now hardcode it and ignore the FADT value. This provides/maintains compatibility with other ACPI implementations that have allowed BIOS code with bad register width values to go unnoticed. Matthew Garett, Bob Moore, Lv Zheng. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index f81fb06..d3682c2 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -83,11 +83,17 @@ acpi_status acpi_reset(void) * For I/O space, write directly to the OSL. This bypasses the port * validation mechanism, which may block a valid write to the reset * register. - * Spec section 4.7.3.6 requires register width to be 8. + * + * NOTE: + * The ACPI spec requires the reset register width to be 8, so we + * hardcode it here and ignore the FADT value. This maintains + * compatibility with other ACPI implementations that have allowed + * BIOS code with bad register width values to go unnoticed. */ status = acpi_os_write_port((acpi_io_address) reset_reg->address, - acpi_gbl_FADT.reset_value, 8); + acpi_gbl_FADT.reset_value, + ACPI_RESET_REGISTER_WIDTH); } else { /* Write the reset value to the reset register */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index fed5af2..63909d9 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -349,6 +349,7 @@ typedef u32 acpi_physical_address; #define ACPI_PM1_REGISTER_WIDTH 16 #define ACPI_PM2_REGISTER_WIDTH 8 #define ACPI_PM_TIMER_WIDTH 32 +#define ACPI_RESET_REGISTER_WIDTH 8 /* Names within the namespace are 4 bytes long */ -- cgit v0.10.2 From ae7c4c878046b09c38d7c6cb49328df032f3d987 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 21 Oct 2013 10:52:15 +0900 Subject: ARM: EXYNOS: Use dev_err() instead of printk() for cpuidle driver Change raw printk() call to dev_err() to provide a better message to userspace so it can properly identify the device. Signed-off-by: Jingoo Han Signed-off-by: Rafael J. Wysocki diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 1bde6ad..6616e0f 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -206,7 +206,7 @@ static int __init exynos_cpuidle_probe(struct platform_device *pdev) ret = cpuidle_register_driver(&exynos4_idle_driver); if (ret) { - printk(KERN_ERR "CPUidle failed to register driver\n"); + dev_err(&pdev->dev, "failed to register cpuidle driver\n"); return ret; } @@ -220,7 +220,7 @@ static int __init exynos_cpuidle_probe(struct platform_device *pdev) ret = cpuidle_register_device(device); if (ret) { - printk(KERN_ERR "CPUidle register device failed\n"); + dev_err(&pdev->dev, "failed to register cpuidle device\n"); return ret; } } -- cgit v0.10.2 From f612a4fbdc8d6c77eb3721557f64bf0653ee5299 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 21 Oct 2013 10:53:03 +0900 Subject: ARM: EXYNOS: Remove incorrect __init annotation from cpuidle driver When platform_driver_probe() is not used, bind/unbind via sysfs is enabled. Thus, __init annotation should be removed from probe(). Also, this patch fixes section mismatch warning. Signed-off-by: Jingoo Han Signed-off-by: Rafael J. Wysocki diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 6616e0f..ddbfe87 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -193,7 +193,7 @@ static void __init exynos5_core_down_clk(void) __raw_writel(tmp, EXYNOS5_PWR_CTRL2); } -static int __init exynos_cpuidle_probe(struct platform_device *pdev) +static int exynos_cpuidle_probe(struct platform_device *pdev) { int cpu_id, ret; struct cpuidle_device *device; -- cgit v0.10.2 From e79a23c5b9870b7f80425793abeb10e57f7486d4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 30 Oct 2013 15:44:40 -0400 Subject: cpufreq: arm_big_little: add in-kernel switching (IKS) support This patch adds IKS (In Kernel Switcher) support to cpufreq driver. This creates a combined freq table for A7-A15 CPU pairs. A7 frequencies are virtualized and scaled down to half the actual frequencies to approximate a linear scale across the combined A7+A15 range. When the requested frequency change crosses the A7-A15 boundary a cluster switch is invoked. Based on earlier work from Sudeep KarkadaNagesha. Signed-off-by: Sudeep KarkadaNagesha Signed-off-by: Viresh Kumar Signed-off-by: Nicolas Pitre Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 163e337..9986f79 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -24,27 +24,165 @@ #include #include #include +#include #include #include #include #include #include +#include #include "arm_big_little.h" /* Currently we support only two clusters */ +#define A15_CLUSTER 0 +#define A7_CLUSTER 1 #define MAX_CLUSTERS 2 +#ifdef CONFIG_BL_SWITCHER +#define is_bL_switching_enabled() true +#else +#define is_bL_switching_enabled() false +#endif + +#define ACTUAL_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq << 1 : freq) +#define VIRT_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq >> 1 : freq) + static struct cpufreq_arm_bL_ops *arm_bL_ops; static struct clk *clk[MAX_CLUSTERS]; -static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; -static atomic_t cluster_usage[MAX_CLUSTERS] = {ATOMIC_INIT(0), ATOMIC_INIT(0)}; +static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1]; +static atomic_t cluster_usage[MAX_CLUSTERS + 1]; + +static unsigned int clk_big_min; /* (Big) clock frequencies */ +static unsigned int clk_little_max; /* Maximum clock frequency (Little) */ + +static DEFINE_PER_CPU(unsigned int, physical_cluster); +static DEFINE_PER_CPU(unsigned int, cpu_last_req_freq); + +static struct mutex cluster_lock[MAX_CLUSTERS]; + +static inline int raw_cpu_to_cluster(int cpu) +{ + return topology_physical_package_id(cpu); +} + +static inline int cpu_to_cluster(int cpu) +{ + return is_bL_switching_enabled() ? + MAX_CLUSTERS : raw_cpu_to_cluster(cpu); +} + +static unsigned int find_cluster_maxfreq(int cluster) +{ + int j; + u32 max_freq = 0, cpu_freq; + + for_each_online_cpu(j) { + cpu_freq = per_cpu(cpu_last_req_freq, j); + + if ((cluster == per_cpu(physical_cluster, j)) && + (max_freq < cpu_freq)) + max_freq = cpu_freq; + } + + pr_debug("%s: cluster: %d, max freq: %d\n", __func__, cluster, + max_freq); + + return max_freq; +} + +static unsigned int clk_get_cpu_rate(unsigned int cpu) +{ + u32 cur_cluster = per_cpu(physical_cluster, cpu); + u32 rate = clk_get_rate(clk[cur_cluster]) / 1000; + + /* For switcher we use virtual A7 clock rates */ + if (is_bL_switching_enabled()) + rate = VIRT_FREQ(cur_cluster, rate); + + pr_debug("%s: cpu: %d, cluster: %d, freq: %u\n", __func__, cpu, + cur_cluster, rate); + + return rate; +} + +static unsigned int bL_cpufreq_get_rate(unsigned int cpu) +{ + if (is_bL_switching_enabled()) { + pr_debug("%s: freq: %d\n", __func__, per_cpu(cpu_last_req_freq, + cpu)); + + return per_cpu(cpu_last_req_freq, cpu); + } else { + return clk_get_cpu_rate(cpu); + } +} -static unsigned int bL_cpufreq_get(unsigned int cpu) +static unsigned int +bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate) { - u32 cur_cluster = cpu_to_cluster(cpu); + u32 new_rate, prev_rate; + int ret; + bool bLs = is_bL_switching_enabled(); + + mutex_lock(&cluster_lock[new_cluster]); + + if (bLs) { + prev_rate = per_cpu(cpu_last_req_freq, cpu); + per_cpu(cpu_last_req_freq, cpu) = rate; + per_cpu(physical_cluster, cpu) = new_cluster; + + new_rate = find_cluster_maxfreq(new_cluster); + new_rate = ACTUAL_FREQ(new_cluster, new_rate); + } else { + new_rate = rate; + } + + pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d, freq: %d\n", + __func__, cpu, old_cluster, new_cluster, new_rate); + + ret = clk_set_rate(clk[new_cluster], new_rate * 1000); + if (WARN_ON(ret)) { + pr_err("clk_set_rate failed: %d, new cluster: %d\n", ret, + new_cluster); + if (bLs) { + per_cpu(cpu_last_req_freq, cpu) = prev_rate; + per_cpu(physical_cluster, cpu) = old_cluster; + } + + mutex_unlock(&cluster_lock[new_cluster]); + + return ret; + } + + mutex_unlock(&cluster_lock[new_cluster]); + + /* Recalc freq for old cluster when switching clusters */ + if (old_cluster != new_cluster) { + pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d\n", + __func__, cpu, old_cluster, new_cluster); + + /* Switch cluster */ + bL_switch_request(cpu, new_cluster); + + mutex_lock(&cluster_lock[old_cluster]); - return clk_get_rate(clk[cur_cluster]) / 1000; + /* Set freq of old cluster if there are cpus left on it */ + new_rate = find_cluster_maxfreq(old_cluster); + new_rate = ACTUAL_FREQ(old_cluster, new_rate); + + if (new_rate) { + pr_debug("%s: Updating rate of old cluster: %d, to freq: %d\n", + __func__, old_cluster, new_rate); + + if (clk_set_rate(clk[old_cluster], new_rate * 1000)) + pr_err("%s: clk_set_rate failed: %d, old cluster: %d\n", + __func__, ret, old_cluster); + } + mutex_unlock(&cluster_lock[old_cluster]); + } + + return 0; } /* Set clock frequency */ @@ -52,63 +190,164 @@ static int bL_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) { struct cpufreq_freqs freqs; - u32 cpu = policy->cpu, cur_cluster; + u32 cpu = policy->cpu, cur_cluster, new_cluster, actual_cluster; int ret = 0; - cur_cluster = cpu_to_cluster(policy->cpu); + cur_cluster = cpu_to_cluster(cpu); + new_cluster = actual_cluster = per_cpu(physical_cluster, cpu); - freqs.old = bL_cpufreq_get(policy->cpu); + freqs.old = bL_cpufreq_get_rate(cpu); freqs.new = freq_table[cur_cluster][index].frequency; pr_debug("%s: cpu: %d, cluster: %d, oldfreq: %d, target freq: %d, new freq: %d\n", __func__, cpu, cur_cluster, freqs.old, freqs.new, freqs.new); + if (is_bL_switching_enabled()) { + if ((actual_cluster == A15_CLUSTER) && + (freqs.new < clk_big_min)) { + new_cluster = A7_CLUSTER; + } else if ((actual_cluster == A7_CLUSTER) && + (freqs.new > clk_little_max)) { + new_cluster = A15_CLUSTER; + } + } + cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - ret = clk_set_rate(clk[cur_cluster], freqs.new * 1000); - if (ret) { - pr_err("clk_set_rate failed: %d\n", ret); + ret = bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs.new); + if (ret) freqs.new = freqs.old; - } cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); return ret; } +static inline u32 get_table_count(struct cpufreq_frequency_table *table) +{ + int count; + + for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++) + ; + + return count; +} + +/* get the minimum frequency in the cpufreq_frequency_table */ +static inline u32 get_table_min(struct cpufreq_frequency_table *table) +{ + int i; + uint32_t min_freq = ~0; + for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) + if (table[i].frequency < min_freq) + min_freq = table[i].frequency; + return min_freq; +} + +/* get the maximum frequency in the cpufreq_frequency_table */ +static inline u32 get_table_max(struct cpufreq_frequency_table *table) +{ + int i; + uint32_t max_freq = 0; + for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) + if (table[i].frequency > max_freq) + max_freq = table[i].frequency; + return max_freq; +} + +static int merge_cluster_tables(void) +{ + int i, j, k = 0, count = 1; + struct cpufreq_frequency_table *table; + + for (i = 0; i < MAX_CLUSTERS; i++) + count += get_table_count(freq_table[i]); + + table = kzalloc(sizeof(*table) * count, GFP_KERNEL); + if (!table) + return -ENOMEM; + + freq_table[MAX_CLUSTERS] = table; + + /* Add in reverse order to get freqs in increasing order */ + for (i = MAX_CLUSTERS - 1; i >= 0; i--) { + for (j = 0; freq_table[i][j].frequency != CPUFREQ_TABLE_END; + j++) { + table[k].frequency = VIRT_FREQ(i, + freq_table[i][j].frequency); + pr_debug("%s: index: %d, freq: %d\n", __func__, k, + table[k].frequency); + k++; + } + } + + table[k].driver_data = k; + table[k].frequency = CPUFREQ_TABLE_END; + + pr_debug("%s: End, table: %p, count: %d\n", __func__, table, k); + + return 0; +} + +static void _put_cluster_clk_and_freq_table(struct device *cpu_dev) +{ + u32 cluster = raw_cpu_to_cluster(cpu_dev->id); + + if (!freq_table[cluster]) + return; + + clk_put(clk[cluster]); + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]); + dev_dbg(cpu_dev, "%s: cluster: %d\n", __func__, cluster); +} + static void put_cluster_clk_and_freq_table(struct device *cpu_dev) { u32 cluster = cpu_to_cluster(cpu_dev->id); + int i; + + if (atomic_dec_return(&cluster_usage[cluster])) + return; + + if (cluster < MAX_CLUSTERS) + return _put_cluster_clk_and_freq_table(cpu_dev); - if (!atomic_dec_return(&cluster_usage[cluster])) { - clk_put(clk[cluster]); - dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]); - dev_dbg(cpu_dev, "%s: cluster: %d\n", __func__, cluster); + for_each_present_cpu(i) { + struct device *cdev = get_cpu_device(i); + if (!cdev) { + pr_err("%s: failed to get cpu%d device\n", __func__, i); + return; + } + + _put_cluster_clk_and_freq_table(cdev); } + + /* free virtual table */ + kfree(freq_table[cluster]); } -static int get_cluster_clk_and_freq_table(struct device *cpu_dev) +static int _get_cluster_clk_and_freq_table(struct device *cpu_dev) { - u32 cluster = cpu_to_cluster(cpu_dev->id); + u32 cluster = raw_cpu_to_cluster(cpu_dev->id); char name[14] = "cpu-cluster."; int ret; - if (atomic_inc_return(&cluster_usage[cluster]) != 1) + if (freq_table[cluster]) return 0; ret = arm_bL_ops->init_opp_table(cpu_dev); if (ret) { dev_err(cpu_dev, "%s: init_opp_table failed, cpu: %d, err: %d\n", __func__, cpu_dev->id, ret); - goto atomic_dec; + goto out; } ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]); if (ret) { dev_err(cpu_dev, "%s: failed to init cpufreq table, cpu: %d, err: %d\n", __func__, cpu_dev->id, ret); - goto atomic_dec; + goto out; } name[12] = cluster + '0'; @@ -125,13 +364,72 @@ static int get_cluster_clk_and_freq_table(struct device *cpu_dev) ret = PTR_ERR(clk[cluster]); dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]); -atomic_dec: - atomic_dec(&cluster_usage[cluster]); +out: dev_err(cpu_dev, "%s: Failed to get data for cluster: %d\n", __func__, cluster); return ret; } +static int get_cluster_clk_and_freq_table(struct device *cpu_dev) +{ + u32 cluster = cpu_to_cluster(cpu_dev->id); + int i, ret; + + if (atomic_inc_return(&cluster_usage[cluster]) != 1) + return 0; + + if (cluster < MAX_CLUSTERS) { + ret = _get_cluster_clk_and_freq_table(cpu_dev); + if (ret) + atomic_dec(&cluster_usage[cluster]); + return ret; + } + + /* + * Get data for all clusters and fill virtual cluster with a merge of + * both + */ + for_each_present_cpu(i) { + struct device *cdev = get_cpu_device(i); + if (!cdev) { + pr_err("%s: failed to get cpu%d device\n", __func__, i); + return -ENODEV; + } + + ret = _get_cluster_clk_and_freq_table(cdev); + if (ret) + goto put_clusters; + } + + ret = merge_cluster_tables(); + if (ret) + goto put_clusters; + + /* Assuming 2 cluster, set clk_big_min and clk_little_max */ + clk_big_min = get_table_min(freq_table[0]); + clk_little_max = VIRT_FREQ(1, get_table_max(freq_table[1])); + + pr_debug("%s: cluster: %d, clk_big_min: %d, clk_little_max: %d\n", + __func__, cluster, clk_big_min, clk_little_max); + + return 0; + +put_clusters: + for_each_present_cpu(i) { + struct device *cdev = get_cpu_device(i); + if (!cdev) { + pr_err("%s: failed to get cpu%d device\n", __func__, i); + return -ENODEV; + } + + _put_cluster_clk_and_freq_table(cdev); + } + + atomic_dec(&cluster_usage[cluster]); + + return ret; +} + /* Per-CPU initialization */ static int bL_cpufreq_init(struct cpufreq_policy *policy) { @@ -158,13 +456,23 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy) return ret; } + if (cur_cluster < MAX_CLUSTERS) { + cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu)); + + per_cpu(physical_cluster, policy->cpu) = cur_cluster; + } else { + /* Assumption: during init, we are always running on A15 */ + per_cpu(physical_cluster, policy->cpu) = A15_CLUSTER; + } + if (arm_bL_ops->get_transition_latency) policy->cpuinfo.transition_latency = arm_bL_ops->get_transition_latency(cpu_dev); else policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu)); + if (is_bL_switching_enabled()) + per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu); dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu); return 0; @@ -194,7 +502,7 @@ static struct cpufreq_driver bL_cpufreq_driver = { CPUFREQ_HAVE_GOVERNOR_PER_POLICY, .verify = cpufreq_generic_frequency_table_verify, .target_index = bL_cpufreq_set_target, - .get = bL_cpufreq_get, + .get = bL_cpufreq_get_rate, .init = bL_cpufreq_init, .exit = bL_cpufreq_exit, .attr = cpufreq_generic_attr, @@ -202,7 +510,7 @@ static struct cpufreq_driver bL_cpufreq_driver = { int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) { - int ret; + int ret, i; if (arm_bL_ops) { pr_debug("%s: Already registered: %s, exiting\n", __func__, @@ -217,6 +525,9 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) arm_bL_ops = ops; + for (i = 0; i < MAX_CLUSTERS; i++) + mutex_init(&cluster_lock[i]); + ret = cpufreq_register_driver(&bL_cpufreq_driver); if (ret) { pr_info("%s: Failed registering platform driver: %s, err: %d\n", diff --git a/drivers/cpufreq/arm_big_little.h b/drivers/cpufreq/arm_big_little.h index 79b2ce1..70f18fc 100644 --- a/drivers/cpufreq/arm_big_little.h +++ b/drivers/cpufreq/arm_big_little.h @@ -34,11 +34,6 @@ struct cpufreq_arm_bL_ops { int (*init_opp_table)(struct device *cpu_dev); }; -static inline int cpu_to_cluster(int cpu) -{ - return topology_physical_package_id(cpu); -} - int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops); void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops); -- cgit v0.10.2 From 45cac118ffd7c9920b3d85bf551c2205674eb4f2 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 30 Oct 2013 15:44:41 -0400 Subject: cpufreq: arm_big_little: reconfigure switcher behavior at run time The b.L switcher can be turned on/off at run time. It is therefore necessary to change the cpufreq driver behavior accordingly. The driver must be unregistered/registered with the cpufreq core to reconfigure freq tables for the virtual or actual CPUs. This is accomplished via the b.L switcher notifier callback. Signed-off-by: Nicolas Pitre Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 9986f79..71f1af9 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -40,9 +40,12 @@ #define MAX_CLUSTERS 2 #ifdef CONFIG_BL_SWITCHER -#define is_bL_switching_enabled() true +static bool bL_switching_enabled; +#define is_bL_switching_enabled() bL_switching_enabled +#define set_switching_enabled(x) (bL_switching_enabled = (x)) #else #define is_bL_switching_enabled() false +#define set_switching_enabled(x) do { } while (0) #endif #define ACTUAL_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq << 1 : freq) @@ -508,6 +511,38 @@ static struct cpufreq_driver bL_cpufreq_driver = { .attr = cpufreq_generic_attr, }; +static int bL_cpufreq_switcher_notifier(struct notifier_block *nfb, + unsigned long action, void *_arg) +{ + pr_debug("%s: action: %ld\n", __func__, action); + + switch (action) { + case BL_NOTIFY_PRE_ENABLE: + case BL_NOTIFY_PRE_DISABLE: + cpufreq_unregister_driver(&bL_cpufreq_driver); + break; + + case BL_NOTIFY_POST_ENABLE: + set_switching_enabled(true); + cpufreq_register_driver(&bL_cpufreq_driver); + break; + + case BL_NOTIFY_POST_DISABLE: + set_switching_enabled(false); + cpufreq_register_driver(&bL_cpufreq_driver); + break; + + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + +static struct notifier_block bL_switcher_notifier = { + .notifier_call = bL_cpufreq_switcher_notifier, +}; + int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) { int ret, i; @@ -525,6 +560,9 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) arm_bL_ops = ops; + ret = bL_switcher_get_enabled(); + set_switching_enabled(ret); + for (i = 0; i < MAX_CLUSTERS; i++) mutex_init(&cluster_lock[i]); @@ -534,10 +572,17 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) __func__, ops->name, ret); arm_bL_ops = NULL; } else { - pr_info("%s: Registered platform driver: %s\n", __func__, - ops->name); + ret = bL_switcher_register_notifier(&bL_switcher_notifier); + if (ret) { + cpufreq_unregister_driver(&bL_cpufreq_driver); + arm_bL_ops = NULL; + } else { + pr_info("%s: Registered platform driver: %s\n", + __func__, ops->name); + } } + bL_switcher_put_enabled(); return ret; } EXPORT_SYMBOL_GPL(bL_cpufreq_register); @@ -550,7 +595,10 @@ void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops) return; } + bL_switcher_get_enabled(); + bL_switcher_unregister_notifier(&bL_switcher_notifier); cpufreq_unregister_driver(&bL_cpufreq_driver); + bL_switcher_put_enabled(); pr_info("%s: Un-registered platform driver: %s\n", __func__, arm_bL_ops->name); arm_bL_ops = NULL; -- cgit v0.10.2 From e0a261a207fb5bcbc6cc5db3b51a96d9cbe9b97e Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Wed, 30 Oct 2013 08:38:32 -0700 Subject: cpufreq/intel_pstate: Add static declarations to internal functions Fixes warnings reported by kbuild test robot sparse warnings: (new ones prefixed by >>) drivers/cpufreq/intel_pstate.c:729:6: sparse: symbol 'copy_pid_params' was not declared. Should it be static? drivers/cpufreq/intel_pstate.c:739:6: sparse: symbol 'copy_cpu_funcs' was not declared. Should it be static? Signed-off-by: Dirk Brandewie Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 27c2753..81e0062 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -761,7 +761,7 @@ static int intel_pstate_msrs_not_valid(void) return 0; } -void copy_pid_params(struct pstate_adjust_policy *policy) +static void copy_pid_params(struct pstate_adjust_policy *policy) { pid_params.sample_rate_ms = policy->sample_rate_ms; pid_params.p_gain_pct = policy->p_gain_pct; @@ -771,7 +771,7 @@ void copy_pid_params(struct pstate_adjust_policy *policy) pid_params.setpoint = policy->setpoint; } -void copy_cpu_funcs(struct pstate_funcs *funcs) +static void copy_cpu_funcs(struct pstate_funcs *funcs) { pstate_funcs.get_max = funcs->get_max; pstate_funcs.get_min = funcs->get_min; -- cgit v0.10.2 From 7dbf694db6ac7c759599316d50d7050efcbd512a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 29 Oct 2013 18:56:06 +0530 Subject: cpufreq: distinguish drivers that do asynchronous notifications There are few special cases like exynos5440 which doesn't send POSTCHANGE notification from their ->target() routine and call some kind of bottom halves for doing this work, work/tasklet/etc.. From which they finally send POSTCHANGE notification. Its better if we distinguish them from other cpufreq drivers in some way so that core can handle them specially. So this patch introduces another flag: CPUFREQ_ASYNC_NOTIFICATION, which will be set by such drivers. This also changes exynos5440-cpufreq.c and powernow-k8 in order to set this flag. Acked-by: Amit Daniel Kachhap Acked-by: Kukjin Kim Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index 1bf9b06..76bef8b 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -312,7 +312,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) } static struct cpufreq_driver exynos_driver = { - .flags = CPUFREQ_STICKY, + .flags = CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION, .verify = cpufreq_generic_frequency_table_verify, .target_index = exynos_target, .get = exynos_getspeed, diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 62a1ce4..0023c7d 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1204,6 +1204,7 @@ out: } static struct cpufreq_driver cpufreq_amd64_driver = { + .flags = CPUFREQ_ASYNC_NOTIFICATION, .verify = cpufreq_generic_frequency_table_verify, .target_index = powernowk8_target, .bios_limit = acpi_processor_get_bios_limit, diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 93a8c34..5bd6ab9 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -237,6 +237,13 @@ struct cpufreq_driver { */ #define CPUFREQ_HAVE_GOVERNOR_PER_POLICY (1 << 3) +/* + * Driver will do POSTCHANGE notifications from outside of their ->target() + * routine and so must set cpufreq_driver->flags with this flag, so that core + * can handle them specially. + */ +#define CPUFREQ_ASYNC_NOTIFICATION (1 << 4) + int cpufreq_register_driver(struct cpufreq_driver *driver_data); int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); -- cgit v0.10.2 From d4019f0a92ab802f385cc9c8ad3ab7b5449712cb Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 14 Aug 2013 19:38:24 +0530 Subject: cpufreq: move freq change notifications to cpufreq core Most of the drivers do following in their ->target_index() routines: struct cpufreq_freqs freqs; freqs.old = old freq... freqs.new = new freq... cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); /* Change rate here */ cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); This is replicated over all cpufreq drivers today and there doesn't exists a good enough reason why this shouldn't be moved to cpufreq core instead. There are few special cases though, like exynos5440, which doesn't do everything on the call to ->target_index() routine and call some kind of bottom halves for doing this work, work/tasklet/etc.. They may continue doing notification from their own code as flag: CPUFREQ_ASYNC_NOTIFICATION is already set for them. All drivers are also modified in this patch to avoid breaking 'git bisect', as double notification would happen otherwise. Acked-by: Hans-Christian Egtvedt Acked-by: Jesper Nilsson Acked-by: Linus Walleij Acked-by: Russell King Acked-by: Stephen Warren Tested-by: Andrew Lunn Tested-by: Nicolas Pitre Reviewed-by: Lan Tianyu Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 889cec0..3c060dd 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -428,14 +428,10 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, { struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); struct acpi_processor_performance *perf; - struct cpufreq_freqs freqs; struct drv_cmd cmd; unsigned int next_perf_state = 0; /* Index into perf table */ int result = 0; - pr_debug("acpi_cpufreq_target %d (%d)\n", - data->freq_table[index].frequency, policy->cpu); - if (unlikely(data == NULL || data->acpi_data == NULL || data->freq_table == NULL)) { return -ENODEV; @@ -483,23 +479,17 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, else cmd.mask = cpumask_of(policy->cpu); - freqs.old = perf->states[perf->state].core_frequency * 1000; - freqs.new = data->freq_table[index].frequency; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - drv_write(&cmd); if (acpi_pstate_strict) { - if (!check_freqs(cmd.mask, freqs.new, data)) { + if (!check_freqs(cmd.mask, data->freq_table[index].frequency, + data)) { pr_debug("acpi_cpufreq_target failed (%d)\n", policy->cpu); result = -EAGAIN; - freqs.new = freqs.old; } } - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - if (!result) perf->state = next_perf_state; diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 71f1af9..5519933 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -192,39 +192,25 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate) static int bL_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; u32 cpu = policy->cpu, cur_cluster, new_cluster, actual_cluster; - int ret = 0; + unsigned int freqs_new; cur_cluster = cpu_to_cluster(cpu); new_cluster = actual_cluster = per_cpu(physical_cluster, cpu); - freqs.old = bL_cpufreq_get_rate(cpu); - freqs.new = freq_table[cur_cluster][index].frequency; - - pr_debug("%s: cpu: %d, cluster: %d, oldfreq: %d, target freq: %d, new freq: %d\n", - __func__, cpu, cur_cluster, freqs.old, freqs.new, - freqs.new); + freqs_new = freq_table[cur_cluster][index].frequency; if (is_bL_switching_enabled()) { if ((actual_cluster == A15_CLUSTER) && - (freqs.new < clk_big_min)) { + (freqs_new < clk_big_min)) { new_cluster = A7_CLUSTER; } else if ((actual_cluster == A7_CLUSTER) && - (freqs.new > clk_little_max)) { + (freqs_new > clk_little_max)) { new_cluster = A15_CLUSTER; } } - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - - ret = bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs.new); - if (ret) - freqs.new = freqs.old; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - return ret; + return bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs_new); } static inline u32 get_table_count(struct cpufreq_frequency_table *table) diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c index 81d0752..856ad80 100644 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ b/drivers/cpufreq/at32ap-cpufreq.c @@ -37,27 +37,23 @@ static unsigned long loops_per_jiffy_ref; static int at32_set_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; + unsigned int old_freq, new_freq; - freqs.old = at32_get_speed(0); - freqs.new = freq_table[index].frequency; + old_freq = at32_get_speed(0); + new_freq = freq_table[index].frequency; if (!ref_freq) { - ref_freq = freqs.old; + ref_freq = old_freq; loops_per_jiffy_ref = boot_cpu_data.loops_per_jiffy; } - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - if (freqs.old < freqs.new) + if (old_freq < new_freq) boot_cpu_data.loops_per_jiffy = cpufreq_scale( - loops_per_jiffy_ref, ref_freq, freqs.new); - clk_set_rate(cpuclk, freqs.new * 1000); - if (freqs.new < freqs.old) + loops_per_jiffy_ref, ref_freq, new_freq); + clk_set_rate(cpuclk, new_freq * 1000); + if (new_freq < old_freq) boot_cpu_data.loops_per_jiffy = cpufreq_scale( - loops_per_jiffy_ref, ref_freq, freqs.new); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - pr_debug("cpufreq: set frequency %u Hz\n", freqs.new * 1000); + loops_per_jiffy_ref, ref_freq, new_freq); return 0; } diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c index 12528b2..e9e63fc 100644 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ b/drivers/cpufreq/blackfin-cpufreq.c @@ -132,27 +132,23 @@ static int bfin_target(struct cpufreq_policy *policy, unsigned int index) #ifndef CONFIG_BF60x unsigned int plldiv; #endif - struct cpufreq_freqs freqs; static unsigned long lpj_ref; static unsigned int lpj_ref_freq; + unsigned int old_freq, new_freq; int ret = 0; #if defined(CONFIG_CYCLES_CLOCKSOURCE) cycles_t cycles; #endif - freqs.old = bfin_getfreq_khz(0); - freqs.new = bfin_freq_table[index].frequency; + old_freq = bfin_getfreq_khz(0); + new_freq = bfin_freq_table[index].frequency; - pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n", - freqs.new, freqs.new, freqs.old); - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); #ifndef CONFIG_BF60x plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel; bfin_write_PLL_DIV(plldiv); #else - ret = cpu_set_cclk(policy->cpu, freqs.new * 1000); + ret = cpu_set_cclk(policy->cpu, new_freq * 1000); if (ret != 0) { WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret); return ret; @@ -168,17 +164,13 @@ static int bfin_target(struct cpufreq_policy *policy, unsigned int index) #endif if (!lpj_ref_freq) { lpj_ref = loops_per_jiffy; - lpj_ref_freq = freqs.old; + lpj_ref_freq = old_freq; } - if (freqs.new != freqs.old) { + if (new_freq != old_freq) { loops_per_jiffy = cpufreq_scale(lpj_ref, - lpj_ref_freq, freqs.new); + lpj_ref_freq, new_freq); } - /* TODO: just test case for cycles clock source, remove later */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - pr_debug("cpufreq: done\n"); return ret; } diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 4dbe7ef..d4585ce 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -37,20 +37,19 @@ static unsigned int cpu0_get_speed(unsigned int cpu) static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; struct dev_pm_opp *opp; unsigned long volt = 0, volt_old = 0, tol = 0; + unsigned int old_freq, new_freq; long freq_Hz, freq_exact; int ret; freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); if (freq_Hz < 0) freq_Hz = freq_table[index].frequency * 1000; - freq_exact = freq_Hz; - freqs.new = freq_Hz / 1000; - freqs.old = clk_get_rate(cpu_clk) / 1000; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + freq_exact = freq_Hz; + new_freq = freq_Hz / 1000; + old_freq = clk_get_rate(cpu_clk) / 1000; if (!IS_ERR(cpu_reg)) { rcu_read_lock(); @@ -58,9 +57,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index) if (IS_ERR(opp)) { rcu_read_unlock(); pr_err("failed to find OPP for %ld\n", freq_Hz); - freqs.new = freqs.old; - ret = PTR_ERR(opp); - goto post_notify; + return PTR_ERR(opp); } volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); @@ -69,16 +66,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index) } pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n", - freqs.old / 1000, volt_old ? volt_old / 1000 : -1, - freqs.new / 1000, volt ? volt / 1000 : -1); + old_freq / 1000, volt_old ? volt_old / 1000 : -1, + new_freq / 1000, volt ? volt / 1000 : -1); /* scaling up? scale voltage before frequency */ - if (!IS_ERR(cpu_reg) && freqs.new > freqs.old) { + if (!IS_ERR(cpu_reg) && new_freq > old_freq) { ret = regulator_set_voltage_tol(cpu_reg, volt, tol); if (ret) { pr_err("failed to scale voltage up: %d\n", ret); - freqs.new = freqs.old; - goto post_notify; + return ret; } } @@ -87,23 +83,18 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index) pr_err("failed to set clock rate: %d\n", ret); if (!IS_ERR(cpu_reg)) regulator_set_voltage_tol(cpu_reg, volt_old, tol); - freqs.new = freqs.old; - goto post_notify; + return ret; } /* scaling down? scale voltage after frequency */ - if (!IS_ERR(cpu_reg) && freqs.new < freqs.old) { + if (!IS_ERR(cpu_reg) && new_freq < old_freq) { ret = regulator_set_voltage_tol(cpu_reg, volt, tol); if (ret) { pr_err("failed to scale voltage down: %d\n", ret); - clk_set_rate(cpu_clk, freqs.old * 1000); - freqs.new = freqs.old; + clk_set_rate(cpu_clk, old_freq * 1000); } } -post_notify: - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return ret; } diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6c9cbb9..02d534d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1669,6 +1669,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, retval = cpufreq_driver->target(policy, target_freq, relation); else if (cpufreq_driver->target_index) { struct cpufreq_frequency_table *freq_table; + struct cpufreq_freqs freqs; + bool notify; int index; freq_table = cpufreq_frequency_get_table(policy->cpu); @@ -1684,10 +1686,42 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, goto out; } - if (freq_table[index].frequency == policy->cur) + if (freq_table[index].frequency == policy->cur) { retval = 0; - else - retval = cpufreq_driver->target_index(policy, index); + goto out; + } + + notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION); + + if (notify) { + freqs.old = policy->cur; + freqs.new = freq_table[index].frequency; + freqs.flags = 0; + + pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n", + __func__, policy->cpu, freqs.old, + freqs.new); + + cpufreq_notify_transition(policy, &freqs, + CPUFREQ_PRECHANGE); + } + + retval = cpufreq_driver->target_index(policy, index); + if (retval) + pr_err("%s: Failed to change cpu frequency: %d\n", + __func__, retval); + + if (notify) { + /* + * Notify with old freq in case we failed to change + * frequency + */ + if (retval) + freqs.new = freqs.old; + + cpufreq_notify_transition(policy, &freqs, + CPUFREQ_POSTCHANGE); + } } out: diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c index 841857c..8655904 100644 --- a/drivers/cpufreq/cris-artpec3-cpufreq.c +++ b/drivers/cpufreq/cris-artpec3-cpufreq.c @@ -29,15 +29,9 @@ static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu) static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state) { - struct cpufreq_freqs freqs; reg_clkgen_rw_clk_ctrl clk_ctrl; clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl); - freqs.old = cris_freq_get_cpu_frequency(policy->cpu); - freqs.new = cris_freq_table[state].frequency; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - local_irq_disable(); /* Even though we may be SMP they will share the same clock @@ -50,8 +44,6 @@ static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state) local_irq_enable(); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return 0; } diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c index c58811a..26d940d 100644 --- a/drivers/cpufreq/cris-etraxfs-cpufreq.c +++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c @@ -29,15 +29,9 @@ static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu) static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state) { - struct cpufreq_freqs freqs; reg_config_rw_clk_ctrl clk_ctrl; clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl); - freqs.old = cris_freq_get_cpu_frequency(policy->cpu); - freqs.new = cris_freq_table[state].frequency; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - local_irq_disable(); /* Even though we may be SMP they will share the same clock @@ -50,8 +44,6 @@ static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state) local_irq_enable(); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return 0; } diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c index 1f5d8a5..5e8a854 100644 --- a/drivers/cpufreq/davinci-cpufreq.c +++ b/drivers/cpufreq/davinci-cpufreq.c @@ -68,46 +68,36 @@ static unsigned int davinci_getspeed(unsigned int cpu) static int davinci_target(struct cpufreq_policy *policy, unsigned int idx) { - int ret = 0; - struct cpufreq_freqs freqs; struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; struct clk *armclk = cpufreq.armclk; + unsigned int old_freq, new_freq; + int ret = 0; - freqs.old = davinci_getspeed(0); - freqs.new = pdata->freq_table[idx].frequency; - - dev_dbg(cpufreq.dev, "transition: %u --> %u\n", freqs.old, freqs.new); - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + old_freq = davinci_getspeed(0); + new_freq = pdata->freq_table[idx].frequency; /* if moving to higher frequency, up the voltage beforehand */ - if (pdata->set_voltage && freqs.new > freqs.old) { + if (pdata->set_voltage && new_freq > old_freq) { ret = pdata->set_voltage(idx); if (ret) - goto out; + return ret; } ret = clk_set_rate(armclk, idx); if (ret) - goto out; + return ret; if (cpufreq.asyncclk) { ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate); if (ret) - goto out; + return ret; } /* if moving to lower freq, lower the voltage after lowering freq */ - if (pdata->set_voltage && freqs.new < freqs.old) + if (pdata->set_voltage && new_freq < old_freq) pdata->set_voltage(idx); -out: - if (ret) - freqs.new = freqs.old; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - return ret; + return 0; } static int davinci_cpu_init(struct cpufreq_policy *policy) diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c index 238b169..0e67ab9 100644 --- a/drivers/cpufreq/dbx500-cpufreq.c +++ b/drivers/cpufreq/dbx500-cpufreq.c @@ -22,28 +22,8 @@ static struct clk *armss_clk; static int dbx500_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; - int ret; - - freqs.old = policy->cur; - freqs.new = freq_table[index].frequency; - - /* pre-change notification */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - /* update armss clk frequency */ - ret = clk_set_rate(armss_clk, freqs.new * 1000); - - if (ret) { - pr_err("dbx500-cpufreq: Failed to set armss_clk to %d Hz: error %d\n", - freqs.new * 1000, ret); - freqs.new = freqs.old; - } - - /* post change notification */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - return ret; + return clk_set_rate(armss_clk, freq_table[index].frequency * 1000); } static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu) diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index b39c4ef..9012b8b 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -107,15 +107,9 @@ static int eps_set_state(struct eps_cpu_data *centaur, struct cpufreq_policy *policy, u32 dest_state) { - struct cpufreq_freqs freqs; u32 lo, hi; - int err = 0; int i; - freqs.old = eps_get(policy->cpu); - freqs.new = centaur->fsb * ((dest_state >> 8) & 0xff); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - /* Wait while CPU is busy */ rdmsr(MSR_IA32_PERF_STATUS, lo, hi); i = 0; @@ -124,8 +118,7 @@ static int eps_set_state(struct eps_cpu_data *centaur, rdmsr(MSR_IA32_PERF_STATUS, lo, hi); i++; if (unlikely(i > 64)) { - err = -ENODEV; - goto postchange; + return -ENODEV; } } /* Set new multiplier and voltage */ @@ -137,16 +130,10 @@ static int eps_set_state(struct eps_cpu_data *centaur, rdmsr(MSR_IA32_PERF_STATUS, lo, hi); i++; if (unlikely(i > 64)) { - err = -ENODEV; - goto postchange; + return -ENODEV; } } while (lo & ((1 << 16) | (1 << 17))); - /* Return current frequency */ -postchange: - rdmsr(MSR_IA32_PERF_STATUS, lo, hi); - freqs.new = centaur->fsb * ((lo >> 8) & 0xff); - #ifdef DEBUG { u8 current_multiplier, current_voltage; @@ -161,11 +148,7 @@ postchange: current_multiplier); } #endif - if (err) - freqs.new = freqs.old; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return err; + return 0; } static int eps_target(struct cpufreq_policy *policy, unsigned int index) diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index 4ab4153..de08acf 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c @@ -108,17 +108,6 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu) static int elanfreq_target(struct cpufreq_policy *policy, unsigned int state) { - struct cpufreq_freqs freqs; - - freqs.old = elanfreq_get_cpu_frequency(0); - freqs.new = elan_multiplier[state].clock; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - - printk(KERN_INFO "elanfreq: attempting to set frequency to %i kHz\n", - elan_multiplier[state].clock); - - /* * Access to the Elan's internal registers is indexed via * 0x22: Chip Setup & Control Register Index Register (CSCI) @@ -149,8 +138,6 @@ static int elanfreq_target(struct cpufreq_policy *policy, udelay(10000); local_irq_enable(); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return 0; } /* diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index 9982fcb..7b6dc06 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -25,7 +25,6 @@ static struct exynos_dvfs_info *exynos_info; static struct regulator *arm_regulator; -static struct cpufreq_freqs freqs; static unsigned int locking_frequency; static bool frequency_locked; @@ -59,18 +58,18 @@ static int exynos_cpufreq_scale(unsigned int target_freq) struct cpufreq_policy *policy = cpufreq_cpu_get(0); unsigned int arm_volt, safe_arm_volt = 0; unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz; + unsigned int old_freq; int index, old_index; int ret = 0; - freqs.old = policy->cur; - freqs.new = target_freq; + old_freq = policy->cur; /* * The policy max have been changed so that we cannot get proper * old_index with cpufreq_frequency_table_target(). Thus, ignore * policy and get the index from the raw freqeuncy table. */ - old_index = exynos_cpufreq_get_index(freqs.old); + old_index = exynos_cpufreq_get_index(old_freq); if (old_index < 0) { ret = old_index; goto out; @@ -95,17 +94,14 @@ static int exynos_cpufreq_scale(unsigned int target_freq) } arm_volt = volt_table[index]; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - /* When the new frequency is higher than current frequency */ - if ((freqs.new > freqs.old) && !safe_arm_volt) { + if ((target_freq > old_freq) && !safe_arm_volt) { /* Firstly, voltage up to increase frequency */ ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt); if (ret) { pr_err("%s: failed to set cpu voltage to %d\n", __func__, arm_volt); - freqs.new = freqs.old; - goto post_notify; + return ret; } } @@ -115,22 +111,15 @@ static int exynos_cpufreq_scale(unsigned int target_freq) if (ret) { pr_err("%s: failed to set cpu voltage to %d\n", __func__, safe_arm_volt); - freqs.new = freqs.old; - goto post_notify; + return ret; } } exynos_info->set_freq(old_index, index); -post_notify: - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - if (ret) - goto out; - /* When the new frequency is lower than current frequency */ - if ((freqs.new < freqs.old) || - ((freqs.new > freqs.old) && safe_arm_volt)) { + if ((target_freq < old_freq) || + ((target_freq > old_freq) && safe_arm_volt)) { /* down the voltage after frequency change */ ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt); @@ -142,7 +131,6 @@ post_notify: } out: - cpufreq_cpu_put(policy); return ret; diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index 4695fa2..53c6ac6 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -141,7 +141,6 @@ processor_set_freq ( { int ret = 0; u32 value = 0; - struct cpufreq_freqs cpufreq_freqs; cpumask_t saved_mask; int retval; @@ -168,13 +167,6 @@ processor_set_freq ( pr_debug("Transitioning from P%d to P%d\n", data->acpi_data.state, state); - /* cpufreq frequency struct */ - cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency; - cpufreq_freqs.new = data->freq_table[state].frequency; - - /* notify cpufreq */ - cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_PRECHANGE); - /* * First we write the target state's 'control' value to the * control_register. @@ -186,22 +178,11 @@ processor_set_freq ( ret = processor_set_pstate(value); if (ret) { - unsigned int tmp = cpufreq_freqs.new; - cpufreq_notify_transition(policy, &cpufreq_freqs, - CPUFREQ_POSTCHANGE); - cpufreq_freqs.new = cpufreq_freqs.old; - cpufreq_freqs.old = tmp; - cpufreq_notify_transition(policy, &cpufreq_freqs, - CPUFREQ_PRECHANGE); - cpufreq_notify_transition(policy, &cpufreq_freqs, - CPUFREQ_POSTCHANGE); printk(KERN_WARNING "Transition failed with error %d\n", ret); retval = -ENODEV; goto migrate_end; } - cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_POSTCHANGE); - data->acpi_data.state = state; retval = 0; diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 07af3b0..4b3f18e 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -42,14 +42,14 @@ static unsigned int imx6q_get_speed(unsigned int cpu) static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; struct dev_pm_opp *opp; unsigned long freq_hz, volt, volt_old; + unsigned int old_freq, new_freq; int ret; - freqs.new = freq_table[index].frequency; - freq_hz = freqs.new * 1000; - freqs.old = clk_get_rate(arm_clk) / 1000; + new_freq = freq_table[index].frequency; + freq_hz = new_freq * 1000; + old_freq = clk_get_rate(arm_clk) / 1000; rcu_read_lock(); opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); @@ -64,26 +64,23 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) volt_old = regulator_get_voltage(arm_reg); dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", - freqs.old / 1000, volt_old / 1000, - freqs.new / 1000, volt / 1000); - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + old_freq / 1000, volt_old / 1000, + new_freq / 1000, volt / 1000); /* scaling up? scale voltage before frequency */ - if (freqs.new > freqs.old) { + if (new_freq > old_freq) { ret = regulator_set_voltage_tol(arm_reg, volt, 0); if (ret) { dev_err(cpu_dev, "failed to scale vddarm up: %d\n", ret); - freqs.new = freqs.old; - goto post_notify; + return ret; } /* * Need to increase vddpu and vddsoc for safety * if we are about to run at 1.2 GHz. */ - if (freqs.new == FREQ_1P2_GHZ / 1000) { + if (new_freq == FREQ_1P2_GHZ / 1000) { regulator_set_voltage_tol(pu_reg, PU_SOC_VOLTAGE_HIGH, 0); regulator_set_voltage_tol(soc_reg, @@ -103,21 +100,20 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) clk_set_parent(step_clk, pll2_pfd2_396m_clk); clk_set_parent(pll1_sw_clk, step_clk); if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { - clk_set_rate(pll1_sys_clk, freqs.new * 1000); + clk_set_rate(pll1_sys_clk, new_freq * 1000); clk_set_parent(pll1_sw_clk, pll1_sys_clk); } /* Ensure the arm clock divider is what we expect */ - ret = clk_set_rate(arm_clk, freqs.new * 1000); + ret = clk_set_rate(arm_clk, new_freq * 1000); if (ret) { dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); regulator_set_voltage_tol(arm_reg, volt_old, 0); - freqs.new = freqs.old; - goto post_notify; + return ret; } /* scaling down? scale voltage after frequency */ - if (freqs.new < freqs.old) { + if (new_freq < old_freq) { ret = regulator_set_voltage_tol(arm_reg, volt, 0); if (ret) { dev_warn(cpu_dev, @@ -125,7 +121,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) ret = 0; } - if (freqs.old == FREQ_1P2_GHZ / 1000) { + if (old_freq == FREQ_1P2_GHZ / 1000) { regulator_set_voltage_tol(pu_reg, PU_SOC_VOLTAGE_NORMAL, 0); regulator_set_voltage_tol(soc_reg, @@ -133,10 +129,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) } } -post_notify: - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - return ret; + return 0; } static int imx6q_cpufreq_init(struct cpufreq_policy *policy) diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index 0ae4dd7..0767a4e 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -58,48 +58,34 @@ static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu) static int kirkwood_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; unsigned int state = kirkwood_freq_table[index].driver_data; unsigned long reg; - freqs.old = kirkwood_cpufreq_get_cpu_frequency(0); - freqs.new = kirkwood_freq_table[index].frequency; + local_irq_disable(); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + /* Disable interrupts to the CPU */ + reg = readl_relaxed(priv.base); + reg |= CPU_SW_INT_BLK; + writel_relaxed(reg, priv.base); - dev_dbg(priv.dev, "Attempting to set frequency to %i KHz\n", - kirkwood_freq_table[index].frequency); - dev_dbg(priv.dev, "old frequency was %i KHz\n", - kirkwood_cpufreq_get_cpu_frequency(0)); - - if (freqs.old != freqs.new) { - local_irq_disable(); - - /* Disable interrupts to the CPU */ - reg = readl_relaxed(priv.base); - reg |= CPU_SW_INT_BLK; - writel_relaxed(reg, priv.base); - - switch (state) { - case STATE_CPU_FREQ: - clk_disable(priv.powersave_clk); - break; - case STATE_DDR_FREQ: - clk_enable(priv.powersave_clk); - break; - } + switch (state) { + case STATE_CPU_FREQ: + clk_disable(priv.powersave_clk); + break; + case STATE_DDR_FREQ: + clk_enable(priv.powersave_clk); + break; + } - /* Wait-for-Interrupt, while the hardware changes frequency */ - cpu_do_idle(); + /* Wait-for-Interrupt, while the hardware changes frequency */ + cpu_do_idle(); - /* Enable interrupts to the CPU */ - reg = readl_relaxed(priv.base); - reg &= ~CPU_SW_INT_BLK; - writel_relaxed(reg, priv.base); + /* Enable interrupts to the CPU */ + reg = readl_relaxed(priv.base); + reg &= ~CPU_SW_INT_BLK; + writel_relaxed(reg, priv.base); - local_irq_enable(); - } - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); + local_irq_enable(); return 0; } diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index 41a8e2c..a436092 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -57,7 +57,6 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy, { unsigned int cpu = policy->cpu; cpumask_t cpus_allowed; - struct cpufreq_freqs freqs; unsigned int freq; cpus_allowed = current->cpus_allowed; @@ -67,26 +66,11 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy, ((cpu_clock_freq / 1000) * loongson2_clockmod_table[index].driver_data) / 8; - pr_debug("cpufreq: requested frequency %u Hz\n", - loongson2_clockmod_table[index].frequency * 1000); - - freqs.old = loongson2_cpufreq_get(cpu); - freqs.new = freq; - freqs.flags = 0; - - /* notifiers */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - set_cpus_allowed_ptr(current, &cpus_allowed); /* setting the cpu frequency */ clk_set_rate(cpuclk, freq); - /* notifiers */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - pr_debug("cpufreq: set frequency %u kHz\n", freq); - return 0; } diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c index 4e2da08..c4dfa42 100644 --- a/drivers/cpufreq/maple-cpufreq.c +++ b/drivers/cpufreq/maple-cpufreq.c @@ -69,8 +69,6 @@ static struct cpufreq_frequency_table maple_cpu_freqs[] = { */ static int maple_pmode_cur; -static DEFINE_MUTEX(maple_switch_mutex); - static const u32 *maple_pmode_data; static int maple_pmode_max; @@ -133,21 +131,7 @@ static int maple_scom_query_freq(void) static int maple_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; - int rc; - - mutex_lock(&maple_switch_mutex); - - freqs.old = maple_cpu_freqs[maple_pmode_cur].frequency; - freqs.new = maple_cpu_freqs[index].frequency; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - rc = maple_scom_switch_freq(index); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - mutex_unlock(&maple_switch_mutex); - - return rc; + return maple_scom_switch_freq(index); } static unsigned int maple_cpufreq_get_speed(unsigned int cpu) diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index b551271..be6d143 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -53,15 +53,14 @@ static unsigned int omap_getspeed(unsigned int cpu) static int omap_target(struct cpufreq_policy *policy, unsigned int index) { - int r, ret = 0; - struct cpufreq_freqs freqs; struct dev_pm_opp *opp; unsigned long freq, volt = 0, volt_old = 0, tol = 0; + unsigned int old_freq, new_freq; - freqs.old = omap_getspeed(policy->cpu); - freqs.new = freq_table[index].frequency; + old_freq = omap_getspeed(policy->cpu); + new_freq = freq_table[index].frequency; - freq = freqs.new * 1000; + freq = new_freq * 1000; ret = clk_round_rate(mpu_clk, freq); if (IS_ERR_VALUE(ret)) { dev_warn(mpu_dev, @@ -77,7 +76,7 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int index) if (IS_ERR(opp)) { rcu_read_unlock(); dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", - __func__, freqs.new); + __func__, new_freq); return -EINVAL; } volt = dev_pm_opp_get_voltage(opp); @@ -87,43 +86,32 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int index) } dev_dbg(mpu_dev, "cpufreq-omap: %u MHz, %ld mV --> %u MHz, %ld mV\n", - freqs.old / 1000, volt_old ? volt_old / 1000 : -1, - freqs.new / 1000, volt ? volt / 1000 : -1); - - /* notifiers */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + old_freq / 1000, volt_old ? volt_old / 1000 : -1, + new_freq / 1000, volt ? volt / 1000 : -1); /* scaling up? scale voltage before frequency */ - if (mpu_reg && (freqs.new > freqs.old)) { + if (mpu_reg && (new_freq > old_freq)) { r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol); if (r < 0) { dev_warn(mpu_dev, "%s: unable to scale voltage up.\n", __func__); - freqs.new = freqs.old; - goto done; + return r; } } - ret = clk_set_rate(mpu_clk, freqs.new * 1000); + ret = clk_set_rate(mpu_clk, new_freq * 1000); /* scaling down? scale voltage after frequency */ - if (mpu_reg && (freqs.new < freqs.old)) { + if (mpu_reg && (new_freq < old_freq)) { r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol); if (r < 0) { dev_warn(mpu_dev, "%s: unable to scale voltage down.\n", __func__); - ret = clk_set_rate(mpu_clk, freqs.old * 1000); - freqs.new = freqs.old; - goto done; + clk_set_rate(mpu_clk, old_freq * 1000); + return r; } } - freqs.new = omap_getspeed(policy->cpu); - -done: - /* notifiers */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return ret; } diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 3c23053..3d1cba9 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -107,15 +107,8 @@ static struct cpufreq_frequency_table p4clockmod_table[] = { static int cpufreq_p4_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; int i; - freqs.old = cpufreq_p4_get(policy->cpu); - freqs.new = stock_freq * p4clockmod_table[index].driver_data / 8; - - /* notifiers */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - /* run on each logical CPU, * see section 13.15.3 of IA32 Intel Architecture Software * Developer's Manual, Volume 3 @@ -123,9 +116,6 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, unsigned int index) for_each_cpu(i, policy->cpus) cpufreq_p4_setdc(i, p4clockmod_table[index].driver_data); - /* notifiers */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return 0; } diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index 17424dd..1c33136 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c @@ -51,8 +51,6 @@ static void __iomem *sdcpwr_mapbase; static void __iomem *sdcasr_mapbase; -static DEFINE_MUTEX(pas_switch_mutex); - /* Current astate, is used when waking up from power savings on * one core, in case the other core has switched states during * the idle time. @@ -242,15 +240,8 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy) static int pas_cpufreq_target(struct cpufreq_policy *policy, unsigned int pas_astate_new) { - struct cpufreq_freqs freqs; int i; - freqs.old = policy->cur; - freqs.new = pas_freqs[pas_astate_new].frequency; - - mutex_lock(&pas_switch_mutex); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", policy->cpu, pas_freqs[pas_astate_new].frequency, @@ -261,10 +252,7 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy, for_each_online_cpu(i) set_astate(i, pas_astate_new); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - mutex_unlock(&pas_switch_mutex); - - ppc_proc_freq = freqs.new * 1000ul; + ppc_proc_freq = pas_freqs[pas_astate_new].frequency * 1000ul; return 0; } diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index 05f705e1..cf55d20 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -331,21 +331,11 @@ static int pmu_set_cpu_speed(int low_speed) return 0; } -static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode, - int notify) +static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode) { - struct cpufreq_freqs freqs; unsigned long l3cr; static unsigned long prev_l3cr; - freqs.old = cur_freq; - freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; - - if (freqs.old == freqs.new) - return 0; - - if (notify) - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); if (speed_mode == CPUFREQ_LOW && cpu_has_feature(CPU_FTR_L3CR)) { l3cr = _get_L3CR(); @@ -361,8 +351,6 @@ static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode, if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) _set_L3CR(prev_l3cr); } - if (notify) - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; return 0; @@ -378,7 +366,7 @@ static int pmac_cpufreq_target( struct cpufreq_policy *policy, { int rc; - rc = do_set_cpu_speed(policy, index, 1); + rc = do_set_cpu_speed(policy, index); ppc_proc_freq = cur_freq * 1000ul; return rc; @@ -420,7 +408,7 @@ static int pmac_cpufreq_suspend(struct cpufreq_policy *policy) no_schedule = 1; sleep_freq = cur_freq; if (cur_freq == low_freq && !is_pmu_based) - do_set_cpu_speed(policy, CPUFREQ_HIGH, 0); + do_set_cpu_speed(policy, CPUFREQ_HIGH); return 0; } @@ -437,7 +425,7 @@ static int pmac_cpufreq_resume(struct cpufreq_policy *policy) * probably high speed due to our suspend() routine */ do_set_cpu_speed(policy, sleep_freq == low_freq ? - CPUFREQ_LOW : CPUFREQ_HIGH, 0); + CPUFREQ_LOW : CPUFREQ_HIGH); ppc_proc_freq = cur_freq * 1000ul; diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 234b598..6a338f8 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -79,8 +79,6 @@ static void (*g5_switch_volt)(int speed_mode); static int (*g5_switch_freq)(int speed_mode); static int (*g5_query_freq)(void); -static DEFINE_MUTEX(g5_switch_mutex); - static unsigned long transition_latency; #ifdef CONFIG_PMAC_SMU @@ -314,21 +312,7 @@ static int g5_pfunc_query_freq(void) static int g5_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; - int rc; - - mutex_lock(&g5_switch_mutex); - - freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; - freqs.new = g5_cpu_freqs[index].frequency; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - rc = g5_switch_freq(index); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - mutex_unlock(&g5_switch_mutex); - - return rc; + return g5_switch_freq(index); } static unsigned int g5_cpufreq_get_speed(unsigned int cpu) diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c index 79d8e9c..3f7be46 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/ppc-corenet-cpufreq.c @@ -69,8 +69,6 @@ static const struct soc_data sdata[] = { static u32 min_cpufreq; static const u32 *fmask; -/* serialize frequency changes */ -static DEFINE_MUTEX(cpufreq_lock); static DEFINE_PER_CPU(struct cpu_data *, cpu_data); /* cpumask in a cluster */ @@ -253,26 +251,11 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy) static int corenet_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; struct clk *parent; - int ret; struct cpu_data *data = per_cpu(cpu_data, policy->cpu); - freqs.old = policy->cur; - freqs.new = data->table[index].frequency; - - mutex_lock(&cpufreq_lock); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - parent = of_clk_get(data->parent, data->table[index].driver_data); - ret = clk_set_parent(data->clk, parent); - if (ret) - freqs.new = freqs.old; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - mutex_unlock(&cpufreq_lock); - - return ret; + return clk_set_parent(data->clk, parent); } static struct cpufreq_driver ppc_corenet_cpufreq_driver = { diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c index 52f707d..e42ca9c 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq.c @@ -30,9 +30,6 @@ #include "ppc_cbe_cpufreq.h" -static DEFINE_MUTEX(cbe_switch_mutex); - - /* the CBE supports an 8 step frequency scaling */ static struct cpufreq_frequency_table cbe_freqs[] = { {1, 0}, @@ -131,27 +128,13 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int cbe_pmode_new) { - int rc; - struct cpufreq_freqs freqs; - - freqs.old = policy->cur; - freqs.new = cbe_freqs[cbe_pmode_new].frequency; - - mutex_lock(&cbe_switch_mutex); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - pr_debug("setting frequency for cpu %d to %d kHz, " \ "1/%d of max frequency\n", policy->cpu, cbe_freqs[cbe_pmode_new].frequency, cbe_freqs[cbe_pmode_new].driver_data); - rc = set_pmode(policy->cpu, cbe_pmode_new); - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - mutex_unlock(&cbe_switch_mutex); - - return rc; + return set_pmode(policy->cpu, cbe_pmode_new); } static struct cpufreq_driver cbe_cpufreq_driver = { diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index 183bc13..0a0f436 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -271,7 +271,6 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx) { struct cpufreq_frequency_table *pxa_freqs_table; pxa_freqs_t *pxa_freq_settings; - struct cpufreq_freqs freqs; unsigned long flags; unsigned int new_freq_cpu, new_freq_mem; unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg; @@ -282,24 +281,17 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx) new_freq_cpu = pxa_freq_settings[idx].khz; new_freq_mem = pxa_freq_settings[idx].membus; - freqs.old = policy->cur; - freqs.new = new_freq_cpu; if (freq_debug) pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n", - freqs.new / 1000, (pxa_freq_settings[idx].div2) ? + new_freq_cpu / 1000, (pxa_freq_settings[idx].div2) ? (new_freq_mem / 2000) : (new_freq_mem / 1000)); - if (vcc_core && freqs.new > freqs.old) + if (vcc_core && new_freq_cpu > policy->cur) { ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]); - if (ret) - return ret; - /* - * Tell everyone what we're about to do... - * you should add a notify client with any platform specific - * Vcc changing capability - */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + if (ret) + return ret; + } /* Calculate the next MDREFR. If we're slowing down the SDRAM clock * we need to preset the smaller DRI before the change. If we're @@ -350,13 +342,6 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx) local_irq_restore(flags); /* - * Tell everyone what we've just done... - * you should add a notify client with any platform specific - * SDRAM refresh timer adjustments - */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - /* * Even if voltage setting fails, we don't report it, as the frequency * change succeeded. The voltage reduction is not a critical failure, * only power savings will suffer from this. @@ -365,7 +350,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx) * bug is triggered (seems a deadlock). Should anybody find out where, * the "return 0" should become a "return ret". */ - if (vcc_core && freqs.new < freqs.old) + if (vcc_core && new_freq_cpu < policy->cur) ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]); return 0; diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c index 132e37d..9384004 100644 --- a/drivers/cpufreq/pxa3xx-cpufreq.c +++ b/drivers/cpufreq/pxa3xx-cpufreq.c @@ -158,7 +158,6 @@ static unsigned int pxa3xx_cpufreq_get(unsigned int cpu) static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, unsigned int index) { struct pxa3xx_freq_info *next; - struct cpufreq_freqs freqs; unsigned long flags; if (policy->cpu != 0) @@ -166,22 +165,11 @@ static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, unsigned int index) next = &pxa3xx_freqs[index]; - freqs.old = policy->cur; - freqs.new = next->cpufreq_mhz * 1000; - - pr_debug("CPU frequency from %d MHz to %d MHz%s\n", - freqs.old / 1000, freqs.new / 1000, - (freqs.old == freqs.new) ? " (skipped)" : ""); - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - local_irq_save(flags); __update_core_freq(next); __update_bus_freq(next); local_irq_restore(flags); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return 0; } diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index 4188acc..8d904a0 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -220,7 +220,7 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) { struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; - struct cpufreq_freqs freqs; + unsigned int new_freq; int idx, ret, to_dvs = 0; mutex_lock(&cpufreq_lock); @@ -237,25 +237,14 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy, goto out; } - freqs.flags = 0; - freqs.old = s3c_freq->is_dvs ? FREQ_DVS - : clk_get_rate(s3c_freq->armclk) / 1000; - /* When leavin dvs mode, always switch the armdiv to the hclk rate * The S3C2416 has stability issues when switching directly to * higher frequencies. */ - freqs.new = (s3c_freq->is_dvs && !to_dvs) + new_freq = (s3c_freq->is_dvs && !to_dvs) ? clk_get_rate(s3c_freq->hclk) / 1000 : s3c_freq->freq_table[index].frequency; - pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new); - - if (!to_dvs && freqs.old == freqs.new) - goto out; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - if (to_dvs) { pr_debug("cpufreq: enter dvs\n"); ret = s3c2416_cpufreq_enter_dvs(s3c_freq, idx); @@ -263,12 +252,10 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy, pr_debug("cpufreq: leave dvs\n"); ret = s3c2416_cpufreq_leave_dvs(s3c_freq, idx); } else { - pr_debug("cpufreq: change armdiv to %dkHz\n", freqs.new); - ret = s3c2416_cpufreq_set_armdiv(s3c_freq, freqs.new); + pr_debug("cpufreq: change armdiv to %dkHz\n", new_freq); + ret = s3c2416_cpufreq_set_armdiv(s3c_freq, new_freq); } - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - out: mutex_unlock(&cpufreq_lock); diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c index 8bdcf32..67e302e 100644 --- a/drivers/cpufreq/s3c64xx-cpufreq.c +++ b/drivers/cpufreq/s3c64xx-cpufreq.c @@ -65,54 +65,46 @@ static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu) static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) { - int ret; - struct cpufreq_freqs freqs; struct s3c64xx_dvfs *dvfs; + unsigned int old_freq, new_freq; + int ret; - freqs.old = clk_get_rate(armclk) / 1000; - freqs.new = s3c64xx_freq_table[index].frequency; - freqs.flags = 0; + old_freq = clk_get_rate(armclk) / 1000; + new_freq = s3c64xx_freq_table[index].frequency; dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[index].driver_data]; - pr_debug("Transition %d-%dkHz\n", freqs.old, freqs.new); - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - #ifdef CONFIG_REGULATOR - if (vddarm && freqs.new > freqs.old) { + if (vddarm && new_freq > old_freq) { ret = regulator_set_voltage(vddarm, dvfs->vddarm_min, dvfs->vddarm_max); if (ret != 0) { pr_err("Failed to set VDDARM for %dkHz: %d\n", - freqs.new, ret); - freqs.new = freqs.old; - goto post_notify; + new_freq, ret); + return ret; } } #endif - ret = clk_set_rate(armclk, freqs.new * 1000); + ret = clk_set_rate(armclk, new_freq * 1000); if (ret < 0) { pr_err("Failed to set rate %dkHz: %d\n", - freqs.new, ret); - freqs.new = freqs.old; + new_freq, ret); + return ret; } -post_notify: - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - if (ret) - goto err; - #ifdef CONFIG_REGULATOR - if (vddarm && freqs.new < freqs.old) { + if (vddarm && new_freq < old_freq) { ret = regulator_set_voltage(vddarm, dvfs->vddarm_min, dvfs->vddarm_max); if (ret != 0) { pr_err("Failed to set VDDARM for %dkHz: %d\n", - freqs.new, ret); - goto err_clk; + new_freq, ret); + if (clk_set_rate(armclk, old_freq * 1000) < 0) + pr_err("Failed to restore original clock rate\n"); + + return ret; } } #endif @@ -121,14 +113,6 @@ post_notify: clk_get_rate(armclk) / 1000); return 0; - -err_clk: - if (clk_set_rate(armclk, freqs.old * 1000) < 0) - pr_err("Failed to restore original clock rate\n"); -err: - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - return ret; } #ifdef CONFIG_REGULATOR diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 5978b94..e3973da 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -26,7 +26,6 @@ static struct clk *cpu_clk; static struct clk *dmc0_clk; static struct clk *dmc1_clk; -static struct cpufreq_freqs freqs; static DEFINE_MUTEX(set_freq_lock); /* APLL M,P,S values for 1G/800Mhz */ @@ -179,6 +178,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) unsigned int priv_index; unsigned int pll_changing = 0; unsigned int bus_speed_changing = 0; + unsigned int old_freq, new_freq; int arm_volt, int_volt; int ret = 0; @@ -193,12 +193,12 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) goto exit; } - freqs.old = s5pv210_getspeed(0); - freqs.new = s5pv210_freq_table[index].frequency; + old_freq = s5pv210_getspeed(0); + new_freq = s5pv210_freq_table[index].frequency; /* Finding current running level index */ if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, - freqs.old, CPUFREQ_RELATION_H, + old_freq, CPUFREQ_RELATION_H, &priv_index)) { ret = -EINVAL; goto exit; @@ -207,7 +207,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) arm_volt = dvs_conf[index].arm_volt; int_volt = dvs_conf[index].int_volt; - if (freqs.new > freqs.old) { + if (new_freq > old_freq) { ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt_max); if (ret) @@ -219,8 +219,6 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) goto exit; } - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - /* Check if there need to change PLL */ if ((index == L0) || (priv_index == L0)) pll_changing = 1; @@ -431,9 +429,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) } } - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - - if (freqs.new < freqs.old) { + if (new_freq < old_freq) { regulator_set_voltage(int_regulator, int_volt, int_volt_max); diff --git a/drivers/cpufreq/sa1100-cpufreq.c b/drivers/cpufreq/sa1100-cpufreq.c index b0da1fe..623da74 100644 --- a/drivers/cpufreq/sa1100-cpufreq.c +++ b/drivers/cpufreq/sa1100-cpufreq.c @@ -180,22 +180,17 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed) static int sa1100_target(struct cpufreq_policy *policy, unsigned int ppcr) { unsigned int cur = sa11x0_getspeed(0); - struct cpufreq_freqs freqs; + unsigned int new_freq; - freqs.old = cur; - freqs.new = sa11x0_freq_table[ppcr].frequency; + new_freq = sa11x0_freq_table[ppcr].frequency; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - - if (freqs.new > cur) - sa1100_update_dram_timings(cur, freqs.new); + if (new_freq > cur) + sa1100_update_dram_timings(cur, new_freq); PPCR = ppcr; - if (freqs.new < cur) - sa1100_update_dram_timings(cur, freqs.new); - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); + if (new_freq < cur) + sa1100_update_dram_timings(cur, new_freq); return 0; } diff --git a/drivers/cpufreq/sa1110-cpufreq.c b/drivers/cpufreq/sa1110-cpufreq.c index 55b1818c..2c2b2e6 100644 --- a/drivers/cpufreq/sa1110-cpufreq.c +++ b/drivers/cpufreq/sa1110-cpufreq.c @@ -232,15 +232,11 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram) static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr) { struct sdram_params *sdram = &sdram_params; - struct cpufreq_freqs freqs; struct sdram_info sd; unsigned long flags; unsigned int unused; - freqs.old = sa11x0_getspeed(0); - freqs.new = sa11x0_freq_table[ppcr].frequency; - - sdram_calculate_timing(&sd, freqs.new, sdram); + sdram_calculate_timing(&sd, sa11x0_freq_table[ppcr].frequency, sdram); #if 0 /* @@ -259,8 +255,6 @@ static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr) sd.mdcas[2] = 0xaaaaaaaa; #endif - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - /* * The clock could be going away for some time. Set the SDRAMs * to refresh rapidly (every 64 memory clock cycles). To get @@ -305,9 +299,7 @@ static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr) /* * Now, return the SDRAM refresh back to normal. */ - sdram_update_refresh(freqs.new, sdram); - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); + sdram_update_refresh(sa11x0_freq_table[ppcr].frequency, sdram); return 0; } diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index 6c86452..6adb354 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c @@ -56,17 +56,8 @@ static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu) static int sc520_freq_target(struct cpufreq_policy *policy, unsigned int state) { - struct cpufreq_freqs freqs; u8 clockspeed_reg; - freqs.old = sc520_freq_get_cpu_frequency(0); - freqs.new = sc520_freq_table[state].frequency; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - - pr_debug("attempting to set frequency to %i kHz\n", - sc520_freq_table[state].frequency); - local_irq_disable(); clockspeed_reg = *cpuctl & ~0x03; @@ -74,8 +65,6 @@ static int sc520_freq_target(struct cpufreq_policy *policy, unsigned int state) local_irq_enable(); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return 0; } diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c index 3bf5b8f..62aa23e 100644 --- a/drivers/cpufreq/sparc-us2e-cpufreq.c +++ b/drivers/cpufreq/sparc-us2e-cpufreq.c @@ -251,7 +251,6 @@ static int us2e_freq_target(struct cpufreq_policy *policy, unsigned int index) unsigned long new_bits, new_freq; unsigned long clock_tick, divisor, old_divisor, estar; cpumask_t cpus_allowed; - struct cpufreq_freqs freqs; cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); set_cpus_allowed_ptr(current, cpumask_of(cpu)); @@ -265,16 +264,10 @@ static int us2e_freq_target(struct cpufreq_policy *policy, unsigned int index) old_divisor = estar_to_divisor(estar); - freqs.old = clock_tick / old_divisor; - freqs.new = new_freq; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - if (old_divisor != divisor) us2e_transition(estar, new_bits, clock_tick * 1000, old_divisor, divisor); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - set_cpus_allowed_ptr(current, &cpus_allowed); return 0; diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c index 2e54d55..724ffbd 100644 --- a/drivers/cpufreq/sparc-us3-cpufreq.c +++ b/drivers/cpufreq/sparc-us3-cpufreq.c @@ -98,7 +98,6 @@ static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index) unsigned int cpu = policy->cpu; unsigned long new_bits, new_freq, reg; cpumask_t cpus_allowed; - struct cpufreq_freqs freqs; cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); set_cpus_allowed_ptr(current, cpumask_of(cpu)); @@ -124,16 +123,10 @@ static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index) reg = read_safari_cfg(); - freqs.old = get_current_freq(cpu, reg); - freqs.new = new_freq; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - reg &= ~SAFARI_CFG_DIV_MASK; reg |= new_bits; write_safari_cfg(reg); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - set_cpus_allowed_ptr(current, &cpus_allowed); return 0; diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index 11a65be..d02ccd1 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -107,12 +107,10 @@ static int spear1340_set_cpu_rate(struct clk *sys_pclk, unsigned long newfreq) static int spear_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; long newfreq; struct clk *srcclk; int ret, mult = 1; - freqs.old = spear_cpufreq_get(0); newfreq = spear_cpufreq.freq_tbl[index].frequency * 1000; if (of_machine_is_compatible("st,spear1340")) { @@ -145,23 +143,14 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy, return newfreq; } - freqs.new = newfreq / 1000; - freqs.new /= mult; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - if (mult == 2) ret = spear1340_set_cpu_rate(srcclk, newfreq); else ret = clk_set_rate(spear_cpufreq.clk, newfreq); - /* Get current rate after clk_set_rate, in case of failure */ - if (ret) { + if (ret) pr_err("CPU Freq: cpu clk_set_rate failed: %d\n", ret); - freqs.new = clk_get_rate(spear_cpufreq.clk) / 1000; - } - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); return ret; } diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index c51ec8c..4e1daca 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -423,9 +423,8 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) static int centrino_target(struct cpufreq_policy *policy, unsigned int index) { unsigned int msr, oldmsr = 0, h = 0, cpu = policy->cpu; - struct cpufreq_freqs freqs; int retval = 0; - unsigned int j, first_cpu, tmp; + unsigned int j, first_cpu; struct cpufreq_frequency_table *op_points; cpumask_var_t covered_cpus; @@ -473,16 +472,6 @@ static int centrino_target(struct cpufreq_policy *policy, unsigned int index) goto out; } - freqs.old = extract_clock(oldmsr, cpu, 0); - freqs.new = extract_clock(msr, cpu, 0); - - pr_debug("target=%dkHz old=%d new=%d msr=%04x\n", - op_points->frequency, freqs.old, freqs.new, - msr); - - cpufreq_notify_transition(policy, &freqs, - CPUFREQ_PRECHANGE); - first_cpu = 0; /* all but 16 LSB are reserved, treat them with care */ oldmsr &= ~0xffff; @@ -497,8 +486,6 @@ static int centrino_target(struct cpufreq_policy *policy, unsigned int index) cpumask_set_cpu(j, covered_cpus); } - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - if (unlikely(retval)) { /* * We have failed halfway through the frequency change. @@ -509,12 +496,6 @@ static int centrino_target(struct cpufreq_policy *policy, unsigned int index) for_each_cpu(j, covered_cpus) wrmsr_on_cpu(j, MSR_IA32_PERF_CTL, oldmsr, h); - - tmp = freqs.new; - freqs.new = freqs.old; - freqs.old = tmp; - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); } retval = 0; diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index 707721e..7639b2b 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -258,21 +258,12 @@ static unsigned int speedstep_get(unsigned int cpu) static int speedstep_target(struct cpufreq_policy *policy, unsigned int index) { unsigned int policy_cpu; - struct cpufreq_freqs freqs; policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask); - freqs.old = speedstep_get(policy_cpu); - freqs.new = speedstep_freqs[index].frequency; - - pr_debug("transiting from %u to %u kHz\n", freqs.old, freqs.new); - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); smp_call_function_single(policy_cpu, _speedstep_set_state, &index, true); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); - return 0; } diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index 19446e4..0f5326d 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -241,14 +241,7 @@ static void speedstep_set_state(unsigned int state) */ static int speedstep_target(struct cpufreq_policy *policy, unsigned int index) { - struct cpufreq_freqs freqs; - - freqs.old = speedstep_freqs[speedstep_get_state()].frequency; - freqs.new = speedstep_freqs[index].frequency; - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); speedstep_set_state(index); - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); return 0; } diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra-cpufreq.c index bd7d89c..f42df7e 100644 --- a/drivers/cpufreq/tegra-cpufreq.c +++ b/drivers/cpufreq/tegra-cpufreq.c @@ -102,12 +102,8 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy, unsigned long rate) { int ret = 0; - struct cpufreq_freqs freqs; - freqs.old = tegra_getspeed(0); - freqs.new = rate; - - if (freqs.old == freqs.new) + if (tegra_getspeed(0) == rate) return ret; /* @@ -121,21 +117,10 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy, else clk_set_rate(emc_clk, 100000000); /* emc 50Mhz */ - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - -#ifdef CONFIG_CPU_FREQ_DEBUG - printk(KERN_DEBUG "cpufreq-tegra: transition: %u --> %u\n", - freqs.old, freqs.new); -#endif - - ret = tegra_cpu_clk_set_rate(freqs.new * 1000); - if (ret) { - pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n", - freqs.new); - freqs.new = freqs.old; - } - - cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); + ret = tegra_cpu_clk_set_rate(rate * 1000); + if (ret) + pr_err("cpu-tegra: Failed to set cpu frequency to %lu kHz\n", + rate); return ret; } -- cgit v0.10.2 From 839e928f5bbb695c31ddc23cf3fae3cf1c9e9f20 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:29:51 +0800 Subject: ACPICA: Add EXPORT_ACPI_INTERFACES macro to external interface modules. For Linux, there are no functional changes/binary generation differences introduced by this patch. This change adds a new macro to all files that contain external ACPICA interfaces. It can be detected and used by the host (via the host-specific header) for any special processing required for such modules. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 6f56146..6d88b13 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 7039606..39d06af 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "actables.h" diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 7662f1a..fab40d9 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acevents.h" diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 80cecf8..1bd3225 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index 2d7d22e..3c498dc 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index d3682c2..b156848 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index f2e669db..4895fca 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 481a6b4..a6e3bca 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index 83c1644..3a6d78a 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index c0853ef..94e961c 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index 94e3517..01e4769 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acresrc.h" diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index ad11162..2ad8532 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "actables.h" diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 0ba9e32..2620dbe 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index ffd0db5..1a67b39 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index 11e2e02..b3f31dd 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -41,7 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include #include #include "accommon.h" #include "acnamesp.h" diff --git a/drivers/acpi/acpica/utexcep.c b/drivers/acpi/acpica/utexcep.c index ff6d9e8..3cf7b59 100644 --- a/drivers/acpi/acpica/utexcep.c +++ b/drivers/acpi/acpica/utexcep.c @@ -41,8 +41,9 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#define EXPORT_ACPI_INTERFACES + #define ACPI_DEFINE_EXCEPTION_TABLE -#include #include #include "accommon.h" diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 046d5b0..4f59784 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -41,9 +41,9 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#define EXPORT_ACPI_INTERFACES #define DEFINE_ACPI_GLOBALS -#include #include #include "accommon.h" diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 03a211e..2178da8a 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acdebug.h" diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index e966a2e..f7edb88 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index 41ebaaf..dda18e6 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include +#define EXPORT_ACPI_INTERFACES + #include #include "accommon.h" #include "acevents.h" diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 7346a92..0e6e73c 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -74,7 +74,7 @@ #define acpi_spinlock spinlock_t * #define acpi_cpu_flags unsigned long -#else /* !__KERNEL__ */ +#else /* !__KERNEL__ */ #include #include @@ -102,7 +102,7 @@ #define __cdecl #endif -#endif /* __KERNEL__ */ +#endif /* __KERNEL__ */ /* Linux uses GCC */ @@ -183,6 +183,10 @@ static inline void acpi_os_free(void *a) lock ? AE_OK : AE_NO_MEMORY; \ }) -#endif /* __KERNEL__ */ +#ifdef EXPORT_ACPI_INTERFACES +#include +#endif + +#endif /* __KERNEL__ */ -#endif /* __ACLINUX_H__ */ +#endif /* __ACLINUX_H__ */ -- cgit v0.10.2 From bb1cab3d52375b5007645ca55d2b55167e5f757b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:29:57 +0800 Subject: ACPICA: Clarify ACPI_FREE_BUFFER usage. Add a comment to clarify reason for using ACPI_FREE_BUFFER directly instead of ACPI_FREE. In addition to that, change one instance in which ACPI_FREE_BUFFER() should be used instead of ACPI_FREE(). [rjw: Subject and changelog] Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index a6e3bca..ce2a845 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -139,7 +139,7 @@ acpi_evaluate_object_typed(acpi_handle handle, /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ - ACPI_FREE(return_buffer->pointer); + ACPI_FREE_BUFFER(*return_buffer); return_buffer->pointer = NULL; } diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 63909d9..0bb23e6 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -919,9 +919,13 @@ struct acpi_buffer { void *pointer; /* pointer to buffer */ }; -/* Free a buffer created in an struct acpi_buffer via ACPI_ALLOCATE_LOCAL_BUFFER */ - -#define ACPI_FREE_BUFFER(b) ACPI_FREE(b.pointer) +/* + * Free a buffer created in an struct acpi_buffer via ACPI_ALLOCATE_BUFFER. + * Note: We use acpi_os_free here because acpi_os_allocate was used to allocate + * the buffer. This purposefully bypasses the internal allocation tracking + * mechanism (if it is enabled). + */ +#define ACPI_FREE_BUFFER(b) acpi_os_free((b).pointer) /* * name_type for acpi_get_name -- cgit v0.10.2 From 10622bf8ce432e6a53fd3c37163e99e99c9e43ee Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:30:02 +0800 Subject: ACPICA: Linuxize: Change indentation of C labels. It is reported by kernel build test systems that all ACPICA source files in the kernel tree have incorrect label indentation. This patch changes default indent option used in the release process to fix this bug. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c index fb09b08..afdc6df 100644 --- a/drivers/acpi/acpica/dsargs.c +++ b/drivers/acpi/acpica/dsargs.c @@ -158,7 +158,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node, walk_state->deferred_node = node; status = acpi_ps_parse_aml(walk_state); - cleanup: +cleanup: acpi_ps_delete_parse_tree(op); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index d4bfe7b..2d4c073 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -259,7 +259,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, goto cleanup; } - cleanup: +cleanup: /* Remove local reference to the object */ diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index a9ffd44..df3ea12 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -294,7 +294,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, obj_desc->method.thread_count++; return_ACPI_STATUS(status); - cleanup: +cleanup: /* On error, must release the method mutex (if present) */ if (obj_desc->method.mutex) { @@ -424,7 +424,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, return_ACPI_STATUS(status); - cleanup: +cleanup: /* On error, we must terminate the method properly */ diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index 63f0d22..b1746a6 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -240,7 +240,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } - exit: +exit: *obj_desc_ptr = obj_desc; return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 1fc1ff1..5205edc 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -257,7 +257,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode, (buffer_desc->common.reference_count + obj_desc->common.reference_count); - cleanup: +cleanup: /* Always delete the operands */ diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index c666fc0..ade44e4 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -299,7 +299,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, goto result_used; } - result_used: +result_used: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Result of [%s] used by Parent [%s] Op=%p\n", acpi_ps_get_opcode_name(op->common.aml_opcode), @@ -308,7 +308,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, return_UINT8(TRUE); - result_not_used: +result_not_used: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Result of [%s] not used by Parent [%s] Op=%p\n", acpi_ps_get_opcode_name(op->common.aml_opcode), @@ -752,7 +752,7 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); - cleanup: +cleanup: /* * We must undo everything done above; meaning that we must * pop everything off of the operand stack and delete those @@ -851,7 +851,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) goto exit; } - push_result: +push_result: walk_state->result_obj = new_obj_desc; @@ -863,7 +863,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) op->common.flags |= ACPI_PARSEOP_IN_STACK; } - exit: +exit: return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index 151d924..1bbb22f 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -170,7 +170,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE); - cleanup: +cleanup: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", walk_state->control_state->common.value, @@ -335,7 +335,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); - error_exit: +error_exit: status = acpi_ds_method_error(status, walk_state); return_ACPI_STATUS(status); } @@ -722,7 +722,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) walk_state->result_obj = NULL; } - cleanup: +cleanup: if (walk_state->result_obj) { diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index b1f8f47..7f569d5 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c @@ -728,7 +728,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) break; } - cleanup: +cleanup: /* Remove the Node pushed at the very beginning */ diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c index fdb0a76..4c67193 100644 --- a/drivers/acpi/acpica/evglock.c +++ b/drivers/acpi/acpica/evglock.c @@ -173,7 +173,7 @@ static u32 acpi_ev_global_lock_handler(void *context) acpi_gbl_global_lock_pending = FALSE; - cleanup_and_exit: +cleanup_and_exit: acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags); return (ACPI_INTERRUPT_HANDLED); diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 1979a25..a9cb4a1 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -458,7 +458,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) gpe_block = gpe_block->next; } - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return (int_status); diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index c1aa1ed..a9e76bc 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -111,7 +111,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, gpe_block->xrupt_block = gpe_xrupt_block; acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - unlock_and_exit: +unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -178,7 +178,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) ACPI_FREE(gpe_block->event_info); ACPI_FREE(gpe_block); - unlock_and_exit: +unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -302,7 +302,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) return_ACPI_STATUS(AE_OK); - error_exit: +error_exit: if (gpe_register_info) { ACPI_FREE(gpe_register_info); } diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 7842700..a3e2f38 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -203,7 +203,7 @@ acpi_status acpi_ev_gpe_initialize(void) goto cleanup; } - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index d523390..d3f5e1e 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -101,7 +101,7 @@ acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context) gpe_xrupt_info = gpe_xrupt_info->next; } - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c index 068af96..e315731 100644 --- a/drivers/acpi/acpica/evhandler.c +++ b/drivers/acpi/acpica/evhandler.c @@ -129,7 +129,7 @@ acpi_status acpi_ev_install_region_handlers(void) } } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -531,6 +531,6 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, acpi_ev_install_handler, NULL, handler_obj, NULL); - unlock_and_exit: +unlock_and_exit: return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 6293d6b..144cbb9 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -573,10 +573,10 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) status = acpi_ns_evaluate(info); acpi_ut_remove_reference(args[1]); - cleanup2: +cleanup2: acpi_ut_remove_reference(args[0]); - cleanup1: +cleanup1: ACPI_FREE(info); return_ACPI_STATUS(status); } @@ -761,7 +761,7 @@ acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node) status = acpi_evaluate_object(reg_method, NULL, &args, NULL); - exit: +exit: /* We ignore all errors from above, don't care */ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 6d88b13..23a7fad 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -375,7 +375,7 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler) acpi_gbl_exception_handler = handler; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -445,12 +445,12 @@ acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context) new_sci_handler->next = acpi_gbl_sci_handler_list; acpi_gbl_sci_handler_list = new_sci_handler; - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - exit: +exit: if (ACPI_FAILURE(status)) { ACPI_FREE(new_sci_handler); } @@ -517,7 +517,7 @@ acpi_status acpi_remove_sci_handler(acpi_sci_handler address) acpi_os_release_lock(acpi_gbl_gpe_lock, flags); status = AE_NOT_EXIST; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -566,7 +566,7 @@ acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) acpi_gbl_global_event_handler = handler; acpi_gbl_global_event_handler_context = context; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -638,7 +638,7 @@ acpi_install_fixed_event_handler(u32 event, handler)); } - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index fab40d9..5713da7 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -472,7 +472,7 @@ acpi_get_gpe_status(acpi_handle gpe_device, if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) *event_status |= ACPI_EVENT_FLAG_HANDLE; - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } @@ -625,7 +625,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, obj_desc->device.gpe_block = gpe_block; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -680,7 +680,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) obj_desc->device.gpe_block = NULL; } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 1bd3225..02ed75a 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -148,7 +148,7 @@ acpi_install_address_space_handler(acpi_handle device, status = acpi_ev_execute_reg_methods(node, space_id); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -287,7 +287,7 @@ acpi_remove_address_space_handler(acpi_handle device, status = AE_NOT_EXIST; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index 269e81d..3c2e6dc 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -193,7 +193,7 @@ acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state) acpi_ns_attach_object((struct acpi_namespace_node *)walk_state-> operands[0], obj_desc, ACPI_TYPE_EVENT); - cleanup: +cleanup: /* * Remove local reference to the object (on error, will cause deletion * of both object and semaphore if present.) @@ -248,7 +248,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) acpi_ns_attach_object(obj_desc->mutex.node, obj_desc, ACPI_TYPE_MUTEX); - cleanup: +cleanup: /* * Remove local reference to the object (on error, will cause deletion * of both object and semaphore if present.) @@ -347,7 +347,7 @@ acpi_ex_create_region(u8 * aml_start, status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); - cleanup: +cleanup: /* Remove local reference to the object */ @@ -520,7 +520,7 @@ acpi_ex_create_method(u8 * aml_start, acpi_ut_remove_reference(obj_desc); - exit: +exit: /* Remove a reference to the operand */ acpi_ut_remove_reference(operand[1]); diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index c2a65aa..cfd8752 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -197,7 +197,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - exit: +exit: if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(buffer_desc); } else { diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 7e0afe7..8ab01b6 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -1002,7 +1002,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, mask, merged_datum, field_offset); - exit: +exit: /* Free temporary buffer if we used one */ if (new_buffer) { diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 00bf298..65d9360 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -388,7 +388,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, *actual_return_desc = return_desc; - cleanup: +cleanup: if (local_operand1 != operand1) { acpi_ut_remove_reference(local_operand1); } @@ -718,7 +718,7 @@ acpi_ex_do_logical_op(u16 opcode, } } - cleanup: +cleanup: /* New object was created if implicit conversion performed - delete */ diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index 2cdd41d..d74cea4 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -115,7 +115,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) break; } - cleanup: +cleanup: /* Delete return object on error */ @@ -234,7 +234,7 @@ acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: return_ACPI_STATUS(status); } @@ -551,7 +551,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) status = acpi_ex_store(return_desc, operand[1], walk_state); } - cleanup: +cleanup: /* Delete return object on error */ @@ -1054,7 +1054,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index d5088f7..d6fa0fc 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -215,7 +215,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: /* * Since the remainder is not returned indirectly, remove a reference to * it. Only the quotient is returned indirectly. @@ -445,7 +445,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) break; } - store_result_to_target: +store_result_to_target: if (ACPI_SUCCESS(status)) { /* @@ -462,7 +462,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) } } - cleanup: +cleanup: /* Delete return object on error */ @@ -553,7 +553,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - store_logical_result: +store_logical_result: /* * Set return value to according to logical_result. logical TRUE (all ones) * Default is FALSE (zero) @@ -562,7 +562,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) return_desc->integer.value = ACPI_UINT64_MAX; } - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index 37656f1..bc042adf 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -124,7 +124,7 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: return_ACPI_STATUS(status); } @@ -252,7 +252,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) status = acpi_ex_store(return_desc, operand[3], walk_state); - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c index 879b6cd..4459e32 100644 --- a/drivers/acpi/acpica/exoparg6.c +++ b/drivers/acpi/acpica/exoparg6.c @@ -314,7 +314,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) goto cleanup; } - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index ac04278..1606524 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -521,7 +521,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, */ type = obj_desc->common.type; - exit: +exit: /* Convert internal types to external types */ switch (type) { diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index 00e5af7..be3f669 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -683,7 +683,7 @@ acpi_ex_resolve_operands(u16 opcode, return_ACPI_STATUS(status); } - next_operand: +next_operand: /* * If more operands needed, decrement stack_ptr to point * to next operand on stack diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 8d2e866..12e6cff 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -560,7 +560,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) break; } - exit: +exit: return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index b156848..b4b47db 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -570,10 +570,10 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) break; } - cleanup1: +cleanup1: acpi_ut_remove_reference(info->return_object); - cleanup: +cleanup: if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "While evaluating Sleep State [%s]", diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index aff79c7..14f65f6 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -240,7 +240,7 @@ acpi_status acpi_ns_root_initialize(void) } } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); /* Save a handle to "_GPE", it is always present */ diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index c634854..48b9c6f 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -620,7 +620,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */ } - cleanup: +cleanup: acpi_os_printf("\n"); return (AE_OK); } diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 18108bc..963ceef 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -314,7 +314,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) "*** Completed evaluation of object %s ***\n", info->relative_pathname)); - cleanup: +cleanup: /* * Namespace was unlocked by the handling acpi_ns* function, so we * just free the pathname and return @@ -486,7 +486,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, parent_node->type = (u8)type; } - exit: +exit: if (parent_obj) { acpi_ut_remove_reference(parent_obj); } diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index dd2ceae..3a0423a 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -213,7 +213,7 @@ acpi_status acpi_ns_initialize_devices(void) return_ACPI_STATUS(status); - error_exit: +error_exit: ACPI_EXCEPTION((AE_INFO, status, "During device initialization")); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index 0a7badc..89ec645 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -114,7 +114,7 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) (void)acpi_tb_release_owner_id(table_index); } - unlock: +unlock: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index 35dde81..1778573 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -140,7 +140,7 @@ acpi_ns_one_complete_parse(u32 pass_number, pass_number)); status = acpi_ps_parse_aml(walk_state); - cleanup: +cleanup: acpi_ps_delete_parse_tree(parse_root); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 098e766..d2855d9 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -271,7 +271,7 @@ acpi_ns_check_object_type(struct acpi_evaluate_info *info, return (AE_OK); /* Successful repair */ } - type_error_exit: +type_error_exit: /* Create a string with all expected types for this predefined object */ diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c index 6d55cef..3d5391f 100644 --- a/drivers/acpi/acpica/nsprepkg.c +++ b/drivers/acpi/acpica/nsprepkg.c @@ -330,7 +330,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, return (status); - package_too_small: +package_too_small: /* Error exit for the case with an incorrect package count */ @@ -555,7 +555,7 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, return (AE_OK); - package_too_small: +package_too_small: /* The sub-package count was smaller than required */ diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index f8e71ea..a05afff 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -263,7 +263,7 @@ acpi_ns_simple_repair(struct acpi_evaluate_info *info, return (AE_AML_OPERAND_TYPE); - object_repaired: +object_repaired: /* Object was successfully repaired */ diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index c84603e..6a25d32 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -478,7 +478,7 @@ acpi_ns_repair_CST(struct acpi_evaluate_info *info, removing = TRUE; } - remove_element: +remove_element: if (removing) { acpi_ns_remove_element(return_object, i + 1); outer_element_count--; diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index 08c0b5b..cc2fea9 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -722,7 +722,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - cleanup: +cleanup: ACPI_FREE(internal_path); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index ce2a845..e973e311 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -442,7 +442,7 @@ acpi_evaluate_object(acpi_handle handle, acpi_ex_exit_interpreter(); } - cleanup: +cleanup: /* Free the input parameter list (if we created one) */ @@ -618,10 +618,10 @@ acpi_walk_namespace(acpi_object_type type, descending_callback, ascending_callback, context, return_value); - unlock_and_exit2: +unlock_and_exit2: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock); return_ACPI_STATUS(status); } @@ -865,7 +865,7 @@ acpi_attach_data(acpi_handle obj_handle, status = acpi_ns_attach_data(node, handler, data); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } @@ -911,7 +911,7 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) status = acpi_ns_detach_data(node, handler); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } @@ -958,7 +958,7 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) status = acpi_ns_get_attached_data(node, handler, data); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index 3a6d78a..3a4bd3f 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -209,7 +209,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0; status = AE_OK; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); @@ -497,7 +497,7 @@ acpi_get_object_info(acpi_handle handle, *return_buffer = info; status = AE_OK; - cleanup: +cleanup: if (hid) { ACPI_FREE(hid); } diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index 94e961c..0e6d79e 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -201,7 +201,7 @@ acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle) status = AE_NULL_ENTRY; } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); @@ -281,7 +281,7 @@ acpi_get_next_object(acpi_object_type type, *ret_handle = ACPI_CAST_PTR(acpi_handle, node); } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c index 86198a9..79d9a28 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c @@ -297,7 +297,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, } } - cleanup: +cleanup: /* Now we can actually delete the subtree rooted at Op */ diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index 11b99ab..fcb7a84 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c @@ -142,7 +142,7 @@ static void acpi_ps_start_trace(struct acpi_evaluate_info *info) acpi_dbg_layer = acpi_gbl_trace_dbg_layer; } - exit: +exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); } @@ -185,7 +185,7 @@ static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) acpi_dbg_level = acpi_gbl_original_dbg_level; acpi_dbg_layer = acpi_gbl_original_dbg_layer; - exit: +exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); } @@ -323,7 +323,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) /* walk_state was deleted by parse_aml */ - cleanup: +cleanup: acpi_ps_delete_parse_tree(op); /* End optional tracing */ diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c index 80d1299..c99cec9 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c @@ -440,7 +440,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, info++; } - exit: +exit: if (!flags_mode) { /* Round the resource struct length up to the next boundary (32 or 64) */ @@ -783,7 +783,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, info++; } - exit: +exit: return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 480b6b4..aef303d 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -784,7 +784,7 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, acpi_ut_remove_reference(args[0]); - cleanup: +cleanup: ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 9e6788f..634357d 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -231,10 +231,10 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) goto release; } - print_header: +print_header: acpi_tb_print_table_header(table_desc->address, table_desc->pointer); - release: +release: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); } @@ -306,7 +306,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header return (NULL); /* There was no override */ - finish_override: +finish_override: ACPI_INFO((AE_INFO, "%4.4s %p %s table override, new table: %p", diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index bffdfc7..43ffe21 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -350,7 +350,7 @@ acpi_tb_install_table(acpi_physical_address address, acpi_tb_delete_table(table_desc); } - unmap_and_exit: +unmap_and_exit: /* Always unmap the table header that we mapped above */ diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 2ad8532..bbaad5c 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -466,7 +466,7 @@ acpi_install_table_handler(acpi_table_handler handler, void *context) acpi_gbl_table_handler = handler; acpi_gbl_table_handler_context = context; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -507,7 +507,7 @@ acpi_status acpi_remove_table_handler(acpi_table_handler handler) acpi_gbl_table_handler = NULL; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 2620dbe..5a22024 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -201,7 +201,7 @@ static acpi_status acpi_tb_load_namespace(void) ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired")); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); } @@ -269,7 +269,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table) acpi_gbl_table_handler_context); } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 1731c27..edff4e6 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -552,7 +552,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, *ret_internal_object = internal_object; return_ACPI_STATUS(AE_OK); - error_exit: +error_exit: acpi_ut_remove_reference(internal_object); return_ACPI_STATUS(AE_NO_MEMORY); } @@ -899,7 +899,7 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, return (status); - error_exit: +error_exit: acpi_ut_remove_reference(target_object); return (status); } diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index d6b33f2..c07d222 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -649,7 +649,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) return (AE_OK); - error_exit: +error_exit: ACPI_EXCEPTION((AE_INFO, status, "Could not update object reference count")); diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 4fd6897..16fb905 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -181,7 +181,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, *return_desc = info->return_object; - cleanup: +cleanup: ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index fa69071..bfca7b4 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c @@ -184,7 +184,7 @@ acpi_ut_execute_SUB(struct acpi_namespace_node *device_node, sub->length = length; *return_id = sub; - cleanup: +cleanup: /* On exit, we must delete the return object */ diff --git a/drivers/acpi/acpica/utownerid.c b/drivers/acpi/acpica/utownerid.c index 835340b..eb3aca7 100644 --- a/drivers/acpi/acpica/utownerid.c +++ b/drivers/acpi/acpica/utownerid.c @@ -148,7 +148,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) ACPI_ERROR((AE_INFO, "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); - exit: +exit: (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index cb7fa49..2c2accb 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -643,7 +643,7 @@ acpi_ut_validate_resource(struct acpi_walk_state *walk_state, return (AE_OK); - invalid_resource: +invalid_resource: if (walk_state) { ACPI_ERROR((AE_INFO, @@ -652,7 +652,7 @@ acpi_ut_validate_resource(struct acpi_walk_state *walk_state, } return (AE_AML_INVALID_RESOURCE_TYPE); - bad_resource_length: +bad_resource_length: if (walk_state) { ACPI_ERROR((AE_INFO, diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index 5ef41ff..45c0eb2 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -310,7 +310,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) /* All done, normal exit */ - all_done: +all_done: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", ACPI_FORMAT_UINT64(return_value))); @@ -318,7 +318,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) *ret_integer = return_value; return_ACPI_STATUS(AE_OK); - error_exit: +error_exit: /* Base was set/validated above */ if (base == 10) { diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index 77e3eb7..c002777 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -430,7 +430,7 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation, element->next = allocation; } - unlock_and_exit: +unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); return_ACPI_STATUS(status); } -- cgit v0.10.2 From d21f600b0e4d5a694a338688e61d95f08dbf0afb Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:30:10 +0800 Subject: ACPICA: Deploy ACPI_EXPORT_SYMBOL_INIT for main ACPICA initialization interfaces. This changes can reduce source code differences between Linux and ACPICA upstream to help improving the release automation. The side effect of applying this patch in Linux is: 1. Some ACPICA initialization/termination APIs are no longer exported in Linux, these include: acpi_load_tables acpi_initialize_subsystem acpi_enable_subsystem acpi_initialize_objects acpi_terminate 2. This patch does not affect the following APIs as they are currently not marked with ACPI_EXPORT_SYMBOL in Linux: acpi_reallocate_root_table acpi_initialize_tables Such functions should not be exported as they are internal to ACPI subsystem in Linux, and will only be invoked inside of ACPI subsystem's initialization routines marked with __init and termination routines marked with __exit. While on other OSPMs, such functions may still need to be exported. Thus this patch adds the configurability for ACPICA, so that it leaves OSPMs to determine if the __init/__exit marked functions should be exported or not. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index bbaad5c..7e63090 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -148,6 +148,8 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables) + /******************************************************************************* * * FUNCTION: acpi_reallocate_root_table @@ -182,6 +184,8 @@ acpi_status acpi_reallocate_root_table(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL_INIT(acpi_reallocate_root_table) + /******************************************************************************* * * FUNCTION: acpi_get_table_header @@ -357,6 +361,7 @@ acpi_get_table_with_size(char *signature, return (AE_NOT_FOUND); } + ACPI_EXPORT_SYMBOL(acpi_get_table_with_size) acpi_status @@ -368,6 +373,7 @@ acpi_get_table(char *signature, return acpi_get_table_with_size(signature, instance, out_table, &tbl_size); } + ACPI_EXPORT_SYMBOL(acpi_get_table) /******************************************************************************* @@ -425,7 +431,6 @@ acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table) ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) - /******************************************************************************* * * FUNCTION: acpi_install_table_handler diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 5a22024..b1e1edd 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -83,7 +83,7 @@ acpi_status acpi_load_tables(void) return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_load_tables) +ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables) /******************************************************************************* * diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 2178da8a..891a37b 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -105,7 +105,7 @@ acpi_status acpi_terminate(void) return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_terminate) +ACPI_EXPORT_SYMBOL_INIT(acpi_terminate) #ifndef ACPI_ASL_COMPILER #ifdef ACPI_FUTURE_USAGE diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index dda18e6..ff6f4d1 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -125,7 +125,8 @@ acpi_status acpi_initialize_subsystem(void) ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem) + +ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_subsystem) /******************************************************************************* * @@ -229,7 +230,8 @@ acpi_status acpi_enable_subsystem(u32 flags) return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_enable_subsystem) + +ACPI_EXPORT_SYMBOL_INIT(acpi_enable_subsystem) /******************************************************************************* * @@ -315,4 +317,5 @@ acpi_status acpi_initialize_objects(u32 flags) acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK; return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_initialize_objects) + +ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_objects) diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 0bb23e6..8614bc1 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -299,9 +299,18 @@ typedef u32 acpi_physical_address; #endif /* - * All ACPICA functions that are available to the rest of the kernel are - * tagged with this macro which can be defined as appropriate for the host. + * All ACPICA external functions that are available to the rest of the kernel + * are tagged with thes macros which can be defined as appropriate for the host. + * + * Notes: + * ACPI_EXPORT_SYMBOL_INIT is used for initialization and termination + * interfaces that may need special processing. + * ACPI_EXPORT_SYMBOL is used for all other public external functions. */ +#ifndef ACPI_EXPORT_SYMBOL_INIT +#define ACPI_EXPORT_SYMBOL_INIT(symbol) +#endif + #ifndef ACPI_EXPORT_SYMBOL #define ACPI_EXPORT_SYMBOL(symbol) #endif -- cgit v0.10.2 From 4506bf2329cab39d41f027cdccb1cf455de2bf79 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:30:16 +0800 Subject: ACPICA: Prevent possible build issues for use of ACPI_PRINTF_LIKE macro The following build error: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CC arch/x86/kernel/setup.o In file included from include/acpi/acpi.h:64:0, from include/linux/iscsi_ibft.h:24, from arch/x86/kernel/setup.c:43: include/acpi/acpixf.h:543:1: error: expected ',' or ';' before '{' token include/acpi/acpixf.h:540:1: warning: 'acpi_error' declared 'static' but never defined [-Wunused-function] make[2]: *** [arch/x86/kernel/setup.o] Error 1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ can be triggerred by the following stub function (if implemented): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static inline void ACPI_INTERNAL_VAR_XFACE acpi_error(const char *module_name, u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This patch changes the position of ACPI_PRINTF_LIKE(x) to follow the style of __printf(x, x+1) used in Linux to prevent such issues from happening. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index ddde61b..9759bd5f 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -530,50 +530,53 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status /* * Error/Warning output */ +ACPI_PRINTF_LIKE(3) void ACPI_INTERNAL_VAR_XFACE -acpi_error(const char *module_name, - u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3); +acpi_error(const char *module_name, u32 line_number, const char *format, ...); +ACPI_PRINTF_LIKE(4) void ACPI_INTERNAL_VAR_XFACE acpi_exception(const char *module_name, - u32 line_number, - acpi_status status, const char *format, ...) ACPI_PRINTF_LIKE(4); + u32 line_number, acpi_status status, const char *format, ...); +ACPI_PRINTF_LIKE(3) void ACPI_INTERNAL_VAR_XFACE -acpi_warning(const char *module_name, - u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3); +acpi_warning(const char *module_name, u32 line_number, const char *format, ...); +ACPI_PRINTF_LIKE(3) void ACPI_INTERNAL_VAR_XFACE -acpi_info(const char *module_name, - u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3); +acpi_info(const char *module_name, u32 line_number, const char *format, ...); +ACPI_PRINTF_LIKE(3) void ACPI_INTERNAL_VAR_XFACE acpi_bios_error(const char *module_name, - u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3); + u32 line_number, const char *format, ...); +ACPI_PRINTF_LIKE(3) void ACPI_INTERNAL_VAR_XFACE acpi_bios_warning(const char *module_name, - u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3); + u32 line_number, const char *format, ...); /* * Debug output */ #ifdef ACPI_DEBUG_OUTPUT +ACPI_PRINTF_LIKE(6) void ACPI_INTERNAL_VAR_XFACE acpi_debug_print(u32 requested_debug_level, u32 line_number, const char *function_name, const char *module_name, - u32 component_id, const char *format, ...) ACPI_PRINTF_LIKE(6); + u32 component_id, const char *format, ...); +ACPI_PRINTF_LIKE(6) void ACPI_INTERNAL_VAR_XFACE acpi_debug_print_raw(u32 requested_debug_level, u32 line_number, const char *function_name, const char *module_name, - u32 component_id, - const char *format, ...) ACPI_PRINTF_LIKE(6); + u32 component_id, const char *format, ...); #endif #endif /* __ACXFACE_H__ */ -- cgit v0.10.2 From cd27d79f56e77924b6c66fa4a48306209b93605f Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:30:22 +0800 Subject: ACPICA: Fix indentation issues for macro invocations. During the automatic translation of the upstream ACPICA source code into Linux kernel source code some extra white spaces are added by the "indent" program at the beginning of each line which is an invocation of a macro and there is no ";" at the end of the line. For this reason, a new mode has been added to the translation scripts to remove the extra spaces inserted before invoking such macros and add an empty line between the invocations of such macros (like the other function declarations). This new mode is executed after executing "indent" during the Linux release process. Consequently, some existing ACPICA source code in the Linux kernel tree needs to be adjusted to allow the new scripts to work correctly. The affected macros and files are: 1. ACPI_HW_DEPENDENT_RETURN (acpixf.h/acdebug.h/acevents.h): This macro is used as a wrapper for hardware dependent APIs to offer a stub when the reduced hardware is configured during compilation. 2. ACPI_EXPORT_SYMBOL (utglobal.c): This macro is used by Linux to export symbols to be found by Linux modules. All such invocations are well formatted except those exported as global variables. This can help to reduce the source code differences between Linux and upstream ACPICA, and also help to automate the release process. No functional or binary generation changes should result from it. Lv Zheng. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 57cdc77..a9fd0b8 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -113,7 +113,8 @@ void acpi_db_display_handlers(void); ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_gpe(char *gpe_arg, char *block_arg)) - ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void)) + +ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void)) /* * dbconvert - miscellaneous conversion routines diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 3ae5fd0..41abe55 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -71,7 +71,8 @@ acpi_status acpi_ev_init_global_lock_handler(void); ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_acquire_global_lock(u16 timeout)) - ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void)) + +ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void)) acpi_status acpi_ev_remove_global_lock_handler(void); /* diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c index a877a96..366bfec 100644 --- a/drivers/acpi/acpica/utcache.c +++ b/drivers/acpi/acpica/utcache.c @@ -65,7 +65,7 @@ ACPI_MODULE_NAME("utcache") acpi_status acpi_os_create_cache(char *cache_name, u16 object_size, - u16 max_depth, struct acpi_memory_list ** return_cache) + u16 max_depth, struct acpi_memory_list **return_cache) { struct acpi_memory_list *cache; diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 4f59784..77caa4f 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -378,6 +378,9 @@ acpi_status acpi_ut_init_globals(void) /* Public globals */ ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) + ACPI_EXPORT_SYMBOL(acpi_dbg_level) + ACPI_EXPORT_SYMBOL(acpi_dbg_layer) + ACPI_EXPORT_SYMBOL(acpi_current_gpe_count) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 9759bd5f..cb2e744 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -54,6 +54,7 @@ #include extern u8 acpi_gbl_permanent_mmap; +extern u32 acpi_rsdt_forced; /* * Globals that are publically available @@ -110,7 +111,6 @@ extern u8 acpi_gbl_disable_ssdt_table_load; #endif /* !ACPI_REDUCED_HARDWARE */ -extern u32 acpi_rsdt_forced; /* * Initialization */ @@ -130,9 +130,10 @@ acpi_status acpi_terminate(void); * Miscellaneous global interfaces */ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable(void)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable(void)) #ifdef ACPI_FUTURE_USAGE -acpi_status acpi_subsystem_status(void); + acpi_status acpi_subsystem_status(void); #endif #ifdef ACPI_FUTURE_USAGE @@ -172,7 +173,7 @@ acpi_status acpi_load_tables(void); */ acpi_status acpi_reallocate_root_table(void); -acpi_status acpi_find_root_pointer(acpi_size *rsdp_address); +acpi_status acpi_find_root_pointer(acpi_size * rsdp_address); acpi_status acpi_unload_table_id(acpi_owner_id id); @@ -184,6 +185,7 @@ acpi_status acpi_get_table_with_size(acpi_string signature, u32 instance, struct acpi_table_header **out_table, acpi_size *tbl_size); + acpi_status acpi_get_table(acpi_string signature, u32 instance, struct acpi_table_header **out_table); @@ -274,13 +276,16 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_remove_sci_handler(acpi_sci_handler address)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_install_global_event_handler (acpi_gbl_event_handler handler, void *context)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_install_fixed_event_handler(u32 acpi_event, @@ -288,10 +293,12 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status handler, void *context)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_remove_fixed_event_handler(u32 acpi_event, acpi_event_handler handler)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_install_gpe_handler(acpi_handle gpe_device, @@ -300,6 +307,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_gpe_handler address, void *context)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_remove_gpe_handler(acpi_handle gpe_device, u32 gpe_number, @@ -336,6 +344,7 @@ acpi_status acpi_install_interface_handler(acpi_interface_handler handler); ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_acquire_global_lock(u16 timeout, u32 *handle)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_release_global_lock(u32 handle)) @@ -362,6 +371,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_get_event_status(u32 event, acpi_event_status *event_status)) + /* * General Purpose Event (GPE) Interfaces */ @@ -392,10 +402,12 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status parent_device, acpi_handle gpe_device, u32 gpe_number)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_get_gpe_status(acpi_handle gpe_device, u32 gpe_number, @@ -417,6 +429,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status *gpe_block_address, u32 register_count, u32 interrupt_number)) + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)) @@ -491,7 +504,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status * Sleep/Wake interfaces */ acpi_status -acpi_get_sleep_type_data(u8 sleep_state, u8 * slp_typ_a, u8 * slp_typ_b); +acpi_get_sleep_type_data(u8 sleep_state, u8 *slp_typ_a, u8 *slp_typ_b); acpi_status acpi_enter_sleep_state_prep(u8 sleep_state); @@ -506,7 +519,6 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state); ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_set_firmware_waking_vector(u32 physical_address)) - #if ACPI_MACHINE_WIDTH == 64 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_set_firmware_waking_vector64(u64 -- cgit v0.10.2 From c0144dc0e43ed97d60ce34c900a4326bb087bf11 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:30:29 +0800 Subject: ACPICA: Simplify configuration of global ACPI_REDUCED_HARDWARE macro. Surround definition of this with a #ifndef so that the kernel can define it elsewhere if desired. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 1c16f82..d98c670 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -100,7 +100,9 @@ * ACPI PM timer * FACS table (Waking vectors and Global Lock) */ +#ifndef ACPI_REDUCED_HARDWARE #define ACPI_REDUCED_HARDWARE FALSE +#endif /****************************************************************************** * -- cgit v0.10.2 From 7e94632fc530d990de3110e6c53425d6e28dd238 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:30:35 +0800 Subject: ACPICA: Add support to allow host OS to redefine individual OSL prototypes. This change enables the host OS to redefine OSL prototypes found in the acpiosxf.h file. This allows the host OS to implement OSL interfaces with a macro or inlined function. Further, it allows the host OS to add any additional required modifiers such as __iomem, __init, __exit, etc., as necessary on a per-interface basis. Enables maximum flexibility for the OSL interfaces. Lv Zheng. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 7f95215..55165fc 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -77,54 +77,80 @@ struct acpi_signal_fatal_info { /* * OSL Initialization and shutdown primitives */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize acpi_status __init acpi_os_initialize(void); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate acpi_status acpi_os_terminate(void); +#endif /* * ACPI Table interfaces */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_root_pointer acpi_physical_address acpi_os_get_root_pointer(void); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_predefined_override acpi_status acpi_os_predefined_override(const struct acpi_predefined_names *init_val, acpi_string * new_val); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_table_override acpi_status acpi_os_table_override(struct acpi_table_header *existing_table, struct acpi_table_header **new_table); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_physical_table_override acpi_status acpi_os_physical_table_override(struct acpi_table_header *existing_table, acpi_physical_address * new_address, u32 *new_table_length); +#endif /* * Spinlock primitives */ -#ifndef acpi_os_create_lock +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock acpi_status acpi_os_create_lock(acpi_spinlock * out_handle); #endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_lock void acpi_os_delete_lock(acpi_spinlock handle); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_lock acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock handle); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_lock void acpi_os_release_lock(acpi_spinlock handle, acpi_cpu_flags flags); +#endif /* * Semaphore primitives */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_semaphore acpi_status acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_semaphore * out_handle); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_semaphore acpi_status acpi_os_delete_semaphore(acpi_semaphore handle); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_wait_semaphore acpi_status acpi_os_wait_semaphore(acpi_semaphore handle, u32 units, u16 timeout); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_signal_semaphore acpi_status acpi_os_signal_semaphore(acpi_semaphore handle, u32 units); +#endif /* * Mutex primitives. May be configured to use semaphores instead via @@ -132,63 +158,98 @@ acpi_status acpi_os_signal_semaphore(acpi_semaphore handle, u32 units); */ #if (ACPI_MUTEX_TYPE != ACPI_BINARY_SEMAPHORE) +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_mutex acpi_status acpi_os_create_mutex(acpi_mutex * out_handle); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_mutex void acpi_os_delete_mutex(acpi_mutex handle); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_mutex acpi_status acpi_os_acquire_mutex(acpi_mutex handle, u16 timeout); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_mutex void acpi_os_release_mutex(acpi_mutex handle); #endif +#endif + /* * Memory allocation and mapping */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_allocate void *acpi_os_allocate(acpi_size size); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_allocate_zeroed void *acpi_os_allocate_zeroed(acpi_size size); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_free void acpi_os_free(void *memory); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_map_memory void __iomem *acpi_os_map_memory(acpi_physical_address where, acpi_size length); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_unmap_memory void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size); +#endif void early_acpi_os_unmap_memory(void __iomem * virt, acpi_size size); #ifdef ACPI_FUTURE_USAGE +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_physical_address acpi_status acpi_os_get_physical_address(void *logical_address, acpi_physical_address * physical_address); #endif +#endif /* * Memory/Object Cache */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_cache acpi_status acpi_os_create_cache(char *cache_name, u16 object_size, u16 max_depth, acpi_cache_t ** return_cache); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_cache acpi_status acpi_os_delete_cache(acpi_cache_t * cache); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_purge_cache acpi_status acpi_os_purge_cache(acpi_cache_t * cache); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_object void *acpi_os_acquire_object(acpi_cache_t * cache); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_object acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object); +#endif /* * Interrupt handlers */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_install_interrupt_handler acpi_status acpi_os_install_interrupt_handler(u32 interrupt_number, acpi_osd_handler service_routine, void *context); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_remove_interrupt_handler acpi_status acpi_os_remove_interrupt_handler(u32 interrupt_number, acpi_osd_handler service_routine); +#endif void acpi_os_gpe_count(u32 gpe_number); void acpi_os_fixed_event_count(u32 fixed_event_number); @@ -196,86 +257,158 @@ void acpi_os_fixed_event_count(u32 fixed_event_number); /* * Threads and Scheduling */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id acpi_thread_id acpi_os_get_thread_id(void); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_execute acpi_status acpi_os_execute(acpi_execute_type type, acpi_osd_exec_callback function, void *context); +#endif acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, void *context); +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_wait_events_complete void acpi_os_wait_events_complete(void); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_sleep void acpi_os_sleep(u64 milliseconds); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_stall void acpi_os_stall(u32 microseconds); +#endif /* * Platform and hardware-independent I/O interfaces */ -acpi_status acpi_os_read_port(acpi_io_address address, u32 * value, u32 width); +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_read_port +acpi_status acpi_os_read_port(acpi_io_address address, u32 *value, u32 width); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_write_port acpi_status acpi_os_write_port(acpi_io_address address, u32 value, u32 width); +#endif /* * Platform and hardware-independent physical memory interfaces */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_read_memory acpi_status acpi_os_read_memory(acpi_physical_address address, u64 *value, u32 width); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_write_memory acpi_status acpi_os_write_memory(acpi_physical_address address, u64 value, u32 width); +#endif /* * Platform and hardware-independent PCI configuration space access * Note: Can't use "Register" as a parameter, changed to "Reg" -- * certain compilers complain. */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_read_pci_configuration acpi_status acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id, u32 reg, u64 *value, u32 width); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_write_pci_configuration acpi_status acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id, u32 reg, u64 value, u32 width); +#endif /* * Miscellaneous */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_readable +u8 acpi_os_readable(void *pointer, acpi_size length); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_writable +u8 acpi_os_writable(void *pointer, acpi_size length); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_timer u64 acpi_os_get_timer(void); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_signal acpi_status acpi_os_signal(u32 function, void *info); +#endif /* * Debug print routines */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_printf void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *format, ...); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_vprintf void acpi_os_vprintf(const char *format, va_list args); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_redirect_output void acpi_os_redirect_output(void *destination); +#endif #ifdef ACPI_FUTURE_USAGE /* * Debug input */ -u32 acpi_os_get_line(char *buffer); +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_line +acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read); +#endif +#endif + +/* + * Obtain ACPI table(s) + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_name +acpi_status +acpi_os_get_table_by_name(char *signature, + u32 instance, + struct acpi_table_header **table, + acpi_physical_address * address); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_index +acpi_status +acpi_os_get_table_by_index(u32 index, + struct acpi_table_header **table, + u32 *instance, acpi_physical_address * address); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_address +acpi_status +acpi_os_get_table_by_address(acpi_physical_address address, + struct acpi_table_header **table); #endif /* * Directory manipulation */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_open_directory void *acpi_os_open_directory(char *pathname, char *wildcard_spec, char requested_file_type); +#endif /* requeste_file_type values */ #define REQUEST_FILE_ONLY 0 #define REQUEST_DIR_ONLY 1 +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_next_filename char *acpi_os_get_next_filename(void *dir_handle); +#endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_close_directory void acpi_os_close_directory(void *dir_handle); +#endif #endif /* __ACPIOSXF_H__ */ diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 0e6e73c..04e87a3 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -182,6 +182,7 @@ static inline void acpi_os_free(void *a) } \ lock ? AE_OK : AE_NO_MEMORY; \ }) +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock #ifdef EXPORT_ACPI_INTERFACES #include -- cgit v0.10.2 From 93220587f76b8a4eca89cb655fc0cc04e9da663d Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 29 Oct 2013 09:30:41 +0800 Subject: ACPICA: Update aclinux.h for new OSL override mechanism. The new ACPICA OSL override mechanism is used to solve these issues for the Linux OSL: 1. Linux can implement OSL using a macro. 2. Linux can implement OSL using an inlined function. 3. Linux can leave OSL not implemented for __KERNEL__ undefined code fragments. 4. Linux can add sparse declarators (__iomem) to OSL. 5. Linux can add memory tuning declarators (__init/__exit) to OSL. This patch also moves Linux specific OSL to aclinux.h which has not been maintained in the ACPICA code base. Lv Zheng. Known issue: From ACPICA's perspective, actypes.h should be included after inclusion of acenv.h. But currently in Linux, aclinux.h included by acenv.h has included actypes.h to find ACPICA types for inline functions. This is a known and existing issue and currently there is no real problem caused by this issue for Linux kernel build. Thus this issue is not covered by this cleanup commit. Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 55165fc..01e6c6d 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -78,7 +78,7 @@ struct acpi_signal_fatal_info { * OSL Initialization and shutdown primitives */ #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize -acpi_status __init acpi_os_initialize(void); +acpi_status acpi_os_initialize(void); #endif #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate @@ -192,22 +192,18 @@ void acpi_os_free(void *memory); #endif #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_map_memory -void __iomem *acpi_os_map_memory(acpi_physical_address where, - acpi_size length); +void *acpi_os_map_memory(acpi_physical_address where, acpi_size length); #endif #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_unmap_memory -void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size); +void acpi_os_unmap_memory(void *logical_address, acpi_size size); #endif -void early_acpi_os_unmap_memory(void __iomem * virt, acpi_size size); -#ifdef ACPI_FUTURE_USAGE #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_physical_address acpi_status acpi_os_get_physical_address(void *logical_address, acpi_physical_address * physical_address); #endif -#endif /* * Memory/Object Cache @@ -251,9 +247,6 @@ acpi_os_remove_interrupt_handler(u32 interrupt_number, acpi_osd_handler service_routine); #endif -void acpi_os_gpe_count(u32 gpe_number); -void acpi_os_fixed_event_count(u32 fixed_event_number); - /* * Threads and Scheduling */ @@ -267,9 +260,6 @@ acpi_os_execute(acpi_execute_type type, acpi_osd_exec_callback function, void *context); #endif -acpi_status -acpi_os_hotplug_execute(acpi_osd_exec_callback function, void *context); - #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_wait_events_complete void acpi_os_wait_events_complete(void); #endif @@ -357,14 +347,12 @@ void acpi_os_vprintf(const char *format, va_list args); void acpi_os_redirect_output(void *destination); #endif -#ifdef ACPI_FUTURE_USAGE /* * Debug input */ #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_line acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read); #endif -#endif /* * Obtain ACPI table(s) diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 04e87a3..ab57930 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -50,7 +50,6 @@ #define ACPI_USE_DO_WHILE_0 #define ACPI_MUTEX_TYPE ACPI_BINARY_SEMAPHORE - #ifdef __KERNEL__ #include @@ -58,11 +57,13 @@ #include #include #include -#include -#include +#include #include #include -#include +#ifdef EXPORT_ACPI_INTERFACES +#include +#endif +#include /* Host-dependent types and defines for in-kernel ACPICA */ @@ -109,23 +110,29 @@ #include #ifdef __KERNEL__ + +/* + * FIXME: Inclusion of actypes.h + * Linux kernel need this before defining inline OSL interfaces as + * actypes.h need to be included to find ACPICA type definitions. + * Since from ACPICA's perspective, the actypes.h should be included after + * acenv.h (aclinux.h), this leads to a inclusion mis-ordering issue. + */ #include + /* * Overrides for in-kernel ACPICA */ -static inline acpi_thread_id acpi_os_get_thread_id(void) -{ - return (acpi_thread_id)(unsigned long)current; -} +acpi_status __init acpi_os_initialize(void); +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize + +acpi_status acpi_os_terminate(void); +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate /* * Memory allocation/deallocation */ -/* Use native linux version of acpi_os_allocate_zeroed */ - -#define USE_NATIVE_ALLOCATE_ZEROED - /* * The irqs_disabled() check is for resume from RAM. * Interrupts are off during resume, just like they are for boot. @@ -134,26 +141,45 @@ static inline acpi_thread_id acpi_os_get_thread_id(void) */ static inline void *acpi_os_allocate(acpi_size size) { - return kmalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL); + return kmalloc(size, irqs_disabled()? GFP_ATOMIC : GFP_KERNEL); } +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_allocate + +/* Use native linux version of acpi_os_allocate_zeroed */ + static inline void *acpi_os_allocate_zeroed(acpi_size size) { - return kzalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL); + return kzalloc(size, irqs_disabled()? GFP_ATOMIC : GFP_KERNEL); +} + +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_allocate_zeroed +#define USE_NATIVE_ALLOCATE_ZEROED + +static inline void acpi_os_free(void *memory) +{ + kfree(memory); } +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_free + static inline void *acpi_os_acquire_object(acpi_cache_t * cache) { return kmem_cache_zalloc(cache, - irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL); + irqs_disabled()? GFP_ATOMIC : GFP_KERNEL); } -static inline void acpi_os_free(void *a) +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_object + +static inline acpi_thread_id acpi_os_get_thread_id(void) { - kfree(a); + return (acpi_thread_id) (unsigned long)current; } +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_thread_id + #ifndef CONFIG_PREEMPT + /* * Used within ACPICA to show where it is safe to preempt execution * when CONFIG_PREEMPT=n @@ -163,6 +189,7 @@ static inline void acpi_os_free(void *a) if (!irqs_disabled()) \ cond_resched(); \ } while (0) + #endif /* @@ -172,21 +199,52 @@ static inline void acpi_os_free(void *a) * all locks to the name of the argument of acpi_os_create_lock(), which * prevents lockdep from reporting false positives for ACPICA locks. */ -#define acpi_os_create_lock(__handle) \ -({ \ - spinlock_t *lock = ACPI_ALLOCATE(sizeof(*lock)); \ - \ - if (lock) { \ - *(__handle) = lock; \ - spin_lock_init(*(__handle)); \ - } \ - lock ? AE_OK : AE_NO_MEMORY; \ -}) +#define acpi_os_create_lock(__handle) \ + ({ \ + spinlock_t *lock = ACPI_ALLOCATE(sizeof(*lock)); \ + if (lock) { \ + *(__handle) = lock; \ + spin_lock_init(*(__handle)); \ + } \ + lock ? AE_OK : AE_NO_MEMORY; \ + }) #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_create_lock -#ifdef EXPORT_ACPI_INTERFACES -#include -#endif +void __iomem *acpi_os_map_memory(acpi_physical_address where, acpi_size length); +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_map_memory + +void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size); +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_unmap_memory + +/* + * OSL interfaces used by debugger/disassembler + */ +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_readable +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_writable + +/* + * OSL interfaces used by utilities + */ +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_redirect_output +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_line +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_name +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_index +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_table_by_address +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_open_directory +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_next_filename +#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_close_directory + +/* + * OSL interfaces added by Linux + */ +void early_acpi_os_unmap_memory(void __iomem * virt, acpi_size size); + +void acpi_os_gpe_count(u32 gpe_number); + +void acpi_os_fixed_event_count(u32 fixed_event_number); + +acpi_status +acpi_os_hotplug_execute(acpi_osd_exec_callback function, void *context); #endif /* __KERNEL__ */ -- cgit v0.10.2 From affffae367c7ee1003232201c52db1fd7dd4f472 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 29 Oct 2013 09:30:48 +0800 Subject: ACPICA: Update version to 20130927. Version 20130927. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index cb2e744..b2dcab0 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20130823 +#define ACPI_CA_VERSION 0x20130927 #include #include -- cgit v0.10.2 From bb42cc224a4626f9eaef34d9a334f0dc65133c40 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:29:49 +0800 Subject: ACPICA: Update default space handlers. This patch adds code that is already in ACPICA upstream, so applying it can help to reduce the source code differences between Linux and ACPICA upstream. This code fragment is only useful for ACPICA utilities and no functional changes to the Linux kernel should result from it. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 303429bb..9d28867e 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -400,6 +400,7 @@ acpi_ex_pci_config_space_handler(u32 function, switch (function) { case ACPI_READ: + *value = 0; status = acpi_os_read_pci_configuration(pci_id, pci_register, value, bit_width); break; -- cgit v0.10.2 From 99567bc5507bf404ae13a0c53264c921f380d06f Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:04 +0800 Subject: ACPICA: Update check for setting the ANOBJ_IS_EXTERNAL flag. The ANOBJ_IS_EXTERNAL flag is only used by an ACPICA utilities - iASL. No functional change for the Linux kernel should results from applying this patch, but it helps to reduce source code differences between the kernel and ACPICA upstream. [rjw: Subject and changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index 5d43efc..47420fa 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -381,7 +381,8 @@ acpi_ns_search_and_enter(u32 target_name, /* Node is an object defined by an External() statement */ - if (flags & ACPI_NS_EXTERNAL) { + if (flags & ACPI_NS_EXTERNAL || + (walk_state && walk_state->opcode == AML_SCOPE_OP)) { new_node->flags |= ANOBJ_IS_EXTERNAL; } #endif -- cgit v0.10.2 From 98f7eb878a3495474f5d616301a914d7f9bdb389 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:10 +0800 Subject: ACPICA: Update namespace dump code. This patch merges namespace dump code updates from ACPICA upstream to reduce the source code differences between Linux and ACPICA upstream. No functional changes as currently nsdumpdv.c is not used by Linux. This patch does not affect the generation of the Linux kernel binary. Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c index 409ae80..2837625 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c @@ -69,6 +69,7 @@ static acpi_status acpi_ns_dump_one_device(acpi_handle obj_handle, u32 level, void *context, void **return_value) { + struct acpi_buffer buffer; struct acpi_device_info *info; acpi_status status; u32 i; @@ -78,15 +79,17 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, status = acpi_ns_dump_one_object(obj_handle, level, context, return_value); - status = acpi_get_object_info(obj_handle, &info); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info(obj_handle, &buffer); if (ACPI_SUCCESS(status)) { + info = buffer.pointer; for (i = 0; i < level; i++) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " ")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", - info->hardware_id.string, + info->hardware_id.value, ACPI_FORMAT_UINT64(info->address), info->current_status)); ACPI_FREE(info); -- cgit v0.10.2 From 09b8b1fce7688958f44884135b83fb857eb6e1b6 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:16 +0800 Subject: ACPICA: Update RSDP table definitions. This patch updates RSDP table header definitions as such enhancement has been made in ACPICA upstream already. It ports that change to the Linux source to reduce source code differences between Linux and ACPICA upstream. This patch does not affect the generation of the Linux kernel binary. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index 9b58a8f..9497088 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -146,7 +146,24 @@ struct acpi_table_rsdp { u8 reserved[3]; /* Reserved, must be zero */ }; -#define ACPI_RSDP_REV0_SIZE 20 /* Size of original ACPI 1.0 RSDP */ +/* Standalone struct for the ACPI 1.0 RSDP */ + +struct acpi_rsdp_common { + char signature[8]; + u8 checksum; + char oem_id[ACPI_OEM_ID_SIZE]; + u8 revision; + u32 rsdt_physical_address; +}; + +/* Standalone struct for the extended part of the RSDP (ACPI 2.0+) */ + +struct acpi_rsdp_extension { + u32 length; + u64 xsdt_physical_address; + u8 extended_checksum; + u8 reserved[3]; +}; /******************************************************************************* * -- cgit v0.10.2 From fa5f508f942faaf73ae5020db7a4189d5ca88d2a Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:22 +0800 Subject: ACPICA: Update DMAR table definitions. This patch updates DMAR table header definitions as such enhancement has been made in ACPICA upstream already. It ports that change to the Linux source to reduce source code differences between Linux and ACPICA upstream. Build test done on x86-64 machine with the following configs enabled: CONFIG_DMAR_TABLE CONFIG_IRQ_REMAP CONFIG_INTEL_IOMMU This patch does not affect the generation of the Linux kernel binary. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 785675a..9009469 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -88,7 +88,7 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope, pr_warn("Device scope bus [%d] not found\n", scope->bus); break; } - pdev = pci_get_slot(bus, PCI_DEVFN(path->dev, path->fn)); + pdev = pci_get_slot(bus, PCI_DEVFN(path->device, path->function)); if (!pdev) { /* warning will be printed below */ break; @@ -99,7 +99,7 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope, } if (!pdev) { pr_warn("Device scope device [%04x:%02x:%02x.%02x] not found\n", - segment, scope->bus, path->dev, path->fn); + segment, scope->bus, path->device, path->function); *dev = NULL; return 0; } diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index f71673d..ab86902 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -686,12 +686,12 @@ static void ir_parse_one_hpet_scope(struct acpi_dmar_device_scope *scope, * Access PCI directly due to the PCI * subsystem isn't initialized yet. */ - bus = read_pci_config_byte(bus, path->dev, path->fn, + bus = read_pci_config_byte(bus, path->device, path->function, PCI_SECONDARY_BUS); path++; } ir_hpet[ir_hpet_num].bus = bus; - ir_hpet[ir_hpet_num].devfn = PCI_DEVFN(path->dev, path->fn); + ir_hpet[ir_hpet_num].devfn = PCI_DEVFN(path->device, path->function); ir_hpet[ir_hpet_num].iommu = iommu; ir_hpet[ir_hpet_num].id = scope->enumeration_id; ir_hpet_num++; @@ -714,13 +714,13 @@ static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope, * Access PCI directly due to the PCI * subsystem isn't initialized yet. */ - bus = read_pci_config_byte(bus, path->dev, path->fn, + bus = read_pci_config_byte(bus, path->device, path->function, PCI_SECONDARY_BUS); path++; } ir_ioapic[ir_ioapic_num].bus = bus; - ir_ioapic[ir_ioapic_num].devfn = PCI_DEVFN(path->dev, path->fn); + ir_ioapic[ir_ioapic_num].devfn = PCI_DEVFN(path->device, path->function); ir_ioapic[ir_ioapic_num].iommu = iommu; ir_ioapic[ir_ioapic_num].id = scope->enumeration_id; ir_ioapic_num++; diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index ffaac0e..40f7ed1 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -444,8 +444,8 @@ enum acpi_dmar_scope_type { }; struct acpi_dmar_pci_path { - u8 dev; - u8 fn; + u8 device; + u8 function; }; /* -- cgit v0.10.2 From 9187a415fd119c1d89a5ad2fd05513cd43699ebf Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:28 +0800 Subject: ACPICA: Add new statistics interface. This patch ports new counters and statistics interface, already implemented in ACPICA upstream, to Linux. That helps to reduce source code differences between Linux and ACPICA upstream. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 0fba431..e9f1fc7 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -406,7 +406,9 @@ extern u32 acpi_gbl_nesting_level; /* Event counters */ +ACPI_EXTERN u32 acpi_method_count; ACPI_EXTERN u32 acpi_gpe_count; +ACPI_EXTERN u32 acpi_sci_count; ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]; /* Support for dynamic control method tracing mechanism */ diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index df3ea12..81a78ba 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -292,6 +292,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, * reentered one more time (even if it is the same thread) */ obj_desc->method.thread_count++; + acpi_method_count++; return_ACPI_STATUS(status); cleanup: diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index 94d9ebd..9e9e345 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -137,6 +137,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) interrupt_handled |= acpi_ev_sci_dispatch(); + acpi_sci_count++; return_UINT32(interrupt_handled); } diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 77caa4f..81f9a95 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -289,6 +289,16 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; + /* Event counters */ + + acpi_method_count = 0; + acpi_sci_count = 0; + acpi_gpe_count = 0; + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + acpi_fixed_event_count[i] = 0; + } + #if (!ACPI_REDUCED_HARDWARE) /* GPE/SCI support */ @@ -383,4 +393,6 @@ ACPI_EXPORT_SYMBOL(acpi_dbg_level) ACPI_EXPORT_SYMBOL(acpi_dbg_layer) +ACPI_EXPORT_SYMBOL(acpi_gpe_count) + ACPI_EXPORT_SYMBOL(acpi_current_gpe_count) diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 891a37b..3986902 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -208,6 +208,44 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) ACPI_EXPORT_SYMBOL(acpi_get_system_info) +/******************************************************************************* + * + * FUNCTION: acpi_get_statistics + * + * PARAMETERS: stats - Where the statistics are returned + * + * RETURN: status - the status of the call + * + * DESCRIPTION: Get the contents of the various system counters + * + ******************************************************************************/ +acpi_status acpi_get_statistics(struct acpi_statistics *stats) +{ + ACPI_FUNCTION_TRACE(acpi_get_statistics); + + /* Parameter validation */ + + if (!stats) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Various interrupt-based event counters */ + + stats->sci_count = acpi_sci_count; + stats->gpe_count = acpi_gpe_count; + + ACPI_MEMCPY(stats->fixed_event_count, acpi_fixed_event_count, + sizeof(acpi_fixed_event_count)); + + /* Other counters */ + + stats->method_count = acpi_method_count; + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_get_statistics) + /***************************************************************************** * * FUNCTION: acpi_install_initialization_handler diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index b2dcab0..7def8ca 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -140,6 +140,8 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable(void)) acpi_status acpi_get_system_info(struct acpi_buffer *ret_buffer); #endif +acpi_status acpi_get_statistics(struct acpi_statistics *stats); + const char *acpi_format_exception(acpi_status exception); acpi_status acpi_purge_cached_objects(void); diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 8614bc1..0e32b6c 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -973,6 +973,16 @@ struct acpi_system_info { u32 debug_layer; }; +/* + * System statistics returned by acpi_get_statistics() + */ +struct acpi_statistics { + u32 sci_count; + u32 gpe_count; + u32 fixed_event_count[ACPI_NUM_FIXED_EVENTS]; + u32 method_count; +}; + /* Table Event Types */ #define ACPI_TABLE_EVENT_LOAD 0x0 -- cgit v0.10.2 From 130797a6c3f1421c10880a1681d6a9c57b80ef17 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:36 +0800 Subject: ACPICA: Fix wrong object length returned by acpi_ut_get_simple_object_size(). The object length returned by acpi_ut_get_simple_object_size() should be rounded up to the closest word boundary. This patch ports a fix from ACPICA upstream to Linux. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index aa61f66..cddb0ef 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -461,25 +461,28 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); + /* Start with the length of the (external) Acpi object */ + + length = sizeof(union acpi_object); + + /* A NULL object is allowed, can be a legal uninitialized package element */ + + if (!internal_object) { /* - * Handle a null object (Could be a uninitialized package - * element -- which is legal) + * Object is NULL, just return the length of union acpi_object + * (A NULL union acpi_object is an object of all zeroes.) */ - if (!internal_object) { - *obj_length = sizeof(union acpi_object); + *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); return_ACPI_STATUS(AE_OK); } - /* Start with the length of the Acpi object */ - - length = sizeof(union acpi_object); + /* A Namespace Node should never appear here */ if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) { - /* Object is a named object (reference), just return the length */ + /* A namespace node should never get here */ - *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_AML_INTERNAL); } /* -- cgit v0.10.2 From bd48d677670bb35548718a1fd54c2c114a449973 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:42 +0800 Subject: ACPICA: Fix an ACPI_ALLOCATE_ZEROED() reversal. ACPI_FREE() should always be used to free objects allocated with ACPI_ALLOCATE_ZEROED(), so make acpi_ut_create_package_object() do that. This patch ports a fix from ACPICA upstream to Linux and helps to reduce source code differences between them. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index cddb0ef..d2a7b61 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -180,7 +180,7 @@ union acpi_operand_object *acpi_ut_create_package_object(u32 count) package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size) count + 1) * sizeof(void *)); if (!package_elements) { - acpi_ut_remove_reference(package_desc); + ACPI_FREE(package_desc); return_PTR(NULL); } -- cgit v0.10.2 From 6208a3dd370c73101d28d761f562723755108803 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:48 +0800 Subject: ACPICA: Cleanup useless memset invocations. This patch removes unnecessary memset() invocations where kmem_cache_zalloc() is used for allocating memory. It also helps to reduce source code differences between ACPICA upstream and Linux. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index d2a7b61..13e0450 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -396,7 +396,6 @@ void *acpi_ut_allocate_object_desc_dbg(const char *module_name, /* Mark the descriptor type */ - memset(object, 0, sizeof(union acpi_operand_object)); ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND); ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p Size %X\n", diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c index a6b729d..03c4c2f 100644 --- a/drivers/acpi/acpica/utstate.c +++ b/drivers/acpi/acpica/utstate.c @@ -161,7 +161,6 @@ union acpi_generic_state *acpi_ut_create_generic_state(void) if (state) { /* Initialize */ - memset(state, 0, sizeof(union acpi_generic_state)); state->common.descriptor_type = ACPI_DESC_TYPE_STATE; } -- cgit v0.10.2 From 2faa046485721c05ad3999bc6c8f6ced7017ef27 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:30:53 +0800 Subject: ACPICA: Remove dead AOPOBJ_INVALID check. Reversion commit 7cb7f45c7fee (Revert "ACPICA: Remove obsolete acpi_os_validate_address interface") restored a piece of dead code related to an obselete AOPOBJ_INVALID flag. Remove that code again. This helps to reduce source code differences between Linux and ACPICA upstream. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 8ab01b6..49fb742 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -123,12 +123,6 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, } } - /* Exit if Address/Length have been disallowed by the host OS */ - - if (rgn_desc->common.flags & AOPOBJ_INVALID) { - return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); - } - /* * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear * address space and the request cannot be directly validated -- cgit v0.10.2 From dba47d3af92bb2e443cdb689422bf30b498bd209 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:31:00 +0800 Subject: ACPICA: Fix cached object deletion code. Function acpi_ut_delete_caches() is meant to be used to implement ACPI_ALLOCATE()/ACPI_FREE() mechanisms in ACPICA, so it should call acpi_os_free() rather than ACPI_FREE(). Linux is not affected by this issue as it uses kmem_cache instead of the ACPICA local cache, but the change helps to reduce source code differences between Linux and ACPICA upstream. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index d844796..814267f 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c @@ -209,10 +209,10 @@ acpi_status acpi_ut_delete_caches(void) /* Free memory lists */ - ACPI_FREE(acpi_gbl_global_list); + acpi_os_free(acpi_gbl_global_list); acpi_gbl_global_list = NULL; - ACPI_FREE(acpi_gbl_ns_node_list); + acpi_os_free(acpi_gbl_ns_node_list); acpi_gbl_ns_node_list = NULL; #endif -- cgit v0.10.2 From a4fb614ad01506aa45f894f0f1c912e99cc7fdf1 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:31:06 +0800 Subject: ACPICA: Update compilation environment settings. This patch updates architecture specific environment settings to reduce source differences between Linux and ACPICA upstream. This patch does not affect the generation of the Linux kernel binary. Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index ef04b36..9b3966c 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -147,6 +147,9 @@ #if defined(_LINUX) || defined(__linux__) #include +#elif defined(_APPLE) || defined(__APPLE__) +#include "acmacosx.h" + #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "acfreebsd.h" -- cgit v0.10.2 From efb835429fff1488e4718138cdf5bc855a6762a4 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:31:12 +0800 Subject: ACPICA: Update acpidump related header file changes. This patch updates header files used by acpidump to reduce the source code differences between Linux and ACPICA upstream. This patch does not affect the generation of the Linux kernel binary. Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 0e32b6c..809b1a0 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -315,6 +315,14 @@ typedef u32 acpi_physical_address; #define ACPI_EXPORT_SYMBOL(symbol) #endif +/* + * Compiler/Clibrary-dependent debug initialization. Used for ACPICA + * utilities only. + */ +#ifndef ACPI_DEBUG_INITIALIZE +#define ACPI_DEBUG_INITIALIZE() +#endif + /******************************************************************************* * * Configuration diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index 9b3966c..974d3ef 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -96,10 +96,11 @@ #endif /* - * acpi_bin/acpi_help/acpi_src configuration. All single threaded, with - * no debug output. + * acpi_bin/acpi_dump/acpi_src/acpi_xtract configuration. All single + * threaded, with no debug output. */ #if (defined ACPI_BIN_APP) || \ + (defined ACPI_DUMP_APP) || \ (defined ACPI_SRC_APP) || \ (defined ACPI_XTRACT_APP) #define ACPI_APPLICATION -- cgit v0.10.2 From 40bce100cafb945f1fb5475a70628b4379c74f38 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:31:18 +0800 Subject: ACPICA: Cleanup asmlinkage for ACPICA APIs. Add an asmlinkage wrapper around acpi_enter_sleep_state() to prevent an empty stub from being called by assmebly code for ACPI_REDUCED_HARDWARE set. As arch/x86/kernel/acpi/wakeup_xx.S is only compiled when CONFIG_ACPI=y and there are no users of ACPI_HARDWARE_REDUCED, currently this is in fact not a real issue, but a cleanup to reduce source code differences between Linux and ACPICA upstream. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 3312010..3a2ae4c 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -26,6 +26,17 @@ static char temp_stack[4096]; #endif /** + * x86_acpi_enter_sleep_state - enter sleep state + * @state: Sleep state to enter. + * + * Wrapper around acpi_enter_sleep_state() to be called by assmebly. + */ +acpi_status asmlinkage x86_acpi_enter_sleep_state(u8 state) +{ + return acpi_enter_sleep_state(state); +} + +/** * x86_acpi_suspend_lowlevel - save kernel state * * Create an identity mapped page table and copy the wakeup routine to diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index c9c2c98..65c7b60 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h @@ -17,3 +17,5 @@ extern void wakeup_long64(void); extern void do_suspend_lowlevel(void); extern int x86_acpi_suspend_lowlevel(void); + +acpi_status asmlinkage x86_acpi_enter_sleep_state(u8 state); diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S index d1daa66..665c6b7 100644 --- a/arch/x86/kernel/acpi/wakeup_32.S +++ b/arch/x86/kernel/acpi/wakeup_32.S @@ -73,7 +73,7 @@ ENTRY(do_suspend_lowlevel) call save_processor_state call save_registers pushl $3 - call acpi_enter_sleep_state + call x86_acpi_enter_sleep_state addl $4, %esp # In case of S3 failure, we'll emerge here. Jump diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S index 8ea5164..ae693b5 100644 --- a/arch/x86/kernel/acpi/wakeup_64.S +++ b/arch/x86/kernel/acpi/wakeup_64.S @@ -73,7 +73,7 @@ ENTRY(do_suspend_lowlevel) addq $8, %rsp movl $3, %edi xorl %eax, %eax - call acpi_enter_sleep_state + call x86_acpi_enter_sleep_state /* in case something went wrong, restore the machine status and go on */ jmp resume_point diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index 4895fca..15dddc1 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -167,7 +167,7 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) +acpi_status acpi_enter_sleep_state_s4bios(void) { u32 in_value; acpi_status status; @@ -361,7 +361,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) +acpi_status acpi_enter_sleep_state(u8 sleep_state) { acpi_status status; diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 7def8ca..00725f4 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -510,9 +510,9 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *slp_typ_a, u8 *slp_typ_b); acpi_status acpi_enter_sleep_state_prep(u8 sleep_state); -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state); +acpi_status acpi_enter_sleep_state(u8 sleep_state); -ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)) +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enter_sleep_state_s4bios(void)) acpi_status acpi_leave_sleep_state_prep(u8 sleep_state); -- cgit v0.10.2 From 45c9f78b25ad9ce6cdf259ac4b652e6783adcb23 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 31 Oct 2013 09:31:24 +0800 Subject: ACPICA: Add __init for ACPICA initializers/finalizers. This patch adds __init to the ACPICA documented initializers: acpi_initialize_tables() acpi_initialize_subsystem() acpi_load_tables() acpi_enable_subsystem() acpi_initialize_objects() and to acpi_reallocate_root_table(), acpi_find_root_pointer() which are also meant to be called only during initialization. This patch adds __init to the ACPICA documented finalizer: acpi_terminate() as this finalizer is only called in __init function now. This change helps to reduce source code differences between ACPICA upstream and Linux. [rjw: Changelog] Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 43ffe21..3d6bb83 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -430,8 +430,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) * ******************************************************************************/ -acpi_status __init -acpi_tb_parse_root_table(acpi_physical_address rsdp_address) +acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) { struct acpi_table_rsdp *rsdp; u32 table_entry_size; diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 7e63090..db826ea 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -164,7 +164,7 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables) * kernel. * ******************************************************************************/ -acpi_status acpi_reallocate_root_table(void) +acpi_status __init acpi_reallocate_root_table(void) { acpi_status status; diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index b1e1edd..60b5a87 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -66,7 +66,7 @@ static acpi_status acpi_tb_load_namespace(void); * ******************************************************************************/ -acpi_status acpi_load_tables(void) +acpi_status __init acpi_load_tables(void) { acpi_status status; diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index 1c95fab..e4e1468 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -111,7 +111,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * ******************************************************************************/ -acpi_status acpi_find_root_pointer(acpi_size *table_address) +acpi_status __init acpi_find_root_pointer(acpi_size *table_address) { u8 *table_ptr; u8 *mem_rover; diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 3986902..be322c8 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -61,7 +61,7 @@ ACPI_MODULE_NAME("utxface") * DESCRIPTION: Shutdown the ACPICA subsystem and release all resources. * ******************************************************************************/ -acpi_status acpi_terminate(void) +acpi_status __init acpi_terminate(void) { acpi_status status; diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index ff6f4d1..75efea0 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -65,7 +65,7 @@ ACPI_MODULE_NAME("utxfinit") * called, so any early initialization belongs here. * ******************************************************************************/ -acpi_status acpi_initialize_subsystem(void) +acpi_status __init acpi_initialize_subsystem(void) { acpi_status status; @@ -140,7 +140,7 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_subsystem) * Puts system into ACPI mode if it isn't already. * ******************************************************************************/ -acpi_status acpi_enable_subsystem(u32 flags) +acpi_status __init acpi_enable_subsystem(u32 flags) { acpi_status status = AE_OK; @@ -245,7 +245,7 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_enable_subsystem) * objects and executing AML code for Regions, buffers, etc. * ******************************************************************************/ -acpi_status acpi_initialize_objects(u32 flags) +acpi_status __init acpi_initialize_objects(u32 flags) { acpi_status status = AE_OK; diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 00725f4..d8f9457 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -114,17 +114,17 @@ extern u8 acpi_gbl_disable_ssdt_table_load; /* * Initialization */ -acpi_status +acpi_status __init acpi_initialize_tables(struct acpi_table_desc *initial_storage, u32 initial_table_count, u8 allow_resize); acpi_status __init acpi_initialize_subsystem(void); -acpi_status acpi_enable_subsystem(u32 flags); +acpi_status __init acpi_enable_subsystem(u32 flags); -acpi_status acpi_initialize_objects(u32 flags); +acpi_status __init acpi_initialize_objects(u32 flags); -acpi_status acpi_terminate(void); +acpi_status __init acpi_terminate(void); /* * Miscellaneous global interfaces @@ -168,14 +168,14 @@ acpi_status acpi_load_table(struct acpi_table_header *table); acpi_status acpi_unload_parent_table(acpi_handle object); -acpi_status acpi_load_tables(void); +acpi_status __init acpi_load_tables(void); /* * ACPI table manipulation interfaces */ -acpi_status acpi_reallocate_root_table(void); +acpi_status __init acpi_reallocate_root_table(void); -acpi_status acpi_find_root_pointer(acpi_size * rsdp_address); +acpi_status __init acpi_find_root_pointer(acpi_size *rsdp_address); acpi_status acpi_unload_table_id(acpi_owner_id id); -- cgit v0.10.2 From 880eef041655b35f9aa488726ea3c4303a4f2204 Mon Sep 17 00:00:00 2001 From: Stratos Karafotis Date: Thu, 31 Oct 2013 20:27:36 +0200 Subject: cpufreq: ondemand: Remove redundant return statement After commit dfa5bb622555 (cpufreq: ondemand: Change the calculation of target frequency), this return statement is no longer needed. Reported-by: Henrik Nilsson Signed-off-by: Stratos Karafotis Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 32f26f6..18d4091 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -168,7 +168,6 @@ static void od_check_cpu(int cpu, unsigned int load) dbs_info->rate_mult = od_tuners->sampling_down_factor; dbs_freq_increase(policy, policy->max); - return; } else { /* Calculate the next frequency proportional to load */ unsigned int freq_next; -- cgit v0.10.2 From 08ff4cbe10da402e7c493ac72e298975f62a9e78 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 4 Nov 2013 08:53:10 -0800 Subject: PowerCap: Fix build error with option -Werror=format-security Fix compile error with gcc option: -Werror=format-security for dev_set_name(&control_type->dev, name). Changed to dev_set_name(&control_type->dev, "%s", name). Signed-off-by: Srinivas Pandruvada Acked-by: Kees Cook Signed-off-by: Rafael J. Wysocki diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c index 21814f9..8d0fe43 100644 --- a/drivers/powercap/powercap_sys.c +++ b/drivers/powercap/powercap_sys.c @@ -625,7 +625,7 @@ struct powercap_control_type *powercap_register_control_type( control_type->ops = ops; INIT_LIST_HEAD(&control_type->node); control_type->dev.class = &powercap_class; - dev_set_name(&control_type->dev, name); + dev_set_name(&control_type->dev, "%s", name); result = device_register(&control_type->dev); if (result) { if (control_type->allocated) -- cgit v0.10.2 From f0eb2e5dc06f5e100d59bb49a823f9a294e82db7 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Tue, 5 Nov 2013 01:20:42 -0600 Subject: ACPI / blacklist: fix name of ThinkPad Edge E530 That is the advertised name. http://shop.lenovo.com/us/en/laptops/thinkpad/edge-series/e530/ Signed-off-by: Felipe Contreras Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index b7fd1ae..fb84837 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -304,7 +304,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { .callback = dmi_disable_osi_win8, - .ident = "Lenovo ThinkPad Edge E530", + .ident = "ThinkPad Edge E530", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), -- cgit v0.10.2 From 71bba8fafac8975dbb684df4098d2dd6baac1fda Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:40:50 +0100 Subject: ACPI: Remove acpi_pci_slot_init() headers from internal.h Since acpi_pci_slot_init() is now called from acpi_pci_init() and pci-acpi.h contains its header, remove that header (and the empty definition of that function for CONFIG_ACPI_PCI_SLOT unset) from internal.h as it doesn't have to be there any more. That also avoids a build warning about duplicate function definitions for CONFIG_ACPI_PCI_SLOT unset. Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 20f4233..ebc3ad0 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -26,11 +26,6 @@ acpi_status acpi_os_initialize1(void); int init_acpi_device_notify(void); int acpi_scan_init(void); -#ifdef CONFIG_ACPI_PCI_SLOT -void acpi_pci_slot_init(void); -#else -static inline void acpi_pci_slot_init(void) { } -#endif void acpi_pci_root_init(void); void acpi_pci_link_init(void); void acpi_pci_root_hp_init(void); -- cgit v0.10.2 From 6931007cc90ba94b3c2b29179d0a7cde194dabe8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:01 +0100 Subject: ACPI / scan: Start matching drivers after trying scan handlers ACPI scan handlers should always be attached to struct acpi_device objects before any ACPI drivers, but there is a window during which a driver may be attached to a struct acpi_device before checking if there is a matching scan handler. Namely, that will happen if an ACPI driver module is loaded during acpi_bus_scan() right after the first namespace walk is complete and before the given device is processed by the second namespace walk. To prevent that from happening, set the match_driver flags of struct acpi_device objects right before running device_attach() for them in acpi_bus_device_attach(). Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index fbdb82e..4d377a2 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1677,7 +1677,6 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, void acpi_device_add_finalize(struct acpi_device *device) { - device->flags.match_driver = true; dev_set_uevent_suppress(&device->dev, false); kobject_uevent(&device->dev.kobj, KOBJ_ADD); } @@ -1916,8 +1915,12 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, return AE_OK; ret = acpi_scan_attach_handler(device); - if (ret) - return ret > 0 ? AE_OK : AE_CTRL_DEPTH; + if (ret < 0) + return AE_CTRL_DEPTH; + + device->flags.match_driver = true; + if (ret > 0) + return AE_OK; ret = device_attach(&device->dev); return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; -- cgit v0.10.2 From 7f28ddeccea453fd20b1c74a88df19590ad9203c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:14 +0100 Subject: ACPI / hotplug: Refuse to hot-remove all objects with disabled hotplug In theory, an ACPI device object may be the parent of another device object whose hotplug is disabled by user space through its scan handler. In that case, the eject operation targeting the parent should fail as though the parent's own hotplug was disabled, but currently this is not the case, because acpi_scan_hot_remove() doesn't check the disable/enable hotplug status of the children of the top-most object passed to it. To fix this, modify acpi_bus_offline_companions() to return an error code if hotplug is disabled for the given device object. [Also change the name of the function to acpi_bus_offline(), because it is not only about companions any more, and change the name of acpi_bus_online_companions() accordingly.] Make acpi_scan_hot_remove() propagate that error to its callers. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4d377a2..9bdcc18 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -125,8 +125,8 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); -static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, - void *data, void **ret_p) +static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, + void **ret_p) { struct acpi_device *device = NULL; struct acpi_device_physical_node *pn; @@ -136,6 +136,11 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, if (acpi_bus_get_device(handle, &device)) return AE_OK; + if (device->handler && !device->handler->hotplug.enabled) { + *ret_p = &device->dev; + return AE_SUPPORT; + } + mutex_lock(&device->physical_node_lock); list_for_each_entry(pn, &device->physical_node_list, node) { @@ -168,8 +173,8 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, return status; } -static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl, - void *data, void **ret_p) +static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data, + void **ret_p) { struct acpi_device *device = NULL; struct acpi_device_physical_node *pn; @@ -214,26 +219,32 @@ static int acpi_scan_hot_remove(struct acpi_device *device) * If the first pass is successful, the second one isn't needed, though. */ errdev = NULL; - acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - NULL, acpi_bus_offline_companions, - (void *)false, (void **)&errdev); - acpi_bus_offline_companions(handle, 0, (void *)false, (void **)&errdev); + status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + NULL, acpi_bus_offline, (void *)false, + (void **)&errdev); + if (status == AE_SUPPORT) { + dev_warn(errdev, "Offline disabled.\n"); + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_online, NULL, NULL, NULL); + put_device(&device->dev); + return -EPERM; + } + acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); if (errdev) { errdev = NULL; acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - NULL, acpi_bus_offline_companions, - (void *)true , (void **)&errdev); + NULL, acpi_bus_offline, (void *)true, + (void **)&errdev); if (!errdev || acpi_force_hot_remove) - acpi_bus_offline_companions(handle, 0, (void *)true, - (void **)&errdev); + acpi_bus_offline(handle, 0, (void *)true, + (void **)&errdev); if (errdev && !acpi_force_hot_remove) { dev_warn(errdev, "Offline failed.\n"); - acpi_bus_online_companions(handle, 0, NULL, NULL); + acpi_bus_online(handle, 0, NULL, NULL); acpi_walk_namespace(ACPI_TYPE_ANY, handle, - ACPI_UINT32_MAX, - acpi_bus_online_companions, NULL, - NULL, NULL); + ACPI_UINT32_MAX, acpi_bus_online, + NULL, NULL, NULL); put_device(&device->dev); return -EBUSY; } @@ -290,10 +301,9 @@ static void acpi_bus_device_eject(void *context) goto err_out; handler = device->handler; - if (!handler || !handler->hotplug.enabled) { - ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; - goto err_out; - } + if (!handler || !handler->hotplug.enabled) + goto err_support; + acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); if (handler->hotplug.mode == AHM_CONTAINER) @@ -301,14 +311,19 @@ static void acpi_bus_device_eject(void *context) get_device(&device->dev); error = acpi_scan_hot_remove(device); - if (error) + if (error == -EPERM) { + goto err_support; + } else if (error) { goto err_out; + } out: mutex_unlock(&acpi_scan_lock); unlock_device_hotplug(); return; + err_support: + ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; err_out: acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code, NULL); -- cgit v0.10.2 From 2441191a19039002b2c454a261fb45986df15184 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:27 +0100 Subject: ACPI / hotplug: Fix handle_root_bridge_removal() It is required to do get_device() on the struct acpi_device in question before passing it to acpi_bus_hot_remove_device() through acpi_os_hotplug_execute(), because acpi_bus_hot_remove_device() calls acpi_scan_hot_remove() that does put_device() on that object. The ACPI PCI root removal routine, handle_root_bridge_removal(), doesn't do that, which may lead to premature freeing of the device object or to executing put_device() on an object that has been freed already. Fix this problem by making handle_root_bridge_removal() use get_device() as appropriate. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani Cc: All applicable diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d3874f4..d7e53ea 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -608,9 +608,12 @@ static void handle_root_bridge_removal(struct acpi_device *device) ej_event->device = device; ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; + get_device(&device->dev); status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + put_device(&device->dev); kfree(ej_event); + } } static void _handle_hotplug_event_root(struct work_struct *work) -- cgit v0.10.2 From 5add99cfef416487d32b4b7075fe1a409f3a5e82 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:39 +0100 Subject: ACPI / hotplug: Simplify device ejection routines Simplify handle_root_bridge_removal() and acpi_eject_store() by getting rid of struct acpi_eject_event and passing device objects directly to async routines executed via acpi_os_hotplug_execute(). Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d7e53ea..2c03aae 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -593,27 +593,11 @@ static void handle_root_bridge_insertion(acpi_handle handle) static void handle_root_bridge_removal(struct acpi_device *device) { acpi_status status; - struct acpi_eject_event *ej_event; - - ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); - if (!ej_event) { - /* Inform firmware the hot-remove operation has error */ - (void) acpi_evaluate_hotplug_ost(device->handle, - ACPI_NOTIFY_EJECT_REQUEST, - ACPI_OST_SC_NON_SPECIFIC_FAILURE, - NULL); - return; - } - - ej_event->device = device; - ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; get_device(&device->dev); - status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); - if (ACPI_FAILURE(status)) { + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, device); + if (ACPI_FAILURE(status)) put_device(&device->dev); - kfree(ej_event); - } } static void _handle_hotplug_event_root(struct work_struct *work) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9bdcc18..cc19d62 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -441,18 +441,8 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) NULL); } -/** - * acpi_bus_hot_remove_device: hot-remove a device and its children - * @context: struct acpi_eject_event pointer (freed in this func) - * - * Hot-remove a device and its children. This function frees up the - * memory space passed by arg context, so that the caller may call - * this function asynchronously through acpi_os_hotplug_execute(). - */ -void acpi_bus_hot_remove_device(void *context) +void __acpi_bus_hot_remove_device(struct acpi_device *device, u32 ost_src) { - struct acpi_eject_event *ej_event = context; - struct acpi_device *device = ej_event->device; acpi_handle handle = device->handle; int error; @@ -461,13 +451,21 @@ void acpi_bus_hot_remove_device(void *context) error = acpi_scan_hot_remove(device); if (error && handle) - acpi_evaluate_hotplug_ost(handle, ej_event->event, + acpi_evaluate_hotplug_ost(handle, ost_src, ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); mutex_unlock(&acpi_scan_lock); unlock_device_hotplug(); - kfree(context); +} + +/** + * acpi_bus_hot_remove_device: Hot-remove a device and its children. + * @context: Address of the ACPI device object to hot-remove. + */ +void acpi_bus_hot_remove_device(void *context) +{ + __acpi_bus_hot_remove_device(context, ACPI_NOTIFY_EJECT_REQUEST); } EXPORT_SYMBOL(acpi_bus_hot_remove_device); @@ -497,15 +495,18 @@ static ssize_t power_state_show(struct device *dev, static DEVICE_ATTR(power_state, 0444, power_state_show, NULL); +static void acpi_eject_store_work(void *context) +{ + __acpi_bus_hot_remove_device(context, ACPI_OST_EC_OSPM_EJECT); +} + static ssize_t acpi_eject_store(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { struct acpi_device *acpi_device = to_acpi_device(d); - struct acpi_eject_event *ej_event; acpi_object_type not_used; acpi_status status; - int ret; if (!count || buf[0] != '1') return -EINVAL; @@ -518,28 +519,17 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) return -ENODEV; - ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); - if (!ej_event) { - ret = -ENOMEM; - goto err_out; - } acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); - ej_event->device = acpi_device; - ej_event->event = ACPI_OST_EC_OSPM_EJECT; get_device(&acpi_device->dev); - status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); + status = acpi_os_hotplug_execute(acpi_eject_store_work, acpi_device); if (ACPI_SUCCESS(status)) return count; put_device(&acpi_device->dev); - kfree(ej_event); - ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; - - err_out: acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); - return ret; + return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; } static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 02e113b..06b644c 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -339,11 +339,6 @@ struct acpi_bus_event { u32 data; }; -struct acpi_eject_event { - struct acpi_device *device; - u32 event; -}; - struct acpi_hp_work { struct work_struct work; acpi_handle handle; -- cgit v0.10.2 From ace8238b00eafd493b8dbcc7db813ed72b8b6e87 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:48 +0100 Subject: ACPI / hotplug: Make acpi_bus_hot_remove_device() internal Notice that handle_root_bridge_removal() is the only user of acpi_bus_hot_remove_device(), so it doesn't have to be exported any more and can be made internal to the ACPI core. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index ebc3ad0..6c79ae6 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -87,6 +87,7 @@ void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); int acpi_bind_one(struct device *dev, acpi_handle handle); int acpi_unbind_one(struct device *dev); +void acpi_bus_hot_remove_device(void *context); /* -------------------------------------------------------------------------- Power Resource diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 2c03aae..add408b 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -39,6 +39,8 @@ #include #include +#include "internal.h" + #define PREFIX "ACPI: " #define _COMPONENT ACPI_PCI_COMPONENT diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index cc19d62..1217ba3 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -467,7 +467,6 @@ void acpi_bus_hot_remove_device(void *context) { __acpi_bus_hot_remove_device(context, ACPI_NOTIFY_EJECT_REQUEST); } -EXPORT_SYMBOL(acpi_bus_hot_remove_device); static ssize_t real_power_state_show(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 06b644c..eb37a6f 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -386,7 +386,6 @@ int acpi_scan_add_handler(struct acpi_scan_handler *handler); int acpi_bus_register_driver(struct acpi_driver *driver); void acpi_bus_unregister_driver(struct acpi_driver *driver); int acpi_bus_scan(acpi_handle handle); -void acpi_bus_hot_remove_device(void *context); void acpi_bus_trim(struct acpi_device *start); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); int acpi_match_device_ids(struct acpi_device *device, -- cgit v0.10.2 From a3b1b1ef78cd2ffb5d3a223465064dee05929dc3 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:58 +0100 Subject: ACPI / hotplug: Merge device hot-removal routines There is no real reasn why acpi_bus_device_eject() and acpi_bus_hot_remove_device() should work differently, so rework acpi_bus_device_eject() so that it can be called internally by both acpi_bus_hot_remove_device() and acpi_eject_store_work(). Accordingly, rework acpi_hotplug_notify_cb() to queue up the execution of acpi_bus_hot_remove_device() through acpi_os_hotplug_execute() on eject request notifications. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 1217ba3..4a0a591 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -285,10 +285,9 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return 0; } -static void acpi_bus_device_eject(void *context) +static void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src) { - acpi_handle handle = context; - struct acpi_device *device = NULL; + acpi_handle handle = device->handle; struct acpi_scan_handler *handler; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; int error; @@ -296,20 +295,19 @@ static void acpi_bus_device_eject(void *context) lock_device_hotplug(); mutex_lock(&acpi_scan_lock); - acpi_bus_get_device(handle, &device); - if (!device) - goto err_out; - handler = device->handler; - if (!handler || !handler->hotplug.enabled) + if (!handler || !handler->hotplug.enabled) { + put_device(&device->dev); goto err_support; + } + + if (ost_src == ACPI_NOTIFY_EJECT_REQUEST) + acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, + ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); - acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, - ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); if (handler->hotplug.mode == AHM_CONTAINER) kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); - get_device(&device->dev); error = acpi_scan_hot_remove(device); if (error == -EPERM) { goto err_support; @@ -325,8 +323,7 @@ static void acpi_bus_device_eject(void *context) err_support: ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; err_out: - acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code, - NULL); + acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL); goto out; } @@ -408,10 +405,20 @@ static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL); } +/** + * acpi_bus_hot_remove_device: Hot-remove a device and its children. + * @context: Address of the ACPI device object to hot-remove. + */ +void acpi_bus_hot_remove_device(void *context) +{ + acpi_bus_device_eject(context, ACPI_NOTIFY_EJECT_REQUEST); +} + static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) { acpi_osd_exec_callback callback; struct acpi_scan_handler *handler = data; + struct acpi_device *adev; acpi_status status; if (!handler->hotplug.enabled) @@ -428,44 +435,29 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) break; case ACPI_NOTIFY_EJECT_REQUEST: acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); - callback = acpi_bus_device_eject; - break; + status = acpi_bus_get_device(handle, &adev); + if (ACPI_FAILURE(status)) + goto err_out; + + get_device(&adev->dev); + callback = acpi_bus_hot_remove_device; + status = acpi_os_hotplug_execute(callback, adev); + if (ACPI_SUCCESS(status)) + return; + + put_device(&adev->dev); + goto err_out; default: /* non-hotplug event; possibly handled by other handler */ return; } status = acpi_os_hotplug_execute(callback, handle); - if (ACPI_FAILURE(status)) - acpi_evaluate_hotplug_ost(handle, type, - ACPI_OST_SC_NON_SPECIFIC_FAILURE, - NULL); -} - -void __acpi_bus_hot_remove_device(struct acpi_device *device, u32 ost_src) -{ - acpi_handle handle = device->handle; - int error; - - lock_device_hotplug(); - mutex_lock(&acpi_scan_lock); - - error = acpi_scan_hot_remove(device); - if (error && handle) - acpi_evaluate_hotplug_ost(handle, ost_src, - ACPI_OST_SC_NON_SPECIFIC_FAILURE, - NULL); - - mutex_unlock(&acpi_scan_lock); - unlock_device_hotplug(); -} + if (ACPI_SUCCESS(status)) + return; -/** - * acpi_bus_hot_remove_device: Hot-remove a device and its children. - * @context: Address of the ACPI device object to hot-remove. - */ -void acpi_bus_hot_remove_device(void *context) -{ - __acpi_bus_hot_remove_device(context, ACPI_NOTIFY_EJECT_REQUEST); + err_out: + acpi_evaluate_hotplug_ost(handle, type, + ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); } static ssize_t real_power_state_show(struct device *dev, @@ -496,7 +488,7 @@ static DEVICE_ATTR(power_state, 0444, power_state_show, NULL); static void acpi_eject_store_work(void *context) { - __acpi_bus_hot_remove_device(context, ACPI_OST_EC_OSPM_EJECT); + acpi_bus_device_eject(context, ACPI_OST_EC_OSPM_EJECT); } static ssize_t -- cgit v0.10.2 From 43d388832bd3e413e9b5e6f3caef4b0844b901af Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:42:09 +0100 Subject: ACPI / hotplug: Carry out PCI root eject directly Since _handle_hotplug_event_root() is run from the ACPI hotplug workqueue, it doesn't need to queue up a work item to eject a PCI host bridge on the same workqueue. Instead, it can just carry out the eject by calling acpi_bus_device_eject() directly, so make that happen. Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 6c79ae6..80cd1a1 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -87,7 +87,7 @@ void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); int acpi_bind_one(struct device *dev, acpi_handle handle); int acpi_unbind_one(struct device *dev); -void acpi_bus_hot_remove_device(void *context); +void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src); /* -------------------------------------------------------------------------- Power Resource diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index add408b..d77f0bf 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -592,16 +592,6 @@ static void handle_root_bridge_insertion(acpi_handle handle) acpi_handle_err(handle, "cannot add bridge to acpi list\n"); } -static void handle_root_bridge_removal(struct acpi_device *device) -{ - acpi_status status; - - get_device(&device->dev); - status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, device); - if (ACPI_FAILURE(status)) - put_device(&device->dev); -} - static void _handle_hotplug_event_root(struct work_struct *work) { struct acpi_pci_root *root; @@ -612,6 +602,7 @@ static void _handle_hotplug_event_root(struct work_struct *work) hp_work = container_of(work, struct acpi_hp_work, work); handle = hp_work->handle; type = hp_work->type; + kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ acpi_scan_lock_acquire(); @@ -641,9 +632,15 @@ static void _handle_hotplug_event_root(struct work_struct *work) /* request device eject */ acpi_handle_printk(KERN_DEBUG, handle, "Device eject notify on %s\n", __func__); - if (root) - handle_root_bridge_removal(root->device); - break; + if (!root) + break; + + get_device(&root->device->dev); + + acpi_scan_lock_release(); + + acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST); + return; default: acpi_handle_warn(handle, "notify_handler: unknown event type 0x%x\n", @@ -652,7 +649,6 @@ static void _handle_hotplug_event_root(struct work_struct *work) } acpi_scan_lock_release(); - kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ } static void handle_hotplug_event_root(acpi_handle handle, u32 type, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4a0a591..c7317fe 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -285,7 +285,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return 0; } -static void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src) +void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src) { acpi_handle handle = device->handle; struct acpi_scan_handler *handler; @@ -409,7 +409,7 @@ static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) * acpi_bus_hot_remove_device: Hot-remove a device and its children. * @context: Address of the ACPI device object to hot-remove. */ -void acpi_bus_hot_remove_device(void *context) +static void acpi_bus_hot_remove_device(void *context) { acpi_bus_device_eject(context, ACPI_NOTIFY_EJECT_REQUEST); } -- cgit v0.10.2 From 176a88d79d6b5aebabaff16734e8b3107efcaaad Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:42:17 +0100 Subject: ACPI / hotplug: Do not execute "insert in progress" _OST According to the ACPI spec (5.0, Section 6.3.5), the "Device insertion in progress (pending)" (0x80) _OST status code is reserved for the "Insertion Processing" (0x200) source event which is "a result of an OSPM action". Specifically, it is not a notification, so that status code should not be used during notification processing, which unfortunately is done by acpi_scan_bus_device_check(). For this reason, drop the ACPI_OST_SC_INSERT_IN_PROGRESS _OST status evaluation from there (it was a mistake to put it in there in the first place). Signed-off-by: Rafael J. Wysocki Cc: All applicable diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c7317fe..5cd7f8c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -343,8 +343,6 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) goto out; } } - acpi_evaluate_hotplug_ost(handle, ost_source, - ACPI_OST_SC_INSERT_IN_PROGRESS, NULL); error = acpi_bus_scan(handle); if (error) { acpi_handle_warn(handle, "Namespace scan failure\n"); -- cgit v0.10.2 From fd432b9f8c7c88428a4635b9f5a9c6e174df6e36 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 6 Nov 2013 08:41:31 +0800 Subject: PM / hibernate: Avoid overflow in hibernate_preallocate_memory() When system has a lot of highmem (e.g. 16GiB using a 32 bits kernel), the code to calculate how much memory we need to preallocate in normal zone may cause overflow. As Leon has analysed: It looks that during computing 'alloc' variable there is overflow: alloc = (3943404 - 1970542) - 1978280 = -5418 (signed) And this function goes to err_out. Fix this by avoiding that overflow. References: https://bugzilla.kernel.org/show_bug.cgi?id=60817 Reported-and-tested-by: Leon Drugi Cc: All applicable Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 98c3b34..10c22ca 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -1402,7 +1402,11 @@ int hibernate_preallocate_memory(void) * highmem and non-highmem zones separately. */ pages_highmem = preallocate_image_highmem(highmem / 2); - alloc = (count - max_size) - pages_highmem; + alloc = count - max_size; + if (alloc > pages_highmem) + alloc -= pages_highmem; + else + alloc = 0; pages = preallocate_image_memory(alloc, avail_normal); if (pages < alloc) { /* We have exhausted non-highmem pages, try highmem. */ -- cgit v0.10.2 From fbbcdc0744dace5fcc8147d11c5fb0791126848a Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Thu, 31 Oct 2013 23:24:05 +0800 Subject: intel_pstate: skip the driver if ACPI has power mgmt option Do not load the Intel pstate driver if the platform firmware (ACPI BIOS) supports the power management alternatives. The ACPI BIOS indicates that the OS control mode can be used if the _PSS (Performance Supported States) is defined in ACPI table. For the OS control mode, the Intel pstate driver will be loaded. HP BIOS has several power management modes (firmware, OS-control and so on). For the OS control mode in HP BIOS, the Intel p-state driver will be loaded. When the customer chooses the firmware power management in HP BIOS, the Intel p-state driver will be ignored. I put hw_vendor_info vendor_info in case other vendors (Dell, Lenovo...) have their firmware power management. Vendors should make sure their firmware power management works properly, and they can go for adding their vendor info to the variable. I have verified the patch on HP ProLiant servers. The patch worked correctly. Signed-off-by: Adrian Huang [rjw: Fixed up !CONFIG_ACPI build] [Linda Knippers: As Adrian has recently left HP, I retested the updated patch on an HP ProLiant server and verified that it is behaving correctly. When the BIOS is configured for OS control for power management, the intel_pstate driver loads as expected. When the BIOS is configured to provide the power management, the intel_pstate driver does not load and we get the pcc_cpufreq driver instead.] Signed-off-by: Linda Knippers Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 81e0062..3b5c535 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -779,6 +780,72 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) pstate_funcs.set = funcs->set; } +#if IS_ENABLED(CONFIG_ACPI) +#include + +static bool intel_pstate_no_acpi_pss(void) +{ + int i; + + for_each_possible_cpu(i) { + acpi_status status; + union acpi_object *pss; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_processor *pr = per_cpu(processors, i); + + if (!pr) + continue; + + status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); + if (ACPI_FAILURE(status)) + continue; + + pss = buffer.pointer; + if (pss && pss->type == ACPI_TYPE_PACKAGE) { + kfree(pss); + return false; + } + + kfree(pss); + } + + return true; +} + +struct hw_vendor_info { + u16 valid; + char oem_id[ACPI_OEM_ID_SIZE]; + char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; +}; + +/* Hardware vendor-specific info that has its own power management modes */ +static struct hw_vendor_info vendor_info[] = { + {1, "HP ", "ProLiant"}, + {0, "", ""}, +}; + +static bool intel_pstate_platform_pwr_mgmt_exists(void) +{ + struct acpi_table_header hdr; + struct hw_vendor_info *v_info; + + if (acpi_disabled + || ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr))) + return false; + + for (v_info = vendor_info; v_info->valid; v_info++) { + if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE) + && !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) + && intel_pstate_no_acpi_pss()) + return true; + } + + return false; +} +#else /* CONFIG_ACPI not enabled */ +static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; } +#endif /* CONFIG_ACPI */ + static int __init intel_pstate_init(void) { int cpu, rc = 0; @@ -792,6 +859,13 @@ static int __init intel_pstate_init(void) if (!id) return -ENODEV; + /* + * The Intel pstate driver will be ignored if the platform + * firmware has its own power management modes. + */ + if (intel_pstate_platform_pwr_mgmt_exists()) + return -ENODEV; + cpu_info = (struct cpu_defaults *)id->driver_data; copy_pid_params(&cpu_info->pid_policy); -- cgit v0.10.2 From 9efa5e50598c5568b0678bb411b239a0b6e9a328 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 6 Nov 2013 09:03:15 +0800 Subject: ACPI / video: Fix initial level validity test When testing if the firmware's initial value is valid, we should use the corrected level value instead of the raw value returned from firmware. Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 38c3a28..bf521b3 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -856,7 +856,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) * or an index). Set the backlight to max_level in this case. */ for (i = 2; i < br->count; i++) - if (level_old == br->levels[i]) + if (level == br->levels[i]) break; if (i == br->count) level = max_level; -- cgit v0.10.2 From 2c62333a408f5badd2d2ffd7177f95deeccc5ca4 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 6 Nov 2013 09:07:10 +0800 Subject: ACPI / video: Quirk initial backlight level 0 Some firmware doesn't initialize initial backlight level to a proper value and _BQC will return 0 on first time evaluation. We used to be able to detect such incorrect value with our code logic, as value 0 normally isn't a valid value in _BCL. But with the introduction of Win8, firmware begins to fill _BCL with values from 0 to 100, now 0 becomes a valid value but that value will make user's screen black. This patch test initial _BQC for value 0, if such a value is returned, do not use it. References: https://bugzilla.kernel.org/show_bug.cgi?id=64031 References: https://bugzilla.kernel.org/show_bug.cgi?id=61231 References: https://bugzilla.kernel.org/show_bug.cgi?id=63111 Reported-by: Qingshuai Tian Tested-by: Aaron Lu # on "Idealpad u330p" Reported-and-tested-by: # on "Acer Aspire V5-573G" Reported-and-tested-by: Kirill Tkhai # on "HP 250 G1" Signed-off-by: Aaron Lu Cc: All applicable Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bf521b3..a049fa9 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -858,7 +858,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) for (i = 2; i < br->count; i++) if (level == br->levels[i]) break; - if (i == br->count) + if (i == br->count || !level) level = max_level; } -- cgit v0.10.2 From 906f187b93d4b15e54066802f2a3100ca4681296 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 6 Nov 2013 09:18:16 +0800 Subject: Revert "ACPI / video: Ignore BIOS initial backlight value for HP 250 G1" This reverts commit e37f14a5fb85522f3bbf88ece6134c4e610ed598. It turned out other systems also share the same problem with bug 63111 so I made a patch to catch initial brightness level 0 problem. With that patch applied, we do not need to place HP 250 G1 in DMI table. References: https://bugzilla.kernel.org/show_bug.cgi?id=63111 Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a049fa9..18dbdff 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -504,14 +504,6 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion m4 Notebook PC"), }, }, - { - .callback = video_ignore_initial_backlight, - .ident = "HP 250 G1", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G1 Notebook PC"), - }, - }, {} }; -- cgit v0.10.2 From 9968e459f1378a1c00301472cfe672497fe001d5 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Tue, 5 Nov 2013 21:25:32 +0100 Subject: ACPI / event: remove unneeded NULL pointer check nla_data() cannot return NULL as it simply adds NLA_HDRLEN to the passed pointer. The NULL pointer check is therefore superfluous. Remove it. Found by smatch: drivers/acpi/event.c:130 acpi_bus_generate_netlink_event() warn: can 'event' even be NULL? Signed-off-by: Mathias Krause Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 8247fcd..fdef416 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -127,11 +127,6 @@ int acpi_bus_generate_netlink_event(const char *device_class, } event = nla_data(attr); - if (!event) { - nlmsg_free(skb); - return -EINVAL; - } - memset(event, 0, sizeof(struct acpi_genl_event)); strcpy(event->device_class, device_class); -- cgit v0.10.2 From baab52ded242c35a2290e1fa82e0cc147d0d8c1a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:51:15 +0100 Subject: PM / runtime: Use pm_runtime_put_sync() in __device_release_driver() Commit fa180eb448fa (PM / Runtime: Idle devices asynchronously after probe|release) modified __device_release_driver() to call pm_runtime_put(dev) instead of pm_runtime_put_sync(dev) before detaching the driver from the device. However, that was a mistake, because pm_runtime_put(dev) causes rpm_idle() to be queued up and the driver may be gone already when that function is executed. That breaks the assumptions the drivers have the right to make about the core's behavior on the basis of the existing documentation and actually causes problems to happen, so revert that part of commit fa180eb448fa and restore the previous behavior of __device_release_driver(). Reported-by: Tomi Valkeinen Fixes: fa180eb448fa (PM / Runtime: Idle devices asynchronously after probe|release) Signed-off-by: Rafael J. Wysocki Acked-by: Kevin Hilman Acked-by: Ulf Hansson Cc: 3.10+ # 3.10+ diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 35fa368..0605176 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -499,7 +499,7 @@ static void __device_release_driver(struct device *dev) BUS_NOTIFY_UNBIND_DRIVER, dev); - pm_runtime_put(dev); + pm_runtime_put_sync(dev); if (dev->bus && dev->bus->remove) dev->bus->remove(dev); -- cgit v0.10.2 From 7b98118aaa5d75644c48f41fc5d0cc181e478383 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:45:40 +0100 Subject: ACPI / hotplug: Consolidate deferred execution of ACPI hotplug routines There are two different interfaces for queuing up work items on the ACPI hotplug workqueue, alloc_acpi_hp_work() used by PCI and PCI host bridge hotplug code and acpi_os_hotplug_execute() used by the common ACPI hotplug code and docking stations. They both are somewhat cumbersome to use and work slightly differently. The users of alloc_acpi_hp_work() have to submit a work function that will extract the necessary data items from a struct acpi_hp_work object allocated by alloc_acpi_hp_work() and then will free that object, while it would be more straightforward to simply use a work function with one more argument and let the interface take care of the execution details. The users of acpi_os_hotplug_execute() also have to deal with the fact that it takes only one argument in addition to the work function pointer, although acpi_os_execute_deferred() actually takes care of the allocation and freeing of memory, so it would have been able to pass more arguments to the work function if it hadn't been constrained by the connection with acpi_os_execute(). Moreover, while alloc_acpi_hp_work() makes GFP_KERNEL memory allocations, which is correct, because hotplug work items are always queued up from process context, acpi_os_hotplug_execute() uses GFP_ATOMIC, as that is needed by acpi_os_execute(). Also, acpi_os_execute_deferred() queued up by it waits for the ACPI event workqueues to flush before executing the work function, whereas alloc_acpi_hp_work() can't do anything similar. That leads to somewhat arbitrary differences in behavior between various ACPI hotplug code paths and has to be straightened up. For this reason, replace both alloc_acpi_hp_work() and acpi_os_hotplug_execute() with a single interface, acpi_hotplug_execute(), combining their behavior and being more friendly to its users than any of the two. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 05ea4be..eab7d11 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -671,39 +671,20 @@ static void dock_notify(struct dock_station *ds, u32 event) } } -struct dock_data { - struct dock_station *ds; - u32 event; -}; - -static void acpi_dock_deferred_cb(void *context) +static void acpi_dock_deferred_cb(void *data, u32 event) { - struct dock_data *data = context; - acpi_scan_lock_acquire(); - dock_notify(data->ds, data->event); + dock_notify(data, event); acpi_scan_lock_release(); - kfree(data); } static void dock_notify_handler(acpi_handle handle, u32 event, void *data) { - struct dock_data *dd; - if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK && event != ACPI_NOTIFY_EJECT_REQUEST) return; - dd = kmalloc(sizeof(*dd), GFP_KERNEL); - if (dd) { - acpi_status status; - - dd->ds = data; - dd->event = event; - status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); - if (ACPI_FAILURE(status)) - kfree(dd); - } + acpi_hotplug_execute(acpi_dock_deferred_cb, data, event); } /** diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 80cd1a1..c6db680 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -87,7 +87,7 @@ void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); int acpi_bind_one(struct device *dev, acpi_handle handle); int acpi_unbind_one(struct device *dev); -void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src); +void acpi_bus_device_eject(void *data, u32 ost_src); /* -------------------------------------------------------------------------- Power Resource diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e5f416c..cfc3e26 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -61,7 +61,6 @@ struct acpi_os_dpc { acpi_osd_exec_callback function; void *context; struct work_struct work; - int wait; }; #ifdef CONFIG_ACPI_CUSTOM_DSDT @@ -1067,9 +1066,6 @@ static void acpi_os_execute_deferred(struct work_struct *work) { struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); - if (dpc->wait) - acpi_os_wait_events_complete(); - dpc->function(dpc->context); kfree(dpc); } @@ -1089,8 +1085,8 @@ static void acpi_os_execute_deferred(struct work_struct *work) * ******************************************************************************/ -static acpi_status __acpi_os_execute(acpi_execute_type type, - acpi_osd_exec_callback function, void *context, int hp) +acpi_status acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context) { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; @@ -1117,20 +1113,11 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, dpc->context = context; /* - * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq - * because the hotplug code may call driver .remove() functions, - * which invoke flush_scheduled_work/acpi_os_wait_events_complete - * to flush these workqueues. - * * To prevent lockdep from complaining unnecessarily, make sure that * there is a different static lockdep key for each workqueue by using * INIT_WORK() for each of them separately. */ - if (hp) { - queue = kacpi_hotplug_wq; - dpc->wait = 1; - INIT_WORK(&dpc->work, acpi_os_execute_deferred); - } else if (type == OSL_NOTIFY_HANDLER) { + if (type == OSL_NOTIFY_HANDLER) { queue = kacpi_notify_wq; INIT_WORK(&dpc->work, acpi_os_execute_deferred); } else { @@ -1155,28 +1142,59 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, } return status; } +EXPORT_SYMBOL(acpi_os_execute); -acpi_status acpi_os_execute(acpi_execute_type type, - acpi_osd_exec_callback function, void *context) +void acpi_os_wait_events_complete(void) { - return __acpi_os_execute(type, function, context, 0); + flush_workqueue(kacpid_wq); + flush_workqueue(kacpi_notify_wq); } -EXPORT_SYMBOL(acpi_os_execute); -acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, - void *context) +struct acpi_hp_work { + struct work_struct work; + acpi_hp_callback func; + void *data; + u32 src; +}; + +static void acpi_hotplug_work_fn(struct work_struct *work) { - return __acpi_os_execute(0, function, context, 1); + struct acpi_hp_work *hpw = container_of(work, struct acpi_hp_work, work); + + acpi_os_wait_events_complete(); + hpw->func(hpw->data, hpw->src); + kfree(hpw); } -EXPORT_SYMBOL(acpi_os_hotplug_execute); -void acpi_os_wait_events_complete(void) +acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src) { - flush_workqueue(kacpid_wq); - flush_workqueue(kacpi_notify_wq); + struct acpi_hp_work *hpw; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Scheduling function [%p(%p, %u)] for deferred execution.\n", + func, data, src)); + + hpw = kmalloc(sizeof(*hpw), GFP_KERNEL); + if (!hpw) + return AE_NO_MEMORY; + + INIT_WORK(&hpw->work, acpi_hotplug_work_fn); + hpw->func = func; + hpw->data = data; + hpw->src = src; + /* + * We can't run hotplug code in kacpid_wq/kacpid_notify_wq etc., because + * the hotplug code may call driver .remove() functions, which may + * invoke flush_scheduled_work()/acpi_os_wait_events_complete() to flush + * these workqueues. + */ + if (!queue_work(kacpi_hotplug_wq, &hpw->work)) { + kfree(hpw); + return AE_ERROR; + } + return AE_OK; } -EXPORT_SYMBOL(acpi_os_wait_events_complete); acpi_status acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) @@ -1825,25 +1843,3 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, { __acpi_os_prepare_extended_sleep = func; } - - -void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context, - void (*func)(struct work_struct *work)) -{ - struct acpi_hp_work *hp_work; - int ret; - - hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL); - if (!hp_work) - return; - - hp_work->handle = handle; - hp_work->type = type; - hp_work->context = context; - - INIT_WORK(&hp_work->work, func); - ret = queue_work(kacpi_hotplug_wq, &hp_work->work); - if (!ret) - kfree(hp_work); -} -EXPORT_SYMBOL_GPL(alloc_acpi_hp_work); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d77f0bf..417876b 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -592,17 +592,10 @@ static void handle_root_bridge_insertion(acpi_handle handle) acpi_handle_err(handle, "cannot add bridge to acpi list\n"); } -static void _handle_hotplug_event_root(struct work_struct *work) +static void hotplug_event_root(void *data, u32 type) { + acpi_handle handle = data; struct acpi_pci_root *root; - struct acpi_hp_work *hp_work; - acpi_handle handle; - u32 type; - - hp_work = container_of(work, struct acpi_hp_work, work); - handle = hp_work->handle; - type = hp_work->type; - kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ acpi_scan_lock_acquire(); @@ -654,8 +647,7 @@ static void _handle_hotplug_event_root(struct work_struct *work) static void handle_hotplug_event_root(acpi_handle handle, u32 type, void *context) { - alloc_acpi_hp_work(handle, type, context, - _handle_hotplug_event_root); + acpi_hotplug_execute(hotplug_event_root, handle, type); } static acpi_status __init diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5cd7f8c..276cde7 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -285,8 +285,9 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return 0; } -void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src) +void acpi_bus_device_eject(void *data, u32 ost_src) { + struct acpi_device *device = data; acpi_handle handle = device->handle; struct acpi_scan_handler *handler; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; @@ -327,8 +328,9 @@ void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src) goto out; } -static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) +static void acpi_scan_bus_device_check(void *data, u32 ost_source) { + acpi_handle handle = data; struct acpi_device *device = NULL; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; int error; @@ -363,18 +365,6 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) unlock_device_hotplug(); } -static void acpi_scan_bus_check(void *context) -{ - acpi_scan_bus_device_check((acpi_handle)context, - ACPI_NOTIFY_BUS_CHECK); -} - -static void acpi_scan_device_check(void *context) -{ - acpi_scan_bus_device_check((acpi_handle)context, - ACPI_NOTIFY_DEVICE_CHECK); -} - static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) { u32 ost_status; @@ -403,18 +393,8 @@ static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL); } -/** - * acpi_bus_hot_remove_device: Hot-remove a device and its children. - * @context: Address of the ACPI device object to hot-remove. - */ -static void acpi_bus_hot_remove_device(void *context) -{ - acpi_bus_device_eject(context, ACPI_NOTIFY_EJECT_REQUEST); -} - static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) { - acpi_osd_exec_callback callback; struct acpi_scan_handler *handler = data; struct acpi_device *adev; acpi_status status; @@ -425,11 +405,9 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) switch (type) { case ACPI_NOTIFY_BUS_CHECK: acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); - callback = acpi_scan_bus_check; break; case ACPI_NOTIFY_DEVICE_CHECK: acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); - callback = acpi_scan_device_check; break; case ACPI_NOTIFY_EJECT_REQUEST: acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); @@ -438,8 +416,7 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) goto err_out; get_device(&adev->dev); - callback = acpi_bus_hot_remove_device; - status = acpi_os_hotplug_execute(callback, adev); + status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type); if (ACPI_SUCCESS(status)) return; @@ -449,7 +426,7 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) /* non-hotplug event; possibly handled by other handler */ return; } - status = acpi_os_hotplug_execute(callback, handle); + status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type); if (ACPI_SUCCESS(status)) return; @@ -484,11 +461,6 @@ static ssize_t power_state_show(struct device *dev, static DEVICE_ATTR(power_state, 0444, power_state_show, NULL); -static void acpi_eject_store_work(void *context) -{ - acpi_bus_device_eject(context, ACPI_OST_EC_OSPM_EJECT); -} - static ssize_t acpi_eject_store(struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -511,7 +483,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); get_device(&acpi_device->dev); - status = acpi_os_hotplug_execute(acpi_eject_store_work, acpi_device); + status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device, + ACPI_OST_EC_OSPM_EJECT); if (ACPI_SUCCESS(status)) return count; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 0b7d23b..5246ba2 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -875,21 +875,17 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) put_bridge(bridge); } -static void hotplug_event_work(struct work_struct *work) +static void hotplug_event_work(void *data, u32 type) { - struct acpiphp_context *context; - struct acpi_hp_work *hp_work; + struct acpiphp_context *context = data; + acpi_handle handle = context->handle; - hp_work = container_of(work, struct acpi_hp_work, work); - context = hp_work->context; acpi_scan_lock_acquire(); - hotplug_event(hp_work->handle, hp_work->type, context); + hotplug_event(handle, type, context); 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() */ + acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); put_bridge(context->func.parent); } @@ -940,10 +936,10 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) mutex_lock(&acpiphp_context_lock); context = acpiphp_get_context(handle); - if (context) { + if (context && !WARN_ON(context->handle != handle)) { get_bridge(context->func.parent); acpiphp_put_context(context); - alloc_acpi_hp_work(handle, type, context, hotplug_event_work); + acpi_hotplug_execute(hotplug_event_work, context, type); mutex_unlock(&acpiphp_context_lock); return; } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index eb37a6f..d64a301 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -339,15 +339,6 @@ struct acpi_bus_event { u32 data; }; -struct acpi_hp_work { - struct work_struct work; - acpi_handle handle; - u32 type; - void *context; -}; -void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context, - void (*func)(struct work_struct *work)); - extern struct kobject *acpi_kobj; extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); void acpi_bus_private_data_handler(acpi_handle, void *); @@ -393,6 +384,9 @@ int acpi_match_device_ids(struct acpi_device *device, int acpi_create_dir(struct acpi_device *); void acpi_remove_dir(struct acpi_device *); +typedef void (*acpi_hp_callback)(void *data, u32 src); + +acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src); /** * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 64b8c76..505cb4d 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -200,9 +200,6 @@ acpi_status acpi_os_execute(acpi_execute_type type, acpi_osd_exec_callback function, void *context); -acpi_status -acpi_os_hotplug_execute(acpi_osd_exec_callback function, void *context); - void acpi_os_wait_events_complete(void); void acpi_os_sleep(u64 milliseconds); -- cgit v0.10.2 From 3baa976ae644f76f5cdb5be0fb26754c3bfb32cb Mon Sep 17 00:00:00 2001 From: Xiaoguang Chen Date: Thu, 7 Nov 2013 10:28:50 +0800 Subject: cpufreq: conservative: fix requested_freq reduction issue When decreasing frequency, requested_freq may be less than freq_target, So requested_freq minus freq_target may be negative, But reqested_freq's unit is unsigned int, then the negative result will be one larger interger which may be even higher than requested_freq. This patch is to fix such issue. when result becomes negative, set requested_freq as the min value of policy. Signed-off-by: Xiaoguang Chen Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index f62d822..218460f 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -80,13 +80,18 @@ static void cs_check_cpu(int cpu, unsigned int load) /* Check for frequency decrease */ if (load < cs_tuners->down_threshold) { + unsigned int freq_target; /* * if we cannot reduce the frequency anymore, break out early */ if (policy->cur == policy->min) return; - dbs_info->requested_freq -= get_freq_target(cs_tuners, policy); + freq_target = get_freq_target(cs_tuners, policy); + if (dbs_info->requested_freq > freq_target) + dbs_info->requested_freq -= freq_target; + else + dbs_info->requested_freq = policy->min; __cpufreq_driver_target(policy, dbs_info->requested_freq, CPUFREQ_RELATION_L); -- cgit v0.10.2