Commit f4d86754f956ab5ea73aa91759a0d89a2f0e3f2a

Authored by Finn Thain
Committed by Linus Torvalds
1 parent d74472f0b2

SONIC interrupt handling

Install the built-in macsonic interrupt handler on both IRQs when using
via_alt_mapping. Otherwise the rare interrupt that still comes from the
nubus slot will wedge the nubus.

$ cat /proc/interrupts
auto       2:      89176 via2
auto       3:     744367 sonic
auto       4:          0 scc
auto       6:     318363 via1
auto       7:          0 NMI
mac        9:     119413 framebuffer vbl
mac       10:       1971 ADB
mac       14:     198517 timer
mac       17:      89104 nubus
mac       19:         72 Mac ESP SCSI
mac       56:        629 sonic
mac       62:    1142593 ide0

Version 1 of this patch had a bug where a nubus sonic card would register
two interrupt handlers. Only a built-in sonic needs both.

Versions 2 and 3 needed some cleanups, as Raylynn Knight and Christoph
Hellwig pointed out (thanks).

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 61 additions and 33 deletions Side-by-side Diff

drivers/net/jazzsonic.c
... ... @@ -88,6 +88,23 @@
88 88 0xffff /* end of list */
89 89 };
90 90  
  91 +static int jazzsonic_open(struct net_device* dev)
  92 +{
  93 + if (request_irq(dev->irq, &sonic_interrupt, IRQF_DISABLED, "sonic", dev)) {
  94 + printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
  95 + return -EAGAIN;
  96 + }
  97 + return sonic_open(dev);
  98 +}
  99 +
  100 +static int jazzsonic_close(struct net_device* dev)
  101 +{
  102 + int err;
  103 + err = sonic_close(dev);
  104 + free_irq(dev->irq, dev);
  105 + return err;
  106 +}
  107 +
91 108 static int __init sonic_probe1(struct net_device *dev)
92 109 {
93 110 static unsigned version_printed;
... ... @@ -169,8 +186,8 @@
169 186 lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
170 187 * SONIC_BUS_SCALE(lp->dma_bitmode));
171 188  
172   - dev->open = sonic_open;
173   - dev->stop = sonic_close;
  189 + dev->open = jazzsonic_open;
  190 + dev->stop = jazzsonic_close;
174 191 dev->hard_start_xmit = sonic_send_packet;
175 192 dev->get_stats = sonic_get_stats;
176 193 dev->set_multicast_list = &sonic_multicast_list;
... ... @@ -259,8 +276,6 @@
259 276 MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
260 277 module_param(sonic_debug, int, 0);
261 278 MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
262   -
263   -#define SONIC_IRQ_FLAG IRQF_DISABLED
264 279  
265 280 #include "sonic.c"
266 281  
drivers/net/macsonic.c
... ... @@ -130,6 +130,46 @@
130 130 addr[i] = bitrev8(addr[i]);
131 131 }
132 132  
  133 +static irqreturn_t macsonic_interrupt(int irq, void *dev_id)
  134 +{
  135 + irqreturn_t result;
  136 + unsigned long flags;
  137 +
  138 + local_irq_save(flags);
  139 + result = sonic_interrupt(irq, dev_id);
  140 + local_irq_restore(flags);
  141 + return result;
  142 +}
  143 +
  144 +static int macsonic_open(struct net_device* dev)
  145 +{
  146 + if (request_irq(dev->irq, &sonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) {
  147 + printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
  148 + return -EAGAIN;
  149 + }
  150 + /* Under the A/UX interrupt scheme, the onboard SONIC interrupt comes
  151 + * in at priority level 3. However, we sometimes get the level 2 inter-
  152 + * rupt as well, which must prevent re-entrance of the sonic handler.
  153 + */
  154 + if (dev->irq == IRQ_AUTO_3)
  155 + if (request_irq(IRQ_NUBUS_9, &macsonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) {
  156 + printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, IRQ_NUBUS_9);
  157 + free_irq(dev->irq, dev);
  158 + return -EAGAIN;
  159 + }
  160 + return sonic_open(dev);
  161 +}
  162 +
  163 +static int macsonic_close(struct net_device* dev)
  164 +{
  165 + int err;
  166 + err = sonic_close(dev);
  167 + free_irq(dev->irq, dev);
  168 + if (dev->irq == IRQ_AUTO_3)
  169 + free_irq(IRQ_NUBUS_9, dev);
  170 + return err;
  171 +}
  172 +
133 173 int __init macsonic_init(struct net_device* dev)
134 174 {
135 175 struct sonic_local* lp = netdev_priv(dev);
... ... @@ -160,8 +200,8 @@
160 200 lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
161 201 * SONIC_BUS_SCALE(lp->dma_bitmode));
162 202  
163   - dev->open = sonic_open;
164   - dev->stop = sonic_close;
  203 + dev->open = macsonic_open;
  204 + dev->stop = macsonic_close;
165 205 dev->hard_start_xmit = sonic_send_packet;
166 206 dev->get_stats = sonic_get_stats;
167 207 dev->set_multicast_list = &sonic_multicast_list;
... ... @@ -571,8 +611,6 @@
571 611 MODULE_DESCRIPTION("Macintosh SONIC ethernet driver");
572 612 module_param(sonic_debug, int, 0);
573 613 MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
574   -
575   -#define SONIC_IRQ_FLAG IRQ_FLG_FAST
576 614  
577 615 #include "sonic.c"
578 616  
... ... @@ -50,29 +50,6 @@
50 50 if (sonic_debug > 2)
51 51 printk("sonic_open: initializing sonic driver.\n");
52 52  
53   - /*
54   - * We don't need to deal with auto-irq stuff since we
55   - * hardwire the sonic interrupt.
56   - */
57   -/*
58   - * XXX Horrible work around: We install sonic_interrupt as fast interrupt.
59   - * This means that during execution of the handler interrupt are disabled
60   - * covering another bug otherwise corrupting data. This doesn't mean
61   - * this glue works ok under all situations.
62   - *
63   - * Note (dhd): this also appears to prevent lockups on the Macintrash
64   - * when more than one Ethernet card is installed (knock on wood)
65   - *
66   - * Note (fthain): whether the above is still true is anyones guess. Certainly
67   - * the buffer handling algorithms will not tolerate re-entrance without some
68   - * mutual exclusion added. Anyway, the memcpy has now been eliminated from the
69   - * rx code to make this a faster "fast interrupt".
70   - */
71   - if (request_irq(dev->irq, &sonic_interrupt, SONIC_IRQ_FLAG, "sonic", dev)) {
72   - printk(KERN_ERR "\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
73   - return -EAGAIN;
74   - }
75   -
76 53 for (i = 0; i < SONIC_NUM_RRS; i++) {
77 54 struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2);
78 55 if (skb == NULL) {
... ... @@ -168,8 +145,6 @@
168 145 lp->rx_skb[i] = NULL;
169 146 }
170 147 }
171   -
172   - free_irq(dev->irq, dev); /* release the IRQ */
173 148  
174 149 return 0;
175 150 }