blob: da4f7593c50f54111b0242f9497c9afc7a0bfa3f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 drivers/net/tulip/interrupt.c
3
4 Maintained by Jeff Garzik <jgarzik@pobox.com>
5 Copyright 2000,2001 The Linux Kernel Team
6 Written/copyright 1994-2001 by Donald Becker.
7
8 This software may be used and distributed according to the terms
9 of the GNU General Public License, incorporated herein by reference.
10
11 Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
12 for more information on this driver, or visit the project
13 Web page at http://sourceforge.net/projects/tulip/
14
15*/
16
17#include <linux/pci.h>
18#include "tulip.h"
19#include <linux/config.h>
20#include <linux/etherdevice.h>
21
22int tulip_rx_copybreak;
23unsigned int tulip_max_interrupt_work;
24
25#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
26#define MIT_SIZE 15
27#define MIT_TABLE 15 /* We use 0 or max */
28
29static unsigned int mit_table[MIT_SIZE+1] =
30{
31 /* CRS11 21143 hardware Mitigation Control Interrupt
32 We use only RX mitigation we other techniques for
33 TX intr. mitigation.
34
35 31 Cycle Size (timer control)
36 30:27 TX timer in 16 * Cycle size
37 26:24 TX No pkts before Int.
38 23:20 RX timer in Cycle size
39 19:17 RX No pkts before Int.
40 16 Continues Mode (CM)
41 */
42
43 0x0, /* IM disabled */
44 0x80150000, /* RX time = 1, RX pkts = 2, CM = 1 */
45 0x80150000,
46 0x80270000,
47 0x80370000,
48 0x80490000,
49 0x80590000,
50 0x80690000,
51 0x807B0000,
52 0x808B0000,
53 0x809D0000,
54 0x80AD0000,
55 0x80BD0000,
56 0x80CF0000,
57 0x80DF0000,
58// 0x80FF0000 /* RX time = 16, RX pkts = 7, CM = 1 */
59 0x80F10000 /* RX time = 16, RX pkts = 0, CM = 1 */
60};
61#endif
62
63
64int tulip_refill_rx(struct net_device *dev)
65{
66 struct tulip_private *tp = netdev_priv(dev);
67 int entry;
68 int refilled = 0;
69
70 /* Refill the Rx ring buffers. */
71 for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
72 entry = tp->dirty_rx % RX_RING_SIZE;
73 if (tp->rx_buffers[entry].skb == NULL) {
74 struct sk_buff *skb;
75 dma_addr_t mapping;
76
77 skb = tp->rx_buffers[entry].skb = dev_alloc_skb(PKT_BUF_SZ);
78 if (skb == NULL)
79 break;
80
David S. Miller689be432005-06-28 15:25:31 -070081 mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ,
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 PCI_DMA_FROMDEVICE);
83 tp->rx_buffers[entry].mapping = mapping;
84
85 skb->dev = dev; /* Mark as being used by this device. */
86 tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping);
87 refilled++;
88 }
89 tp->rx_ring[entry].status = cpu_to_le32(DescOwned);
90 }
91 if(tp->chip_id == LC82C168) {
92 if(((ioread32(tp->base_addr + CSR5)>>17)&0x07) == 4) {
93 /* Rx stopped due to out of buffers,
94 * restart it
95 */
96 iowrite32(0x01, tp->base_addr + CSR2);
97 }
98 }
99 return refilled;
100}
101
102#ifdef CONFIG_TULIP_NAPI
103
104void oom_timer(unsigned long data)
105{
106 struct net_device *dev = (struct net_device *)data;
107 netif_rx_schedule(dev);
108}
109
110int tulip_poll(struct net_device *dev, int *budget)
111{
112 struct tulip_private *tp = netdev_priv(dev);
113 int entry = tp->cur_rx % RX_RING_SIZE;
114 int rx_work_limit = *budget;
115 int received = 0;
116
117 if (!netif_running(dev))
118 goto done;
119
120 if (rx_work_limit > dev->quota)
121 rx_work_limit = dev->quota;
122
123#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
124
125/* that one buffer is needed for mit activation; or might be a
126 bug in the ring buffer code; check later -- JHS*/
127
128 if (rx_work_limit >=RX_RING_SIZE) rx_work_limit--;
129#endif
130
131 if (tulip_debug > 4)
132 printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
133 tp->rx_ring[entry].status);
134
135 do {
136 if (ioread32(tp->base_addr + CSR5) == 0xffffffff) {
137 printk(KERN_DEBUG " In tulip_poll(), hardware disappeared.\n");
138 break;
139 }
140 /* Acknowledge current RX interrupt sources. */
141 iowrite32((RxIntr | RxNoBuf), tp->base_addr + CSR5);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400142
143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 /* If we own the next entry, it is a new packet. Send it up. */
145 while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
146 s32 status = le32_to_cpu(tp->rx_ring[entry].status);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400147
148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx)
150 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 if (tulip_debug > 5)
153 printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
154 dev->name, entry, status);
155 if (--rx_work_limit < 0)
156 goto not_done;
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400157
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 if ((status & 0x38008300) != 0x0300) {
159 if ((status & 0x38000300) != 0x0300) {
160 /* Ingore earlier buffers. */
161 if ((status & 0xffff) != 0x7fff) {
162 if (tulip_debug > 1)
163 printk(KERN_WARNING "%s: Oversized Ethernet frame "
164 "spanned multiple buffers, status %8.8x!\n",
165 dev->name, status);
166 tp->stats.rx_length_errors++;
167 }
168 } else if (status & RxDescFatalErr) {
169 /* There was a fatal error. */
170 if (tulip_debug > 2)
171 printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
172 dev->name, status);
173 tp->stats.rx_errors++; /* end of a packet.*/
174 if (status & 0x0890) tp->stats.rx_length_errors++;
175 if (status & 0x0004) tp->stats.rx_frame_errors++;
176 if (status & 0x0002) tp->stats.rx_crc_errors++;
177 if (status & 0x0001) tp->stats.rx_fifo_errors++;
178 }
179 } else {
180 /* Omit the four octet CRC from the length. */
181 short pkt_len = ((status >> 16) & 0x7ff) - 4;
182 struct sk_buff *skb;
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400183
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184#ifndef final_version
185 if (pkt_len > 1518) {
186 printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
187 dev->name, pkt_len, pkt_len);
188 pkt_len = 1518;
189 tp->stats.rx_length_errors++;
190 }
191#endif
192 /* Check if the packet is long enough to accept without copying
193 to a minimally-sized skbuff. */
194 if (pkt_len < tulip_rx_copybreak
195 && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
196 skb->dev = dev;
197 skb_reserve(skb, 2); /* 16 byte align the IP header */
198 pci_dma_sync_single_for_cpu(tp->pdev,
199 tp->rx_buffers[entry].mapping,
200 pkt_len, PCI_DMA_FROMDEVICE);
201#if ! defined(__alpha__)
David S. Miller689be432005-06-28 15:25:31 -0700202 eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 pkt_len, 0);
204 skb_put(skb, pkt_len);
205#else
206 memcpy(skb_put(skb, pkt_len),
David S. Miller689be432005-06-28 15:25:31 -0700207 tp->rx_buffers[entry].skb->data,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 pkt_len);
209#endif
210 pci_dma_sync_single_for_device(tp->pdev,
211 tp->rx_buffers[entry].mapping,
212 pkt_len, PCI_DMA_FROMDEVICE);
213 } else { /* Pass up the skb already on the Rx ring. */
214 char *temp = skb_put(skb = tp->rx_buffers[entry].skb,
215 pkt_len);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400216
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217#ifndef final_version
218 if (tp->rx_buffers[entry].mapping !=
219 le32_to_cpu(tp->rx_ring[entry].buffer1)) {
220 printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
221 "do not match in tulip_rx: %08x vs. %08llx %p / %p.\n",
222 dev->name,
223 le32_to_cpu(tp->rx_ring[entry].buffer1),
224 (unsigned long long)tp->rx_buffers[entry].mapping,
225 skb->head, temp);
226 }
227#endif
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
230 PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400231
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 tp->rx_buffers[entry].skb = NULL;
233 tp->rx_buffers[entry].mapping = 0;
234 }
235 skb->protocol = eth_type_trans(skb, dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 netif_receive_skb(skb);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400238
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 dev->last_rx = jiffies;
240 tp->stats.rx_packets++;
241 tp->stats.rx_bytes += pkt_len;
242 }
243 received++;
244
245 entry = (++tp->cur_rx) % RX_RING_SIZE;
246 if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4)
247 tulip_refill_rx(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400248
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400250
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 /* New ack strategy... irq does not ack Rx any longer
252 hopefully this helps */
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400253
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 /* Really bad things can happen here... If new packet arrives
255 * and an irq arrives (tx or just due to occasionally unset
256 * mask), it will be acked by irq handler, but new thread
257 * is not scheduled. It is major hole in design.
258 * No idea how to fix this if "playing with fire" will fail
259 * tomorrow (night 011029). If it will not fail, we won
260 * finally: amount of IO did not increase at all. */
261 } while ((ioread32(tp->base_addr + CSR5) & RxIntr));
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400262
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263done:
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400264
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400266
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 /* We use this simplistic scheme for IM. It's proven by
268 real life installations. We can have IM enabled
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400269 continuesly but this would cause unnecessary latency.
270 Unfortunely we can't use all the NET_RX_* feedback here.
271 This would turn on IM for devices that is not contributing
272 to backlog congestion with unnecessary latency.
273
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 We monitor the the device RX-ring and have:
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400275
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 HW Interrupt Mitigation either ON or OFF.
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400277
278 ON: More then 1 pkt received (per intr.) OR we are dropping
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 OFF: Only 1 pkt received
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400280
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 Note. We only use min and max (0, 15) settings from mit_table */
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400282
283
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 if( tp->flags & HAS_INTR_MITIGATION) {
285 if( received > 1 ) {
286 if( ! tp->mit_on ) {
287 tp->mit_on = 1;
288 iowrite32(mit_table[MIT_TABLE], tp->base_addr + CSR11);
289 }
290 }
291 else {
292 if( tp->mit_on ) {
293 tp->mit_on = 0;
294 iowrite32(0, tp->base_addr + CSR11);
295 }
296 }
297 }
298
299#endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 dev->quota -= received;
302 *budget -= received;
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400303
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 tulip_refill_rx(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400305
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 /* If RX ring is not full we are out of memory. */
307 if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom;
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 /* Remove us from polling list and enable RX intr. */
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400310
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 netif_rx_complete(dev);
312 iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400313
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 /* The last op happens after poll completion. Which means the following:
315 * 1. it can race with disabling irqs in irq handler
316 * 2. it can race with dise/enabling irqs in other poll threads
317 * 3. if an irq raised after beginning loop, it will be immediately
318 * triggered here.
319 *
320 * Summarizing: the logic results in some redundant irqs both
321 * due to races in masking and due to too late acking of already
322 * processed irqs. But it must not result in losing events.
323 */
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400324
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 return 0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400326
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 not_done:
328 if (!received) {
329
330 received = dev->quota; /* Not to happen */
331 }
332 dev->quota -= received;
333 *budget -= received;
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 ||
336 tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
337 tulip_refill_rx(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400338
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom;
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400340
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 return 1;
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400342
343
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 oom: /* Executed with RX ints disabled */
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400345
346
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 /* Start timer, stop polling, but do not enable rx interrupts. */
348 mod_timer(&tp->oom_timer, jiffies+1);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 /* Think: timer_pending() was an explicit signature of bug.
351 * Timer can be pending now but fired and completed
352 * before we did netif_rx_complete(). See? We would lose it. */
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 /* remove ourselves from the polling list */
355 netif_rx_complete(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400356
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 return 0;
358}
359
360#else /* CONFIG_TULIP_NAPI */
361
362static int tulip_rx(struct net_device *dev)
363{
364 struct tulip_private *tp = netdev_priv(dev);
365 int entry = tp->cur_rx % RX_RING_SIZE;
366 int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
367 int received = 0;
368
369 if (tulip_debug > 4)
370 printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
371 tp->rx_ring[entry].status);
372 /* If we own the next entry, it is a new packet. Send it up. */
373 while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
374 s32 status = le32_to_cpu(tp->rx_ring[entry].status);
375
376 if (tulip_debug > 5)
377 printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
378 dev->name, entry, status);
379 if (--rx_work_limit < 0)
380 break;
381 if ((status & 0x38008300) != 0x0300) {
382 if ((status & 0x38000300) != 0x0300) {
383 /* Ingore earlier buffers. */
384 if ((status & 0xffff) != 0x7fff) {
385 if (tulip_debug > 1)
386 printk(KERN_WARNING "%s: Oversized Ethernet frame "
387 "spanned multiple buffers, status %8.8x!\n",
388 dev->name, status);
389 tp->stats.rx_length_errors++;
390 }
391 } else if (status & RxDescFatalErr) {
392 /* There was a fatal error. */
393 if (tulip_debug > 2)
394 printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
395 dev->name, status);
396 tp->stats.rx_errors++; /* end of a packet.*/
397 if (status & 0x0890) tp->stats.rx_length_errors++;
398 if (status & 0x0004) tp->stats.rx_frame_errors++;
399 if (status & 0x0002) tp->stats.rx_crc_errors++;
400 if (status & 0x0001) tp->stats.rx_fifo_errors++;
401 }
402 } else {
403 /* Omit the four octet CRC from the length. */
404 short pkt_len = ((status >> 16) & 0x7ff) - 4;
405 struct sk_buff *skb;
406
407#ifndef final_version
408 if (pkt_len > 1518) {
409 printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
410 dev->name, pkt_len, pkt_len);
411 pkt_len = 1518;
412 tp->stats.rx_length_errors++;
413 }
414#endif
415
416 /* Check if the packet is long enough to accept without copying
417 to a minimally-sized skbuff. */
418 if (pkt_len < tulip_rx_copybreak
419 && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
420 skb->dev = dev;
421 skb_reserve(skb, 2); /* 16 byte align the IP header */
422 pci_dma_sync_single_for_cpu(tp->pdev,
423 tp->rx_buffers[entry].mapping,
424 pkt_len, PCI_DMA_FROMDEVICE);
425#if ! defined(__alpha__)
David S. Miller689be432005-06-28 15:25:31 -0700426 eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 pkt_len, 0);
428 skb_put(skb, pkt_len);
429#else
430 memcpy(skb_put(skb, pkt_len),
David S. Miller689be432005-06-28 15:25:31 -0700431 tp->rx_buffers[entry].skb->data,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 pkt_len);
433#endif
434 pci_dma_sync_single_for_device(tp->pdev,
435 tp->rx_buffers[entry].mapping,
436 pkt_len, PCI_DMA_FROMDEVICE);
437 } else { /* Pass up the skb already on the Rx ring. */
438 char *temp = skb_put(skb = tp->rx_buffers[entry].skb,
439 pkt_len);
440
441#ifndef final_version
442 if (tp->rx_buffers[entry].mapping !=
443 le32_to_cpu(tp->rx_ring[entry].buffer1)) {
444 printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
445 "do not match in tulip_rx: %08x vs. %Lx %p / %p.\n",
446 dev->name,
447 le32_to_cpu(tp->rx_ring[entry].buffer1),
448 (long long)tp->rx_buffers[entry].mapping,
449 skb->head, temp);
450 }
451#endif
452
453 pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
454 PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
455
456 tp->rx_buffers[entry].skb = NULL;
457 tp->rx_buffers[entry].mapping = 0;
458 }
459 skb->protocol = eth_type_trans(skb, dev);
460
461 netif_rx(skb);
462
463 dev->last_rx = jiffies;
464 tp->stats.rx_packets++;
465 tp->stats.rx_bytes += pkt_len;
466 }
467 received++;
468 entry = (++tp->cur_rx) % RX_RING_SIZE;
469 }
470 return received;
471}
472#endif /* CONFIG_TULIP_NAPI */
473
474static inline unsigned int phy_interrupt (struct net_device *dev)
475{
476#ifdef __hppa__
477 struct tulip_private *tp = netdev_priv(dev);
478 int csr12 = ioread32(tp->base_addr + CSR12) & 0xff;
479
480 if (csr12 != tp->csr12_shadow) {
481 /* ack interrupt */
482 iowrite32(csr12 | 0x02, tp->base_addr + CSR12);
483 tp->csr12_shadow = csr12;
484 /* do link change stuff */
485 spin_lock(&tp->lock);
486 tulip_check_duplex(dev);
487 spin_unlock(&tp->lock);
488 /* clear irq ack bit */
489 iowrite32(csr12 & ~0x02, tp->base_addr + CSR12);
490
491 return 1;
492 }
493#endif
494
495 return 0;
496}
497
498/* The interrupt handler does all of the Rx thread work and cleans up
499 after the Tx thread. */
500irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
501{
502 struct net_device *dev = (struct net_device *)dev_instance;
503 struct tulip_private *tp = netdev_priv(dev);
504 void __iomem *ioaddr = tp->base_addr;
505 int csr5;
506 int missed;
507 int rx = 0;
508 int tx = 0;
509 int oi = 0;
510 int maxrx = RX_RING_SIZE;
511 int maxtx = TX_RING_SIZE;
512 int maxoi = TX_RING_SIZE;
513#ifdef CONFIG_TULIP_NAPI
514 int rxd = 0;
515#else
516 int entry;
517#endif
518 unsigned int work_count = tulip_max_interrupt_work;
519 unsigned int handled = 0;
520
521 /* Let's see whether the interrupt really is for us */
522 csr5 = ioread32(ioaddr + CSR5);
523
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400524 if (tp->flags & HAS_PHY_IRQ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 handled = phy_interrupt (dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
528 return IRQ_RETVAL(handled);
529
530 tp->nir++;
531
532 do {
533
534#ifdef CONFIG_TULIP_NAPI
535
536 if (!rxd && (csr5 & (RxIntr | RxNoBuf))) {
537 rxd++;
538 /* Mask RX intrs and add the device to poll list. */
539 iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7);
540 netif_rx_schedule(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400541
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass)))
543 break;
544 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400545
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 /* Acknowledge the interrupt sources we handle here ASAP
547 the poll function does Rx and RxNoBuf acking */
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400548
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5);
550
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400551#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 /* Acknowledge all of the current interrupt sources ASAP. */
553 iowrite32(csr5 & 0x0001ffff, ioaddr + CSR5);
554
555
556 if (csr5 & (RxIntr | RxNoBuf)) {
557 rx += tulip_rx(dev);
558 tulip_refill_rx(dev);
559 }
560
561#endif /* CONFIG_TULIP_NAPI */
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400562
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 if (tulip_debug > 4)
564 printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n",
565 dev->name, csr5, ioread32(ioaddr + CSR5));
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400566
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
568 if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) {
569 unsigned int dirty_tx;
570
571 spin_lock(&tp->lock);
572
573 for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;
574 dirty_tx++) {
575 int entry = dirty_tx % TX_RING_SIZE;
576 int status = le32_to_cpu(tp->tx_ring[entry].status);
577
578 if (status < 0)
579 break; /* It still has not been Txed */
580
581 /* Check for Rx filter setup frames. */
582 if (tp->tx_buffers[entry].skb == NULL) {
583 /* test because dummy frames not mapped */
584 if (tp->tx_buffers[entry].mapping)
585 pci_unmap_single(tp->pdev,
586 tp->tx_buffers[entry].mapping,
587 sizeof(tp->setup_frame),
588 PCI_DMA_TODEVICE);
589 continue;
590 }
591
592 if (status & 0x8000) {
593 /* There was an major error, log it. */
594#ifndef final_version
595 if (tulip_debug > 1)
596 printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
597 dev->name, status);
598#endif
599 tp->stats.tx_errors++;
600 if (status & 0x4104) tp->stats.tx_aborted_errors++;
601 if (status & 0x0C00) tp->stats.tx_carrier_errors++;
602 if (status & 0x0200) tp->stats.tx_window_errors++;
603 if (status & 0x0002) tp->stats.tx_fifo_errors++;
604 if ((status & 0x0080) && tp->full_duplex == 0)
605 tp->stats.tx_heartbeat_errors++;
606 } else {
607 tp->stats.tx_bytes +=
608 tp->tx_buffers[entry].skb->len;
609 tp->stats.collisions += (status >> 3) & 15;
610 tp->stats.tx_packets++;
611 }
612
613 pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping,
614 tp->tx_buffers[entry].skb->len,
615 PCI_DMA_TODEVICE);
616
617 /* Free the original skb. */
618 dev_kfree_skb_irq(tp->tx_buffers[entry].skb);
619 tp->tx_buffers[entry].skb = NULL;
620 tp->tx_buffers[entry].mapping = 0;
621 tx++;
622 }
623
624#ifndef final_version
625 if (tp->cur_tx - dirty_tx > TX_RING_SIZE) {
626 printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n",
627 dev->name, dirty_tx, tp->cur_tx);
628 dirty_tx += TX_RING_SIZE;
629 }
630#endif
631
632 if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2)
633 netif_wake_queue(dev);
634
635 tp->dirty_tx = dirty_tx;
636 if (csr5 & TxDied) {
637 if (tulip_debug > 2)
638 printk(KERN_WARNING "%s: The transmitter stopped."
639 " CSR5 is %x, CSR6 %x, new CSR6 %x.\n",
640 dev->name, csr5, ioread32(ioaddr + CSR6), tp->csr6);
641 tulip_restart_rxtx(tp);
642 }
643 spin_unlock(&tp->lock);
644 }
645
646 /* Log errors. */
647 if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */
648 if (csr5 == 0xffffffff)
649 break;
650 if (csr5 & TxJabber) tp->stats.tx_errors++;
651 if (csr5 & TxFIFOUnderflow) {
652 if ((tp->csr6 & 0xC000) != 0xC000)
653 tp->csr6 += 0x4000; /* Bump up the Tx threshold */
654 else
655 tp->csr6 |= 0x00200000; /* Store-n-forward. */
656 /* Restart the transmit process. */
657 tulip_restart_rxtx(tp);
658 iowrite32(0, ioaddr + CSR1);
659 }
660 if (csr5 & (RxDied | RxNoBuf)) {
661 if (tp->flags & COMET_MAC_ADDR) {
662 iowrite32(tp->mc_filter[0], ioaddr + 0xAC);
663 iowrite32(tp->mc_filter[1], ioaddr + 0xB0);
664 }
665 }
666 if (csr5 & RxDied) { /* Missed a Rx frame. */
667 tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
668 tp->stats.rx_errors++;
669 tulip_start_rxtx(tp);
670 }
671 /*
672 * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this
673 * call is ever done under the spinlock
674 */
675 if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) {
676 if (tp->link_change)
677 (tp->link_change)(dev, csr5);
678 }
679 if (csr5 & SytemError) {
680 int error = (csr5 >> 23) & 7;
681 /* oops, we hit a PCI error. The code produced corresponds
682 * to the reason:
683 * 0 - parity error
684 * 1 - master abort
685 * 2 - target abort
686 * Note that on parity error, we should do a software reset
687 * of the chip to get it back into a sane state (according
688 * to the 21142/3 docs that is).
689 * -- rmk
690 */
691 printk(KERN_ERR "%s: (%lu) System Error occurred (%d)\n",
692 dev->name, tp->nir, error);
693 }
694 /* Clear all error sources, included undocumented ones! */
695 iowrite32(0x0800f7ba, ioaddr + CSR5);
696 oi++;
697 }
698 if (csr5 & TimerInt) {
699
700 if (tulip_debug > 2)
701 printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n",
702 dev->name, csr5);
703 iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
704 tp->ttimer = 0;
705 oi++;
706 }
707 if (tx > maxtx || rx > maxrx || oi > maxoi) {
708 if (tulip_debug > 1)
709 printk(KERN_WARNING "%s: Too much work during an interrupt, "
710 "csr5=0x%8.8x. (%lu) (%d,%d,%d)\n", dev->name, csr5, tp->nir, tx, rx, oi);
711
712 /* Acknowledge all interrupt sources. */
713 iowrite32(0x8001ffff, ioaddr + CSR5);
714 if (tp->flags & HAS_INTR_MITIGATION) {
715 /* Josip Loncaric at ICASE did extensive experimentation
716 to develop a good interrupt mitigation setting.*/
717 iowrite32(0x8b240000, ioaddr + CSR11);
718 } else if (tp->chip_id == LC82C168) {
719 /* the LC82C168 doesn't have a hw timer.*/
720 iowrite32(0x00, ioaddr + CSR7);
721 mod_timer(&tp->timer, RUN_AT(HZ/50));
722 } else {
723 /* Mask all interrupting sources, set timer to
724 re-enable. */
725 iowrite32(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7);
726 iowrite32(0x0012, ioaddr + CSR11);
727 }
728 break;
729 }
730
731 work_count--;
732 if (work_count == 0)
733 break;
734
735 csr5 = ioread32(ioaddr + CSR5);
736
737#ifdef CONFIG_TULIP_NAPI
738 if (rxd)
739 csr5 &= ~RxPollInt;
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400740 } while ((csr5 & (TxNoBuf |
741 TxDied |
742 TxIntr |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 TimerInt |
744 /* Abnormal intr. */
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400745 RxDied |
746 TxFIFOUnderflow |
747 TxJabber |
748 TPLnkFail |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 SytemError )) != 0);
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400750#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0);
752
753 tulip_refill_rx(dev);
754
755 /* check if the card is in suspend mode */
756 entry = tp->dirty_rx % RX_RING_SIZE;
757 if (tp->rx_buffers[entry].skb == NULL) {
758 if (tulip_debug > 1)
759 printk(KERN_WARNING "%s: in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n", dev->name, tp->nir, tp->cur_rx, tp->ttimer, rx);
760 if (tp->chip_id == LC82C168) {
761 iowrite32(0x00, ioaddr + CSR7);
762 mod_timer(&tp->timer, RUN_AT(HZ/50));
763 } else {
764 if (tp->ttimer == 0 || (ioread32(ioaddr + CSR11) & 0xffff) == 0) {
765 if (tulip_debug > 1)
766 printk(KERN_WARNING "%s: in rx suspend mode: (%lu) set timer\n", dev->name, tp->nir);
767 iowrite32(tulip_tbl[tp->chip_id].valid_intrs | TimerInt,
768 ioaddr + CSR7);
769 iowrite32(TimerInt, ioaddr + CSR5);
770 iowrite32(12, ioaddr + CSR11);
771 tp->ttimer = 1;
772 }
773 }
774 }
775#endif /* CONFIG_TULIP_NAPI */
776
777 if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) {
778 tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
779 }
780
781 if (tulip_debug > 4)
782 printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
783 dev->name, ioread32(ioaddr + CSR5));
784
785 return IRQ_HANDLED;
786}