]> git.hungrycats.org Git - linux/commitdiff
Fix several bugs in DL2K Gigabit Ethernet driver, updating to
authorJeff Garzik <jgarzik@rum.normnet.org>
Wed, 6 Feb 2002 22:57:38 +0000 (17:57 -0500)
committerJeff Garzik <jgarzik@rum.normnet.org>
Wed, 6 Feb 2002 22:57:38 +0000 (17:57 -0500)
vendor revision 1.08.
Contributed by the vendor, D-Link.

Documentation/networking/dl2k.txt
drivers/net/dl2k.c
drivers/net/dl2k.h

index a3ca9ff673791700fe99d86a7afa053752a89594..04b18033bebcf94a1443af7e0626d659799efcd7 100644 (file)
@@ -1,7 +1,7 @@
 
     D-Link DL2000-based Gigabit Ethernet Adapter Installation
     for Linux
-    Nov 12, 2001
+    Jan 02, 2002
 
 Contents
 ========
@@ -182,7 +182,7 @@ driver.
 mtu=packet_size                        - Specifies the maximum packet size. default
                                  is 1500.
 
-media=xxxxxxxxx                        - Specifies the media type the NIC operates at.
+media=media_type               - Specifies the media type the NIC operates at.
                                  autosense     Autosensing active media.
                                  10mbps_hd     10Mbps half duplex.
                                  10mbps_fd     10Mbps full duplex.
@@ -195,28 +195,41 @@ media=xxxxxxxxx                   - Specifies the media type the NIC operates at.
                                  2             10Mbps full duplex.
                                  3             100Mbps half duplex.
                                  4             100Mbps full duplex.
-                                 5             1000Mbps full duplex.
-                                 6             1000Mbps half duplex.
+                                 5             1000Mbps half duplex.
+                                 6             1000Mbps full duplex.
 
                                  By default, the NIC operates at autosense.
                                  Note that only 1000mbps_fd and 1000mbps_hd
                                  types are available for fiber adapter.
 
-vlan=x                         - Specifies the VLAN ID. If vlan=0, the
+vlan=[0|1]                     - Specifies the VLAN ID. If vlan=0, the
                                  Virtual Local Area Network (VLAN) function is
                                  disable.
 
-jumbo=x                                - Specifies the jumbo frame support. If jumbo=1,
+jumbo=[0|1]                    - Specifies the jumbo frame support. If jumbo=1,
                                  the NIC accept jumbo frames. By default, this
                                  function is disabled.
                                  Jumbo frame usually improve the performance
                                  int gigabit.
                                  
-int_count                      - Rx frame count each interrupt.
-int_timeout                    - Rx DMA wait time for an interrupt. Proper 
-                                 values of int_count and int_timeout bring 
-                                 a conspicuous performance in the fast machine. 
-                                 Ex. int_count=5 and int_timeout=750 
+rx_coalesce=n                  - Rx frame count each interrupt.
+rx_timeout=n                   - Rx DMA wait time for an interrupt. Proper 
+                                 values of rx_coalesce and rx_timeout bring 
+                                 a conspicuous performance in the fast machine.
+                                 Ex. rx_coalesce=5 and rx_timeout=750 
+
+tx_coalesce=n                  - Tx transmit count each TxComp interrupt.
+                                 Setting value larger than 1 will improve 
+                                 performance, but this is possible to lower 
+                                 stability in slow UP machines. By default, 
+                                 tx_coalesce=1. (dl2k)
+                                 
+tx_flow=[1|0]                  - Specifies the Tx flow control. If tx_flow=1, 
+                                 the Tx flow control enable.
+                                 
+rx_flow=[1|0]                  - Specifies the Rx flow control. If rx_flow=1, 
+                                 the Rx flow control enable.
+
 
 Configuration Script Sample
 ===========================
index 707adf273215b6995049dad8faba34453e2f8811..efdffd67667ed3c30c5927e8200d3ae4d10d974c 100644 (file)
     0.01       2001/05/03      Created DL2000-based linux driver
     0.02       2001/05/21      Added VLAN and hardware checksum support.
     1.00       2001/06/26      Added jumbo frame support.
