Power management for au1000_eth.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxx
Linux Device Driver                             giometti@xxxxxxxxx
Embedded Systems                     		giometti@xxxxxxxx
UNIX programming                     phone:     +39 349 2432127


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux