Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ps.c
Go to the documentation of this file.
1 /*
2  * This file is part of wl1251
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * version 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA
19  *
20  */
21 
22 #include "reg.h"
23 #include "ps.h"
24 #include "cmd.h"
25 #include "io.h"
26 
27 /* in ms */
28 #define WL1251_WAKEUP_TIMEOUT 100
29 
31 {
32  struct delayed_work *dwork;
33  struct wl1251 *wl;
34 
35  dwork = container_of(work, struct delayed_work, work);
36  wl = container_of(dwork, struct wl1251, elp_work);
37 
38  wl1251_debug(DEBUG_PSM, "elp work");
39 
40  mutex_lock(&wl->mutex);
41 
42  if (wl->elp || wl->station_mode == STATION_ACTIVE_MODE)
43  goto out;
44 
45  wl1251_debug(DEBUG_PSM, "chip to elp");
46  wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
47  wl->elp = true;
48 
49 out:
50  mutex_unlock(&wl->mutex);
51 }
52 
53 #define ELP_ENTRY_DELAY 5
54 
55 /* Routines to toggle sleep mode while in ELP */
56 void wl1251_ps_elp_sleep(struct wl1251 *wl)
57 {
58  unsigned long delay;
59 
60  if (wl->station_mode != STATION_ACTIVE_MODE) {
62  ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay);
63  }
64 }
65 
67 {
68  unsigned long timeout, start;
69  u32 elp_reg;
70 
73 
74  if (!wl->elp)
75  return 0;
76 
77  wl1251_debug(DEBUG_PSM, "waking up chip from elp");
78 
79  start = jiffies;
81 
82  wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
83 
84  elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
85 
86  /*
87  * FIXME: we should wait for irq from chip but, as a temporary
88  * solution to simplify locking, let's poll instead
89  */
90  while (!(elp_reg & ELPCTRL_WLAN_READY)) {
91  if (time_after(jiffies, timeout)) {
92  wl1251_error("elp wakeup timeout");
93  return -ETIMEDOUT;
94  }
95  msleep(1);
96  elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
97  }
98 
99  wl1251_debug(DEBUG_PSM, "wakeup time: %u ms",
100  jiffies_to_msecs(jiffies - start));
101 
102  wl->elp = false;
103 
104  return 0;
105 }
106 
108 {
109  int ret;
110 
111  switch (mode) {
113  wl1251_debug(DEBUG_PSM, "entering psm");
114 
115  /* enable beacon filtering */
116  ret = wl1251_acx_beacon_filter_opt(wl, true);
117  if (ret < 0)
118  return ret;
119 
122  wl->listen_int);
123  if (ret < 0)
124  return ret;
125 
128  if (ret < 0)
129  return ret;
130 
132  if (ret < 0)
133  return ret;
134 
136  if (ret < 0)
137  return ret;
138  break;
139  case STATION_IDLE:
140  wl1251_debug(DEBUG_PSM, "entering idle");
141 
143  if (ret < 0)
144  return ret;
145 
147  if (ret < 0)
148  return ret;
149  break;
150  case STATION_ACTIVE_MODE:
151  default:
152  wl1251_debug(DEBUG_PSM, "leaving psm");
153 
155  if (ret < 0)
156  return ret;
157 
158  /* disable BET */
161  if (ret < 0)
162  return ret;
163 
164  /* disable beacon filtering */
165  ret = wl1251_acx_beacon_filter_opt(wl, false);
166  if (ret < 0)
167  return ret;
168 
171  wl->listen_int);
172  if (ret < 0)
173  return ret;
174 
176  if (ret < 0)
177  return ret;
178 
179  break;
180  }
181  wl->station_mode = mode;
182 
183  return ret;
184 }
185