-    1.01       2001/08/21      Added two parameters, int_count and int_timeout.
+    1.01       2001/08/21      Added two parameters, rx_coalesce and rx_timeout.
     1.02       2001/10/08      Supported fiber media.
                                Added flow control parameters.
-    1.03       2001/10/12      Changed the default media to 1000mbps_fd for the 
-                               fiber devices.
-    1.04       2001/11/08      Fixed a bug which Tx stop when a very busy case.
-*/
+    1.03       2001/10/12      Changed the default media to 1000mbps_fd for 
+                               the fiber devices.
+    1.04       2001/11/08      Fixed Tx stopped when tx very busy.
+    1.05       2001/11/22      Fixed Tx stopped when unidirectional tx busy.
+    1.06       2001/12/13      Fixed disconnect bug at 10Mbps mode.
+                               Fixed tx_full flag incorrect.
+                               Added tx_coalesce paramter.
+    1.07       2002/01/03      Fixed miscount of RX frame error.
+    1.08       2002/01/17      Fixed the multicast bug.
+ */
 
 #include "dl2k.h"
 
 static char version[] __devinitdata =
-    KERN_INFO "D-Link DL2000-based linux driver v1.04 2001/11/08\n";
+    KERN_INFO "D-Link DL2000-based linux driver v1.08 2002/01/17\n";
 
 #define MAX_UNITS 8
 static int mtu[MAX_UNITS];
@@ -36,11 +42,13 @@ static char *media[MAX_UNITS];
 static int tx_flow[MAX_UNITS];
 static int rx_flow[MAX_UNITS];
 static int copy_thresh;
-static int int_count;          /* Rx frame count each interrupt */
-static int int_timeout;                /* Rx DMA wait time in 64ns increments */
+static int rx_coalesce = DEFAULT_RXC;
+static int rx_timeout = DEFAULT_RXT;   
+static int tx_coalesce = DEFAULT_TXC;  
 
 MODULE_AUTHOR ("Edward Peng");
 MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter");
+MODULE_LICENSE("GPL");
 MODULE_PARM (mtu, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (media, "1-" __MODULE_STRING (MAX_UNITS) "s");
 MODULE_PARM (vlan, "1-" __MODULE_STRING (MAX_UNITS) "i");
@@ -48,13 +56,16 @@ MODULE_PARM (jumbo, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (tx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (rx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (copy_thresh, "i");
-MODULE_PARM (int_count, "i");
-MODULE_PARM (int_timeout, "i");
+MODULE_PARM (rx_coalesce, "i");        /* Rx frame count each interrupt */
+MODULE_PARM (rx_timeout, "i"); /* Rx DMA wait time in 64ns increments */
+MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxComplete [1-8] */
+
 
 /* Enable the default interrupts */
+#define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxComplete| \
+       UpdateStats | LinkEvent)
 #define EnableInt() \
-writew(RxDMAComplete | HostError | IntRequested | TxComplete| \
-       UpdateStats | LinkEvent, ioaddr + IntEnable)
+writew(DEFAULT_INTR, ioaddr + IntEnable)
 
 static int max_intrloop = 50;
 static int multicast_filter_limit = 0x40;
@@ -162,11 +173,11 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
                                np->speed = 10;
                                np->full_duplex = 0;
                        } else if (strcmp (media[card_idx], "1000mbps_fd") == 0 ||
-                                strcmp (media[card_idx], "5") == 0) {
+                                strcmp (media[card_idx], "6") == 0) {
                                np->speed=1000;
                                np->full_duplex=1;
                        } else if (strcmp (media[card_idx], "1000mbps_hd") == 0 ||
-                                strcmp (media[card_idx], "6") == 0) {
+                                strcmp (media[card_idx], "5") == 0) {
                                np->speed = 1000;
                                np->full_duplex = 0;
                        } else {
@@ -175,7 +186,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
                }
                if (jumbo[card_idx] != 0) {
                        np->jumbo = 1;
-                       dev->mtu = 9000;
+                       dev->mtu = MAX_JUMBO;
                } else {
                        np->jumbo = 0;
                        if (mtu[card_idx] > 0 && mtu[card_idx] < PACKET_SIZE)
@@ -183,14 +194,17 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
                }
                np->vlan = (vlan[card_idx] > 0 && vlan[card_idx] < 4096) ?
                    vlan[card_idx] : 0;
-               if (int_count != 0 && int_timeout != 0) {
-                       np->int_count = int_count;
-                       np->int_timeout = int_timeout;
+               if (rx_coalesce != 0 && rx_timeout != 0) {
+                       np->rx_coalesce = rx_coalesce;
+                       np->rx_timeout = rx_timeout;
                        np->coalesce = 1;
                }
                np->tx_flow = (tx_flow[card_idx]) ? 1 : 0;
                np->rx_flow = (rx_flow[card_idx]) ? 1 : 0;
-               
+               if (tx_coalesce < 1)
+                       tx_coalesce = 1;
+               if (tx_coalesce > 8)
+                       tx_coalesce = 8;
        }
        dev->open = &rio_open;
        dev->hard_start_xmit = &start_xmit;
@@ -201,8 +215,8 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->tx_timeout = &tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
        dev->change_mtu = &change_mtu;
-#ifdef TX_HW_CHECKSUM
-       dev->features = NETIF_F_SG | NETIF_F_HW_CSUM;
+#if 0
+       dev->features = NETIF_F_IP_CSUM;
 #endif
        pci_set_drvdata (pdev, dev);
 
@@ -326,7 +340,7 @@ parse_eeprom (struct net_device *dev)
        }
 
        /* Check CRC */
-       crc = ~ether_crc_le(256-4, sromdata);
+       crc = ~ether_crc_le(256 - 4, sromdata);
        if (psrom->crc != crc) {
                printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name);
                return -1;
@@ -388,13 +402,12 @@ rio_open (struct net_device *dev)
        i = request_irq (dev->irq, &rio_interrupt, SA_SHIRQ, dev->name, dev);
        if (i)
                return i;
-
        /* DebugCtrl bit 4, 5, 9 must set */
        writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);
 
        /* Jumbo frame */
        if (np->jumbo != 0)
-               writew (9014, ioaddr + MaxFrameSize);
+               writew (MAX_JUMBO+14, ioaddr + MaxFrameSize);
 
        alloc_list (dev);
 
@@ -404,7 +417,7 @@ rio_open (struct net_device *dev)
 
        set_multicast (dev);
        if (np->coalesce) {
-               writel (np->int_count | np->int_timeout << 16,
+               writel (np->rx_coalesce | np->rx_timeout << 16,
                        ioaddr + RxDMAIntCtrl);
        }
        /* Set RIO to poll every N*320nsec. */
@@ -441,13 +454,31 @@ tx_timeout (struct net_device *dev)
        struct netdev_private *np = dev->priv;
        long ioaddr = dev->base_addr;
 
-       printk (KERN_WARNING "%s: Transmit timed out, TxStatus %4.4x.\n",
+       printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n",
                dev->name, readl (ioaddr + TxStatus));
+       /* Free used tx skbuffs */
+       for (; np->cur_tx - np->old_tx > 0; np->old_tx++) {
+               int entry = np->old_tx % TX_RING_SIZE;
+               struct sk_buff *skb;
+
+               if (!(np->tx_ring[entry].status & TFDDone))
+                       break;
+               skb = np->tx_skbuff[entry];
+               pci_unmap_single (np->pdev,
+                                 np->tx_ring[entry].fraginfo,
+                                 skb->len, PCI_DMA_TODEVICE);
+               dev_kfree_skb_irq (skb);
+               np->tx_skbuff[entry] = 0;
+       }
        dev->if_port = 0;
        dev->trans_start = jiffies;
        np->stats.tx_errors++;
-       if (!np->tx_full)
+       /* If the ring is no longer full, clear tx_full and 
+          call netif_wake_queue() */
+       if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) {
+               np->tx_full = 0;
                netif_wake_queue (dev);
+       }
 }
 
  /* allocate and initialize Tx and Rx descriptors */
