drivers/net/: use DEFINE_PCI_DEVICE_TABLE()
[safe/jmp/linux-2.6] / drivers / net / tulip / uli526x.c
index e64bde4..d549042 100644 (file)
@@ -34,9 +34,9 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/dma-mapping.h>
+#include <linux/bitops.h>
 
 #include <asm/processor.h>
-#include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
@@ -168,9 +168,6 @@ struct uli526x_board_info {
        u8 wait_reset;                  /* Hardware failed, need to reset */
        struct timer_list timer;
 
-       /* System defined statistic counter */
-       struct net_device_stats stats;
-
        /* Driver defined statistic counter */
        unsigned long tx_fifo_underrun;
        unsigned long tx_loss_carrier;
@@ -203,7 +200,7 @@ enum uli526x_CR6_bits {
 
 /* Global variable declaration ----------------------------- */
 static int __devinitdata printed_version;
-static char version[] __devinitdata =
+static const char version[] __devinitconst =
        KERN_INFO DRV_NAME ": ULi M5261/M5263 net driver, version "
        DRV_VERSION " (" DRV_RELDATE ")\n";
 
@@ -218,13 +215,16 @@ static int mode = 8;
 
 /* function declaration ------------------------------------- */
 static int uli526x_open(struct net_device *);
-static int uli526x_start_xmit(struct sk_buff *, struct net_device *);
+static netdev_tx_t uli526x_start_xmit(struct sk_buff *,
+                                           struct net_device *);
 static int uli526x_stop(struct net_device *);
-static struct net_device_stats * uli526x_get_stats(struct net_device *);
 static void uli526x_set_filter_mode(struct net_device *);
 static const struct ethtool_ops netdev_ethtool_ops;
 static u16 read_srom_word(long, int);
 static irqreturn_t uli526x_interrupt(int, void *);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void uli526x_poll(struct net_device *dev);
+#endif
 static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
 static void allocate_rx_buffer(struct uli526x_board_info *);
 static void update_cr6(u32, unsigned long);
@@ -248,6 +248,19 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *);
 
 /* ULI526X network board routine ---------------------------- */
 
+static const struct net_device_ops netdev_ops = {
+       .ndo_open               = uli526x_open,
+       .ndo_stop               = uli526x_stop,
+       .ndo_start_xmit         = uli526x_start_xmit,
+       .ndo_set_multicast_list = uli526x_set_filter_mode,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = uli526x_poll,
+#endif
+};
+
 /*
  *     Search ULI526X board, allocate space and register it
  */
@@ -258,7 +271,6 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
        struct uli526x_board_info *db;  /* board information structure */
        struct net_device *dev;
        int i, err;
-       DECLARE_MAC_BUF(mac);
 
        ULI526X_DBUG(0, "uli526x_init_one()", 0);
 
@@ -271,7 +283,7 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
                return -ENOMEM;
        SET_NETDEV_DEV(dev, &pdev->dev);
 
-       if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
                printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n");
                err = -ENODEV;
                goto err_out_free;
@@ -333,12 +345,9 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
        pci_set_drvdata(pdev, dev);
 
        /* Register some necessary functions */
-       dev->open = &uli526x_open;
-       dev->hard_start_xmit = &uli526x_start_xmit;
-       dev->stop = &uli526x_stop;
-       dev->get_stats = &uli526x_get_stats;
-       dev->set_multicast_list = &uli526x_set_filter_mode;
+       dev->netdev_ops = &netdev_ops;
        dev->ethtool_ops = &netdev_ethtool_ops;
+
        spin_lock_init(&db->lock);
 
 
@@ -373,9 +382,9 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
        if (err)
                goto err_out_res;
 
-       printk(KERN_INFO "%s: ULi M%04lx at pci%s, %s, irq %d.\n",
+       printk(KERN_INFO "%s: ULi M%04lx at pci%s, %pM, irq %d.\n",
               dev->name,ent->driver_data >> 16,pci_name(pdev),
-              print_mac(mac, dev->dev_addr), dev->irq);
+              dev->dev_addr, dev->irq);
 
        pci_set_master(pdev);
 
@@ -434,10 +443,6 @@ static int uli526x_open(struct net_device *dev)
 
        ULI526X_DBUG(0, "uli526x_open", 0);
 
-       ret = request_irq(dev->irq, &uli526x_interrupt, IRQF_SHARED, dev->name, dev);
-       if (ret)
-               return ret;
-
        /* system variable init */
        db->cr6_data = CR6_DEFAULT | uli526x_cr6_user_set;
        db->tx_packet_cnt = 0;
@@ -456,6 +461,10 @@ static int uli526x_open(struct net_device *dev)
        /* Initialize ULI526X board */
        uli526x_init(dev);
 
+       ret = request_irq(dev->irq, uli526x_interrupt, IRQF_SHARED, dev->name, dev);
+       if (ret)
+               return ret;
+
        /* Active System Interface */
        netif_wake_queue(dev);
 
@@ -482,9 +491,11 @@ static void uli526x_init(struct net_device *dev)
        struct uli526x_board_info *db = netdev_priv(dev);
        unsigned long ioaddr = db->ioaddr;
        u8      phy_tmp;
+       u8      timeout;
        u16     phy_value;
        u16 phy_reg_reset;
 
+
        ULI526X_DBUG(0, "uli526x_init()", 0);
 
        /* Reset M526x MAC controller */
@@ -509,11 +520,19 @@ static void uli526x_init(struct net_device *dev)
        /* Parser SROM and media mode */
        db->media_mode = uli526x_media_mode;
 
-       /* Phyxcer capability setting */
+       /* phyxcer capability setting */
        phy_reg_reset = phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id);
        phy_reg_reset = (phy_reg_reset | 0x8000);
        phy_write(db->ioaddr, db->phy_addr, 0, phy_reg_reset, db->chip_id);
+
+       /* See IEEE 802.3-2002.pdf (Section 2, Chapter "22.2.4 Management
+        * functions") or phy data sheet for details on phy reset
+        */
        udelay(500);
+       timeout = 10;
+       while (timeout-- &&
+               phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id) & 0x8000)
+                       udelay(100);
 
        /* Process Phyxcer Media Mode */
        uli526x_set_phyxcer(db);
@@ -549,7 +568,8 @@ static void uli526x_init(struct net_device *dev)
  *     Send a packet to media from the upper layer.
  */
 
-static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t uli526x_start_xmit(struct sk_buff *skb,
+                                           struct net_device *dev)
 {
        struct uli526x_board_info *db = netdev_priv(dev);
        struct tx_desc *txptr;
@@ -564,7 +584,7 @@ static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (skb->len > MAX_PACKET_SIZE) {
                printk(KERN_ERR DRV_NAME ": big packet = %d\n", (u16)skb->len);
                dev_kfree_skb(skb);
-               return 0;
+               return NETDEV_TX_OK;
        }
 
        spin_lock_irqsave(&db->lock, flags);
@@ -573,7 +593,7 @@ static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) {
                spin_unlock_irqrestore(&db->lock, flags);
                printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_packet_cnt);
-               return 1;
+               return NETDEV_TX_BUSY;
        }
 
        /* Disable NIC interrupt */
@@ -606,7 +626,7 @@ static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* free this SKB */
        dev_kfree_skb(skb);
 
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 
@@ -664,11 +684,6 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id)
        unsigned long ioaddr = dev->base_addr;
        unsigned long flags;
 
-       if (!dev) {
-               ULI526X_DBUG(1, "uli526x_interrupt() without DEVICE arg", 0);
-               return IRQ_NONE;
-       }
-
        spin_lock_irqsave(&db->lock, flags);
        outl(0, ioaddr + DCR7);
 
@@ -676,8 +691,9 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id)
        db->cr5_data = inl(ioaddr + DCR5);
        outl(db->cr5_data, ioaddr + DCR5);
        if ( !(db->cr5_data & 0x180c1) ) {
-               spin_unlock_irqrestore(&db->lock, flags);
+               /* Restore CR7 to enable interrupt mask */
                outl(db->cr7_data, ioaddr + DCR7);
+               spin_unlock_irqrestore(&db->lock, flags);
                return IRQ_HANDLED;
        }
 
@@ -710,12 +726,20 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void uli526x_poll(struct net_device *dev)
+{
+       /* ISR grabs the irqsave lock, so this should be safe */
+       uli526x_interrupt(dev->irq, dev);
+}
+#endif
 
 /*
  *     Free TX resource after TX complete
  */
 
