linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/7] ath6kl: suspend cutpower mode
@ 2011-11-01  6:43 Kalle Valo
  2011-11-01  6:43 ` [PATCH v2 1/7] ath6kl: add aborted parameter to ath6kl_cfg80211_scan_complete_event() Kalle Valo
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Kalle Valo @ 2011-11-01  6:43 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

Here's my v2 of suspend cutpower patches.

v2:

o fix ath6kl_cfg80211_stop() to clear connect flags
o refactor sdio configuration to a separate function

---

Kalle Valo (7):
      ath6kl: add aborted parameter to ath6kl_cfg80211_scan_complete_event()
      ath6kl: create ath6kl_cfg80211_stop()
      ath6kl: reset CONNECT_PEND and CONNECTED flags in ath6kl_cfg80211_stop()
      ath6kl: implement ath6kl_cfg80211_suspend()
      ath6kl: add state variable depicting hw/fw state
      ath6kl: refactor sdio configuration to a separate function
      ath6kl: cut power during suspend


 drivers/net/wireless/ath/ath6kl/cfg80211.c |  158 ++++++++++++++++++++++++++--
 drivers/net/wireless/ath/ath6kl/cfg80211.h |   13 ++
 drivers/net/wireless/ath/ath6kl/core.h     |   11 ++
 drivers/net/wireless/ath/ath6kl/debug.h    |    1 
 drivers/net/wireless/ath/ath6kl/init.c     |    4 +
 drivers/net/wireless/ath/ath6kl/main.c     |   64 +----------
 drivers/net/wireless/ath/ath6kl/sdio.c     |  146 ++++++++++++++++++--------
 drivers/net/wireless/ath/ath6kl/wmi.h      |    4 +
 8 files changed, 283 insertions(+), 118 deletions(-)


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/7] ath6kl: add aborted parameter to ath6kl_cfg80211_scan_complete_event()
  2011-11-01  6:43 [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
@ 2011-11-01  6:43 ` Kalle Valo
  2011-11-01  6:44 ` [PATCH v2 2/7] ath6kl: create ath6kl_cfg80211_stop() Kalle Valo
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Kalle Valo @ 2011-11-01  6:43 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

Currently it takes an error code as status, but what we really want to
tell is if the scan was aborted or not.

Also fix a bug where we were comparing firmware scan status values
with kernel error codes, which is obviously wrong. This meant
that ath6kl didn't detect when firmware informed about failed scans. I
doubt that this fix doesn't make any difference in practise but it
still needs to be fixed. This is fixed by adding an enum for the success
status code and checking for that.

Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/cfg80211.c |   12 ++++--------
 drivers/net/wireless/ath/ath6kl/cfg80211.h |    2 +-
 drivers/net/wireless/ath/ath6kl/main.c     |   10 +++++++---
 drivers/net/wireless/ath/ath6kl/wmi.h      |    4 ++++
 4 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 994c646..188fded 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -871,23 +871,19 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 	return ret;
 }
 
-void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, int status)
+void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
 {
 	struct ath6kl *ar = vif->ar;
-	bool aborted;
 	int i;
 
-	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status %d\n", __func__, status);
+	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__,
+		   aborted ? " aborted" : "");
 
 	if (!vif->scan_req)
 		return;
 
-	if ((status == -ECANCELED) || (status == -EBUSY)) {
-		aborted = true;
+	if (aborted)
 		goto out;
-	}
-
-	aborted = false;
 
 	if (vif->scan_req->n_ssids && vif->scan_req->ssids[0].ssid_len) {
 		for (i = 0; i < vif->scan_req->n_ssids; i++) {
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
index d1a0216..f323a49 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.h
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -24,7 +24,7 @@ int ath6kl_register_ieee80211_hw(struct ath6kl *ar);
 struct ath6kl *ath6kl_core_alloc(struct device *dev);
 void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar);
 
-void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, int status);
+void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted);
 
 void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
 				   u8 *bssid, u16 listen_intvl,
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index def0b7f..d2822d0 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -624,7 +624,7 @@ void ath6kl_deep_sleep_enable(struct ath6kl *ar)
 		printk(KERN_WARNING "ath6kl: failed to disable scan "
 		       "during suspend\n");
 
-	ath6kl_cfg80211_scan_complete_event(vif, -ECANCELED);
+	ath6kl_cfg80211_scan_complete_event(vif, true);
 
 	/* save the current power mode before enabling power save */
 	ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
@@ -684,8 +684,12 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
 void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status)
 {
 	struct ath6kl *ar = vif->ar;
+	bool aborted = false;
 
-	ath6kl_cfg80211_scan_complete_event(vif, status);
+	if (status != WMI_SCAN_STATUS_SUCCESS)
+		aborted = true;
+
+	ath6kl_cfg80211_scan_complete_event(vif, aborted);
 
 	if (!ar->usr_bss_filter) {
 		clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
@@ -1149,7 +1153,7 @@ static int ath6kl_close(struct net_device *dev)
 
 	}
 
-	ath6kl_cfg80211_scan_complete_event(vif, -ECANCELED);
+	ath6kl_cfg80211_scan_complete_event(vif, true);
 
 	/* FIXME: how to handle multi vif support? */
 	ret = ath6kl_init_hw_stop(ar);
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index ae514cb..cf0462a 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1472,6 +1472,10 @@ struct wmi_tkip_micerr_event {
 	u8 is_mcast;
 } __packed;
 
+enum wmi_scan_status {
+	WMI_SCAN_STATUS_SUCCESS = 0,
+};
+
 /* WMI_SCAN_COMPLETE_EVENTID */
 struct wmi_scan_complete_event {
 	a_sle32 status;


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/7] ath6kl: create ath6kl_cfg80211_stop()
  2011-11-01  6:43 [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
  2011-11-01  6:43 ` [PATCH v2 1/7] ath6kl: add aborted parameter to ath6kl_cfg80211_scan_complete_event() Kalle Valo
