1 // SPDX-License-Identifier: GPL-2.0
2 #include "acx.h"
3
4 #include <linux/module.h>
5 #include <linux/slab.h>
6 #include <linux/string.h>
7
8 #include "wl1251.h"
9 #include "reg.h"
10 #include "cmd.h"
11 #include "ps.h"
12
wl1251_acx_frame_rates(struct wl1251 * wl,u8 ctrl_rate,u8 ctrl_mod,u8 mgt_rate,u8 mgt_mod)13 int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
14 u8 mgt_rate, u8 mgt_mod)
15 {
16 struct acx_fw_gen_frame_rates *rates;
17 int ret;
18
19 wl1251_debug(DEBUG_ACX, "acx frame rates");
20
21 rates = kzalloc_obj(*rates);
22 if (!rates)
23 return -ENOMEM;
24
25 rates->tx_ctrl_frame_rate = ctrl_rate;
26 rates->tx_ctrl_frame_mod = ctrl_mod;
27 rates->tx_mgt_frame_rate = mgt_rate;
28 rates->tx_mgt_frame_mod = mgt_mod;
29
30 ret = wl1251_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES,
31 rates, sizeof(*rates));
32 if (ret < 0) {
33 wl1251_error("Failed to set FW rates and modulation");
34 goto out;
35 }
36
37 out:
38 kfree(rates);
39 return ret;
40 }
41
42
wl1251_acx_station_id(struct wl1251 * wl)43 int wl1251_acx_station_id(struct wl1251 *wl)
44 {
45 struct acx_dot11_station_id *mac;
46 int ret, i;
47
48 wl1251_debug(DEBUG_ACX, "acx dot11_station_id");
49
50 mac = kzalloc_obj(*mac);
51 if (!mac)
52 return -ENOMEM;
53
54 for (i = 0; i < ETH_ALEN; i++)
55 mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
56
57 ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac));
58
59 kfree(mac);
60 return ret;
61 }
62
wl1251_acx_default_key(struct wl1251 * wl,u8 key_id)63 int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id)
64 {
65 struct acx_dot11_default_key *default_key;
66 int ret;
67
68 wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);
69
70 default_key = kzalloc_obj(*default_key);
71 if (!default_key)
72 return -ENOMEM;
73
74 default_key->id = key_id;
75
76 ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY,
77 default_key, sizeof(*default_key));
78 if (ret < 0) {
79 wl1251_error("Couldn't set default key");
80 goto out;
81 }
82
83 wl->default_key = key_id;
84
85 out:
86 kfree(default_key);
87 return ret;
88 }
89
wl1251_acx_wake_up_conditions(struct wl1251 * wl,u8 wake_up_event,u8 listen_interval)90 int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
91 u8 listen_interval)
92 {
93 struct acx_wake_up_condition *wake_up;
94 int ret;
95
96 wl1251_debug(DEBUG_ACX, "acx wake up conditions");
97
98 wake_up = kzalloc_obj(*wake_up);
99 if (!wake_up)
100 return -ENOMEM;
101
102 wake_up->wake_up_event = wake_up_event;
103 wake_up->listen_interval = listen_interval;
104
105 ret = wl1251_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
106 wake_up, sizeof(*wake_up));
107 if (ret < 0) {
108 wl1251_warning("could not set wake up conditions: %d", ret);
109 goto out;
110 }
111
112 out:
113 kfree(wake_up);
114 return ret;
115 }
116
wl1251_acx_sleep_auth(struct wl1251 * wl,u8 sleep_auth)117 int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth)
118 {
119 struct acx_sleep_auth *auth;
120 int ret;
121
122 wl1251_debug(DEBUG_ACX, "acx sleep auth");
123
124 auth = kzalloc_obj(*auth);
125 if (!auth)
126 return -ENOMEM;
127
128 auth->sleep_auth = sleep_auth;
129
130 ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
131
132 kfree(auth);
133 return ret;
134 }
135
wl1251_acx_fw_version(struct wl1251 * wl,char * buf,size_t len)136 int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len)
137 {
138 struct acx_revision *rev;
139 int ret;
140
141 wl1251_debug(DEBUG_ACX, "acx fw rev");
142
143 rev = kzalloc_obj(*rev);
144 if (!rev)
145 return -ENOMEM;
146
147 ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
148 if (ret < 0) {
149 wl1251_warning("ACX_FW_REV interrogate failed");
150 goto out;
151 }
152
153 strscpy(buf, rev->fw_version, len);
154
155 out:
156 kfree(rev);
157 return ret;
158 }
159
wl1251_acx_tx_power(struct wl1251 * wl,int power)160 int wl1251_acx_tx_power(struct wl1251 *wl, int power)
161 {
162 struct acx_current_tx_power *acx;
163 int ret;
164
165 wl1251_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
166
167 if (power < 0 || power > 25)
168 return -EINVAL;
169
170 acx = kzalloc_obj(*acx);
171 if (!acx)
172 return -ENOMEM;
173
174 acx->current_tx_power = power * 10;
175
176 ret = wl1251_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
177 if (ret < 0) {
178 wl1251_warning("configure of tx power failed: %d", ret);
179 goto out;
180 }
181
182 out:
183 kfree(acx);
184 return ret;
185 }
186
wl1251_acx_feature_cfg(struct wl1251 * wl,u32 data_flow_options)187 int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options)
188 {
189 struct acx_feature_config *feature;
190 int ret;
191
192 wl1251_debug(DEBUG_ACX, "acx feature cfg");
193
194 feature = kzalloc_obj(*feature);
195 if (!feature)
196 return -ENOMEM;
197
198 /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE can be set */
199 feature->data_flow_options = data_flow_options;
200 feature->options = 0;
201
202 ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
203 feature, sizeof(*feature));
204 if (ret < 0) {
205 wl1251_error("Couldn't set HW encryption");
206 goto out;
207 }
208
209 out:
210 kfree(feature);
211 return ret;
212 }
213
wl1251_acx_mem_map(struct wl1251 * wl,struct acx_header * mem_map,size_t len)214 int wl1251_acx_mem_map(struct wl1251 *wl, struct acx_header *mem_map,
215 size_t len)
216 {
217 int ret;
218
219 wl1251_debug(DEBUG_ACX, "acx mem map");
220
221 ret = wl1251_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
222 if (ret < 0)
223 return ret;
224
225 return 0;
226 }
227
wl1251_acx_data_path_params(struct wl1251 * wl,struct acx_data_path_params_resp * resp)228 int wl1251_acx_data_path_params(struct wl1251 *wl,
229 struct acx_data_path_params_resp *resp)
230 {
231 struct acx_data_path_params *params;
232 int ret;
233
234 wl1251_debug(DEBUG_ACX, "acx data path params");
235
236 params = kzalloc_obj(*params);
237 if (!params)
238 return -ENOMEM;
239
240 params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
241 params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
242
243 params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM;
244 params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM;
245
246 params->tx_complete_threshold = 1;
247
248 params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE;
249
250 params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT;
251
252 ret = wl1251_cmd_configure(wl, ACX_DATA_PATH_PARAMS,
253 params, sizeof(*params));
254 if (ret < 0)
255 goto out;
256
257 /* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */
258 ret = wl1251_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS,
259 resp, sizeof(*resp));
260
261 if (ret < 0) {
262 wl1251_warning("failed to read data path parameters: %d", ret);
263 goto out;
264 } else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) {
265 wl1251_warning("data path parameter acx status failed");
266 ret = -EIO;
267 goto out;
268 }
269
270 out:
271 kfree(params);
272 return ret;
273 }
274
wl1251_acx_rx_msdu_life_time(struct wl1251 * wl,u32 life_time)275 int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time)
276 {
277 struct acx_rx_msdu_lifetime *acx;
278 int ret;
279
280 wl1251_debug(DEBUG_ACX, "acx rx msdu life time");
281
282 acx = kzalloc_obj(*acx);
283 if (!acx)
284 return -ENOMEM;
285
286 acx->lifetime = life_time;
287 ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
288 acx, sizeof(*acx));
289 if (ret < 0) {
290 wl1251_warning("failed to set rx msdu life time: %d", ret);
291 goto out;
292 }
293
294 out:
295 kfree(acx);
296 return ret;
297 }
298
wl1251_acx_rx_config(struct wl1251 * wl,u32 config,u32 filter)299 int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter)
300 {
301 struct acx_rx_config *rx_config;
302 int ret;
303
304 wl1251_debug(DEBUG_ACX, "acx rx config");
305
306 rx_config = kzalloc_obj(*rx_config);
307 if (!rx_config)
308 return -ENOMEM;
309
310 rx_config->config_options = config;
311 rx_config->filter_options = filter;
312
313 ret = wl1251_cmd_configure(wl, ACX_RX_CFG,
314 rx_config, sizeof(*rx_config));
315 if (ret < 0) {
316 wl1251_warning("failed to set rx config: %d", ret);
317 goto out;
318 }
319
320 out:
321 kfree(rx_config);
322 return ret;
323 }
324
wl1251_acx_pd_threshold(struct wl1251 * wl)325 int wl1251_acx_pd_threshold(struct wl1251 *wl)
326 {
327 struct acx_packet_detection *pd;
328 int ret;
329
330 wl1251_debug(DEBUG_ACX, "acx data pd threshold");
331
332 pd = kzalloc_obj(*pd);
333 if (!pd)
334 return -ENOMEM;
335
336 /* FIXME: threshold value not set */
337
338 ret = wl1251_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
339 if (ret < 0) {
340 wl1251_warning("failed to set pd threshold: %d", ret);
341 goto out;
342 }
343
344 out:
345 kfree(pd);
346 return ret;
347 }
348
wl1251_acx_slot(struct wl1251 * wl,enum acx_slot_type slot_time)349 int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time)
350 {
351 struct acx_slot *slot;
352 int ret;
353
354 wl1251_debug(DEBUG_ACX, "acx slot");
355
356 slot = kzalloc_obj(*slot);
357 if (!slot)
358 return -ENOMEM;
359
360 slot->wone_index = STATION_WONE_INDEX;
361 slot->slot_time = slot_time;
362
363 ret = wl1251_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
364 if (ret < 0) {
365 wl1251_warning("failed to set slot time: %d", ret);
366 goto out;
367 }
368
369 out:
370 kfree(slot);
371 return ret;
372 }
373
wl1251_acx_group_address_tbl(struct wl1251 * wl,bool enable,void * mc_list,u32 mc_list_len)374 int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
375 void *mc_list, u32 mc_list_len)
376 {
377 struct acx_dot11_grp_addr_tbl *acx;
378 int ret;
379
380 wl1251_debug(DEBUG_ACX, "acx group address tbl");
381
382 acx = kzalloc_obj(*acx);
383 if (!acx)
384 return -ENOMEM;
385
386 /* MAC filtering */
387 acx->enabled = enable;
388 acx->num_groups = mc_list_len;
389 memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
390
391 ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
392 acx, sizeof(*acx));
393 if (ret < 0) {
394 wl1251_warning("failed to set group addr table: %d", ret);
395 goto out;
396 }
397
398 out:
399 kfree(acx);
400 return ret;
401 }
402
wl1251_acx_service_period_timeout(struct wl1251 * wl)403 int wl1251_acx_service_period_timeout(struct wl1251 *wl)
404 {
405 struct acx_rx_timeout *rx_timeout;
406 int ret;
407
408 rx_timeout = kzalloc_obj(*rx_timeout);
409 if (!rx_timeout)
410 return -ENOMEM;
411
412 wl1251_debug(DEBUG_ACX, "acx service period timeout");
413
414 rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
415 rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
416
417 ret = wl1251_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
418 rx_timeout, sizeof(*rx_timeout));
419 if (ret < 0) {
420 wl1251_warning("failed to set service period timeout: %d",
421 ret);
422 goto out;
423 }
424
425 out:
426 kfree(rx_timeout);
427 return ret;
428 }
429
wl1251_acx_rts_threshold(struct wl1251 * wl,u16 rts_threshold)430 int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold)
431 {
432 struct acx_rts_threshold *rts;
433 int ret;
434
435 wl1251_debug(DEBUG_ACX, "acx rts threshold");
436
437 rts = kzalloc_obj(*rts);
438 if (!rts)
439 return -ENOMEM;
440
441 rts->threshold = rts_threshold;
442
443 ret = wl1251_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
444 if (ret < 0) {
445 wl1251_warning("failed to set rts threshold: %d", ret);
446 goto out;
447 }
448
449 out:
450 kfree(rts);
451 return ret;
452 }
453
wl1251_acx_beacon_filter_opt(struct wl1251 * wl,bool enable_filter)454 int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter)
455 {
456 struct acx_beacon_filter_option *beacon_filter;
457 int ret;
458
459 wl1251_debug(DEBUG_ACX, "acx beacon filter opt");
460
461 beacon_filter = kzalloc_obj(*beacon_filter);
462 if (!beacon_filter)
463 return -ENOMEM;
464
465 beacon_filter->enable = enable_filter;
466 beacon_filter->max_num_beacons = 0;
467
468 ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
469 beacon_filter, sizeof(*beacon_filter));
470 if (ret < 0) {
471 wl1251_warning("failed to set beacon filter opt: %d", ret);
472 goto out;
473 }
474
475 out:
476 kfree(beacon_filter);
477 return ret;
478 }
479
wl1251_acx_beacon_filter_table(struct wl1251 * wl)480 int wl1251_acx_beacon_filter_table(struct wl1251 *wl)
481 {
482 struct acx_beacon_filter_ie_table *ie_table;
483 int idx = 0;
484 int ret;
485
486 wl1251_debug(DEBUG_ACX, "acx beacon filter table");
487
488 ie_table = kzalloc_obj(*ie_table);
489 if (!ie_table)
490 return -ENOMEM;
491
492 /* configure default beacon pass-through rules */
493 ie_table->num_ie = 1;
494 ie_table->table[idx++] = BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN;
495 ie_table->table[idx++] = BEACON_RULE_PASS_ON_APPEARANCE;
496
497 ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
498 ie_table, sizeof(*ie_table));
499 if (ret < 0) {
500 wl1251_warning("failed to set beacon filter table: %d", ret);
501 goto out;
502 }
503
504 out:
505 kfree(ie_table);
506 return ret;
507 }
508
wl1251_acx_conn_monit_params(struct wl1251 * wl)509 int wl1251_acx_conn_monit_params(struct wl1251 *wl)
510 {
511 struct acx_conn_monit_params *acx;
512 int ret;
513
514 wl1251_debug(DEBUG_ACX, "acx connection monitor parameters");
515
516 acx = kzalloc_obj(*acx);
517 if (!acx)
518 return -ENOMEM;
519
520 acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD;
521 acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT;
522
523 ret = wl1251_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
524 acx, sizeof(*acx));
525 if (ret < 0) {
526 wl1251_warning("failed to set connection monitor "
527 "parameters: %d", ret);
528 goto out;
529 }
530
531 out:
532 kfree(acx);
533 return ret;
534 }
535
wl1251_acx_sg_enable(struct wl1251 * wl)536 int wl1251_acx_sg_enable(struct wl1251 *wl)
537 {
538 struct acx_bt_wlan_coex *pta;
539 int ret;
540
541 wl1251_debug(DEBUG_ACX, "acx sg enable");
542
543 pta = kzalloc_obj(*pta);
544 if (!pta)
545 return -ENOMEM;
546
547 pta->enable = SG_ENABLE;
548
549 ret = wl1251_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
550 if (ret < 0) {
551 wl1251_warning("failed to set softgemini enable: %d", ret);
552 goto out;
553 }
554
555 out:
556 kfree(pta);
557 return ret;
558 }
559
wl1251_acx_sg_cfg(struct wl1251 * wl)560 int wl1251_acx_sg_cfg(struct wl1251 *wl)
561 {
562 struct acx_bt_wlan_coex_param *param;
563 int ret;
564
565 wl1251_debug(DEBUG_ACX, "acx sg cfg");
566
567 param = kzalloc_obj(*param);
568 if (!param)
569 return -ENOMEM;
570
571 /* BT-WLAN coext parameters */
572 param->min_rate = RATE_INDEX_24MBPS;
573 param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
574 param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
575 param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
576 param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
577 param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
578 param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
579 param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
580 param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
581 param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
582 param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
583 param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
584 param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
585 param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
586 param->antenna_type = PTA_ANTENNA_TYPE_DEF;
587 param->signal_type = PTA_SIGNALING_TYPE_DEF;
588 param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
589 param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
590 param->max_cts = PTA_MAX_NUM_CTS_DEF;
591 param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
592 param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
593 param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
594 param->wlan_elp_hp = PTA_ELP_HP_DEF;
595 param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
596 param->ack_mode_dual_ant = PTA_ACK_MODE_DEF;
597 param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
598 param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
599 param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
600
601 ret = wl1251_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
602 if (ret < 0) {
603 wl1251_warning("failed to set sg config: %d", ret);
604 goto out;
605 }
606
607 out:
608 kfree(param);
609 return ret;
610 }
611
wl1251_acx_cca_threshold(struct wl1251 * wl)612 int wl1251_acx_cca_threshold(struct wl1251 *wl)
613 {
614 struct acx_energy_detection *detection;
615 int ret;
616
617 wl1251_debug(DEBUG_ACX, "acx cca threshold");
618
619 detection = kzalloc_obj(*detection);
620 if (!detection)
621 return -ENOMEM;
622
623 detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
624 detection->tx_energy_detection = 0;
625
626 ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD,
627 detection, sizeof(*detection));
628 if (ret < 0)
629 wl1251_warning("failed to set cca threshold: %d", ret);
630
631 kfree(detection);
632 return ret;
633 }
634
wl1251_acx_bcn_dtim_options(struct wl1251 * wl)635 int wl1251_acx_bcn_dtim_options(struct wl1251 *wl)
636 {
637 struct acx_beacon_broadcast *bb;
638 int ret;
639
640 wl1251_debug(DEBUG_ACX, "acx bcn dtim options");
641
642 bb = kzalloc_obj(*bb);
643 if (!bb)
644 return -ENOMEM;
645
646 bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
647 bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
648 bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
649 bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
650
651 ret = wl1251_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
652 if (ret < 0) {
653 wl1251_warning("failed to set rx config: %d", ret);
654 goto out;
655 }
656
657 out:
658 kfree(bb);
659 return ret;
660 }
661
wl1251_acx_aid(struct wl1251 * wl,u16 aid)662 int wl1251_acx_aid(struct wl1251 *wl, u16 aid)
663 {
664 struct acx_aid *acx_aid;
665 int ret;
666
667 wl1251_debug(DEBUG_ACX, "acx aid");
668
669 acx_aid = kzalloc_obj(*acx_aid);
670 if (!acx_aid)
671 return -ENOMEM;
672
673 acx_aid->aid = aid;
674
675 ret = wl1251_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
676 if (ret < 0) {
677 wl1251_warning("failed to set aid: %d", ret);
678 goto out;
679 }
680
681 out:
682 kfree(acx_aid);
683 return ret;
684 }
685
wl1251_acx_event_mbox_mask(struct wl1251 * wl,u32 event_mask)686 int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask)
687 {
688 struct acx_event_mask *mask;
689 int ret;
690
691 wl1251_debug(DEBUG_ACX, "acx event mbox mask");
692
693 mask = kzalloc_obj(*mask);
694 if (!mask)
695 return -ENOMEM;
696
697 /* high event mask is unused */
698 mask->high_event_mask = 0xffffffff;
699
700 mask->event_mask = event_mask;
701
702 ret = wl1251_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
703 mask, sizeof(*mask));
704 if (ret < 0) {
705 wl1251_warning("failed to set acx_event_mbox_mask: %d", ret);
706 goto out;
707 }
708
709 out:
710 kfree(mask);
711 return ret;
712 }
713
wl1251_acx_low_rssi(struct wl1251 * wl,s8 threshold,u8 weight,u8 depth,enum wl1251_acx_low_rssi_type type)714 int wl1251_acx_low_rssi(struct wl1251 *wl, s8 threshold, u8 weight,
715 u8 depth, enum wl1251_acx_low_rssi_type type)
716 {
717 struct acx_low_rssi *rssi;
718 int ret;
719
720 wl1251_debug(DEBUG_ACX, "acx low rssi");
721
722 rssi = kzalloc_obj(*rssi);
723 if (!rssi)
724 return -ENOMEM;
725
726 rssi->threshold = threshold;
727 rssi->weight = weight;
728 rssi->depth = depth;
729 rssi->type = type;
730
731 ret = wl1251_cmd_configure(wl, ACX_LOW_RSSI, rssi, sizeof(*rssi));
732 if (ret < 0)
733 wl1251_warning("failed to set low rssi threshold: %d", ret);
734
735 kfree(rssi);
736 return ret;
737 }
738
wl1251_acx_set_preamble(struct wl1251 * wl,enum acx_preamble_type preamble)739 int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble)
740 {
741 struct acx_preamble *acx;
742 int ret;
743
744 wl1251_debug(DEBUG_ACX, "acx_set_preamble");
745
746 acx = kzalloc_obj(*acx);
747 if (!acx)
748 return -ENOMEM;
749
750 acx->preamble = preamble;
751
752 ret = wl1251_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
753 if (ret < 0) {
754 wl1251_warning("Setting of preamble failed: %d", ret);
755 goto out;
756 }
757
758 out:
759 kfree(acx);
760 return ret;
761 }
762
wl1251_acx_cts_protect(struct wl1251 * wl,enum acx_ctsprotect_type ctsprotect)763 int wl1251_acx_cts_protect(struct wl1251 *wl,
764 enum acx_ctsprotect_type ctsprotect)
765 {
766 struct acx_ctsprotect *acx;
767 int ret;
768
769 wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect");
770
771 acx = kzalloc_obj(*acx);
772 if (!acx)
773 return -ENOMEM;
774
775 acx->ctsprotect = ctsprotect;
776
777 ret = wl1251_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
778 if (ret < 0) {
779 wl1251_warning("Setting of ctsprotect failed: %d", ret);
780 goto out;
781 }
782
783 out:
784 kfree(acx);
785 return ret;
786 }
787
wl1251_acx_tsf_info(struct wl1251 * wl,u64 * mactime)788 int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime)
789 {
790 struct acx_tsf_info *tsf_info;
791 int ret;
792
793 tsf_info = kzalloc_obj(*tsf_info);
794 if (!tsf_info)
795 return -ENOMEM;
796
797 ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO,
798 tsf_info, sizeof(*tsf_info));
799 if (ret < 0) {
800 wl1251_warning("ACX_FW_REV interrogate failed");
801 goto out;
802 }
803
804 *mactime = tsf_info->current_tsf_lsb |
805 ((u64)tsf_info->current_tsf_msb << 32);
806
807 out:
808 kfree(tsf_info);
809 return ret;
810 }
811
wl1251_acx_statistics(struct wl1251 * wl,struct acx_statistics * stats)812 int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats)
813 {
814 int ret;
815
816 wl1251_debug(DEBUG_ACX, "acx statistics");
817
818 ret = wl1251_cmd_interrogate(wl, ACX_STATISTICS, stats,
819 sizeof(*stats));
820 if (ret < 0) {
821 wl1251_warning("acx statistics failed: %d", ret);
822 return -ENOMEM;
823 }
824
825 return 0;
826 }
827
wl1251_acx_mem_cfg(struct wl1251 * wl)828 int wl1251_acx_mem_cfg(struct wl1251 *wl)
829 {
830 struct wl1251_acx_config_memory *mem_conf;
831 int ret, i;
832
833 wl1251_debug(DEBUG_ACX, "acx mem cfg");
834
835 mem_conf = kzalloc_obj(*mem_conf);
836 if (!mem_conf)
837 return -ENOMEM;
838
839 /* memory config */
840 mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
841 mem_conf->mem_config.rx_mem_block_num = 35;
842 mem_conf->mem_config.tx_min_mem_block_num = 64;
843 mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES;
844 mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING;
845 mem_conf->mem_config.num_ssid_profiles = 1;
846 mem_conf->mem_config.debug_buffer_size =
847 cpu_to_le16(TRACE_BUFFER_MAX_SIZE);
848
849 /* RX queue config */
850 mem_conf->rx_queue_config.dma_address = 0;
851 mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF;
852 mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY;
853 mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE;
854
855 /* TX queue config */
856 for (i = 0; i < MAX_TX_QUEUES; i++) {
857 mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF;
858 mem_conf->tx_queue_config[i].attributes = i;
859 }
860
861 ret = wl1251_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
862 sizeof(*mem_conf));
863 if (ret < 0) {
864 wl1251_warning("wl1251 mem config failed: %d", ret);
865 goto out;
866 }
867
868 out:
869 kfree(mem_conf);
870 return ret;
871 }
872
wl1251_acx_wr_tbtt_and_dtim(struct wl1251 * wl,u16 tbtt,u8 dtim)873 int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim)
874 {
875 struct wl1251_acx_wr_tbtt_and_dtim *acx;
876 int ret;
877
878 wl1251_debug(DEBUG_ACX, "acx tbtt and dtim");
879
880 acx = kzalloc_obj(*acx);
881 if (!acx)
882 return -ENOMEM;
883
884 acx->tbtt = tbtt;
885 acx->dtim = dtim;
886
887 ret = wl1251_cmd_configure(wl, ACX_WR_TBTT_AND_DTIM,
888 acx, sizeof(*acx));
889 if (ret < 0) {
890 wl1251_warning("failed to set tbtt and dtim: %d", ret);
891 goto out;
892 }
893
894 out:
895 kfree(acx);
896 return ret;
897 }
898
wl1251_acx_bet_enable(struct wl1251 * wl,enum wl1251_acx_bet_mode mode,u8 max_consecutive)899 int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
900 u8 max_consecutive)
901 {
902 struct wl1251_acx_bet_enable *acx;
903 int ret;
904
905 wl1251_debug(DEBUG_ACX, "acx bet enable");
906
907 acx = kzalloc_obj(*acx);
908 if (!acx)
909 return -ENOMEM;
910
911 acx->enable = mode;
912 acx->max_consecutive = max_consecutive;
913
914 ret = wl1251_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
915 if (ret < 0) {
916 wl1251_warning("wl1251 acx bet enable failed: %d", ret);
917 goto out;
918 }
919
920 out:
921 kfree(acx);
922 return ret;
923 }
924
wl1251_acx_arp_ip_filter(struct wl1251 * wl,bool enable,__be32 address)925 int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address)
926 {
927 struct wl1251_acx_arp_filter *acx;
928 int ret;
929
930 wl1251_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
931
932 acx = kzalloc_obj(*acx);
933 if (!acx)
934 return -ENOMEM;
935
936 acx->version = ACX_IPV4_VERSION;
937 acx->enable = enable;
938
939 if (enable)
940 memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);
941
942 ret = wl1251_cmd_configure(wl, ACX_ARP_IP_FILTER,
943 acx, sizeof(*acx));
944 if (ret < 0)
945 wl1251_warning("failed to set arp ip filter: %d", ret);
946
947 kfree(acx);
948 return ret;
949 }
950
wl1251_acx_ac_cfg(struct wl1251 * wl,u8 ac,u8 cw_min,u16 cw_max,u8 aifs,u16 txop)951 int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
952 u8 aifs, u16 txop)
953 {
954 struct wl1251_acx_ac_cfg *acx;
955 int ret = 0;
956
957 wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d "
958 "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop);
959
960 acx = kzalloc_obj(*acx);
961 if (!acx)
962 return -ENOMEM;
963
964 acx->ac = ac;
965 acx->cw_min = cw_min;
966 acx->cw_max = cw_max;
967 acx->aifsn = aifs;
968 acx->txop_limit = txop;
969
970 ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
971 if (ret < 0) {
972 wl1251_warning("acx ac cfg failed: %d", ret);
973 goto out;
974 }
975
976 out:
977 kfree(acx);
978 return ret;
979 }
980
wl1251_acx_tid_cfg(struct wl1251 * wl,u8 queue,enum wl1251_acx_channel_type type,u8 tsid,enum wl1251_acx_ps_scheme ps_scheme,enum wl1251_acx_ack_policy ack_policy)981 int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
982 enum wl1251_acx_channel_type type,
983 u8 tsid, enum wl1251_acx_ps_scheme ps_scheme,
984 enum wl1251_acx_ack_policy ack_policy)
985 {
986 struct wl1251_acx_tid_cfg *acx;
987 int ret = 0;
988
989 wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d "
990 "ps_scheme %d ack_policy %d", queue, type, tsid,
991 ps_scheme, ack_policy);
992
993 acx = kzalloc_obj(*acx);
994 if (!acx)
995 return -ENOMEM;
996
997 acx->queue = queue;
998 acx->type = type;
999 acx->tsid = tsid;
1000 acx->ps_scheme = ps_scheme;
1001 acx->ack_policy = ack_policy;
1002
1003 ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
1004 if (ret < 0) {
1005 wl1251_warning("acx tid cfg failed: %d", ret);
1006 goto out;
1007 }
1008
1009 out:
1010 kfree(acx);
1011 return ret;
1012 }
1013