Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
net
wireless
ti
wl1251
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
30
void
wl1251_elp_work
(
struct
work_struct
*
work
)
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
) {
61
delay =
msecs_to_jiffies
(
ELP_ENTRY_DELAY
);
62
ieee80211_queue_delayed_work
(wl->
hw
, &wl->
elp_work
, delay);
63
}
64
}
65
66
int
wl1251_ps_elp_wakeup
(
struct
wl1251
*wl)
67
{
68
unsigned
long
timeout
,
start
;
69
u32
elp_reg;
70
71
if
(
delayed_work_pending
(&wl->
elp_work
))
72
cancel_delayed_work
(&wl->
elp_work
);
73
74
if
(!wl->
elp
)
75
return
0;
76
77
wl1251_debug
(
DEBUG_PSM
,
"waking up chip from elp"
);
78
79
start =
jiffies
;
80
timeout =
jiffies
+
msecs_to_jiffies
(
WL1251_WAKEUP_TIMEOUT
);
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
107
int
wl1251_ps_set_mode
(
struct
wl1251
*wl,
enum
wl1251_station_mode
mode
)
108
{
109
int
ret
;
110
111
switch
(mode) {
112
case
STATION_POWER_SAVE_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
120
ret =
wl1251_acx_wake_up_conditions
(wl,
121
WAKE_UP_EVENT_DTIM_BITMAP
,
122
wl->
listen_int
);
123
if
(ret < 0)
124
return
ret
;
125
126
ret =
wl1251_acx_bet_enable
(wl,
WL1251_ACX_BET_ENABLE
,
127
WL1251_DEFAULT_BET_CONSECUTIVE
);
128
if
(ret < 0)
129
return
ret
;
130
131
ret =
wl1251_cmd_ps_mode
(wl,
CHIP_POWER_SAVE_MODE
);
132
if
(ret < 0)
133
return
ret
;
134
135
ret =
wl1251_acx_sleep_auth
(wl,
WL1251_PSM_ELP
);
136
if
(ret < 0)
137
return
ret
;
138
break
;
139
case
STATION_IDLE
:
140
wl1251_debug
(
DEBUG_PSM
,
"entering idle"
);
141
142
ret =
wl1251_acx_sleep_auth
(wl,
WL1251_PSM_ELP
);
143
if
(ret < 0)
144
return
ret
;
145
146
ret =
wl1251_cmd_template_set
(wl,
CMD_DISCONNECT
,
NULL
, 0);
147
if
(ret < 0)
148
return
ret
;
149
break
;
150
case
STATION_ACTIVE_MODE
:
151
default
:
152
wl1251_debug
(
DEBUG_PSM
,
"leaving psm"
);
153
154
ret =
wl1251_acx_sleep_auth
(wl,
WL1251_PSM_CAM
);
155
if
(ret < 0)
156
return
ret
;
157
158
/* disable BET */
159
ret =
wl1251_acx_bet_enable
(wl,
WL1251_ACX_BET_DISABLE
,
160
WL1251_DEFAULT_BET_CONSECUTIVE
);
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
169
ret =
wl1251_acx_wake_up_conditions
(wl,
170
WAKE_UP_EVENT_DTIM_BITMAP
,
171
wl->
listen_int
);
172
if
(ret < 0)
173
return
ret
;
174
175
ret =
wl1251_cmd_ps_mode
(wl,
CHIP_ACTIVE_MODE
);
176
if
(ret < 0)
177
return
ret
;
178
179
break
;
180
}
181
wl->
station_mode
=
mode
;
182
183
return
ret
;
184
}
185
Generated on Thu Jan 10 2013 14:13:02 for Linux Kernel by
1.8.2