@ 2011-11-01  6:44 ` Kalle Valo
  2011-11-01  6:44 ` [PATCH v2 3/7] ath6kl: reset CONNECT_PEND and CONNECTED flags in ath6kl_cfg80211_stop() Kalle Valo
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Kalle Valo @ 2011-11-01  6:44 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

Just take code from deep sleep for now, will be improved later. No
functional changes.

Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/cfg80211.c |   49 ++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath6kl/cfg80211.h |    2 +
 drivers/net/wireless/ath/ath6kl/main.c     |   46 +-------------------------
 3 files changed, 52 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 188fded..94038cb 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2112,6 +2112,55 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
 	.mgmt_frame_register = ath6kl_mgmt_frame_register,
 };
 
+void ath6kl_cfg80211_stop(struct ath6kl *ar)
+{
+	struct ath6kl_vif *vif;
+
+	/* FIXME: for multi vif */
+	vif = ath6kl_vif_first(ar);
+	if (!vif) {
+		/* save the current power mode before enabling power save */
+		ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
+
+		if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
+			ath6kl_warn("ath6kl_deep_sleep_enable: "
+				    "wmi_powermode_cmd failed\n");
+		return;
+	}
+
+	switch (vif->sme_state) {
+	case SME_CONNECTING:
+		cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0,
+					NULL, 0,
+					WLAN_STATUS_UNSPECIFIED_FAILURE,
+					GFP_KERNEL);
+		break;
+	case SME_CONNECTED:
+	default:
+		/*
+		 * FIXME: oddly enough smeState is in DISCONNECTED during
+		 * suspend, why? Need to send disconnected event in that
+		 * state.
+		 */
+		cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL);
+		break;
+	}
+
+	if (test_bit(CONNECTED, &vif->flags) ||
+	    test_bit(CONNECT_PEND, &vif->flags))
+		ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
+
+	vif->sme_state = SME_DISCONNECTED;
+
+	/* disable scanning */
+	if (ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0xFFFF, 0, 0,
+				      0, 0, 0, 0, 0, 0, 0) != 0)
+		printk(KERN_WARNING "ath6kl: failed to disable scan "
+		       "during suspend\n");
+
+	ath6kl_cfg80211_scan_complete_event(vif, true);
+}
+
 struct ath6kl *ath6kl_core_alloc(struct device *dev)
 {
 	struct ath6kl *ar;
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
index f323a49..bb0ac22 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.h
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -40,4 +40,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
 void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
 				     bool ismcast);
 
