Message ID | 1398371029-21176-1-git-send-email-l.stach@pengutronix.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Apr 24, 2014 at 5:23 PM, Lucas Stach <l.stach@pengutronix.de> wrote: > The i.MX6 PMU has a design errata where the interrupts of all cores are > wired together into a single irq line. To work around this we have to Is there an erratum reference number for this, please?
On 24.04.2014 22:32, Fabio Estevam wrote: > On Thu, Apr 24, 2014 at 5:23 PM, Lucas Stach <l.stach@pengutronix.de> wrote: >> The i.MX6 PMU has a design errata where the interrupts of all cores are >> wired together into a single irq line. To work around this we have to > > Is there an erratum reference number for this, please? First, many thanks to Lucas for working on this! Up to now, it was my impression that the PMU on i.MX6 is completely useless for !single core SoCs. So maybe there is some hope, now :) Regarding the erratum: To my knowledge there is no erratum. In 2013 I've had a discussion with the FSL support about this and got the answer: -- cut -- This is the IC design issue, we have OR'ed the interrupt pin of the four PMU and provide one interrupt to the CPU. currently, we don't have the SW workaround available for it. -- cut -- This is just what has been called as "braindead, broken system" in http://lists.infradead.org/pipermail/linux-arm-kernel/2012-August/113802.html Best regards Dirk
On 24.04.2014 22:23, Lucas Stach wrote: > The i.MX6 PMU has a design errata where the interrupts of all cores are > wired together into a single irq line. To work around this we have to > bounce the interrupt around all cores until we find the one where the PMU > counter overflow has happened. > > This causes the perf measurements to be less accurate and we can't really > handle the case where two cores fire a PMU irq at the same time. The > implemented woraround makes perf at least somewhat useable on imx6 SoCs > with more than one core. > > Signed-off-by: Lucas Stach <l.stach@pengutronix.de> > --- > arch/arm/mach-imx/mach-imx6q.c | 38 +++++++++++++++++++++++++++++++++++++- > 1 file changed, 37 insertions(+), 1 deletion(-) > > diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c > index e60456d85c9d..73976c484826 100644 > --- a/arch/arm/mach-imx/mach-imx6q.c > +++ b/arch/arm/mach-imx/mach-imx6q.c > @@ -16,6 +16,7 @@ > #include <linux/delay.h> > #include <linux/export.h> > #include <linux/init.h> > +#include "linux/interrupt.h" > #include <linux/io.h> > #include <linux/irq.h> > #include <linux/irqchip.h> > @@ -33,6 +34,7 @@ > #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> > #include <asm/mach/arch.h> > #include <asm/mach/map.h> > +#include "asm/pmu.h" > #include <asm/system_misc.h> > > #include "common.h" > @@ -261,6 +263,39 @@ static void __init imx6q_axi_init(void) > } > } > > +/* > + * The i.MX6 PMU has a design errata where the interrupts of all cores are > + * wired together into a single irq line. To work around this we have to > + * bounce the interrupt around all cores until we find the one where the PMU > + * counter overflow has happened. > + */ > +static irqreturn_t imx6q_pmu_handler(int irq, void *dev, irq_handler_t handler) > +{ > + irqreturn_t ret = handler(irq, dev); > + int next; > + > + if (ret == IRQ_NONE) { > + /* > + * Kick the irq over to the next cpu, regardless of it's > + * online status (it might have gone offline while we were busy > + * bouncing the irq). > + */ > + next = (smp_processor_id() + 1) % num_present_cpus(); > + irq_set_affinity(irq, cpumask_of(next)); > + } > + > + return ret; > +} > + > +struct arm_pmu_platdata imx6q_pmu_platdata = { > + .handle_irq = imx6q_pmu_handler, > +}; > + > +static struct of_dev_auxdata imx6q_auxdata_lookup[] __initdata = { > + OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &imx6q_pmu_platdata), > + {} > +}; > + > static void __init imx6q_init_machine(void) > { > struct device *parent; > @@ -276,7 +311,8 @@ static void __init imx6q_init_machine(void) > > imx6q_enet_phy_init(); > > - of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); > + of_platform_populate(NULL, of_default_bus_match_table, > + imx6q_auxdata_lookup, parent); > > imx_anatop_init(); > cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init(); Do you have anything like a test case which shows that it works (at least better) on a !single core with this patch? Compared to a non-patched system? Many thanks Dirk
Am Freitag, den 25.04.2014, 07:37 +0200 schrieb Dirk Behme: > On 24.04.2014 22:23, Lucas Stach wrote: > > The i.MX6 PMU has a design errata where the interrupts of all cores are > > wired together into a single irq line. To work around this we have to > > bounce the interrupt around all cores until we find the one where the PMU > > counter overflow has happened. > > > > This causes the perf measurements to be less accurate and we can't really > > handle the case where two cores fire a PMU irq at the same time. The > > implemented woraround makes perf at least somewhat useable on imx6 SoCs > > with more than one core. > > > > Signed-off-by: Lucas Stach <l.stach@pengutronix.de> > > --- > > arch/arm/mach-imx/mach-imx6q.c | 38 +++++++++++++++++++++++++++++++++++++- > > 1 file changed, 37 insertions(+), 1 deletion(-) > > > > diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c > > index e60456d85c9d..73976c484826 100644 > > --- a/arch/arm/mach-imx/mach-imx6q.c > > +++ b/arch/arm/mach-imx/mach-imx6q.c > > @@ -16,6 +16,7 @@ > > #include <linux/delay.h> > > #include <linux/export.h> > > #include <linux/init.h> > > +#include "linux/interrupt.h" > > #include <linux/io.h> > > #include <linux/irq.h> > > #include <linux/irqchip.h> > > @@ -33,6 +34,7 @@ > > #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> > > #include <asm/mach/arch.h> > > #include <asm/mach/map.h> > > +#include "asm/pmu.h" > > #include <asm/system_misc.h> > > > > #include "common.h" > > @@ -261,6 +263,39 @@ static void __init imx6q_axi_init(void) > > } > > } > > > > +/* > > + * The i.MX6 PMU has a design errata where the interrupts of all cores are > > + * wired together into a single irq line. To work around this we have to > > + * bounce the interrupt around all cores until we find the one where the PMU > > + * counter overflow has happened. > > + */ > > +static irqreturn_t imx6q_pmu_handler(int irq, void *dev, irq_handler_t handler) > > +{ > > + irqreturn_t ret = handler(irq, dev); > > + int next; > > + > > + if (ret == IRQ_NONE) { > > + /* > > + * Kick the irq over to the next cpu, regardless of it's > > + * online status (it might have gone offline while we were busy > > + * bouncing the irq). > > + */ > > + next = (smp_processor_id() + 1) % num_present_cpus(); > > + irq_set_affinity(irq, cpumask_of(next)); > > + } > > + > > + return ret; > > +} > > + > > +struct arm_pmu_platdata imx6q_pmu_platdata = { > > + .handle_irq = imx6q_pmu_handler, > > +}; > > + > > +static struct of_dev_auxdata imx6q_auxdata_lookup[] __initdata = { > > + OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &imx6q_pmu_platdata), > > + {} > > +}; > > + > > static void __init imx6q_init_machine(void) > > { > > struct device *parent; > > @@ -276,7 +311,8 @@ static void __init imx6q_init_machine(void) > > > > imx6q_enet_phy_init(); > > > > - of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); > > + of_platform_populate(NULL, of_default_bus_match_table, > > + imx6q_auxdata_lookup, parent); > > > > imx_anatop_init(); > > cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init(); > > Do you have anything like a test case which shows that it works (at > least better) on a !single core with this patch? Compared to a > non-patched system? > Without this patch, running perf top completely kills the system on i.MX6q, most likely because of the sheer number of spurious interrupts hitting the system from 4 cores. Even the spurious killer doesn't work sometimes, so perf is completely busted right now. With this patch perf has to reduce the sample frequency in order to compensate the added irq latency, but at least we get some plausible numbers out. Though I won't take any blame if the amount of salt you have to apply while looking at those numbers is already a deadly dose. ;) I don't yet have any numbers on how accurate the measurement is, but at least things didn't look completely off. Regards, Lucas
On Fri, Apr 25, 2014 at 11:13:25AM +0200, Lucas Stach wrote: > Am Freitag, den 25.04.2014, 07:37 +0200 schrieb Dirk Behme: > > On 24.04.2014 22:23, Lucas Stach wrote: > > > The i.MX6 PMU has a design errata where the interrupts of all cores are > > > wired together into a single irq line. To work around this we have to > > > bounce the interrupt around all cores until we find the one where the PMU > > > counter overflow has happened. > > > > > > This causes the perf measurements to be less accurate and we can't really > > > handle the case where two cores fire a PMU irq at the same time. The > > > implemented woraround makes perf at least somewhat useable on imx6 SoCs > > > with more than one core. > > > > > > Signed-off-by: Lucas Stach <l.stach@pengutronix.de> > > > --- > > > arch/arm/mach-imx/mach-imx6q.c | 38 +++++++++++++++++++++++++++++++++++++- > > > 1 file changed, 37 insertions(+), 1 deletion(-) > > > > > > diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c > > > index e60456d85c9d..73976c484826 100644 > > > --- a/arch/arm/mach-imx/mach-imx6q.c > > > +++ b/arch/arm/mach-imx/mach-imx6q.c > > > @@ -16,6 +16,7 @@ > > > #include <linux/delay.h> > > > #include <linux/export.h> > > > #include <linux/init.h> > > > +#include "linux/interrupt.h" > > > #include <linux/io.h> > > > #include <linux/irq.h> > > > #include <linux/irqchip.h> > > > @@ -33,6 +34,7 @@ > > > #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> > > > #include <asm/mach/arch.h> > > > #include <asm/mach/map.h> > > > +#include "asm/pmu.h" > > > #include <asm/system_misc.h> > > > > > > #include "common.h" > > > @@ -261,6 +263,39 @@ static void __init imx6q_axi_init(void) > > > } > > > } > > > > > > +/* > > > + * The i.MX6 PMU has a design errata where the interrupts of all cores are > > > + * wired together into a single irq line. To work around this we have to > > > + * bounce the interrupt around all cores until we find the one where the PMU > > > + * counter overflow has happened. > > > + */ > > > +static irqreturn_t imx6q_pmu_handler(int irq, void *dev, irq_handler_t handler) > > > +{ > > > + irqreturn_t ret = handler(irq, dev); > > > + int next; > > > + > > > + if (ret == IRQ_NONE) { > > > + /* > > > + * Kick the irq over to the next cpu, regardless of it's > > > + * online status (it might have gone offline while we were busy > > > + * bouncing the irq). > > > + */ > > > + next = (smp_processor_id() + 1) % num_present_cpus(); > > > + irq_set_affinity(irq, cpumask_of(next)); > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +struct arm_pmu_platdata imx6q_pmu_platdata = { > > > + .handle_irq = imx6q_pmu_handler, > > > +}; > > > + > > > +static struct of_dev_auxdata imx6q_auxdata_lookup[] __initdata = { > > > + OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &imx6q_pmu_platdata), > > > + {} > > > +}; > > > + > > > static void __init imx6q_init_machine(void) > > > { > > > struct device *parent; > > > @@ -276,7 +311,8 @@ static void __init imx6q_init_machine(void) > > > > > > imx6q_enet_phy_init(); > > > > > > - of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); > > > + of_platform_populate(NULL, of_default_bus_match_table, > > > + imx6q_auxdata_lookup, parent); > > > > > > imx_anatop_init(); > > > cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init(); > > > > Do you have anything like a test case which shows that it works (at > > least better) on a !single core with this patch? Compared to a > > non-patched system? > > > Without this patch, running perf top completely kills the system on > i.MX6q, most likely because of the sheer number of spurious interrupts > hitting the system from 4 cores. Even the spurious killer doesn't work > sometimes, so perf is completely busted right now. > > With this patch perf has to reduce the sample frequency in order to > compensate the added irq latency, but at least we get some plausible > numbers out. Though I won't take any blame if the amount of salt you > have to apply while looking at those numbers is already a deadly > dose. ;) > > I don't yet have any numbers on how accurate the measurement is, but at > least things didn't look completely off. If it cannot provide correct/accurate data, I'd say let's not fake it to, and just let it be completely broken there, so that people can be aware of the brokenness, and not take inaccurate data as accurate one. Shawn
Am Dienstag, den 29.04.2014, 13:28 +0800 schrieb Shawn Guo: > On Fri, Apr 25, 2014 at 11:13:25AM +0200, Lucas Stach wrote: > > Am Freitag, den 25.04.2014, 07:37 +0200 schrieb Dirk Behme: > > > On 24.04.2014 22:23, Lucas Stach wrote: > > > > The i.MX6 PMU has a design errata where the interrupts of all cores are > > > > wired together into a single irq line. To work around this we have to > > > > bounce the interrupt around all cores until we find the one where the PMU > > > > counter overflow has happened. > > > > > > > > This causes the perf measurements to be less accurate and we can't really > > > > handle the case where two cores fire a PMU irq at the same time. The > > > > implemented woraround makes perf at least somewhat useable on imx6 SoCs > > > > with more than one core. > > > > [...] > > > Do you have anything like a test case which shows that it works (at > > > least better) on a !single core with this patch? Compared to a > > > non-patched system? > > > > > Without this patch, running perf top completely kills the system on > > i.MX6q, most likely because of the sheer number of spurious interrupts > > hitting the system from 4 cores. Even the spurious killer doesn't work > > sometimes, so perf is completely busted right now. > > > > With this patch perf has to reduce the sample frequency in order to > > compensate the added irq latency, but at least we get some plausible > > numbers out. Though I won't take any blame if the amount of salt you > > have to apply while looking at those numbers is already a deadly > > dose. ;) > > > > I don't yet have any numbers on how accurate the measurement is, but at > > least things didn't look completely off. > > If it cannot provide correct/accurate data, I'd say let's not fake it > to, and just let it be completely broken there, so that people can be > aware of the brokenness, and not take inaccurate data as accurate one. > The data isn't bogus, it just isn't as accurate as it could be with a properly working PMU. I'll run some tests with a defined load on Solo/Quad to see how far the measurements are off. I'm fine with holding this patch until then. But the thing is this patch also fixes a serious userspace triggerable DoS on i.MX6q. Just running perf top completely locks up the system because of the sheer number of stray irqs. This isn't the case anymore with this patch applied. Maybe we can just print a warning into dmesg to make the users aware of the imprecise measurement. Regards, Lucas
On 29.04.2014 11:55, Lucas Stach wrote: > Am Dienstag, den 29.04.2014, 13:28 +0800 schrieb Shawn Guo: >> On Fri, Apr 25, 2014 at 11:13:25AM +0200, Lucas Stach wrote: >>> Am Freitag, den 25.04.2014, 07:37 +0200 schrieb Dirk Behme: >>>> On 24.04.2014 22:23, Lucas Stach wrote: >>>>> The i.MX6 PMU has a design errata where the interrupts of all cores are >>>>> wired together into a single irq line. To work around this we have to >>>>> bounce the interrupt around all cores until we find the one where the PMU >>>>> counter overflow has happened. >>>>> >>>>> This causes the perf measurements to be less accurate and we can't really >>>>> handle the case where two cores fire a PMU irq at the same time. The >>>>> implemented woraround makes perf at least somewhat useable on imx6 SoCs >>>>> with more than one core. >>>>> > [...] >>>> Do you have anything like a test case which shows that it works (at >>>> least better) on a !single core with this patch? Compared to a >>>> non-patched system? >>>> >>> Without this patch, running perf top completely kills the system on >>> i.MX6q, most likely because of the sheer number of spurious interrupts >>> hitting the system from 4 cores. Even the spurious killer doesn't work >>> sometimes, so perf is completely busted right now. >>> >>> With this patch perf has to reduce the sample frequency in order to >>> compensate the added irq latency, but at least we get some plausible >>> numbers out. Though I won't take any blame if the amount of salt you >>> have to apply while looking at those numbers is already a deadly >>> dose. ;) >>> >>> I don't yet have any numbers on how accurate the measurement is, but at >>> least things didn't look completely off. >> >> If it cannot provide correct/accurate data, I'd say let's not fake it >> to, and just let it be completely broken there, so that people can be >> aware of the brokenness, and not take inaccurate data as accurate one. >> > The data isn't bogus, it just isn't as accurate as it could be with a > properly working PMU. I'll run some tests with a defined load on > Solo/Quad to see how far the measurements are off. I'm fine with holding > this patch until then. > > But the thing is this patch also fixes a serious userspace triggerable > DoS on i.MX6q. Just running perf top completely locks up the system > because of the sheer number of stray irqs. This isn't the case anymore > with this patch applied. > > Maybe we can just print a warning into dmesg to make the users aware of > the imprecise measurement. Yes, I think this sounds like a good compromise :) Best regards Dirk
On Tue, Apr 29, 2014 at 6:17 AM, Dirk Behme <dirk.behme@de.bosch.com> wrote: > On 29.04.2014 11:55, Lucas Stach wrote: >> >> Am Dienstag, den 29.04.2014, 13:28 +0800 schrieb Shawn Guo: >>> >>> On Fri, Apr 25, 2014 at 11:13:25AM +0200, Lucas Stach wrote: >>>> >>>> Am Freitag, den 25.04.2014, 07:37 +0200 schrieb Dirk Behme: >>>>> >>>>> On 24.04.2014 22:23, Lucas Stach wrote: >>>>>> >>>>>> The i.MX6 PMU has a design errata where the interrupts of all cores >>>>>> are >>>>>> wired together into a single irq line. To work around this we have to >>>>>> bounce the interrupt around all cores until we find the one where the >>>>>> PMU >>>>>> counter overflow has happened. >>>>>> >>>>>> This causes the perf measurements to be less accurate and we can't >>>>>> really >>>>>> handle the case where two cores fire a PMU irq at the same time. The >>>>>> implemented woraround makes perf at least somewhat useable on imx6 >>>>>> SoCs >>>>>> with more than one core. >>>>>> >> [...] >>>>> >>>>> Do you have anything like a test case which shows that it works (at >>>>> least better) on a !single core with this patch? Compared to a >>>>> non-patched system? >>>>> >>>> Without this patch, running perf top completely kills the system on >>>> i.MX6q, most likely because of the sheer number of spurious interrupts >>>> hitting the system from 4 cores. Even the spurious killer doesn't work >>>> sometimes, so perf is completely busted right now. >>>> >>>> With this patch perf has to reduce the sample frequency in order to >>>> compensate the added irq latency, but at least we get some plausible >>>> numbers out. Though I won't take any blame if the amount of salt you >>>> have to apply while looking at those numbers is already a deadly >>>> dose. ;) >>>> >>>> I don't yet have any numbers on how accurate the measurement is, but at >>>> least things didn't look completely off. >>> >>> >>> If it cannot provide correct/accurate data, I'd say let's not fake it >>> to, and just let it be completely broken there, so that people can be >>> aware of the brokenness, and not take inaccurate data as accurate one. >>> >> The data isn't bogus, it just isn't as accurate as it could be with a >> properly working PMU. I'll run some tests with a defined load on >> Solo/Quad to see how far the measurements are off. I'm fine with holding >> this patch until then. >> >> But the thing is this patch also fixes a serious userspace triggerable >> DoS on i.MX6q. Just running perf top completely locks up the system >> because of the sheer number of stray irqs. This isn't the case anymore >> with this patch applied. I am very strange. Why PMU can work because below errata? ERR006259 ARM: Debug/trace functions (PMU, PTM and ETB) are disabled with absence of JTAG_TCK clock after POR Default it should no any PMU irqs happen. best regards Frank Li >> >> Maybe we can just print a warning into dmesg to make the users aware of >> the imprecise measurement. > > > Yes, I think this sounds like a good compromise :) > > Best regards > > Dirk > > > > > > > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Am Dienstag, den 29.04.2014, 13:33 -0500 schrieb Frank Li: > On Tue, Apr 29, 2014 at 6:17 AM, Dirk Behme <dirk.behme@de.bosch.com> wrote: > > On 29.04.2014 11:55, Lucas Stach wrote: > >> > >> Am Dienstag, den 29.04.2014, 13:28 +0800 schrieb Shawn Guo: > >>> > >>> On Fri, Apr 25, 2014 at 11:13:25AM +0200, Lucas Stach wrote: > >>>> > >>>> Am Freitag, den 25.04.2014, 07:37 +0200 schrieb Dirk Behme: > >>>>> > >>>>> On 24.04.2014 22:23, Lucas Stach wrote: > >>>>>> > >>>>>> The i.MX6 PMU has a design errata where the interrupts of all cores > >>>>>> are > >>>>>> wired together into a single irq line. To work around this we have to > >>>>>> bounce the interrupt around all cores until we find the one where the > >>>>>> PMU > >>>>>> counter overflow has happened. > >>>>>> > >>>>>> This causes the perf measurements to be less accurate and we can't > >>>>>> really > >>>>>> handle the case where two cores fire a PMU irq at the same time. The > >>>>>> implemented woraround makes perf at least somewhat useable on imx6 > >>>>>> SoCs > >>>>>> with more than one core. > >>>>>> > >> [...] > >>>>> > >>>>> Do you have anything like a test case which shows that it works (at > >>>>> least better) on a !single core with this patch? Compared to a > >>>>> non-patched system? > >>>>> > >>>> Without this patch, running perf top completely kills the system on > >>>> i.MX6q, most likely because of the sheer number of spurious interrupts > >>>> hitting the system from 4 cores. Even the spurious killer doesn't work > >>>> sometimes, so perf is completely busted right now. > >>>> > >>>> With this patch perf has to reduce the sample frequency in order to > >>>> compensate the added irq latency, but at least we get some plausible > >>>> numbers out. Though I won't take any blame if the amount of salt you > >>>> have to apply while looking at those numbers is already a deadly > >>>> dose. ;) > >>>> > >>>> I don't yet have any numbers on how accurate the measurement is, but at > >>>> least things didn't look completely off. > >>> > >>> > >>> If it cannot provide correct/accurate data, I'd say let's not fake it > >>> to, and just let it be completely broken there, so that people can be > >>> aware of the brokenness, and not take inaccurate data as accurate one. > >>> > >> The data isn't bogus, it just isn't as accurate as it could be with a > >> properly working PMU. I'll run some tests with a defined load on > >> Solo/Quad to see how far the measurements are off. I'm fine with holding > >> this patch until then. > >> > >> But the thing is this patch also fixes a serious userspace triggerable > >> DoS on i.MX6q. Just running perf top completely locks up the system > >> because of the sheer number of stray irqs. This isn't the case anymore > >> with this patch applied. > > I am very strange. Why PMU can work because below errata? > > ERR006259 ARM: Debug/trace functions (PMU, PTM and ETB) are disabled > with absence of JTAG_TCK clock after POR > > Default it should no any PMU irqs happen. Hm, I wasn't aware of this errata and I have to say it confuses me a bit, as contrary to what the errata claims the PMU is working just fine on imx6 without a JTAG_TCK connected. I've just tested this on 3 different boards (2 of them imx6q, 1 imx6dl) and you can clearly see the interrupt hitting. Regards, Lucas
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index e60456d85c9d..73976c484826 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -16,6 +16,7 @@ #include <linux/delay.h> #include <linux/export.h> #include <linux/init.h> +#include "linux/interrupt.h" #include <linux/io.h> #include <linux/irq.h> #include <linux/irqchip.h> @@ -33,6 +34,7 @@ #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> +#include "asm/pmu.h" #include <asm/system_misc.h> #include "common.h" @@ -261,6 +263,39 @@ static void __init imx6q_axi_init(void) } } +/* + * The i.MX6 PMU has a design errata where the interrupts of all cores are + * wired together into a single irq line. To work around this we have to + * bounce the interrupt around all cores until we find the one where the PMU + * counter overflow has happened. + */ +static irqreturn_t imx6q_pmu_handler(int irq, void *dev, irq_handler_t handler) +{ + irqreturn_t ret = handler(irq, dev); + int next; + + if (ret == IRQ_NONE) { + /* + * Kick the irq over to the next cpu, regardless of it's + * online status (it might have gone offline while we were busy + * bouncing the irq). + */ + next = (smp_processor_id() + 1) % num_present_cpus(); + irq_set_affinity(irq, cpumask_of(next)); + } + + return ret; +} + +struct arm_pmu_platdata imx6q_pmu_platdata = { + .handle_irq = imx6q_pmu_handler, +}; + +static struct of_dev_auxdata imx6q_auxdata_lookup[] __initdata = { + OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &imx6q_pmu_platdata), + {} +}; + static void __init imx6q_init_machine(void) { struct device *parent; @@ -276,7 +311,8 @@ static void __init imx6q_init_machine(void) imx6q_enet_phy_init(); - of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); + of_platform_populate(NULL, of_default_bus_match_table, + imx6q_auxdata_lookup, parent); imx_anatop_init(); cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();
The i.MX6 PMU has a design errata where the interrupts of all cores are wired together into a single irq line. To work around this we have to bounce the interrupt around all cores until we find the one where the PMU counter overflow has happened. This causes the perf measurements to be less accurate and we can't really handle the case where two cores fire a PMU irq at the same time. The implemented woraround makes perf at least somewhat useable on imx6 SoCs with more than one core. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> --- arch/arm/mach-imx/mach-imx6q.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)