Skip to content

Commit

Permalink
ARC: SMP resurrect foss-for-synopsys-dwc-arc-processors#21: request_i…
Browse files Browse the repository at this point in the history
…rq() workaround for clockevent Timer

request_irq() for TIMER0 failing on CPU1

Ideally we want to use the request_percpu_irq( ) / enable_percpu_irq()
calls from GENERIC_IRQ framework, however that seems to be faltering
even on the boot cpu at the time of first interrupt.

Until that is resolved (with Thomas G), we need to pretend that
TIMER0 is IRQF_SHARED. This also requires yet another hack of explicitly
unmasking the IRQ on that CPU.

Query sent to Thomas Gleixner

======================>8====================================
In a SMP setup, each ARC700 CPU has a in-core TIMER, hooked up to
private IRQ 3 of respective CPU and would serve as the local
clock_event_device.

request_irq( ) for my first CPU which succeeds, looks roughly as
follows:

	void __cpuinit arc_clockevent_init(void)
	{
	    int rc;
	    unsigned int cpu = smp_processor_id();
	    struct clock_event_device *evt = &per_cpu(arc_clockevent_device,
							cpu);
	....
	    rc = request_irq(TIMER0_INT, timer_irq_handler,
        	    IRQF_TIMER | IRQF_DISABLED | IRQF_PERCPU,
	            "Timer0 (clock-evt-dev)", evt);
	....

The exact same call, when done from 2nd CPU fails, as it wants to see
IRQF_SHARED which is semantically not correct, since IRQ is not really
shared, it is a private instance (albeit same value), per cpu.

I figured that the right APIs for our case is the pair:
(request|enable)_percpu_irq to be called for both CPUs, with a prior one
time call to irq_set_percpu_devid().  Is that correct?

Assuming it is, the trouble now is that, even on the first CPU,
handle_level_irq( ) is bailing out w/o calling handle_irq_event()
because irqd_irq_disabled( ) is true. This in turn happens because,
irq_set_percpu_devid(), our much needed init routine, sets IRQ_NOAUTOEN
causing __setup_irq( ) to skip calling irq_startup() => irq_enable()
which would have cleared IRQD_IRQ_DISABLED.

While enable_percpu_irq( ), could have fixed this, it only seems to be
unmasking IRQ at device level, it is not clearing the above flag.

I tried calling enable_irq( ) right after, but that doesn't seem to help
either.
What API am I missing here, to enable the irqd machinery, or am I seeing
a bug where enable_percpu_irq( ) call-chain should somehow be doing it.

======================>8====================================

This needs to be reverted and replaced with right calls once ThomasG
responds to my query.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
  • Loading branch information
vineetgarc committed Jul 26, 2012
1 parent d754b06 commit 2985184
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 1 deletion.
3 changes: 3 additions & 0 deletions arch/arc/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ void __cpuinit start_kernel_secondary(void)

arc_clockevent_init();

/* Hack for request_irq() failing on non-boot CPU */
arch_unmask_irq(TIMER0_INT);

local_irq_enable();
preempt_disable();
cpu_idle();
Expand Down
2 changes: 1 addition & 1 deletion arch/arc/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ void __cpuinit arc_clockevent_init(void)
clockevents_register_device(evt);

rc = request_irq(TIMER0_INT, timer_irq_handler,
IRQF_TIMER | IRQF_DISABLED | IRQF_PERCPU,
IRQF_TIMER | IRQF_DISABLED | IRQF_PERCPU | IRQF_SHARED,
"Timer0 (clock-evt-dev)", evt);

if (rc)
Expand Down

0 comments on commit 2985184

Please sign in to comment.