+void ath6kl_cfg80211_stop(struct ath6kl *ar);
+
 #endif /* ATH6KL_CFG80211_H */
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index d2822d0..378dc8d 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -580,51 +580,7 @@ void ath6kl_disconnect(struct ath6kl_vif *vif)
 
 void ath6kl_deep_sleep_enable(struct ath6kl *ar)
 {
-	struct ath6kl_vif *vif;
-
-	/* FIXME: for multi vif */
-	vif = ath6kl_vif_first(ar);
-	if (!vif) {
-		/* save the current power mode before enabling power save */
-		ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
-
-		if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
-			ath6kl_warn("ath6kl_deep_sleep_enable: "
-				    "wmi_powermode_cmd failed\n");
-		return;
-	}
-
-	switch (vif->sme_state) {
-	case SME_CONNECTING:
-		cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0,
-					NULL, 0,
-					WLAN_STATUS_UNSPECIFIED_FAILURE,
-					GFP_KERNEL);
-		break;
-	case SME_CONNECTED:
-	default:
-		/*
-		 * FIXME: oddly enough smeState is in DISCONNECTED during
-		 * suspend, why? Need to send disconnected event in that
-		 * state.
-		 */
-		cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL);
-		break;
-	}
-
-	if (test_bit(CONNECTED, &vif->flags) ||
-	    test_bit(CONNECT_PEND, &vif->flags))
-		ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
-
-	vif->sme_state = SME_DISCONNECTED;
-
-	/* disable scanning */
-	if (ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0xFFFF, 0, 0,
-				      0, 0, 0, 0, 0, 0, 0) != 0)
-		printk(KERN_WARNING "ath6kl: failed to disable scan "
-		       "during suspend\n");
-
-	ath6kl_cfg80211_scan_complete_event(vif, true);
+	ath6kl_cfg80211_stop(ar);
 
 	/* save the current power mode before enabling power save */
 	ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/7] ath6kl: reset CONNECT_PEND and CONNECTED flags in ath6kl_cfg80211_stop()
  2011-11-01  6:43 [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
  2011-11-01  6:43 ` [PATCH v2 1/7] ath6kl: add aborted parameter to ath6kl_cfg80211_scan_complete_event() Kalle Valo
  2011-11-01  6:44 ` [PATCH v2 2/7] ath6kl: create ath6kl_cfg80211_stop() Kalle Valo
@ 2011-11-01  6:44 ` Kalle Valo
  2011-11-01  6:44 ` [PATCH v2 4/7] ath6kl: implement ath6kl_cfg80211_suspend() Kalle Valo
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Kalle Valo @ 2011-11-01  6:44 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

Otherwise first connection establish after cutpower suspend will
fail.

Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/cfg80211.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 94038cb..565cdbe 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2151,6 +2151,8 @@ void ath6kl_cfg80211_stop(struct ath6kl *ar)
 		ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
 
 	vif->sme_state = SME_DISCONNECTED;
+	clear_bit(CONNECTED, &vif->flags);
+	clear_bit(CONNECT_PEND, &vif->flags);
 
 	/* disable scanning */
 	if (ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0xFFFF, 0, 0,


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/7] ath6kl: implement ath6kl_cfg80211_suspend()
  2011-11-01  6:43 [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
                   ` (2 preceding siblings ...)
  2011-11-01  6:44 ` [PATCH v2 3/7] ath6kl: reset CONNECT_PEND and CONNECTED flags in ath6kl_cfg80211_stop() Kalle Valo
@ 2011-11-01  6:44 ` Kalle Valo
  2011-11-01  6:44 ` [PATCH v2 5/7] ath6kl: add state variable depicting hw/fw state Kalle Valo
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Kalle Valo @ 2011-11-01  6:44 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

This is in preparation for cutpower suspend feature. HIF layer makes
the decision based on information provided by cfg80211 and what hardware
actually supports. Then it calls ath6kl_cfg80211_suspend() to enable
the chosen mode.

Functionality should be the same, this is just preparation for
more suspend modes (cutpower and wow).

Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/cfg80211.c |   46 ++++++++++++++++++++++++++--
 drivers/net/wireless/ath/ath6kl/cfg80211.h |    8 +++++
 drivers/net/wireless/ath/ath6kl/core.h     |    1 -
 drivers/net/wireless/ath/ath6kl/main.c     |   12 -------
 drivers/net/wireless/ath/ath6kl/sdio.c     |    9 +----
 5 files changed, 52 insertions(+), 24 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 565cdbe..ef0ab9b 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1653,8 +1653,46 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
 	return 0;
 }
 
+int ath6kl_cfg80211_suspend(struct ath6kl *ar,
+			    enum ath6kl_cfg_suspend_mode mode)
+{
+	int ret;
+
+	ath6kl_cfg80211_stop(ar);
+
+	switch (mode) {
+	case ATH6KL_CFG_SUSPEND_DEEPSLEEP:
+		/* save the current power mode before enabling power save */
+		ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
+
+		ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
+		if (ret) {
+			ath6kl_warn("wmi powermode command failed during suspend: %d\n",
+				    ret);
+		}
+
+		break;
+	}
+
+	return 0;
+}
+
+int ath6kl_cfg80211_resume(struct ath6kl *ar)
+{
+	if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
+		if (ath6kl_wmi_powermode_cmd(ar->wmi, 0,
+			ar->wmi->saved_pwr_mode) != 0)
+			ath6kl_warn("ath6kl_sdio_resume: "
+				"wmi_powermode_cmd failed\n");
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_PM
-static int ar6k_cfg80211_suspend(struct wiphy *wiphy,
+
+/* hif layer decides what suspend mode to use */
+static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
 				 struct cfg80211_wowlan *wow)
 {
 	struct ath6kl *ar = wiphy_priv(wiphy);
@@ -1662,7 +1700,7 @@ static int ar6k_cfg80211_suspend(struct wiphy *wiphy,
 	return ath6kl_hif_suspend(ar);
 }
 
-static int ar6k_cfg80211_resume(struct wiphy *wiphy)
+static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
 {
 	struct ath6kl *ar = wiphy_priv(wiphy);
 
@@ -2098,8 +2136,8 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
 	.flush_pmksa = ath6kl_flush_pmksa,
 	CFG80211_TESTMODE_CMD(ath6kl_tm_cmd)
 #ifdef CONFIG_PM
-	.suspend = ar6k_cfg80211_suspend,
-	.resume = ar6k_cfg80211_resume,
+	.suspend = __ath6kl_cfg80211_suspend,
+	.resume = __ath6kl_cfg80211_resume,
 #endif
 	.set_channel = ath6kl_set_channel,
 	.add_beacon = ath6kl_add_beacon,
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
index bb0ac22..3630c5e 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.h
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -17,6 +17,10 @@
 #ifndef ATH6KL_CFG80211_H
 #define ATH6KL_CFG80211_H
 
+enum ath6kl_cfg_suspend_mode {
+	ATH6KL_CFG_SUSPEND_DEEPSLEEP,
+};
+
 struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
 					enum nl80211_iftype type,
 					u8 fw_vif_idx, u8 nw_type);
@@ -40,6 +44,10 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
 void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
 				     bool ismcast);
 
+int ath6kl_cfg80211_suspend(struct ath6kl *ar,
+			    enum ath6kl_cfg_suspend_mode mode);
+int ath6kl_cfg80211_resume(struct ath6kl *ar);
+
 void ath6kl_cfg80211_stop(struct ath6kl *ar);
 
 #endif /* ATH6KL_CFG80211_H */
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 95aed7d..00cc1db 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -649,7 +649,6 @@ void ath6kl_pspoll_event(struct ath6kl_vif *vif, u8 aid);
 
 void ath6kl_dtimexpiry_event(struct ath6kl_vif *vif);
 void ath6kl_disconnect(struct ath6kl_vif *vif);
-void ath6kl_deep_sleep_enable(struct ath6kl *ar);
 void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid);
 void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no,
 			     u8 win_sz);
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 378dc8d..23da82e 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -578,18 +578,6 @@ void ath6kl_disconnect(struct ath6kl_vif *vif)
 	}
 }
 
