ACPI: Make AC and battery drivers available on !X86
[sfrench/cifs-2.6.git] / drivers / net / wireless / st / cw1200 / pm.c
1 /*
2  * Mac80211 power management API for ST-Ericsson CW1200 drivers
3  *
4  * Copyright (c) 2011, ST-Ericsson
5  * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/module.h>
13 #include <linux/if_ether.h>
14 #include "cw1200.h"
15 #include "pm.h"
16 #include "sta.h"
17 #include "bh.h"
18 #include "hwbus.h"
19
20 #define CW1200_BEACON_SKIPPING_MULTIPLIER 3
21
22 struct cw1200_udp_port_filter {
23         struct wsm_udp_port_filter_hdr hdr;
24         /* Up to 4 filters are allowed. */
25         struct wsm_udp_port_filter filters[WSM_MAX_FILTER_ELEMENTS];
26 } __packed;
27
28 struct cw1200_ether_type_filter {
29         struct wsm_ether_type_filter_hdr hdr;
30         /* Up to 4 filters are allowed. */
31         struct wsm_ether_type_filter filters[WSM_MAX_FILTER_ELEMENTS];
32 } __packed;
33
34 static struct cw1200_udp_port_filter cw1200_udp_port_filter_on = {
35         .hdr.num = 2,
36         .filters = {
37                 [0] = {
38                         .action = WSM_FILTER_ACTION_FILTER_OUT,
39                         .type = WSM_FILTER_PORT_TYPE_DST,
40                         .port = __cpu_to_le16(67), /* DHCP Bootps */
41                 },
42                 [1] = {
43                         .action = WSM_FILTER_ACTION_FILTER_OUT,
44                         .type = WSM_FILTER_PORT_TYPE_DST,
45                         .port = __cpu_to_le16(68), /* DHCP Bootpc */
46                 },
47         }
48 };
49
50 static struct wsm_udp_port_filter_hdr cw1200_udp_port_filter_off = {
51         .num = 0,
52 };
53
54 #ifndef ETH_P_WAPI
55 #define ETH_P_WAPI     0x88B4
56 #endif
57
58 static struct cw1200_ether_type_filter cw1200_ether_type_filter_on = {
59         .hdr.num = 4,
60         .filters = {
61                 [0] = {
62                         .action = WSM_FILTER_ACTION_FILTER_IN,
63                         .type = __cpu_to_le16(ETH_P_IP),
64                 },
65                 [1] = {
66                         .action = WSM_FILTER_ACTION_FILTER_IN,
67                         .type = __cpu_to_le16(ETH_P_PAE),
68                 },
69                 [2] = {
70                         .action = WSM_FILTER_ACTION_FILTER_IN,
71                         .type = __cpu_to_le16(ETH_P_WAPI),
72                 },
73                 [3] = {
74                         .action = WSM_FILTER_ACTION_FILTER_IN,
75                         .type = __cpu_to_le16(ETH_P_ARP),
76                 },
77         },
78 };
79
80 static struct wsm_ether_type_filter_hdr cw1200_ether_type_filter_off = {
81         .num = 0,
82 };
83
84 /* private */
85 struct cw1200_suspend_state {
86         unsigned long bss_loss_tmo;
87         unsigned long join_tmo;
88         unsigned long direct_probe;
89         unsigned long link_id_gc;
90         bool beacon_skipping;
91         u8 prev_ps_mode;
92 };
93
94 static void cw1200_pm_stay_awake_tmo(struct timer_list *unused)
95 {
96         /* XXX what's the point of this ? */
97 }
98
99 int cw1200_pm_init(struct cw1200_pm_state *pm,
100                    struct cw1200_common *priv)
101 {
102         spin_lock_init(&pm->lock);
103
104         timer_setup(&pm->stay_awake, cw1200_pm_stay_awake_tmo, 0);
105
106         return 0;
107 }
108
109 void cw1200_pm_deinit(struct cw1200_pm_state *pm)
110 {
111         del_timer_sync(&pm->stay_awake);
112 }
113
114 void cw1200_pm_stay_awake(struct cw1200_pm_state *pm,
115                           unsigned long tmo)
116 {
117         long cur_tmo;
118         spin_lock_bh(&pm->lock);
119         cur_tmo = pm->stay_awake.expires - jiffies;
120         if (!timer_pending(&pm->stay_awake) || cur_tmo < (long)tmo)
121                 mod_timer(&pm->stay_awake, jiffies + tmo);
122         spin_unlock_bh(&pm->lock);
123 }
124
125 static long cw1200_suspend_work(struct delayed_work *work)
126 {
127         int ret = cancel_delayed_work(work);
128         long tmo;
129         if (ret > 0) {
130                 /* Timer is pending */
131                 tmo = work->timer.expires - jiffies;
132                 if (tmo < 0)
133                         tmo = 0;
134         } else {
135                 tmo = -1;
136         }
137         return tmo;
138 }
139
140 static int cw1200_resume_work(struct cw1200_common *priv,
141                                struct delayed_work *work,
142                                unsigned long tmo)
143 {
144         if ((long)tmo < 0)
145                 return 1;
146
147         return queue_delayed_work(priv->workqueue, work, tmo);
148 }
149
150 int cw1200_can_suspend(struct cw1200_common *priv)
151 {
152         if (atomic_read(&priv->bh_rx)) {
153                 wiphy_dbg(priv->hw->wiphy, "Suspend interrupted.\n");
154                 return 0;
155         }
156         return 1;
157 }
158 EXPORT_SYMBOL_GPL(cw1200_can_suspend);
159
160 int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
161 {
162         struct cw1200_common *priv = hw->priv;
163         struct cw1200_pm_state *pm_state = &priv->pm_state;
164         struct cw1200_suspend_state *state;
165         int ret;
166
167         spin_lock_bh(&pm_state->lock);
168         ret = timer_pending(&pm_state->stay_awake);
169         spin_unlock_bh(&pm_state->lock);
170         if (ret)
171                 return -EAGAIN;
172
173         /* Do not suspend when datapath is not idle */
174         if (priv->tx_queue_stats.num_queued)
175                 return -EBUSY;
176
177         /* Make sure there is no configuration requests in progress. */
178         if (!mutex_trylock(&priv->conf_mutex))
179                 return -EBUSY;
180
181         /* Ensure pending operations are done.
182          * Note also that wow_suspend must return in ~2.5sec, before
183          * watchdog is triggered.
184          */
185         if (priv->channel_switch_in_progress)
186                 goto revert1;
187
188         /* Do not suspend when join is pending */
189         if (priv->join_pending)
190                 goto revert1;
191
192         /* Do not suspend when scanning */
193         if (down_trylock(&priv->scan.lock))
194                 goto revert1;
195
196         /* Lock TX. */
197         wsm_lock_tx_async(priv);
198
199         /* Wait to avoid possible race with bh code.
200          * But do not wait too long...
201          */
202         if (wait_event_timeout(priv->bh_evt_wq,
203                                !priv->hw_bufs_used, HZ / 10) <= 0)
204                 goto revert2;
205
206         /* Set UDP filter */
207         wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_on.hdr);
208
209         /* Set ethernet frame type filter */
210         wsm_set_ether_type_filter(priv, &cw1200_ether_type_filter_on.hdr);
211
212         /* Allocate state */
213         state = kzalloc(sizeof(struct cw1200_suspend_state), GFP_KERNEL);
214         if (!state)
215                 goto revert3;
216
217         /* Change to legacy PS while going to suspend */
218         if (!priv->vif->p2p &&
219             priv->join_status == CW1200_JOIN_STATUS_STA &&
220             priv->powersave_mode.mode != WSM_PSM_PS) {
221                 state->prev_ps_mode = priv->powersave_mode.mode;
222                 priv->powersave_mode.mode = WSM_PSM_PS;
223                 cw1200_set_pm(priv, &priv->powersave_mode);
224                 if (wait_event_interruptible_timeout(priv->ps_mode_switch_done,
225                                                      !priv->ps_mode_switch_in_progress, 1*HZ) <= 0) {
226                         goto revert4;
227                 }
228         }
229
230         /* Store delayed work states. */
231         state->bss_loss_tmo =
232                 cw1200_suspend_work(&priv->bss_loss_work);
233         state->join_tmo =
234                 cw1200_suspend_work(&priv->join_timeout);
235         state->direct_probe =
236                 cw1200_suspend_work(&priv->scan.probe_work);
237         state->link_id_gc =
238                 cw1200_suspend_work(&priv->link_id_gc_work);
239
240         cancel_delayed_work_sync(&priv->clear_recent_scan_work);
241         atomic_set(&priv->recent_scan, 0);
242
243         /* Enable beacon skipping */
244         if (priv->join_status == CW1200_JOIN_STATUS_STA &&
245             priv->join_dtim_period &&
246             !priv->has_multicast_subscription) {
247                 state->beacon_skipping = true;
248                 wsm_set_beacon_wakeup_period(priv,
249                                              priv->join_dtim_period,
250                                              CW1200_BEACON_SKIPPING_MULTIPLIER * priv->join_dtim_period);
251         }
252
253         /* Stop serving thread */
254         if (cw1200_bh_suspend(priv))
255                 goto revert5;
256
257         ret = timer_pending(&priv->mcast_timeout);
258         if (ret)
259                 goto revert6;
260
261         /* Store suspend state */
262         pm_state->suspend_state = state;
263
264         /* Enable IRQ wake */
265         ret = priv->hwbus_ops->power_mgmt(priv->hwbus_priv, true);
266         if (ret) {
267                 wiphy_err(priv->hw->wiphy,
268                           "PM request failed: %d. WoW is disabled.\n", ret);
269                 cw1200_wow_resume(hw);
270                 return -EBUSY;
271         }
272
273         /* Force resume if event is coming from the device. */
274         if (atomic_read(&priv->bh_rx)) {
275                 cw1200_wow_resume(hw);
276                 return -EAGAIN;
277         }
278
279         return 0;
280
281 revert6:
282         WARN_ON(cw1200_bh_resume(priv));
283 revert5:
284         cw1200_resume_work(priv, &priv->bss_loss_work,
285                            state->bss_loss_tmo);
286         cw1200_resume_work(priv, &priv->join_timeout,
287                            state->join_tmo);
288         cw1200_resume_work(priv, &priv->scan.probe_work,
289                            state->direct_probe);
290         cw1200_resume_work(priv, &priv->link_id_gc_work,
291                            state->link_id_gc);
292 revert4:
293         kfree(state);
294 revert3:
295         wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_off);
296         wsm_set_ether_type_filter(priv, &cw1200_ether_type_filter_off);
297 revert2:
298         wsm_unlock_tx(priv);
299         up(&priv->scan.lock);
300 revert1:
301         mutex_unlock(&priv->conf_mutex);
302         return -EBUSY;
303 }
304
305 int cw1200_wow_resume(struct ieee80211_hw *hw)
306 {
307         struct cw1200_common *priv = hw->priv;
308         struct cw1200_pm_state *pm_state = &priv->pm_state;
309         struct cw1200_suspend_state *state;
310
311         state = pm_state->suspend_state;
312         pm_state->suspend_state = NULL;
313
314         /* Disable IRQ wake */
315         priv->hwbus_ops->power_mgmt(priv->hwbus_priv, false);
316
317         /* Scan.lock must be released before BH is resumed other way
318          * in case when BSS_LOST command arrived the processing of the
319          * command will be delayed.
320          */
321         up(&priv->scan.lock);
322
323         /* Resume BH thread */
324         WARN_ON(cw1200_bh_resume(priv));
325
326         /* Restores previous PS mode */
327         if (!priv->vif->p2p && priv->join_status == CW1200_JOIN_STATUS_STA) {
328                 priv->powersave_mode.mode = state->prev_ps_mode;
329                 cw1200_set_pm(priv, &priv->powersave_mode);
330         }
331
332         if (state->beacon_skipping) {
333                 wsm_set_beacon_wakeup_period(priv, priv->beacon_int *
334                                              priv->join_dtim_period >
335                                              MAX_BEACON_SKIP_TIME_MS ? 1 :
336                                              priv->join_dtim_period, 0);
337                 state->beacon_skipping = false;
338         }
339
340         /* Resume delayed work */
341         cw1200_resume_work(priv, &priv->bss_loss_work,
342                            state->bss_loss_tmo);
343         cw1200_resume_work(priv, &priv->join_timeout,
344                            state->join_tmo);
345         cw1200_resume_work(priv, &priv->scan.probe_work,
346                            state->direct_probe);
347         cw1200_resume_work(priv, &priv->link_id_gc_work,
348                            state->link_id_gc);
349
350         /* Remove UDP port filter */
351         wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_off);
352
353         /* Remove ethernet frame type filter */
354         wsm_set_ether_type_filter(priv, &cw1200_ether_type_filter_off);
355
356         /* Unlock datapath */
357         wsm_unlock_tx(priv);
358
359         /* Unlock configuration mutex */
360         mutex_unlock(&priv->conf_mutex);
361
362         /* Free memory */
363         kfree(state);
364
365         return 0;
366 }