@@ -465,16 +496,19 @@ alloc_list (struct net_device *dev)
        /* Initialize Tx descriptors, TFDListPtr leaves in start_xmit(). */
        for (i = 0; i < TX_RING_SIZE; i++) {
                np->tx_skbuff[i] = 0;
-               np->tx_ring[i].status = 0;
+               np->tx_ring[i].status = cpu_to_le64 (TFDDone);
+               np->tx_ring[i].next_desc = cpu_to_le64 (np->tx_ring_dma +
+                                             ((i+1)%TX_RING_SIZE) *
+                                             sizeof (struct
+                                             netdev_desc));
        }
 
        /* Initialize Rx descriptors */
        for (i = 0; i < RX_RING_SIZE; i++) {
                np->rx_ring[i].next_desc = cpu_to_le64 (np->rx_ring_dma +
-                                                       ((i +
-                                                         1) % RX_RING_SIZE) *
-                                                       sizeof (struct
-                                                               netdev_desc));
+                                               ((i + 1) % RX_RING_SIZE) *
+                                               sizeof (struct
+                                               netdev_desc));
                np->rx_ring[i].status = 0;
                np->rx_ring[i].fraginfo = 0;
                np->rx_skbuff[i] = 0;
@@ -522,13 +556,12 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
        entry = np->cur_tx % TX_RING_SIZE;
        np->tx_skbuff[entry] = skb;
        txdesc = &np->tx_ring[entry];
-       txdesc->next_desc = 0;
 
        /* Set TFDDone to avoid TxDMA gather this descriptor */
        txdesc->status = cpu_to_le64 (TFDDone);
        txdesc->status |=
            cpu_to_le64 (entry | WordAlignDisable | (1 << FragCountShift));
-#ifdef TX_HW_CHECKSUM
+#if 0
        if (skb->ip_summed == CHECKSUM_HW) {
                txdesc->status |=
                    cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable |
@@ -544,21 +577,13 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
 
        /* Send one packet each time at 10Mbps mode */
        /* Tx coalescing loop do not exceed 8 */
-       if (entry % 0x08 == 0 || np->speed == 10)
+       if (entry % tx_coalesce == 0 || np->speed == 10)
                txdesc->status |= cpu_to_le64 (TxIndicate);
        txdesc->fraginfo = cpu_to_le64 (pci_map_single (np->pdev, skb->data,
                                                        skb->len,
                                                        PCI_DMA_TODEVICE));
        txdesc->fraginfo |= cpu_to_le64 (skb->len) << 48;
 
-       /* Chain the last descriptor's pointer to this one */
-       if (np->last_tx)
-               np->last_tx->next_desc = cpu_to_le64 (np->tx_ring_dma +
-                                                     entry *
-                                                     sizeof (struct
-                                                             netdev_desc));
-       np->last_tx = txdesc;
-
        /* Clear TFDDone, then TxDMA start to send this descriptor */
        txdesc->status &= ~cpu_to_le64 (TFDDone);
 
@@ -570,8 +595,10 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
        if (np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1 && np->speed != 10) {
                /* do nothing */
        } else {
+               spin_lock_irqsave(&np->lock, flags);
                np->tx_full = 1;
                netif_stop_queue (dev);
+               spin_unlock_irqrestore (&np->lock, flags);
        }
 
        /* The first TFDListPtr */
@@ -580,15 +607,15 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
                        dev->base_addr + TFDListPtr0);
                writel (0, dev->base_addr + TFDListPtr1);
        }
-
-       spin_lock_irqsave (&np->lock, flags);
+       
        if (np->old_tx > TX_RING_SIZE) {
+               spin_lock_irqsave (&np->lock, flags);
                tx_shift = TX_RING_SIZE;
                np->old_tx -= tx_shift;
                np->cur_tx -= tx_shift;
+               spin_unlock_irqrestore (&np->lock, flags);
        }
-       spin_unlock_irqrestore (&np->lock, flags);
-
+       
        /* NETDEV WATCHDOG timer */
        dev->trans_start = jiffies;
        return 0;
@@ -605,33 +632,24 @@ rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs)
 
        ioaddr = dev->base_addr;
        np = dev->priv;
