[go: nahoru, domu]

11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
23396c7823efb3a5b8630388c464e1034ea031cedPaul Gortmaker	drivers/net/ethernet/dec/tulip/interrupt.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Copyright 2000,2001  The Linux Kernel Team
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Written/copyright 1994-2001 by Donald Becker.
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	This software may be used and distributed according to the terms
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	of the GNU General Public License, incorporated herein by reference.
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1078a655181409d9d0f2b730ccb897c18794826495Grant Grundler        Please submit bugs to http://bugzilla.kernel.org/ .
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "tulip.h"
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint tulip_rx_copybreak;
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int tulip_max_interrupt_work;
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MIT_SIZE 15
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MIT_TABLE 15 /* We use 0 or max */
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int mit_table[MIT_SIZE+1] =
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /*  CRS11 21143 hardware Mitigation Control Interrupt
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            We use only RX mitigation we other techniques for
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            TX intr. mitigation.
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds           31    Cycle Size (timer control)
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds           30:27 TX timer in 16 * Cycle size
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds           26:24 TX No pkts before Int.
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds           23:20 RX timer in Cycle size
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds           19:17 RX No pkts before Int.
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds           16       Continues Mode (CM)
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        */
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x0,             /* IM disabled */
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80150000,      /* RX time = 1, RX pkts = 2, CM = 1 */
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80150000,
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80270000,
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80370000,
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80490000,
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80590000,
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80690000,
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x807B0000,
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x808B0000,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x809D0000,
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80AD0000,
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80BD0000,
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80CF0000,
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80DF0000,
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//       0x80FF0000      /* RX time = 16, RX pkts = 7, CM = 1 */
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        0x80F10000      /* RX time = 16, RX pkts = 0, CM = 1 */
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint tulip_refill_rx(struct net_device *dev)
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tulip_private *tp = netdev_priv(dev);
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int entry;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int refilled = 0;
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Refill the Rx ring buffers. */
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		entry = tp->dirty_rx % RX_RING_SIZE;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tp->rx_buffers[entry].skb == NULL) {
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct sk_buff *skb;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dma_addr_t mapping;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7221a4e46995fa1a76281ac0281ff837f706231a37Pradeep A Dalvi			skb = tp->rx_buffers[entry].skb =
7321a4e46995fa1a76281ac0281ff837f706231a37Pradeep A Dalvi				netdev_alloc_skb(dev, PKT_BUF_SZ);
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (skb == NULL)
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
77689be43945e9ca7dd704522e55af1b8a73a994d3David S. Miller			mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ,
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						 PCI_DMA_FROMDEVICE);
79c9bfbb31af7c8428267b34eb9706a621ac219a28Neil Horman			if (dma_mapping_error(&tp->pdev->dev, mapping)) {
80c9bfbb31af7c8428267b34eb9706a621ac219a28Neil Horman				dev_kfree_skb(skb);
81c9bfbb31af7c8428267b34eb9706a621ac219a28Neil Horman				tp->rx_buffers[entry].skb = NULL;
82c9bfbb31af7c8428267b34eb9706a621ac219a28Neil Horman				break;
83c9bfbb31af7c8428267b34eb9706a621ac219a28Neil Horman			}
84c9bfbb31af7c8428267b34eb9706a621ac219a28Neil Horman
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->rx_buffers[entry].mapping = mapping;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			refilled++;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tp->rx_ring[entry].status = cpu_to_le32(DescOwned);
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(tp->chip_id == LC82C168) {
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(((ioread32(tp->base_addr + CSR5)>>17)&0x07) == 4) {
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Rx stopped due to out of buffers,
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * restart it
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iowrite32(0x01, tp->base_addr + CSR2);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return refilled;
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_TULIP_NAPI
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid oom_timer(unsigned long data)
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_device *dev = (struct net_device *)data;
108bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	struct tulip_private *tp = netdev_priv(dev);
109288379f050284087578b77e04f040b57db3db3f8Ben Hutchings	napi_schedule(&tp->napi);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
112bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerint tulip_poll(struct napi_struct *napi, int budget)
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
114bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	struct tulip_private *tp = container_of(napi, struct tulip_private, napi);
115bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	struct net_device *dev = tp->dev;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int entry = tp->cur_rx % RX_RING_SIZE;
117bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	int work_done = 0;
118bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int received = 0;
120bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger#endif
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* that one buffer is needed for mit activation; or might be a
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   bug in the ring buffer code; check later -- JHS*/
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
127bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger        if (budget >=RX_RING_SIZE) budget--;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tulip_debug > 4)
131726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches		netdev_dbg(dev, " In tulip_rx(), entry %d %08x\n",
132726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches			   entry, tp->rx_ring[entry].status);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       do {
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ioread32(tp->base_addr + CSR5) == 0xffffffff) {
136726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches			netdev_dbg(dev, " In tulip_poll(), hardware disappeared\n");
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               /* Acknowledge current RX interrupt sources. */
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               iowrite32((RxIntr | RxNoBuf), tp->base_addr + CSR5);
141f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
142f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               /* If we own the next entry, it is a new packet. Send it up. */
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                       s32 status = le32_to_cpu(tp->rx_ring[entry].status);
1461f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		       short pkt_len;
147f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                       if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx)
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               break;
150f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
151726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches		       if (tulip_debug > 5)
152726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches				netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n",
153726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches					   entry, status);
154c6a1b62de9d043f274ec3ae2e207908c6d5feff3Stephen Hemminger
155c6a1b62de9d043f274ec3ae2e207908c6d5feff3Stephen Hemminger		       if (++work_done >= budget)
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               goto not_done;
157f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
1581f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		       /*
1591f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			* Omit the four octet CRC from the length.
1601f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			* (May not be considered valid until we have
1611f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			* checked status for RxLengthOver2047 bits)
1621f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			*/
1631f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		       pkt_len = ((status >> 16) & 0x7ff) - 4;
1641f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech
1651f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		       /*
1661f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			* Maximum pkt_len is 1518 (1514 + vlan header)
1671f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			* Anything higher than this is always invalid
1681f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			* regardless of RxLengthOver2047 bits
1691f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			*/
1701f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech
1711f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		       if ((status & (RxLengthOver2047 |
1721f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech				      RxDescCRCError |
1731f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech				      RxDescCollisionSeen |
1741f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech				      RxDescRunt |
1751f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech				      RxDescDescErr |
1768e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches				      RxWholePkt)) != RxWholePkt ||
1778e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches			   pkt_len > 1518) {
1781f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			       if ((status & (RxLengthOver2047 |
1791f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech					      RxWholePkt)) != RxWholePkt) {
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                /* Ingore earlier buffers. */
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       if ((status & 0xffff) != 0x7fff) {
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                               if (tulip_debug > 1)
183abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches                                                       dev_warn(&dev->dev,
184abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches								"Oversized Ethernet frame spanned multiple buffers, status %08x!\n",
185abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches								status);
1861a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet						dev->stats.rx_length_errors++;
1871a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					}
1881f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			       } else {
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                /* There was a fatal error. */
190726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches				       if (tulip_debug > 2)
191726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches						netdev_dbg(dev, "Receive error, Rx status %08x\n",
192726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches							   status);
1931a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					dev->stats.rx_errors++; /* end of a packet.*/
1941a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					if (pkt_len > 1518 ||
1951a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					    (status & RxDescRunt))
1961a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet						dev->stats.rx_length_errors++;
1971a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet
1981a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					if (status & 0x0004)
1991a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet						dev->stats.rx_frame_errors++;
2001a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					if (status & 0x0002)
2011a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet						dev->stats.rx_crc_errors++;
2021a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					if (status & 0x0001)
2031a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet						dev->stats.rx_fifo_errors++;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               }
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                       } else {
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               struct sk_buff *skb;
207f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               /* Check if the packet is long enough to accept without copying
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                  to a minimally-sized skbuff. */
2108e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches                               if (pkt_len < tulip_rx_copybreak &&
21121a4e46995fa1a76281ac0281ff837f706231a37Pradeep A Dalvi                                   (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       skb_reserve(skb, 2);    /* 16 byte align the IP header */
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       pci_dma_sync_single_for_cpu(tp->pdev,
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								   tp->rx_buffers[entry].mapping,
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								   pkt_len, PCI_DMA_FROMDEVICE);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if ! defined(__alpha__)
2178c7b7faaa630fef7f68d8728cee1cce398cc9697David S. Miller                                       skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
2188c7b7faaa630fef7f68d8728cee1cce398cc9697David S. Miller                                                        pkt_len);
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       skb_put(skb, pkt_len);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       memcpy(skb_put(skb, pkt_len),
222689be43945e9ca7dd704522e55af1b8a73a994d3David S. Miller                                              tp->rx_buffers[entry].skb->data,
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                              pkt_len);
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       pci_dma_sync_single_for_device(tp->pdev,
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								      tp->rx_buffers[entry].mapping,
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								      pkt_len, PCI_DMA_FROMDEVICE);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               } else {        /* Pass up the skb already on the Rx ring. */
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       char *temp = skb_put(skb = tp->rx_buffers[entry].skb,
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                            pkt_len);
231f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef final_version
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       if (tp->rx_buffers[entry].mapping !=
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                           le32_to_cpu(tp->rx_ring[entry].buffer1)) {
235abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches                                               dev_err(&dev->dev,
236abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						       "Internal fault: The skbuff addresses do not match in tulip_rx: %08x vs. %08llx %p / %p\n",
237abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						       le32_to_cpu(tp->rx_ring[entry].buffer1),
238abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						       (unsigned long long)tp->rx_buffers[entry].mapping,
239abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						       skb->head, temp);
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       }
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
242f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
245f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       tp->rx_buffers[entry].skb = NULL;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                       tp->rx_buffers[entry].mapping = 0;
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               }
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               skb->protocol = eth_type_trans(skb, dev);
250f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               netif_receive_skb(skb);
252f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2531a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet				dev->stats.rx_packets++;
2541a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet				dev->stats.rx_bytes += pkt_len;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                       }
256bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
257bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger		       received++;
258bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger#endif
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                       entry = (++tp->cur_rx) % RX_RING_SIZE;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                       if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4)
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               tulip_refill_rx(dev);
263f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
265f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               /* New ack strategy... irq does not ack Rx any longer
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  hopefully this helps */
268f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               /* Really bad things can happen here... If new packet arrives
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                * and an irq arrives (tx or just due to occasionally unset
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                * mask), it will be acked by irq handler, but new thread
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                * is not scheduled. It is major hole in design.
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                * No idea how to fix this if "playing with fire" will fail
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                * tomorrow (night 011029). If it will not fail, we won
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                * finally: amount of IO did not increase at all. */
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       } while ((ioread32(tp->base_addr + CSR5) & RxIntr));
277f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
279f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /* We use this simplistic scheme for IM. It's proven by
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds             real life installations. We can have IM enabled
282f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik            continuesly but this would cause unnecessary latency.
283f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik            Unfortunely we can't use all the NET_RX_* feedback here.
284f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik            This would turn on IM for devices that is not contributing
285f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik            to backlog congestion with unnecessary latency.
286f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
28759c51591a0ac7568824f541f57de967e88adaa07Michael Opdenacker             We monitor the device RX-ring and have:
288f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds             HW Interrupt Mitigation either ON or OFF.
290f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
291f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik            ON:  More then 1 pkt received (per intr.) OR we are dropping
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds             OFF: Only 1 pkt received
293f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds             Note. We only use min and max (0, 15) settings from mit_table */
295f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
296f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          if( tp->flags &  HAS_INTR_MITIGATION) {
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 if( received > 1 ) {
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         if( ! tp->mit_on ) {
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                 tp->mit_on = 1;
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                 iowrite32(mit_table[MIT_TABLE], tp->base_addr + CSR11);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         }
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  }
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 else {
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         if( tp->mit_on ) {
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                 tp->mit_on = 0;
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                 iowrite32(0, tp->base_addr + CSR11);
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         }
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  }
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          }
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */
313f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         tulip_refill_rx(dev);
315f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         /* If RX ring is not full we are out of memory. */
317bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger         if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
318bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger		 goto oom;
319f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         /* Remove us from polling list and enable RX intr. */
321f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
322288379f050284087578b77e04f040b57db3db3f8Ben Hutchings         napi_complete(napi);
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7);
324f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         /* The last op happens after poll completion. Which means the following:
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          * 1. it can race with disabling irqs in irq handler
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          * 2. it can race with dise/enabling irqs in other poll threads
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          * 3. if an irq raised after beginning loop, it will be immediately
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          *    triggered here.
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          *
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          * Summarizing: the logic results in some redundant irqs both
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          * due to races in masking and due to too late acking of already
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          * processed irqs. But it must not result in losing events.
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          */
335f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
336bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger         return work_done;
337f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds not_done:
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 ||
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds             tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 tulip_refill_rx(dev);
342f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
343bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger         if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
344bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger		 goto oom;
345f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
346bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger         return work_done;
347f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oom:    /* Executed with RX ints disabled */
349f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         /* Start timer, stop polling, but do not enable rx interrupts. */
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         mod_timer(&tp->oom_timer, jiffies+1);
352f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         /* Think: timer_pending() was an explicit signature of bug.
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          * Timer can be pending now but fired and completed
355288379f050284087578b77e04f040b57db3db3f8Ben Hutchings          * before we did napi_complete(). See? We would lose it. */
356f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         /* remove ourselves from the polling list */
358288379f050284087578b77e04f040b57db3db3f8Ben Hutchings         napi_complete(napi);
359f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
360bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger         return work_done;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* CONFIG_TULIP_NAPI */
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tulip_rx(struct net_device *dev)
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tulip_private *tp = netdev_priv(dev);
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int entry = tp->cur_rx % RX_RING_SIZE;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int received = 0;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tulip_debug > 4)
373726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches		netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n",
374726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches			   entry, tp->rx_ring[entry].status);
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If we own the next entry, it is a new packet. Send it up. */
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s32 status = le32_to_cpu(tp->rx_ring[entry].status);
3781f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		short pkt_len;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tulip_debug > 5)
381726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches			netdev_dbg(dev, "In tulip_rx(), entry %d %08x\n",
382726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches				   entry, status);
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (--rx_work_limit < 0)
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3851f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech
3861f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		/*
3871f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		  Omit the four octet CRC from the length.
3881f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		  (May not be considered valid until we have
3891f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		  checked status for RxLengthOver2047 bits)
3901f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		*/
3911f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		pkt_len = ((status >> 16) & 0x7ff) - 4;
3921f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		/*
3931f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		  Maximum pkt_len is 1518 (1514 + vlan header)
3941f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		  Anything higher than this is always invalid
3951f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		  regardless of RxLengthOver2047 bits
3961f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		*/
3971f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech
3981f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech		if ((status & (RxLengthOver2047 |
3991f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			       RxDescCRCError |
4001f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			       RxDescCollisionSeen |
4011f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			       RxDescRunt |
4021f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			       RxDescDescErr |
4038e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches			       RxWholePkt))        != RxWholePkt ||
4048e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches		    pkt_len > 1518) {
4051f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			if ((status & (RxLengthOver2047 |
4061f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			     RxWholePkt))         != RxWholePkt) {
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Ingore earlier buffers. */
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((status & 0xffff) != 0x7fff) {
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (tulip_debug > 1)
410726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches						netdev_warn(dev,
411726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches							    "Oversized Ethernet frame spanned multiple buffers, status %08x!\n",
412726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches							    status);
4131a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					dev->stats.rx_length_errors++;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
4151f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech			} else {
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* There was a fatal error. */
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (tulip_debug > 2)
418726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches					netdev_dbg(dev, "Receive error, Rx status %08x\n",
419726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches						   status);
4201a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet				dev->stats.rx_errors++; /* end of a packet.*/
4211f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech				if (pkt_len > 1518 ||
4221f8ae0a21d83f43006d7f6d2862e921dbf2eedddTomasz Lemiech				    (status & RxDescRunt))
4231a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					dev->stats.rx_length_errors++;
4241a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet				if (status & 0x0004)
4251a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					dev->stats.rx_frame_errors++;
4261a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet				if (status & 0x0002)
4271a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					dev->stats.rx_crc_errors++;
4281a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet				if (status & 0x0001)
4291a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					dev->stats.rx_fifo_errors++;
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct sk_buff *skb;
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Check if the packet is long enough to accept without copying
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   to a minimally-sized skbuff. */
4368e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches			if (pkt_len < tulip_rx_copybreak &&
43721a4e46995fa1a76281ac0281ff837f706231a37Pradeep A Dalvi			    (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				skb_reserve(skb, 2);	/* 16 byte align the IP header */
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_dma_sync_single_for_cpu(tp->pdev,
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							    tp->rx_buffers[entry].mapping,
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							    pkt_len, PCI_DMA_FROMDEVICE);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if ! defined(__alpha__)
4438c7b7faaa630fef7f68d8728cee1cce398cc9697David S. Miller				skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
4448c7b7faaa630fef7f68d8728cee1cce398cc9697David S. Miller						 pkt_len);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				skb_put(skb, pkt_len);
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memcpy(skb_put(skb, pkt_len),
448689be43945e9ca7dd704522e55af1b8a73a994d3David S. Miller				       tp->rx_buffers[entry].skb->data,
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       pkt_len);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_dma_sync_single_for_device(tp->pdev,
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							       tp->rx_buffers[entry].mapping,
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							       pkt_len, PCI_DMA_FROMDEVICE);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else { 	/* Pass up the skb already on the Rx ring. */
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				char *temp = skb_put(skb = tp->rx_buffers[entry].skb,
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						     pkt_len);
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef final_version
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (tp->rx_buffers[entry].mapping !=
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    le32_to_cpu(tp->rx_ring[entry].buffer1)) {
461abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches					dev_err(&dev->dev,
462abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						"Internal fault: The skbuff addresses do not match in tulip_rx: %08x vs. %Lx %p / %p\n",
463abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						le32_to_cpu(tp->rx_ring[entry].buffer1),
464abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						(long long)tp->rx_buffers[entry].mapping,
465abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						skb->head, temp);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						 PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tp->rx_buffers[entry].skb = NULL;
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tp->rx_buffers[entry].mapping = 0;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb->protocol = eth_type_trans(skb, dev);
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			netif_rx(skb);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4791a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet			dev->stats.rx_packets++;
4801a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet			dev->stats.rx_bytes += pkt_len;
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		received++;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		entry = (++tp->cur_rx) % RX_RING_SIZE;
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return received;
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif  /* CONFIG_TULIP_NAPI */
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline unsigned int phy_interrupt (struct net_device *dev)
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __hppa__
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tulip_private *tp = netdev_priv(dev);
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int csr12 = ioread32(tp->base_addr + CSR12) & 0xff;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (csr12 != tp->csr12_shadow) {
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* ack interrupt */
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iowrite32(csr12 | 0x02, tp->base_addr + CSR12);
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tp->csr12_shadow = csr12;
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* do link change stuff */
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock(&tp->lock);
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tulip_check_duplex(dev);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock(&tp->lock);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* clear irq ack bit */
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iowrite32(csr12 & ~0x02, tp->base_addr + CSR12);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The interrupt handler does all of the Rx thread work and cleans up
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   after the Tx thread. */
5157d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsirqreturn_t tulip_interrupt(int irq, void *dev_instance)
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *dev = (struct net_device *)dev_instance;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tulip_private *tp = netdev_priv(dev);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ioaddr = tp->base_addr;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int csr5;
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int missed;
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rx = 0;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int tx = 0;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int oi = 0;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int maxrx = RX_RING_SIZE;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int maxtx = TX_RING_SIZE;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int maxoi = TX_RING_SIZE;
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_TULIP_NAPI
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rxd = 0;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int entry;
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int work_count = tulip_max_interrupt_work;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int handled = 0;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Let's see whether the interrupt really is for us */
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	csr5 = ioread32(ioaddr + CSR5);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
539f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik        if (tp->flags & HAS_PHY_IRQ)
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	        handled = phy_interrupt (dev);
541f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return IRQ_RETVAL(handled);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->nir++;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_TULIP_NAPI
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!rxd && (csr5 & (RxIntr | RxNoBuf))) {
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rxd++;
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Mask RX intrs and add the device to poll list. */
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7);
555288379f050284087578b77e04f040b57db3db3f8Ben Hutchings			napi_schedule(&tp->napi);
556f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass)))
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                               break;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
560f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               /* Acknowledge the interrupt sources we handle here ASAP
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  the poll function does Rx and RxNoBuf acking */
563f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
566f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik#else
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Acknowledge all of the current interrupt sources ASAP. */
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iowrite32(csr5 & 0x0001ffff, ioaddr + CSR5);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (csr5 & (RxIntr | RxNoBuf)) {
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rx += tulip_rx(dev);
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tulip_refill_rx(dev);
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /*  CONFIG_TULIP_NAPI */
577f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tulip_debug > 4)
579726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches			netdev_dbg(dev, "interrupt  csr5=%#8.8x new csr5=%#8.8x\n",
580726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches				   csr5, ioread32(ioaddr + CSR5));
581f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) {
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned int dirty_tx;
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_lock(&tp->lock);
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 dirty_tx++) {
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				int entry = dirty_tx % TX_RING_SIZE;
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				int status = le32_to_cpu(tp->tx_ring[entry].status);
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (status < 0)
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;			/* It still has not been Txed */
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Check for Rx filter setup frames. */
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (tp->tx_buffers[entry].skb == NULL) {
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					/* test because dummy frames not mapped */
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (tp->tx_buffers[entry].mapping)
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						pci_unmap_single(tp->pdev,
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							 tp->tx_buffers[entry].mapping,
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							 sizeof(tp->setup_frame),
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							 PCI_DMA_TODEVICE);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					continue;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (status & 0x8000) {
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					/* There was an major error, log it. */
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef final_version
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (tulip_debug > 1)
611726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches						netdev_dbg(dev, "Transmit error, Tx status %08x\n",
612726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches							   status);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6141a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					dev->stats.tx_errors++;
6151a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					if (status & 0x4104)
6161a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet						dev->stats.tx_aborted_errors++;
6171a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					if (status & 0x0C00)
6181a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet						dev->stats.tx_carrier_errors++;
6191a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					if (status & 0x0200)
6201a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet						dev->stats.tx_window_errors++;
6211a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					if (status & 0x0002)
6221a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet						dev->stats.tx_fifo_errors++;
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if ((status & 0x0080) && tp->full_duplex == 0)
6241a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet						dev->stats.tx_heartbeat_errors++;
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
6261a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					dev->stats.tx_bytes +=
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						tp->tx_buffers[entry].skb->len;
6281a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					dev->stats.collisions += (status >> 3) & 15;
6291a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet					dev->stats.tx_packets++;
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping,
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						 tp->tx_buffers[entry].skb->len,
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						 PCI_DMA_TODEVICE);
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Free the original skb. */
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dev_kfree_skb_irq(tp->tx_buffers[entry].skb);
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tp->tx_buffers[entry].skb = NULL;
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tp->tx_buffers[entry].mapping = 0;
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tx++;
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef final_version
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tp->cur_tx - dirty_tx > TX_RING_SIZE) {
645abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches				dev_err(&dev->dev,
646abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches					"Out-of-sync dirty pointer, %d vs. %d\n",
647abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches					dirty_tx, tp->cur_tx);
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dirty_tx += TX_RING_SIZE;
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2)
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				netif_wake_queue(dev);
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->dirty_tx = dirty_tx;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (csr5 & TxDied) {
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (tulip_debug > 2)
658abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches					dev_warn(&dev->dev,
659abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						 "The transmitter stopped.  CSR5 is %x, CSR6 %x, new CSR6 %x\n",
660abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						 csr5, ioread32(ioaddr + CSR6),
661abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						 tp->csr6);
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tulip_restart_rxtx(tp);
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock(&tp->lock);
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Log errors. */
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (csr5 & AbnormalIntr) {	/* Abnormal error summary bit. */
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (csr5 == 0xffffffff)
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
6711a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet			if (csr5 & TxJabber)
6721a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet				dev->stats.tx_errors++;
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (csr5 & TxFIFOUnderflow) {
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((tp->csr6 & 0xC000) != 0xC000)
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					tp->csr6 += 0x4000;	/* Bump up the Tx threshold */
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					tp->csr6 |= 0x00200000;  /* Store-n-forward. */
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Restart the transmit process. */
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tulip_restart_rxtx(tp);
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iowrite32(0, ioaddr + CSR1);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (csr5 & (RxDied | RxNoBuf)) {
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (tp->flags & COMET_MAC_ADDR) {
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					iowrite32(tp->mc_filter[0], ioaddr + 0xAC);
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					iowrite32(tp->mc_filter[1], ioaddr + 0xB0);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (csr5 & RxDied) {		/* Missed a Rx frame. */
6891a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet				dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
6901a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet				dev->stats.rx_errors++;
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tulip_start_rxtx(tp);
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * call is ever done under the spinlock
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) {
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (tp->link_change)
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(tp->link_change)(dev, csr5);
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7011ddb98618d5b797cb5300f093c1df1f38f79d9baValerie Henson			if (csr5 & SystemError) {
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				int error = (csr5 >> 23) & 7;
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* oops, we hit a PCI error.  The code produced corresponds
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * to the reason:
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 *  0 - parity error
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 *  1 - master abort
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 *  2 - target abort
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * Note that on parity error, we should do a software reset
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * of the chip to get it back into a sane state (according
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * to the 21142/3 docs that is).
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 *   -- rmk
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
713abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches				dev_err(&dev->dev,
714abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches					"(%lu) System Error occurred (%d)\n",
715abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches					tp->nir, error);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Clear all error sources, included undocumented ones! */
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iowrite32(0x0800f7ba, ioaddr + CSR5);
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			oi++;
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (csr5 & TimerInt) {
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tulip_debug > 2)
724abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches				dev_err(&dev->dev,
725abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches					"Re-enabling interrupts, %08x\n",
726abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches					csr5);
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->ttimer = 0;
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			oi++;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tx > maxtx || rx > maxrx || oi > maxoi) {
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tulip_debug > 1)
733abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches				dev_warn(&dev->dev, "Too much work during an interrupt, csr5=0x%08x. (%lu) (%d,%d,%d)\n",
734abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches					 csr5, tp->nir, tx, rx, oi);
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                       /* Acknowledge all interrupt sources. */
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        iowrite32(0x8001ffff, ioaddr + CSR5);
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if (tp->flags & HAS_INTR_MITIGATION) {
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                     /* Josip Loncaric at ICASE did extensive experimentation
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			to develop a good interrupt mitigation setting.*/
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                iowrite32(0x8b240000, ioaddr + CSR11);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        } else if (tp->chip_id == LC82C168) {
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* the LC82C168 doesn't have a hw timer.*/
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iowrite32(0x00, ioaddr + CSR7);
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mod_timer(&tp->timer, RUN_AT(HZ/50));
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                          /* Mask all interrupting sources, set timer to
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				re-enable. */
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                iowrite32(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7);
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                iowrite32(0x0012, ioaddr + CSR11);
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		work_count--;
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (work_count == 0)
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		csr5 = ioread32(ioaddr + CSR5);
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_TULIP_NAPI
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rxd)
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			csr5 &= ~RxPollInt;
764f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik	} while ((csr5 & (TxNoBuf |
765f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik			  TxDied |
766f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik			  TxIntr |
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  TimerInt |
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  /* Abnormal intr. */
769f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik			  RxDied |
770f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik			  TxFIFOUnderflow |
771f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik			  TxJabber |
772f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik			  TPLnkFail |
7731ddb98618d5b797cb5300f093c1df1f38f79d9baValerie Henson			  SystemError )) != 0);
774f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik#else
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while ((csr5 & (NormalIntr|AbnormalIntr)) != 0);
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tulip_refill_rx(dev);
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the card is in suspend mode */
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	entry = tp->dirty_rx % RX_RING_SIZE;
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tp->rx_buffers[entry].skb == NULL) {
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tulip_debug > 1)
783abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches			dev_warn(&dev->dev,
784abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches				 "in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n",
785abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches				 tp->nir, tp->cur_rx, tp->ttimer, rx);
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tp->chip_id == LC82C168) {
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iowrite32(0x00, ioaddr + CSR7);
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mod_timer(&tp->timer, RUN_AT(HZ/50));
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tp->ttimer == 0 || (ioread32(ioaddr + CSR11) & 0xffff) == 0) {
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (tulip_debug > 1)
792abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches					dev_warn(&dev->dev,
793abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						 "in rx suspend mode: (%lu) set timer\n",
794abe02af8263ae17e201994a1be7fc5eac6642acfJoe Perches						 tp->nir);
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iowrite32(tulip_tbl[tp->chip_id].valid_intrs | TimerInt,
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ioaddr + CSR7);
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iowrite32(TimerInt, ioaddr + CSR5);
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iowrite32(12, ioaddr + CSR11);
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tp->ttimer = 1;
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_TULIP_NAPI */
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) {
8061a18abaa87c4c68a13c2ffcace39a078605b980aEric Dumazet		dev->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tulip_debug > 4)
810726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches		netdev_dbg(dev, "exiting interrupt, csr5=%#04x\n",
811726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches			   ioread32(ioaddr + CSR5));
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_HANDLED;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
815