net: spread __net_init, __net_exit
[safe/jmp/linux-2.6] / drivers / net / davinci_emac.c
index a421ec0..33c4fe2 100644 (file)
@@ -330,6 +330,9 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DM646X_MAC_EOI_C0_RXEN    (0x01)
 #define EMAC_DM646X_MAC_EOI_C0_TXEN    (0x02)
 
+/* EMAC Stats Clear Mask */
+#define EMAC_STATS_CLR_MASK    (0xFFFFFFFF)
+
 /** net_buf_obj: EMAC network bufferdata structure
  *
  * EMAC network buffer data structure
@@ -2133,9 +2136,6 @@ static int emac_poll(struct napi_struct *napi, int budget)
        u32 status = 0;
        u32 num_pkts = 0;
 
-       if (!netif_running(ndev))
-               return 0;
-
        /* Check interrupt vectors and call packet processing */
        status = emac_read(EMAC_MACINVECTOR);
 
@@ -2214,7 +2214,7 @@ void emac_poll_controller(struct net_device *ndev)
        struct emac_priv *priv = netdev_priv(ndev);
 
        emac_int_disable(priv);
-       emac_irq(ndev->irq, priv);
+       emac_irq(ndev->irq, ndev);
        emac_int_enable(priv);
 }
 #endif
@@ -2272,7 +2272,7 @@ static int emac_mii_reset(struct mii_bus *bus)
        unsigned int clk_div;
        int mdio_bus_freq = emac_bus_frequency;
 
-       if (mdio_max_freq & mdio_bus_freq)
+       if (mdio_max_freq && mdio_bus_freq)
                clk_div = ((mdio_bus_freq / mdio_max_freq) - 1);
        else
                clk_div = 0xFF;
@@ -2544,40 +2544,49 @@ static int emac_dev_stop(struct net_device *ndev)
 static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
 {
        struct emac_priv *priv = netdev_priv(ndev);
+       u32 mac_control;
+       u32 stats_clear_mask;
 
        /* update emac hardware stats and reset the registers*/
 
+       mac_control = emac_read(EMAC_MACCONTROL);
+
+       if (mac_control & EMAC_MACCONTROL_GMIIEN)
+               stats_clear_mask = EMAC_STATS_CLR_MASK;
+       else
+               stats_clear_mask = 0;
+
        priv->net_dev_stats.multicast += emac_read(EMAC_RXMCASTFRAMES);
-       emac_write(EMAC_RXMCASTFRAMES, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXMCASTFRAMES, stats_clear_mask);
 
        priv->net_dev_stats.collisions += (emac_read(EMAC_TXCOLLISION) +
                                           emac_read(EMAC_TXSINGLECOLL) +
                                           emac_read(EMAC_TXMULTICOLL));
-       emac_write(EMAC_TXCOLLISION, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_TXSINGLECOLL, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_TXMULTICOLL, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_TXCOLLISION, stats_clear_mask);
+       emac_write(EMAC_TXSINGLECOLL, stats_clear_mask);
+       emac_write(EMAC_TXMULTICOLL, stats_clear_mask);
 
        priv->net_dev_stats.rx_length_errors += (emac_read(EMAC_RXOVERSIZED) +
                                                emac_read(EMAC_RXJABBER) +
                                                emac_read(EMAC_RXUNDERSIZED));
-       emac_write(EMAC_RXOVERSIZED, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_RXJABBER, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_RXUNDERSIZED, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXOVERSIZED, stats_clear_mask);
+       emac_write(EMAC_RXJABBER, stats_clear_mask);
+       emac_write(EMAC_RXUNDERSIZED, stats_clear_mask);
 
        priv->net_dev_stats.rx_over_errors += (emac_read(EMAC_RXSOFOVERRUNS) +
                                               emac_read(EMAC_RXMOFOVERRUNS));
-       emac_write(EMAC_RXSOFOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_RXMOFOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXSOFOVERRUNS, stats_clear_mask);
+       emac_write(EMAC_RXMOFOVERRUNS, stats_clear_mask);
 
        priv->net_dev_stats.rx_fifo_errors += emac_read(EMAC_RXDMAOVERRUNS);
-       emac_write(EMAC_RXDMAOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXDMAOVERRUNS, stats_clear_mask);
 
        priv->net_dev_stats.tx_carrier_errors +=
                emac_read(EMAC_TXCARRIERSENSE);
-       emac_write(EMAC_TXCARRIERSENSE, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_TXCARRIERSENSE, stats_clear_mask);
 
        priv->net_dev_stats.tx_fifo_errors = emac_read(EMAC_TXUNDERRUN);
-       emac_write(EMAC_TXUNDERRUN, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
 
        return &priv->net_dev_stats;
 }
@@ -2702,6 +2711,8 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        SET_ETHTOOL_OPS(ndev, &ethtool_ops);
        netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
 
+       clk_enable(emac_clk);
+
        /* register the network device */
        SET_NETDEV_DEV(ndev, &pdev->dev);
        rc = register_netdev(ndev);
@@ -2711,7 +2722,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
                goto netdev_reg_err;
        }
 
-       clk_enable(emac_clk);
 
        /* MII/Phy intialisation, mdio bus registration */
        emac_mii = mdiobus_alloc();
@@ -2751,6 +2761,7 @@ mdiobus_quit:
 
 netdev_reg_err:
 mdio_alloc_err:
+       clk_disable(emac_clk);
 no_irq_res:
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, res->end - res->start + 1);
@@ -2794,11 +2805,33 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
        return 0;
 }
 
+static
+int davinci_emac_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (netif_running(dev))
+               emac_dev_stop(dev);
+
+       clk_disable(emac_clk);
+
+       return 0;
+}
+
+static int davinci_emac_resume(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       clk_enable(emac_clk);
+
+       if (netif_running(dev))
+               emac_dev_open(dev);
+
+       return 0;
+}
+
 /**
  * davinci_emac_driver: EMAC platform driver structure
- *
- * We implement only probe and remove functions - suspend/resume and
- * others not supported by this module
  */
 static struct platform_driver davinci_emac_driver = {
        .driver = {
@@ -2807,6 +2840,8 @@ static struct platform_driver davinci_emac_driver = {
        },
        .probe = davinci_emac_probe,
        .remove = __devexit_p(davinci_emac_remove),
+       .suspend = davinci_emac_suspend,
+       .resume = davinci_emac_resume,
 };
 
 /**