After writing PUT_TO_SLEEP to the device,
wait untill the CURRENT_STATE of the device indicates
it is asleep before returning from the suspend function.
When suspend fails, call the resume function to bring
the device back to live again.

Signed-off-by Ivo van Doorn <[EMAIL PROTECTED]>

diff -U 3 -H -w -E -d -r -N -- 
wireless-2.6/drivers/net/wireless/rt2x00/rt2400pci.c 
wireless-2.6-rt2x00/drivers/net/wireless/rt2x00/rt2400pci.c
--- wireless-2.6/drivers/net/wireless/rt2x00/rt2400pci.c        2006-02-09 
20:35:21.000000000 +0100
+++ wireless-2.6-rt2x00/drivers/net/wireless/rt2x00/rt2400pci.c 2006-02-11 
22:56:08.000000000 +0100
@@ -2238,11 +2279,15 @@
 }
 
 #ifdef CONFIG_PM
+static int rt2400pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
+static int rt2400pci_resume(struct pci_dev *pci_dev);
+
 static int
 rt2400pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
        struct net_device       *net_dev = pci_get_drvdata(pci_dev);
        struct rt2x00_pci       *rt2x00pci = ieee80211_dev_hw_data(net_dev);
+       int                     counter = 0;
        u32                     reg = 0;
 
        NOTICE("Going to sleep.\n");
@@ -2250,21 +2295,42 @@
        if(ieee80211_netif_oper(net_dev, NETIF_DETACH))
                return -EBUSY;
 
-       reg = 0;
+       rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
        rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
        rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, 1);
        rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, 1);
        rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, 1);
        rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
 
+       /*
+        * Device is not guarenteed to be asleep yet.
+        * We must wait untill the register indicates
+        * device has been correctly put to sleep.
+        */
+       for(counter = 0; counter < REGISTER_BUSY_COUNT; counter++){
+               rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
+               if((rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE) == 1)
+               && (rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE) == 1))
+                       break;
+               NOTICE("Waiting for device to sleep.\n");
+               msleep(10);
+       }
+
+       if(counter == REGISTER_BUSY_COUNT)
+               goto exit;
+
        if(pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1)
        || pci_save_state(pci_dev)
-       || pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))){
-               ERROR("Failed to suspend device.\n");
-               return -EIO;
-       }
+       || pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)))
+               goto exit;
 
        return 0;
+
+exit:
+       ERROR("Failed to suspend device.\n");
+
+       rt2400pci_resume(pci_dev);
+       return -EIO;
 }
 
 static int
@@ -2283,6 +2349,7 @@
                return -EIO;
        }
 
+       rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
        rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
        rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, 3);
        rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, 3);
diff -U 3 -H -w -E -d -r -N -- 
wireless-2.6/drivers/net/wireless/rt2x00/rt2500pci.c 
wireless-2.6-rt2x00/drivers/net/wireless/rt2x00/rt2500pci.c
--- wireless-2.6/drivers/net/wireless/rt2x00/rt2500pci.c        2006-02-09 
20:35:21.000000000 +0100
+++ wireless-2.6-rt2x00/drivers/net/wireless/rt2x00/rt2500pci.c 2006-02-11 
22:56:28.000000000 +0100
@@ -2513,11 +2541,15 @@
 }
 
 #ifdef CONFIG_PM
+static int rt2500pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
+static int rt2500pci_resume(struct pci_dev *pci_dev);
+
 static int
 rt2500pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
        struct net_device       *net_dev = pci_get_drvdata(pci_dev);
        struct rt2x00_pci       *rt2x00pci = ieee80211_dev_hw_data(net_dev);
+       int                     counter = 0;
        u32                     reg = 0;
 
        NOTICE("Going to sleep.\n");
@@ -2525,21 +2557,42 @@
        if(ieee80211_netif_oper(net_dev, NETIF_DETACH))
                return -EBUSY;
 
-       reg = 0;
+       rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
        rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
        rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, 1);
        rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, 1);
        rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, 1);
        rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
 
+       /*
+        * Device is not guarenteed to be asleep yet.
+        * We must wait untill the register indicates
+        * device has been correctly put to sleep.
+        */
+       for(counter = 0; counter < REGISTER_BUSY_COUNT; counter++){
+               rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
+               if((rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE) == 1)
+               && (rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE) == 1))
+                       break;
+               NOTICE("Waiting for device to sleep.\n");
+               msleep(10);
+       }
+
+       if(counter == REGISTER_BUSY_COUNT)
+               goto exit;
+
        if(pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1)
        || pci_save_state(pci_dev)
-       || pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))){
-               ERROR("Failed to suspend device.\n");
-               return -EIO;
-       }
+       || pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)))
+               goto exit;
 
        return 0;
+
+exit:
+       ERROR("Failed to suspend device.\n");
+
+       rt2500pci_resume(pci_dev);
+       return -EIO;
 }
 
 static int
@@ -2558,6 +2611,7 @@
                return -EIO;
        }
 
+       rt2x00_register_read(rt2x00pci, PWRCSR1, &reg);
        rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
        rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, 3);
        rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, 3);
diff -U 3 -H -w -E -d -r -N -- 
wireless-2.6/drivers/net/wireless/rt2x00/rt2500usb.c 
wireless-2.6-rt2x00/drivers/net/wireless/rt2x00/rt2500usb.c
--- wireless-2.6/drivers/net/wireless/rt2x00/rt2500usb.c        2006-02-09 
20:35:21.000000000 +0100
+++ wireless-2.6-rt2x00/drivers/net/wireless/rt2x00/rt2500usb.c 2006-02-11 
22:56:01.000000000 +0100
@@ -2133,11 +2172,16 @@
 }
 
 #ifdef CONFIG_PM
+static int rt2500usb_suspend(
+       struct usb_interface *usb_intf, pm_message_t state);
+static int rt2500usb_resume(struct usb_interface *usb_intf);
+
 static int
 rt2500usb_suspend(struct usb_interface *usb_intf, pm_message_t state)
 {
        struct net_device       *net_dev = usb_get_intfdata(usb_intf);
        struct rt2x00_usb       *rt2x00usb = ieee80211_dev_hw_data(net_dev);
+       int                     counter = 0;
        u16                     reg = 0;
 
        NOTICE("Going to sleep.\n");
@@ -2145,14 +2189,29 @@
        if(ieee80211_netif_oper(net_dev, NETIF_DETACH))
                return -EBUSY;
 
-       reg = 0;
+       rt2x00_register_read(rt2x00usb, MAC_CSR17, &reg);
        rt2x00_set_field16_nb(&reg, MAC_CSR17_SET_STATE, 1);
        rt2x00_set_field16_nb(&reg, MAC_CSR17_BBP_DESIRE_STATE, 1);
        rt2x00_set_field16_nb(&reg, MAC_CSR17_RF_DESIRE_STATE, 1);
        rt2x00_set_field16_nb(&reg, MAC_CSR17_PUT_TO_SLEEP, 1);
        rt2x00_register_write(rt2x00usb, MAC_CSR17, reg);
 
+       /*
+        * Device is not guarenteed to be asleep yet.
+        * We must wait untill the register indicates
+        * device has been correctly put to sleep.
+        */
+       for(counter = 0; counter < REGISTER_BUSY_COUNT; counter++){
+               rt2x00_register_read(rt2x00usb, MAC_CSR17, &reg);
+               if((rt2x00_get_field16_nb(reg, MAC_CSR17_BBP_CURR_STATE) == 1)
+               && (rt2x00_get_field16_nb(reg, MAC_CSR17_RF_CURR_STATE) == 1))
        return 0;
+               NOTICE("Waiting for device to sleep.\n");
+               msleep(10);
+       }
+
+       rt2500usb_resume(usb_intf);
+       return -EIO;
 }
 
 static int
@@ -2164,6 +2223,7 @@
 
        NOTICE("Waking up.\n");
 
+       rt2x00_register_read(rt2x00usb, MAC_CSR17, &reg);
        rt2x00_set_field16_nb(&reg, MAC_CSR17_SET_STATE, 1);
        rt2x00_set_field16_nb(&reg, MAC_CSR17_BBP_DESIRE_STATE, 3);
        rt2x00_set_field16_nb(&reg, MAC_CSR17_RF_DESIRE_STATE, 3);

Attachment: pgpx5QoON7e0y.pgp
Description: PGP signature

Reply via email to