ath6kl: Wait for host sleep mode cmd processed event during WOW suspend
authorRaja Mani <rmani@qca.qualcomm.com>
Mon, 30 Jan 2012 11:43:11 +0000 (17:13 +0530)
committerKalle Valo <kvalo@qca.qualcomm.com>
Mon, 30 Jan 2012 19:22:55 +0000 (21:22 +0200)
For every WMI_SET_HOST_SLEEP_MODE_CMDID command (send from the host),
the firmware sends WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID as
an acknowledgement to the host.

In order to being sync with the firmware, the host has to wait for
WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENT event before going to
the suspend state. This patch ensures ath6kl_wow_suspend() waits
until it gets this event after sending set host sleep mode command.

This patch adds,
 * New command WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID in
   WMI event table.
 * New WMI function ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx()
   to process the event.
 * New flag HOST_SLEEP_MODE_CMD_PROCESSED in VIF flags to record
   the arrival of the event.

Signed-off-by: Raja Mani <rmani@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.h

index e676cfccedfe5fa7690844e6687aac994280699d..1902e2fa1a68949988eae8eb82d449dabf7d1a19 100644 (file)
@@ -1975,11 +1975,26 @@ skip_arp:
        if (ret)
                return ret;
 
+       clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
+
        ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
                                                 ATH6KL_HOST_MODE_ASLEEP);
        if (ret)
                return ret;
 
+       left = wait_event_interruptible_timeout(ar->event_wq,
+                       test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags),
+                       WMI_TIMEOUT);
+       if (left == 0) {
+               ath6kl_warn("timeout, didn't get host sleep cmd "
+                           "processed event\n");
+               ret = -ETIMEDOUT;
+       } else if (left < 0) {
+               ath6kl_warn("error while waiting for host sleep cmd "
+                           "processed event %d\n", left);
+               ret = left;
+       }
+
        if (ar->tx_pending[ar->ctrl_ep]) {
                left = wait_event_interruptible_timeout(ar->event_wq,
                                ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT);
index ce572c04b92417715c5ec25c52aef8c71d738ff9..c4d66e066dc9f293afeddcc449770fa0386a8d3e 100644 (file)
@@ -451,6 +451,7 @@ enum ath6kl_vif_state {
        DTIM_PERIOD_AVAIL,
        WLAN_ENABLED,
        STATS_UPDATE_PEND,
+       HOST_SLEEP_MODE_CMD_PROCESSED,
 };
 
 struct ath6kl_vif {
index 9c8e4dfbfa0cb1067bb12b8acbadc4606323de7c..18fa9aa8af92464a4888f37b68d9904293ed2573 100644 (file)
@@ -2590,6 +2590,18 @@ int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
        return ret;
 }
 
+/* This command has zero length payload */
+static int ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(struct wmi *wmi,
+                                                     struct ath6kl_vif *vif)
+{
+       struct ath6kl *ar = wmi->parent_dev;
+
+       set_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
+       wake_up(&ar->event_wq);
+
+       return 0;
+}
+
 int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
                                enum ath6kl_wow_mode wow_mode,
                                u32 filter, u16 host_req_delay)
@@ -3556,6 +3568,11 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n");
                ret = ath6kl_wmi_tx_complete_event_rx(datap, len);
                break;
+       case WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID:
+               ath6kl_dbg(ATH6KL_DBG_WMI,
+                          "WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID");
+               ret = ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(wmi, vif);
+               break;
        case WMI_REMAIN_ON_CHNL_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n");
                ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif);
index 85698ef2dd88dc288ad146c14cbbba20f59a1f29..e7919869725e07b9d6300a259c522f3bd2b59ce3 100644 (file)
@@ -1357,6 +1357,8 @@ enum wmi_event_id {
        WMI_P2P_START_SDPD_EVENTID,
        WMI_P2P_SDPD_RX_EVENTID,
 
+       WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID = 0x1047,
+
        WMI_THIN_RESERVED_START_EVENTID = 0x8000,
        /* Events in this range are reserved for thinmode */
        WMI_THIN_RESERVED_END_EVENTID = 0x8fff,