d2b0178
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
d2b0178
index 2571a2f..822f9e5 100644
d2b0178
--- a/drivers/net/wireless/rt2x00/rt2800.h
d2b0178
+++ b/drivers/net/wireless/rt2x00/rt2800.h
d2b0178
@@ -1627,6 +1627,7 @@ struct mac_iveiv_entry {
d2b0178
 
d2b0178
 /*
d2b0178
  * H2M_MAILBOX_CSR: Host-to-MCU Mailbox.
d2b0178
+ * CMD_TOKEN: Command id, 0xff disable status reporting
d2b0178
  */
d2b0178
 #define H2M_MAILBOX_CSR			0x7010
d2b0178
 #define H2M_MAILBOX_CSR_ARG0		FIELD32(0x000000ff)
d2b0178
@@ -1636,6 +1637,8 @@ struct mac_iveiv_entry {
d2b0178
 
d2b0178
 /*
d2b0178
  * H2M_MAILBOX_CID:
d2b0178
+ * Free slots contain 0xff. MCU will store command's token to lowest free slot.
d2b0178
+ * If all slots are occupied status will be dropped.
d2b0178
  */
d2b0178
 #define H2M_MAILBOX_CID			0x7014
d2b0178
 #define H2M_MAILBOX_CID_CMD0		FIELD32(0x000000ff)
d2b0178
@@ -1645,6 +1648,7 @@ struct mac_iveiv_entry {
d2b0178
 
d2b0178
 /*
d2b0178
  * H2M_MAILBOX_STATUS:
d2b0178
+ * Command status will be saved to same slot as command id.
d2b0178
  */
d2b0178
 #define H2M_MAILBOX_STATUS		0x701c
d2b0178
 
d2b0178
@@ -2259,6 +2263,12 @@ struct mac_iveiv_entry {
d2b0178
 
d2b0178
 /*
d2b0178
  * MCU mailbox commands.
d2b0178
+ * MCU_SLEEP - go to power-save mode.
d2b0178
+ *             arg1: 1: save as much power as possible, 0: save less power
d2b0178
+ *             status: 1: success, 2: already asleep,
d2b0178
+ *                     3: maybe MAC is busy so can't finish this task
d2b0178
+ * MCU_RADIO_OFF
d2b0178
+ *             arg0: 0: do power-saving, NOT turn off radio
d2b0178
  */
d2b0178
 #define MCU_SLEEP			0x30
d2b0178
 #define MCU_WAKEUP			0x31
d2b0178
@@ -2279,7 +2289,9 @@ struct mac_iveiv_entry {
d2b0178
 /*
d2b0178
  * MCU mailbox tokens
d2b0178
  */
d2b0178
-#define TOKEN_WAKUP			3
d2b0178
+#define TOKEN_SLEEP			1
d2b0178
+#define TOKEN_RADIO_OFF			2
d2b0178
+#define TOKEN_WAKEUP			3
d2b0178
 
d2b0178
 /*
d2b0178
  * DMA descriptor defines.
d2b0178
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
d2b0178
index dc88bae..9ac3017 100644
d2b0178
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
d2b0178
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
d2b0178
@@ -517,23 +517,6 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
d2b0178
 	}
d2b0178
 }
d2b0178
 
d2b0178
-static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
d2b0178
-			       enum dev_state state)
d2b0178
-{
d2b0178
-	if (state == STATE_AWAKE) {
d2b0178
-		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);
d2b0178
-		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
d2b0178
-	} else if (state == STATE_SLEEP) {
d2b0178
-		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
d2b0178
-					 0xffffffff);
d2b0178
-		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID,
d2b0178
-					 0xffffffff);
d2b0178
-		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);
d2b0178
-	}
d2b0178
-
d2b0178
-	return 0;
d2b0178
-}
d2b0178
-
d2b0178
 static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
d2b0178
 				      enum dev_state state)
d2b0178
 {
d2b0178
@@ -541,14 +524,20 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
d2b0178
 
d2b0178
 	switch (state) {
d2b0178
 	case STATE_RADIO_ON:
d2b0178
-		/*
d2b0178
-		 * Before the radio can be enabled, the device first has
d2b0178
-		 * to be woken up. After that it needs a bit of time
d2b0178
-		 * to be fully awake and then the radio can be enabled.
d2b0178
-		 */
d2b0178
-		rt2800pci_set_state(rt2x00dev, STATE_AWAKE);
d2b0178
-		msleep(1);
d2b0178
+		/* Initialise all registers and send MCU_BOOT_SIGNAL. */
d2b0178
 		retval = rt2800pci_enable_radio(rt2x00dev);
d2b0178
+
d2b0178
+		/* After resume MCU_BOOT_SIGNAL will trash those. */
d2b0178
+		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
d2b0178
+		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
d2b0178
+
d2b0178
+		/* Finish initialization procedure. */
d2b0178
+		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF,
d2b0178
+				   0xff, 0x02);
d2b0178
+		rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
d2b0178
+
d2b0178
+		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, 0, 0);
d2b0178
+		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
d2b0178
 		break;
d2b0178
 	case STATE_RADIO_OFF:
d2b0178
 		/*
d2b0178
@@ -556,7 +545,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
d2b0178
 		 * be put to sleep for powersaving.
d2b0178
 		 */
d2b0178
 		rt2800pci_disable_radio(rt2x00dev);
d2b0178
-		rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
d2b0178
+		rt2800pci_set_device_state(rt2x00dev, STATE_SLEEP);
d2b0178
 		break;
d2b0178
 	case STATE_RADIO_IRQ_ON:
d2b0178
 	case STATE_RADIO_IRQ_OFF:
d2b0178
@@ -565,8 +554,16 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
d2b0178
 	case STATE_DEEP_SLEEP:
d2b0178
 	case STATE_SLEEP:
d2b0178
 	case STATE_STANDBY:
d2b0178
+		/* PCIe devices won't report status after SLEEP request. */
d2b0178
+		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
d2b0178
+		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
d2b0178
+		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
d2b0178
+				   0xff, 0x01);
d2b0178
+		break;
d2b0178
 	case STATE_AWAKE:
d2b0178
-		retval = rt2800pci_set_state(rt2x00dev, state);
d2b0178
+		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP,
d2b0178
+				   0, 0x02);
d2b0178
+		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
d2b0178
 		break;
d2b0178
 	default:
d2b0178
 		retval = -ENOTSUPP;