drivers/base: Convert dev->sem to mutex
[safe/jmp/linux-2.6] / drivers / net / tsi108_eth.c
index 0bfc2c9..a03730b 100644 (file)
@@ -36,8 +36,8 @@
 #include <linux/net.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/ethtool.h>
 #include <linux/skbuff.h>
-#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
 #include <linux/crc32.h>
@@ -47,7 +47,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/timer.h>
 #include <linux/platform_device.h>
-#include <linux/etherdevice.h>
+#include <linux/gfp.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -79,9 +79,13 @@ struct tsi108_prv_data {
        void  __iomem *regs;    /* Base of normal regs */
        void  __iomem *phyregs; /* Base of register bank used for PHY access */
 
+       struct net_device *dev;
+       struct napi_struct napi;
+
        unsigned int phy;               /* Index of PHY for this interface */
        unsigned int irq_num;
        unsigned int id;
+       unsigned int phy_type;
 
        struct timer_list timer;/* Timer that triggers the check phy function */
        unsigned int rxtail;    /* Next entry in rxring to read */
@@ -158,6 +162,7 @@ static struct platform_driver tsi_eth_driver = {
        .remove = tsi108_ether_remove,
        .driver = {
                .name = "tsi-ethernet",
+               .owner = THIS_MODULE,
        },
 };
 
@@ -258,7 +263,7 @@ static inline void tsi108_write_tbi(struct tsi108_prv_data *data,
                        return;
                udelay(10);
        }
-       printk(KERN_ERR "%s function time out \n", __FUNCTION__);
+       printk(KERN_ERR "%s function time out\n", __func__);
 }
 
 static int mii_speed(struct mii_if_info *mii)
@@ -294,18 +299,11 @@ static void tsi108_check_phy(struct net_device *dev)
        u32 speed;
        unsigned long flags;
 
-       /* Do a dummy read, as for some reason the first read
-        * after a link becomes up returns link down, even if
-        * it's been a while since the link came up.
-        */
-
        spin_lock_irqsave(&phy_lock, flags);
 
        if (!data->phy_ok)
                goto out;
 
-       tsi108_read_mii(data, MII_BMSR);
-
        duplex = mii_check_media(&data->mii_if, netif_msg_link(data), data->init_media);
        data->init_media = 0;
 
@@ -342,22 +340,21 @@ static void tsi108_check_phy(struct net_device *dev)
 
                        TSI_WRITE(TSI108_MAC_CFG2, mac_cfg2_reg);
                        TSI_WRITE(TSI108_EC_PORTCTRL, portctrl_reg);
+               }
 
-                       if (data->link_up == 0) {
-                               /* The manual says it can take 3-4 usecs for the speed change
-                                * to take effect.
-                                */
-                               udelay(5);
+               if (data->link_up == 0) {
+                       /* The manual says it can take 3-4 usecs for the speed change
+                        * to take effect.
+                        */
+                       udelay(5);
 
-                               spin_lock(&data->txlock);
-                               if (is_valid_ether_addr(dev->dev_addr) && data->txfree)
-                                       netif_wake_queue(dev);
+                       spin_lock(&data->txlock);
+                       if (is_valid_ether_addr(dev->dev_addr) && data->txfree)
+                               netif_wake_queue(dev);
 
-                               data->link_up = 1;
-                               spin_unlock(&data->txlock);
-                       }
+                       data->link_up = 1;
+                       spin_unlock(&data->txlock);
                }
