Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / wireless / wl12xx / wl1271_init.c
1 /*
2  * This file is part of wl1271
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  *
6  * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/slab.h>
27
28 #include "wl1271_init.h"
29 #include "wl12xx_80211.h"
30 #include "wl1271_acx.h"
31 #include "wl1271_cmd.h"
32 #include "wl1271_reg.h"
33
34 static int wl1271_init_hwenc_config(struct wl1271 *wl)
35 {
36         int ret;
37
38         ret = wl1271_acx_feature_cfg(wl);
39         if (ret < 0) {
40                 wl1271_warning("couldn't set feature config");
41                 return ret;
42         }
43
44         ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key);
45         if (ret < 0) {
46                 wl1271_warning("couldn't set default key");
47                 return ret;
48         }
49
50         return 0;
51 }
52
53 int wl1271_init_templates_config(struct wl1271 *wl)
54 {
55         int ret;
56
57         /* send empty templates for fw memory reservation */
58         ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
59                                       sizeof(struct wl12xx_probe_req_template));
60         if (ret < 0)
61                 return ret;
62
63         if (wl1271_11a_enabled()) {
64                 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
65                                 NULL,
66                                 sizeof(struct wl12xx_probe_req_template));
67                 if (ret < 0)
68                         return ret;
69         }
70
71         ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
72                                       sizeof(struct wl12xx_null_data_template));
73         if (ret < 0)
74                 return ret;
75
76         ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
77                                       sizeof(struct wl12xx_ps_poll_template));
78         if (ret < 0)
79                 return ret;
80
81         ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
82                                       sizeof
83                                       (struct wl12xx_qos_null_data_template));
84         if (ret < 0)
85                 return ret;
86
87         ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
88                                       sizeof
89                                       (struct wl12xx_probe_resp_template));
90         if (ret < 0)
91                 return ret;
92
93         ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
94                                       sizeof
95                                       (struct wl12xx_beacon_template));
96         if (ret < 0)
97                 return ret;
98
99         return 0;
100 }
101
102 static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
103 {
104         int ret;
105
106         ret = wl1271_acx_rx_msdu_life_time(wl);
107         if (ret < 0)
108                 return ret;
109
110         ret = wl1271_acx_rx_config(wl, config, filter);
111         if (ret < 0)
112                 return ret;
113
114         return 0;
115 }
116
117 int wl1271_init_phy_config(struct wl1271 *wl)
118 {
119         int ret;
120
121         ret = wl1271_acx_pd_threshold(wl);
122         if (ret < 0)
123                 return ret;
124
125         ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME);
126         if (ret < 0)
127                 return ret;
128
129         ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
130         if (ret < 0)
131                 return ret;
132
133         ret = wl1271_acx_service_period_timeout(wl);
134         if (ret < 0)
135                 return ret;
136
137         ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold);
138         if (ret < 0)
139                 return ret;
140
141         return 0;
142 }
143
144 static int wl1271_init_beacon_filter(struct wl1271 *wl)
145 {
146         int ret;
147
148         /* disable beacon filtering at this stage */
149         ret = wl1271_acx_beacon_filter_opt(wl, false);
150         if (ret < 0)
151                 return ret;
152
153         ret = wl1271_acx_beacon_filter_table(wl);
154         if (ret < 0)
155                 return ret;
156
157         return 0;
158 }
159
160 int wl1271_init_pta(struct wl1271 *wl)
161 {
162         int ret;
163
164         ret = wl1271_acx_sg_cfg(wl);
165         if (ret < 0)
166                 return ret;
167
168         ret = wl1271_acx_sg_enable(wl, wl->sg_enabled);
169         if (ret < 0)
170                 return ret;
171
172         return 0;
173 }
174
175 int wl1271_init_energy_detection(struct wl1271 *wl)
176 {
177         int ret;
178
179         ret = wl1271_acx_cca_threshold(wl);
180         if (ret < 0)
181                 return ret;
182
183         return 0;
184 }
185
186 static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
187 {
188         int ret;
189
190         ret = wl1271_acx_bcn_dtim_options(wl);
191         if (ret < 0)
192                 return ret;
193
194         return 0;
195 }
196
197 int wl1271_hw_init(struct wl1271 *wl)
198 {
199         struct conf_tx_ac_category *conf_ac;
200         struct conf_tx_tid *conf_tid;
201         int ret, i;
202
203         ret = wl1271_cmd_general_parms(wl);
204         if (ret < 0)
205                 return ret;
206
207         ret = wl1271_cmd_radio_parms(wl);
208         if (ret < 0)
209                 return ret;
210
211         /* Template settings */
212         ret = wl1271_init_templates_config(wl);
213         if (ret < 0)
214                 return ret;
215
216         /* Default memory configuration */
217         ret = wl1271_acx_init_mem_config(wl);
218         if (ret < 0)
219                 return ret;
220
221         /* RX config */
222         ret = wl1271_init_rx_config(wl,
223                                     RX_CFG_PROMISCUOUS | RX_CFG_TSF,
224                                     RX_FILTER_OPTION_DEF);
225         /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
226            RX_FILTER_OPTION_FILTER_ALL); */
227         if (ret < 0)
228                 goto out_free_memmap;
229
230         /* PHY layer config */
231         ret = wl1271_init_phy_config(wl);
232         if (ret < 0)
233                 goto out_free_memmap;
234
235         ret = wl1271_acx_dco_itrim_params(wl);
236         if (ret < 0)
237                 goto out_free_memmap;
238
239         /* Initialize connection monitoring thresholds */
240         ret = wl1271_acx_conn_monit_params(wl);
241         if (ret < 0)
242                 goto out_free_memmap;
243
244         /* Beacon filtering */
245         ret = wl1271_init_beacon_filter(wl);
246         if (ret < 0)
247                 goto out_free_memmap;
248
249         /* Configure TX patch complete interrupt behavior */
250         ret = wl1271_acx_tx_config_options(wl);
251         if (ret < 0)
252                 goto out_free_memmap;
253
254         /* RX complete interrupt pacing */
255         ret = wl1271_acx_init_rx_interrupt(wl);
256         if (ret < 0)
257                 goto out_free_memmap;
258
259         /* Bluetooth WLAN coexistence */
260         ret = wl1271_init_pta(wl);
261         if (ret < 0)
262                 goto out_free_memmap;
263
264         /* Energy detection */
265         ret = wl1271_init_energy_detection(wl);
266         if (ret < 0)
267                 goto out_free_memmap;
268
269         /* Beacons and boradcast settings */
270         ret = wl1271_init_beacon_broadcast(wl);
271         if (ret < 0)
272                 goto out_free_memmap;
273
274         /* Default fragmentation threshold */
275         ret = wl1271_acx_frag_threshold(wl);
276         if (ret < 0)
277                 goto out_free_memmap;
278
279         /* Default TID configuration */
280         for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
281                 conf_tid = &wl->conf.tx.tid_conf[i];
282                 ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
283                                          conf_tid->channel_type,
284                                          conf_tid->tsid,
285                                          conf_tid->ps_scheme,
286                                          conf_tid->ack_policy,
287                                          conf_tid->apsd_conf[0],
288                                          conf_tid->apsd_conf[1]);
289                 if (ret < 0)
290                         goto out_free_memmap;
291         }
292
293         /* Default AC configuration */
294         for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
295                 conf_ac = &wl->conf.tx.ac_conf[i];
296                 ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
297                                         conf_ac->cw_max, conf_ac->aifsn,
298                                         conf_ac->tx_op_limit);
299                 if (ret < 0)
300                         goto out_free_memmap;
301         }
302
303         /* Configure TX rate classes */
304         ret = wl1271_acx_rate_policies(wl);
305         if (ret < 0)
306                 goto out_free_memmap;
307
308         /* Enable data path */
309         ret = wl1271_cmd_data_path(wl, 1);
310         if (ret < 0)
311                 goto out_free_memmap;
312
313         /* Configure for ELP power saving */
314         ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
315         if (ret < 0)
316                 goto out_free_memmap;
317
318         /* Configure HW encryption */
319         ret = wl1271_init_hwenc_config(wl);
320         if (ret < 0)
321                 goto out_free_memmap;
322
323         /* configure PM */
324         ret = wl1271_acx_pm_config(wl);
325         if (ret < 0)
326                 goto out_free_memmap;
327
328         return 0;
329
330  out_free_memmap:
331         kfree(wl->target_mem_map);
332         wl->target_mem_map = NULL;
333
334         return ret;
335 }