linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* APUS irq patch
@ 2001-11-01 23:18 Roman Zippel
  2001-11-01 23:53 ` Tom Rini
  2001-11-02 21:54 ` Paul Mackerras
  0 siblings, 2 replies; 12+ messages in thread
From: Roman Zippel @ 2001-11-01 23:18 UTC (permalink / raw)
  To: linuxppc-dev


Hi,

Here is the next APUS patch. The patch applies basically to stable and
devel (only the last patch fails on stable, but can be ignored).
This patch converts the irq assembly in head.S into C, the only problem is
that I needed to change a prototype in <linux/irq.h>, as some additional
info has to be saved/restored during an irq.

bye, Roman

--- arch/ppc/kernel/apus_setup.c	2001/10/25 19:30:42	1.1.1.14
+++ arch/ppc/kernel/apus_setup.c	2001/10/29 23:09:38	1.26
@@ -755,30 +708,39 @@
 int apus_get_irq(struct pt_regs* regs)
 {
 #ifdef CONFIG_APUS
-	int level = apus_get_IPL();
+	unsigned char ipl_emu;
+	unsigned int level;

+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET|IPLEMU_DISABLEINT);
+	APUS_READ(APUS_IPL_EMU, ipl_emu);
+	regs->mq = ipl_emu;
+
+	level = (ipl_emu >> 3) & 7;
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET|level);
+	level ^= 7;
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|level);
+
 #ifdef __INTERRUPT_DEBUG
 	printk("<%d:%d>", level, apus_get_prev_IPL(regs));
 #endif

-	if (0 == level)
-		return -8;
-	if (7 == level)
-		return -9;
-
 	return level + IRQ_AMIGA_AUTO;
 #else
 	return 0;
 #endif
 }
+

-void apus_post_irq(struct pt_regs* regs, int level)
+void apus_end_irq(struct pt_regs* regs, unsigned int irq)
 {
+	unsigned char ipl_emu;
 #ifdef __INTERRUPT_DEBUG
 	printk("{%d}", apus_get_prev_IPL(regs));
 #endif
-	/* Restore IPL to the previous value */
-	apus_set_IPL(apus_get_prev_IPL(regs));
+	ipl_emu = regs->mq & 7;
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET|ipl_emu);
+	ipl_emu ^= 7;
+	APUS_WRITE(APUS_IPL_EMU, ipl_emu);
 }

 /****************************************************** keyboard */
@@ -958,6 +926,7 @@
 	amiga_enable_irq,
 	amiga_disable_irq,
 	0,
+	apus_end_irq,
 	0
 };

@@ -1074,9 +1054,6 @@
 	ppc_md.irq_cannonicalize = apus_irq_cannonicalize;
 	ppc_md.init_IRQ       = apus_init_IRQ;
 	ppc_md.get_irq        = apus_get_irq;
-
-#error Should use the ->end() member of irq_desc[x]. -- Cort
-	/*ppc_md.post_irq       = apus_post_irq;*/

 #ifdef CONFIG_HEARTBEAT
 	ppc_md.heartbeat      = apus_heartbeat;
--- arch/ppc/kernel/head.S	2001/10/25 19:30:56	1.1.1.20
+++ arch/ppc/kernel/head.S	2001/10/25 22:02:39	1.24
@@ -385,19 +401,15 @@
 /* External interrupt */
 	. = 0x500;
 HardwareInterrupt:
-	EXCEPTION_PROLOG;
+	EXCEPTION_PROLOG
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	li	r20,MSR_KERNEL
-#ifndef CONFIG_APUS
 	li	r4,0
 	bl	transfer_to_handler
 	.globl do_IRQ_intercept
 do_IRQ_intercept:
 	.long	do_IRQ;
 	.long	ret_from_intercept
-#else
-	bl	apus_interrupt_entry
-#endif /* CONFIG_APUS */

 /* Alignment exception */
 	. = 0x600
@@ -1172,63 +1184,7 @@
 	sync				/* additional sync needed on g4 */
 	isync				/* No speculative loading until now */
 	blr
