linux-mips
[Top] [All Lists]

Power management for au1000_eth.c

To: Linux MIPS <linux-mips@linux-mips.org>
Subject: Power management for au1000_eth.c
From: Rodolfo Giometti <giometti@linux.it>
Date: Wed, 5 Apr 2006 17:47:11 +0200
Cc: ppopov@mvista.com
Organization: GNU/Linux Device Drivers, Embedded Systems and Courses
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
User-agent: Mutt/1.5.11+cvs20060126
Hello,

I'm trying to add power management support to au1000_eth.c driver.

In order to to it I 've added these two functions:

   static int au1000_eth_suspend(struct device *dev, pm_message_t state, u32 
level)
   {
        struct net_device *ndev = dev_get_drvdata(dev);
        struct au1000_private *aup = (struct au1000_private *) ndev->priv;

        if (!ndev)
                return 0;

        switch (level) {
        case SUSPEND_DISABLE :
                if (netif_running(ndev))
                        netif_device_detach(ndev);

                break;
        
        case SUSPEND_SAVE_STATE :
                /* bring the device out of reset, otherwise accessing to mii
                 * will hang */
                *aup->enable = MAC_EN_CLOCK_ENABLE;
                au_sync_delay(2);
                *aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
                                MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
                au_sync_delay(2);

                if (aup->phy_ops->phy_suspend)
                        aup->phy_ops->phy_suspend(ndev, aup->phy_addr, level);

                del_timer_sync(&aup->timer); /* FIXME: REMOVED??? */
                reset_mac(ndev);

                netif_stop_queue(ndev);

                free_irq(ndev->irq, dev);

                break;

        case SUSPEND_POWER_DOWN :

                break;
        }

        return 0;
   }

   static int au1000_eth_resume(struct device *dev, u32 level)
   {
        struct net_device *ndev = dev_get_drvdata(dev);
        struct au1000_private *aup = (struct au1000_private *) ndev->priv;
           u32 flags;
        int ret;

        if (!ndev)
                return 0;

        switch (level) {
        case RESUME_RESTORE_STATE :
                /* bring the device out of reset, otherwise accessing to mii
                 * will hang */
                *aup->enable = MAC_EN_CLOCK_ENABLE;
                au_sync_delay(2);
                *aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
                                MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
                au_sync_delay(2);

                if (aup->phy_ops->phy_resume)
                        aup->phy_ops->phy_resume(ndev, aup->phy_addr, level);
                aup->phy_ops->phy_init(ndev, aup->phy_addr);

                /* au1000_init() expects that the device is in reset state.
                 */
                reset_mac(ndev); /* au1000_init() expects the device in reset */
                au1000_init(ndev);

                ret = request_irq(ndev->irq, &au1000_interrupt, 0, ndev->name, 
ndev);
                if (ret) {
                        printk(KERN_ERR "%s: unable to get IRQ %d\n",
                                         ndev->name, ndev->irq);
                        return ret; //FIXME
                }

                init_timer(&aup->timer); /* used in ioctl() */
                aup->timer.expires = RUN_AT((3*HZ));
                aup->timer.data = (unsigned long) ndev;
                aup->timer.function = &au1000_timer; /* timer handler */
                add_timer(&aup->timer);

                break;

        case RESUME_ENABLE :
                if (netif_running(ndev))
                        netif_device_attach(ndev);

                break;
        }

        return 0;
   }

The problem is that after wakeup the system hangs or returns lots of
errors like:

   Reserved instruction in kernel code in arch/mips/kernel/traps.c::do_ri, line 
706[#169]:

Note that if I compile the driver as a module and removing it before
sleeping and reinstalling it after wake up the system (and the
ethernet) works correctly...

Suggestions? :)

Thanks in advance,

Rodolfo

-- 

GNU/Linux Solutions                  e-mail:    giometti@enneenne.com
Linux Device Driver                             giometti@gnudd.com
Embedded Systems                                giometti@linux.it
UNIX programming                     phone:     +39 349 2432127

<Prev in Thread] Current Thread [Next in Thread>