• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/net/wireless/wl12xx/
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
34static 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
53int wl1271_init_templates_config(struct wl1271 *wl)
54{
55	int ret, i;
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				      0, WL1271_RATE_AUTOMATIC);
61	if (ret < 0)
62		return ret;
63
64	if (wl1271_11a_enabled()) {
65		size_t size = sizeof(struct wl12xx_probe_req_template);
66		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
67					      NULL, size, 0,
68					      WL1271_RATE_AUTOMATIC);
69		if (ret < 0)
70			return ret;
71	}
72
73	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
74				      sizeof(struct wl12xx_null_data_template),
75				      0, WL1271_RATE_AUTOMATIC);
76	if (ret < 0)
77		return ret;
78
79	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
80				      sizeof(struct wl12xx_ps_poll_template),
81				      0, WL1271_RATE_AUTOMATIC);
82	if (ret < 0)
83		return ret;
84
85	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
86				      sizeof
87				      (struct wl12xx_qos_null_data_template),
88				      0, WL1271_RATE_AUTOMATIC);
89	if (ret < 0)
90		return ret;
91
92	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
93				      sizeof
94				      (struct wl12xx_probe_resp_template),
95				      0, WL1271_RATE_AUTOMATIC);
96	if (ret < 0)
97		return ret;
98
99	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
100				      sizeof
101				      (struct wl12xx_beacon_template),
102				      0, WL1271_RATE_AUTOMATIC);
103	if (ret < 0)
104		return ret;
105
106	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
107		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
108					      WL1271_CMD_TEMPL_MAX_SIZE, i,
109					      WL1271_RATE_AUTOMATIC);
110		if (ret < 0)
111			return ret;
112	}
113
114	return 0;
115}
116
117static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
118{
119	int ret;
120
121	ret = wl1271_acx_rx_msdu_life_time(wl);
122	if (ret < 0)
123		return ret;
124
125	ret = wl1271_acx_rx_config(wl, config, filter);
126	if (ret < 0)
127		return ret;
128
129	return 0;
130}
131
132int wl1271_init_phy_config(struct wl1271 *wl)
133{
134	int ret;
135
136	ret = wl1271_acx_pd_threshold(wl);
137	if (ret < 0)
138		return ret;
139
140	ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME);
141	if (ret < 0)
142		return ret;
143
144	ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
145	if (ret < 0)
146		return ret;
147
148	ret = wl1271_acx_service_period_timeout(wl);
149	if (ret < 0)
150		return ret;
151
152	ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold);
153	if (ret < 0)
154		return ret;
155
156	return 0;
157}
158
159static int wl1271_init_beacon_filter(struct wl1271 *wl)
160{
161	int ret;
162
163	/* disable beacon filtering at this stage */
164	ret = wl1271_acx_beacon_filter_opt(wl, false);
165	if (ret < 0)
166		return ret;
167
168	ret = wl1271_acx_beacon_filter_table(wl);
169	if (ret < 0)
170		return ret;
171
172	return 0;
173}
174
175int wl1271_init_pta(struct wl1271 *wl)
176{
177	int ret;
178
179	ret = wl1271_acx_sg_cfg(wl);
180	if (ret < 0)
181		return ret;
182
183	ret = wl1271_acx_sg_enable(wl, wl->sg_enabled);
184	if (ret < 0)
185		return ret;
186
187	return 0;
188}
189
190int wl1271_init_energy_detection(struct wl1271 *wl)
191{
192	int ret;
193
194	ret = wl1271_acx_cca_threshold(wl);
195	if (ret < 0)
196		return ret;
197
198	return 0;
199}
200
201static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
202{
203	int ret;
204
205	ret = wl1271_acx_bcn_dtim_options(wl);
206	if (ret < 0)
207		return ret;
208
209	return 0;
210}
211
212int wl1271_hw_init(struct wl1271 *wl)
213{
214	struct conf_tx_ac_category *conf_ac;
215	struct conf_tx_tid *conf_tid;
216	int ret, i;
217
218	ret = wl1271_cmd_general_parms(wl);
219	if (ret < 0)
220		return ret;
221
222	ret = wl1271_cmd_radio_parms(wl);
223	if (ret < 0)
224		return ret;
225
226	/* Template settings */
227	ret = wl1271_init_templates_config(wl);
228	if (ret < 0)
229		return ret;
230
231	/* Default memory configuration */
232	ret = wl1271_acx_init_mem_config(wl);
233	if (ret < 0)
234		return ret;
235
236	/* RX config */
237	ret = wl1271_init_rx_config(wl,
238				    RX_CFG_PROMISCUOUS | RX_CFG_TSF,
239				    RX_FILTER_OPTION_DEF);
240	/* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
241	   RX_FILTER_OPTION_FILTER_ALL); */
242	if (ret < 0)
243		goto out_free_memmap;
244
245	/* PHY layer config */
246	ret = wl1271_init_phy_config(wl);
247	if (ret < 0)
248		goto out_free_memmap;
249
250	ret = wl1271_acx_dco_itrim_params(wl);
251	if (ret < 0)
252		goto out_free_memmap;
253
254	/* Initialize connection monitoring thresholds */
255	ret = wl1271_acx_conn_monit_params(wl, false);
256	if (ret < 0)
257		goto out_free_memmap;
258
259	/* Beacon filtering */
260	ret = wl1271_init_beacon_filter(wl);
261	if (ret < 0)
262		goto out_free_memmap;
263
264	/* Configure TX patch complete interrupt behavior */
265	ret = wl1271_acx_tx_config_options(wl);
266	if (ret < 0)
267		goto out_free_memmap;
268
269	/* RX complete interrupt pacing */
270	ret = wl1271_acx_init_rx_interrupt(wl);
271	if (ret < 0)
272		goto out_free_memmap;
273
274	/* Bluetooth WLAN coexistence */
275	ret = wl1271_init_pta(wl);
276	if (ret < 0)
277		goto out_free_memmap;
278
279	/* Energy detection */
280	ret = wl1271_init_energy_detection(wl);
281	if (ret < 0)
282		goto out_free_memmap;
283
284	/* Beacons and boradcast settings */
285	ret = wl1271_init_beacon_broadcast(wl);
286	if (ret < 0)
287		goto out_free_memmap;
288
289	/* Default fragmentation threshold */
290	ret = wl1271_acx_frag_threshold(wl);
291	if (ret < 0)
292		goto out_free_memmap;
293
294	/* Default TID configuration */
295	for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
296		conf_tid = &wl->conf.tx.tid_conf[i];
297		ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
298					 conf_tid->channel_type,
299					 conf_tid->tsid,
300					 conf_tid->ps_scheme,
301					 conf_tid->ack_policy,
302					 conf_tid->apsd_conf[0],
303					 conf_tid->apsd_conf[1]);
304		if (ret < 0)
305			goto out_free_memmap;
306	}
307
308	/* Default AC configuration */
309	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
310		conf_ac = &wl->conf.tx.ac_conf[i];
311		ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
312					conf_ac->cw_max, conf_ac->aifsn,
313					conf_ac->tx_op_limit);
314		if (ret < 0)
315			goto out_free_memmap;
316	}
317
318	/* Configure TX rate classes */
319	ret = wl1271_acx_rate_policies(wl);
320	if (ret < 0)
321		goto out_free_memmap;
322
323	/* Enable data path */
324	ret = wl1271_cmd_data_path(wl, 1);
325	if (ret < 0)
326		goto out_free_memmap;
327
328	/* Configure for ELP power saving */
329	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
330	if (ret < 0)
331		goto out_free_memmap;
332
333	/* Configure HW encryption */
334	ret = wl1271_init_hwenc_config(wl);
335	if (ret < 0)
336		goto out_free_memmap;
337
338	/* configure PM */
339	ret = wl1271_acx_pm_config(wl);
340	if (ret < 0)
341		goto out_free_memmap;
342
343	/* disable all keep-alive templates */
344	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
345		ret = wl1271_acx_keep_alive_config(wl, i,
346						   ACX_KEEP_ALIVE_TPL_INVALID);
347		if (ret < 0)
348			goto out_free_memmap;
349	}
350
351	/* disable the keep-alive feature */
352	ret = wl1271_acx_keep_alive_mode(wl, false);
353	if (ret < 0)
354		goto out_free_memmap;
355
356	/* Configure rssi/snr averaging weights */
357	ret = wl1271_acx_rssi_snr_avg_weights(wl);
358	if (ret < 0)
359		goto out_free_memmap;
360
361	return 0;
362
363 out_free_memmap:
364	kfree(wl->target_mem_map);
365	wl->target_mem_map = NULL;
366
367	return ret;
368}
369