• 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/drivers/net/wireless/wl12xx/
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-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 "wl1271_acx.h"
25
26#include <linux/module.h>
27#include <linux/platform_device.h>
28#include <linux/crc7.h>
29#include <linux/spi/spi.h>
30#include <linux/slab.h>
31
32#include "wl1271.h"
33#include "wl12xx_80211.h"
34#include "wl1271_reg.h"
35#include "wl1271_ps.h"
36
37int wl1271_acx_wake_up_conditions(struct wl1271 *wl)
38{
39	struct acx_wake_up_condition *wake_up;
40	int ret;
41
42	wl1271_debug(DEBUG_ACX, "acx wake up conditions");
43
44	wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
45	if (!wake_up) {
46		ret = -ENOMEM;
47		goto out;
48	}
49
50	wake_up->wake_up_event = wl->conf.conn.wake_up_event;
51	wake_up->listen_interval = wl->conf.conn.listen_interval;
52
53	ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
54				   wake_up, sizeof(*wake_up));
55	if (ret < 0) {
56		wl1271_warning("could not set wake up conditions: %d", ret);
57		goto out;
58	}
59
60out:
61	kfree(wake_up);
62	return ret;
63}
64
65int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
66{
67	struct acx_sleep_auth *auth;
68	int ret;
69
70	wl1271_debug(DEBUG_ACX, "acx sleep auth");
71
72	auth = kzalloc(sizeof(*auth), GFP_KERNEL);
73	if (!auth) {
74		ret = -ENOMEM;
75		goto out;
76	}
77
78	auth->sleep_auth = sleep_auth;
79
80	ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
81	if (ret < 0)
82		return ret;
83
84out:
85	kfree(auth);
86	return ret;
87}
88
89int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len)
90{
91	struct acx_revision *rev;
92	int ret;
93
94	wl1271_debug(DEBUG_ACX, "acx fw rev");
95
96	rev = kzalloc(sizeof(*rev), GFP_KERNEL);
97	if (!rev) {
98		ret = -ENOMEM;
99		goto out;
100	}
101
102	ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
103	if (ret < 0) {
104		wl1271_warning("ACX_FW_REV interrogate failed");
105		goto out;
106	}
107
108	/* be careful with the buffer sizes */
109	strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
110
111	/*
112	 * if the firmware version string is exactly
113	 * sizeof(rev->fw_version) long or fw_len is less than
114	 * sizeof(rev->fw_version) it won't be null terminated
115	 */
116	buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
117
118out:
119	kfree(rev);
120	return ret;
121}
122
123int wl1271_acx_tx_power(struct wl1271 *wl, int power)
124{
125	struct acx_current_tx_power *acx;
126	int ret;
127
128	wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
129
130	if (power < 0 || power > 25)
131		return -EINVAL;
132
133	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
134	if (!acx) {
135		ret = -ENOMEM;
136		goto out;
137	}
138
139	acx->current_tx_power = power * 10;
140
141	ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
142	if (ret < 0) {
143		wl1271_warning("configure of tx power failed: %d", ret);
144		goto out;
145	}
146
147out:
148	kfree(acx);
149	return ret;
150}
151
152int wl1271_acx_feature_cfg(struct wl1271 *wl)
153{
154	struct acx_feature_config *feature;
155	int ret;
156
157	wl1271_debug(DEBUG_ACX, "acx feature cfg");
158
159	feature = kzalloc(sizeof(*feature), GFP_KERNEL);
160	if (!feature) {
161		ret = -ENOMEM;
162		goto out;
163	}
164
165	/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
166	feature->data_flow_options = 0;
167	feature->options = 0;
168
169	ret = wl1271_cmd_configure(wl, ACX_FEATURE_CFG,
170				   feature, sizeof(*feature));
171	if (ret < 0) {
172		wl1271_error("Couldnt set HW encryption");
173		goto out;
174	}
175
176out:
177	kfree(feature);
178	return ret;
179}
180
181int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map,
182		       size_t len)
183{
184	int ret;
185
186	wl1271_debug(DEBUG_ACX, "acx mem map");
187
188	ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
189	if (ret < 0)
190		return ret;
191
192	return 0;
193}
194
195int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl)
196{
197	struct acx_rx_msdu_lifetime *acx;
198	int ret;
199
200	wl1271_debug(DEBUG_ACX, "acx rx msdu life time");
201
202	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
203	if (!acx) {
204		ret = -ENOMEM;
205		goto out;
206	}
207
208	acx->lifetime = cpu_to_le32(wl->conf.rx.rx_msdu_life_time);
209	ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
210				   acx, sizeof(*acx));
211	if (ret < 0) {
212		wl1271_warning("failed to set rx msdu life time: %d", ret);
213		goto out;
214	}
215
216out:
217	kfree(acx);
218	return ret;
219}
220
221int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter)
222{
223	struct acx_rx_config *rx_config;
224	int ret;
225
226	wl1271_debug(DEBUG_ACX, "acx rx config");
227
228	rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
229	if (!rx_config) {
230		ret = -ENOMEM;
231		goto out;
232	}
233
234	rx_config->config_options = cpu_to_le32(config);
235	rx_config->filter_options = cpu_to_le32(filter);
236
237	ret = wl1271_cmd_configure(wl, ACX_RX_CFG,
238				   rx_config, sizeof(*rx_config));
239	if (ret < 0) {
240		wl1271_warning("failed to set rx config: %d", ret);
241		goto out;
242	}
243
244out:
245	kfree(rx_config);
246	return ret;
247}
248
249int wl1271_acx_pd_threshold(struct wl1271 *wl)
250{
251	struct acx_packet_detection *pd;
252	int ret;
253
254	wl1271_debug(DEBUG_ACX, "acx data pd threshold");
255
256	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
257	if (!pd) {
258		ret = -ENOMEM;
259		goto out;
260	}
261
262	pd->threshold = cpu_to_le32(wl->conf.rx.packet_detection_threshold);
263
264	ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
265	if (ret < 0) {
266		wl1271_warning("failed to set pd threshold: %d", ret);
267		goto out;
268	}
269
270out:
271	kfree(pd);
272	return 0;
273}
274
275int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
276{
277	struct acx_slot *slot;
278	int ret;
279
280	wl1271_debug(DEBUG_ACX, "acx slot");
281
282	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
283	if (!slot) {
284		ret = -ENOMEM;
285		goto out;
286	}
287
288	slot->wone_index = STATION_WONE_INDEX;
289	slot->slot_time = slot_time;
290
291	ret = wl1271_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
292	if (ret < 0) {
293		wl1271_warning("failed to set slot time: %d", ret);
294		goto out;
295	}
296
297out:
298	kfree(slot);
299	return ret;
300}
301
302int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
303				 void *mc_list, u32 mc_list_len)
304{
305	struct acx_dot11_grp_addr_tbl *acx;
306	int ret;
307
308	wl1271_debug(DEBUG_ACX, "acx group address tbl");
309
310	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
311	if (!acx) {
312		ret = -ENOMEM;
313		goto out;
314	}
315
316	/* MAC filtering */
317	acx->enabled = enable;
318	acx->num_groups = mc_list_len;
319	memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
320
321	ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
322				   acx, sizeof(*acx));
323	if (ret < 0) {
324		wl1271_warning("failed to set group addr table: %d", ret);
325		goto out;
326	}
327
328out:
329	kfree(acx);
330	return ret;
331}
332
333int wl1271_acx_service_period_timeout(struct wl1271 *wl)
334{
335	struct acx_rx_timeout *rx_timeout;
336	int ret;
337
338	rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
339	if (!rx_timeout) {
340		ret = -ENOMEM;
341		goto out;
342	}
343
344	wl1271_debug(DEBUG_ACX, "acx service period timeout");
345
346	rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout);
347	rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout);
348
349	ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
350				   rx_timeout, sizeof(*rx_timeout));
351	if (ret < 0) {
352		wl1271_warning("failed to set service period timeout: %d",
353			       ret);
354		goto out;
355	}
356
357out:
358	kfree(rx_timeout);
359	return ret;
360}
361
362int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold)
363{
364	struct acx_rts_threshold *rts;
365	int ret;
366
367	wl1271_debug(DEBUG_ACX, "acx rts threshold");
368
369	rts = kzalloc(sizeof(*rts), GFP_KERNEL);
370	if (!rts) {
371		ret = -ENOMEM;
372		goto out;
373	}
374
375	rts->threshold = cpu_to_le16(rts_threshold);
376
377	ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
378	if (ret < 0) {
379		wl1271_warning("failed to set rts threshold: %d", ret);
380		goto out;
381	}
382
383out:
384	kfree(rts);
385	return ret;
386}
387
388int wl1271_acx_dco_itrim_params(struct wl1271 *wl)
389{
390	struct acx_dco_itrim_params *dco;
391	struct conf_itrim_settings *c = &wl->conf.itrim;
392	int ret;
393
394	wl1271_debug(DEBUG_ACX, "acx dco itrim parameters");
395
396	dco = kzalloc(sizeof(*dco), GFP_KERNEL);
397	if (!dco) {
398		ret = -ENOMEM;
399		goto out;
400	}
401
402	dco->enable = c->enable;
403	dco->timeout = cpu_to_le32(c->timeout);
404
405	ret = wl1271_cmd_configure(wl, ACX_SET_DCO_ITRIM_PARAMS,
406				   dco, sizeof(*dco));
407	if (ret < 0) {
408		wl1271_warning("failed to set dco itrim parameters: %d", ret);
409		goto out;
410	}
411
412out:
413	kfree(dco);
414	return ret;
415}
416
417int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
418{
419	struct acx_beacon_filter_option *beacon_filter = NULL;
420	int ret = 0;
421
422	wl1271_debug(DEBUG_ACX, "acx beacon filter opt");
423
424	if (enable_filter &&
425	    wl->conf.conn.bcn_filt_mode == CONF_BCN_FILT_MODE_DISABLED)
426		goto out;
427
428	beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
429	if (!beacon_filter) {
430		ret = -ENOMEM;
431		goto out;
432	}
433
434	beacon_filter->enable = enable_filter;
435
436	/*
437	 * When set to zero, and the filter is enabled, beacons
438	 * without the unicast TIM bit set are dropped.
439	 */
440	beacon_filter->max_num_beacons = 0;
441
442	ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
443				   beacon_filter, sizeof(*beacon_filter));
444	if (ret < 0) {
445		wl1271_warning("failed to set beacon filter opt: %d", ret);
446		goto out;
447	}
448
449out:
450	kfree(beacon_filter);
451	return ret;
452}
453
454int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
455{
456	struct acx_beacon_filter_ie_table *ie_table;
457	int i, idx = 0;
458	int ret;
459	bool vendor_spec = false;
460
461	wl1271_debug(DEBUG_ACX, "acx beacon filter table");
462
463	ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
464	if (!ie_table) {
465		ret = -ENOMEM;
466		goto out;
467	}
468
469	/* configure default beacon pass-through rules */
470	ie_table->num_ie = 0;
471	for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) {
472		struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]);
473		ie_table->table[idx++] = r->ie;
474		ie_table->table[idx++] = r->rule;
475
476		if (r->ie == WLAN_EID_VENDOR_SPECIFIC) {
477			/* only one vendor specific ie allowed */
478			if (vendor_spec)
479				continue;
480
481			/* for vendor specific rules configure the
482			   additional fields */
483			memcpy(&(ie_table->table[idx]), r->oui,
484			       CONF_BCN_IE_OUI_LEN);
485			idx += CONF_BCN_IE_OUI_LEN;
486			ie_table->table[idx++] = r->type;
487			memcpy(&(ie_table->table[idx]), r->version,
488			       CONF_BCN_IE_VER_LEN);
489			idx += CONF_BCN_IE_VER_LEN;
490			vendor_spec = true;
491		}
492
493		ie_table->num_ie++;
494	}
495
496	ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
497				   ie_table, sizeof(*ie_table));
498	if (ret < 0) {
499		wl1271_warning("failed to set beacon filter table: %d", ret);
500		goto out;
501	}
502
503out:
504	kfree(ie_table);
505	return ret;
506}
507
508#define ACX_CONN_MONIT_DISABLE_VALUE  0xffffffff
509
510int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable)
511{
512	struct acx_conn_monit_params *acx;
513	u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE;
514	u32 timeout = ACX_CONN_MONIT_DISABLE_VALUE;
515	int ret;
516
517	wl1271_debug(DEBUG_ACX, "acx connection monitor parameters: %s",
518		     enable ? "enabled" : "disabled");
519
520	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
521	if (!acx) {
522		ret = -ENOMEM;
523		goto out;
524	}
525
526	if (enable) {
527		threshold = wl->conf.conn.synch_fail_thold;
528		timeout = wl->conf.conn.bss_lose_timeout;
529	}
530
531	acx->synch_fail_thold = cpu_to_le32(threshold);
532	acx->bss_lose_timeout = cpu_to_le32(timeout);
533
534	ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
535				   acx, sizeof(*acx));
536	if (ret < 0) {
537		wl1271_warning("failed to set connection monitor "
538			       "parameters: %d", ret);
539		goto out;
540	}
541
542out:
543	kfree(acx);
544	return ret;
545}
546
547
548int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable)
549{
550	struct acx_bt_wlan_coex *pta;
551	int ret;
552
553	wl1271_debug(DEBUG_ACX, "acx sg enable");
554
555	pta = kzalloc(sizeof(*pta), GFP_KERNEL);
556	if (!pta) {
557		ret = -ENOMEM;
558		goto out;
559	}
560
561	if (enable)
562		pta->enable = wl->conf.sg.state;
563	else
564		pta->enable = CONF_SG_DISABLE;
565
566	ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
567	if (ret < 0) {
568		wl1271_warning("failed to set softgemini enable: %d", ret);
569		goto out;
570	}
571
572out:
573	kfree(pta);
574	return ret;
575}
576
577int wl1271_acx_sg_cfg(struct wl1271 *wl)
578{
579	struct acx_bt_wlan_coex_param *param;
580	struct conf_sg_settings *c = &wl->conf.sg;
581	int i, ret;
582
583	wl1271_debug(DEBUG_ACX, "acx sg cfg");
584
585	param = kzalloc(sizeof(*param), GFP_KERNEL);
586	if (!param) {
587		ret = -ENOMEM;
588		goto out;
589	}
590
591	/* BT-WLAN coext parameters */
592	for (i = 0; i < CONF_SG_PARAMS_MAX; i++)
593		param->params[i] = cpu_to_le32(c->params[i]);
594	param->param_idx = CONF_SG_PARAMS_ALL;
595
596	ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
597	if (ret < 0) {
598		wl1271_warning("failed to set sg config: %d", ret);
599		goto out;
600	}
601
602out:
603	kfree(param);
604	return ret;
605}
606
607int wl1271_acx_cca_threshold(struct wl1271 *wl)
608{
609	struct acx_energy_detection *detection;
610	int ret;
611
612	wl1271_debug(DEBUG_ACX, "acx cca threshold");
613
614	detection = kzalloc(sizeof(*detection), GFP_KERNEL);
615	if (!detection) {
616		ret = -ENOMEM;
617		goto out;
618	}
619
620	detection->rx_cca_threshold = cpu_to_le16(wl->conf.rx.rx_cca_threshold);
621	detection->tx_energy_detection = wl->conf.tx.tx_energy_detection;
622
623	ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD,
624				   detection, sizeof(*detection));
625	if (ret < 0) {
626		wl1271_warning("failed to set cca threshold: %d", ret);
627		return ret;
628	}
629
630out:
631	kfree(detection);
632	return ret;
633}
634
635int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
636{
637	struct acx_beacon_broadcast *bb;
638	int ret;
639
640	wl1271_debug(DEBUG_ACX, "acx bcn dtim options");
641
642	bb = kzalloc(sizeof(*bb), GFP_KERNEL);
643	if (!bb) {
644		ret = -ENOMEM;
645		goto out;
646	}
647
648	bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout);
649	bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout);
650	bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps;
651	bb->ps_poll_threshold = wl->conf.conn.ps_poll_threshold;
652
653	ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
654	if (ret < 0) {
655		wl1271_warning("failed to set rx config: %d", ret);
656		goto out;
657	}
658
659out:
660	kfree(bb);
661	return ret;
662}
663
664int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
665{
666	struct acx_aid *acx_aid;
667	int ret;
668
669	wl1271_debug(DEBUG_ACX, "acx aid");
670
671	acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
672	if (!acx_aid) {
673		ret = -ENOMEM;
674		goto out;
675	}
676
677	acx_aid->aid = cpu_to_le16(aid);
678
679	ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
680	if (ret < 0) {
681		wl1271_warning("failed to set aid: %d", ret);
682		goto out;
683	}
684
685out:
686	kfree(acx_aid);
687	return ret;
688}
689
690int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask)
691{
692	struct acx_event_mask *mask;
693	int ret;
694
695	wl1271_debug(DEBUG_ACX, "acx event mbox mask");
696
697	mask = kzalloc(sizeof(*mask), GFP_KERNEL);
698	if (!mask) {
699		ret = -ENOMEM;
700		goto out;
701	}
702
703	/* high event mask is unused */
704	mask->high_event_mask = cpu_to_le32(0xffffffff);
705	mask->event_mask = cpu_to_le32(event_mask);
706
707	ret = wl1271_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
708				   mask, sizeof(*mask));
709	if (ret < 0) {
710		wl1271_warning("failed to set acx_event_mbox_mask: %d", ret);
711		goto out;
712	}
713
714out:
715	kfree(mask);
716	return ret;
717}
718
719int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
720{
721	struct acx_preamble *acx;
722	int ret;
723
724	wl1271_debug(DEBUG_ACX, "acx_set_preamble");
725
726	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
727	if (!acx) {
728		ret = -ENOMEM;
729		goto out;
730	}
731
732	acx->preamble = preamble;
733
734	ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
735	if (ret < 0) {
736		wl1271_warning("Setting of preamble failed: %d", ret);
737		goto out;
738	}
739
740out:
741	kfree(acx);
742	return ret;
743}
744
745int wl1271_acx_cts_protect(struct wl1271 *wl,
746			   enum acx_ctsprotect_type ctsprotect)
747{
748	struct acx_ctsprotect *acx;
749	int ret;
750
751	wl1271_debug(DEBUG_ACX, "acx_set_ctsprotect");
752
753	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
754	if (!acx) {
755		ret = -ENOMEM;
756		goto out;
757	}
758
759	acx->ctsprotect = ctsprotect;
760
761	ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
762	if (ret < 0) {
763		wl1271_warning("Setting of ctsprotect failed: %d", ret);
764		goto out;
765	}
766
767out:
768	kfree(acx);
769	return ret;
770}
771
772int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
773{
774	int ret;
775
776	wl1271_debug(DEBUG_ACX, "acx statistics");
777
778	ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats,
779				     sizeof(*stats));
780	if (ret < 0) {
781		wl1271_warning("acx statistics failed: %d", ret);
782		return -ENOMEM;
783	}
784
785	return 0;
786}
787
788int wl1271_acx_rate_policies(struct wl1271 *wl)
789{
790	struct acx_rate_policy *acx;
791	struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
792	int idx = 0;
793	int ret = 0;
794
795	wl1271_debug(DEBUG_ACX, "acx rate policies");
796
797	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
798
799	if (!acx) {
800		ret = -ENOMEM;
801		goto out;
802	}
803
804	/* configure one basic rate class */
805	idx = ACX_TX_BASIC_RATE;
806	acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate);
807	acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
808	acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
809	acx->rate_class[idx].aflags = c->aflags;
810
811	/* configure one AP supported rate class */
812	idx = ACX_TX_AP_FULL_RATE;
813	acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set);
814	acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
815	acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
816	acx->rate_class[idx].aflags = c->aflags;
817
818	acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
819
820	ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
821	if (ret < 0) {
822		wl1271_warning("Setting of rate policies failed: %d", ret);
823		goto out;
824	}
825
826out:
827	kfree(acx);
828	return ret;
829}
830
831int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
832		      u8 aifsn, u16 txop)
833{
834	struct acx_ac_cfg *acx;
835	int ret = 0;
836
837	wl1271_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d "
838		     "aifs %d txop %d", ac, cw_min, cw_max, aifsn, txop);
839
840	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
841
842	if (!acx) {
843		ret = -ENOMEM;
844		goto out;
845	}
846
847	acx->ac = ac;
848	acx->cw_min = cw_min;
849	acx->cw_max = cpu_to_le16(cw_max);
850	acx->aifsn = aifsn;
851	acx->tx_op_limit = cpu_to_le16(txop);
852
853	ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
854	if (ret < 0) {
855		wl1271_warning("acx ac cfg failed: %d", ret);
856		goto out;
857	}
858
859out:
860	kfree(acx);
861	return ret;
862}
863
864int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
865		       u8 tsid, u8 ps_scheme, u8 ack_policy,
866		       u32 apsd_conf0, u32 apsd_conf1)
867{
868	struct acx_tid_config *acx;
869	int ret = 0;
870
871	wl1271_debug(DEBUG_ACX, "acx tid config");
872
873	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
874
875	if (!acx) {
876		ret = -ENOMEM;
877		goto out;
878	}
879
880	acx->queue_id = queue_id;
881	acx->channel_type = channel_type;
882	acx->tsid = tsid;
883	acx->ps_scheme = ps_scheme;
884	acx->ack_policy = ack_policy;
885	acx->apsd_conf[0] = cpu_to_le32(apsd_conf0);
886	acx->apsd_conf[1] = cpu_to_le32(apsd_conf1);
887
888	ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
889	if (ret < 0) {
890		wl1271_warning("Setting of tid config failed: %d", ret);
891		goto out;
892	}
893
894out:
895	kfree(acx);
896	return ret;
897}
898
899int wl1271_acx_frag_threshold(struct wl1271 *wl)
900{
901	struct acx_frag_threshold *acx;
902	int ret = 0;
903
904	wl1271_debug(DEBUG_ACX, "acx frag threshold");
905
906	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
907
908	if (!acx) {
909		ret = -ENOMEM;
910		goto out;
911	}
912
913	acx->frag_threshold = cpu_to_le16(wl->conf.tx.frag_threshold);
914	ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx));
915	if (ret < 0) {
916		wl1271_warning("Setting of frag threshold failed: %d", ret);
917		goto out;
918	}
919
920out:
921	kfree(acx);
922	return ret;
923}
924
925int wl1271_acx_tx_config_options(struct wl1271 *wl)
926{
927	struct acx_tx_config_options *acx;
928	int ret = 0;
929
930	wl1271_debug(DEBUG_ACX, "acx tx config options");
931
932	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
933
934	if (!acx) {
935		ret = -ENOMEM;
936		goto out;
937	}
938
939	acx->tx_compl_timeout = cpu_to_le16(wl->conf.tx.tx_compl_timeout);
940	acx->tx_compl_threshold = cpu_to_le16(wl->conf.tx.tx_compl_threshold);
941	ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx));
942	if (ret < 0) {
943		wl1271_warning("Setting of tx options failed: %d", ret);
944		goto out;
945	}
946
947out:
948	kfree(acx);
949	return ret;
950}
951
952int wl1271_acx_mem_cfg(struct wl1271 *wl)
953{
954	struct wl1271_acx_config_memory *mem_conf;
955	int ret;
956
957	wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
958
959	mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
960	if (!mem_conf) {
961		ret = -ENOMEM;
962		goto out;
963	}
964
965	/* memory config */
966	mem_conf->num_stations = DEFAULT_NUM_STATIONS;
967	mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
968	mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
969	mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
970	mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
971
972	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
973				   sizeof(*mem_conf));
974	if (ret < 0) {
975		wl1271_warning("wl1271 mem config failed: %d", ret);
976		goto out;
977	}
978
979out:
980	kfree(mem_conf);
981	return ret;
982}
983
984int wl1271_acx_init_mem_config(struct wl1271 *wl)
985{
986	int ret;
987
988	ret = wl1271_acx_mem_cfg(wl);
989	if (ret < 0)
990		return ret;
991
992	wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map),
993				     GFP_KERNEL);
994	if (!wl->target_mem_map) {
995		wl1271_error("couldn't allocate target memory map");
996		return -ENOMEM;
997	}
998
999	/* we now ask for the firmware built memory map */
1000	ret = wl1271_acx_mem_map(wl, (void *)wl->target_mem_map,
1001				 sizeof(struct wl1271_acx_mem_map));
1002	if (ret < 0) {
1003		wl1271_error("couldn't retrieve firmware memory map");
1004		kfree(wl->target_mem_map);
1005		wl->target_mem_map = NULL;
1006		return ret;
1007	}
1008
1009	/* initialize TX block book keeping */
1010	wl->tx_blocks_available =
1011		le32_to_cpu(wl->target_mem_map->num_tx_mem_blocks);
1012	wl1271_debug(DEBUG_TX, "available tx blocks: %d",
1013		     wl->tx_blocks_available);
1014
1015	return 0;
1016}
1017
1018int wl1271_acx_init_rx_interrupt(struct wl1271 *wl)
1019{
1020	struct wl1271_acx_rx_config_opt *rx_conf;
1021	int ret;
1022
1023	wl1271_debug(DEBUG_ACX, "wl1271 rx interrupt config");
1024
1025	rx_conf = kzalloc(sizeof(*rx_conf), GFP_KERNEL);
1026	if (!rx_conf) {
1027		ret = -ENOMEM;
1028		goto out;
1029	}
1030
1031	rx_conf->threshold = cpu_to_le16(wl->conf.rx.irq_pkt_threshold);
1032	rx_conf->timeout = cpu_to_le16(wl->conf.rx.irq_timeout);
1033	rx_conf->mblk_threshold = cpu_to_le16(wl->conf.rx.irq_blk_threshold);
1034	rx_conf->queue_type = wl->conf.rx.queue_type;
1035
1036	ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf,
1037				   sizeof(*rx_conf));
1038	if (ret < 0) {
1039		wl1271_warning("wl1271 rx config opt failed: %d", ret);
1040		goto out;
1041	}
1042
1043out:
1044	kfree(rx_conf);
1045	return ret;
1046}
1047
1048int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
1049{
1050	struct wl1271_acx_bet_enable *acx = NULL;
1051	int ret = 0;
1052
1053	wl1271_debug(DEBUG_ACX, "acx bet enable");
1054
1055	if (enable && wl->conf.conn.bet_enable == CONF_BET_MODE_DISABLE)
1056		goto out;
1057
1058	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1059	if (!acx) {
1060		ret = -ENOMEM;
1061		goto out;
1062	}
1063
1064	acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE;
1065	acx->max_consecutive = wl->conf.conn.bet_max_consecutive;
1066
1067	ret = wl1271_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
1068	if (ret < 0) {
1069		wl1271_warning("acx bet enable failed: %d", ret);
1070		goto out;
1071	}
1072
1073out:
1074	kfree(acx);
1075	return ret;
1076}
1077
1078int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address)
1079{
1080	struct wl1271_acx_arp_filter *acx;
1081	int ret;
1082
1083	wl1271_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
1084
1085	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1086	if (!acx) {
1087		ret = -ENOMEM;
1088		goto out;
1089	}
1090
1091	acx->version = ACX_IPV4_VERSION;
1092	acx->enable = enable;
1093
1094	if (enable == true)
1095		memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);
1096
1097	ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER,
1098				   acx, sizeof(*acx));
1099	if (ret < 0) {
1100		wl1271_warning("failed to set arp ip filter: %d", ret);
1101		goto out;
1102	}
1103
1104out:
1105	kfree(acx);
1106	return ret;
1107}
1108
1109int wl1271_acx_pm_config(struct wl1271 *wl)
1110{
1111	struct wl1271_acx_pm_config *acx = NULL;
1112	struct  conf_pm_config_settings *c = &wl->conf.pm_config;
1113	int ret = 0;
1114
1115	wl1271_debug(DEBUG_ACX, "acx pm config");
1116
1117	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1118	if (!acx) {
1119		ret = -ENOMEM;
1120		goto out;
1121	}
1122
1123	acx->host_clk_settling_time = cpu_to_le32(c->host_clk_settling_time);
1124	acx->host_fast_wakeup_support = c->host_fast_wakeup_support;
1125
1126	ret = wl1271_cmd_configure(wl, ACX_PM_CONFIG, acx, sizeof(*acx));
1127	if (ret < 0) {
1128		wl1271_warning("acx pm config failed: %d", ret);
1129		goto out;
1130	}
1131
1132out:
1133	kfree(acx);
1134	return ret;
1135}
1136
1137int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable)
1138{
1139	struct wl1271_acx_keep_alive_mode *acx = NULL;
1140	int ret = 0;
1141
1142	wl1271_debug(DEBUG_ACX, "acx keep alive mode: %d", enable);
1143
1144	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1145	if (!acx) {
1146		ret = -ENOMEM;
1147		goto out;
1148	}
1149
1150	acx->enabled = enable;
1151
1152	ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx));
1153	if (ret < 0) {
1154		wl1271_warning("acx keep alive mode failed: %d", ret);
1155		goto out;
1156	}
1157
1158out:
1159	kfree(acx);
1160	return ret;
1161}
1162
1163int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid)
1164{
1165	struct wl1271_acx_keep_alive_config *acx = NULL;
1166	int ret = 0;
1167
1168	wl1271_debug(DEBUG_ACX, "acx keep alive config");
1169
1170	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1171	if (!acx) {
1172		ret = -ENOMEM;
1173		goto out;
1174	}
1175
1176	acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval);
1177	acx->index = index;
1178	acx->tpl_validation = tpl_valid;
1179	acx->trigger = ACX_KEEP_ALIVE_NO_TX;
1180
1181	ret = wl1271_cmd_configure(wl, ACX_SET_KEEP_ALIVE_CONFIG,
1182				   acx, sizeof(*acx));
1183	if (ret < 0) {
1184		wl1271_warning("acx keep alive config failed: %d", ret);
1185		goto out;
1186	}
1187
1188out:
1189	kfree(acx);
1190	return ret;
1191}
1192
1193int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
1194				s16 thold, u8 hyst)
1195{
1196	struct wl1271_acx_rssi_snr_trigger *acx = NULL;
1197	int ret = 0;
1198
1199	wl1271_debug(DEBUG_ACX, "acx rssi snr trigger");
1200
1201	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1202	if (!acx) {
1203		ret = -ENOMEM;
1204		goto out;
1205	}
1206
1207	wl->last_rssi_event = -1;
1208
1209	acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing);
1210	acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON;
1211	acx->type = WL1271_ACX_TRIG_TYPE_EDGE;
1212	if (enable)
1213		acx->enable = WL1271_ACX_TRIG_ENABLE;
1214	else
1215		acx->enable = WL1271_ACX_TRIG_DISABLE;
1216
1217	acx->index = WL1271_ACX_TRIG_IDX_RSSI;
1218	acx->dir = WL1271_ACX_TRIG_DIR_BIDIR;
1219	acx->threshold = cpu_to_le16(thold);
1220	acx->hysteresis = hyst;
1221
1222	ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_TRIGGER, acx, sizeof(*acx));
1223	if (ret < 0) {
1224		wl1271_warning("acx rssi snr trigger setting failed: %d", ret);
1225		goto out;
1226	}
1227
1228out:
1229	kfree(acx);
1230	return ret;
1231}
1232
1233int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl)
1234{
1235	struct wl1271_acx_rssi_snr_avg_weights *acx = NULL;
1236	struct conf_roam_trigger_settings *c = &wl->conf.roam_trigger;
1237	int ret = 0;
1238
1239	wl1271_debug(DEBUG_ACX, "acx rssi snr avg weights");
1240
1241	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1242	if (!acx) {
1243		ret = -ENOMEM;
1244		goto out;
1245	}
1246
1247	acx->rssi_beacon = c->avg_weight_rssi_beacon;
1248	acx->rssi_data = c->avg_weight_rssi_data;
1249	acx->snr_beacon = c->avg_weight_snr_beacon;
1250	acx->snr_data = c->avg_weight_snr_data;
1251
1252	ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_WEIGHTS, acx, sizeof(*acx));
1253	if (ret < 0) {
1254		wl1271_warning("acx rssi snr trigger weights failed: %d", ret);
1255		goto out;
1256	}
1257
1258out:
1259	kfree(acx);
1260	return ret;
1261}
1262
1263int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
1264{
1265	struct wl1271_acx_fw_tsf_information *tsf_info;
1266	int ret;
1267
1268	tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL);
1269	if (!tsf_info) {
1270		ret = -ENOMEM;
1271		goto out;
1272	}
1273
1274	ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO,
1275				     tsf_info, sizeof(*tsf_info));
1276	if (ret < 0) {
1277		wl1271_warning("acx tsf info interrogate failed");
1278		goto out;
1279	}
1280
1281	*mactime = le32_to_cpu(tsf_info->current_tsf_low) |
1282		((u64) le32_to_cpu(tsf_info->current_tsf_high) << 32);
1283
1284out:
1285	kfree(tsf_info);
1286	return ret;
1287}
1288