-       spin_lock (&np->lock);
+       spin_lock(&np->lock);
        while (1) {
-               int_status = readw (ioaddr + IntStatus) &
-                   (HostError | TxComplete | IntRequested |
-                    UpdateStats | LinkEvent | RxDMAComplete);
-               writew (int_status & (HostError | TxComplete | RxComplete |
-                                     IntRequested | UpdateStats | LinkEvent |
-                                     TxDMAComplete | RxDMAComplete | RFDListEnd
-                                     | RxDMAPriority), ioaddr + IntStatus);
+               int_status = readw (ioaddr + IntStatus); 
+               writew (int_status, ioaddr + IntStatus);
+               int_status &= DEFAULT_INTR;
                if (int_status == 0)
                        break;
                /* Processing received packets */
                if (int_status & RxDMAComplete)
                        receive_packet (dev);
                /* TxComplete interrupt */
-               if (int_status & TxComplete || np->tx_full) {
-                       int tx_status = readl (ioaddr + TxStatus);
+               if ((int_status & TxComplete) || np->tx_full) {
+                       int tx_status;
+                       tx_status = readl (ioaddr + TxStatus);
                        if (tx_status & 0x01)
                                tx_error (dev, tx_status);
-                       /* Send one packet each time at 10Mbps mode */
-                       if (np->speed == 10) {
-                               np->tx_full = 0;
-                               netif_wake_queue (dev);
-                       }
-
                        /* Free used tx skbuffs */
-                       for (; np->cur_tx - np->old_tx > 0; np->old_tx++) {
+                       for (;np->cur_tx - np->old_tx > 0; np->old_tx++) {
                                int entry = np->old_tx % TX_RING_SIZE;
                                struct sk_buff *skb;
 
@@ -648,9 +666,12 @@ rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs)
                /* If the ring is no longer full, clear tx_full and 
                   call netif_wake_queue() */
                if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) {
-                       np->tx_full = 0;
-                       netif_wake_queue (dev);
+                       if (np->speed != 10 || int_status & TxComplete) {
+                               np->tx_full = 0;
+                               netif_wake_queue (dev);
+                       }
                }
+
                /* Handle uncommon events */
                if (int_status &
                    (IntRequested | HostError | LinkEvent | UpdateStats))
@@ -665,7 +686,7 @@ rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs)
                        break;
                }
        }
-       spin_unlock (&np->lock);
+       spin_unlock(&np->lock);
 }
 
 static void
@@ -741,7 +762,7 @@ tx_error (struct net_device *dev, int tx_status)
                np->stats.collisions++;
 #endif
 
-       /* Restart the Tx. */
+       /* Restart the Tx */
        writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl);
 }
 
@@ -782,7 +803,7 @@ receive_packet (struct net_device *dev)
                        if (frame_status & 0x00300000)
                                np->stats.rx_length_errors++;
                        if (frame_status & 0x00010000)
-                               np->stats.rx_fifo_errors++;
+                               np->stats.rx_fifo_errors++;
                        if (frame_status & 0x00060000)
                                np->stats.rx_frame_errors++;
                        if (frame_status & 0x00080000)
@@ -807,7 +828,7 @@ receive_packet (struct net_device *dev)
                                skb_put (skb, pkt_len);
                        }
                        skb->protocol = eth_type_trans (skb, dev);