-
        } else {
                if (data->link_up == 1) {
                        netif_stop_queue(dev);
@@ -707,8 +704,8 @@ static int tsi108_send_packet(struct sk_buff * skb, struct net_device *dev)
 
                if (i == 0) {
                        data->txring[tx].buf0 = dma_map_single(NULL, skb->data,
-                                       skb->len - skb->data_len, DMA_TO_DEVICE);
-                       data->txring[tx].len = skb->len - skb->data_len;
+                                       skb_headlen(skb), DMA_TO_DEVICE);
+                       data->txring[tx].len = skb_headlen(skb);
                        misc |= TSI108_TX_SOF;
                } else {
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
@@ -791,7 +788,6 @@ static int tsi108_complete_rx(struct net_device *dev, int budget)
                skb_put(skb, data->rxring[rx].len);
                skb->protocol = eth_type_trans(skb, dev);
                netif_receive_skb(skb);
-               dev->last_rx = jiffies;
        }
 
        return done;
@@ -806,12 +802,11 @@ static int tsi108_refill_rx(struct net_device *dev, int budget)
                int rx = data->rxhead;
                struct sk_buff *skb;
 
-               data->rxskbs[rx] = skb = dev_alloc_skb(TSI108_RXBUF_SIZE + 2);
+               skb = netdev_alloc_skb_ip_align(dev, TSI108_RXBUF_SIZE);
+               data->rxskbs[rx] = skb;
                if (!skb)
                        break;
 
-               skb_reserve(skb, 2); /* Align the data on a 4-byte boundary. */
-
                data->rxring[rx].buf0 = dma_map_single(NULL, skb->data,
                                                        TSI108_RX_SKB_SIZE,
                                                        DMA_FROM_DEVICE);
@@ -836,13 +831,13 @@ static int tsi108_refill_rx(struct net_device *dev, int budget)
        return done;
 }
 
-static int tsi108_poll(struct net_device *dev, int *budget)
+static int tsi108_poll(struct napi_struct *napi, int budget)
 {
-       struct tsi108_prv_data *data = netdev_priv(dev);
+       struct tsi108_prv_data *data = container_of(napi, struct tsi108_prv_data, napi);
+       struct net_device *dev = data->dev;
        u32 estat = TSI_READ(TSI108_EC_RXESTAT);
        u32 intstat = TSI_READ(TSI108_EC_INTSTAT);
-       int total_budget = min(*budget, dev->quota);
-       int num_received = 0, num_filled = 0, budget_used;
+       int num_received = 0, num_filled = 0;
 
        intstat &= TSI108_INT_RXQUEUE0 | TSI108_INT_RXTHRESH |
            TSI108_INT_RXOVERRUN | TSI108_INT_RXERROR | TSI108_INT_RXWAIT;
@@ -851,7 +846,7 @@ static int tsi108_poll(struct net_device *dev, int *budget)
        TSI_WRITE(TSI108_EC_INTSTAT, intstat);
 
        if (data->rxpending || (estat & TSI108_EC_RXESTAT_Q0_DESCINT))
-               num_received = tsi108_complete_rx(dev, total_budget);
+               num_received = tsi108_complete_rx(dev, budget);
 
        /* This should normally fill no more slots than the number of
         * packets received in tsi108_complete_rx().  The exception
@@ -866,7 +861,7 @@ static int tsi108_poll(struct net_device *dev, int *budget)
         */
 
        if (data->rxfree < TSI108_RXRING_LEN)
-               num_filled = tsi108_refill_rx(dev, total_budget * 2);
+               num_filled = tsi108_refill_rx(dev, budget * 2);
 
        if (intstat & TSI108_INT_RXERROR) {
                u32 err = TSI_READ(TSI108_EC_RXERR);
@@ -889,14 +884,9 @@ static int tsi108_poll(struct net_device *dev, int *budget)
                spin_unlock_irq(&data->misclock);
        }
 
-       budget_used = max(num_received, num_filled / 2);
-
-       *budget -= budget_used;
-       dev->quota -= budget_used;
-
-       if (budget_used != total_budget) {
+       if (num_received < budget) {
                data->rxpending = 0;
-               netif_rx_complete(dev);
+               napi_complete(napi);
 
                TSI_WRITE(TSI108_EC_INTMASK,
                                     TSI_READ(TSI108_EC_INTMASK)
@@ -905,14 +895,11 @@ static int tsi108_poll(struct net_device *dev, int *budget)
                                         TSI108_INT_RXOVERRUN |
                                         TSI108_INT_RXERROR |
                                         TSI108_INT_RXWAIT));
-
-               /* IRQs are level-triggered, so no need to re-check */
-               return 0;
        } else {
                data->rxpending = 1;
        }
 
-       return 1;
+       return num_received;
 }
 
 static void tsi108_rx_int(struct net_device *dev)
