blob: 038203bcf447c3b1b64f0ea34e24d9c753261184 [file] [log] [blame]
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001/*
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
31#include "wl1271.h"
32#include "wl12xx_80211.h"
33#include "wl1271_reg.h"
34#include "wl1271_spi.h"
35#include "wl1271_ps.h"
36
37int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event,
38 u8 listen_interval)
39{
40 struct acx_wake_up_condition *wake_up;
41 int ret;
42
43 wl1271_debug(DEBUG_ACX, "acx wake up conditions");
44
45 wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
46 if (!wake_up) {
47 ret = -ENOMEM;
48 goto out;
49 }
50
51 wake_up->wake_up_event = wake_up_event;
52 wake_up->listen_interval = listen_interval;
53
54 ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
55 wake_up, sizeof(*wake_up));
56 if (ret < 0) {
57 wl1271_warning("could not set wake up conditions: %d", ret);
58 goto out;
59 }
60
61out:
62 kfree(wake_up);
63 return ret;
64}
65
66int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
67{
68 struct acx_sleep_auth *auth;
69 int ret;
70
71 wl1271_debug(DEBUG_ACX, "acx sleep auth");
72
73 auth = kzalloc(sizeof(*auth), GFP_KERNEL);
74 if (!auth) {
75 ret = -ENOMEM;
76 goto out;
77 }
78
79 auth->sleep_auth = sleep_auth;
80
81 ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
82 if (ret < 0)
83 return ret;
84
85out:
86 kfree(auth);
87 return ret;
88}
89
90int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len)
91{
92 struct acx_revision *rev;
93 int ret;
94
95 wl1271_debug(DEBUG_ACX, "acx fw rev");
96
97 rev = kzalloc(sizeof(*rev), GFP_KERNEL);
98 if (!rev) {
99 ret = -ENOMEM;
100 goto out;
101 }
102
103 ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
104 if (ret < 0) {
105 wl1271_warning("ACX_FW_REV interrogate failed");
106 goto out;
107 }
108
109 /* be careful with the buffer sizes */
110 strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
111
112 /*
113 * if the firmware version string is exactly
114 * sizeof(rev->fw_version) long or fw_len is less than
115 * sizeof(rev->fw_version) it won't be null terminated
116 */
117 buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
118
119out:
120 kfree(rev);
121 return ret;
122}
123
124int wl1271_acx_tx_power(struct wl1271 *wl, int power)
125{
126 struct acx_current_tx_power *acx;
127 int ret;
128
129 wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
130
131 if (power < 0 || power > 25)
132 return -EINVAL;
133
134 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
135 if (!acx) {
136 ret = -ENOMEM;
137 goto out;
138 }
139
Luciano Coelhoac784032009-10-12 15:08:44 +0300140 /*
141 * FIXME: This is a workaround needed while we don't the correct
142 * calibration, to avoid distortions
143 */
144 /* acx->current_tx_power = power * 10; */
145 acx->current_tx_power = 70;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300146
147 ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
148 if (ret < 0) {
149 wl1271_warning("configure of tx power failed: %d", ret);
150 goto out;
151 }
152
153out:
154 kfree(acx);
155 return ret;
156}
157
158int wl1271_acx_feature_cfg(struct wl1271 *wl)
159{
160 struct acx_feature_config *feature;
161 int ret;
162
163 wl1271_debug(DEBUG_ACX, "acx feature cfg");
164
165 feature = kzalloc(sizeof(*feature), GFP_KERNEL);
166 if (!feature) {
167 ret = -ENOMEM;
168 goto out;
169 }
170
171 /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
172 feature->data_flow_options = 0;
173 feature->options = 0;
174
175 ret = wl1271_cmd_configure(wl, ACX_FEATURE_CFG,
176 feature, sizeof(*feature));
177 if (ret < 0) {
178 wl1271_error("Couldnt set HW encryption");
179 goto out;
180 }
181
182out:
183 kfree(feature);
184 return ret;
185}
186
187int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map,
188 size_t len)
189{
190 int ret;
191
192 wl1271_debug(DEBUG_ACX, "acx mem map");
193
194 ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
195 if (ret < 0)
196 return ret;
197
198 return 0;
199}
200
Juuso Oikarinen8793f9b2009-10-13 12:47:40 +0300201int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300202{
203 struct acx_rx_msdu_lifetime *acx;
204 int ret;
205
206 wl1271_debug(DEBUG_ACX, "acx rx msdu life time");
207
208 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
209 if (!acx) {
210 ret = -ENOMEM;
211 goto out;
212 }
213
Juuso Oikarinen8793f9b2009-10-13 12:47:40 +0300214 acx->lifetime = wl->conf.rx.rx_msdu_life_time;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300215 ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
216 acx, sizeof(*acx));
217 if (ret < 0) {
218 wl1271_warning("failed to set rx msdu life time: %d", ret);
219 goto out;
220 }
221
222out:
223 kfree(acx);
224 return ret;
225}
226
227int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter)
228{
229 struct acx_rx_config *rx_config;
230 int ret;
231
232 wl1271_debug(DEBUG_ACX, "acx rx config");
233
234 rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
235 if (!rx_config) {
236 ret = -ENOMEM;
237 goto out;
238 }
239
240 rx_config->config_options = config;
241 rx_config->filter_options = filter;
242
243 ret = wl1271_cmd_configure(wl, ACX_RX_CFG,
244 rx_config, sizeof(*rx_config));
245 if (ret < 0) {
246 wl1271_warning("failed to set rx config: %d", ret);
247 goto out;
248 }
249
250out:
251 kfree(rx_config);
252 return ret;
253}
254
255int wl1271_acx_pd_threshold(struct wl1271 *wl)
256{
257 struct acx_packet_detection *pd;
258 int ret;
259
260 wl1271_debug(DEBUG_ACX, "acx data pd threshold");
261
262 pd = kzalloc(sizeof(*pd), GFP_KERNEL);
263 if (!pd) {
264 ret = -ENOMEM;
265 goto out;
266 }
267
Juuso Oikarinen8793f9b2009-10-13 12:47:40 +0300268 pd->threshold = wl->conf.rx.packet_detection_threshold;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300269
270 ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
271 if (ret < 0) {
272 wl1271_warning("failed to set pd threshold: %d", ret);
273 goto out;
274 }
275
276out:
277 kfree(pd);
278 return 0;
279}
280
281int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
282{
283 struct acx_slot *slot;
284 int ret;
285
286 wl1271_debug(DEBUG_ACX, "acx slot");
287
288 slot = kzalloc(sizeof(*slot), GFP_KERNEL);
289 if (!slot) {
290 ret = -ENOMEM;
291 goto out;
292 }
293
294 slot->wone_index = STATION_WONE_INDEX;
295 slot->slot_time = slot_time;
296
297 ret = wl1271_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
298 if (ret < 0) {
299 wl1271_warning("failed to set slot time: %d", ret);
300 goto out;
301 }
302
303out:
304 kfree(slot);
305 return ret;
306}
307
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300308int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
309 void *mc_list, u32 mc_list_len)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300310{
311 struct acx_dot11_grp_addr_tbl *acx;
312 int ret;
313
314 wl1271_debug(DEBUG_ACX, "acx group address tbl");
315
316 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
317 if (!acx) {
318 ret = -ENOMEM;
319 goto out;
320 }
321
322 /* MAC filtering */
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300323 acx->enabled = enable;
324 acx->num_groups = mc_list_len;
325 memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300326
327 ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
328 acx, sizeof(*acx));
329 if (ret < 0) {
330 wl1271_warning("failed to set group addr table: %d", ret);
331 goto out;
332 }
333
334out:
335 kfree(acx);
336 return ret;
337}
338
339int wl1271_acx_service_period_timeout(struct wl1271 *wl)
340{
341 struct acx_rx_timeout *rx_timeout;
342 int ret;
343
344 rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
345 if (!rx_timeout) {
346 ret = -ENOMEM;
347 goto out;
348 }
349
350 wl1271_debug(DEBUG_ACX, "acx service period timeout");
351
Juuso Oikarinen8793f9b2009-10-13 12:47:40 +0300352 rx_timeout->ps_poll_timeout = wl->conf.rx.ps_poll_timeout;
353 rx_timeout->upsd_timeout = wl->conf.rx.upsd_timeout;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300354
355 ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
356 rx_timeout, sizeof(*rx_timeout));
357 if (ret < 0) {
358 wl1271_warning("failed to set service period timeout: %d",
359 ret);
360 goto out;
361 }
362
363out:
364 kfree(rx_timeout);
365 return ret;
366}
367
368int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold)
369{
370 struct acx_rts_threshold *rts;
371 int ret;
372
373 wl1271_debug(DEBUG_ACX, "acx rts threshold");
374
375 rts = kzalloc(sizeof(*rts), GFP_KERNEL);
376 if (!rts) {
377 ret = -ENOMEM;
378 goto out;
379 }
380
381 rts->threshold = rts_threshold;
382
383 ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
384 if (ret < 0) {
385 wl1271_warning("failed to set rts threshold: %d", ret);
386 goto out;
387 }
388
389out:
390 kfree(rts);
391 return ret;
392}
393
Juuso Oikarinen19221672009-10-08 21:56:35 +0300394int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300395{
396 struct acx_beacon_filter_option *beacon_filter;
397 int ret;
398
399 wl1271_debug(DEBUG_ACX, "acx beacon filter opt");
400
401 beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
402 if (!beacon_filter) {
403 ret = -ENOMEM;
404 goto out;
405 }
406
Juuso Oikarinen19221672009-10-08 21:56:35 +0300407 beacon_filter->enable = enable_filter;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300408 beacon_filter->max_num_beacons = 0;
409
410 ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
411 beacon_filter, sizeof(*beacon_filter));
412 if (ret < 0) {
413 wl1271_warning("failed to set beacon filter opt: %d", ret);
414 goto out;
415 }
416
417out:
418 kfree(beacon_filter);
419 return ret;
420}
421
422int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
423{
424 struct acx_beacon_filter_ie_table *ie_table;
Juuso Oikarinen19221672009-10-08 21:56:35 +0300425 int idx = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300426 int ret;
427
428 wl1271_debug(DEBUG_ACX, "acx beacon filter table");
429
430 ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
431 if (!ie_table) {
432 ret = -ENOMEM;
433 goto out;
434 }
435
Juuso Oikarinen19221672009-10-08 21:56:35 +0300436 /* configure default beacon pass-through rules */
437 ie_table->num_ie = 1;
438 ie_table->table[idx++] = BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN;
439 ie_table->table[idx++] = BEACON_RULE_PASS_ON_APPEARANCE;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300440
441 ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
442 ie_table, sizeof(*ie_table));
443 if (ret < 0) {
444 wl1271_warning("failed to set beacon filter table: %d", ret);
445 goto out;
446 }
447
448out:
449 kfree(ie_table);
450 return ret;
451}
452
Juuso Oikarinen34415232009-10-08 21:56:33 +0300453int wl1271_acx_conn_monit_params(struct wl1271 *wl)
454{
455 struct acx_conn_monit_params *acx;
456 int ret;
457
458 wl1271_debug(DEBUG_ACX, "acx connection monitor parameters");
459
460 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
461 if (!acx) {
462 ret = -ENOMEM;
463 goto out;
464 }
465
466 acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD;
467 acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT;
468
469 ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
470 acx, sizeof(*acx));
471 if (ret < 0) {
472 wl1271_warning("failed to set connection monitor "
473 "parameters: %d", ret);
474 goto out;
475 }
476
477out:
478 kfree(acx);
479 return ret;
480}
481
482
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300483int wl1271_acx_sg_enable(struct wl1271 *wl)
484{
485 struct acx_bt_wlan_coex *pta;
486 int ret;
487
488 wl1271_debug(DEBUG_ACX, "acx sg enable");
489
490 pta = kzalloc(sizeof(*pta), GFP_KERNEL);
491 if (!pta) {
492 ret = -ENOMEM;
493 goto out;
494 }
495
496 pta->enable = SG_ENABLE;
497
498 ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
499 if (ret < 0) {
500 wl1271_warning("failed to set softgemini enable: %d", ret);
501 goto out;
502 }
503
504out:
505 kfree(pta);
506 return ret;
507}
508
509int wl1271_acx_sg_cfg(struct wl1271 *wl)
510{
511 struct acx_bt_wlan_coex_param *param;
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300512 struct conf_sg_settings *c = &wl->conf.sg;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300513 int ret;
514
515 wl1271_debug(DEBUG_ACX, "acx sg cfg");
516
517 param = kzalloc(sizeof(*param), GFP_KERNEL);
518 if (!param) {
519 ret = -ENOMEM;
520 goto out;
521 }
522
523 /* BT-WLAN coext parameters */
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300524 param->per_threshold = c->per_threshold;
525 param->max_scan_compensation_time = c->max_scan_compensation_time;
526 param->nfs_sample_interval = c->nfs_sample_interval;
527 param->load_ratio = c->load_ratio;
528 param->auto_ps_mode = c->auto_ps_mode;
529 param->probe_req_compensation = c->probe_req_compensation;
530 param->scan_window_compensation = c->scan_window_compensation;
531 param->antenna_config = c->antenna_config;
532 param->beacon_miss_threshold = c->beacon_miss_threshold;
533 param->rate_adaptation_threshold = c->rate_adaptation_threshold;
534 param->rate_adaptation_snr = c->rate_adaptation_snr;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300535
536 ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
537 if (ret < 0) {
538 wl1271_warning("failed to set sg config: %d", ret);
539 goto out;
540 }
541
542out:
543 kfree(param);
544 return ret;
545}
546
547int wl1271_acx_cca_threshold(struct wl1271 *wl)
548{
549 struct acx_energy_detection *detection;
550 int ret;
551
552 wl1271_debug(DEBUG_ACX, "acx cca threshold");
553
554 detection = kzalloc(sizeof(*detection), GFP_KERNEL);
555 if (!detection) {
556 ret = -ENOMEM;
557 goto out;
558 }
559
Juuso Oikarinen8793f9b2009-10-13 12:47:40 +0300560 detection->rx_cca_threshold = wl->conf.rx.rx_cca_threshold;
Juuso Oikarinen45b531a2009-10-13 12:47:41 +0300561 detection->tx_energy_detection = wl->conf.tx.tx_energy_detection;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300562
563 ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD,
564 detection, sizeof(*detection));
565 if (ret < 0) {
566 wl1271_warning("failed to set cca threshold: %d", ret);
567 return ret;
568 }
569
570out:
571 kfree(detection);
572 return ret;
573}
574
575int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
576{
577 struct acx_beacon_broadcast *bb;
578 int ret;
579
580 wl1271_debug(DEBUG_ACX, "acx bcn dtim options");
581
582 bb = kzalloc(sizeof(*bb), GFP_KERNEL);
583 if (!bb) {
584 ret = -ENOMEM;
585 goto out;
586 }
587
588 bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
589 bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
590 bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
591 bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
592
593 ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
594 if (ret < 0) {
595 wl1271_warning("failed to set rx config: %d", ret);
596 goto out;
597 }
598
599out:
600 kfree(bb);
601 return ret;
602}
603
604int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
605{
606 struct acx_aid *acx_aid;
607 int ret;
608
609 wl1271_debug(DEBUG_ACX, "acx aid");
610
611 acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
612 if (!acx_aid) {
613 ret = -ENOMEM;
614 goto out;
615 }
616
617 acx_aid->aid = aid;
618
619 ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
620 if (ret < 0) {
621 wl1271_warning("failed to set aid: %d", ret);
622 goto out;
623 }
624
625out:
626 kfree(acx_aid);
627 return ret;
628}
629
630int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask)
631{
632 struct acx_event_mask *mask;
633 int ret;
634
635 wl1271_debug(DEBUG_ACX, "acx event mbox mask");
636
637 mask = kzalloc(sizeof(*mask), GFP_KERNEL);
638 if (!mask) {
639 ret = -ENOMEM;
640 goto out;
641 }
642
643 /* high event mask is unused */
644 mask->high_event_mask = 0xffffffff;
645
646 mask->event_mask = event_mask;
647
648 ret = wl1271_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
649 mask, sizeof(*mask));
650 if (ret < 0) {
651 wl1271_warning("failed to set acx_event_mbox_mask: %d", ret);
652 goto out;
653 }
654
655out:
656 kfree(mask);
657 return ret;
658}
659
660int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
661{
662 struct acx_preamble *acx;
663 int ret;
664
665 wl1271_debug(DEBUG_ACX, "acx_set_preamble");
666
667 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
668 if (!acx) {
669 ret = -ENOMEM;
670 goto out;
671 }
672
673 acx->preamble = preamble;
674
675 ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
676 if (ret < 0) {
677 wl1271_warning("Setting of preamble failed: %d", ret);
678 goto out;
679 }
680
681out:
682 kfree(acx);
683 return ret;
684}
685
686int wl1271_acx_cts_protect(struct wl1271 *wl,
687 enum acx_ctsprotect_type ctsprotect)
688{
689 struct acx_ctsprotect *acx;
690 int ret;
691
692 wl1271_debug(DEBUG_ACX, "acx_set_ctsprotect");
693
694 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
695 if (!acx) {
696 ret = -ENOMEM;
697 goto out;
698 }
699
700 acx->ctsprotect = ctsprotect;
701
702 ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
703 if (ret < 0) {
704 wl1271_warning("Setting of ctsprotect failed: %d", ret);
705 goto out;
706 }
707
708out:
709 kfree(acx);
710 return ret;
711}
712
713int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
714{
715 int ret;
716
717 wl1271_debug(DEBUG_ACX, "acx statistics");
718
719 ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats,
720 sizeof(*stats));
721 if (ret < 0) {
722 wl1271_warning("acx statistics failed: %d", ret);
723 return -ENOMEM;
724 }
725
726 return 0;
727}
728
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +0300729int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300730{
731 struct acx_rate_policy *acx;
Juuso Oikarinen45b531a2009-10-13 12:47:41 +0300732 struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300733 int ret = 0;
734
735 wl1271_debug(DEBUG_ACX, "acx rate policies");
736
737 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
738
739 if (!acx) {
740 ret = -ENOMEM;
741 goto out;
742 }
743
744 /* configure one default (one-size-fits-all) rate class */
745 acx->rate_class_cnt = 1;
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +0300746 acx->rate_class[0].enabled_rates = enabled_rates;
Juuso Oikarinen45b531a2009-10-13 12:47:41 +0300747 acx->rate_class[0].short_retry_limit = c->short_retry_limit;
748 acx->rate_class[0].long_retry_limit = c->long_retry_limit;
749 acx->rate_class[0].aflags = c->aflags;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300750
751 ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
752 if (ret < 0) {
753 wl1271_warning("Setting of rate policies failed: %d", ret);
754 goto out;
755 }
756
757out:
758 kfree(acx);
759 return ret;
760}
761
762int wl1271_acx_ac_cfg(struct wl1271 *wl)
763{
764 struct acx_ac_cfg *acx;
765 int i, ret = 0;
766
767 wl1271_debug(DEBUG_ACX, "acx access category config");
768
769 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
770
771 if (!acx) {
772 ret = -ENOMEM;
773 goto out;
774 }
775
Juuso Oikarinen45b531a2009-10-13 12:47:41 +0300776 for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
777 struct conf_tx_ac_category *c = &(wl->conf.tx.ac_conf[i]);
778 acx->ac = c->ac;
779 acx->cw_min = c->cw_min;
780 acx->cw_max = c->cw_max;
781 acx->aifsn = c->aifsn;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300782 acx->reserved = 0;
Juuso Oikarinen45b531a2009-10-13 12:47:41 +0300783 acx->tx_op_limit = c->tx_op_limit;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300784
785 ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
786 if (ret < 0) {
787 wl1271_warning("Setting of access category "
788 "config: %d", ret);
789 goto out;
790 }
791 }
792
793out:
794 kfree(acx);
795 return ret;
796}
797
798int wl1271_acx_tid_cfg(struct wl1271 *wl)
799{
800 struct acx_tid_config *acx;
801 int i, ret = 0;
802
803 wl1271_debug(DEBUG_ACX, "acx tid config");
804
805 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
806
807 if (!acx) {
808 ret = -ENOMEM;
809 goto out;
810 }
811
Juuso Oikarinen45b531a2009-10-13 12:47:41 +0300812 for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
813 struct conf_tx_tid *c = &(wl->conf.tx.tid_conf[i]);
814 acx->queue_id = c->queue_id;
815 acx->channel_type = c->channel_type;
816 acx->tsid = c->tsid;
817 acx->ps_scheme = c->ps_scheme;
818 acx->ack_policy = c->ack_policy;
819 acx->apsd_conf[0] = c->apsd_conf[0];
820 acx->apsd_conf[1] = c->apsd_conf[1];
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300821
822 ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
823 if (ret < 0) {
824 wl1271_warning("Setting of tid config failed: %d", ret);
825 goto out;
826 }
827 }
828
829out:
830 kfree(acx);
831 return ret;
832}
833
834int wl1271_acx_frag_threshold(struct wl1271 *wl)
835{
836 struct acx_frag_threshold *acx;
837 int ret = 0;
838
839 wl1271_debug(DEBUG_ACX, "acx frag threshold");
840
841 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
842
843 if (!acx) {
844 ret = -ENOMEM;
845 goto out;
846 }
847
Juuso Oikarinen45b531a2009-10-13 12:47:41 +0300848 acx->frag_threshold = wl->conf.tx.frag_threshold;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300849 ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx));
850 if (ret < 0) {
851 wl1271_warning("Setting of frag threshold failed: %d", ret);
852 goto out;
853 }
854
855out:
856 kfree(acx);
857 return ret;
858}
859
860int wl1271_acx_tx_config_options(struct wl1271 *wl)
861{
862 struct acx_tx_config_options *acx;
863 int ret = 0;
864
865 wl1271_debug(DEBUG_ACX, "acx tx config options");
866
867 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
868
869 if (!acx) {
870 ret = -ENOMEM;
871 goto out;
872 }
873
Juuso Oikarinen45b531a2009-10-13 12:47:41 +0300874 acx->tx_compl_timeout = wl->conf.tx.tx_compl_timeout;
875 acx->tx_compl_threshold = wl->conf.tx.tx_compl_threshold;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300876 ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx));
877 if (ret < 0) {
878 wl1271_warning("Setting of tx options failed: %d", ret);
879 goto out;
880 }
881
882out:
883 kfree(acx);
884 return ret;
885}
886
887int wl1271_acx_mem_cfg(struct wl1271 *wl)
888{
889 struct wl1271_acx_config_memory *mem_conf;
890 int ret;
891
892 wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
893
894 mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
895 if (!mem_conf) {
896 ret = -ENOMEM;
897 goto out;
898 }
899
900 /* memory config */
901 mem_conf->num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
902 mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
903 mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
904 mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
905 mem_conf->total_tx_descriptors = ACX_TX_DESCRIPTORS;
906
907 ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
908 sizeof(*mem_conf));
909 if (ret < 0) {
910 wl1271_warning("wl1271 mem config failed: %d", ret);
911 goto out;
912 }
913
914out:
915 kfree(mem_conf);
916 return ret;
917}
918
919int wl1271_acx_init_mem_config(struct wl1271 *wl)
920{
921 int ret;
922
923 ret = wl1271_acx_mem_cfg(wl);
924 if (ret < 0)
925 return ret;
926
927 wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map),
Juuso Oikarinen45b531a2009-10-13 12:47:41 +0300928 GFP_KERNEL);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300929 if (!wl->target_mem_map) {
930 wl1271_error("couldn't allocate target memory map");
931 return -ENOMEM;
932 }
933
934 /* we now ask for the firmware built memory map */
935 ret = wl1271_acx_mem_map(wl, (void *)wl->target_mem_map,
936 sizeof(struct wl1271_acx_mem_map));
937 if (ret < 0) {
938 wl1271_error("couldn't retrieve firmware memory map");
939 kfree(wl->target_mem_map);
940 wl->target_mem_map = NULL;
941 return ret;
942 }
943
944 /* initialize TX block book keeping */
945 wl->tx_blocks_available = wl->target_mem_map->num_tx_mem_blocks;
946 wl1271_debug(DEBUG_TX, "available tx blocks: %d",
947 wl->tx_blocks_available);
948
949 return 0;
950}
951
952int wl1271_acx_init_rx_interrupt(struct wl1271 *wl)
953{
954 struct wl1271_acx_rx_config_opt *rx_conf;
955 int ret;
956
957 wl1271_debug(DEBUG_ACX, "wl1271 rx interrupt config");
958
959 rx_conf = kzalloc(sizeof(*rx_conf), GFP_KERNEL);
960 if (!rx_conf) {
961 ret = -ENOMEM;
962 goto out;
963 }
964
Juuso Oikarinen8793f9b2009-10-13 12:47:40 +0300965 rx_conf->threshold = wl->conf.rx.irq_pkt_threshold;
966 rx_conf->timeout = wl->conf.rx.irq_timeout;
967 rx_conf->mblk_threshold = wl->conf.rx.irq_blk_threshold;
968 rx_conf->queue_type = wl->conf.rx.queue_type;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300969
970 ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf,
971 sizeof(*rx_conf));
972 if (ret < 0) {
973 wl1271_warning("wl1271 rx config opt failed: %d", ret);
974 goto out;
975 }
976
977out:
978 kfree(rx_conf);
979 return ret;
980}
Juuso Oikarinen3cfd6cf2009-10-12 15:08:52 +0300981
982int wl1271_acx_smart_reflex(struct wl1271 *wl)
983{
984 struct acx_smart_reflex_state *sr_state = NULL;
985 struct acx_smart_reflex_config_params *sr_param = NULL;
986 int ret;
987
988 wl1271_debug(DEBUG_ACX, "acx smart reflex");
989
990 sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL);
991 if (!sr_param) {
992 ret = -ENOMEM;
993 goto out;
994 }
995
996 /* set cryptic smart reflex parameters - source TI reference code */
997 sr_param->error_table[0].len = 0x07;
998 sr_param->error_table[0].upper_limit = 0x03;
999 sr_param->error_table[0].values[0] = 0x18;
1000 sr_param->error_table[0].values[1] = 0x10;
1001 sr_param->error_table[0].values[2] = 0x05;
1002 sr_param->error_table[0].values[3] = 0xfb;
1003 sr_param->error_table[0].values[4] = 0xf0;
1004 sr_param->error_table[0].values[5] = 0xe8;
1005
1006 sr_param->error_table[1].len = 0x07;
1007 sr_param->error_table[1].upper_limit = 0x03;
1008 sr_param->error_table[1].values[0] = 0x18;
1009 sr_param->error_table[1].values[1] = 0x10;
1010 sr_param->error_table[1].values[2] = 0x05;
1011 sr_param->error_table[1].values[3] = 0xf6;
1012 sr_param->error_table[1].values[4] = 0xf0;
1013 sr_param->error_table[1].values[5] = 0xe8;
1014
1015 sr_param->error_table[2].len = 0x07;
1016 sr_param->error_table[2].upper_limit = 0x03;
1017 sr_param->error_table[2].values[0] = 0x18;
1018 sr_param->error_table[2].values[1] = 0x10;
1019 sr_param->error_table[2].values[2] = 0x05;
1020 sr_param->error_table[2].values[3] = 0xfb;
1021 sr_param->error_table[2].values[4] = 0xf0;
1022 sr_param->error_table[2].values[5] = 0xe8;
1023
1024 ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS,
1025 sr_param, sizeof(*sr_param));
1026 if (ret < 0) {
1027 wl1271_warning("failed to set smart reflex params: %d", ret);
1028 goto out;
1029 }
1030
1031 sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL);
1032 if (!sr_state) {
1033 ret = -ENOMEM;
1034 goto out;
1035 }
1036
1037 /* enable smart reflex */
1038 sr_state->enable = 1;
1039
1040 ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE,
1041 sr_state, sizeof(*sr_state));
1042 if (ret < 0) {
1043 wl1271_warning("failed to set smart reflex params: %d", ret);
1044 goto out;
1045 }
1046
1047out:
1048 kfree(sr_state);
1049 kfree(sr_param);
1050 return ret;
1051
1052}