-static void uli526x_free_tx_pkt(struct net_device *dev, struct uli526x_board_info * db)
+static void uli526x_free_tx_pkt(struct net_device *dev,
+                               struct uli526x_board_info * db)
 {
        struct tx_desc *txptr;
        u32 tdes0;
@@ -729,15 +753,15 @@ static void uli526x_free_tx_pkt(struct net_device *dev, struct uli526x_board_inf
 
                /* A packet sent completed */
                db->tx_packet_cnt--;
-               db->stats.tx_packets++;
+               dev->stats.tx_packets++;
 
                /* Transmit statistic counter */
                if ( tdes0 != 0x7fffffff ) {
                        /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
-                       db->stats.collisions += (tdes0 >> 3) & 0xf;
-                       db->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff;
+                       dev->stats.collisions += (tdes0 >> 3) & 0xf;
+                       dev->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff;
                        if (tdes0 & TDES0_ERR_MASK) {
-                               db->stats.tx_errors++;
+                               dev->stats.tx_errors++;
                                if (tdes0 & 0x0002) {   /* UnderRun */
                                        db->tx_fifo_underrun++;
                                        if ( !(db->cr6_data & CR6_SFT) ) {
@@ -807,13 +831,13 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
                        if (rdes0 & 0x8000) {
                                /* This is a error packet */
                                //printk(DRV_NAME ": rdes0: %lx\n", rdes0);
-                               db->stats.rx_errors++;
+                               dev->stats.rx_errors++;
                                if (rdes0 & 1)
-                                       db->stats.rx_fifo_errors++;
+                                       dev->stats.rx_fifo_errors++;
                                if (rdes0 & 2)
-                                       db->stats.rx_crc_errors++;
+                                       dev->stats.rx_crc_errors++;
                                if (rdes0 & 0x80)
-                                       db->stats.rx_length_errors++;
+                                       dev->stats.rx_length_errors++;
                        }
 
                        if ( !(rdes0 & 0x8000) ||
@@ -836,9 +860,8 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
 
                                skb->protocol = eth_type_trans(skb, dev);
                                netif_rx(skb);
-                               dev->last_rx = jiffies;
-                               db->stats.rx_packets++;
-                               db->stats.rx_bytes += rxlen;
+                               dev->stats.rx_packets++;
+                               dev->stats.rx_bytes += rxlen;
 
                        } else {
                                /* Reuse SKB buffer when the packet is error */
@@ -855,25 +878,12 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
 
 
 /*
- *     Get statistics from driver.
- */
-
-static struct net_device_stats * uli526x_get_stats(struct net_device *dev)
-{
-       struct uli526x_board_info *db = netdev_priv(dev);
-
-       ULI526X_DBUG(0, "uli526x_get_stats", 0);
-       return &db->stats;
-}
-
-
-/*
  * Set ULI526X multicast address
  */
 
 static void uli526x_set_filter_mode(struct net_device * dev)
 {
-       struct uli526x_board_info *db = dev->priv;
+       struct uli526x_board_info *db = netdev_priv(dev);
        unsigned long flags;
 
        ULI526X_DBUG(0, "uli526x_set_filter_mode()", 0);
@@ -1363,6 +1373,12 @@ static void update_cr6(u32 cr6_data, unsigned long ioaddr)
  *     This setup frame initialize ULI526X address filter mode
  */
 
+#ifdef __BIG_ENDIAN
+#define FLT_SHIFT 16
+#else
+#define FLT_SHIFT 0
+#endif
+
 static void send_filter_frame(struct net_device *dev, int mc_cnt)
 {
        struct uli526x_board_info *db = netdev_priv(dev);
@@ -1379,27 +1395,27 @@ static void send_filter_frame(struct net_device *dev, int mc_cnt)
 
        /* Node address */
        addrptr = (u16 *) dev->dev_addr;
-       *suptr++ = addrptr[0];
-       *suptr++ = addrptr[1];
-       *suptr++ = addrptr[2];
+       *suptr++ = addrptr[0] << FLT_SHIFT;
+       *suptr++ = addrptr[1] << FLT_SHIFT;
+       *suptr++ = addrptr[2] << FLT_SHIFT;
 
        /* broadcast address */
-       *suptr++ = 0xffff;
-       *suptr++ = 0xffff;
-       *suptr++ = 0xffff;
+       *suptr++ = 0xffff << FLT_SHIFT;
+       *suptr++ = 0xffff << FLT_SHIFT;
+       *suptr++ = 0xffff << FLT_SHIFT;
 
        /* fit the multicast address */
        for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
                addrptr = (u16 *) mcptr->dmi_addr;
-               *suptr++ = addrptr[0];
-               *suptr++ = addrptr[1];
-               *suptr++ = addrptr[2];
+               *suptr++ = addrptr[0] << FLT_SHIFT;
+               *suptr++ = addrptr[1] << FLT_SHIFT;
+               *suptr++ = addrptr[2] << FLT_SHIFT;
        }
 
        for (; i<14; i++) {
-               *suptr++ = 0xffff;
-               *suptr++ = 0xffff;
-               *suptr++ = 0xffff;
+               *suptr++ = 0xffff << FLT_SHIFT;
+               *suptr++ = 0xffff << FLT_SHIFT;
+               *suptr++ = 0xffff << FLT_SHIFT;
        }
 
        /* prepare the setup frame */
@@ -1767,7 +1783,7 @@ static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id)
 }
 
 
-static struct pci_device_id uli526x_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(uli526x_pci_tbl) = {
        { 0x10B9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5261_ID },
        { 0x10B9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5263_ID },
        { 0, }