[PATCH] libertas: remove incorrect vi modelines
[safe/jmp/linux-2.6] / drivers / net / 8139cp.c
index e4b3c5c..e8c9f27 100644 (file)
        See the file COPYING in this distribution for more information.
 
        Contributors:
-       
+
                Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br>
                PCI suspend/resume  - Felipe Damasio <felipewd@terra.com.br>
                LinkChg interrupt   - Felipe Damasio <felipewd@terra.com.br>
-                       
+
        TODO:
        * Test Tx checksumming thoroughly
        * Implement dev->tx_timeout
  */
 
 #define DRV_NAME               "8139cp"
-#define DRV_VERSION            "1.2"
+#define DRV_VERSION            "1.3"
 #define DRV_RELDATE            "Mar 22, 2004"
 
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -315,12 +314,6 @@ struct cp_desc {
        u64             addr;
 };
 
-struct ring_info {
-       struct sk_buff          *skb;
-       dma_addr_t              mapping;
-       u32                     len;
-};
-
 struct cp_dma_stats {
        u64                     tx_ok;
        u64                     rx_ok;
@@ -353,26 +346,24 @@ struct cp_private {
 
        struct net_device_stats net_stats;
        struct cp_extra_stats   cp_stats;
-       struct cp_dma_stats     *nic_stats;
-       dma_addr_t              nic_stats_dma;
 
-       unsigned                rx_tail         ____cacheline_aligned;
+       unsigned                rx_head         ____cacheline_aligned;
+       unsigned                rx_tail;
        struct cp_desc          *rx_ring;
-       struct ring_info        rx_skb[CP_RX_RING_SIZE];
-       unsigned                rx_buf_sz;
+       struct sk_buff          *rx_skb[CP_RX_RING_SIZE];
 
        unsigned                tx_head         ____cacheline_aligned;
        unsigned                tx_tail;
-
        struct cp_desc          *tx_ring;
-       struct ring_info        tx_skb[CP_TX_RING_SIZE];
-       dma_addr_t              ring_dma;
+       struct sk_buff          *tx_skb[CP_TX_RING_SIZE];
+
+       unsigned                rx_buf_sz;
+       unsigned                wol_enabled : 1; /* Is Wake-on-LAN enabled? */
 
 #if CP_VLAN_TAG_USED
        struct vlan_group       *vlgrp;
 #endif
-
-       unsigned int            wol_enabled : 1; /* Is Wake-on-LAN enabled? */
+       dma_addr_t              ring_dma;
 
        struct mii_if_info      mii_if;
 };
@@ -403,12 +394,15 @@ static void cp_clean_rings (struct cp_private *cp);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void cp_poll_controller(struct net_device *dev);
 #endif
+static int cp_get_eeprom_len(struct net_device *dev);
+static int cp_get_eeprom(struct net_device *dev,
+                        struct ethtool_eeprom *eeprom, u8 *data);
+static int cp_set_eeprom(struct net_device *dev,
+                        struct ethtool_eeprom *eeprom, u8 *data);
 
 static struct pci_device_id cp_pci_tbl[] = {
-       { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-       { PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+       { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     PCI_DEVICE_ID_REALTEK_8139), },
+       { PCI_DEVICE(PCI_VENDOR_ID_TTTECH,      PCI_DEVICE_ID_TTTECH_MC322), },
        { },
 };
 MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
@@ -454,8 +448,7 @@ static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        spin_lock_irqsave(&cp->lock, flags);
        cp->cpcmd &= ~RxVlanOn;
        cpw16(CpCmd, cp->cpcmd);
-       if (cp->vlgrp)
-               cp->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(cp->vlgrp, vid, NULL);
        spin_unlock_irqrestore(&cp->lock, flags);
 }
 #endif /* CP_VLAN_TAG_USED */
@@ -463,7 +456,7 @@ static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 static inline void cp_set_rxbufsize (struct cp_private *cp)
 {
        unsigned int mtu = cp->dev->mtu;
-       
+
        if (mtu > ETH_DATA_LEN)
                /* MTU + ethernet header + FCS + optional VLAN tag */
                cp->rx_buf_sz = mtu + ETH_HLEN + 8;
@@ -512,7 +505,7 @@ static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
 static inline unsigned int cp_rx_csum_ok (u32 status)
 {
        unsigned int protocol = (status >> 16) & 0x3;
-       
+
        if (likely((protocol == RxProtoTCP) && (!(status & TCPFail))))
                return 1;
        else if ((protocol == RxProtoUDP) && (!(status & UDPFail)))
@@ -540,9 +533,8 @@ rx_status_loop:
                struct cp_desc *desc;
                unsigned buflen;
 
-               skb = cp->rx_skb[rx_tail].skb;
-               if (!skb)
-                       BUG();
+               skb = cp->rx_skb[rx_tail];
+               BUG_ON(!skb);
 
                desc = &cp->rx_ring[rx_tail];
                status = le32_to_cpu(desc->opts1);
@@ -550,7 +542,7 @@ rx_status_loop:
                        break;
 
                len = (status & 0x1fff) - 4;
-               mapping = cp->rx_skb[rx_tail].mapping;
+               mapping = le64_to_cpu(desc->addr);
 
                if ((status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag)) {
                        /* we don't support incoming fragmented frames.
@@ -571,7 +563,7 @@ rx_status_loop:
 
                if (netif_msg_rx_status(cp))
                        printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d\n",
-                              cp->dev->name, rx_tail, status, len);
+                              dev->name, rx_tail, status, len);
 
                buflen = cp->rx_buf_sz + RX_OFFSET;
                new_skb = dev_alloc_skb (buflen);
@@ -581,7 +573,6 @@ rx_status_loop:
                }
 
                skb_reserve(new_skb, RX_OFFSET);
-               new_skb->dev = cp->dev;
 
                pci_unmap_single(cp->pdev, mapping,
                                 buflen, PCI_DMA_FROMDEVICE);
@@ -594,11 +585,9 @@ rx_status_loop:
 
                skb_put(skb, len);
 
-               mapping =
-               cp->rx_skb[rx_tail].mapping =
-                       pci_map_single(cp->pdev, new_skb->tail,
-                                      buflen, PCI_DMA_FROMDEVICE);
-               cp->rx_skb[rx_tail].skb = new_skb;
+               mapping = pci_map_single(cp->pdev, new_skb->data, buflen,
+                                        PCI_DMA_FROMDEVICE);
+               cp->rx_skb[rx_tail] = new_skb;
 
                cp_rx_skb(cp, skb, desc);
                rx++;
@@ -626,13 +615,15 @@ rx_next:
         * this round of polling
         */
        if (rx_work) {
+               unsigned long flags;
+
                if (cpr16(IntrStatus) & cp_rx_intr_mask)
                        goto rx_status_loop;
 
-               local_irq_disable();
+               local_irq_save(flags);
                cpw16_f(IntrMask, cp_intr_mask);
                __netif_rx_complete(dev);
-               local_irq_enable();
+               local_irq_restore(flags);
 
                return 0;       /* done */
        }
@@ -640,8 +631,7 @@ rx_next:
        return 1;               /* not done */
 }
 
-static irqreturn_t
-cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t cp_interrupt (int irq, void *dev_instance)
 {
        struct net_device *dev = dev_instance;
        struct cp_private *cp;
@@ -705,7 +695,7 @@ cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
 static void cp_poll_controller(struct net_device *dev)
 {
        disable_irq(dev->irq);
-       cp_interrupt(dev->irq, dev, NULL);
+       cp_interrupt(dev->irq, dev);
        enable_irq(dev->irq);
 }
 #endif
@@ -716,20 +706,21 @@ static void cp_tx (struct cp_private *cp)
        unsigned tx_tail = cp->tx_tail;
 
        while (tx_tail != tx_head) {
+               struct cp_desc *txd = cp->tx_ring + tx_tail;
                struct sk_buff *skb;
                u32 status;
 
                rmb();
-               status = le32_to_cpu(cp->tx_ring[tx_tail].opts1);
+               status = le32_to_cpu(txd->opts1);
                if (status & DescOwn)
                        break;
 
-               skb = cp->tx_skb[tx_tail].skb;
-               if (!skb)
-                       BUG();
+               skb = cp->tx_skb[tx_tail];
+               BUG_ON(!skb);
 
-               pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
-                                cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
+               pci_unmap_single(cp->pdev, le64_to_cpu(txd->addr),
+                                le32_to_cpu(txd->opts1) & 0xffff,
+                                PCI_DMA_TODEVICE);
 
                if (status & LastFrag) {
                        if (status & (TxError | TxFIFOUnder)) {
@@ -756,7 +747,7 @@ static void cp_tx (struct cp_private *cp)
                        dev_kfree_skb_irq(skb);
                }
 
-               cp->tx_skb[tx_tail].skb = NULL;
+               cp->tx_skb[tx_tail] = NULL;
 
                tx_tail = NEXT_TX(tx_tail);
        }
@@ -772,17 +763,18 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
        struct cp_private *cp = netdev_priv(dev);
        unsigned entry;
        u32 eor, flags;
+       unsigned long intr_flags;
 #if CP_VLAN_TAG_USED
        u32 vlan_tag = 0;
 #endif
        int mss = 0;
 
-       spin_lock_irq(&cp->lock);
+       spin_lock_irqsave(&cp->lock, intr_flags);
 
        /* This is a hard error, log it. */
        if (TX_BUFFS_AVAIL(cp) <= (skb_shinfo(skb)->nr_frags + 1)) {
                netif_stop_queue(dev);
-               spin_unlock_irq(&cp->lock);
+               spin_unlock_irqrestore(&cp->lock, intr_flags);
                printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
                       dev->name);
                return 1;
@@ -796,7 +788,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
        entry = cp->tx_head;
        eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
        if (dev->features & NETIF_F_TSO)
-               mss = skb_shinfo(skb)->tso_size;
+               mss = skb_shinfo(skb)->gso_size;
 
        if (skb_shinfo(skb)->nr_frags == 0) {
                struct cp_desc *txd = &cp->tx_ring[entry];
@@ -813,8 +805,8 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
 
                if (mss)
                        flags |= LargeSend | ((mss & MSSMask) << MSSShift);
-               else if (skb->ip_summed == CHECKSUM_HW) {
-                       const struct iphdr *ip = skb->nh.iph;
+               else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+                       const struct iphdr *ip = ip_hdr(skb);
                        if (ip->protocol == IPPROTO_TCP)
                                flags |= IPCS | TCPCS;
                        else if (ip->protocol == IPPROTO_UDP)
@@ -826,16 +818,14 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
                txd->opts1 = cpu_to_le32(flags);
                wmb();
 
-               cp->tx_skb[entry].skb = skb;
-               cp->tx_skb[entry].mapping = mapping;
-               cp->tx_skb[entry].len = len;
+               cp->tx_skb[entry] = skb;
                entry = NEXT_TX(entry);
        } else {
                struct cp_desc *txd;
                u32 first_len, first_eor;
                dma_addr_t first_mapping;
                int frag, first_entry = entry;
-               const struct iphdr *ip = skb->nh.iph;
+               const struct iphdr *ip = ip_hdr(skb);
 
                /* We must give this initial chunk to the device last.
                 * Otherwise we could race with the device.
@@ -844,9 +834,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
                first_len = skb_headlen(skb);
                first_mapping = pci_map_single(cp->pdev, skb->data,
                                               first_len, PCI_DMA_TODEVICE);
-               cp->tx_skb[entry].skb = skb;
-               cp->tx_skb[entry].mapping = first_mapping;
-               cp->tx_skb[entry].len = first_len;
+               cp->tx_skb[entry] = skb;
                entry = NEXT_TX(entry);
 
                for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -867,7 +855,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
                        if (mss)
                                ctrl |= LargeSend |
                                        ((mss & MSSMask) << MSSShift);
-                       else if (skb->ip_summed == CHECKSUM_HW) {
+                       else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                                if (ip->protocol == IPPROTO_TCP)
                                        ctrl |= IPCS | TCPCS;
                                else if (ip->protocol == IPPROTO_UDP)
@@ -887,9 +875,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
                        txd->opts1 = cpu_to_le32(ctrl);
                        wmb();
 
-                       cp->tx_skb[entry].skb = skb;
-                       cp->tx_skb[entry].mapping = mapping;
-                       cp->tx_skb[entry].len = len;
+                       cp->tx_skb[entry] = skb;
                        entry = NEXT_TX(entry);
                }
 
@@ -898,7 +884,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
                txd->addr = cpu_to_le64(first_mapping);
                wmb();
 
-               if (skb->ip_summed == CHECKSUM_HW) {
+               if (skb->ip_summed == CHECKSUM_PARTIAL) {
                        if (ip->protocol == IPPROTO_TCP)
                                txd->opts1 = cpu_to_le32(first_eor | first_len |
                                                         FirstFrag | DescOwn |
@@ -921,7 +907,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
        if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
                netif_stop_queue(dev);
 
-       spin_unlock_irq(&cp->lock);
+       spin_unlock_irqrestore(&cp->lock, intr_flags);
 
        cpw8(TxPoll, NormalTxPoll);
        dev->trans_start = jiffies;
@@ -942,8 +928,6 @@ static void __cp_set_rx_mode (struct net_device *dev)
        /* Note: do not reorder, GCC is clever about common statements. */
        if (dev->flags & IFF_PROMISC) {
                /* Unconditionally log net taps. */
-               printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-                       dev->name);
                rx_mode =
                    AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
                    AcceptAllPhys;
@@ -1029,8 +1013,7 @@ static void cp_reset_hw (struct cp_private *cp)
                if (!(cpr8(Cmd) & CmdReset))
                        return;
 
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(10);
+               schedule_timeout_uninterruptible(10);
        }
 
        printk(KERN_ERR "%s: hardware reset timeout\n", cp->dev->name);
@@ -1066,7 +1049,7 @@ static void cp_init_hw (struct cp_private *cp)
        cpw8(Config3, PARMEnable);
        cp->wol_enabled = 0;
 
-       cpw8(Config5, cpr8(Config5) & PMEStatus); 
+       cpw8(Config5, cpr8(Config5) & PMEStatus);
 
        cpw32_f(HiTxRingAddr, 0);
        cpw32_f(HiTxRingAddr + 4, 0);
@@ -1092,20 +1075,20 @@ static int cp_refill_rx (struct cp_private *cp)
 
        for (i = 0; i < CP_RX_RING_SIZE; i++) {
                struct sk_buff *skb;
+               dma_addr_t mapping;
 
                skb = dev_alloc_skb(cp->rx_buf_sz + RX_OFFSET);
                if (!skb)
                        goto err_out;
 
-               skb->dev = cp->dev;
                skb_reserve(skb, RX_OFFSET);
 
-               cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
-                       skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-               cp->rx_skb[i].skb = skb;
+               mapping = pci_map_single(cp->pdev, skb->data, cp->rx_buf_sz,
+                                        PCI_DMA_FROMDEVICE);
+               cp->rx_skb[i] = skb;
 
                cp->rx_ring[i].opts2 = 0;
-               cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
+               cp->rx_ring[i].addr = cpu_to_le64(mapping);
                if (i == (CP_RX_RING_SIZE - 1))
                        cp->rx_ring[i].opts1 =
                                cpu_to_le32(DescOwn | RingEnd | cp->rx_buf_sz);
@@ -1121,13 +1104,18 @@ err_out:
        return -ENOMEM;
 }
 
+static void cp_init_rings_index (struct cp_private *cp)
+{
+       cp->rx_tail = 0;
+       cp->tx_head = cp->tx_tail = 0;
+}
+
 static int cp_init_rings (struct cp_private *cp)
 {
        memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
        cp->tx_ring[CP_TX_RING_SIZE - 1].opts1 = cpu_to_le32(RingEnd);
 
-       cp->rx_tail = 0;
-       cp->tx_head = cp->tx_tail = 0;
+       cp_init_rings_index(cp);
 
        return cp_refill_rx (cp);
 }
@@ -1143,32 +1131,32 @@ static int cp_alloc_rings (struct cp_private *cp)
        cp->rx_ring = mem;
        cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];
 
-       mem += (CP_RING_BYTES - CP_STATS_SIZE);
-       cp->nic_stats = mem;
-       cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE);
-
        return cp_init_rings(cp);
 }
 
 static void cp_clean_rings (struct cp_private *cp)
 {
+       struct cp_desc *desc;
        unsigned i;
 
        for (i = 0; i < CP_RX_RING_SIZE; i++) {
-               if (cp->rx_skb[i].skb) {
-                       pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
+               if (cp->rx_skb[i]) {
+                       desc = cp->rx_ring + i;
+                       pci_unmap_single(cp->pdev, le64_to_cpu(desc->addr),
                                         cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-                       dev_kfree_skb(cp->rx_skb[i].skb);
+                       dev_kfree_skb(cp->rx_skb[i]);
                }
        }
 
        for (i = 0; i < CP_TX_RING_SIZE; i++) {
-               if (cp->tx_skb[i].skb) {
-                       struct sk_buff *skb = cp->tx_skb[i].skb;
-
-                       pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
-                                        cp->tx_skb[i].len, PCI_DMA_TODEVICE);
-                       if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
+               if (cp->tx_skb[i]) {
+                       struct sk_buff *skb = cp->tx_skb[i];
+
+                       desc = cp->tx_ring + i;
+                       pci_unmap_single(cp->pdev, le64_to_cpu(desc->addr),
+                                        le32_to_cpu(desc->opts1) & 0xffff,
+                                        PCI_DMA_TODEVICE);
+                       if (le32_to_cpu(desc->opts1) & LastFrag)
                                dev_kfree_skb(skb);
                        cp->net_stats.tx_dropped++;
                }
@@ -1177,8 +1165,8 @@ static void cp_clean_rings (struct cp_private *cp)
        memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
        memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
 
-       memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
-       memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
+       memset(cp->rx_skb, 0, sizeof(struct sk_buff *) * CP_RX_RING_SIZE);
+       memset(cp->tx_skb, 0, sizeof(struct sk_buff *) * CP_TX_RING_SIZE);
 }
 
 static void cp_free_rings (struct cp_private *cp)
@@ -1187,7 +1175,6 @@ static void cp_free_rings (struct cp_private *cp)
        pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma);
        cp->rx_ring = NULL;
        cp->tx_ring = NULL;
-       cp->nic_stats = NULL;
 }
 
 static int cp_open (struct net_device *dev)
@@ -1204,7 +1191,7 @@ static int cp_open (struct net_device *dev)
 
        cp_init_hw(cp);
 
-       rc = request_irq(dev->irq, cp_interrupt, SA_SHIRQ, dev->name, dev);
+       rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev);
        if (rc)
                goto err_out_hw;
 
@@ -1279,7 +1266,7 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu)
 }
 #endif /* BROKEN */
 
-static char mii_2_8139_map[8] = {
+static const char mii_2_8139_map[8] = {
        BasicModeCtrl,
        BasicModeStatus,
        0,
@@ -1356,7 +1343,7 @@ static void netdev_get_wol (struct cp_private *cp,
                         WAKE_MCAST | WAKE_UCAST;
        /* We don't need to go on if WOL is disabled */
        if (!cp->wol_enabled) return;
-       
+
        options        = cpr8 (Config3);
        if (options & LinkUp)        wol->wolopts |= WAKE_PHY;
        if (options & MagicPacket)   wol->wolopts |= WAKE_MAGIC;
@@ -1516,13 +1503,17 @@ static void cp_get_ethtool_stats (struct net_device *dev,
                                  struct ethtool_stats *estats, u64 *tmp_stats)
 {
        struct cp_private *cp = netdev_priv(dev);
+       struct cp_dma_stats *nic_stats;
+       dma_addr_t dma;
        int i;
 
-       memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats));
+       nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma);
+       if (!nic_stats)
+               return;
 
        /* begin NIC statistics dump */
-       cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16);
-       cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats);
+       cpw32(StatsAddr + 4, (u64)dma >> 32);
+       cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats);
        cpr32(StatsAddr);
 
        for (i = 0; i < 1000; i++) {
@@ -1532,27 +1523,29 @@ static void cp_get_ethtool_stats (struct net_device *dev,
        }
        cpw32(StatsAddr, 0);
        cpw32(StatsAddr + 4, 0);
+       cpr32(StatsAddr);
 
        i = 0;
-       tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok);
-       tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok);
-       tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err);
-       tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err);
-       tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo);
-       tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align);
-       tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col);
-       tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol);
-       tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys);
-       tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast);
-       tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast);
-       tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort);
-       tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun);
+       tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok);
+       tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok);
+       tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err);
+       tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err);
+       tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo);
+       tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align);
+       tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col);
+       tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol);
+       tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys);
+       tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast);
+       tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast);
+       tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
+       tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
        tmp_stats[i++] = cp->cp_stats.rx_frags;