-void ath6kl_deep_sleep_enable(struct ath6kl *ar)
-{
-	ath6kl_cfg80211_stop(ar);
-
-	/* save the current power mode before enabling power save */
-	ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
-
-	if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
-		ath6kl_warn("ath6kl_deep_sleep_enable: "
-			"wmi_powermode_cmd failed\n");
-}
-
 /* WMI Event handlers */
 
 static const char *get_hw_id_string(u32 id)
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 2d15557..75b1eaa 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -757,19 +757,14 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar)
 		return ret;
 	}
 
-	ath6kl_deep_sleep_enable(ar);
+	ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP);
 
 	return 0;
 }
 
 static int ath6kl_sdio_resume(struct ath6kl *ar)
 {
-	if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
-		if (ath6kl_wmi_powermode_cmd(ar->wmi, 0,
-			ar->wmi->saved_pwr_mode) != 0)
-			ath6kl_warn("ath6kl_sdio_resume: "
-				"wmi_powermode_cmd failed\n");
-	}
+	ath6kl_cfg80211_resume(ar);
 
 	return 0;
 }


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 5/7] ath6kl: add state variable depicting hw/fw state
  2011-11-01  6:43 [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
                   ` (3 preceding siblings ...)
  2011-11-01  6:44 ` [PATCH v2 4/7] ath6kl: implement ath6kl_cfg80211_suspend() Kalle Valo
@ 2011-11-01  6:44 ` Kalle Valo
  2011-11-01  6:44 ` [PATCH v2 6/7] ath6kl: refactor sdio configuration to a separate function Kalle Valo
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Kalle Valo @ 2011-11-01  6:44 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

This way it's easier to track state changes and in the future add
more warnings about using hardware in wrong states. Currently there
are few random flags for trying to do the same, those will be cleaned
and removed in the future.

Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/cfg80211.c |   28 +++++++++++++++++++++++-----
 drivers/net/wireless/ath/ath6kl/core.h     |    9 +++++++++
 drivers/net/wireless/ath/ath6kl/init.c     |    4 ++++
 3 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index ef0ab9b..b618119 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1671,6 +1671,8 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
 				    ret);
 		}
 