@@ -926,11 +913,11 @@ static void tsi108_rx_int(struct net_device *dev)
         *
         * This can happen if this code races with tsi108_poll(), which masks
         * the interrupts after tsi108_irq_one() read the mask, but before
-        * netif_rx_schedule is called.  It could also happen due to calls
+        * napi_schedule is called.  It could also happen due to calls
         * from tsi108_check_rxring().
         */
 
-       if (netif_rx_schedule_prep(dev)) {
+       if (napi_schedule_prep(&data->napi)) {
                /* Mask, rather than ack, the receive interrupts.  The ack
                 * will happen in tsi108_poll().
                 */
@@ -941,7 +928,7 @@ static void tsi108_rx_int(struct net_device *dev)
                                     | TSI108_INT_RXTHRESH |
                                     TSI108_INT_RXOVERRUN | TSI108_INT_RXERROR |
                                     TSI108_INT_RXWAIT);
-               __netif_rx_schedule(dev);
+               __napi_schedule(&data->napi);
        } else {
                if (!netif_running(dev)) {
                        /* This can happen if an interrupt occurs while the
@@ -1069,7 +1056,7 @@ static void tsi108_stop_ethernet(struct net_device *dev)
                        return;
                udelay(10);
        }
-       printk(KERN_ERR "%s function time out \n", __FUNCTION__);
+       printk(KERN_ERR "%s function time out\n", __func__);
 }
 
 static void tsi108_reset_ether(struct tsi108_prv_data * data)
@@ -1143,7 +1130,9 @@ static int tsi108_get_mac(struct net_device *dev)
        }
 
        if (!is_valid_ether_addr(dev->dev_addr)) {
-               printk("KERN_ERR: word1: %08x, word2: %08x\n", word1, word2);
+               printk(KERN_ERR
+                      "%s: Invalid MAC address. word1: %08x, word2: %08x\n",
+                      dev->name, word1, word2);
                return -EINVAL;
        }
 
@@ -1195,29 +1184,19 @@ static void tsi108_set_rx_mode(struct net_device *dev)
 
        rxcfg &= ~(TSI108_EC_RXCFG_UFE | TSI108_EC_RXCFG_MFE);
 
-       if (dev->flags & IFF_ALLMULTI || dev->mc_count) {
+       if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) {
                int i;
-               struct dev_mc_list *mc = dev->mc_list;
+               struct netdev_hw_addr *ha;
                rxcfg |= TSI108_EC_RXCFG_MFE | TSI108_EC_RXCFG_MC_HASH;
 
                memset(data->mc_hash, 0, sizeof(data->mc_hash));
 
-               while (mc) {
+               netdev_for_each_mc_addr(ha, dev) {
                        u32 hash, crc;
 
-                       if (mc->dmi_addrlen == 6) {
-                               crc = ether_crc(6, mc->dmi_addr);
-                               hash = crc >> 23;
-
-                               __set_bit(hash, &data->mc_hash[0]);
-                       } else {
-                               printk(KERN_ERR
-                                      "%s: got multicast address of length %d "
-                                      "instead of 6.\n", dev->name,
-                                      mc->dmi_addrlen);
-                       }
-
-                       mc = mc->next;
+                       crc = ether_crc(6, ha->addr);
+                       hash = crc >> 23;
+                       __set_bit(hash, &data->mc_hash[0]);
                }
 
                TSI_WRITE(TSI108_EC_HASHADDR,
@@ -1248,19 +1227,19 @@ static void tsi108_init_phy(struct net_device *dev)
        spin_lock_irqsave(&phy_lock, flags);
 
        tsi108_write_mii(data, MII_BMCR, BMCR_RESET);
-       while (i--){
+       while (--i) {
                if(!(tsi108_read_mii(data, MII_BMCR) & BMCR_RESET))
                        break;
                udelay(10);
        }
        if (i == 0)
-               printk(KERN_ERR "%s function time out \n", __FUNCTION__);
+               printk(KERN_ERR "%s function time out\n", __func__);
 
-#if (TSI108_PHY_TYPE == PHY_BCM54XX)   /* Broadcom BCM54xx PHY */
-       tsi108_write_mii(data, 0x09, 0x0300);
-       tsi108_write_mii(data, 0x10, 0x1020);
-       tsi108_write_mii(data, 0x1c, 0x8c00);
-#endif
+       if (data->phy_type == TSI108_PHY_BCM54XX) {
+               tsi108_write_mii(data, 0x09, 0x0300);
+               tsi108_write_mii(data, 0x10, 0x1020);
+               tsi108_write_mii(data, 0x1c, 0x8c00);
+       }
 
        tsi108_write_mii(data,
                         MII_BMCR,
@@ -1279,12 +1258,11 @@ static void tsi108_init_phy(struct net_device *dev)
         * PHY_STAT register before the link up status bit is set.
         */
 
-       data->link_up = 1;
+       data->link_up = 0;
 
        while (!((phyval = tsi108_read_mii(data, MII_BMSR)) &
                 BMSR_LSTATUS)) {
                if (i++ > (MII_READ_DELAY / 10)) {
-                       data->link_up = 0;
                        break;
                }
                spin_unlock_irqrestore(&phy_lock, flags);
@@ -1292,6 +1270,7 @@ static void tsi108_init_phy(struct net_device *dev)
                spin_lock_irqsave(&phy_lock, flags);
        }
 
+       data->mii_if.supports_gmii = mii_check_gmii_support(&data->mii_if);
        printk(KERN_DEBUG "PHY_STAT reg contains %08x\n", phyval);
        data->phy_ok = 1;
        data->init_media = 1;
@@ -1363,8 +1342,9 @@ static int tsi108_open(struct net_device *dev)
        data->rxhead = 0;
 
        for (i = 0; i < TSI108_RXRING_LEN; i++) {
-               struct sk_buff *skb = dev_alloc_skb(TSI108_RXBUF_SIZE + NET_IP_ALIGN);
+               struct sk_buff *skb;
 
+               skb = netdev_alloc_skb_ip_align(dev, TSI108_RXBUF_SIZE);
                if (!skb) {
                        /* Bah.  No memory for now, but maybe we'll get
                         * some more later.
@@ -1378,8 +1358,6 @@ static int tsi108_open(struct net_device *dev)
                }
 
                data->rxskbs[i] = skb;
-               /* Align the payload on a 4-byte boundary */
-               skb_reserve(skb, 2);
                data->rxskbs[i] = skb;
                data->rxring[i].buf0 = virt_to_phys(data->rxskbs[i]->data);
                data->rxring[i].misc = TSI108_RX_OWN | TSI108_RX_INT;
@@ -1400,6 +1378,8 @@ static int tsi108_open(struct net_device *dev)
        TSI_WRITE(TSI108_EC_TXQ_PTRLOW, data->txdma);
        tsi108_init_phy(dev);
 
+       napi_enable(&data->napi);
+
        setup_timer(&data->timer, tsi108_timed_checker, (unsigned long)dev);
        mod_timer(&data->timer, jiffies + 1);
 
@@ -1424,6 +1404,7 @@ static int tsi108_close(struct net_device *dev)
        struct tsi108_prv_data *data = netdev_priv(dev);
 
        netif_stop_queue(dev);
+       napi_disable(&data->napi);
 
        del_timer_sync(&data->timer);
 
@@ -1443,7 +1424,6 @@ static int tsi108_close(struct net_device *dev)
                dev_kfree_skb(skb);
        }
 
-       synchronize_irq(data->irq_num);
        free_irq(data->irq_num, dev);
 
        /* Discard the RX ring. */
@@ -1529,12 +1509,58 @@ static void tsi108_init_mac(struct net_device *dev)
        TSI_WRITE(TSI108_EC_INTMASK, ~0);
 }
 
+static int tsi108_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct tsi108_prv_data *data = netdev_priv(dev);
+       unsigned long flags;
+       int rc;
+
+       spin_lock_irqsave(&data->txlock, flags);
+       rc = mii_ethtool_gset(&data->mii_if, cmd);
+       spin_unlock_irqrestore(&data->txlock, flags);
+
+       return rc;
+}
+
+static int tsi108_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct tsi108_prv_data *data = netdev_priv(dev);
+       unsigned long flags;
+       int rc;
+
+       spin_lock_irqsave(&data->txlock, flags);
+       rc = mii_ethtool_sset(&data->mii_if, cmd);
+       spin_unlock_irqrestore(&data->txlock, flags);
+
+       return rc;
+}
+
 static int tsi108_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct tsi108_prv_data *data = netdev_priv(dev);
+       if (!netif_running(dev))
+               return -EINVAL;
        return generic_mii_ioctl(&data->mii_if, if_mii(rq), cmd, NULL);
 }
 
