Loading arch/arm/kernel/perf_event_cpu.c +43 −2 Original line number Original line Diff line number Diff line Loading @@ -211,6 +211,46 @@ static void armpmu_update_counters(void) } } } } static void armpmu_hotplug_enable(void *parm_pmu) { struct arm_pmu *armpmu = parm_pmu; struct pmu *pmu = &(armpmu->pmu); struct pmu_hw_events *hw_events = armpmu->get_hw_events(); int idx; for (idx = 0; idx <= armpmu->num_events; ++idx) { struct perf_event *event = hw_events->events[idx]; if (!event) continue; event->state = event->hotplug_save_state; pmu->start(event, 0); } } static void armpmu_hotplug_disable(void *parm_pmu) { struct arm_pmu *armpmu = parm_pmu; struct pmu *pmu = &(armpmu->pmu); struct pmu_hw_events *hw_events = armpmu->get_hw_events(); int idx; for (idx = 0; idx <= armpmu->num_events; ++idx) { struct perf_event *event = hw_events->events[idx]; if (!event) continue; event->hotplug_save_state = event->state; /* * Prevent timer tick handler perf callback from enabling * this event and potentially generating an interrupt * before the CPU goes down. */ event->state = PERF_EVENT_STATE_OFF; pmu->stop(event, 0); } } /* /* * PMU hardware loses all context when a CPU goes offline. * PMU hardware loses all context when a CPU goes offline. * When a CPU is hotplugged back in, since some hardware registers are * When a CPU is hotplugged back in, since some hardware registers are Loading Loading @@ -243,7 +283,8 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b, cpu_pmu->save_pm_registers, hcpu, 1); cpu_pmu->save_pm_registers, hcpu, 1); if (cpu_pmu->pmu_state != ARM_PMU_STATE_OFF) { if (cpu_pmu->pmu_state != ARM_PMU_STATE_OFF) { if (cpu_has_active_perf(cpu)) if (cpu_has_active_perf(cpu)) armpmu_update_counters(); smp_call_function_single(cpu, armpmu_hotplug_disable, cpu_pmu, 1); /* Disarm the PMU IRQ before disappearing. */ /* Disarm the PMU IRQ before disappearing. */ if (cpu_pmu->plat_device) { if (cpu_pmu->plat_device) { irq = platform_get_irq(cpu_pmu->plat_device, 0); irq = platform_get_irq(cpu_pmu->plat_device, 0); Loading @@ -266,7 +307,7 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b, enable_irq_callback(&irq); enable_irq_callback(&irq); } } if (cpu_has_active_perf(cpu)) { if (cpu_has_active_perf(cpu)) { __get_cpu_var(from_idle) = 1; armpmu_hotplug_enable(cpu_pmu); pmu = &cpu_pmu->pmu; pmu = &cpu_pmu->pmu; pmu->pmu_enable(pmu); pmu->pmu_enable(pmu); } } Loading arch/arm/mach-msm/perf_debug.c +1 −0 Original line number Original line Diff line number Diff line Loading @@ -49,6 +49,7 @@ static char *descriptions = "24 Perf: Add debugfs node to clear PMU\n" "24 Perf: Add debugfs node to clear PMU\n" "25 msm: perf: reset perf cycle counter on krait\n" "25 msm: perf: reset perf cycle counter on krait\n" "26 Perf: interrupt disable without bringing cpus up\n" "26 Perf: interrupt disable without bringing cpus up\n" "27 Perf: stop counters when going into hotplug\n" ; ; static ssize_t desc_read(struct file *fp, char __user *buf, static ssize_t desc_read(struct file *fp, char __user *buf, Loading include/linux/perf_event.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -319,6 +319,7 @@ struct perf_event { struct pmu *pmu; struct pmu *pmu; enum perf_event_active_state state; enum perf_event_active_state state; enum perf_event_active_state hotplug_save_state; unsigned int attach_state; unsigned int attach_state; local64_t count; local64_t count; atomic64_t child_count; atomic64_t child_count; Loading Loading
arch/arm/kernel/perf_event_cpu.c +43 −2 Original line number Original line Diff line number Diff line Loading @@ -211,6 +211,46 @@ static void armpmu_update_counters(void) } } } } static void armpmu_hotplug_enable(void *parm_pmu) { struct arm_pmu *armpmu = parm_pmu; struct pmu *pmu = &(armpmu->pmu); struct pmu_hw_events *hw_events = armpmu->get_hw_events(); int idx; for (idx = 0; idx <= armpmu->num_events; ++idx) { struct perf_event *event = hw_events->events[idx]; if (!event) continue; event->state = event->hotplug_save_state; pmu->start(event, 0); } } static void armpmu_hotplug_disable(void *parm_pmu) { struct arm_pmu *armpmu = parm_pmu; struct pmu *pmu = &(armpmu->pmu); struct pmu_hw_events *hw_events = armpmu->get_hw_events(); int idx; for (idx = 0; idx <= armpmu->num_events; ++idx) { struct perf_event *event = hw_events->events[idx]; if (!event) continue; event->hotplug_save_state = event->state; /* * Prevent timer tick handler perf callback from enabling * this event and potentially generating an interrupt * before the CPU goes down. */ event->state = PERF_EVENT_STATE_OFF; pmu->stop(event, 0); } } /* /* * PMU hardware loses all context when a CPU goes offline. * PMU hardware loses all context when a CPU goes offline. * When a CPU is hotplugged back in, since some hardware registers are * When a CPU is hotplugged back in, since some hardware registers are Loading Loading @@ -243,7 +283,8 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b, cpu_pmu->save_pm_registers, hcpu, 1); cpu_pmu->save_pm_registers, hcpu, 1); if (cpu_pmu->pmu_state != ARM_PMU_STATE_OFF) { if (cpu_pmu->pmu_state != ARM_PMU_STATE_OFF) { if (cpu_has_active_perf(cpu)) if (cpu_has_active_perf(cpu)) armpmu_update_counters(); smp_call_function_single(cpu, armpmu_hotplug_disable, cpu_pmu, 1); /* Disarm the PMU IRQ before disappearing. */ /* Disarm the PMU IRQ before disappearing. */ if (cpu_pmu->plat_device) { if (cpu_pmu->plat_device) { irq = platform_get_irq(cpu_pmu->plat_device, 0); irq = platform_get_irq(cpu_pmu->plat_device, 0); Loading @@ -266,7 +307,7 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b, enable_irq_callback(&irq); enable_irq_callback(&irq); } } if (cpu_has_active_perf(cpu)) { if (cpu_has_active_perf(cpu)) { __get_cpu_var(from_idle) = 1; armpmu_hotplug_enable(cpu_pmu); pmu = &cpu_pmu->pmu; pmu = &cpu_pmu->pmu; pmu->pmu_enable(pmu); pmu->pmu_enable(pmu); } } Loading
arch/arm/mach-msm/perf_debug.c +1 −0 Original line number Original line Diff line number Diff line Loading @@ -49,6 +49,7 @@ static char *descriptions = "24 Perf: Add debugfs node to clear PMU\n" "24 Perf: Add debugfs node to clear PMU\n" "25 msm: perf: reset perf cycle counter on krait\n" "25 msm: perf: reset perf cycle counter on krait\n" "26 Perf: interrupt disable without bringing cpus up\n" "26 Perf: interrupt disable without bringing cpus up\n" "27 Perf: stop counters when going into hotplug\n" ; ; static ssize_t desc_read(struct file *fp, char __user *buf, static ssize_t desc_read(struct file *fp, char __user *buf, Loading
include/linux/perf_event.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -319,6 +319,7 @@ struct perf_event { struct pmu *pmu; struct pmu *pmu; enum perf_event_active_state state; enum perf_event_active_state state; enum perf_event_active_state hotplug_save_state; unsigned int attach_state; unsigned int attach_state; local64_t count; local64_t count; atomic64_t child_count; atomic64_t child_count; Loading