/* * xen-acpi-pad.c - Xen pad interface * * Copyright (c) 2012, Intel Corporation. * Author: Liu, Jinsong * * 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. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include #include #include #include #include #define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad" #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator" #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80 static DEFINE_MUTEX(xen_cpu_lock); static int xen_acpi_pad_idle_cpus(unsigned int idle_nums) { struct xen_platform_op op; op.cmd = XENPF_core_parking; op.u.core_parking.type = XEN_CORE_PARKING_SET; op.u.core_parking.idle_nums = idle_nums; return HYPERVISOR_platform_op(&op); } static int xen_acpi_pad_idle_cpus_num(void) { struct xen_platform_op op; op.cmd = XENPF_core_parking; op.u.core_parking.type = XEN_CORE_PARKING_GET; return HYPERVISOR_platform_op(&op) ?: op.u.core_parking.idle_nums; } /* * Query firmware how many CPUs should be idle * return -1 on failure */ static int acpi_pad_pur(acpi_handle handle) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *package; int num = -1; if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer))) return num; if (!buffer.length || !buffer.pointer) return num; package = buffer.pointer; if (package->type == ACPI_TYPE_PACKAGE && package->package.count == 2 && package->package.elements[0].integer.value == 1) /* rev 1 */ num = package->package.elements[1].integer.value; kfree(buffer.pointer); return num; } static void acpi_pad_handle_notify(acpi_handle handle) { int idle_nums; struct acpi_buffer param = { .length = 4, .pointer = (void *)&idle_nums, }; mutex_lock(&xen_cpu_lock); idle_nums = acpi_pad_pur(handle); if (idle_nums < 0) { mutex_unlock(&xen_cpu_lock); return; } idle_nums = xen_acpi_pad_idle_cpus(idle_nums) ?: xen_acpi_pad_idle_cpus_num(); if (idle_nums >= 0) acpi_evaluate_ost(handle, ACPI_PROCESSOR_AGGREGATOR_NOTIFY, 0, ¶m); mutex_unlock(&xen_cpu_lock); } static void acpi_pad_notify(acpi_handle handle, u32 event, void *data) { switch (event) { case ACPI_PROCESSOR_AGGREGATOR_NOTIFY: acpi_pad_handle_notify(handle); break; default: pr_warn("Unsupported event [0x%x]\n", event); break; } } static int acpi_pad_add(struct acpi_device *device) { acpi_status status; strcpy(acpi_device_name(device), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PROCESSOR_AGGREGATOR_CLASS); status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_pad_notify, device); if (ACPI_FAILURE(status)) return -ENODEV; return 0; } static int acpi_pad_remove(struct acpi_device *device) { mutex_lock(&xen_cpu_lock); xen_acpi_pad_idle_cpus(0); mutex_unlock(&xen_cpu_lock); acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_pad_notify); return 0; } static const struct acpi_device_id pad_device_ids[] = { {"ACPI000C", 0}, {"", 0}, }; static struct acpi_driver acpi_pad_driver = { .name = "processor_aggregator", .class = ACPI_PROCESSOR_AGGREGATOR_CLASS, .ids = pad_device_ids, .ops = { .add = acpi_pad_add, .remove = acpi_pad_remove, }, }; static int __init xen_acpi_pad_init(void) { /* Only DOM0 is responsible for Xen acpi pad */ if (!xen_initial_domain()) return -ENODEV; /* Only Xen4.2 or later support Xen acpi pad */ if (!xen_running_on_version_or_later(4, 2)) return -ENODEV; return acpi_bus_register_driver(&acpi_pad_driver); } subsys_initcall(xen_acpi_pad_init); on>space:mode:
authorThomas Gleixner <tglx@linutronix.de>2017-01-31 19:03:21 +0100
committerThomas Gleixner <tglx@linutronix.de>2017-01-31 20:22:18 +0100
commitaaaec6fc755447a1d056765b11b24d8ff2b81366 (patch)
treea7f4167960ee1df86739905b6ccdeb95465bfe5f /tools/build/feature/test-gtk2.c
parent08d85f3ea99f1eeafc4e8507936190e86a16ee8c (diff)
x86/irq: Make irq activate operations symmetric
The recent commit which prevents double activation of interrupts unearthed interesting code in x86. The code (ab)uses irq_domain_activate_irq() to reconfigure an already activated interrupt. That trips over the prevention code now. Fix it by deactivating the interrupt before activating the new configuration. Fixes: 08d85f3ea99f1 "irqdomain: Avoid activating interrupts more than once" Reported-and-tested-by: Mike Galbraith <efault@gmx.de> Reported-and-tested-by: Borislav Petkov <bp@alien8.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1701311901580.3457@nanos
Diffstat (limited to 'tools/build/feature/test-gtk2.c')