All of lore.kernel.org
 help / color / mirror / Atom feed
From: Robert Reif <reif@earthlink.net>
To: sparclinux@vger.kernel.org
Subject: Re: [PATCH]: Updated PROM sun4m IRQ register patch.
Date: Sat, 20 Sep 2008 02:27:13 +0000	[thread overview]
Message-ID: <48D45F81.8020103@earthlink.net> (raw)
In-Reply-To: <20080913.214526.47086017.davem@davemloft.net>

David Miller wrote:
> From: Robert Reif <reif@earthlink.net>
> Date: Tue, 16 Sep 2008 22:52:02 -0400
>
>   
>> David Miller wrote:
>>     
>>> Please try this new version of the patch:
>>>   
>>>       
>> Same results: UP boots and SMP produces Watchdog Reset
>>     
>
> Ok, let's try this one more time :-)
>
> diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
> index 68689fa..def41ba 100644
> --- a/arch/sparc/kernel/entry.S
> +++ b/arch/sparc/kernel/entry.S
> @@ -272,17 +272,18 @@ smp4m_ticker:
>  	 */
>  maybe_smp4m_msg:
>  	GET_PROCESSOR4M_ID(o3)
> -	set	sun4m_interrupts, %l5
> -	ld	[%l5], %o5
> +	sethi	%hi(sun4m_irq_percpu), %l5
> +	sll	%o3, 2, %o3
> +	or	%l5, %lo(sun4m_irq_percpu), %l5
>   
This patch works SMP when this line is changed to:
       or      %l5, %lo(sun4m_irq_percpu), %o5
