This is a first attempt to add PM support to the PPC 440 emac 
driver.  Still needed are code to take care of the PHY chip, 
and to support wake-on-lan.  Any comments on how to do 
those would be most welcome.

The 'PM support for Ebony' patch I posted can be used to test 
on that platform.

-Geoff

* emac-pm.patch

Signed-off-by: Geoff Levand <geoffrey.levand at am.sony.com> for CELF

--

Index: linux-2.6.12-bhpm/drivers/net/ibm_emac/ibm_emac_core.c
===================================================================
--- linux-2.6.12-bhpm.orig/drivers/net/ibm_emac/ibm_emac_core.c 2005-06-02 
15:09:23.000000000 -0700
+++ linux-2.6.12-bhpm/drivers/net/ibm_emac/ibm_emac_core.c      2005-06-02 
17:11:02.000000000 -0700
@@ -1306,7 +1306,7 @@
        ep->ack_slot = 0;
 }
 
-static void emac_reset_configure(struct ocp_enet_private *fep)
+static void emac_reset(struct ocp_enet_private *fep)
 {
        emac_t *emacp = fep->emacp;
        int i;
@@ -1338,6 +1338,14 @@
 
        /* Switch IRQs off for now */
        out_be32(&emacp->em0iser, 0);
+}
+
+static void emac_reset_configure(struct ocp_enet_private *fep)
+{
+       emac_t *emacp = fep->emacp;
+
+       /* Reset EMAC */
+       emac_reset(fep);
 
        /* Configure MAL rx channel */
        mal_set_rcbs(fep->mal, fep->mal_rx_chan, DESC_BUF_SIZE_REG);
@@ -1615,20 +1623,10 @@
        }
 }
 
-static int emac_open(struct net_device *dev)
+static int emac_up(struct net_device *dev)
 {
-       struct ocp_enet_private *fep = dev->priv;
        int rc;
-
-       spin_lock_irq(&fep->lock);
-
-       fep->opened = 1;
-       netif_carrier_off(dev);
-
-       /* Reset & configure the chip */
-       emac_reset_configure(fep);
-
-       spin_unlock_irq(&fep->lock);
+       struct ocp_enet_private *fep = dev->priv;
 
        /* Request our interrupt lines */
        rc = request_irq(dev->irq, emac_mac_irq, 0, "IBM EMAC MAC", dev);
@@ -1646,6 +1644,24 @@
        return rc;
 }
 
+static int emac_open(struct net_device *dev)
+{
+       struct ocp_enet_private *fep = dev->priv;
+
+       spin_lock_irq(&fep->lock);
+
+       fep->opened = 1;
+       netif_carrier_off(dev);
+
+       /* Reset & configure the chip */
+       emac_reset_configure(fep);
+
+       spin_unlock_irq(&fep->lock);
+
+       return emac_up(dev);
+
+}
+
 static int emac_close(struct net_device *dev)
 {
        struct ocp_enet_private *fep = dev->priv;
@@ -1975,6 +1991,71 @@
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int emac_suspend(struct ocp_device *pdev, u32 state)
+{
+       struct net_device *netdev = ocp_get_drvdata(pdev);
+       struct ocp_enet_private *fep = netdev->priv;
+
+       pr_debug("PM:emac_suspend:%d\n", state);
+
+       if(netif_running(netdev))
+               emac_close(netdev);
+
+       /* Stop timer and Reset the chip */
+       spin_lock_irq(&fep->lock);
+       del_timer(&fep->link_timer);
+       fep->opened = 0;
+       emac_reset(fep);
+       spin_unlock_irq(&fep->lock);
+
+       /* detach */
+       netif_device_detach(netdev);
+
+       /* 
+        * Save current states then turn off EMAC and PHY
+        * according to specified state.  
+        * make WOL(WakeupOnLan) enable, if needed
+        */
+       // XXX:TBD
+       pdev->current_state = state;
+
+       return 0;
+}
+
+static int emac_resume(struct ocp_device *pdev)
+{
+       struct net_device *netdev = ocp_get_drvdata(pdev);
+       struct ocp_enet_private *fep = netdev->priv;
+
+       pr_debug("emac_resume:\n");
+
+       /* Turn on EMAC and PHY and restore state */
+       // XXX:TBD
+       pdev->current_state = 0;
+
+       /* Reset & configure the chip then Restart Timer */
+       spin_lock_irq(&fep->lock);
+
+       fep->opened = 1;
+       netif_carrier_off(netdev);
+       emac_reset_configure(fep);
+
+       (fep->link_timer).expires = jiffies+1;
+       add_timer(&fep->link_timer);
+
+       spin_unlock_irq(&fep->lock);
+
+       /* attach */
+       netif_device_attach(netdev);
+
+       if(netif_running(netdev))
+               emac_up(netdev);
+
+       return 0;
+}
+#endif
+
 /* Structure for a device driver */
 static struct ocp_device_id emac_ids[] = {
        {.vendor = OCP_ANY_ID,.function = OCP_FUNC_EMAC},
@@ -1987,6 +2068,10 @@
 
        .probe = emac_probe,
        .remove = emac_remove,
+#ifdef CONFIG_PM
+       .suspend = emac_suspend,
+       .resume = emac_resume,
+#endif
 };
 
 static int __init emac_init(void)

-EOF






Reply via email to