ath6kl: Perform WOW resume in RX path in case of SDIO IRQ wake up
authorRaja Mani <rmani@qca.qualcomm.com>
Mon, 7 Nov 2011 20:52:46 +0000 (22:52 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Fri, 11 Nov 2011 11:00:00 +0000 (13:00 +0200)
The target triggers sdio data line to wake up the host when
WOW pattern matches. This causes sdio irq handler is being
executed in the host side which internally hits ath6kl's RX path.

WOW resume should happen before start processing any data from
the target. So it's required to perform WOW resume in RX path.

This area needs bit rework to avoid WOW resume in RX path,
As of now it's fine to have this model, rework will be done later.

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/txrx.c

index 0e3ecf814635c8ba0ab24c737cb529e5fbcd4821..c981e137e1d13469cf02ee67b409fefe31186ac9 100644 (file)
@@ -1886,6 +1886,34 @@ static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
 
        return ath6kl_hif_resume(ar);
 }
+
+/*
+ * FIXME: WOW suspend mode is selected if the host sdio controller supports
+ * both sdio irq wake up and keep power. The target pulls sdio data line to
+ * wake up the host when WOW pattern matches. This causes sdio irq handler
+ * is being called in the host side which internally hits ath6kl's RX path.
+ *
+ * Since sdio interrupt is not disabled, RX path executes even before
+ * the host executes the actual resume operation from PM module.
+ *
+ * In the current scenario, WOW resume should happen before start processing
+ * any data from the target. So It's required to perform WOW resume in RX path.
+ * Ideally we should perform WOW resume only in the actual platform
+ * resume path. This area needs bit rework to avoid WOW resume in RX path.
+ *
+ * ath6kl_check_wow_status() is called from ath6kl_rx().
+ */
+void ath6kl_check_wow_status(struct ath6kl *ar)
+{
+       if (ar->state == ATH6KL_STATE_WOW)
+               ath6kl_cfg80211_resume(ar);
+}
+
+#else
+
+void ath6kl_check_wow_status(struct ath6kl *ar)
+{
+}
 #endif
 
 static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
index 9e8b8e3339cb3bccbb4857d0fe2f17d2481d267d..e7e095e536a7e0bb34d81e4a63d1a87b159a2a14 100644 (file)
@@ -678,5 +678,6 @@ struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar);
 void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready);
 int ath6kl_init_hw_start(struct ath6kl *ar);
 int ath6kl_init_hw_stop(struct ath6kl *ar);
+void ath6kl_check_wow_status(struct ath6kl *ar);
 
 #endif /* CORE_H */
index 06e4912f03216d161ac4ff1a662a808fc4954eec..6f1de4468a12b6b2c377a608ab8d188a2329b9aa 100644 (file)
@@ -1134,6 +1134,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
                return;
        }
 
+       ath6kl_check_wow_status(ar);
+
        if (ept == ar->ctrl_ep) {
                ath6kl_wmi_control_rx(ar->wmi, skb);
                return;