+		ar->state = ATH6KL_STATE_DEEPSLEEP;
+
 		break;
 	}
 
@@ -1679,11 +1681,25 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
 
 int ath6kl_cfg80211_resume(struct ath6kl *ar)
 {
-	if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
-		if (ath6kl_wmi_powermode_cmd(ar->wmi, 0,
-			ar->wmi->saved_pwr_mode) != 0)
-			ath6kl_warn("ath6kl_sdio_resume: "
-				"wmi_powermode_cmd failed\n");
+	int ret;
+
+	switch (ar->state) {
+	case ATH6KL_STATE_DEEPSLEEP:
+		if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
+			ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
+						       ar->wmi->saved_pwr_mode);
+			if (ret) {
+				ath6kl_warn("wmi powermode command failed during resume: %d\n",
+					    ret);
+			}
+		}
+
+		ar->state = ATH6KL_STATE_ON;
+
+		break;
+
+	default:
+		break;
 	}
 
 	return 0;
@@ -2253,6 +2269,8 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev)
 	ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS;
 	ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
 
+	ar->state = ATH6KL_STATE_OFF;
+
 	memset((u8 *)ar->sta_list, 0,
 	       AP_MAX_NUM_STA * sizeof(struct ath6kl_sta));
 
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 00cc1db..6613248 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -450,9 +450,18 @@ enum ath6kl_dev_state {
 	FIRST_BOOT,
 };
 
+enum ath6kl_state {
+	ATH6KL_STATE_OFF,
+	ATH6KL_STATE_ON,
+	ATH6KL_STATE_DEEPSLEEP,
+};
+
 struct ath6kl {
 	struct device *dev;
 	struct wiphy *wiphy;
+
+	enum ath6kl_state state;
+
 	struct ath6kl_bmi bmi;
 	const struct ath6kl_hif_ops *hif_ops;
 	struct wmi *wmi;
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 06e5cea..f7fcd91 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1452,6 +1452,8 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
 			goto err_htc_stop;
 	}
 
+	ar->state = ATH6KL_STATE_ON;
+
 	return 0;
 
 err_htc_stop:
@@ -1480,6 +1482,8 @@ int ath6kl_init_hw_stop(struct ath6kl *ar)
 	if (ret)
 		ath6kl_warn("failed to power off hif: %d\n", ret);
 