-
-apus_interrupt_entry:
-	/* This is horrible, but there's no way around it. Enable the
-	 * data cache so the IRQ hardware register can be accessed
-	 * without cache intervention. Then disable interrupts and get
-	 * the current emulated m68k IPL value.
-	 */
-
-	mfmsr	20
-	xori	r20,r20,MSR_DR
-	SYNC
-	mtmsr	r20
-	isync
-
-	lis	r4,APUS_IPL_EMU@h
-
-	li	r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT)
-	stb	r20,APUS_IPL_EMU@l(r4)
-	eieio
-
-	lbz	r3,APUS_IPL_EMU@l(r4)
-
-	li	r2,IPLEMU_IPLMASK
-	rlwinm. r20,r3,32-3,29,31
-	bne	2f
-	mr	r20,r2		/* lvl7! Need to reset state machine. */
-	b	3f
-2:	cmp	0,r20,r2
-	beq	1f
-3:	eieio
-	stb     r2,APUS_IPL_EMU@l(r4)
-	ori	r20,r20,IPLEMU_SETRESET
-	eieio
-	stb     r20,APUS_IPL_EMU@l(r4)
-1:	eieio
-	li	r20,IPLEMU_DISABLEINT
-	stb	r20,APUS_IPL_EMU@l(r4)
-
-	/* At this point we could do some magic to avoid the overhead
-	 * of calling the C interrupt handler in case of a spurious
-	 * interrupt. Could not get a simple hack to work though.
-	 */
-
-	mfmsr	r20
-	xori	r20,r20,MSR_DR
-	SYNC
-	mtmsr	r20
-	isync

-	stw	r3,(_CCR+4)(r21);
-
-	addi	r3,r1,STACK_FRAME_OVERHEAD;
-	li	r20,MSR_KERNEL;
-	bl	transfer_to_handler;
-	.long	do_IRQ;
-	.long	ret_from_except
-
 /***********************************************************************
  *  Please note that on APUS the exception handlers are located at the
  *  physical address 0xfff0000. For this reason, the exception handlers
--- arch/ppc/kernel/i8259.c	2001/07/08 15:57:31	1.1.1.6
+++ arch/ppc/kernel/i8259.c	2001/11/01 22:30:26
@@ -114,7 +114,7 @@
 	spin_unlock_irqrestore(&i8259_lock, flags);
 }

-static void i8259_end_irq(unsigned int irq)
+static void i8259_end_irq(struct pt_regs* regs, unsigned int irq)
 {
 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		i8259_unmask_irq(irq);
--- arch/ppc/kernel/irq.c	2001/10/16 15:53:49	1.1.1.18
+++ arch/ppc/kernel/irq.c	2001/10/17 22:56:12	1.11
@@ -527,7 +527,7 @@
 	 */
 	if (irq_desc[irq].handler) {
 		if (irq_desc[irq].handler->end)
-			irq_desc[irq].handler->end(irq);
+			irq_desc[irq].handler->end(regs, irq);
 		else if (irq_desc[irq].handler->enable)
 			irq_desc[irq].handler->enable(irq);
 	}
--- arch/ppc/kernel/open_pic.c	2001/10/25 19:30:53	1.1.1.16
+++ arch/ppc/kernel/open_pic.c	2001/11/01 22:30:27
@@ -84,7 +84,7 @@
 /*
  * Description of the openpic for the higher-level irq code
  */
-static void openpic_end_irq(unsigned int irq_nr);
+static void openpic_end_irq(struct pt_regs* regs, unsigned int irq_nr);
 static void openpic_ack_irq(unsigned int irq_nr);
 static void openpic_set_affinity(unsigned int irq_nr, unsigned long cpumask);

@@ -100,7 +100,7 @@
 };

 #ifdef CONFIG_SMP
-static void openpic_end_ipi(unsigned int irq_nr);
+static void openpic_end_ipi(struct pt_regs* regs, unsigned int irq_nr);
 static void openpic_ack_ipi(unsigned int irq_nr);
 static void openpic_enable_ipi(unsigned int irq_nr);
 static void openpic_disable_ipi(unsigned int irq_nr);
@@ -749,7 +749,7 @@
 	openpic_eoi();
 }

-static void openpic_end_irq(unsigned int irq_nr)
+static void openpic_end_irq(struct pt_regs* regs, unsigned int irq_nr)
 {
 	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		openpic_enable_irq(irq_nr);
@@ -766,7 +766,7 @@
 	openpic_eoi();
 }

-static void openpic_end_ipi(unsigned int irq_nr)
+static void openpic_end_ipi(struct pt_regs* regs, unsigned int irq_nr)
 {
 }

--- arch/ppc/kernel/pmac_pic.c	2001/10/16 15:53:40	1.1.1.13
+++ arch/ppc/kernel/pmac_pic.c	2001/11/01 22:30:30
@@ -124,7 +124,7 @@
         pmac_set_irq_mask(irq_nr);
 }

-static void __pmac pmac_end_irq(unsigned int irq_nr)
+static void __pmac pmac_end_irq(struct pt_regs* regs, unsigned int irq_nr)
 {
 	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
         	set_bit(irq_nr, ppc_cached_irq_mask);
--- arch/ppc/kernel/xics.c	2001/07/08 15:57:58	1.1.1.5
+++ arch/ppc/kernel/xics.c	2001/11/01 22:30:30
@@ -24,7 +24,7 @@
 void xics_enable_irq(u_int irq);
 void xics_disable_irq(u_int irq);
 void xics_mask_and_ack_irq(u_int irq);
-void xics_end_irq(u_int irq);
+void xics_end_irq(struct pt_regs* regs, u_int irq);

 struct hw_interrupt_type xics_pic = {
 	" XICS     ",
@@ -120,7 +120,7 @@

 void
 xics_end_irq(
-	u_int	irq
+	struct pt_regs* regs, u_int	irq
 	)
 {
 	int cpu = smp_processor_id();
--- include/linux/irq.h	2001/10/16 18:57:02	1.1.1.6
+++ include/linux/irq.h	2001/10/17 22:56:15	1.4
@@ -43,7 +43,7 @@
 	void (*enable)(unsigned int irq);
 	void (*disable)(unsigned int irq);
 	void (*ack)(unsigned int irq);
-	void (*end)(unsigned int irq);
+	void (*end)(struct pt_regs* regs, unsigned int irq);
 	void (*set_affinity)(unsigned int irq, unsigned long mask);
 };


------------ linuxppc_2_4_devel only!

--- arch/ppc/kernel/ppc8xx_pic.c.org	Thu Nov  1 23:49:06 2001
+++ arch/ppc/kernel/ppc8xx_pic.c	Thu Nov  1 23:49:40 2001
@@ -44,7 +44,7 @@
 						ppc_cached_irq_mask[word];
 }

-static void m8xx_end_irq(unsigned int irq_nr)
+static void m8xx_end_irq(struct pt_regs* regs, unsigned int irq_nr)
 {
 	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
 		int bit, word;


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: APUS irq patch
  2001-11-01 23:18 APUS irq patch Roman Zippel
@ 2001-11-01 23:53 ` Tom Rini
  2001-11-02  0:27   ` Roman Zippel
  2001-11-02 21:54 ` Paul Mackerras
  1 sibling, 1 reply; 12+ messages in thread
From: Tom Rini @ 2001-11-01 23:53 UTC (permalink / raw)
  To: Roman Zippel; +Cc: linuxppc-dev


On Fri, Nov 02, 2001 at 12:18:34AM +0100, Roman Zippel wrote:

> This patch converts the irq assembly in head.S into C, the only problem is
> that I needed to change a prototype in <linux/irq.h>, as some additional
> info has to be saved/restored during an irq.

Ack.  Won't this break other things?  I'm assuming other arches use
-end() too..

--
Tom Rini (TR1265)
http://gate.crashing.org/~trini/

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: APUS irq patch
  2001-11-01 23:53 ` Tom Rini
@ 2001-11-02  0:27   ` Roman Zippel
  2001-11-02  0:57     ` Tom Rini
  0 siblings, 1 reply; 12+ messages in thread
From: Roman Zippel @ 2001-11-02  0:27 UTC (permalink / raw)
  To: Tom Rini; +Cc: linuxppc-dev


Hi,

Tom Rini wrote:

> > This patch converts the irq assembly in head.S into C, the only problem is
> > that I needed to change a prototype in <linux/irq.h>, as some additional
> > info has to be saved/restored during an irq.
>
> Ack.  Won't this break other things?  I'm assuming other arches use
> -end() too..

Quite a lot actually and I don't think it's solvable before 2.5.
It's a bit unfortunate that a architecture specific structure is in a
general header. post_irq doesn't exist anymore (which had the pt_regs
pointer), the only other solution would be to rename hw_interrupt_type
and use a private version.

bye, Roman

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: APUS irq patch
  2001-11-02  0:27   ` Roman Zippel
@ 2001-11-02  0:57     ` Tom Rini
  2001-11-02  9:59       ` Roman Zippel
  0 siblings, 1 reply; 12+ messages in thread
From: Tom Rini @ 2001-11-02  0:57 UTC (permalink / raw)
  To: Roman Zippel; +Cc: linuxppc-dev


On Fri, Nov 02, 2001 at 01:27:46AM +0100, Roman Zippel wrote:

> Tom Rini wrote:
>
> > > This patch converts the irq assembly in head.S into C, the only problem is
> > > that I needed to change a prototype in <linux/irq.h>, as some additional
> > > info has to be saved/restored during an irq.
> >
> > Ack.  Won't this break other things?  I'm assuming other arches use
> > -end() too..
>
> Quite a lot actually and I don't think it's solvable before 2.5.
> It's a bit unfortunate that a architecture specific structure is in a
> general header. post_irq doesn't exist anymore (which had the pt_regs
> pointer), the only other solution would be to rename hw_interrupt_type
> and use a private version.

Well, could we accomidate APUS with some PPC-specific changes that don't
touch generic stuffs?

--
Tom Rini (TR1265)
http://gate.crashing.org/~trini/

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: APUS irq patch
  2001-11-02  0:57     ` Tom Rini
@ 2001-11-02  9:59       ` Roman Zippel
  2001-11-02 16:03         ` Tom Rini
  0 siblings, 1 reply; 12+ messages in thread
From: Roman Zippel @ 2001-11-02  9:59 UTC (permalink / raw)
  To: Tom Rini; +Cc: linuxppc-dev


Hi,

On Thu, 1 Nov 2001, Tom Rini wrote:

> Well, could we accomidate APUS with some PPC-specific changes that don't
> touch generic stuffs?

Hmm, only by adding the call to apus_end_irq directly to the interrupt
routine (within an #ifdef CONFIG_APUS).

bye, Roman


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: APUS irq patch
  2001-11-02  9:59       ` Roman Zippel
@ 2001-11-02 16:03         ` Tom Rini
  0 siblings, 0 replies; 12+ messages in thread
From: Tom Rini @ 2001-11-02 16:03 UTC (permalink / raw)
  To: Roman Zippel; +Cc: linuxppc-dev


On Fri, Nov 02, 2001 at 10:59:00AM +0100, Roman Zippel wrote:
> Hi,
>
> On Thu, 1 Nov 2001, Tom Rini wrote:
>
> > Well, could we accomidate APUS with some PPC-specific changes that don't
> > touch generic stuffs?
>
> Hmm, only by adding the call to apus_end_irq directly to the interrupt
> routine (within an #ifdef CONFIG_APUS).

IMHO, that's a better solution for 2.4.  I'm assuming the end goal of
all of this merging is to get APUS working in kernel.org, right? :)

--
Tom Rini (TR1265)
http://gate.crashing.org/~trini/

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: APUS irq patch
  2001-11-01 23:18 APUS irq patch Roman Zippel
  2001-11-01 23:53 ` Tom Rini
@ 2001-11-02 21:54 ` Paul Mackerras
  2001-11-02 22:44   ` Roman Zippel
  1 sibling, 1 reply; 12+ messages in thread
From: Paul Mackerras @ 2001-11-02 21:54 UTC (permalink / raw)
  To: Roman Zippel; +Cc: linuxppc-dev


Roman,

> This patch converts the irq assembly in head.S into C, the only problem is
> that I needed to change a prototype in <linux/irq.h>, as some additional
> info has to be saved/restored during an irq.

Could you describe for us how the APUS interrupt stuff works?  In
looking at your patch, I found myself thinking "there's got to be a
better way" but before making any suggestions I want to make sure I
understand what is being done and why.

Paul.

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: APUS irq patch
  2001-11-02 21:54 ` Paul Mackerras
@ 2001-11-02 22:44   ` Roman Zippel
  0 siblings, 0 replies; 12+ messages in thread
From: Roman Zippel @ 2001-11-02 22:44 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev


Hi,

Paul Mackerras wrote:

> Could you describe for us how the APUS interrupt stuff works?  In
> looking at your patch, I found myself thinking "there's got to be a
> better way" but before making any suggestions I want to make sure I
> understand what is being done and why.

APUS emulates the interrupt levels of the m68k, so at interrupt entry we
have to save the current interrupt level, set the new one and restore it
at the exit. There is another possibility to use a local lookup table to
store the previous value. I have to test that...

bye, Roman

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* APUS irq patch
@ 2001-11-10 22:10 Roman Zippel
  2001-11-11  2:58 ` Tom Rini
  0 siblings, 1 reply; 12+ messages in thread
From: Roman Zippel @ 2001-11-10 22:10 UTC (permalink / raw)
  To: linuxppc-dev


Hi,

Here is a new patch to update APUS irq handling.
First, it moves the assembly part in head.S to apus_get_irq, which uses a
local table instead of the stack now to save some additional irq context.
Second, the major change of this patch is to convert APUS to use the
general irq management code.

bye, Roman

--- arch/ppc/amiga/amiints.c	Sat Nov 10 20:21:14 2001
+++ arch/ppc/amiga/amiints.c	Sat Nov 10 22:56:20 2001
@@ -42,6 +42,8 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>

@@ -78,7 +80,7 @@

 static void ami_badint(int irq, void *dev_id, struct pt_regs *fp)
 {
-	num_spurious += 1;
+/*	num_spurious += 1;*/
 }

 /*
@@ -97,19 +99,6 @@
 {
 	int i;

-	/* initialize handlers */
-	for (i = 0; i < AMI_STD_IRQS; i++) {
-		if (ami_servers[i]) {
-			ami_irq_list[i] = NULL;
-		} else {
-			ami_irq_list[i] = new_irq_node();
-			ami_irq_list[i]->handler = ami_badint;
-			ami_irq_list[i]->flags   = 0;
-			ami_irq_list[i]->dev_id  = NULL;
-			ami_irq_list[i]->devname = NULL;
-			ami_irq_list[i]->next    = NULL;
-		}
-	}
 	for (i = 0; i < AMI_IRQS; i++)
 		ami_ablecount[i] = 0;

@@ -350,20 +339,24 @@

 inline void amiga_do_irq(int irq, struct pt_regs *fp)
 {
+	irq_desc_t *desc = irq_desc + irq;
+	struct irqaction *action = desc->action;
+
 	kstat.irqs[0][irq]++;
-	ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
+	action->handler(irq, action->dev_id, fp);
 }

 void amiga_do_irq_list(int irq, struct pt_regs *fp)
 {
-	irq_node_t *node;
+	irq_desc_t *desc = irq_desc + irq;
+	struct irqaction *action;

 	kstat.irqs[0][irq]++;

 	custom.intreq = ami_intena_vals[irq];

-	for (node = ami_irq_list[irq]; node; node = node->next)
-		node->handler(irq, node->dev_id, fp);
+	for (action = desc->action; action; action = action->next)
+		action->handler(irq, action->dev_id, fp);
 }

 /*
@@ -469,9 +462,15 @@
 /* The PPC irq handling links all handlers requested on the same vector
    and executes them in a loop. Having ami_badint at the end of the chain
    is a bad idea. */
-void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
-	NULL, ami_int1, NULL, ami_int3,
-	ami_int4, ami_int5, NULL, ami_int7
+struct irqaction amiga_sys_irqaction[AUTO_IRQS] = {
+	{ handler: ami_badint, name: "spurious int" },
+	{ handler: ami_int1, name: "int1 handler" },
+	{ 0, /* CIAA */ },
+	{ handler: ami_int3, name: "int3 handler" },
+	{ handler: ami_int4, name: "int4 handler" },
+	{ handler: ami_int5, name: "int5 handler" },
+	{ 0, /* CIAB */ },
+	{ handler: ami_int7, name: "int7 handler" },
 };
 #else
 void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
--- arch/ppc/amiga/cia.c	Sat Nov 10 20:24:14 2001
+++ arch/ppc/amiga/cia.c	Sat Nov 10 22:58:12 2001
@@ -16,7 +16,8 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>

@@ -99,15 +100,13 @@
 }

 /*
- *  Enable or disable CIA interrupts, return old interrupt mask,
- *  interrupts will only be enabled if a handler exists
+ *  Enable or disable CIA interrupts, return old interrupt mask.
  */

 static unsigned char cia_able_irq_private(struct ciabase *base,
 					  unsigned char mask)
 {
-	u_char old, tmp;
-	int i;
+	u_char old;

 	old = base->icr_mask;
 	base->icr_data |= base->cia->icr;
@@ -117,12 +116,7 @@
 	else
 		base->icr_mask &= ~mask;
 	base->icr_mask &= CIA_ICR_ALL;
-	for (i = 0, tmp = 1; i < CIA_IRQS; i++, tmp <<= 1) {
-		if ((tmp & base->icr_mask) && !base->irq_list[i].handler) {
-			base->icr_mask &= ~tmp;
-			base->cia->icr = tmp;
-		}
-	}
+
 	if (base->icr_data & base->icr_mask)
 		custom.intreq = IF_SETCLR | base->int_mask;
 	return old;
@@ -185,38 +179,42 @@
 static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
 {
 	struct ciabase *base = (struct ciabase *)dev_id;
+	irq_desc_t *desc;
+	struct irqaction *action;
 	int i;
 	unsigned char ints;

 	irq = base->cia_irq;
+	desc = irq_desc + irq;
 	ints = cia_set_irq_private(base, CIA_ICR_ALL);
 	custom.intreq = base->int_mask;
 	for (i = 0; i < CIA_IRQS; i++, irq++) {
 		if (ints & 1) {
 			kstat.irqs[0][irq]++;
-			base->irq_list[i].handler(irq, base->irq_list[i].dev_id, fp);
+			action = desc->action;
+			action->handler(irq, action->dev_id, fp);
 		}
 		ints >>= 1;
+		desc++;
 	}
 	amiga_do_irq_list(base->server_irq, fp);
 }

 void __init cia_init_IRQ(struct ciabase *base)
 {
-	int i;
-
-	/* init isr handlers */
-	for (i = 0; i < CIA_IRQS; i++) {
-		base->irq_list[i].handler = NULL;
-		base->irq_list[i].flags   = 0;
-	}
+	extern struct irqaction amiga_sys_irqaction[AUTO_IRQS];
+	struct irqaction *action;

 	/* clear any pending interrupt and turn off all interrupts */
 	cia_set_irq_private(base, CIA_ICR_ALL);
 	cia_able_irq_private(base, CIA_ICR_ALL);

 	/* install CIA handler */
-	request_irq(base->handler_irq, cia_handler, 0, base->name, base);
+	action = &amiga_sys_irqaction[base->handler_irq-IRQ_AMIGA_AUTO];
+	action->handler = cia_handler;
+	action->dev_id = base;
+	action->name = base->name;
+	setup_irq(base->handler_irq, &amiga_sys_irqaction[base->handler_irq-IRQ_AMIGA_AUTO]);

 	custom.intena = IF_SETCLR | base->int_mask;
 }
--- arch/ppc/amiga/config.c	Sat Nov 10 20:24:35 2001
+++ arch/ppc/amiga/config.c	Sat Nov 10 20:34:45 2001
@@ -413,16 +413,16 @@
   mach_keyb_init       = amiga_keyb_init;
   mach_kbdrate         = amiga_kbdrate;
   mach_init_IRQ        = amiga_init_IRQ;
-  mach_default_handler = &amiga_default_handler;
 #ifndef CONFIG_APUS
+  mach_default_handler = &amiga_default_handler;
   mach_request_irq     = amiga_request_irq;
   mach_free_irq        = amiga_free_irq;
   enable_irq           = amiga_enable_irq;
   disable_irq          = amiga_disable_irq;
+  mach_get_irq_list    = amiga_get_irq_list;
 #endif
   mach_get_model       = amiga_get_model;
   mach_get_hardware_list = amiga_get_hardware_list;
-  mach_get_irq_list    = amiga_get_irq_list;
   mach_gettimeoffset   = amiga_gettimeoffset;
   if (AMIGAHW_PRESENT(A3000_CLK)){
     mach_gettod  = a3000_gettod;
--- arch/ppc/kernel/apus_setup.c	Sat Nov 10 20:31:04 2001
+++ arch/ppc/kernel/apus_setup.c	Sat Nov 10 23:00:10 2001
@@ -77,6 +77,8 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/machdep.h>
+#include <asm/keyboard.h>
+#include <asm/time.h>

 unsigned long m68k_machtype;
 char debug_device[6] = "";
@@ -751,33 +753,47 @@
 }
 #endif

+static unsigned char last_ipl[8];
+
 int apus_get_irq(struct pt_regs* regs)
 {
-#ifdef CONFIG_APUS
-	int level = apus_get_IPL();
+	unsigned char ipl_emu, mask;
+	unsigned int level;

-#ifdef __INTERRUPT_DEBUG
-	printk("<%d:%d>", level, apus_get_prev_IPL(regs));
-#endif
+	APUS_READ(APUS_IPL_EMU, ipl_emu);
+	level = (ipl_emu >> 3) & IPLEMU_IPLMASK;
+	mask = IPLEMU_SETRESET|IPLEMU_DISABLEINT|level;
+	level ^= 7;
+
+	/* Save previous IPL value */
+	if (last_ipl[level])
+		return -2;
+	last_ipl[level] = ipl_emu;
+
+	/* Set to current IPL value */
+	APUS_WRITE(APUS_IPL_EMU, mask);
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|level);

-	if (0 == level)
-		return -8;
-	if (7 == level)
-		return -9;

-	return level + IRQ_AMIGA_AUTO;
-#else
-	return 0;
+#ifdef __INTERRUPT_DEBUG
+	printk("<%d:%d>", level, ~ipl_emu & IPLEMU_IPLMASK);
 #endif
+	return level + IRQ_AMIGA_AUTO;
 }

-void apus_post_irq(struct pt_regs* regs, int level)
+void apus_end_irq(unsigned int irq)
 {
+	unsigned char ipl_emu;
+	unsigned int level = irq - IRQ_AMIGA_AUTO;
 #ifdef __INTERRUPT_DEBUG
-	printk("{%d}", apus_get_prev_IPL(regs));
+	printk("{%d}", ~last_ipl[level] & IPLEMU_IPLMASK);
 #endif
 	/* Restore IPL to the previous value */
-	apus_set_IPL(apus_get_prev_IPL(regs));
+	ipl_emu = last_ipl[level] & IPLEMU_IPLMASK;
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET|IPLEMU_DISABLEINT|ipl_emu);
+	last_ipl[level] = 0;
+	ipl_emu ^= 7;
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|ipl_emu);
 }

 /****************************************************** keyboard */
