diff options
Diffstat (limited to 'arch/arm/kernel/pmu.c')
-rw-r--r-- | arch/arm/kernel/pmu.c | 133 |
1 files changed, 10 insertions, 123 deletions
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index 2c79eec..2c3407e 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c @@ -10,139 +10,26 @@ * */ -#define pr_fmt(fmt) "PMU: " fmt - -#include <linux/cpumask.h> #include <linux/err.h> -#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/platform_device.h> #include <asm/pmu.h> -static volatile long pmu_lock; - -static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES]; - -static int __devinit pmu_device_probe(struct platform_device *pdev) -{ - - if (pdev->id < 0 || pdev->id >= ARM_NUM_PMU_DEVICES) { - pr_warning("received registration request for unknown " - "device %d\n", pdev->id); - return -EINVAL; - } - - if (pmu_devices[pdev->id]) - pr_warning("registering new PMU device type %d overwrites " - "previous registration!\n", pdev->id); - else - pr_info("registered new PMU device of type %d\n", - pdev->id); - - pmu_devices[pdev->id] = pdev; - return 0; -} - -static struct platform_driver pmu_driver = { - .driver = { - .name = "arm-pmu", - }, - .probe = pmu_device_probe, -}; - -static int __init register_pmu_driver(void) -{ - return platform_driver_register(&pmu_driver); -} -device_initcall(register_pmu_driver); - -struct platform_device * -reserve_pmu(enum arm_pmu_type device) -{ - struct platform_device *pdev; - - if (test_and_set_bit_lock(device, &pmu_lock)) { - pdev = ERR_PTR(-EBUSY); - } else if (pmu_devices[device] == NULL) { - clear_bit_unlock(device, &pmu_lock); - pdev = ERR_PTR(-ENODEV); - } else { - pdev = pmu_devices[device]; - } - - return pdev; -} -EXPORT_SYMBOL_GPL(reserve_pmu); +/* + * PMU locking to ensure mutual exclusion between different subsystems. + */ +static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)]; int -release_pmu(struct platform_device *pdev) -{ - if (WARN_ON(pdev != pmu_devices[pdev->id])) - return -EINVAL; - clear_bit_unlock(pdev->id, &pmu_lock); - return 0; -} -EXPORT_SYMBOL_GPL(release_pmu); - -static int -set_irq_affinity(int irq, - unsigned int cpu) +reserve_pmu(enum arm_pmu_type type) { -#ifdef CONFIG_SMP - int err = irq_set_affinity(irq, cpumask_of(cpu)); - if (err) - pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", - irq, cpu); - return err; -#else - return -EINVAL; -#endif -} - -static int -init_cpu_pmu(void) -{ - int i, irqs, err = 0; - struct platform_device *pdev = pmu_devices[ARM_PMU_DEVICE_CPU]; - - if (!pdev) - return -ENODEV; - - irqs = pdev->num_resources; - - /* - * If we have a single PMU interrupt that we can't shift, assume that - * we're running on a uniprocessor machine and continue. - */ - if (irqs == 1 && !irq_can_set_affinity(platform_get_irq(pdev, 0))) - return 0; - - for (i = 0; i < irqs; ++i) { - err = set_irq_affinity(platform_get_irq(pdev, i), i); - if (err) - break; - } - - return err; + return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0; } +EXPORT_SYMBOL_GPL(reserve_pmu); -int -init_pmu(enum arm_pmu_type device) +void +release_pmu(enum arm_pmu_type type) { - int err = 0; - - switch (device) { - case ARM_PMU_DEVICE_CPU: - err = init_cpu_pmu(); - break; - default: - pr_warning("attempt to initialise unknown device %d\n", - device); - err = -EINVAL; - } - - return err; + clear_bit_unlock(type, pmu_lock); } -EXPORT_SYMBOL_GPL(init_pmu); |