+	ar->state = ATH6KL_STATE_OFF;
+
 	return 0;
 }
 


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 6/7] ath6kl: refactor sdio configuration to a separate function
  2011-11-01  6:43 [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
                   ` (4 preceding siblings ...)
  2011-11-01  6:44 ` [PATCH v2 5/7] ath6kl: add state variable depicting hw/fw state Kalle Valo
@ 2011-11-01  6:44 ` Kalle Valo
  2011-11-01  6:44 ` [PATCH v2 7/7] ath6kl: cut power during suspend Kalle Valo
  2011-11-01 11:57 ` [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
  7 siblings, 0 replies; 9+ messages in thread
From: Kalle Valo @ 2011-11-01  6:44 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

These commands are also needed after cutpower suspend so create
a function for them. Also fix memory leaks in ath6kl_sdio_probe() error
path.

Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/sdio.c |   77 ++++++++++++++++++--------------
 1 files changed, 44 insertions(+), 33 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 75b1eaa..b02ecea 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -733,6 +733,46 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
 	return 0;
 }
 
+static int ath6kl_sdio_config(struct ath6kl *ar)
+{
+	struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+	struct sdio_func *func = ar_sdio->func;
+	int ret;
+
+	sdio_claim_host(func);
+
+	if ((ar_sdio->id->device & MANUFACTURER_ID_ATH6KL_BASE_MASK) >=
+	    MANUFACTURER_ID_AR6003_BASE) {
+		/* enable 4-bit ASYNC interrupt on AR6003 or later */
+		ret = ath6kl_sdio_func0_cmd52_wr_byte(func->card,
+						CCCR_SDIO_IRQ_MODE_REG,
+						SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
+		if (ret) {
+			ath6kl_err("Failed to enable 4-bit async irq mode %d\n",
+				   ret);
+			goto out;
+		}
+
+		ath6kl_dbg(ATH6KL_DBG_BOOT, "4-bit async irq mode enabled\n");
+	}
+
+	/* give us some time to enable, in ms */
+	func->enable_timeout = 100;
+
+	ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
+	if (ret) {
+		ath6kl_err("Set sdio block size %d failed: %d)\n",
+			   HIF_MBOX_BLOCK_SIZE, ret);
+		sdio_release_host(func);
+		goto out;
+	}
+
+out:
+	sdio_release_host(func);
+
+	return ret;
+}
+
 static int ath6kl_sdio_suspend(struct ath6kl *ar)
 {
 	struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
@@ -873,45 +913,16 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
 
 	ath6kl_sdio_set_mbox_info(ar);
 
-	sdio_claim_host(func);
-
-	if ((ar_sdio->id->device & MANUFACTURER_ID_ATH6KL_BASE_MASK) >=
-	    MANUFACTURER_ID_AR6003_BASE) {
-		/* enable 4-bit ASYNC interrupt on AR6003 or later */
-		ret = ath6kl_sdio_func0_cmd52_wr_byte(func->card,
-						CCCR_SDIO_IRQ_MODE_REG,
-						SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
-		if (ret) {
-			ath6kl_err("Failed to enable 4-bit async irq mode %d\n",
-				   ret);
-			sdio_release_host(func);
-			goto err_core_alloc;
-		}
-
-		ath6kl_dbg(ATH6KL_DBG_BOOT, "4-bit async irq mode enabled\n");
-	}
-
-	/* give us some time to enable, in ms */
-	func->enable_timeout = 100;
-
-	sdio_release_host(func);
-
-	sdio_claim_host(func);
-
-	ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
+	ret = ath6kl_sdio_config(ar);
 	if (ret) {
-		ath6kl_err("Set sdio block size %d failed: %d)\n",
-			   HIF_MBOX_BLOCK_SIZE, ret);
-		sdio_release_host(func);
-		goto err_hif;
+		ath6kl_err("Failed to config sdio: %d\n", ret);
+		goto err_core_alloc;
 	}
 
-	sdio_release_host(func);
-
 	ret = ath6kl_core_init(ar);
 	if (ret) {
 		ath6kl_err("Failed to init ath6kl core\n");
-		goto err_hif;
+		goto err_core_alloc;
 	}
 
 	return ret;


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 7/7] ath6kl: cut power during suspend
  2011-11-01  6:43 [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
                   ` (5 preceding siblings ...)
  2011-11-01  6:44 ` [PATCH v2 6/7] ath6kl: refactor sdio configuration to a separate function Kalle Valo
@ 2011-11-01  6:44 ` Kalle Valo
  2011-11-01 11:57 ` [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
  7 siblings, 0 replies; 9+ messages in thread
From: Kalle Valo @ 2011-11-01  6:44 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

If sdio controller doesn't support keep power, cut power from hardware
during suspend and restart firmware during resume. If we are connected
during suspend, send a disconnected event to user space.

Earlier suspend failed with an error if sdio didn't support keep power.
Now suspend will happen succesfully even with that case.

Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/cfg80211.c |   31 ++++++++++++++
 drivers/net/wireless/ath/ath6kl/cfg80211.h |    1 
 drivers/net/wireless/ath/ath6kl/core.h     |    1 
 drivers/net/wireless/ath/ath6kl/debug.h    |    1 
 drivers/net/wireless/ath/ath6kl/sdio.c     |   64 +++++++++++++++++++++++++---
 5 files changed, 90 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index b618119..a942475 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1674,6 +1674,28 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
 		ar->state = ATH6KL_STATE_DEEPSLEEP;
 
 		break;
+
+	case ATH6KL_CFG_SUSPEND_CUTPOWER:
+		if (ar->state == ATH6KL_STATE_OFF) {
+			ath6kl_dbg(ATH6KL_DBG_SUSPEND,
+				   "suspend hw off, no action for cutpower\n");
+			break;
+		}
+
+		ath6kl_dbg(ATH6KL_DBG_SUSPEND, "suspend cutting power\n");
+
+		ret = ath6kl_init_hw_stop(ar);
+		if (ret) {
+			ath6kl_warn("failed to stop hw during suspend: %d\n",
+				    ret);
+		}
+
+		ar->state = ATH6KL_STATE_CUTPOWER;
+
+		break;
+
+	default:
+		break;
 	}
 
 	return 0;
@@ -1698,6 +1720,15 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
 
 		break;
 
+	case ATH6KL_STATE_CUTPOWER:
+		ath6kl_dbg(ATH6KL_DBG_SUSPEND, "resume restoring power\n");
+
+		ret = ath6kl_init_hw_start(ar);
+		if (ret) {
+			ath6kl_warn("Failed to boot hw in resume: %d\n", ret);
+			return ret;
+		}
+
 	default:
 		break;
 	}
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
index 3630c5e..72eadf8 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.h
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -19,6 +19,7 @@
 
 enum ath6kl_cfg_suspend_mode {
 	ATH6KL_CFG_SUSPEND_DEEPSLEEP,
+	ATH6KL_CFG_SUSPEND_CUTPOWER,
 };
 
 struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 6613248..f301c32 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -454,6 +454,7 @@ enum ath6kl_state {
 	ATH6KL_STATE_OFF,
 	ATH6KL_STATE_ON,
 	ATH6KL_STATE_DEEPSLEEP,
+	ATH6KL_STATE_CUTPOWER,
 };
 
 struct ath6kl {
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index 491485e..c24d120 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -40,6 +40,7 @@ enum ATH6K_DEBUG_MASK {
 	ATH6KL_DBG_SDIO_DUMP	= BIT(17),
 	ATH6KL_DBG_BOOT		= BIT(18),    /* driver init and fw boot */
 	ATH6KL_DBG_WMI_DUMP	= BIT(19),
+	ATH6KL_DBG_SUSPEND	= BIT(20),
 	ATH6KL_DBG_ANY	        = 0xffffffff  /* enable all logs */
 };
 
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index b02ecea..ccb888b 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -782,12 +782,11 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar)
 
 	flags = sdio_get_host_pm_caps(func);
 
+	ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio suspend pm_caps 0x%x\n", flags);
+
 	if (!(flags & MMC_PM_KEEP_POWER)) {
-		/* as host doesn't support keep power we need to bail out */
-		ath6kl_dbg(ATH6KL_DBG_SDIO,
-			   "func %d doesn't support MMC_PM_KEEP_POWER\n",
-			   func->num);
-		return -EINVAL;
+		/* as host doesn't support keep power we need to cut power */
+		return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER);
 	}
 
 	ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
@@ -797,13 +796,30 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar)
 		return ret;
 	}
 
-	ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP);
-
-	return 0;
+	return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP);
 }
 
 static int ath6kl_sdio_resume(struct ath6kl *ar)
 {
+	switch (ar->state) {
+	case ATH6KL_STATE_OFF:
+	case ATH6KL_STATE_CUTPOWER:
+		ath6kl_dbg(ATH6KL_DBG_SUSPEND,
+			   "sdio resume configuring sdio\n");
+
+		/* need to set sdio settings after power is cut from sdio */
+		ath6kl_sdio_config(ar);
+		break;
+
+	case ATH6KL_STATE_ON:
+		/* we shouldn't be on this state during resume */
+		WARN_ON(1);
+		break;
+
+	case ATH6KL_STATE_DEEPSLEEP:
+		break;
+	}
+
 	ath6kl_cfg80211_resume(ar);
 
 	return 0;
@@ -858,6 +874,37 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
 	.stop = ath6kl_sdio_stop,
 };
 
+#ifdef CONFIG_PM_SLEEP
+
+/*
+ * Empty handlers so that mmc subsystem doesn't remove us entirely during
+ * suspend. We instead follow cfg80211 suspend/resume handlers.
+ */
+static int ath6kl_sdio_pm_suspend(struct device *device)
+{
+	ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio pm suspend\n");
+
+	return 0;
+}
+
+static int ath6kl_sdio_pm_resume(struct device *device)
+{
+	ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio pm resume\n");
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ath6kl_sdio_pm_ops, ath6kl_sdio_pm_suspend,
+			 ath6kl_sdio_pm_resume);
+
+#define ATH6KL_SDIO_PM_OPS (&ath6kl_sdio_pm_ops)
+
+#else
+
+#define ATH6KL_SDIO_PM_OPS NULL
+
+#endif /* CONFIG_PM_SLEEP */
+
 static int ath6kl_sdio_probe(struct sdio_func *func,
 			     const struct sdio_device_id *id)
 {
@@ -969,6 +1016,7 @@ static struct sdio_driver ath6kl_sdio_driver = {
 	.id_table = ath6kl_sdio_devices,
 	.probe = ath6kl_sdio_probe,
 	.remove = ath6kl_sdio_remove,
+	.drv.pm = ATH6KL_SDIO_PM_OPS,
 };
 
 static int __init ath6kl_sdio_init(void)


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/7] ath6kl: suspend cutpower mode
  2011-11-01  6:43 [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
                   ` (6 preceding siblings ...)
  2011-11-01  6:44 ` [PATCH v2 7/7] ath6kl: cut power during suspend Kalle Valo
@ 2011-11-01 11:57 ` Kalle Valo
  7 siblings, 0 replies; 9+ messages in thread
From: Kalle Valo @ 2011-11-01 11:57 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless

On 11/01/2011 08:43 AM, Kalle Valo wrote:
> Here's my v2 of suspend cutpower patches.

All seven applied.

Kalle

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2011-11-01 11:59 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-01  6:43 [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo
2011-11-01  6:43 ` [PATCH v2 1/7] ath6kl: add aborted parameter to ath6kl_cfg80211_scan_complete_event() Kalle Valo
2011-11-01  6:44 ` [PATCH v2 2/7] ath6kl: create ath6kl_cfg80211_stop() Kalle Valo
2011-11-01  6:44 ` [PATCH v2 3/7] ath6kl: reset CONNECT_PEND and CONNECTED flags in ath6kl_cfg80211_stop() Kalle Valo
2011-11-01  6:44 ` [PATCH v2 4/7] ath6kl: implement ath6kl_cfg80211_suspend() Kalle Valo
2011-11-01  6:44 ` [PATCH v2 5/7] ath6kl: add state variable depicting hw/fw state Kalle Valo
2011-11-01  6:44 ` [PATCH v2 6/7] ath6kl: refactor sdio configuration to a separate function Kalle Valo
2011-11-01  6:44 ` [PATCH v2 7/7] ath6kl: cut power during suspend Kalle Valo
2011-11-01 11:57 ` [PATCH v2 0/7] ath6kl: suspend cutpower mode Kalle Valo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).