Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6.git] / drivers / net / pxa168_eth.c
index 764aa90..c1bb05b 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2010 Marvell International Ltd.
  *             Sachin Sanap <ssanap@marvell.com>
+ *             Zhangfei Gao <zgao6@marvell.com>
  *             Philip Rakity <prakity@marvell.com>
  *             Mark Brown <markb@marvell.com>
  *
@@ -461,7 +462,7 @@ static u32 hash_function(unsigned char *mac_addr_orig)
  * pep - ETHERNET .
  * mac_addr - MAC address.
  * skip - if 1, skip this address.Used in case of deleting an entry which is a
- *       part of chain in the hash table.We cant just delete the entry since
+ *       part of chain in the hash table.We can't just delete the entry since
  *       that will break the chain.We need to defragment the tables time to
  *       time.
  * rd   - 0 Discard packet upon match.
@@ -501,7 +502,7 @@ static int add_del_hash_entry(struct pxa168_eth_private *pep,
         * Pick the appropriate table, start scanning for free/reusable
         * entries at the index obtained by hashing the specified MAC address
         */
-       start = (struct addr_table_entry *)(pep->htpr);
+       start = pep->htpr;
        entry = start + hash_function(mac_addr);
        for (i = 0; i < HOP_NUMBER; i++) {
                if (!(le32_to_cpu(entry->lo) & HASH_ENTRY_VALID)) {
@@ -652,15 +653,15 @@ static void eth_port_start(struct net_device *dev)
        /* Assignment of Tx CTRP of given queue */
        tx_curr_desc = pep->tx_curr_desc_q;
        wrl(pep, ETH_C_TX_DESC_1,
-           (u32) ((struct tx_desc *)pep->tx_desc_dma + tx_curr_desc));
+           (u32) (pep->tx_desc_dma + tx_curr_desc * sizeof(struct tx_desc)));
 
        /* Assignment of Rx CRDP of given queue */
        rx_curr_desc = pep->rx_curr_desc_q;
        wrl(pep, ETH_C_RX_DESC_0,
-           (u32) ((struct rx_desc *)pep->rx_desc_dma + rx_curr_desc));
+           (u32) (pep->rx_desc_dma + rx_curr_desc * sizeof(struct rx_desc)));
 
        wrl(pep, ETH_F_RX_DESC_0,
-           (u32) ((struct rx_desc *)pep->rx_desc_dma + rx_curr_desc));
+           (u32) (pep->rx_desc_dma + rx_curr_desc * sizeof(struct rx_desc)));
 
        /* Clear all interrupts */
        wrl(pep, INT_CAUSE, 0);
@@ -1266,13 +1267,16 @@ static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
        pep->tx_skb[tx_index] = skb;
        desc->byte_cnt = length;
        desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
+
+       skb_tx_timestamp(skb);
+
        wmb();
        desc->cmd_sts = BUF_OWNED_BY_DMA | TX_GEN_CRC | TX_FIRST_DESC |
                        TX_ZERO_PADDING | TX_LAST_DESC | TX_EN_INT;
        wmb();
        wrl(pep, SDMA_CMD, SDMA_CMD_TXDH | SDMA_CMD_ERD);
 
-       stats->tx_bytes += skb->len;
+       stats->tx_bytes += length;
        stats->tx_packets++;
        dev->trans_start = jiffies;
        if (pep->tx_ring_size - pep->tx_desc_count <= 1) {
@@ -1347,7 +1351,7 @@ static int pxa168_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr,
 {
        struct pxa168_eth_private *pep = netdev_priv(dev);
        if (pep->phy != NULL)
-               return phy_mii_ioctl(pep->phy, if_mii(ifr), cmd);
+               return phy_mii_ioctl(pep->phy, ifr, cmd);
 
        return -EOPNOTSUPP;
 }
@@ -1411,10 +1415,8 @@ static int ethernet_phy_setup(struct net_device *dev)
 {
        struct pxa168_eth_private *pep = netdev_priv(dev);
 
-       if (pep->pd != NULL) {
-               if (pep->pd->init)
-                       pep->pd->init();
-       }
+       if (pep->pd->init)
+               pep->pd->init();
        pep->phy = phy_scan(pep, pep->pd->phy_addr & 0x1f);
        if (pep->phy != NULL)
                phy_init(pep, pep->pd->speed, pep->pd->duplex);
@@ -1451,16 +1453,11 @@ static void pxa168_get_drvinfo(struct net_device *dev,
        strncpy(info->bus_info, "N/A", 32);
 }
 
-static u32 pxa168_get_link(struct net_device *dev)
-{
-       return !!netif_carrier_ok(dev);
-}
-
 static const struct ethtool_ops pxa168_ethtool_ops = {
        .get_settings = pxa168_get_settings,
        .set_settings = pxa168_set_settings,
        .get_drvinfo = pxa168_get_drvinfo,
-       .get_link = pxa168_get_link,
+       .get_link = ethtool_op_get_link,
 };
 
 static const struct net_device_ops pxa168_eth_netdev_ops = {
@@ -1496,7 +1493,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
        dev = alloc_etherdev(sizeof(struct pxa168_eth_private));
        if (!dev) {
                err = -ENOMEM;
-               goto out;
+               goto err_clk;
        }
 
        platform_set_drvdata(pdev, dev);
@@ -1506,12 +1503,12 @@ static int pxa168_eth_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res == NULL) {
                err = -ENODEV;
-               goto out;
+               goto err_netdev;
        }
        pep->base = ioremap(res->start, res->end - res->start + 1);
        if (pep->base == NULL) {
                err = -ENOMEM;
-               goto out;
+               goto err_netdev;
        }
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        BUG_ON(!res);
@@ -1548,7 +1545,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
        pep->smi_bus = mdiobus_alloc();
        if (pep->smi_bus == NULL) {
                err = -ENOMEM;
-               goto out;
+               goto err_base;
        }
        pep->smi_bus->priv = pep;
        pep->smi_bus->name = "pxa168_eth smi";
@@ -1557,31 +1554,31 @@ static int pxa168_eth_probe(struct platform_device *pdev)
        snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id);
        pep->smi_bus->parent = &pdev->dev;
        pep->smi_bus->phy_mask = 0xffffffff;
-       if (mdiobus_register(pep->smi_bus) < 0) {
-               err = -ENOMEM;
-               goto out;
-       }
+       err = mdiobus_register(pep->smi_bus);
+       if (err)
+               goto err_free_mdio;
+
        pxa168_init_hw(pep);
        err = ethernet_phy_setup(dev);
        if (err)
-               goto out;
+               goto err_mdiobus;
        SET_NETDEV_DEV(dev, &pdev->dev);
        err = register_netdev(dev);
        if (err)
-               goto out;
+               goto err_mdiobus;
        return 0;
-out:
-       if (pep->clk) {
-               clk_disable(pep->clk);
-               clk_put(pep->clk);
-               pep->clk = NULL;
-       }
-       if (pep->base) {
-               iounmap(pep->base);
-               pep->base = NULL;
-       }
-       if (dev)
-               free_netdev(dev);
+
+err_mdiobus:
+       mdiobus_unregister(pep->smi_bus);
+err_free_mdio:
+       mdiobus_free(pep->smi_bus);
+err_base:
+       iounmap(pep->base);
+err_netdev:
+       free_netdev(dev);
+err_clk:
+       clk_disable(clk);
+       clk_put(clk);
        return err;
 }
 
@@ -1605,8 +1602,10 @@ static int pxa168_eth_remove(struct platform_device *pdev)
 
        iounmap(pep->base);
        pep->base = NULL;
+       mdiobus_unregister(pep->smi_bus);
+       mdiobus_free(pep->smi_bus);
        unregister_netdev(dev);
-       flush_scheduled_work();
+       cancel_work_sync(&pep->tx_timeout_task);
        free_netdev(dev);
        platform_set_drvdata(pdev, NULL);
        return 0;