perf_event: no PMU interrupt on OMAP4 with 3.2.0 (Pandaboard)
Subsystems (6)
Hi,
I am trying to get perf_event to work properly on my OMAP4 Pandabaord running the 3.2.0 kernel. I am the developer on libpfm4 and a regular contributor to the perf_event subsystem and perf tool. I want to use a Pandaboard to test libpfm4 ARM support.
I have been talking with Will Deacon and he suggested I post to this list.
I know that the off-the-shelf 3.2.0 does not have working PMU interrupts. I have integrated additional patches from both Ming Lei and Linaro. It seems some parts of those patches were integrated into 3.2.0.
I have attached my 3.2.0 changes to this message. With that, I get perf_event to register PMU interrupts 33 and 34. However, they don't fire when I count therefore the counts are bogus (counters wrap around).
I suspect I am missing something in the patch I put together. But I don't know what's missing. I am not an ARM platform expert. I am hoping someone on this list may shed some light on this problem.
It would be really nice to have perf_event running out of the box on Pandaboard for 3.3. It would go a long way into making performance monitoring usable on ARM.
Thanks.
---
arch/arm/include/asm/pmu.h +12 -3
@@ -27,13 +27,22 @@ enum arm_pmu_type {/* * struct arm_pmu_platdata - ARM PMU platform data * -* @handle_irq: an optional handler which will be called from the interrupt and -* passed the address of the low level handler, and can be used to implement -* any platform specific handling before or after calling it. +* @handle_irq: an optional handler which will be called from the +* interrupt and passed the address of the low level handler, +* and can be used to implement any platform specific handling +* before or after calling it. +* @enable_irq: an optional handler which will be called after +* request_irq and be used to handle some platform specific +* irq enablement +* @disable_irq: an optional handler which will be called before +* free_irq and be used to handle some platform specific +* irq disablement */ struct arm_pmu_platdata {irqreturn_t (*handle_irq)(int irq,void *dev,irq_handler_t pmu_handler); +void (*enable_irq)(int irq); +void (*disable_irq)(int irq); };#ifdef CONFIG_CPU_HAS_PMU
arch/arm/kernel/perf_event.c +8 -1
@@ -380,6 +380,8 @@ armpmu_release_hardware(struct arm_pmu *armpmu) {int i, irq, irqs;struct platform_device *pmu_device = armpmu->plat_device; +struct arm_pmu_platdata *plat = +dev_get_platdata (&pmu_device->dev); irqs =min (pmu_device->num_resources,num_possible_cpus ());
@@ -387,8 +389,11 @@ armpmu_release_hardware(struct arm_pmu *armpmu)if (!cpumask_test_and_clear_cpu (i, &armpmu->active_irqs))continue ; irq =platform_get_irq (pmu_device, i); -if (irq >=0 ) +if (irq >=0 ) { +if (plat->disable_irq) + plat->disable_irq (irq);free_irq (irq, armpmu); + } }release_pmu (armpmu->type);
@@ -449,6 +454,8 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)armpmu_release_hardware (armpmu);return err; } +if (plat->enable_irq) + plat->enable_irq (irq);cpumask_set_cpu (i, &armpmu->active_irqs); }
arch/arm/mach-omap2/devices.c +128 -4
154 lines not on this page · raw message
arch/arm/mach-omap2/omap_hwmod_44xx_data.c +27 -0
@@ -5276,6 +5276,30 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_wd_timer3_slaves), }; +static struct omap_hwmod_class omap44xx_emu_hwmod_class = { + .name ="emu" , +}; + +static struct omap_hwmod_irq_info omap44xx_emu_irqs[] = { + { .name ="cti0" , .irq =1 +OMAP44XX_IRQ_GIC_START }, + { .name ="cti1" , .irq =2 +OMAP44XX_IRQ_GIC_START }, + { .irq =-1 } +}; + +/*emu hwmod*/ +static struct omap_hwmod omap44xx_emu_hwmod = { + .name ="emu" , + .class = &omap44xx_emu_hwmod_class, + .clkdm_name ="emu_sys_clkdm" , + .prcm = { + .omap4 = { + .clkctrl_offs =OMAP4_CM_EMU_CLKSTCTRL_OFFSET , + .modulemode =MODULEMODE_HWCTRL , + }, + }, + .mpu_irqs = omap44xx_emu_irqs, +}; +static __initdata struct omap_hwmod *omap44xx_hwmods[] = {/* dmm class */
@@ -5422,6 +5446,9 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_wd_timer2_hwmod, &omap44xx_wd_timer3_hwmod, +/*emu class*/ + &omap44xx_emu_hwmod, + NULL, };
arch/arm/plat-omap/include/plat/omap44xx.h +2 -0
@@ -57,5 +57,7 @@#define OMAP44XX_HSUSB_OHCI_BASE (L4_44XX_BASE + 0x64800)#define OMAP44XX_HSUSB_EHCI_BASE (L4_44XX_BASE + 0x64C00) +#define OMAP44XX_CTI0_BASE 0x54148000 +#define OMAP44XX_CTI1_BASE 0x54149000#endif /* __ASM_ARCH_OMAP44XX_H */
Paul Walmsley
maintainerQuoted 3 lines · Stephane Eranian
I have attached my 3.2.0 changes to this message. With that, I get
perf_eventto register PMU interrupts 33 and 34. However, they don't fire when I count therefore the counts are bogus (counters wrap around).
Consider verifying first that register accesses to/from the PMU succeed. It sounds like this is the case from what you describe, but that would be a good first step in debugging this.
If that works, then I'd suggest reviewing the CTI integration code in the patch that you sent. There are lots of magic numbers in there that need to be verified.
Please keep in mind that the PMU/CTI support in the patches that you're using is quite hacky. There are several changes that are needed to that code for it to be supported cleanly.
Quoted 3 lines
It would be really nice to have
perf_eventrunning out of the box on Pandaboard for 3.3. It would go a long way into making performance monitoring usable on ARM.
Sorry to say that given the rework needed in the OMAP PMU/CTI support, it's unlikely that this is going into 3.3.
- Paul