+static const struct ethtool_ops tsi108_ethtool_ops = {
+       .get_link       = ethtool_op_get_link,
+       .get_settings   = tsi108_get_settings,
+       .set_settings   = tsi108_set_settings,
+};
+
+static const struct net_device_ops tsi108_netdev_ops = {
+       .ndo_open               = tsi108_open,
+       .ndo_stop               = tsi108_close,
+       .ndo_start_xmit         = tsi108_send_packet,
+       .ndo_set_multicast_list = tsi108_set_rx_mode,
+       .ndo_get_stats          = tsi108_get_stats,
+       .ndo_do_ioctl           = tsi108_do_ioctl,
+       .ndo_set_mac_address    = tsi108_set_mac,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+};
+
 static int
 tsi108_init_one(struct platform_device *pdev)
 {
@@ -1561,6 +1587,7 @@ tsi108_init_one(struct platform_device *pdev)
 
        printk("tsi108_eth%d: probe...\n", pdev->id);
        data = netdev_priv(dev);
+       data->dev = dev;
 
        pr_debug("tsi108_eth%d:regs:phyresgs:phy:irq_num=0x%x:0x%x:0x%x:0x%x\n",
                        pdev->id, einfo->regs, einfo->phyregs,
@@ -1584,20 +1611,14 @@ tsi108_init_one(struct platform_device *pdev)
        data->mii_if.phy_id = einfo->phy;
        data->mii_if.phy_id_mask = 0x1f;
        data->mii_if.reg_num_mask = 0x1f;
-       data->mii_if.supports_gmii = mii_check_gmii_support(&data->mii_if);
 
        data->phy = einfo->phy;
+       data->phy_type = einfo->phy_type;
        data->irq_num = einfo->irq_num;
        data->id = pdev->id;
-       dev->open = tsi108_open;
-       dev->stop = tsi108_close;
-       dev->hard_start_xmit = tsi108_send_packet;
-       dev->set_mac_address = tsi108_set_mac;
-       dev->set_multicast_list = tsi108_set_rx_mode;
-       dev->get_stats = tsi108_get_stats;
-       dev->poll = tsi108_poll;
-       dev->do_ioctl = tsi108_do_ioctl;
-       dev->weight = 64;  /* 64 is more suitable for GigE interface - klai */
+       netif_napi_add(dev, &data->napi, tsi108_poll, 64);
+       dev->netdev_ops = &tsi108_netdev_ops;
+       dev->ethtool_ops = &tsi108_ethtool_ops;
 
        /* Apparently, the Linux networking code won't use scatter-gather
         * if the hardware doesn't do checksums.  However, it's faster
@@ -1608,7 +1629,6 @@ tsi108_init_one(struct platform_device *pdev)
         */
 
        dev->features = NETIF_F_HIGHDMA;
-       SET_MODULE_OWNER(dev);
 
        spin_lock_init(&data->txlock);
        spin_lock_init(&data->misclock);
@@ -1630,10 +1650,9 @@ tsi108_init_one(struct platform_device *pdev)
                goto register_fail;
        }
 
-       printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: "
-              "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
-              dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-              dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+       platform_set_drvdata(pdev, dev);
+       printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %pM\n",
+              dev->name, dev->dev_addr);
 #ifdef DEBUG
        data->msg_enable = DEBUG;
        dump_eth_one(dev);
@@ -1704,3 +1723,4 @@ module_exit(tsi108_ether_exit);
 MODULE_AUTHOR("Tundra Semiconductor Corporation");
 MODULE_DESCRIPTION("Tsi108 Gigabit Ethernet driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:tsi-ethernet");