drivers/base: Convert dev->sem to mutex
[safe/jmp/linux-2.6] / drivers / net / smsc9420.c
index 2a8e9b7..6cdee6a 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/if_vlan.h>
 #include <linux/dma-mapping.h>
 #include <linux/crc32.h>
+#include <linux/slab.h>
 #include <asm/unaligned.h>
 #include "smsc9420.h"
 
@@ -80,7 +81,7 @@ struct smsc9420_pdata {
        int last_carrier;
 };
 
-static const struct pci_device_id smsc9420_id_table[] = {
+static DEFINE_PCI_DEVICE_TABLE(smsc9420_id_table) = {
        { PCI_VENDOR_ID_9420, PCI_DEVICE_ID_9420, PCI_ANY_ID, PCI_ANY_ID, },
        { 0, }
 };
@@ -252,6 +253,9 @@ static int smsc9420_ethtool_get_settings(struct net_device *dev,
 {
        struct smsc9420_pdata *pd = netdev_priv(dev);
 
+       if (!pd->phy_dev)
+               return -ENODEV;
+
        cmd->maxtxpkt = 1;
        cmd->maxrxpkt = 1;
        return phy_ethtool_gset(pd->phy_dev, cmd);
@@ -262,6 +266,9 @@ static int smsc9420_ethtool_set_settings(struct net_device *dev,
 {
        struct smsc9420_pdata *pd = netdev_priv(dev);
 
+       if (!pd->phy_dev)
+               return -ENODEV;
+
        return phy_ethtool_sset(pd->phy_dev, cmd);
 }
 
@@ -290,9 +297,40 @@ static void smsc9420_ethtool_set_msglevel(struct net_device *netdev, u32 data)
 static int smsc9420_ethtool_nway_reset(struct net_device *netdev)
 {
        struct smsc9420_pdata *pd = netdev_priv(netdev);
+
+       if (!pd->phy_dev)
+               return -ENODEV;
+
        return phy_start_aneg(pd->phy_dev);
 }
 
+static int smsc9420_ethtool_getregslen(struct net_device *dev)
+{
+       /* all smsc9420 registers plus all phy registers */
+       return 0x100 + (32 * sizeof(u32));
+}
+
+static void
+smsc9420_ethtool_getregs(struct net_device *dev, struct ethtool_regs *regs,
+                        void *buf)
+{
+       struct smsc9420_pdata *pd = netdev_priv(dev);
+       struct phy_device *phy_dev = pd->phy_dev;
+       unsigned int i, j = 0;
+       u32 *data = buf;
+
+       regs->version = smsc9420_reg_read(pd, ID_REV);
+       for (i = 0; i < 0x100; i += (sizeof(u32)))
+               data[j++] = smsc9420_reg_read(pd, i);
+
+       // cannot read phy registers if the net device is down
+       if (!phy_dev)
+               return;
+
+       for (i = 0; i <= 31; i++)
+               data[j++] = smsc9420_mii_read(phy_dev->bus, phy_dev->addr, i);
+}
+
 static void smsc9420_eeprom_enable_access(struct smsc9420_pdata *pd)
 {
        unsigned int temp = smsc9420_reg_read(pd, GPIO_CFG);
@@ -318,7 +356,7 @@ static int smsc9420_eeprom_send_cmd(struct smsc9420_pdata *pd, u32 op)
        do {
                msleep(1);
                e2cmd = smsc9420_reg_read(pd, E2P_CMD);
-       } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--));
+       } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (--timeout));
 
        if (!timeout) {
                smsc_info(HW, "TIMED OUT");
@@ -390,6 +428,7 @@ static int smsc9420_ethtool_get_eeprom(struct net_device *dev,
        }
 
        memcpy(data, &eeprom_data[eeprom->offset], len);
+       eeprom->magic = SMSC9420_EEPROM_MAGIC;
        eeprom->len = len;
        return 0;
 }
@@ -400,6 +439,9 @@ static int smsc9420_ethtool_set_eeprom(struct net_device *dev,
        struct smsc9420_pdata *pd = netdev_priv(dev);
        int ret;
 
+       if (eeprom->magic != SMSC9420_EEPROM_MAGIC)
+               return -EINVAL;
+
        smsc9420_eeprom_enable_access(pd);
        smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWEN_);
        ret = smsc9420_eeprom_write_location(pd, eeprom->offset, *data);
@@ -422,6 +464,8 @@ static const struct ethtool_ops smsc9420_ethtool_ops = {
        .get_eeprom_len = smsc9420_ethtool_get_eeprom_len,
        .get_eeprom = smsc9420_ethtool_get_eeprom,
        .set_eeprom = smsc9420_ethtool_set_eeprom,
+       .get_regs_len = smsc9420_ethtool_getregslen,
+       .get_regs = smsc9420_ethtool_getregs,
 };
 
 /* Sets the device MAC address to dev_addr */
@@ -473,7 +517,7 @@ static void smsc9420_check_mac_address(struct net_device *dev)
 static void smsc9420_stop_tx(struct smsc9420_pdata *pd)
 {
        u32 dmac_control, mac_cr, dma_intr_ena;
-       int timeOut = 1000;
+       int timeout = 1000;
 
        /* disable TX DMAC */
        dmac_control = smsc9420_reg_read(pd, DMAC_CONTROL);
@@ -481,13 +525,13 @@ static void smsc9420_stop_tx(struct smsc9420_pdata *pd)
        smsc9420_reg_write(pd, DMAC_CONTROL, dmac_control);
 
        /* Wait max 10ms for transmit process to stop */
-       while (timeOut--) {
+       while (--timeout) {
                if (smsc9420_reg_read(pd, DMAC_STATUS) & DMAC_STS_TS_)
                        break;
                udelay(10);
        }
 
-       if (!timeOut)
+       if (!timeout)
                smsc_warn(IFDOWN, "TX DMAC failed to stop");
 
        /* ACK Tx DMAC stop bit */
@@ -571,7 +615,7 @@ static void smsc9420_free_rx_ring(struct smsc9420_pdata *pd)
 
 static void smsc9420_stop_rx(struct smsc9420_pdata *pd)
 {
-       int timeOut = 1000;
+       int timeout = 1000;
        u32 mac_cr, dmac_control, dma_intr_ena;
 
        /* mask RX DMAC interrupts */
@@ -592,13 +636,13 @@ static void smsc9420_stop_rx(struct smsc9420_pdata *pd)
        smsc9420_pci_flush_write(pd);
 
        /* wait up to 10ms for receive to stop */
-       while (timeOut--) {
+       while (--timeout) {
                if (smsc9420_reg_read(pd, DMAC_STATUS) & DMAC_STS_RS_)
                        break;
                udelay(10);
        }
 
-       if (!timeOut)
+       if (!timeout)
                smsc_warn(IFDOWN, "RX DMAC did not stop! timeout.");
 
        /* ACK the Rx DMAC stop bit */
@@ -641,7 +685,7 @@ static irqreturn_t smsc9420_isr(int irq, void *dev_id)
                        smsc9420_pci_flush_write(pd);
 
                        ints_to_clear |= (DMAC_STS_RX_ | DMAC_STS_NIS_);
-                       netif_rx_schedule(pd->dev, &pd->napi);
+                       napi_schedule(&pd->napi);
                }
 
                if (ints_to_clear)
@@ -778,7 +822,7 @@ static void smsc9420_rx_handoff(struct smsc9420_pdata *pd, const int index,
        if (pd->rx_csum) {
                u16 hw_csum = get_unaligned_le16(skb_tail_pointer(skb) +
                        NET_IP_ALIGN + packet_length + 4);
-               put_unaligned_le16(cpu_to_le16(hw_csum), &skb->csum);
+               put_unaligned_le16(hw_csum, &skb->csum);
                skb->ip_summed = CHECKSUM_COMPLETE;
        }
 
@@ -788,7 +832,6 @@ static void smsc9420_rx_handoff(struct smsc9420_pdata *pd, const int index,
        skb->protocol = eth_type_trans(skb, dev);
 
        netif_receive_skb(skb);
-       dev->last_rx = jiffies;
 }
 
 static int smsc9420_alloc_rx_buffer(struct smsc9420_pdata *pd, int index)
@@ -864,7 +907,7 @@ static int smsc9420_rx_poll(struct napi_struct *napi, int budget)
        smsc9420_pci_flush_write(pd);
 
        if (work_done < budget) {
-               netif_rx_complete(dev, &pd->napi);
+               napi_complete(&pd->napi);
 
                /* re-enable RX DMA interrupts */
                dma_intr_ena = smsc9420_reg_read(pd, DMAC_INTR_ENA);
@@ -939,7 +982,8 @@ static void smsc9420_complete_tx(struct net_device *dev)
        }
 }
 
-static int smsc9420_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t smsc9420_hard_start_xmit(struct sk_buff *skb,
+                                           struct net_device *dev)
 {
        struct smsc9420_pdata *pd = netdev_priv(dev);
        dma_addr_t mapping;
@@ -990,8 +1034,6 @@ static int smsc9420_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        smsc9420_reg_write(pd, TX_POLL_DEMAND, 1);
        smsc9420_pci_flush_write(pd);
 
-       dev->trans_start = jiffies;
-
        return NETDEV_TX_OK;
 }
 
@@ -1019,13 +1061,13 @@ static void smsc9420_set_multicast_list(struct net_device *dev)
                mac_cr &= (~MAC_CR_PRMS_);
                mac_cr |= MAC_CR_MCPAS_;
                mac_cr &= (~MAC_CR_HPFILT_);
-       } else if (dev->mc_count > 0) {
-               struct dev_mc_list *mc_list = dev->mc_list;
+       } else if (!netdev_mc_empty(dev)) {
+               struct netdev_hw_addr *ha;
                u32 hash_lo = 0, hash_hi = 0;
 
                smsc_dbg(HW, "Multicast filter enabled");
-               while (mc_list) {
-                       u32 bit_num = smsc9420_hash(mc_list->dmi_addr);
+               netdev_for_each_mc_addr(ha, dev) {
+                       u32 bit_num = smsc9420_hash(ha->addr);
                        u32 mask = 1 << (bit_num & 0x1F);
 
                        if (bit_num & 0x20)
@@ -1033,7 +1075,6 @@ static void smsc9420_set_multicast_list(struct net_device *dev)
                        else
                                hash_lo |= mask;
 
-                       mc_list = mc_list->next;
                }
                smsc9420_reg_write(pd, HASHH, hash_hi);
                smsc9420_reg_write(pd, HASHL, hash_lo);
@@ -1055,28 +1096,6 @@ static void smsc9420_set_multicast_list(struct net_device *dev)
        smsc9420_pci_flush_write(pd);
 }
 
-static u8 smsc9420_resolve_flowctrl_fulldplx(u16 lcladv, u16 rmtadv)
-{
-       u8 cap = 0;
-
-       if (lcladv & ADVERTISE_PAUSE_CAP) {
-               if (lcladv & ADVERTISE_PAUSE_ASYM) {
-                       if (rmtadv & LPA_PAUSE_CAP)
-                               cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
-                       else if (rmtadv & LPA_PAUSE_ASYM)
-                               cap = FLOW_CTRL_RX;
-               } else {
-                       if (rmtadv & LPA_PAUSE_CAP)
-                               cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
-               }
-       } else if (lcladv & ADVERTISE_PAUSE_ASYM) {
-               if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM))
-                       cap = FLOW_CTRL_TX;
-       }
-
-       return cap;
-}
-
 static void smsc9420_phy_update_flowcontrol(struct smsc9420_pdata *pd)
 {
        struct phy_device *phy_dev = pd->phy_dev;
@@ -1085,7 +1104,7 @@ static void smsc9420_phy_update_flowcontrol(struct smsc9420_pdata *pd)
        if (phy_dev->duplex == DUPLEX_FULL) {
                u16 lcladv = phy_read(phy_dev, MII_ADVERTISE);
                u16 rmtadv = phy_read(phy_dev, MII_LPA);
-               u8 cap = smsc9420_resolve_flowctrl_fulldplx(lcladv, rmtadv);
+               u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
 
                if (cap & FLOW_CTRL_RX)
                        flow = 0xFFFF0002;
@@ -1153,8 +1172,8 @@ static int smsc9420_mii_probe(struct net_device *dev)
        smsc_info(PROBE, "PHY addr %d, phy_id 0x%08X", phydev->addr,
                phydev->phy_id);
 
-       phydev = phy_connect(dev, phydev->dev.bus_id,
-               &smsc9420_phy_adjust_link, 0, PHY_INTERFACE_MODE_MII);
+       phydev = phy_connect(dev, dev_name(&phydev->dev),
+               smsc9420_phy_adjust_link, 0, PHY_INTERFACE_MODE_MII);
 
        if (IS_ERR(phydev)) {
                pr_err("%s: Could not attach to PHY\n", dev->name);
@@ -1162,7 +1181,7 @@ static int smsc9420_mii_probe(struct net_device *dev)
        }
 
        pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
-               dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
+               dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
 
        /* mask with MAC supported features */
        phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
@@ -1327,7 +1346,7 @@ static int smsc9420_open(struct net_device *dev)
 
        netif_carrier_off(dev);
 
-       /* disable, mask and acknowlege all interrupts */
+       /* disable, mask and acknowledge all interrupts */
        spin_lock_irqsave(&pd->int_lock, flags);
        int_cfg = smsc9420_reg_read(pd, INT_CFG) & (~INT_CFG_IRQ_EN_);
        smsc9420_reg_write(pd, INT_CFG, int_cfg);
@@ -1375,6 +1394,7 @@ static int smsc9420_open(struct net_device *dev)
 
        /* test the IRQ connection to the ISR */
        smsc_dbg(IFUP, "Testing ISR using IRQ %d", dev->irq);
+       pd->software_irq_signal = false;
 
        spin_lock_irqsave(&pd->int_lock, flags);
        /* configure interrupt deassertion timer and enable interrupts */
@@ -1390,8 +1410,6 @@ static int smsc9420_open(struct net_device *dev)
        smsc9420_pci_flush_write(pd);
 
        timeout = 1000;
-       pd->software_irq_signal = false;
-       smp_wmb();
        while (timeout--) {
                if (pd->software_irq_signal)
                        break;
@@ -1548,6 +1566,7 @@ static const struct net_device_ops smsc9420_netdev_ops = {
        .ndo_set_multicast_list = smsc9420_set_multicast_list,
        .ndo_do_ioctl           = smsc9420_do_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = smsc9420_poll_controller,
 #endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -1591,7 +1610,7 @@ smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto out_free_netdev_2;
        }
 
-       if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
                printk(KERN_ERR "No usable DMA configuration, aborting.\n");
                goto out_free_regions_3;
        }