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
init.c
Go to the documentation of this file.
1
/*
2
* This file is part of wl1251
3
*
4
* Copyright (C) 2009 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 <linux/kernel.h>
23
#include <linux/module.h>
24
#include <linux/slab.h>
25
26
#include "
init.h
"
27
#include "
wl12xx_80211.h
"
28
#include "
acx.h
"
29
#include "
cmd.h
"
30
#include "
reg.h
"
31
32
int
wl1251_hw_init_hwenc_config
(
struct
wl1251
*wl)
33
{
34
int
ret
;
35
36
ret =
wl1251_acx_feature_cfg
(wl);
37
if
(ret < 0) {
38
wl1251_warning
(
"couldn't set feature config"
);
39
return
ret
;
40
}
41
42
ret =
wl1251_acx_default_key
(wl, wl->
default_key
);
43
if
(ret < 0) {
44
wl1251_warning
(
"couldn't set default key"
);
45
return
ret
;
46
}
47
48
return
0;
49
}
50
51
int
wl1251_hw_init_templates_config
(
struct
wl1251
*wl)
52
{
53
int
ret
;
54
u8
partial_vbm[
PARTIAL_VBM_MAX
];
55
56
/* send empty templates for fw memory reservation */
57
ret =
wl1251_cmd_template_set
(wl,
CMD_PROBE_REQ
,
NULL
,
58
sizeof
(
struct
wl12xx_probe_req_template
));
59
if
(ret < 0)
60
return
ret
;
61
62
ret =
wl1251_cmd_template_set
(wl,
CMD_NULL_DATA
,
NULL
,
63
sizeof
(
struct
wl12xx_null_data_template
));
64
if
(ret < 0)
65
return
ret
;
66
67
ret =
wl1251_cmd_template_set
(wl,
CMD_PS_POLL
,
NULL
,
68
sizeof
(
struct
wl12xx_ps_poll_template
));
69
if
(ret < 0)
70
return
ret
;
71
72
ret =
wl1251_cmd_template_set
(wl,
CMD_QOS_NULL_DATA
,
NULL
,
73
sizeof
74
(
struct
wl12xx_qos_null_data_template
));
75
if
(ret < 0)
76
return
ret
;
77
78
ret =
wl1251_cmd_template_set
(wl,
CMD_PROBE_RESP
,
NULL
,
79
sizeof
80
(
struct
wl12xx_probe_resp_template
));
81
if
(ret < 0)
82
return
ret
;
83
84
ret =
wl1251_cmd_template_set
(wl,
CMD_BEACON
,
NULL
,
85
sizeof
86
(
struct
wl12xx_beacon_template
));
87
if
(ret < 0)
88
return
ret
;
89
90
/* tim templates, first reserve space then allocate an empty one */
91
memset
(partial_vbm, 0,
PARTIAL_VBM_MAX
);
92
ret =
wl1251_cmd_vbm
(wl,
TIM_ELE_ID
, partial_vbm,
PARTIAL_VBM_MAX
, 0);
93
if
(ret < 0)
94
return
ret
;
95
96
ret =
wl1251_cmd_vbm
(wl,
TIM_ELE_ID
, partial_vbm, 1, 0);
97
if
(ret < 0)
98
return
ret
;
99
100
return
0;
101
}
102
103
int
wl1251_hw_init_rx_config
(
struct
wl1251
*wl,
u32
config
,
u32
filter
)
104
{
105
int
ret
;
106
107
ret =
wl1251_acx_rx_msdu_life_time
(wl,
RX_MSDU_LIFETIME_DEF
);
108
if
(ret < 0)
109
return
ret
;
110
111
ret =
wl1251_acx_rx_config
(wl, config, filter);
112
if
(ret < 0)
113
return
ret
;
114
115
return
0;
116
}
117
118
int
wl1251_hw_init_phy_config
(
struct
wl1251
*wl)
119
{
120
int
ret
;
121
122
ret =
wl1251_acx_pd_threshold
(wl);
123
if
(ret < 0)
124
return
ret
;
125
126
ret =
wl1251_acx_slot
(wl,
DEFAULT_SLOT_TIME
);
127
if
(ret < 0)
128
return
ret
;
129
130
ret =
wl1251_acx_group_address_tbl
(wl);
131
if
(ret < 0)
132
return
ret
;
133
134
ret =
wl1251_acx_service_period_timeout
(wl);
135
if
(ret < 0)
136
return
ret
;
137
138
ret =
wl1251_acx_rts_threshold
(wl,
RTS_THRESHOLD_DEF
);
139
if
(ret < 0)
140
return
ret
;
141
142
return
0;
143
}
144
145
int
wl1251_hw_init_beacon_filter
(
struct
wl1251
*wl)
146
{
147
int
ret
;
148
149
/* disable beacon filtering at this stage */
150
ret =
wl1251_acx_beacon_filter_opt
(wl,
false
);
151
if
(ret < 0)
152
return
ret
;
153
154
ret =
wl1251_acx_beacon_filter_table
(wl);
155
if
(ret < 0)
156
return
ret
;
157
158
return
0;
159
}
160
161
int
wl1251_hw_init_pta
(
struct
wl1251
*wl)
162
{
163
int
ret
;
164
165
ret =
wl1251_acx_sg_enable
(wl);
166
if
(ret < 0)
167
return
ret
;
168
169
ret =
wl1251_acx_sg_cfg
(wl);
170
if
(ret < 0)
171
return
ret
;
172
173
return
0;
174
}
175
176
int
wl1251_hw_init_energy_detection
(
struct
wl1251
*wl)
177
{
178
int
ret
;
179
180
ret =
wl1251_acx_cca_threshold
(wl);
181
if
(ret < 0)
182
return
ret
;
183
184
return
0;
185
}
186
187
int
wl1251_hw_init_beacon_broadcast
(
struct
wl1251
*wl)
188
{
189
int
ret
;
190
191
ret =
wl1251_acx_bcn_dtim_options
(wl);
192
if
(ret < 0)
193
return
ret
;
194
195
return
0;
196
}
197
198
int
wl1251_hw_init_power_auth
(
struct
wl1251
*wl)
199
{
200
return
wl1251_acx_sleep_auth
(wl,
WL1251_PSM_CAM
);
201
}
202
203
int
wl1251_hw_init_mem_config
(
struct
wl1251
*wl)
204
{
205
int
ret
;
206
207
ret =
wl1251_acx_mem_cfg
(wl);
208
if
(ret < 0)
209
return
ret
;
210
211
wl->
target_mem_map
= kzalloc(
sizeof
(
struct
wl1251_acx_mem_map
),
212
GFP_KERNEL
);
213
if
(!wl->
target_mem_map
) {
214
wl1251_error
(
"couldn't allocate target memory map"
);
215
return
-
ENOMEM
;
216
}
217
218
/* we now ask for the firmware built memory map */
219
ret =
wl1251_acx_mem_map
(wl, wl->
target_mem_map
,
220
sizeof
(
struct
wl1251_acx_mem_map
));
221
if
(ret < 0) {
222
wl1251_error
(
"couldn't retrieve firmware memory map"
);
223
kfree
(wl->
target_mem_map
);
224
wl->
target_mem_map
=
NULL
;
225
return
ret
;
226
}
227
228
return
0;
229
}
230
231
static
int
wl1251_hw_init_txq_fill(
u8
qid
,
232
struct
acx_tx_queue_qos_config
*
config
,
233
u32
num_blocks)
234
{
235
config->
qid
=
qid
;
236
237
switch
(qid) {
238
case
QOS_AC_BE
:
239
config->
high_threshold
=
240
(
QOS_TX_HIGH_BE_DEF
* num_blocks) / 100;
241
config->
low_threshold
=
242
(
QOS_TX_LOW_BE_DEF
* num_blocks) / 100;
243
break
;
244
case
QOS_AC_BK
:
245
config->
high_threshold
=
246
(
QOS_TX_HIGH_BK_DEF
* num_blocks) / 100;
247
config->
low_threshold
=
248
(
QOS_TX_LOW_BK_DEF
* num_blocks) / 100;
249
break
;
250
case
QOS_AC_VI
:
251
config->
high_threshold
=
252
(
QOS_TX_HIGH_VI_DEF
* num_blocks) / 100;
253
config->
low_threshold
=
254
(
QOS_TX_LOW_VI_DEF
* num_blocks) / 100;
255
break
;
256
case
QOS_AC_VO
:
257
config->
high_threshold
=
258
(
QOS_TX_HIGH_VO_DEF
* num_blocks) / 100;
259
config->
low_threshold
=
260
(
QOS_TX_LOW_VO_DEF
* num_blocks) / 100;
261
break
;
262
default
:
263
wl1251_error
(
"Invalid TX queue id: %d"
, qid);
264
return
-
EINVAL
;
265
}
266
267
return
0;
268
}
269
270
static
int
wl1251_hw_init_tx_queue_config(
struct
wl1251
*wl)
271
{
272
struct
acx_tx_queue_qos_config
*
config
;
273
struct
wl1251_acx_mem_map
*wl_mem_map = wl->
target_mem_map
;
274
int
ret
,
i
;
275
276
wl1251_debug
(
DEBUG_ACX
,
"acx tx queue config"
);
277
278
config = kzalloc(
sizeof
(*config),
GFP_KERNEL
);
279
if
(!config) {
280
ret = -
ENOMEM
;
281
goto
out
;
282
}
283
284
for
(i = 0; i <
MAX_NUM_OF_AC
; i++) {
285
ret = wl1251_hw_init_txq_fill(i, config,
286
wl_mem_map->
num_tx_mem_blocks
);
287
if
(ret < 0)
288
goto
out
;
289
290
ret =
wl1251_cmd_configure
(wl,
ACX_TX_QUEUE_CFG
,
291
config,
sizeof
(*config));
292
if
(ret < 0)
293
goto
out
;
294
}
295
296
wl1251_acx_ac_cfg
(wl,
AC_BE
,
CWMIN_BE
,
CWMAX_BE
,
AIFS_DIFS
,
TXOP_BE
);
297
wl1251_acx_ac_cfg
(wl,
AC_BK
,
CWMIN_BK
,
CWMAX_BK
,
AIFS_DIFS
,
TXOP_BK
);
298
wl1251_acx_ac_cfg
(wl,
AC_VI
,
CWMIN_VI
,
CWMAX_VI
,
AIFS_DIFS
,
TXOP_VI
);
299
wl1251_acx_ac_cfg
(wl,
AC_VO
,
CWMIN_VO
,
CWMAX_VO
,
AIFS_DIFS
,
TXOP_VO
);
300
301
out
:
302
kfree
(config);
303
return
ret
;
304
}
305
306
static
int
wl1251_hw_init_data_path_config(
struct
wl1251
*wl)
307
{
308
int
ret
;
309
310
/* asking for the data path parameters */
311
wl->
data_path
= kzalloc(
sizeof
(
struct
acx_data_path_params_resp
),
312
GFP_KERNEL
);
313
if
(!wl->
data_path
) {
314
wl1251_error
(
"Couldnt allocate data path parameters"
);
315
return
-
ENOMEM
;
316
}
317
318
ret =
wl1251_acx_data_path_params
(wl, wl->
data_path
);
319
if
(ret < 0) {
320
kfree
(wl->
data_path
);
321
wl->
data_path
=
NULL
;
322
return
ret
;
323
}
324
325
return
0;
326
}
327
328
329
int
wl1251_hw_init
(
struct
wl1251
*wl)
330
{
331
struct
wl1251_acx_mem_map
*wl_mem_map;
332
int
ret
;
333
334
ret =
wl1251_hw_init_hwenc_config
(wl);
335
if
(ret < 0)
336
return
ret
;
337
338
/* Template settings */
339
ret =
wl1251_hw_init_templates_config
(wl);
340
if
(ret < 0)
341
return
ret
;
342
343
/* Default memory configuration */
344
ret =
wl1251_hw_init_mem_config
(wl);
345
if
(ret < 0)
346
return
ret
;
347
348
/* Default data path configuration */
349
ret = wl1251_hw_init_data_path_config(wl);
350
if
(ret < 0)
351
goto
out_free_memmap;
352
353
/* RX config */
354
ret =
wl1251_hw_init_rx_config
(wl,
355
RX_CFG_PROMISCUOUS
|
RX_CFG_TSF
,
356
RX_FILTER_OPTION_DEF
);
357
/* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
358
RX_FILTER_OPTION_FILTER_ALL); */
359
if
(ret < 0)
360
goto
out_free_data_path;
361
362
/* TX queues config */
363
ret = wl1251_hw_init_tx_queue_config(wl);
364
if
(ret < 0)
365
goto
out_free_data_path;
366
367
/* PHY layer config */
368
ret =
wl1251_hw_init_phy_config
(wl);
369
if
(ret < 0)
370
goto
out_free_data_path;
371
372
/* Initialize connection monitoring thresholds */
373
ret =
wl1251_acx_conn_monit_params
(wl);
374
if
(ret < 0)
375
goto
out_free_data_path;
376
377
/* Beacon filtering */
378
ret =
wl1251_hw_init_beacon_filter
(wl);
379
if
(ret < 0)
380
goto
out_free_data_path;
381
382
/* Bluetooth WLAN coexistence */
383
ret =
wl1251_hw_init_pta
(wl);
384
if
(ret < 0)
385
goto
out_free_data_path;
386
387
/* Energy detection */
388
ret =
wl1251_hw_init_energy_detection
(wl);
389
if
(ret < 0)
390
goto
out_free_data_path;
391
392
/* Beacons and boradcast settings */
393
ret =
wl1251_hw_init_beacon_broadcast
(wl);
394
if
(ret < 0)
395
goto
out_free_data_path;
396
397
/* Enable data path */
398
ret =
wl1251_cmd_data_path
(wl, wl->
channel
, 1);
399
if
(ret < 0)
400
goto
out_free_data_path;
401
402
/* Default power state */
403
ret =
wl1251_hw_init_power_auth
(wl);
404
if
(ret < 0)
405
goto
out_free_data_path;
406
407
wl_mem_map = wl->
target_mem_map
;
408
wl1251_info
(
"%d tx blocks at 0x%x, %d rx blocks at 0x%x"
,
409
wl_mem_map->
num_tx_mem_blocks
,
410
wl->
data_path
->tx_control_addr,
411
wl_mem_map->
num_rx_mem_blocks
,
412
wl->
data_path
->rx_control_addr);
413
414
return
0;
415
416
out_free_data_path:
417
kfree
(wl->
data_path
);
418
419
out_free_memmap:
420
kfree
(wl->
target_mem_map
);
421
422
return
ret
;
423
}
Generated on Thu Jan 10 2013 12:54:15 for Linux Kernel by
1.8.2