>  	sethi	%hi(0x40000000), %o2
> -	sll	%o3, 12, %o3
>  	ld	[%o5 + %o3], %o1
> -	andcc	%o1, %o2, %g0
> +	ld	[%o1 + 0x00], %o3	! sun4m_irq_percpu[cpu]->pending
> +	andcc	%o3, %o2, %g0
>  	be,a	smp4m_ticker
>  	 cmp	%l7, 14
> -	st	%o2, [%o5 + 0x4]
> +	st	%o2, [%o1 + 0x04]	! sun4m_irq_percpu[cpu]->clear=0x40000000
>  	WRITE_PAUSE
> -	ld	[%o5], %g0
> +	ld	[%o1 + 0x00], %g0	! sun4m_irq_percpu[cpu]->pending
>  	WRITE_PAUSE
>  	or	%l0, PSR_PIL, %l4
>  	wr	%l4, 0x0, %psr
> @@ -300,16 +301,16 @@ linux_trap_ipi15_sun4m:
>  	SAVE_ALL
>  	sethi	%hi(0x80000000), %o2
>  	GET_PROCESSOR4M_ID(o0)
> -	set	sun4m_interrupts, %l5
> -	ld	[%l5], %o5
> -	sll	%o0, 12, %o0
> -	add	%o5, %o0, %o5
> -	ld	[%o5], %o3
> +	sethi	%hi(sun4m_irq_percpu), %l5
> +	or	%l5, %lo(sun4m_irq_percpu), %o5
> +	sll	%o0, 2, %o0
> +	ld	[%o5 + %o0], %o5
> +	ld	[%o5 + 0x00], %o3	! sun4m_irq_percpu[cpu]->pending
>  	andcc	%o3, %o2, %g0
>  	be	1f			! Must be an NMI async memory error
> -	 st	%o2, [%o5 + 4]
> +	 st	%o2, [%o5 + 0x04]	! sun4m_irq_percpu[cpu]->clear=0x80000000
>  	WRITE_PAUSE
> -	ld	[%o5], %g0
> +	ld	[%o5 + 0x00], %g0	! sun4m_irq_percpu[cpu]->pending
>  	WRITE_PAUSE
>  	or	%l0, PSR_PIL, %l4
>  	wr	%l4, 0x0, %psr
> @@ -323,12 +324,11 @@ linux_trap_ipi15_sun4m:
>  1:
>  	/* NMI async memory error handling. */
>  	sethi	%hi(0x80000000), %l4
> -	sethi	%hi(0x4000), %o3
> -	sub	%o5, %o0, %o5
> -	add	%o5, %o3, %l5
> -	st	%l4, [%l5 + 0xc]
> +	sethi	%hi(sun4m_irq_global), %o5
> +	ld	[%o5 + %lo(sun4m_irq_global)], %l5
> +	st	%l4, [%l5 + 0x0c]	! sun4m_irq_global->mask_set=0x80000000
>  	WRITE_PAUSE
> -	ld	[%l5], %g0
> +	ld	[%l5 + 0x00], %g0	! sun4m_irq_global->pending
>  	WRITE_PAUSE
>  	or	%l0, PSR_PIL, %l4
>  	wr	%l4, 0x0, %psr
> @@ -337,9 +337,9 @@ linux_trap_ipi15_sun4m:
>  	WRITE_PAUSE
>  	call	sun4m_nmi
>  	 nop
> -	st	%l4, [%l5 + 0x8]
> +	st	%l4, [%l5 + 0x08]	! sun4m_irq_global->mask_clear=0x80000000
>  	WRITE_PAUSE
> -	ld	[%l5], %g0
> +	ld	[%l5 + 0x00], %g0	! sun4m_irq_global->pending
>  	WRITE_PAUSE
>  	RESTORE_ALL
>  
> diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
> index 5b17146..39d40e9 100644
> --- a/arch/sparc/kernel/sun4m_irq.c
> +++ b/arch/sparc/kernel/sun4m_irq.c
> @@ -41,53 +41,25 @@
>  
>  #include "irq.h"
>  
> -/* On the sun4m, just like the timers, we have both per-cpu and master
> - * interrupt registers.
> - */
> -
> -/* These registers are used for sending/receiving irqs from/to
> - * different cpu's.
> - */
> -struct sun4m_intreg_percpu {
> -	unsigned int tbt;        /* Interrupts still pending for this cpu. */
> -
> -	/* These next two registers are WRITE-ONLY and are only
> -	 * "on bit" sensitive, "off bits" written have NO affect.
> -	 */
> -	unsigned int clear;  /* Clear this cpus irqs here. */
> -	unsigned int set;    /* Set this cpus irqs here. */
> -	unsigned char space[PAGE_SIZE - 12];
> +struct sun4m_irq_percpu {
> +	u32		pending;
> +	u32		clear;
> +	u32		set;
>  };
>  
> -/*
> - * djhr
> - * Actually the clear and set fields in this struct are misleading..
> - * according to the SLAVIO manual (and the same applies for the SEC)
> - * the clear field clears bits in the mask which will ENABLE that IRQ
> - * the set field sets bits in the mask to DISABLE the IRQ.
> - *
> - * Also the undirected_xx address in the SLAVIO is defined as
> - * RESERVED and write only..
> - *
> - * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor
> - *             sun4m machines, for MP the layout makes more sense.
> - */
> -struct sun4m_intregs {
> -	struct sun4m_intreg_percpu cpu_intregs[SUN4M_NCPUS];
> -	unsigned int tbt;                /* IRQ's that are still pending. */
> -	unsigned int irqs;               /* Master IRQ bits. */
> -
> -	/* Again, like the above, two these registers are WRITE-ONLY. */
> -	unsigned int clear;              /* Clear master IRQ's by setting bits here. */
> -	unsigned int set;                /* Set master IRQ's by setting bits here. */
> -
> -	/* This register is both READ and WRITE. */
> -	unsigned int undirected_target;  /* Which cpu gets undirected irqs. */
> +struct sun4m_irq_global {
> +	u32		pending;
> +	u32		mask;
> +	u32		mask_clear;
> +	u32		mask_set;
> +	u32		interrupt_target;
>  };
>  
> -static unsigned long dummy;
> +/* Code in entry.S needs to get at these register mappings.  */
> +struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
> +struct sun4m_irq_global __iomem *sun4m_irq_global;
>  
> -struct sun4m_intregs *sun4m_interrupts;
> +static unsigned long dummy;
>  unsigned long *irq_rcvreg = &dummy;
>  
>  /* Dave Redman (djhr@tadpole.co.uk)
> @@ -182,9 +154,9 @@ static void sun4m_disable_irq(unsigned int irq_nr)
>  	mask = sun4m_get_irqmask(irq_nr);
>  	local_irq_save(flags);
>  	if (irq_nr > 15)
> -		sun4m_interrupts->set = mask;
> +		sbus_writel(mask, &sun4m_irq_global->mask_set);
>  	else
> -		sun4m_interrupts->cpu_intregs[cpu].set = mask;
> +		sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
>  	local_irq_restore(flags);    
>  }
>  
> @@ -201,13 +173,13 @@ static void sun4m_enable_irq(unsigned int irq_nr)
>  		mask = sun4m_get_irqmask(irq_nr);
>  		local_irq_save(flags);
>  		if (irq_nr > 15)
> -			sun4m_interrupts->clear = mask;
> +			sbus_writel(mask, &sun4m_irq_global->mask_clear);
>  		else
> -			sun4m_interrupts->cpu_intregs[cpu].clear = mask;
> +			sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
>  		local_irq_restore(flags);    
>  	} else {
>  		local_irq_save(flags);
> -		sun4m_interrupts->clear = SUN4M_INT_FLOPPY;
> +		sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear);
>  		local_irq_restore(flags);
>  	}
>  }
> @@ -236,34 +208,30 @@ static unsigned long cpu_pil_to_imask[16] = {
>   */
>  static void sun4m_disable_pil_irq(unsigned int pil)
>  {
> -	sun4m_interrupts->set = cpu_pil_to_imask[pil];
> +	sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_set);
>  }
>  
>  static void sun4m_enable_pil_irq(unsigned int pil)
>  {
> -	sun4m_interrupts->clear = cpu_pil_to_imask[pil];
> +	sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_clear);
>  }
>  
>  #ifdef CONFIG_SMP
>  static void sun4m_send_ipi(int cpu, int level)
>  {
> -	unsigned long mask;
> -
> -	mask = sun4m_get_irqmask(level);
> -	sun4m_interrupts->cpu_intregs[cpu].set = mask;
> +	unsigned long mask = sun4m_get_irqmask(level);
> +	sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
>  }
>  
>  static void sun4m_clear_ipi(int cpu, int level)
>  {
> -	unsigned long mask;
> -
> -	mask = sun4m_get_irqmask(level);
> -	sun4m_interrupts->cpu_intregs[cpu].clear = mask;
> +	unsigned long mask = sun4m_get_irqmask(level);
> +	sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
>  }
>  
>  static void sun4m_set_udt(int cpu)
>  {
> -	sun4m_interrupts->undirected_target = cpu;
> +	sbus_writel(cpu, &sun4m_irq_global->interrupt_target);
>  }
>  #endif
>  
> @@ -347,7 +315,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
>  	for (i = 0; i < num_cpu_timers; i++)
>  		sbus_writel(0, &timers_percpu[i]->l14_limit);
>  	if (num_cpu_timers = 4)
> -		sbus_writel(SUN4M_INT_E14, &sun4m_interrupts->set);
> +		sbus_writel(SUN4M_INT_E14, &sun4m_irq_global->mask_set);
>  
>  #ifdef CONFIG_SMP
>  	{
> @@ -372,62 +340,38 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
>  
>  void __init sun4m_init_IRQ(void)
>  {
> -	int ie_node,i;
> -	struct linux_prom_registers int_regs[PROMREG_MAX];
> -	int num_regs;
> -	struct resource r;
> -	int mid;
> -    
> -	local_irq_disable();
> -	if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) = 0 ||
> -	   (ie_node = prom_getchild (ie_node)) = 0 ||
> -	   (ie_node = prom_searchsiblings (ie_node, "interrupt")) = 0) {
> -		prom_printf("Cannot find /obio/interrupt node\n");
> -		prom_halt();
> +	struct device_node *dp = of_find_node_by_name(NULL, "interrupt");
> +	int len, i, mid, num_cpu_iregs;
> +	const u32 *addr;
> +
> +	if (!dp) {
> +		printk(KERN_ERR "sun4m_init_IRQ: No 'interrupt' node.\n");
> +		return;
>  	}
> -	num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs,
> -				    sizeof(int_regs));
> -	num_regs = (num_regs/sizeof(struct linux_prom_registers));
> -    
> -	/* Apply the obio ranges to these registers. */
> -	prom_apply_obio_ranges(int_regs, num_regs);
> -    
> -	int_regs[4].phys_addr = int_regs[num_regs-1].phys_addr;
> -	int_regs[4].reg_size = int_regs[num_regs-1].reg_size;
> -	int_regs[4].which_io = int_regs[num_regs-1].which_io;
> -	for(ie_node = 1; ie_node < 4; ie_node++) {
> -		int_regs[ie_node].phys_addr = int_regs[ie_node-1].phys_addr + PAGE_SIZE;
> -		int_regs[ie_node].reg_size = int_regs[ie_node-1].reg_size;
> -		int_regs[ie_node].which_io = int_regs[ie_node-1].which_io;
> +
> +	addr = of_get_property(dp, "address", &len);
> +	if (!addr) {
> +		printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n");
> +		return;
>  	}
>  
> -	memset((char *)&r, 0, sizeof(struct resource));
> -	/* Map the interrupt registers for all possible cpus. */
> -	r.flags = int_regs[0].which_io;
> -	r.start = int_regs[0].phys_addr;
> -	sun4m_interrupts = (struct sun4m_intregs *) of_ioremap(&r, 0,
> -	    PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu");
> +	num_cpu_iregs = (len / sizeof(u32)) - 1;
> +	for (i = 0; i < num_cpu_iregs; i++) {
> +		sun4m_irq_percpu[i] = (void __iomem *)
> +			(unsigned long) addr[i];
> +	}
> +	sun4m_irq_global = (void __iomem *)
> +		(unsigned long) addr[num_cpu_iregs];
>  
> -	/* Map the system interrupt control registers. */
> -	r.flags = int_regs[4].which_io;
> -	r.start = int_regs[4].phys_addr;
> -	of_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system");
> +	local_irq_disable();
>  
> -	sun4m_interrupts->set = ~SUN4M_INT_MASKALL;
> +	sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set);
>  	for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
> -		sun4m_interrupts->cpu_intregs[mid].clear = ~0x17fff;
> -
> -	if (!cpu_find_by_instance(1, NULL, NULL)) {
> -		/* system wide interrupts go to cpu 0, this should always
> -		 * be safe because it is guaranteed to be fitted or OBP doesn't
> -		 * come up
> -		 *
> -		 * Not sure, but writing here on SLAVIO systems may puke
> -		 * so I don't do it unless there is more than 1 cpu.
> -		 */
> -		irq_rcvreg = (unsigned long *)
> -				&sun4m_interrupts->undirected_target;
> -		sun4m_interrupts->undirected_target = 0;
> +		sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear);
> +
> +	if (num_cpu_iregs = 4) {
> +		irq_rcvreg = (unsigned long *) &sun4m_irq_global->interrupt_target;
> +		sbus_writel(0, &sun4m_irq_global->interrupt_target);
>  	}
>  	BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM);
>  	BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM);
> @@ -442,5 +386,6 @@ void __init sun4m_init_IRQ(void)
>  	BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
>  	BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM);
>  #endif
> +
>  	/* Cannot enable interrupts until OBP ticker is disabled. */
>  }
>
>   


  parent reply	other threads:[~2008-09-20  2:27 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-14  4:45 [PATCH]: Updated PROM sun4m IRQ register patch David Miller
2008-09-14 13:41 ` Robert Reif
2008-09-14 14:13 ` Robert Reif
2008-09-14 14:38 ` Robert Reif
2008-09-14 23:51 ` Robert Reif
2008-09-15  0:04 ` David Miller
2008-09-16 17:42 ` David Miller
2008-09-17  2:52 ` Robert Reif
2008-09-17  6:29 ` David Miller
2008-09-19 21:24 ` David Miller
2008-09-20  2:27 ` Robert Reif [this message]
2008-09-20  3:42 ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=48D45F81.8020103@earthlink.net \
    --to=reif@earthlink.net \
    --cc=sparclinux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.