aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sis190.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sis190.c')
-rw-r--r--drivers/net/sis190.c102
1 files changed, 74 insertions, 28 deletions
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 2229698debbd..3c33b2d14852 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -64,8 +64,8 @@
64 64
65#define MAC_ADDR_LEN 6 65#define MAC_ADDR_LEN 6
66 66
67#define NUM_TX_DESC 64 67#define NUM_TX_DESC 64 /* [8..1024] */
68#define NUM_RX_DESC 64 68#define NUM_RX_DESC 64 /* [8..8192] */
69#define TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) 69#define TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
70#define RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) 70#define RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
71#define RX_BUF_SIZE 1536 71#define RX_BUF_SIZE 1536
@@ -149,12 +149,6 @@ enum sis190_register_content {
149 RxHalt = 0x00000002, 149 RxHalt = 0x00000002,
150 TxHalt = 0x00000001, 150 TxHalt = 0x00000001,
151 151
152 /* RxStatusDesc */
153 RxRES = 0x00200000, // unused
154 RxCRC = 0x00080000,
155 RxRUNT = 0x00100000, // unused
156 RxRWT = 0x00400000, // unused
157
158 /* {Rx/Tx}CmdBits */ 152 /* {Rx/Tx}CmdBits */
159 CmdReset = 0x10, 153 CmdReset = 0x10,
160 CmdRxEnb = 0x08, // unused 154 CmdRxEnb = 0x08, // unused
@@ -212,15 +206,55 @@ struct RxDesc {
212 206
213enum _DescStatusBit { 207enum _DescStatusBit {
214 /* _Desc.status */ 208 /* _Desc.status */
215 OWNbit = 0x80000000, 209 OWNbit = 0x80000000, // RXOWN/TXOWN
216 INTbit = 0x40000000, 210 INTbit = 0x40000000, // RXINT/TXINT
217 DEFbit = 0x00200000, 211 CRCbit = 0x00020000, // CRCOFF/CRCEN
218 CRCbit = 0x00020000, 212 PADbit = 0x00010000, // PREADD/PADEN
219 PADbit = 0x00010000,
220 /* _Desc.size */ 213 /* _Desc.size */
221 RingEnd = (1 << 31), 214 RingEnd = 0x80000000,
222 /* _Desc.PSize */ 215 /* TxDesc.status */
216 LSEN = 0x08000000, // TSO ? -- FR
217 IPCS = 0x04000000,
218 TCPCS = 0x02000000,
219 UDPCS = 0x01000000,
220 BSTEN = 0x00800000,
221 EXTEN = 0x00400000,
222 DEFEN = 0x00200000,
223 BKFEN = 0x00100000,
224 CRSEN = 0x00080000,
225 COLEN = 0x00040000,
226 THOL3 = 0x30000000,
227 THOL2 = 0x20000000,
228 THOL1 = 0x10000000,
229 THOL0 = 0x00000000,
230 /* RxDesc.status */
231 IPON = 0x20000000,
232 TCPON = 0x10000000,
233 UDPON = 0x08000000,
234 Wakup = 0x00400000,
235 Magic = 0x00200000,
236 Pause = 0x00100000,
237 DEFbit = 0x00200000,
238 BCAST = 0x000c0000,
239 MCAST = 0x00080000,
240 UCAST = 0x00040000,
241 /* RxDesc.PSize */
242 TAGON = 0x80000000,
243 RxDescCountMask = 0x7f000000, // multi-desc pkt when > 1 ? -- FR
244 ABORT = 0x00800000,
245 SHORT = 0x00400000,
246 LIMIT = 0x00200000,
247 MIIER = 0x00100000,
248 OVRUN = 0x00080000,
249 NIBON = 0x00040000,
250 COLON = 0x00020000,
251 CRCOK = 0x00010000,
223 RxSizeMask = 0x0000ffff 252 RxSizeMask = 0x0000ffff
253 /*
254 * The asic could apparently do vlan, TSO, jumbo (sis191 only) and
255 * provide two (unused with Linux) Tx queues. No publically
256 * available documentation alas.
257 */
224}; 258};
225 259
226enum sis190_eeprom_access_register_bits { 260enum sis190_eeprom_access_register_bits {
@@ -487,6 +521,26 @@ static inline int sis190_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
487 return ret; 521 return ret;
488} 522}
489 523
524static inline int sis190_rx_pkt_err(u32 status, struct net_device_stats *stats)
525{
526#define ErrMask (OVRUN | SHORT | LIMIT | MIIER | NIBON | COLON | ABORT)
527
528 if ((status & CRCOK) && !(status & ErrMask))
529 return 0;
530
531 if (!(status & CRCOK))
532 stats->rx_crc_errors++;
533 else if (status & OVRUN)
534 stats->rx_over_errors++;
535 else if (status & (SHORT | LIMIT))
536 stats->rx_length_errors++;
537 else if (status & (MIIER | NIBON | COLON))
538 stats->rx_frame_errors++;
539
540 stats->rx_errors++;
541 return -1;
542}
543
490static int sis190_rx_interrupt(struct net_device *dev, 544static int sis190_rx_interrupt(struct net_device *dev,
491 struct sis190_private *tp, void __iomem *ioaddr) 545 struct sis190_private *tp, void __iomem *ioaddr)
492{ 546{
@@ -510,19 +564,9 @@ static int sis190_rx_interrupt(struct net_device *dev,
510 // net_intr(tp, KERN_INFO "%s: Rx PSize = %08x.\n", dev->name, 564 // net_intr(tp, KERN_INFO "%s: Rx PSize = %08x.\n", dev->name,
511 // status); 565 // status);
512 566
513 if (status & RxCRC) { 567 if (sis190_rx_pkt_err(status, stats) < 0)
514 net_intr(tp, KERN_INFO "%s: bad crc. status = %08x.\n",
515 dev->name, status);
516 stats->rx_errors++;
517 stats->rx_crc_errors++;
518 sis190_give_to_asic(desc, tp->rx_buf_sz); 568 sis190_give_to_asic(desc, tp->rx_buf_sz);
519 } else if (!(status & PADbit)) { 569 else {
520 net_intr(tp, KERN_INFO "%s: bad pad. status = %08x.\n",
521 dev->name, status);
522 stats->rx_errors++;
523 stats->rx_length_errors++;
524 sis190_give_to_asic(desc, tp->rx_buf_sz);
525 } else {
526 struct sk_buff *skb = tp->Rx_skbuff[entry]; 570 struct sk_buff *skb = tp->Rx_skbuff[entry];
527 int pkt_size = (status & RxSizeMask) - 4; 571 int pkt_size = (status & RxSizeMask) - 4;
528 void (*pci_action)(struct pci_dev *, dma_addr_t, 572 void (*pci_action)(struct pci_dev *, dma_addr_t,
@@ -559,8 +603,10 @@ static int sis190_rx_interrupt(struct net_device *dev,
559 sis190_rx_skb(skb); 603 sis190_rx_skb(skb);
560 604
561 dev->last_rx = jiffies; 605 dev->last_rx = jiffies;
562 stats->rx_bytes += pkt_size;
563 stats->rx_packets++; 606 stats->rx_packets++;
607 stats->rx_bytes += pkt_size;
608 if ((status & BCAST) == MCAST)
609 stats->multicast++;
564 } 610 }
565 } 611 }
566 count = cur_rx - tp->cur_rx; 612 count = cur_rx - tp->cur_rx;