On Mon, Oct 20, 2014 at 03:29:26PM +0800, GP Orcullo wrote:
> On Oct 9, 2014 11:14 PM, "Gilles Chanteperdrix" <
> [email protected]> wrote:
> >
> > On 10/09/2014 01:06 PM, GP Orcullo wrote:
> > > On Oct 9, 2014 6:16 PM, "Gilles Chanteperdrix" <
> > > [email protected]> wrote:
> > >>
> > >> On 10/09/2014 12:12 PM, GP Orcullo wrote:
> > >>> On Thu, Oct 9, 2014 at 6:06 PM, Gilles Chanteperdrix
> > >>> <[email protected]> wrote:
> > >>>> On 10/09/2014 12:02 PM, GP Orcullo wrote:
> > >>>>> On Mon, Oct 6, 2014 at 6:30 AM, Gilles Chanteperdrix
> > >>>>> <[email protected]> wrote:
> > >>>>>>
> > >>>>>> It means that Linux was interrupted by Xenomai during its timer
> > >>>>>> interrupt, and that Xenomai interrupted it for 280us. This may
> > >>>>>> happens with switchtest if it has a really long chain of context
> > >>>>>> switches. If you want to check what happened, enable the I-pipe
> > >>>>>> tracer, and trigger a trace freeze right before this message.
> > >>>>>>
> > >>>>>
> > >>>>> One more piece to the puzzle: disabling CONFIG_IPIPE_DEBUG_INTERNAL
> > >>>>> causes the system to lockup.
> > >>>>>
> > >>>> How do you know this is related?
> > >>>>
> > >>>>
> Gilles.
> > >>>
> > >>> Sorry, I quoted the wrong message.
> > >>>
> > >>> If CONFIG_PREEMPT is disabled and CONFIG_IPIPE_DEBUG_INTERNAL is not
> > >>> disabled, the system works fine.
> > >>>
> > >> So, there is a problem, likely in your port with CONFIG_PREEMPT, but
> > >> maybe in Xenomai (I need to check, because I am not so sure I tested
> > >> xeno-regression-test without CONFIG_PREEMPT).
> > >>
> > >> And there is a problem in your port without
> CONFIG_IPIPE_DEBUG_INTERNAL.
> > >> This I do not need to check, I have tested Xenomai wihout this option
> > >> enabled.
> > >>
> > >> So, my question is: how do you know the two issues are related?
> > >>
> > >
> > > I don't know the answer.
> > >
> > > I'm only looking at the effects and not the cause of the issue.
> > >
> > > So, where shall I start digging? What's in
> CONFIG_IPIPE_DEBUG_INTERNAL
> > > that would somehow suppress the problem?
> > >
> >
> > Quite frankly, I would go the other way: check that every piece of code
> > which may be executed over real-time context does not use any Linux
> > code. That does not include a lot of code, actually all that is covered
> > by the porting guide:
> > - the interrupt controller callbacks (note that the GIC handles some SOC
> > specific callabcks, so if you have some, you need to check them)
> > - the chained interrupt demux handlers
> > - the timer and tsc management functions.
> > - some workaround specific code that hooks in the iowrite/writel
> > functions, such as the L2 cache synchronization on omap4.
> >
> > And it seems that is all, so, there should not be a lot of code to check.
> >
> >
>
> Hello Gilles,
>
> Thanks for all the help.
>
> The problem was traced to the tsc emulation, the counter somehow gets
> messed up when the global timer is shared with Linux.
Hi,
could you try the following patch and tell me if it avoids the
issue?
Thanks.
Regards.
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index fb28b2e..150beb5 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -106,6 +106,12 @@
clocks = <&clks 15>;
};
+ timer@00a00200 {
+ compatible = "arm,cortex-a9-global-timer";
+ reg = <0x00a00200 0x20>;
+ clocks = <&clks 15>;
+ };
+
L2: l2-cache@00a02000 {
compatible = "arm,pl310-cache";
reg = <0x00a02000 0x1000>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index a914496..2cb8144 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -67,6 +67,12 @@
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) |
IRQ_TYPE_LEVEL_HIGH)>;
};
+ global_timer: timer@48240200 {
+ compatible = "arm,cortex-a9-global-timer";
+ reg = <0x48240200 0x20>;
+ clocks = <&mpu_periphclk>;
+ };
+
/*
* The soc node represents the soc top level view. It is uses for IPs
* that are not memory mapped in the MPU view or for the MPU itself.
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index f0b7c52..864651c 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -28,7 +28,6 @@
#include <asm/smp_plat.h>
#include <asm/smp_twd.h>
#include <asm/cputype.h>
-#include <asm/ipipe.h>
/* set up by the platform code */
static void __iomem *twd_base;
@@ -51,42 +50,9 @@ static void twd_ack(void)
writel_relaxed(1, twd_base + TWD_TIMER_INTSTAT);
}
-static struct __ipipe_tscinfo tsc_info;
-
static void twd_get_clock(struct device_node *np);
static void __cpuinit twd_calibrate_rate(void);
-static void __init gt_setup(unsigned long base_paddr, unsigned bits)
-{
- if ((read_cpuid_id() & 0xf00000) == 0)
- return;
-
- gt_base = ioremap(base_paddr, SZ_256);
- BUG_ON(!gt_base);
-
- /* Start global timer */
- __raw_writel(1, gt_base + 0x8);
-
- tsc_info.type = IPIPE_TSC_TYPE_FREERUNNING;
- tsc_info.freq = twd_timer_rate;
- tsc_info.counter_vaddr = (unsigned long)gt_base;
- tsc_info.u.counter_paddr = base_paddr;
-
- switch(bits) {
- case 64:
- tsc_info.u.mask = 0xffffffffffffffffULL;
- break;
- case 32:
- tsc_info.u.mask = 0xffffffff;
- break;
- default:
- /* Only supported as a 32 bits or 64 bits */
- BUG();
- }
-
- __ipipe_tsc_register(&tsc_info);
-}
-
#ifdef CONFIG_IPIPE_DEBUG_INTERNAL
static DEFINE_PER_CPU(int, irqs);
@@ -460,8 +426,6 @@ out_free:
int __init twd_local_timer_register(struct twd_local_timer *tlt)
{
- int rc;
-
if (twd_base || twd_evt)
return -EBUSY;
@@ -472,13 +436,7 @@ int __init twd_local_timer_register(struct twd_local_timer
*tlt)
return -ENOMEM;
- rc = twd_local_timer_common_register(NULL);
- if (rc == 0)
-#ifdef CONFIG_IPIPE
- gt_setup(tlt->res[0].start - 0x400, 32);
-#endif
-
- return rc;
+ return twd_local_timer_common_register(NULL);
}
#ifdef CONFIG_OF
@@ -503,16 +461,6 @@ static void __init twd_local_timer_of_register(struct
device_node *np)
err = twd_local_timer_common_register(np);
-#ifdef CONFIG_IPIPE
- if (err == 0) {
- struct resource res;
-
- if (of_address_to_resource(np, 0, &res))
- res.start = 0;
-
- gt_setup(res.start - 0x400, 32);
- }
-#endif /* CONFIG_IPIPE */
out:
WARN(err, "twd_local_timer_of_register failed (%d)\n", err);
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 33567aa..b825a09 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -808,6 +808,7 @@ config SOC_IMX6Q
select PL310_ERRATA_727915 if CACHE_PL310
select PL310_ERRATA_769419 if CACHE_PL310
select PM_OPP if PM
+ select ARM_GLOBAL_TIMER if SMP && IPIPE
help
This enables support for Freescale i.MX6 Quad processor.
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 0af7ca0..63a5b42 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -45,6 +45,7 @@ config ARCH_OMAP4
select USB_ARCH_HAS_EHCI if USB_SUPPORT
select ARM_ERRATA_754322
select ARM_ERRATA_775420
+ select ARM_GLOBAL_TIMER if IPIPE && SMP
config SOC_OMAP5
bool "TI OMAP5"
diff --git a/drivers/clocksource/arm_global_timer.c
b/drivers/clocksource/arm_global_timer.c
index 0fc31d0..62e208b 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -24,6 +24,7 @@
#include <linux/sched_clock.h>
#include <asm/cputype.h>
+#include <asm/ipipe.h>
#define GT_COUNTER0 0x00
#define GT_COUNTER1 0x04
@@ -48,6 +49,7 @@
* the units for all operations.
*/
static void __iomem *gt_base;
+static unsigned long gt_pbase;
static unsigned long gt_clk_rate;
static int gt_ppi;
static struct clock_event_device __percpu *gt_evt;
@@ -210,6 +212,16 @@ static u64 notrace gt_sched_clock_read(void)
static void __init gt_clocksource_init(void)
{
+#ifdef CONFIG_IPIPE
+ struct __ipipe_tscinfo tsc_info = {
+ .type = IPIPE_TSC_TYPE_FREERUNNING,
+ .freq = gt_clk_rate,
+ .counter_vaddr = (unsigned long)gt_base,
+ .u.counter_paddr = gt_pbase,
+ .u.mask = 0xffffffff,
+ };
+#endif
+
writel(0, gt_base + GT_CONTROL);
writel(0, gt_base + GT_COUNTER0);
writel(0, gt_base + GT_COUNTER1);
@@ -219,6 +231,9 @@ static void __init gt_clocksource_init(void)
#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
sched_clock_register(gt_sched_clock_read, 64, gt_clk_rate);
#endif
+#ifdef CONFIG_IPIPE
+ __ipipe_tsc_register(&tsc_info);
+#endif
clocksource_register_hz(>_clocksource, gt_clk_rate);
}
@@ -242,8 +257,9 @@ static struct notifier_block gt_cpu_nb = {
static void __init global_timer_of_register(struct device_node *np)
{
+ int err = 0, install_clockevent = 1;
+ struct resource res;
struct clk *gt_clk;
- int err = 0;
/*
* In r2p0 the comparators for each processor with the global timer
@@ -252,13 +268,15 @@ static void __init global_timer_of_register(struct
device_node *np)
*/
if ((read_cpuid_id() & 0xf0000f) < 0x200000) {
pr_warn("global-timer: non support for this cpu version.\n");
- return;
+ install_clockevent = 0;
}
- gt_ppi = irq_of_parse_and_map(np, 0);
- if (!gt_ppi) {
- pr_warn("global-timer: unable to parse irq\n");
- return;
+ if (install_clockevent) {
+ gt_ppi = irq_of_parse_and_map(np, 0);
+ if (!gt_ppi) {
+ pr_warn("global-timer: unable to parse irq\n");
+ install_clockevent = 0;
+ }
}
gt_base = of_iomap(np, 0);
@@ -267,6 +285,11 @@ static void __init global_timer_of_register(struct
device_node *np)
return;
}
+ if (of_address_to_resource(np, 0, &res))
+ res.start = 0;
+
+ gt_pbase = res.start;
+
gt_clk = of_clk_get(np, 0);
if (!IS_ERR(gt_clk)) {
err = clk_prepare_enable(gt_clk);
@@ -279,37 +302,39 @@ static void __init global_timer_of_register(struct
device_node *np)
}
gt_clk_rate = clk_get_rate(gt_clk);
- gt_evt = alloc_percpu(struct clock_event_device);
- if (!gt_evt) {
- pr_warn("global-timer: can't allocate memory\n");
- err = -ENOMEM;
- goto out_clk;
- }
-
- err = request_percpu_irq(gt_ppi, gt_clockevent_interrupt,
+ if (install_clockevent) {
+ gt_evt = alloc_percpu(struct clock_event_device);
+ if (!gt_evt) {
+ pr_warn("global-timer: can't allocate memory\n");
+ err = -ENOMEM;
+ goto out_clk;
+ }
+
+ err = request_percpu_irq(gt_ppi, gt_clockevent_interrupt,
"gt", gt_evt);
- if (err) {
- pr_warn("global-timer: can't register interrupt %d (%d)\n",
- gt_ppi, err);
- goto out_free;
- }
-
- err = register_cpu_notifier(>_cpu_nb);
- if (err) {
- pr_warn("global-timer: unable to register cpu notifier.\n");
- goto out_irq;
+ if (err) {
+ pr_warn("global-timer: can't register interrupt %d
(%d)\n",
+ gt_ppi, err);
+ goto out_free;
+ }
+
+ err = register_cpu_notifier(>_cpu_nb);
+ if (err) {
+ pr_warn("global-timer: unable to register cpu
notifier.\n");
+ free_percpu_irq(gt_ppi, gt_evt);
+ out_free:
+ free_percpu(gt_evt);
+ install_clockevent = 0;
+ }
}
/* Immediately configure the timer on the boot CPU */
gt_clocksource_init();
- gt_clockevents_init(this_cpu_ptr(gt_evt));
+ if (install_clockevent)
+ gt_clockevents_init(this_cpu_ptr(gt_evt));
return;
-out_irq:
- free_percpu_irq(gt_ppi, gt_evt);
-out_free:
- free_percpu(gt_evt);
out_clk:
clk_disable_unprepare(gt_clk);
out_unmap:
--
Gilles.
_______________________________________________
Xenomai mailing list
[email protected]
http://www.xenomai.org/mailman/listinfo/xenomai