@@ -947,17 +963,21 @@
 	return NULL;
 }

+extern struct irqaction amiga_sys_irqaction[AUTO_IRQS];
+
+
 extern void amiga_enable_irq(unsigned int irq);
 extern void amiga_disable_irq(unsigned int irq);

+struct hw_interrupt_type amiga_sys_irqctrl = {
+	typename: "Amiga IPL",
+	end: apus_end_irq,
+};
+
 struct hw_interrupt_type amiga_irqctrl = {
-	" Amiga  ",
-	NULL,
-	NULL,
-	amiga_enable_irq,
-	amiga_disable_irq,
-	0,
-	0
+	typename: "Amiga    ",
+	enable: amiga_enable_irq,
+	disable: amiga_disable_irq,
 };

 #define HARDWARE_MAPPED_SIZE (512*1024)
@@ -1027,18 +1047,23 @@
 __init
 void apus_init_IRQ(void)
 {
+	struct irqaction *action;
 	int i;

-	for ( i = 0 ; i < NR_IRQS ; i++ )
-		irq_desc[i].handler = &amiga_irqctrl;
-
-	for (i = 0; i < NUM_IRQ_NODES; i++)
-		nodes[i].handler = NULL;
+#ifdef CONFIG_PCI
+        apus_setup_pci_ptrs();
+#endif

-	for (i = 0; i < AUTO_IRQS; i++) {
-		if (amiga_default_handler[i] != NULL)
-			sys_request_irq(i, amiga_default_handler[i],
-					0, default_names[i], NULL);
+	for ( i = 0 ; i < AMI_IRQS; i++ ) {
+		irq_desc[i].status = IRQ_LEVEL;
+		if (i < IRQ_AMIGA_AUTO) {
+			irq_desc[i].handler = &amiga_irqctrl;
+		} else {
+			irq_desc[i].handler = &amiga_sys_irqctrl;
+			action = &amiga_sys_irqaction[i-IRQ_AMIGA_AUTO];
+			if (action->name)
+				setup_irq(i, action);
+		}
 	}

 	amiga_init_IRQ();
@@ -1074,10 +1099,7 @@
 	ppc_md.irq_cannonicalize = apus_irq_cannonicalize;
 	ppc_md.init_IRQ       = apus_init_IRQ;
 	ppc_md.get_irq        = apus_get_irq;
-
-#error Should use the ->end() member of irq_desc[x]. -- Cort
-	/*ppc_md.post_irq       = apus_post_irq;*/
-
+
 #ifdef CONFIG_HEARTBEAT
 	ppc_md.heartbeat      = apus_heartbeat;
 	ppc_md.heartbeat_count = 1;
--- arch/ppc/kernel/head.S	Sat Nov 10 20:31:25 2001
+++ arch/ppc/kernel/head.S	Sat Nov 10 21:52:28 2001
@@ -373,16 +373,12 @@
 	EXCEPTION_PROLOG;
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	li	r20,MSR_KERNEL
-#ifndef CONFIG_APUS
 	li	r4,0
 	bl	transfer_to_handler
 	.globl do_IRQ_intercept
 do_IRQ_intercept:
 	.long	do_IRQ;
 	.long	ret_from_intercept
-#else
-	bl	apus_interrupt_entry
-#endif /* CONFIG_APUS */

 /* Alignment exception */
 	. = 0x600
@@ -1157,62 +1153,6 @@
 	sync				/* additional sync needed on g4 */
 	isync				/* No speculative loading until now */
 	blr
-
-apus_interrupt_entry:
-	/* This is horrible, but there's no way around it. Enable the
-	 * data cache so the IRQ hardware register can be accessed
-	 * without cache intervention. Then disable interrupts and get
-	 * the current emulated m68k IPL value.
-	 */
-
-	mfmsr	20
-	xori	r20,r20,MSR_DR
-	SYNC
-	mtmsr	r20
-	isync
-
-	lis	r4,APUS_IPL_EMU@h
-
-	li	r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT)
-	stb	r20,APUS_IPL_EMU@l(r4)
-	eieio
-
-	lbz	r3,APUS_IPL_EMU@l(r4)
-
-	li	r2,IPLEMU_IPLMASK
-	rlwinm. r20,r3,32-3,29,31
-	bne	2f
-	mr	r20,r2		/* lvl7! Need to reset state machine. */
-	b	3f
-2:	cmp	0,r20,r2
-	beq	1f
-3:	eieio
-	stb     r2,APUS_IPL_EMU@l(r4)
-	ori	r20,r20,IPLEMU_SETRESET
-	eieio
-	stb     r20,APUS_IPL_EMU@l(r4)
-1:	eieio
-	li	r20,IPLEMU_DISABLEINT
-	stb	r20,APUS_IPL_EMU@l(r4)
-
-	/* At this point we could do some magic to avoid the overhead
-	 * of calling the C interrupt handler in case of a spurious
-	 * interrupt. Could not get a simple hack to work though.
-	 */
-
-	mfmsr	r20
-	xori	r20,r20,MSR_DR
-	SYNC
-	mtmsr	r20
-	isync
-
-	stw	r3,(_CCR+4)(r21);
-
-	addi	r3,r1,STACK_FRAME_OVERHEAD;
-	li	r20,MSR_KERNEL;
-	bl	transfer_to_handler;
-	.long	do_IRQ;
-	.long	ret_from_except

 /***********************************************************************
  *  Please note that on APUS the exception handlers are located at the
--- arch/ppc/kernel/irq.c	Sat Nov 10 20:31:39 2001
+++ arch/ppc/kernel/irq.c	Sat Nov 10 20:34:45 2001
@@ -189,9 +189,6 @@
  * now, this is what I need. -- Dan
  */
 #define request_irq	request_8xxirq
-#elif defined(CONFIG_APUS)
-#define request_irq	request_sysirq
-#define free_irq	sys_free_irq
 #endif

 void free_irq(unsigned int irq, void* dev_id)
@@ -373,9 +370,6 @@

 int get_irq_list(char *buf)
 {
-#ifdef CONFIG_APUS
-	return apus_get_irq_list (buf);
-#else
 	int i, len = 0, j;
 	struct irqaction * action;

@@ -423,7 +417,6 @@
 #endif
 	len += sprintf(buf+len, "BAD: %10u\n", ppc_spurious_interrupts);
 	return len;
-#endif /* CONFIG_APUS */
 }

 static inline void


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: APUS irq patch
  2001-11-10 22:10 Roman Zippel
@ 2001-11-11  2:58 ` Tom Rini
  2001-11-11 11:54   ` Roman Zippel
  0 siblings, 1 reply; 12+ messages in thread
From: Tom Rini @ 2001-11-11  2:58 UTC (permalink / raw)
  To: Roman Zippel; +Cc: linuxppc-dev


On Sat, Nov 10, 2001 at 11:10:25PM +0100, Roman Zippel wrote:

> Here is a new patch to update APUS irq handling.
> First, it moves the assembly part in head.S to apus_get_irq, which uses a
> local table instead of the stack now to save some additional irq context.
> Second, the major change of this patch is to convert APUS to use the
> general irq management code.

Looks good, applied.  In the future can you please make the patches vs
_devel?

--
Tom Rini (TR1265)
http://gate.crashing.org/~trini/

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: APUS irq patch
  2001-11-11  2:58 ` Tom Rini
@ 2001-11-11 11:54   ` Roman Zippel
  2001-11-11 16:18     ` Tom Rini
  0 siblings, 1 reply; 12+ messages in thread
From: Roman Zippel @ 2001-11-11 11:54 UTC (permalink / raw)
  To: Tom Rini; +Cc: linuxppc-dev


Hi,

Tom Rini wrote:

> Looks good, applied.  In the future can you please make the patches vs
> _devel?

I did, but I only didn't made them against the newest version.

bye, Roman

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: APUS irq patch
  2001-11-11 11:54   ` Roman Zippel
@ 2001-11-11 16:18     ` Tom Rini
  0 siblings, 0 replies; 12+ messages in thread
From: Tom Rini @ 2001-11-11 16:18 UTC (permalink / raw)
  To: Roman Zippel; +Cc: linuxppc-dev


On Sun, Nov 11, 2001 at 12:54:25PM +0100, Roman Zippel wrote:

> Tom Rini wrote:
>
> > Looks good, applied.  In the future can you please make the patches vs
> > _devel?
>
> I did, but I only didn't made them against the newest version.

Oh, okay.

--
Tom Rini (TR1265)
http://gate.crashing.org/~trini/

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2001-11-11 16:18 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-11-01 23:18 APUS irq patch Roman Zippel
2001-11-01 23:53 ` Tom Rini
2001-11-02  0:27   ` Roman Zippel
2001-11-02  0:57     ` Tom Rini
2001-11-02  9:59       ` Roman Zippel
2001-11-02 16:03         ` Tom Rini
2001-11-02 21:54 ` Paul Mackerras
2001-11-02 22:44   ` Roman Zippel
  -- strict thread matches above, loose matches on Subject: below --
2001-11-10 22:10 Roman Zippel
2001-11-11  2:58 ` Tom Rini
2001-11-11 11:54   ` Roman Zippel
2001-11-11 16:18     ` Tom Rini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).