-#ifdef RX_HW_CHECKSUM
+#if 0
                        /* Checksum done by hw, but csum value unavailable. */
                        if (!(frame_status & (TCPError | UDPError | IPError))) {
                                skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -898,7 +919,7 @@ rio_error (struct net_device *dev, int int_status)
        /* PCI Error, a catastronphic error related to the bus interface 
           occurs, set GlobalReset and HostReset to reset. */
        if (int_status & HostError) {
-               printk (KERN_ERR "%s: PCI Error! IntStatus %4.4x.\n",
+               printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n",
                        dev->name, int_status);
                writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2);
                mdelay (500);
@@ -913,8 +934,8 @@ get_stats (struct net_device *dev)
        u16 temp1;
        u16 temp2;
        int i;
-       /* All statistics registers need to acknowledge,
-          else overflow could cause some problem */
+       /* All statistics registers need to be acknowledged,
+          else statistic overflow could cause problems */
        np->stats.rx_packets += readl (ioaddr + FramesRcvOk);
        np->stats.tx_packets += readl (ioaddr + FramesXmtOk);
        np->stats.rx_bytes += readl (ioaddr + OctetRcvOk);
@@ -931,11 +952,11 @@ get_stats (struct net_device *dev)
            readl (ioaddr + FramesWDeferredXmt) + temp2;
 
        /* detailed rx_error */
-       np->stats.rx_length_errors += readw (ioaddr + InRangeLengthErrors) +
-           readw (ioaddr + FrameTooLongErrors);
+       np->stats.rx_length_errors += readw (ioaddr + FrameTooLongErrors);
        np->stats.rx_crc_errors += readw (ioaddr + FrameCheckSeqError);
 
        /* Clear all other statistic register. */
+       readw (ioaddr + InRangeLengthErrors);
        readw (ioaddr + MacControlFramesXmtd);
        readw (ioaddr + BcstFramesXmtdOk);
        readl (ioaddr + McstFramesXmtdOk);
@@ -960,7 +981,7 @@ int
 change_mtu (struct net_device *dev, int new_mtu)
 {
        struct netdev_private *np = dev->priv;
-       int max = (np->jumbo) ? 9000 : 1536;
+       int max = (np->jumbo) ? MAX_JUMBO : 1536;
 
        if ((new_mtu < 68) || (new_mtu > max)) {
                return -EINVAL;
@@ -978,36 +999,42 @@ set_multicast (struct net_device *dev)
        u32 hash_table[2];
        u16 rx_mode = 0;
        int i;
+       int bit;
+       int index, crc;
        struct dev_mc_list *mclist;
        struct netdev_private *np = dev->priv;
-
-       /* Default: receive broadcast and unicast */
-       rx_mode = ReceiveBroadcast | ReceiveUnicast;
+       
+       hash_table[0] = hash_table[1] = 0;
+       /* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */
+       hash_table[1] |= 0x02000000;
        if (dev->flags & IFF_PROMISC) {
                /* Receive all frames promiscuously. */
-               rx_mode |= ReceiveAllFrames;
-       } else if (((dev->flags & IFF_MULTICAST)
-                   && (dev->mc_count > multicast_filter_limit))
-                  || (dev->flags & IFF_ALLMULTI)) {
+               rx_mode = ReceiveAllFrames;
+       } else if ((dev->flags & IFF_ALLMULTI) || 
+                       (dev->mc_count > multicast_filter_limit)) {
                /* Receive broadcast and multicast frames */
-               rx_mode |= ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
-       } else if ((dev->flags & IFF_MULTICAST) & (dev->mc_count > 0)) {
-               /* Receive broadcast frames and multicast frames filtering by Hashtable */
-               rx_mode |=
+               rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
+       } else if (dev->mc_count > 0) {
+               /* Receive broadcast frames and multicast frames filtering 
+                  by Hashtable */
+               rx_mode =
                    ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast;
+               for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count; 
+                               i++, mclist=mclist->next) {
+                       crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr);
+                       for (index=0, bit=0; bit<6; bit++, crc<<=1) {
+                               if (crc & 0x80000000) index |= 1 << bit;
+                       }
+                       hash_table[index / 32] |= (1 << (index % 32));
+               }
+       } else {
+               rx_mode = ReceiveBroadcast | ReceiveUnicast;
        }
        if (np->vlan) {
                /* ReceiveVLANMatch field in ReceiveMode */
                rx_mode |= ReceiveVLANMatch;
        }
-       hash_table[0] = 0x00000000;
-       hash_table[1] = 0x00000000;
 
-       for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-            i++, mclist = mclist->next) {
-               set_bit (ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,
-                        hash_table);
-       }
        writel (hash_table[0], ioaddr + HashTable0);
        writel (hash_table[1], ioaddr + HashTable1);
        writew (rx_mode, ioaddr + ReceiveMode);
@@ -1677,8 +1704,9 @@ module_exit (rio_exit);
  
 Compile command: 
  
-gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2x.c
+gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2k.c
 
 Read Documentation/networking/dl2k.txt for details.
 
 */
