aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2011-03-23 16:22:15 -0400
committerLuciano Coelho <coelho@ti.com>2011-04-19 09:49:14 -0400
commitc1b193eb6557279d037ab18c00ab628c6c78847f (patch)
treedad930948af8a88a23a579cb23fadca2fd2ac704 /drivers/net
parent17e672d6e4b5a8a3f330a70dfd58d25a2cb497b5 (diff)
wl12xx: rearrange some ELP wake_up/sleep calls
ELP (Extremely/Enhanced Low Power, or something like that ;)) refers to the powerstate of the 12xx chip, in which very low power is consumed, and no commands (from the host) can be issued until the chip is woken up. Wakeup/sleep commands must be protected by a wl->mutex, so it's generally a good idea to call wakeup/sleep along with the mutex lock/unlock (where needed). However, in some places the wl12xx driver calls wakeup/sleep in some "inner" functions. This result in some "nested" wakeup/sleep calls which might end up letting the chip go to sleep prematurely (e.g. during event handling). Fix it by rearranging the elp calls to come along with mutex_lock/unlock. Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Ido Yariv <ido@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/wl12xx/event.c11
-rw-r--r--drivers/net/wireless/wl12xx/main.c43
-rw-r--r--drivers/net/wireless/wl12xx/ps.c3
-rw-r--r--drivers/net/wireless/wl12xx/tx.c22
4 files changed, 36 insertions, 43 deletions
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 413d901985fe..ae69330e807c 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -33,6 +33,7 @@ void wl1271_pspoll_work(struct work_struct *work)
33{ 33{
34 struct delayed_work *dwork; 34 struct delayed_work *dwork;
35 struct wl1271 *wl; 35 struct wl1271 *wl;
36 int ret;
36 37
37 dwork = container_of(work, struct delayed_work, work); 38 dwork = container_of(work, struct delayed_work, work);
38 wl = container_of(dwork, struct wl1271, pspoll_work); 39 wl = container_of(dwork, struct wl1271, pspoll_work);
@@ -55,8 +56,13 @@ void wl1271_pspoll_work(struct work_struct *work)
55 * delivery failure occurred, and no-one changed state since, so 56 * delivery failure occurred, and no-one changed state since, so
56 * we should go back to powersave. 57 * we should go back to powersave.
57 */ 58 */
59 ret = wl1271_ps_elp_wakeup(wl);
60 if (ret < 0)
61 goto out;
62
58 wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); 63 wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true);
59 64
65 wl1271_ps_elp_sleep(wl);
60out: 66out:
61 mutex_unlock(&wl->mutex); 67 mutex_unlock(&wl->mutex);
62}; 68};
@@ -129,11 +135,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
129 135
130 /* enable beacon early termination */ 136 /* enable beacon early termination */
131 ret = wl1271_acx_bet_enable(wl, true); 137 ret = wl1271_acx_bet_enable(wl, true);
132 if (ret < 0)
133 break;
134
135 /* go to extremely low power mode */
136 wl1271_ps_elp_sleep(wl);
137 break; 138 break;
138 default: 139 default:
139 break; 140 break;
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 5545c3b94d2e..3f6517dda629 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2792,32 +2792,31 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
2792 conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; 2792 conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY;
2793 conf_tid->apsd_conf[0] = 0; 2793 conf_tid->apsd_conf[0] = 0;
2794 conf_tid->apsd_conf[1] = 0; 2794 conf_tid->apsd_conf[1] = 0;
2795 } else { 2795 goto out;
2796 ret = wl1271_ps_elp_wakeup(wl); 2796 }
2797 if (ret < 0)
2798 goto out;
2799 2797
2800 /* 2798 ret = wl1271_ps_elp_wakeup(wl);
2801 * the txop is confed in units of 32us by the mac80211, 2799 if (ret < 0)
2802 * we need us 2800 goto out;
2803 */
2804 ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
2805 params->cw_min, params->cw_max,
2806 params->aifs, params->txop << 5);
2807 if (ret < 0)
2808 goto out_sleep;
2809 2801
2810 ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), 2802 /*
2811 CONF_CHANNEL_TYPE_EDCF, 2803 * the txop is confed in units of 32us by the mac80211,
2812 wl1271_tx_get_queue(queue), 2804 * we need us
2813 ps_scheme, CONF_ACK_POLICY_LEGACY, 2805 */
2814 0, 0); 2806 ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
2815 if (ret < 0) 2807 params->cw_min, params->cw_max,
2816 goto out_sleep; 2808 params->aifs, params->txop << 5);
2809 if (ret < 0)
2810 goto out_sleep;
2811
2812 ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
2813 CONF_CHANNEL_TYPE_EDCF,
2814 wl1271_tx_get_queue(queue),
2815 ps_scheme, CONF_ACK_POLICY_LEGACY,
2816 0, 0);
2817 2817
2818out_sleep: 2818out_sleep:
2819 wl1271_ps_elp_sleep(wl); 2819 wl1271_ps_elp_sleep(wl);
2820 }
2821 2820
2822out: 2821out:
2823 mutex_unlock(&wl->mutex); 2822 mutex_unlock(&wl->mutex);
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 971f13e792da..b8deada5d020 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -149,9 +149,6 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
149 case STATION_ACTIVE_MODE: 149 case STATION_ACTIVE_MODE:
150 default: 150 default:
151 wl1271_debug(DEBUG_PSM, "leaving psm"); 151 wl1271_debug(DEBUG_PSM, "leaving psm");
152 ret = wl1271_ps_elp_wakeup(wl);
153 if (ret < 0)
154 return ret;
155 152
156 /* disable beacon early termination */ 153 /* disable beacon early termination */
157 ret = wl1271_acx_bet_enable(wl, false); 154 ret = wl1271_acx_bet_enable(wl, false);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index db9e47e09fba..2019ed9ebfc4 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -511,22 +511,14 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
511void wl1271_tx_work_locked(struct wl1271 *wl) 511void wl1271_tx_work_locked(struct wl1271 *wl)
512{ 512{
513 struct sk_buff *skb; 513 struct sk_buff *skb;
514 bool woken_up = false;
515 u32 buf_offset = 0; 514 u32 buf_offset = 0;
516 bool sent_packets = false; 515 bool sent_packets = false;
517 int ret; 516 int ret;
518 517
519 if (unlikely(wl->state == WL1271_STATE_OFF)) 518 if (unlikely(wl->state == WL1271_STATE_OFF))
520 goto out; 519 return;
521 520
522 while ((skb = wl1271_skb_dequeue(wl))) { 521 while ((skb = wl1271_skb_dequeue(wl))) {
523 if (!woken_up) {
524 ret = wl1271_ps_elp_wakeup(wl);
525 if (ret < 0)
526 goto out_ack;
527 woken_up = true;
528 }
529
530 ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); 522 ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
531 if (ret == -EAGAIN) { 523 if (ret == -EAGAIN) {
532 /* 524 /*
@@ -573,18 +565,22 @@ out_ack:
573 565
574 wl1271_handle_tx_low_watermark(wl); 566 wl1271_handle_tx_low_watermark(wl);
575 } 567 }
576
577out:
578 if (woken_up)
579 wl1271_ps_elp_sleep(wl);
580} 568}
581 569
582void wl1271_tx_work(struct work_struct *work) 570void wl1271_tx_work(struct work_struct *work)
583{ 571{
584 struct wl1271 *wl = container_of(work, struct wl1271, tx_work); 572 struct wl1271 *wl = container_of(work, struct wl1271, tx_work);
573 int ret;
585 574
586 mutex_lock(&wl->mutex); 575 mutex_lock(&wl->mutex);
576 ret = wl1271_ps_elp_wakeup(wl);
577 if (ret < 0)
578 goto out;
579
587 wl1271_tx_work_locked(wl); 580 wl1271_tx_work_locked(wl);
581
582 wl1271_ps_elp_wakeup(wl);
583out:
588 mutex_unlock(&wl->mutex); 584 mutex_unlock(&wl->mutex);
589} 585}
590 586