diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_acx.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_acx.c | 414 |
1 files changed, 299 insertions, 115 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index f622a4092615..308782421fce 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/crc7.h> | 28 | #include <linux/crc7.h> |
29 | #include <linux/spi/spi.h> | 29 | #include <linux/spi/spi.h> |
30 | #include <linux/slab.h> | ||
30 | 31 | ||
31 | #include "wl1271.h" | 32 | #include "wl1271.h" |
32 | #include "wl12xx_80211.h" | 33 | #include "wl12xx_80211.h" |
@@ -34,8 +35,7 @@ | |||
34 | #include "wl1271_spi.h" | 35 | #include "wl1271_spi.h" |
35 | #include "wl1271_ps.h" | 36 | #include "wl1271_ps.h" |
36 | 37 | ||
37 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event, | 38 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl) |
38 | u8 listen_interval) | ||
39 | { | 39 | { |
40 | struct acx_wake_up_condition *wake_up; | 40 | struct acx_wake_up_condition *wake_up; |
41 | int ret; | 41 | int ret; |
@@ -48,8 +48,8 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event, | |||
48 | goto out; | 48 | goto out; |
49 | } | 49 | } |
50 | 50 | ||
51 | wake_up->wake_up_event = wake_up_event; | 51 | wake_up->wake_up_event = wl->conf.conn.wake_up_event; |
52 | wake_up->listen_interval = listen_interval; | 52 | wake_up->listen_interval = wl->conf.conn.listen_interval; |
53 | 53 | ||
54 | ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, | 54 | ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, |
55 | wake_up, sizeof(*wake_up)); | 55 | wake_up, sizeof(*wake_up)); |
@@ -137,7 +137,12 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) | |||
137 | goto out; | 137 | goto out; |
138 | } | 138 | } |
139 | 139 | ||
140 | acx->current_tx_power = power * 10; | 140 | /* |
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 = 120; | ||
141 | 146 | ||
142 | ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); | 147 | ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); |
143 | if (ret < 0) { | 148 | if (ret < 0) { |
@@ -193,7 +198,7 @@ int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map, | |||
193 | return 0; | 198 | return 0; |
194 | } | 199 | } |
195 | 200 | ||
196 | int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time) | 201 | int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl) |
197 | { | 202 | { |
198 | struct acx_rx_msdu_lifetime *acx; | 203 | struct acx_rx_msdu_lifetime *acx; |
199 | int ret; | 204 | int ret; |
@@ -206,7 +211,7 @@ int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time) | |||
206 | goto out; | 211 | goto out; |
207 | } | 212 | } |
208 | 213 | ||
209 | acx->lifetime = life_time; | 214 | acx->lifetime = cpu_to_le32(wl->conf.rx.rx_msdu_life_time); |
210 | ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, | 215 | ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, |
211 | acx, sizeof(*acx)); | 216 | acx, sizeof(*acx)); |
212 | if (ret < 0) { | 217 | if (ret < 0) { |
@@ -232,8 +237,8 @@ int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter) | |||
232 | goto out; | 237 | goto out; |
233 | } | 238 | } |
234 | 239 | ||
235 | rx_config->config_options = config; | 240 | rx_config->config_options = cpu_to_le32(config); |
236 | rx_config->filter_options = filter; | 241 | rx_config->filter_options = cpu_to_le32(filter); |
237 | 242 | ||
238 | ret = wl1271_cmd_configure(wl, ACX_RX_CFG, | 243 | ret = wl1271_cmd_configure(wl, ACX_RX_CFG, |
239 | rx_config, sizeof(*rx_config)); | 244 | rx_config, sizeof(*rx_config)); |
@@ -260,7 +265,7 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl) | |||
260 | goto out; | 265 | goto out; |
261 | } | 266 | } |
262 | 267 | ||
263 | /* FIXME: threshold value not set */ | 268 | pd->threshold = cpu_to_le32(wl->conf.rx.packet_detection_threshold); |
264 | 269 | ||
265 | ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd)); | 270 | ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd)); |
266 | if (ret < 0) { | 271 | if (ret < 0) { |
@@ -300,7 +305,8 @@ out: | |||
300 | return ret; | 305 | return ret; |
301 | } | 306 | } |
302 | 307 | ||
303 | int wl1271_acx_group_address_tbl(struct wl1271 *wl) | 308 | int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, |
309 | void *mc_list, u32 mc_list_len) | ||
304 | { | 310 | { |
305 | struct acx_dot11_grp_addr_tbl *acx; | 311 | struct acx_dot11_grp_addr_tbl *acx; |
306 | int ret; | 312 | int ret; |
@@ -314,9 +320,9 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl) | |||
314 | } | 320 | } |
315 | 321 | ||
316 | /* MAC filtering */ | 322 | /* MAC filtering */ |
317 | acx->enabled = 0; | 323 | acx->enabled = enable; |
318 | acx->num_groups = 0; | 324 | acx->num_groups = mc_list_len; |
319 | memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN); | 325 | memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN); |
320 | 326 | ||
321 | ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, | 327 | ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, |
322 | acx, sizeof(*acx)); | 328 | acx, sizeof(*acx)); |
@@ -343,8 +349,8 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl) | |||
343 | 349 | ||
344 | wl1271_debug(DEBUG_ACX, "acx service period timeout"); | 350 | wl1271_debug(DEBUG_ACX, "acx service period timeout"); |
345 | 351 | ||
346 | rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF; | 352 | rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout); |
347 | rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF; | 353 | rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout); |
348 | 354 | ||
349 | ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT, | 355 | ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT, |
350 | rx_timeout, sizeof(*rx_timeout)); | 356 | rx_timeout, sizeof(*rx_timeout)); |
@@ -372,7 +378,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold) | |||
372 | goto out; | 378 | goto out; |
373 | } | 379 | } |
374 | 380 | ||
375 | rts->threshold = rts_threshold; | 381 | rts->threshold = cpu_to_le16(rts_threshold); |
376 | 382 | ||
377 | ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); | 383 | ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); |
378 | if (ret < 0) { | 384 | if (ret < 0) { |
@@ -385,20 +391,58 @@ out: | |||
385 | return ret; | 391 | return ret; |
386 | } | 392 | } |
387 | 393 | ||
388 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl) | 394 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl) |
389 | { | 395 | { |
390 | struct acx_beacon_filter_option *beacon_filter; | 396 | struct acx_dco_itrim_params *dco; |
397 | struct conf_itrim_settings *c = &wl->conf.itrim; | ||
391 | int ret; | 398 | int ret; |
392 | 399 | ||
400 | wl1271_debug(DEBUG_ACX, "acx dco itrim parameters"); | ||
401 | |||
402 | dco = kzalloc(sizeof(*dco), GFP_KERNEL); | ||
403 | if (!dco) { | ||
404 | ret = -ENOMEM; | ||
405 | goto out; | ||
406 | } | ||
407 | |||
408 | dco->enable = c->enable; | ||
409 | dco->timeout = cpu_to_le32(c->timeout); | ||
410 | |||
411 | ret = wl1271_cmd_configure(wl, ACX_SET_DCO_ITRIM_PARAMS, | ||
412 | dco, sizeof(*dco)); | ||
413 | if (ret < 0) { | ||
414 | wl1271_warning("failed to set dco itrim parameters: %d", ret); | ||
415 | goto out; | ||
416 | } | ||
417 | |||
418 | out: | ||
419 | kfree(dco); | ||
420 | return ret; | ||
421 | } | ||
422 | |||
423 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) | ||
424 | { | ||
425 | struct acx_beacon_filter_option *beacon_filter = NULL; | ||
426 | int ret = 0; | ||
427 | |||
393 | wl1271_debug(DEBUG_ACX, "acx beacon filter opt"); | 428 | wl1271_debug(DEBUG_ACX, "acx beacon filter opt"); |
394 | 429 | ||
430 | if (enable_filter && | ||
431 | wl->conf.conn.bcn_filt_mode == CONF_BCN_FILT_MODE_DISABLED) | ||
432 | goto out; | ||
433 | |||
395 | beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); | 434 | beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); |
396 | if (!beacon_filter) { | 435 | if (!beacon_filter) { |
397 | ret = -ENOMEM; | 436 | ret = -ENOMEM; |
398 | goto out; | 437 | goto out; |
399 | } | 438 | } |
400 | 439 | ||
401 | beacon_filter->enable = 0; | 440 | beacon_filter->enable = enable_filter; |
441 | |||
442 | /* | ||
443 | * When set to zero, and the filter is enabled, beacons | ||
444 | * without the unicast TIM bit set are dropped. | ||
445 | */ | ||
402 | beacon_filter->max_num_beacons = 0; | 446 | beacon_filter->max_num_beacons = 0; |
403 | 447 | ||
404 | ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT, | 448 | ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT, |
@@ -416,7 +460,9 @@ out: | |||
416 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl) | 460 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl) |
417 | { | 461 | { |
418 | struct acx_beacon_filter_ie_table *ie_table; | 462 | struct acx_beacon_filter_ie_table *ie_table; |
463 | int i, idx = 0; | ||
419 | int ret; | 464 | int ret; |
465 | bool vendor_spec = false; | ||
420 | 466 | ||
421 | wl1271_debug(DEBUG_ACX, "acx beacon filter table"); | 467 | wl1271_debug(DEBUG_ACX, "acx beacon filter table"); |
422 | 468 | ||
@@ -426,8 +472,32 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl) | |||
426 | goto out; | 472 | goto out; |
427 | } | 473 | } |
428 | 474 | ||
475 | /* configure default beacon pass-through rules */ | ||
429 | ie_table->num_ie = 0; | 476 | ie_table->num_ie = 0; |
430 | memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE); | 477 | for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) { |
478 | struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]); | ||
479 | ie_table->table[idx++] = r->ie; | ||
480 | ie_table->table[idx++] = r->rule; | ||
481 | |||
482 | if (r->ie == WLAN_EID_VENDOR_SPECIFIC) { | ||
483 | /* only one vendor specific ie allowed */ | ||
484 | if (vendor_spec) | ||
485 | continue; | ||
486 | |||
487 | /* for vendor specific rules configure the | ||
488 | additional fields */ | ||
489 | memcpy(&(ie_table->table[idx]), r->oui, | ||
490 | CONF_BCN_IE_OUI_LEN); | ||
491 | idx += CONF_BCN_IE_OUI_LEN; | ||
492 | ie_table->table[idx++] = r->type; | ||
493 | memcpy(&(ie_table->table[idx]), r->version, | ||
494 | CONF_BCN_IE_VER_LEN); | ||
495 | idx += CONF_BCN_IE_VER_LEN; | ||
496 | vendor_spec = true; | ||
497 | } | ||
498 | |||
499 | ie_table->num_ie++; | ||
500 | } | ||
431 | 501 | ||
432 | ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, | 502 | ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, |
433 | ie_table, sizeof(*ie_table)); | 503 | ie_table, sizeof(*ie_table)); |
@@ -441,6 +511,36 @@ out: | |||
441 | return ret; | 511 | return ret; |
442 | } | 512 | } |
443 | 513 | ||
514 | int wl1271_acx_conn_monit_params(struct wl1271 *wl) | ||
515 | { | ||
516 | struct acx_conn_monit_params *acx; | ||
517 | int ret; | ||
518 | |||
519 | wl1271_debug(DEBUG_ACX, "acx connection monitor parameters"); | ||
520 | |||
521 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
522 | if (!acx) { | ||
523 | ret = -ENOMEM; | ||
524 | goto out; | ||
525 | } | ||
526 | |||
527 | acx->synch_fail_thold = cpu_to_le32(wl->conf.conn.synch_fail_thold); | ||
528 | acx->bss_lose_timeout = cpu_to_le32(wl->conf.conn.bss_lose_timeout); | ||
529 | |||
530 | ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, | ||
531 | acx, sizeof(*acx)); | ||
532 | if (ret < 0) { | ||
533 | wl1271_warning("failed to set connection monitor " | ||
534 | "parameters: %d", ret); | ||
535 | goto out; | ||
536 | } | ||
537 | |||
538 | out: | ||
539 | kfree(acx); | ||
540 | return ret; | ||
541 | } | ||
542 | |||
543 | |||
444 | int wl1271_acx_sg_enable(struct wl1271 *wl) | 544 | int wl1271_acx_sg_enable(struct wl1271 *wl) |
445 | { | 545 | { |
446 | struct acx_bt_wlan_coex *pta; | 546 | struct acx_bt_wlan_coex *pta; |
@@ -470,6 +570,7 @@ out: | |||
470 | int wl1271_acx_sg_cfg(struct wl1271 *wl) | 570 | int wl1271_acx_sg_cfg(struct wl1271 *wl) |
471 | { | 571 | { |
472 | struct acx_bt_wlan_coex_param *param; | 572 | struct acx_bt_wlan_coex_param *param; |
573 | struct conf_sg_settings *c = &wl->conf.sg; | ||
473 | int ret; | 574 | int ret; |
474 | 575 | ||
475 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); | 576 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); |
@@ -481,34 +582,19 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) | |||
481 | } | 582 | } |
482 | 583 | ||
483 | /* BT-WLAN coext parameters */ | 584 | /* BT-WLAN coext parameters */ |
484 | param->min_rate = RATE_INDEX_24MBPS; | 585 | param->per_threshold = cpu_to_le32(c->per_threshold); |
485 | param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF; | 586 | param->max_scan_compensation_time = |
486 | param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF; | 587 | cpu_to_le32(c->max_scan_compensation_time); |
487 | param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF; | 588 | param->nfs_sample_interval = cpu_to_le16(c->nfs_sample_interval); |
488 | param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF; | 589 | param->load_ratio = c->load_ratio; |
489 | param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF; | 590 | param->auto_ps_mode = c->auto_ps_mode; |
490 | param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF; | 591 | param->probe_req_compensation = c->probe_req_compensation; |
491 | param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF; | 592 | param->scan_window_compensation = c->scan_window_compensation; |
492 | param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF; | 593 | param->antenna_config = c->antenna_config; |
493 | param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF; | 594 | param->beacon_miss_threshold = c->beacon_miss_threshold; |
494 | param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF; | 595 | param->rate_adaptation_threshold = |
495 | param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF; | 596 | cpu_to_le32(c->rate_adaptation_threshold); |
496 | param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF; | 597 | param->rate_adaptation_snr = c->rate_adaptation_snr; |
497 | param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF; | ||
498 | param->antenna_type = PTA_ANTENNA_TYPE_DEF; | ||
499 | param->signal_type = PTA_SIGNALING_TYPE_DEF; | ||
500 | param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF; | ||
501 | param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF; | ||
502 | param->max_cts = PTA_MAX_NUM_CTS_DEF; | ||
503 | param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF; | ||
504 | param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF; | ||
505 | param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF; | ||
506 | param->wlan_elp_hp = PTA_ELP_HP_DEF; | ||
507 | param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF; | ||
508 | param->ack_mode_dual_ant = PTA_ACK_MODE_DEF; | ||
509 | param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF; | ||
510 | param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF; | ||
511 | param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF; | ||
512 | 598 | ||
513 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); | 599 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); |
514 | if (ret < 0) { | 600 | if (ret < 0) { |
@@ -534,8 +620,8 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl) | |||
534 | goto out; | 620 | goto out; |
535 | } | 621 | } |
536 | 622 | ||
537 | detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; | 623 | detection->rx_cca_threshold = cpu_to_le16(wl->conf.rx.rx_cca_threshold); |
538 | detection->tx_energy_detection = 0; | 624 | detection->tx_energy_detection = wl->conf.tx.tx_energy_detection; |
539 | 625 | ||
540 | ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD, | 626 | ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD, |
541 | detection, sizeof(*detection)); | 627 | detection, sizeof(*detection)); |
@@ -562,10 +648,10 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) | |||
562 | goto out; | 648 | goto out; |
563 | } | 649 | } |
564 | 650 | ||
565 | bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; | 651 | bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout); |
566 | bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; | 652 | bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout); |
567 | bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE; | 653 | bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps; |
568 | bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF; | 654 | bb->ps_poll_threshold = wl->conf.conn.ps_poll_threshold; |
569 | 655 | ||
570 | ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb)); | 656 | ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb)); |
571 | if (ret < 0) { | 657 | if (ret < 0) { |
@@ -591,7 +677,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid) | |||
591 | goto out; | 677 | goto out; |
592 | } | 678 | } |
593 | 679 | ||
594 | acx_aid->aid = aid; | 680 | acx_aid->aid = cpu_to_le16(aid); |
595 | 681 | ||
596 | ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); | 682 | ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); |
597 | if (ret < 0) { | 683 | if (ret < 0) { |
@@ -618,9 +704,8 @@ int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask) | |||
618 | } | 704 | } |
619 | 705 | ||
620 | /* high event mask is unused */ | 706 | /* high event mask is unused */ |
621 | mask->high_event_mask = 0xffffffff; | 707 | mask->high_event_mask = cpu_to_le32(0xffffffff); |
622 | 708 | mask->event_mask = cpu_to_le32(event_mask); | |
623 | mask->event_mask = event_mask; | ||
624 | 709 | ||
625 | ret = wl1271_cmd_configure(wl, ACX_EVENT_MBOX_MASK, | 710 | ret = wl1271_cmd_configure(wl, ACX_EVENT_MBOX_MASK, |
626 | mask, sizeof(*mask)); | 711 | mask, sizeof(*mask)); |
@@ -706,6 +791,8 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) | |||
706 | int wl1271_acx_rate_policies(struct wl1271 *wl) | 791 | int wl1271_acx_rate_policies(struct wl1271 *wl) |
707 | { | 792 | { |
708 | struct acx_rate_policy *acx; | 793 | struct acx_rate_policy *acx; |
794 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; | ||
795 | int idx = 0; | ||
709 | int ret = 0; | 796 | int ret = 0; |
710 | 797 | ||
711 | wl1271_debug(DEBUG_ACX, "acx rate policies"); | 798 | wl1271_debug(DEBUG_ACX, "acx rate policies"); |
@@ -717,12 +804,21 @@ int wl1271_acx_rate_policies(struct wl1271 *wl) | |||
717 | goto out; | 804 | goto out; |
718 | } | 805 | } |
719 | 806 | ||
720 | /* configure one default (one-size-fits-all) rate class */ | 807 | /* configure one basic rate class */ |
721 | acx->rate_class_cnt = 1; | 808 | idx = ACX_TX_BASIC_RATE; |
722 | acx->rate_class[0].enabled_rates = ACX_RATE_MASK_ALL; | 809 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); |
723 | acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT; | 810 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; |
724 | acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT; | 811 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; |
725 | acx->rate_class[0].aflags = 0; | 812 | acx->rate_class[idx].aflags = c->aflags; |
813 | |||
814 | /* configure one AP supported rate class */ | ||
815 | idx = ACX_TX_AP_FULL_RATE; | ||
816 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set); | ||
817 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; | ||
818 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; | ||
819 | acx->rate_class[idx].aflags = c->aflags; | ||
820 | |||
821 | acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT); | ||
726 | 822 | ||
727 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); | 823 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); |
728 | if (ret < 0) { | 824 | if (ret < 0) { |
@@ -735,12 +831,14 @@ out: | |||
735 | return ret; | 831 | return ret; |
736 | } | 832 | } |
737 | 833 | ||
738 | int wl1271_acx_ac_cfg(struct wl1271 *wl) | 834 | int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, |
835 | u8 aifsn, u16 txop) | ||
739 | { | 836 | { |
740 | struct acx_ac_cfg *acx; | 837 | struct acx_ac_cfg *acx; |
741 | int i, ret = 0; | 838 | int ret = 0; |
742 | 839 | ||
743 | wl1271_debug(DEBUG_ACX, "acx access category config"); | 840 | wl1271_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d " |
841 | "aifs %d txop %d", ac, cw_min, cw_max, aifsn, txop); | ||
744 | 842 | ||
745 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 843 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
746 | 844 | ||
@@ -749,29 +847,16 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl) | |||
749 | goto out; | 847 | goto out; |
750 | } | 848 | } |
751 | 849 | ||
752 | /* | 850 | acx->ac = ac; |
753 | * FIXME: Configure each AC with appropriate values (most suitable | 851 | acx->cw_min = cw_min; |
754 | * values will probably be different for each AC. | 852 | acx->cw_max = cpu_to_le16(cw_max); |
755 | */ | 853 | acx->aifsn = aifsn; |
756 | for (i = 0; i < WL1271_ACX_AC_COUNT; i++) { | 854 | acx->tx_op_limit = cpu_to_le16(txop); |
757 | acx->ac = i; | 855 | |
758 | 856 | ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); | |
759 | /* | 857 | if (ret < 0) { |
760 | * FIXME: The following default values originate from | 858 | wl1271_warning("acx ac cfg failed: %d", ret); |
761 | * the TI reference driver. What do they mean? | 859 | goto out; |
762 | */ | ||
763 | acx->cw_min = 15; | ||
764 | acx->cw_max = 63; | ||
765 | acx->aifsn = 3; | ||
766 | acx->reserved = 0; | ||
767 | acx->tx_op_limit = 0; | ||
768 | |||
769 | ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); | ||
770 | if (ret < 0) { | ||
771 | wl1271_warning("Setting of access category " | ||
772 | "config: %d", ret); | ||
773 | goto out; | ||
774 | } | ||
775 | } | 860 | } |
776 | 861 | ||
777 | out: | 862 | out: |
@@ -779,10 +864,12 @@ out: | |||
779 | return ret; | 864 | return ret; |
780 | } | 865 | } |
781 | 866 | ||
782 | int wl1271_acx_tid_cfg(struct wl1271 *wl) | 867 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, |
868 | u8 tsid, u8 ps_scheme, u8 ack_policy, | ||
869 | u32 apsd_conf0, u32 apsd_conf1) | ||
783 | { | 870 | { |
784 | struct acx_tid_config *acx; | 871 | struct acx_tid_config *acx; |
785 | int i, ret = 0; | 872 | int ret = 0; |
786 | 873 | ||
787 | wl1271_debug(DEBUG_ACX, "acx tid config"); | 874 | wl1271_debug(DEBUG_ACX, "acx tid config"); |
788 | 875 | ||
@@ -793,18 +880,18 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl) | |||
793 | goto out; | 880 | goto out; |
794 | } | 881 | } |
795 | 882 | ||
796 | /* FIXME: configure each TID with a different AC reference */ | 883 | acx->queue_id = queue_id; |
797 | for (i = 0; i < WL1271_ACX_TID_COUNT; i++) { | 884 | acx->channel_type = channel_type; |
798 | acx->queue_id = i; | 885 | acx->tsid = tsid; |
799 | acx->tsid = WL1271_ACX_AC_BE; | 886 | acx->ps_scheme = ps_scheme; |
800 | acx->ps_scheme = WL1271_ACX_PS_SCHEME_LEGACY; | 887 | acx->ack_policy = ack_policy; |
801 | acx->ack_policy = WL1271_ACX_ACK_POLICY_LEGACY; | 888 | acx->apsd_conf[0] = cpu_to_le32(apsd_conf0); |
889 | acx->apsd_conf[1] = cpu_to_le32(apsd_conf1); | ||
802 | 890 | ||
803 | ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); | 891 | ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); |
804 | if (ret < 0) { | 892 | if (ret < 0) { |
805 | wl1271_warning("Setting of tid config failed: %d", ret); | 893 | wl1271_warning("Setting of tid config failed: %d", ret); |
806 | goto out; | 894 | goto out; |
807 | } | ||
808 | } | 895 | } |
809 | 896 | ||
810 | out: | 897 | out: |
@@ -826,7 +913,7 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl) | |||
826 | goto out; | 913 | goto out; |
827 | } | 914 | } |
828 | 915 | ||
829 | acx->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | 916 | acx->frag_threshold = cpu_to_le16(wl->conf.tx.frag_threshold); |
830 | ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); | 917 | ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); |
831 | if (ret < 0) { | 918 | if (ret < 0) { |
832 | wl1271_warning("Setting of frag threshold failed: %d", ret); | 919 | wl1271_warning("Setting of frag threshold failed: %d", ret); |
@@ -852,8 +939,8 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl) | |||
852 | goto out; | 939 | goto out; |
853 | } | 940 | } |
854 | 941 | ||
855 | acx->tx_compl_timeout = WL1271_ACX_TX_COMPL_TIMEOUT; | 942 | acx->tx_compl_timeout = cpu_to_le16(wl->conf.tx.tx_compl_timeout); |
856 | acx->tx_compl_threshold = WL1271_ACX_TX_COMPL_THRESHOLD; | 943 | acx->tx_compl_threshold = cpu_to_le16(wl->conf.tx.tx_compl_threshold); |
857 | ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx)); | 944 | ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx)); |
858 | if (ret < 0) { | 945 | if (ret < 0) { |
859 | wl1271_warning("Setting of tx options failed: %d", ret); | 946 | wl1271_warning("Setting of tx options failed: %d", ret); |
@@ -879,11 +966,11 @@ int wl1271_acx_mem_cfg(struct wl1271 *wl) | |||
879 | } | 966 | } |
880 | 967 | ||
881 | /* memory config */ | 968 | /* memory config */ |
882 | mem_conf->num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); | 969 | mem_conf->num_stations = DEFAULT_NUM_STATIONS; |
883 | mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS; | 970 | mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS; |
884 | mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS; | 971 | mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS; |
885 | mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES; | 972 | mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES; |
886 | mem_conf->total_tx_descriptors = ACX_TX_DESCRIPTORS; | 973 | mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); |
887 | 974 | ||
888 | ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, | 975 | ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, |
889 | sizeof(*mem_conf)); | 976 | sizeof(*mem_conf)); |
@@ -906,7 +993,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl) | |||
906 | return ret; | 993 | return ret; |
907 | 994 | ||
908 | wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map), | 995 | wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map), |
909 | GFP_KERNEL); | 996 | GFP_KERNEL); |
910 | if (!wl->target_mem_map) { | 997 | if (!wl->target_mem_map) { |
911 | wl1271_error("couldn't allocate target memory map"); | 998 | wl1271_error("couldn't allocate target memory map"); |
912 | return -ENOMEM; | 999 | return -ENOMEM; |
@@ -923,7 +1010,8 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl) | |||
923 | } | 1010 | } |
924 | 1011 | ||
925 | /* initialize TX block book keeping */ | 1012 | /* initialize TX block book keeping */ |
926 | wl->tx_blocks_available = wl->target_mem_map->num_tx_mem_blocks; | 1013 | wl->tx_blocks_available = |
1014 | le32_to_cpu(wl->target_mem_map->num_tx_mem_blocks); | ||
927 | wl1271_debug(DEBUG_TX, "available tx blocks: %d", | 1015 | wl1271_debug(DEBUG_TX, "available tx blocks: %d", |
928 | wl->tx_blocks_available); | 1016 | wl->tx_blocks_available); |
929 | 1017 | ||
@@ -943,10 +1031,10 @@ int wl1271_acx_init_rx_interrupt(struct wl1271 *wl) | |||
943 | goto out; | 1031 | goto out; |
944 | } | 1032 | } |
945 | 1033 | ||
946 | rx_conf->threshold = WL1271_RX_INTR_THRESHOLD_DEF; | 1034 | rx_conf->threshold = cpu_to_le16(wl->conf.rx.irq_pkt_threshold); |
947 | rx_conf->timeout = WL1271_RX_INTR_TIMEOUT_DEF; | 1035 | rx_conf->timeout = cpu_to_le16(wl->conf.rx.irq_timeout); |
948 | rx_conf->mblk_threshold = USHORT_MAX; /* Disabled */ | 1036 | rx_conf->mblk_threshold = cpu_to_le16(wl->conf.rx.irq_blk_threshold); |
949 | rx_conf->queue_type = RX_QUEUE_TYPE_RX_LOW_PRIORITY; | 1037 | rx_conf->queue_type = wl->conf.rx.queue_type; |
950 | 1038 | ||
951 | ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf, | 1039 | ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf, |
952 | sizeof(*rx_conf)); | 1040 | sizeof(*rx_conf)); |
@@ -959,3 +1047,99 @@ out: | |||
959 | kfree(rx_conf); | 1047 | kfree(rx_conf); |
960 | return ret; | 1048 | return ret; |
961 | } | 1049 | } |
1050 | |||
1051 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) | ||
1052 | { | ||
1053 | struct wl1271_acx_bet_enable *acx = NULL; | ||
1054 | int ret = 0; | ||
1055 | |||
1056 | wl1271_debug(DEBUG_ACX, "acx bet enable"); | ||
1057 | |||
1058 | if (enable && wl->conf.conn.bet_enable == CONF_BET_MODE_DISABLE) | ||
1059 | goto out; | ||
1060 | |||
1061 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1062 | if (!acx) { | ||
1063 | ret = -ENOMEM; | ||
1064 | goto out; | ||
1065 | } | ||
1066 | |||
1067 | acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE; | ||
1068 | acx->max_consecutive = wl->conf.conn.bet_max_consecutive; | ||
1069 | |||
1070 | ret = wl1271_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx)); | ||
1071 | if (ret < 0) { | ||
1072 | wl1271_warning("acx bet enable failed: %d", ret); | ||
1073 | goto out; | ||
1074 | } | ||
1075 | |||
1076 | out: | ||
1077 | kfree(acx); | ||
1078 | return ret; | ||
1079 | } | ||
1080 | |||
1081 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | ||
1082 | u8 version) | ||
1083 | { | ||
1084 | struct wl1271_acx_arp_filter *acx; | ||
1085 | int ret; | ||
1086 | |||
1087 | wl1271_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable); | ||
1088 | |||
1089 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1090 | if (!acx) { | ||
1091 | ret = -ENOMEM; | ||
1092 | goto out; | ||
1093 | } | ||
1094 | |||
1095 | acx->version = version; | ||
1096 | acx->enable = enable; | ||
1097 | |||
1098 | if (enable == true) { | ||
1099 | if (version == ACX_IPV4_VERSION) | ||
1100 | memcpy(acx->address, address, ACX_IPV4_ADDR_SIZE); | ||
1101 | else if (version == ACX_IPV6_VERSION) | ||
1102 | memcpy(acx->address, address, sizeof(acx->address)); | ||
1103 | else | ||
1104 | wl1271_error("Invalid IP version"); | ||
1105 | } | ||
1106 | |||
1107 | ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER, | ||
1108 | acx, sizeof(*acx)); | ||
1109 | if (ret < 0) { | ||
1110 | wl1271_warning("failed to set arp ip filter: %d", ret); | ||
1111 | goto out; | ||
1112 | } | ||
1113 | |||
1114 | out: | ||
1115 | kfree(acx); | ||
1116 | return ret; | ||
1117 | } | ||
1118 | |||
1119 | int wl1271_acx_pm_config(struct wl1271 *wl) | ||
1120 | { | ||
1121 | struct wl1271_acx_pm_config *acx = NULL; | ||
1122 | struct conf_pm_config_settings *c = &wl->conf.pm_config; | ||
1123 | int ret = 0; | ||
1124 | |||
1125 | wl1271_debug(DEBUG_ACX, "acx pm config"); | ||
1126 | |||
1127 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1128 | if (!acx) { | ||
1129 | ret = -ENOMEM; | ||
1130 | goto out; | ||
1131 | } | ||
1132 | |||
1133 | acx->host_clk_settling_time = cpu_to_le32(c->host_clk_settling_time); | ||
1134 | acx->host_fast_wakeup_support = c->host_fast_wakeup_support; | ||
1135 | |||
1136 | ret = wl1271_cmd_configure(wl, ACX_PM_CONFIG, acx, sizeof(*acx)); | ||
1137 | if (ret < 0) { | ||
1138 | wl1271_warning("acx pm config failed: %d", ret); | ||
1139 | goto out; | ||
1140 | } | ||
1141 | |||
1142 | out: | ||
1143 | kfree(acx); | ||
1144 | return ret; | ||
1145 | } | ||