+
index 49ed98d4d87830c8388ca5a653fef1f48269ebb1..cafa8d1277bf28f429331bb887b073abbc540108 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/spinlock.h>
 #include <linux/time.h>
 #define TX_RING_SIZE   128
-#define TX_QUEUE_LEN   96      /* Limit ring entries actually used.  */
+#define TX_QUEUE_LEN   120     /* Limit ring entries actually used.  */
 #define RX_RING_SIZE   128
 #define TX_TOTAL_SIZE  TX_RING_SIZE*sizeof(struct netdev_desc)
 #define RX_TOTAL_SIZE  RX_RING_SIZE*sizeof(struct netdev_desc)
@@ -183,12 +183,12 @@ enum IntStatus_bits {
 
 /* Bits in the ReceiveMode register. */
 enum ReceiveMode_bits {
-       ReceiveIPMulticast = 0x0020,
-       ReceiveMulticastHash = 0x0010,
-       ReceiveAllFrames = 0x0008,
-       ReceiveBroadcast = 0x0004,
-       ReceiveMulticast = 0x0002,
        ReceiveUnicast = 0x0001,
+       ReceiveMulticast = 0x0002,
+       ReceiveBroadcast = 0x0004,
+       ReceiveAllFrames = 0x0008,
+       ReceiveMulticastHash = 0x0010,
+       ReceiveIPMulticast = 0x0020,
        ReceiveVLANMatch = 0x0100,
        ReceiveVLANHash = 0x0200,
 };
@@ -650,20 +650,20 @@ struct netdev_private {
        struct pci_dev *pdev;
        spinlock_t lock;
        struct net_device_stats stats;
-       unsigned int rx_buf_sz; /* Based on MTU+slack. */
-       unsigned int speed;     /* Operating speed */
-       unsigned int vlan;      /* VLAN Id */
-       unsigned int chip_id;   /* PCI table chip id */
-       unsigned int int_count; /* Maximum frames each RxDMAComplete intr */
-       unsigned int int_timeout; /* Wait time between RxDMAComplete intr */
-       unsigned int tx_full:1; /* The Tx queue is full. */
+       unsigned int rx_buf_sz;         /* Based on MTU+slack. */
+       unsigned int speed;             /* Operating speed */
+       unsigned int vlan;              /* VLAN Id */
+       unsigned int chip_id;           /* PCI table chip id */
+       unsigned int rx_coalesce;       /* Maximum frames each RxDMAComplete intr */
+       unsigned int rx_timeout;        /* Wait time between RxDMAComplete intr */
+       unsigned int tx_full:1;         /* The Tx queue is full. */
        unsigned int full_duplex:1;     /* Full-duplex operation requested. */
        unsigned int an_enable:2;       /* Auto-Negotiated Enable */
        unsigned int jumbo:1;           /* Jumbo frame enable */
        unsigned int coalesce:1;        /* Rx coalescing enable */
        unsigned int tx_flow:1;         /* Tx flow control enable */
        unsigned int rx_flow:1;         /* Rx flow control enable */
-       unsigned int phy_media:1;       /* 1: fiber, 0: copper */ 
+       unsigned int phy_media:1;       /* 1: fiber, 0: copper */
        struct netdev_desc *last_tx;    /* Last Tx descriptor used. */
        unsigned long cur_rx, old_rx;   /* Producer/consumer ring indices */
        unsigned long cur_tx, old_tx;
@@ -698,7 +698,12 @@ static struct pci_device_id rio_pci_tbl[] __devinitdata = {
 MODULE_DEVICE_TABLE (pci, rio_pci_tbl);
 #define TX_TIMEOUT  (4*HZ)
 #define PACKET_SIZE            1536
+#define MAX_JUMBO              8000
 #define RIO_IO_SIZE             340
+#define DEFAULT_RXC            5
+#define DEFAULT_RXT            750
+#define DEFAULT_TXC            1
+#define MAX_TXC                        8
 #ifdef RIO_DEBUG
 #define DEBUG_TFD_DUMP(x) debug_tfd_dump(x)
 #define DEBUG_RFD_DUMP(x,flag) debug_rfd_dump(x,flag)