-       if (i != CP_NUM_STATS)
-               BUG();
+       BUG_ON(i != CP_NUM_STATS);
+
+       pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
 }
 
-static struct ethtool_ops cp_ethtool_ops = {
+static const struct ethtool_ops cp_ethtool_ops = {
        .get_drvinfo            = cp_get_drvinfo,
        .get_regs_len           = cp_get_regs_len,
        .get_stats_count        = cp_get_stats_count,
@@ -1575,6 +1568,10 @@ static struct ethtool_ops cp_ethtool_ops = {
        .set_wol                = cp_set_wol,
        .get_strings            = cp_get_strings,
        .get_ethtool_stats      = cp_get_ethtool_stats,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
+       .get_eeprom_len         = cp_get_eeprom_len,
+       .get_eeprom             = cp_get_eeprom,
+       .set_eeprom             = cp_set_eeprom,
 };
 
 static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1610,24 +1607,32 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 #define eeprom_delay() readl(ee_addr)
 
 /* The EEPROM commands include the alway-set leading bit. */
+#define EE_EXTEND_CMD  (4)
 #define EE_WRITE_CMD   (5)
 #define EE_READ_CMD            (6)
 #define EE_ERASE_CMD   (7)
 
-static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
-{
-       int i;
-       unsigned retval = 0;
-       void __iomem *ee_addr = ioaddr + Cfg9346;
-       int read_cmd = location | (EE_READ_CMD << addr_len);
+#define EE_EWDS_ADDR   (0)
+#define EE_WRAL_ADDR   (1)
+#define EE_ERAL_ADDR   (2)
+#define EE_EWEN_ADDR   (3)
+
+#define CP_EEPROM_MAGIC PCI_DEVICE_ID_REALTEK_8139
 
+static void eeprom_cmd_start(void __iomem *ee_addr)
+{
        writeb (EE_ENB & ~EE_CS, ee_addr);
        writeb (EE_ENB, ee_addr);
        eeprom_delay ();
+}
 
-       /* Shift the read command bits out. */
-       for (i = 4 + addr_len; i >= 0; i--) {
-               int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+static void eeprom_cmd(void __iomem *ee_addr, int cmd, int cmd_len)
+{
+       int i;
+
+       /* Shift the command bits out. */
+       for (i = cmd_len - 1; i >= 0; i--) {
+               int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
                writeb (EE_ENB | dataval, ee_addr);
                eeprom_delay ();
                writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
@@ -1635,6 +1640,33 @@ static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
        }
        writeb (EE_ENB, ee_addr);
        eeprom_delay ();
+}
+
+static void eeprom_cmd_end(void __iomem *ee_addr)
+{
+       writeb (~EE_CS, ee_addr);
+       eeprom_delay ();
+}
+
+static void eeprom_extend_cmd(void __iomem *ee_addr, int extend_cmd,
+                             int addr_len)
+{
+       int cmd = (EE_EXTEND_CMD << addr_len) | (extend_cmd << (addr_len - 2));
+
+       eeprom_cmd_start(ee_addr);
+       eeprom_cmd(ee_addr, cmd, 3 + addr_len);
+       eeprom_cmd_end(ee_addr);
+}
+
+static u16 read_eeprom (void __iomem *ioaddr, int location, int addr_len)
+{
+       int i;
+       u16 retval = 0;
+       void __iomem *ee_addr = ioaddr + Cfg9346;
+       int read_cmd = location | (EE_READ_CMD << addr_len);
+
+       eeprom_cmd_start(ee_addr);
+       eeprom_cmd(ee_addr, read_cmd, 3 + addr_len);
 
        for (i = 16; i > 0; i--) {
                writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
@@ -1646,13 +1678,125 @@ static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
                eeprom_delay ();
        }
 
-       /* Terminate the EEPROM access. */
-       writeb (~EE_CS, ee_addr);
-       eeprom_delay ();
+       eeprom_cmd_end(ee_addr);
 
        return retval;
 }
 
+static void write_eeprom(void __iomem *ioaddr, int location, u16 val,
+                        int addr_len)
+{
+       int i;
+       void __iomem *ee_addr = ioaddr + Cfg9346;
+       int write_cmd = location | (EE_WRITE_CMD << addr_len);
+
+       eeprom_extend_cmd(ee_addr, EE_EWEN_ADDR, addr_len);
+
+       eeprom_cmd_start(ee_addr);
+       eeprom_cmd(ee_addr, write_cmd, 3 + addr_len);
+       eeprom_cmd(ee_addr, val, 16);
+       eeprom_cmd_end(ee_addr);
+
+       eeprom_cmd_start(ee_addr);
+       for (i = 0; i < 20000; i++)
+               if (readb(ee_addr) & EE_DATA_READ)
+                       break;
+       eeprom_cmd_end(ee_addr);
+
+       eeprom_extend_cmd(ee_addr, EE_EWDS_ADDR, addr_len);
+}
+
+static int cp_get_eeprom_len(struct net_device *dev)
+{
+       struct cp_private *cp = netdev_priv(dev);
+       int size;
+
+       spin_lock_irq(&cp->lock);
+       size = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 256 : 128;
+       spin_unlock_irq(&cp->lock);
+
+       return size;
+}
+
+static int cp_get_eeprom(struct net_device *dev,
+                        struct ethtool_eeprom *eeprom, u8 *data)
+{
+       struct cp_private *cp = netdev_priv(dev);
+       unsigned int addr_len;
+       u16 val;
+       u32 offset = eeprom->offset >> 1;
+       u32 len = eeprom->len;
+       u32 i = 0;
+
+       eeprom->magic = CP_EEPROM_MAGIC;
+
+       spin_lock_irq(&cp->lock);
+
+       addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
+
+       if (eeprom->offset & 1) {
+               val = read_eeprom(cp->regs, offset, addr_len);
+               data[i++] = (u8)(val >> 8);
+               offset++;
+       }
+
+       while (i < len - 1) {
+               val = read_eeprom(cp->regs, offset, addr_len);
+               data[i++] = (u8)val;
+               data[i++] = (u8)(val >> 8);
+               offset++;
+       }
+
+       if (i < len) {
+               val = read_eeprom(cp->regs, offset, addr_len);
+               data[i] = (u8)val;
+       }
+
+       spin_unlock_irq(&cp->lock);
+       return 0;
+}
+
+static int cp_set_eeprom(struct net_device *dev,
+                        struct ethtool_eeprom *eeprom, u8 *data)
+{
+       struct cp_private *cp = netdev_priv(dev);
+       unsigned int addr_len;
+       u16 val;
+       u32 offset = eeprom->offset >> 1;
+       u32 len = eeprom->len;
+       u32 i = 0;
+
+       if (eeprom->magic != CP_EEPROM_MAGIC)
+               return -EINVAL;
+
+       spin_lock_irq(&cp->lock);
+
+       addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
+
+       if (eeprom->offset & 1) {
+               val = read_eeprom(cp->regs, offset, addr_len) & 0xff;
+               val |= (u16)data[i++] << 8;
+               write_eeprom(cp->regs, offset, val, addr_len);
+               offset++;
+       }
+
+       while (i < len - 1) {
+               val = (u16)data[i++];
+               val |= (u16)data[i++] << 8;
+               write_eeprom(cp->regs, offset, val, addr_len);
+               offset++;
+       }
+
+       if (i < len) {
+               val = read_eeprom(cp->regs, offset, addr_len) & 0xff00;
+               val |= (u16)data[i];
+               write_eeprom(cp->regs, offset, val, addr_len);
+       }
+
+       spin_unlock_irq(&cp->lock);
+       return 0;
+}
+
 /* Put the board into D3cold state and wait for WakeUp signal */
 static void cp_set_d3_state (struct cp_private *cp)
 {
@@ -1666,7 +1810,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        struct cp_private *cp;
        int rc;
        void __iomem *regs;
-       long pciaddr;
+       resource_size_t pciaddr;
        unsigned int addr_len, i, pci_using_dac;
        u8 pci_rev;
 
@@ -1680,9 +1824,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
        if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
            pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev < 0x20) {
-               printk(KERN_ERR PFX "pci dev %s (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
-                      pci_name(pdev), pdev->vendor, pdev->device, pci_rev);
-               printk(KERN_ERR PFX "Try the \"8139too\" driver instead.\n");
+               dev_err(&pdev->dev,
+                          "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
+                          pdev->vendor, pdev->device, pci_rev);
+               dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n");
                return -ENODEV;
        }
 
@@ -1720,14 +1865,13 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        pciaddr = pci_resource_start(pdev, 1);
        if (!pciaddr) {
                rc = -EIO;
-               printk(KERN_ERR PFX "no MMIO resource for pci dev %s\n",
-                      pci_name(pdev));
+               dev_err(&pdev->dev, "no MMIO resource\n");
                goto err_out_res;
        }
        if (pci_resource_len(pdev, 1) < CP_REGS_SIZE) {
                rc = -EIO;
-               printk(KERN_ERR PFX "MMIO resource (%lx) too small on pci dev %s\n",
-                      pci_resource_len(pdev, 1), pci_name(pdev));
+               dev_err(&pdev->dev, "MMIO resource (%llx) too small\n",
+                      (unsigned long long)pci_resource_len(pdev, 1));
                goto err_out_res;
        }
 
@@ -1741,14 +1885,15 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
                rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
                if (rc) {
-                       printk(KERN_ERR PFX "No usable DMA configuration, "
-                              "aborting.\n");
+                       dev_err(&pdev->dev,
+                                  "No usable DMA configuration, aborting.\n");
                        goto err_out_res;
                }
                rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
                if (rc) {
-                       printk(KERN_ERR PFX "No usable consistent DMA configuration, "
-                              "aborting.\n");
+                       dev_err(&pdev->dev,
+                                  "No usable consistent DMA configuration, "
+                                  "aborting.\n");
                        goto err_out_res;
                }
        }
@@ -1759,8 +1904,9 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        regs = ioremap(pciaddr, CP_REGS_SIZE);
        if (!regs) {
                rc = -EIO;
-               printk(KERN_ERR PFX "Cannot map PCI MMIO (%lx@%lx) on pci dev %s\n",
-                      pci_resource_len(pdev, 1), pciaddr, pci_name(pdev));
+               dev_err(&pdev->dev, "Cannot map PCI MMIO (%Lx@%Lx)\n",
+                      (unsigned long long)pci_resource_len(pdev, 1),
+                      (unsigned long long)pciaddr);
                goto err_out_res;
        }
        dev->base_addr = (unsigned long) regs;
@@ -1773,6 +1919,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        for (i = 0; i < 3; i++)
                ((u16 *) (dev->dev_addr))[i] =
                    le16_to_cpu (read_eeprom (regs, i + 7, addr_len));
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
        dev->open = cp_open;
        dev->stop = cp_close;
@@ -1828,7 +1975,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        /* enable busmastering and memory-write-invalidate */
        pci_set_master(pdev);
 
-       if (cp->wol_enabled) cp_set_d3_state (cp);
+       if (cp->wol_enabled)
+               cp_set_d3_state (cp);
 
        return 0;
 
@@ -1850,11 +1998,10 @@ static void cp_remove_one (struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct cp_private *cp = netdev_priv(dev);
 
-       if (!dev)
-               BUG();
        unregister_netdev(dev);
        iounmap(cp->regs);
-       if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0);
+       if (cp->wol_enabled)
+               pci_set_power_state (pdev, PCI_D0);
        pci_release_regions(pdev);
        pci_clear_mwi(pdev);
        pci_disable_device(pdev);
@@ -1865,14 +2012,12 @@ static void cp_remove_one (struct pci_dev *pdev)
 #ifdef CONFIG_PM
 static int cp_suspend (struct pci_dev *pdev, pm_message_t state)
 {
-       struct net_device *dev;
-       struct cp_private *cp;
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct cp_private *cp = netdev_priv(dev);
        unsigned long flags;
 
-       dev = pci_get_drvdata (pdev);
-       cp  = netdev_priv(dev);
-
-       if (!dev || !netif_running (dev)) return 0;
+       if (!netif_running(dev))
+               return 0;
 
        netif_device_detach (dev);
        netif_stop_queue (dev);
@@ -1885,32 +2030,39 @@ static int cp_suspend (struct pci_dev *pdev, pm_message_t state)
 
        spin_unlock_irqrestore (&cp->lock, flags);
 
-       if (cp->pdev && cp->wol_enabled) {
-               pci_save_state (cp->pdev);
-               cp_set_d3_state (cp);
-       }
+       pci_save_state(pdev);
+       pci_enable_wake(pdev, pci_choose_state(pdev, state), cp->wol_enabled);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
        return 0;
 }
 
 static int cp_resume (struct pci_dev *pdev)
 {
-       struct net_device *dev;
-       struct cp_private *cp;
+       struct net_device *dev = pci_get_drvdata (pdev);
+       struct cp_private *cp = netdev_priv(dev);
+       unsigned long flags;
 
-       dev = pci_get_drvdata (pdev);
-       cp  = netdev_priv(dev);
+       if (!netif_running(dev))
+               return 0;
 
        netif_device_attach (dev);
-       
-       if (cp->pdev && cp->wol_enabled) {
-               pci_set_power_state (cp->pdev, PCI_D0);
-               pci_restore_state (cp->pdev);
-       }
-       
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       pci_enable_wake(pdev, PCI_D0, 0);
+
+       /* FIXME: sh*t may happen if the Rx ring buffer is depleted */
+       cp_init_rings_index (cp);
        cp_init_hw (cp);
        netif_start_queue (dev);
-       
+
+       spin_lock_irqsave (&cp->lock, flags);
+
+       mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+
+       spin_unlock_irqrestore (&cp->lock, flags);
+
        return 0;
 }
 #endif /* CONFIG_PM */
@@ -1931,7 +2083,7 @@ static int __init cp_init (void)
 #ifdef MODULE
        printk("%s", version);
 #endif
-       return pci_module_init (&cp_driver);
+       return pci_register_driver(&cp_driver);
 }
 
 static void __exit cp_exit (void)