diff options
| -rw-r--r-- | drivers/net/sis190.c | 102 |
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 | ||
| 213 | enum _DescStatusBit { | 207 | enum _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 | ||
| 226 | enum sis190_eeprom_access_register_bits { | 260 | enum 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 | ||
| 524 | static 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 | |||
| 490 | static int sis190_rx_interrupt(struct net_device *dev, | 544 | static 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; |
