Skip to content

Instantly share code, notes, and snippets.

@mikeNG
Last active January 4, 2016 02:09
Show Gist options
  • Save mikeNG/8552750 to your computer and use it in GitHub Desktop.
Save mikeNG/8552750 to your computer and use it in GitHub Desktop.
wl12xx android patches for backports-3.12-1
From 13d7ac43dd73e00fa40621e08805e926575bffaf Mon Sep 17 00:00:00 2001
From: Eliad Peller <[email protected]>
Date: Fri, 20 May 2011 11:58:54 +0300
Subject: [PATCH 1/5] wlcore: add wake_locks (ANDROID)
Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Ido Yariv <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
.../drivers/net/wireless/ti/wlcore/main.c | 31 ++++++++++++++++++++
.../backports/drivers/net/wireless/ti/wlcore/rx.c | 5 ++++
.../drivers/net/wireless/ti/wlcore/wlcore.h | 4 +++
.../drivers/net/wireless/ti/wlcore/wlcore_i.h | 4 +++
4 files changed, 44 insertions(+)
diff --git a/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c b/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
index 641d5e9..4a616ec 100644
--- a/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
+++ b/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
@@ -652,9 +652,17 @@ static irqreturn_t wlcore_irq(int irq, void *cookie)
wl1271_debug(DEBUG_IRQ, "should not enqueue work");
disable_irq_nosync(wl->irq);
pm_wakeup_event(wl->dev, 0);
+#ifdef CONFIG_HAS_WAKELOCK
+ if (!test_and_set_bit(WL1271_FLAG_WAKE_LOCK, &wl->flags))
+ wake_lock(&wl->wake_lock);
+#endif
spin_unlock_irqrestore(&wl->wl_lock, flags);
return IRQ_HANDLED;
}
+#ifdef CONFIG_HAS_WAKELOCK
+ if (!test_and_set_bit(WL1271_FLAG_WAKE_LOCK, &wl->flags))
+ wake_lock(&wl->wake_lock);
+#endif
spin_unlock_irqrestore(&wl->wl_lock, flags);
/* TX might be handled here, avoid redundant work */
@@ -673,6 +681,11 @@ static irqreturn_t wlcore_irq(int irq, void *cookie)
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
wl1271_tx_total_queue_count(wl) > 0)
ieee80211_queue_work(wl->hw, &wl->tx_work);
+
+#ifdef CONFIG_HAS_WAKELOCK
+ if (test_and_clear_bit(WL1271_FLAG_WAKE_LOCK, &wl->flags))
+ wake_unlock(&wl->wake_lock);
+#endif
spin_unlock_irqrestore(&wl->wl_lock, flags);
mutex_unlock(&wl->mutex);
@@ -1800,6 +1813,12 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
}
out:
+#ifdef CONFIG_HAS_WAKELOCK
+ spin_lock_irqsave(&wl->wl_lock, flags);
+ if (test_and_clear_bit(WL1271_FLAG_WAKE_LOCK, &wl->flags))
+ wake_unlock(&wl->wake_lock);
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
+#endif
wl->wow_enabled = false;
mutex_unlock(&wl->mutex);
@@ -5814,6 +5833,10 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size,
wl->tx_frames[i] = NULL;
spin_lock_init(&wl->wl_lock);
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_lock_init(&wl->wake_lock, WAKE_LOCK_SUSPEND, "wl1271_wake");
+ wake_lock_init(&wl->rx_wake, WAKE_LOCK_SUSPEND, "rx_wake");
+#endif
wl->state = WLCORE_STATE_OFF;
wl->fw_type = WL12XX_FW_TYPE_NONE;
@@ -5870,6 +5893,10 @@ err_aggr:
free_pages((unsigned long)wl->aggr_buf, order);
err_wq:
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_lock_destroy(&wl->wake_lock);
+ wake_lock_destroy(&wl->rx_wake);
+#endif
destroy_workqueue(wl->freezable_wq);
err_hw:
@@ -5887,6 +5914,10 @@ EXPORT_SYMBOL_GPL(wlcore_alloc_hw);
int wlcore_free_hw(struct wl1271 *wl)
{
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_lock_destroy(&wl->wake_lock);
+ wake_lock_destroy(&wl->rx_wake);
+#endif
/* Unblock any fwlog readers */
mutex_lock(&wl->mutex);
wl->fwlog_size = -1;
diff --git a/mac80211/backports/drivers/net/wireless/ti/wlcore/rx.c b/mac80211/backports/drivers/net/wireless/ti/wlcore/rx.c
index 6791a1a..99a1ddc 100644
--- a/mac80211/backports/drivers/net/wireless/ti/wlcore/rx.c
+++ b/mac80211/backports/drivers/net/wireless/ti/wlcore/rx.c
@@ -200,6 +200,11 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
skb_queue_tail(&wl->deferred_rx_queue, skb);
queue_work(wl->freezable_wq, &wl->netstack_work);
+#ifdef CONFIG_HAS_WAKELOCK
+ /* let the frame some time to propagate to user-space */
+ wake_lock_timeout(&wl->rx_wake, HZ);
+#endif
+
return is_data;
}
diff --git a/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore.h b/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore.h
index e97c35e..cf4101b 100644
--- a/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -333,6 +333,10 @@ struct wl1271 {
/* in dBm */
int power_level;
+#ifdef CONFIG_HAS_WAKELOCK
+ struct wake_lock wake_lock;
+ struct wake_lock rx_wake;
+#endif
struct wl1271_stats stats;
__le32 *buffer_32;
diff --git a/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore_i.h b/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore_i.h
index e5e1464..a42cd7a 100644
--- a/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -31,6 +31,9 @@
#include <linux/list.h>
#include <linux/bitops.h>
#include <net/mac80211.h>
+#ifdef CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#endif
#include "conf.h"
#include "ini.h"
@@ -230,6 +233,7 @@ enum wl12xx_flags {
WL1271_FLAG_TX_PENDING,
WL1271_FLAG_IN_ELP,
WL1271_FLAG_ELP_REQUESTED,
+ WL1271_FLAG_WAKE_LOCK,
WL1271_FLAG_IRQ_RUNNING,
WL1271_FLAG_FW_TX_BUSY,
WL1271_FLAG_DUMMY_PACKET_PENDING,
--
1.7.10.4
From d31c93cbdc59c75a12daeef10fd61ef8ac408c31 Mon Sep 17 00:00:00 2001
From: Ido Yariv <[email protected]>
Date: Wed, 6 Feb 2013 11:55:45 +0200
Subject: [PATCH 2/5] wlcore: acquire a wakelock in the hardirq only on wake
up (ANDROID)
This wakelock doesn't seem to protect against a reoccurring race, but only
cases in which the system starts suspending after the hardirq was serviced but
prior to the threaded irq. This is not very likely and being handled by
flushing the interrupts in the suspend op.
Signed-off-by: Ido Yariv <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
mac80211/backports/drivers/net/wireless/ti/wlcore/main.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c b/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
index 4a616ec..35f29fd 100644
--- a/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
+++ b/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
@@ -659,10 +659,6 @@ static irqreturn_t wlcore_irq(int irq, void *cookie)
spin_unlock_irqrestore(&wl->wl_lock, flags);
return IRQ_HANDLED;
}
-#ifdef CONFIG_HAS_WAKELOCK
- if (!test_and_set_bit(WL1271_FLAG_WAKE_LOCK, &wl->flags))
- wake_lock(&wl->wake_lock);
-#endif
spin_unlock_irqrestore(&wl->wl_lock, flags);
/* TX might be handled here, avoid redundant work */
--
1.7.10.4
From 92f0be0eec4028d3901c2c6f25e947f60832ec1d Mon Sep 17 00:00:00 2001
From: Eliad Peller <[email protected]>
Date: Mon, 23 May 2011 13:44:18 +0300
Subject: [PATCH 3/5] wlcore: set "any" trigger by default (ANDROID)
Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
mac80211/backports/net/wireless/core.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/mac80211/backports/net/wireless/core.c b/mac80211/backports/net/wireless/core.c
index e4e825b..36cc2bb 100644
--- a/mac80211/backports/net/wireless/core.c
+++ b/mac80211/backports/net/wireless/core.c
@@ -568,6 +568,20 @@ int wiphy_register(struct wiphy *wiphy)
rdev->wiphy.wowlan->pattern_min_len >
rdev->wiphy.wowlan->pattern_max_len)))
return -EINVAL;
+
+#ifdef CONFIG_ANDROID
+ /* use wowlan by default */
+ if (rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) {
+ /* TODO: free wowlan in case we fail later*/
+ struct cfg80211_wowlan *wowlan_cfg;
+
+ wowlan_cfg = kzalloc(sizeof(*wowlan_cfg), GFP_KERNEL);
+ if (!wowlan_cfg)
+ return -ENOMEM;
+ wowlan_cfg->any = true;
+ rdev->wiphy.wowlan_config = wowlan_cfg;
+ }
+#endif
#endif
/* check and set up bitrates */
--
1.7.10.4
From 3f659df00f9165a3df080630b8d7350765b71137 Mon Sep 17 00:00:00 2001
From: Arik Nemtsov <[email protected]>
Date: Wed, 27 Jun 2012 21:43:39 +0300
Subject: [PATCH 4/5] wlcore: don't suspend on pending recovery (ANDROID)
Some customers complain that if we cancel a pending recovery during
suspend, the android scheduler will keep banging on the suspend handler,
without letting recovery take its course. Grab a wakelock to give the
recovery process some breathing room.
Signed-off-by: Arik Nemtsov <[email protected]>
---
mac80211/backports/drivers/net/wireless/ti/wlcore/main.c | 11 +++++++++++
mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore.h | 1 +
2 files changed, 12 insertions(+)
diff --git a/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c b/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
index 35f29fd..d1bc064 100644
--- a/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
+++ b/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
@@ -790,6 +790,10 @@ void wl12xx_queue_recovery_work(struct wl1271 *wl)
wl->state = WLCORE_STATE_RESTARTING;
set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
wlcore_disable_interrupts_nosync(wl);
+#ifdef CONFIG_HAS_WAKELOCK
+ /* give us a grace period for recovery */
+ wake_lock_timeout(&wl->recovery_wake, 5 * HZ);
+#endif
ieee80211_queue_work(wl->hw, &wl->recovery_work);
}
}
@@ -1718,6 +1722,10 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
/* we want to perform the recovery before suspending */
if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) {
wl1271_warning("postponing suspend to perform recovery");
+#ifdef CONFIG_HAS_WAKELOCK
+ /* give us a grace period for recovery */
+ wake_lock_timeout(&wl->recovery_wake, 5 * HZ);
+#endif
return -EBUSY;
}
@@ -5832,6 +5840,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size,
#ifdef CONFIG_HAS_WAKELOCK
wake_lock_init(&wl->wake_lock, WAKE_LOCK_SUSPEND, "wl1271_wake");
wake_lock_init(&wl->rx_wake, WAKE_LOCK_SUSPEND, "rx_wake");
+ wake_lock_init(&wl->recovery_wake, WAKE_LOCK_SUSPEND, "recovery_wake");
#endif
wl->state = WLCORE_STATE_OFF;
@@ -5892,6 +5901,7 @@ err_wq:
#ifdef CONFIG_HAS_WAKELOCK
wake_lock_destroy(&wl->wake_lock);
wake_lock_destroy(&wl->rx_wake);
+ wake_lock_destroy(&wl->recovery_wake);
#endif
destroy_workqueue(wl->freezable_wq);
@@ -5913,6 +5923,7 @@ int wlcore_free_hw(struct wl1271 *wl)
#ifdef CONFIG_HAS_WAKELOCK
wake_lock_destroy(&wl->wake_lock);
wake_lock_destroy(&wl->rx_wake);
+ wake_lock_destroy(&wl->recovery_wake);
#endif
/* Unblock any fwlog readers */
mutex_lock(&wl->mutex);
diff --git a/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore.h b/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore.h
index cf4101b..9d95d8c 100644
--- a/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/mac80211/backports/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -336,6 +336,7 @@ struct wl1271 {
#ifdef CONFIG_HAS_WAKELOCK
struct wake_lock wake_lock;
struct wake_lock rx_wake;
+ struct wake_lock recovery_wake;
#endif
struct wl1271_stats stats;
--
1.7.10.4
From 4ea543c9caafc9d911afce334b5896696197fa94 Mon Sep 17 00:00:00 2001
From: Steven Luo <[email protected]>
Date: Tue, 6 Aug 2013 04:04:10 -0700
Subject: [PATCH 5/5] wlcore: fix unbalanced wakelock in IRQ-while-suspended
path
Change-Id: I2d9cf541884a7e2435865096796a3947439c0f4d
---
.../backports/drivers/net/wireless/ti/wlcore/main.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c b/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
index d1bc064..c283916 100644
--- a/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
+++ b/mac80211/backports/drivers/net/wireless/ti/wlcore/main.c
@@ -1770,6 +1770,9 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
struct wl12xx_vif *wlvif;
unsigned long flags;
bool run_irq_work = false, pending_recovery;
+#ifdef CONFIG_HAS_WAKELOCK
+ bool holding_wake_lock = false;
+#endif
int ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",
@@ -1782,8 +1785,13 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
*/
spin_lock_irqsave(&wl->wl_lock, flags);
clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
- if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags))
+ if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags)) {
run_irq_work = true;
+#ifdef CONFIG_HAS_WAKELOCK
+ if (test_and_clear_bit(WL1271_FLAG_WAKE_LOCK, &wl->flags))
+ holding_wake_lock = true;
+#endif
+ }
spin_unlock_irqrestore(&wl->wl_lock, flags);
mutex_lock(&wl->mutex);
@@ -1803,6 +1811,11 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
wl12xx_queue_recovery_work(wl);
}
+#ifdef CONFIG_HAS_WAKELOCK
+ if (holding_wake_lock)
+ wake_unlock(&wl->wake_lock);
+#endif
+
wlcore_enable_interrupts(wl);
}
--
1.7.10.4
@thoemy
Copy link

thoemy commented Jan 22, 2014

Thanks, you beat me to it. Will test it later today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment