acx.c 17.0 KB
Newer Older
K
Kalle Valo 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include "acx.h"

#include <linux/module.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>

#include "wl12xx.h"
#include "wl12xx_80211.h"
#include "reg.h"
#include "spi.h"
#include "ps.h"

int wl12xx_acx_frame_rates(struct wl12xx *wl, u8 ctrl_rate, u8 ctrl_mod,
			   u8 mgt_rate, u8 mgt_mod)
{
16
	struct acx_fw_gen_frame_rates *rates;
K
Kalle Valo 已提交
17 18 19 20
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx frame rates");

21 22 23 24 25
	rates = kzalloc(sizeof(*rates), GFP_KERNEL);
	if (!rates) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
26

27 28 29 30
	rates->tx_ctrl_frame_rate = ctrl_rate;
	rates->tx_ctrl_frame_mod = ctrl_mod;
	rates->tx_mgt_frame_rate = mgt_rate;
	rates->tx_mgt_frame_mod = mgt_mod;
K
Kalle Valo 已提交
31

32 33
	ret = wl12xx_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES,
				   rates, sizeof(*rates));
K
Kalle Valo 已提交
34 35
	if (ret < 0) {
		wl12xx_error("Failed to set FW rates and modulation");
36
		goto out;
K
Kalle Valo 已提交
37 38
	}

39 40 41
out:
	kfree(rates);
	return ret;
K
Kalle Valo 已提交
42 43 44 45 46
}


int wl12xx_acx_station_id(struct wl12xx *wl)
{
47
	struct acx_dot11_station_id *mac;
K
Kalle Valo 已提交
48 49 50 51
	int ret, i;

	wl12xx_debug(DEBUG_ACX, "acx dot11_station_id");

52 53 54 55 56
	mac = kzalloc(sizeof(*mac), GFP_KERNEL);
	if (!mac) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
57 58

	for (i = 0; i < ETH_ALEN; i++)
59
		mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
K
Kalle Valo 已提交
60

61
	ret = wl12xx_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac));
K
Kalle Valo 已提交
62
	if (ret < 0)
63
		goto out;
K
Kalle Valo 已提交
64

65 66 67
out:
	kfree(mac);
	return ret;
K
Kalle Valo 已提交
68 69 70 71
}

int wl12xx_acx_default_key(struct wl12xx *wl, u8 key_id)
{
72
	struct acx_dot11_default_key *default_key;
K
Kalle Valo 已提交
73 74 75 76
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);

77 78 79 80 81
	default_key = kzalloc(sizeof(*default_key), GFP_KERNEL);
	if (!default_key) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
82

83
	default_key->id = key_id;
K
Kalle Valo 已提交
84

85 86
	ret = wl12xx_cmd_configure(wl, DOT11_DEFAULT_KEY,
				   default_key, sizeof(*default_key));
K
Kalle Valo 已提交
87 88
	if (ret < 0) {
		wl12xx_error("Couldnt set default key");
89
		goto out;
K
Kalle Valo 已提交
90 91 92 93
	}

	wl->default_key = key_id;

94 95 96
out:
	kfree(default_key);
	return ret;
K
Kalle Valo 已提交
97 98
}

99 100
int wl12xx_acx_wake_up_conditions(struct wl12xx *wl, u8 wake_up_event,
				  u8 listen_interval)
K
Kalle Valo 已提交
101
{
102 103
	struct acx_wake_up_condition *wake_up;
	int ret;
K
Kalle Valo 已提交
104 105 106

	wl12xx_debug(DEBUG_ACX, "acx wake up conditions");

107 108 109 110 111
	wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
	if (!wake_up) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
112

113
	wake_up->wake_up_event = wake_up_event;
114
	wake_up->listen_interval = listen_interval;
K
Kalle Valo 已提交
115

116 117 118 119 120 121 122 123 124 125
	ret = wl12xx_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
				   wake_up, sizeof(*wake_up));
	if (ret < 0) {
		wl12xx_warning("could not set wake up conditions: %d", ret);
		goto out;
	}

out:
	kfree(wake_up);
	return ret;
K
Kalle Valo 已提交
126 127 128 129
}

int wl12xx_acx_sleep_auth(struct wl12xx *wl, u8 sleep_auth)
{
130
	struct acx_sleep_auth *auth;
K
Kalle Valo 已提交
131 132 133 134
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx sleep auth");

135 136 137 138 139
	auth = kzalloc(sizeof(*auth), GFP_KERNEL);
	if (!auth) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
140

141
	auth->sleep_auth = sleep_auth;
K
Kalle Valo 已提交
142

143
	ret = wl12xx_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
K
Kalle Valo 已提交
144 145 146
	if (ret < 0)
		return ret;

147 148 149
out:
	kfree(auth);
	return ret;
K
Kalle Valo 已提交
150 151 152 153 154 155 156 157 158
}

int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len)
{
	struct acx_revision *rev;
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx fw rev");

159 160 161 162 163
	rev = kzalloc(sizeof(*rev), GFP_KERNEL);
	if (!rev) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
164

165
	ret = wl12xx_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
K
Kalle Valo 已提交
166 167
	if (ret < 0) {
		wl12xx_warning("ACX_FW_REV interrogate failed");
168
		goto out;
K
Kalle Valo 已提交
169 170 171 172 173 174 175 176 177 178 179 180
	}

	/* be careful with the buffer sizes */
	strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));

	/*
	 * if the firmware version string is exactly
	 * sizeof(rev->fw_version) long or fw_len is less than
	 * sizeof(rev->fw_version) it won't be null terminated
	 */
	buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';

181 182 183
out:
	kfree(rev);
	return ret;
K
Kalle Valo 已提交
184 185 186 187
}

int wl12xx_acx_tx_power(struct wl12xx *wl, int power)
{
188
	struct acx_current_tx_power *acx;
K
Kalle Valo 已提交
189 190 191 192 193 194 195
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");

	if (power < 0 || power > 25)
		return -EINVAL;

196 197 198 199 200
	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
201

202
	acx->current_tx_power = power * 10;
K
Kalle Valo 已提交
203

204
	ret = wl12xx_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
K
Kalle Valo 已提交
205 206
	if (ret < 0) {
		wl12xx_warning("configure of tx power failed: %d", ret);
207
		goto out;
K
Kalle Valo 已提交
208 209
	}

210 211 212
out:
	kfree(acx);
	return ret;
K
Kalle Valo 已提交
213 214 215 216
}

int wl12xx_acx_feature_cfg(struct wl12xx *wl)
{
217
	struct acx_feature_config *feature;
K
Kalle Valo 已提交
218 219 220 221
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx feature cfg");

222 223 224 225 226
	feature = kzalloc(sizeof(*feature), GFP_KERNEL);
	if (!feature) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
227 228

	/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
229 230
	feature->data_flow_options = 0;
	feature->options = 0;
K
Kalle Valo 已提交
231

232 233 234
	ret = wl12xx_cmd_configure(wl, ACX_FEATURE_CFG,
				   feature, sizeof(*feature));
	if (ret < 0) {
K
Kalle Valo 已提交
235
		wl12xx_error("Couldnt set HW encryption");
236 237
		goto out;
	}
K
Kalle Valo 已提交
238

239 240
out:
	kfree(feature);
K
Kalle Valo 已提交
241 242 243
	return ret;
}

244 245
int wl12xx_acx_mem_map(struct wl12xx *wl, struct acx_header *mem_map,
		       size_t len)
K
Kalle Valo 已提交
246 247 248 249 250
{
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx mem map");

251
	ret = wl12xx_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
K
Kalle Valo 已提交
252 253 254 255 256 257 258
	if (ret < 0)
		return ret;

	return 0;
}

int wl12xx_acx_data_path_params(struct wl12xx *wl,
259
				struct acx_data_path_params_resp *resp)
K
Kalle Valo 已提交
260
{
261
	struct acx_data_path_params *params;
K
Kalle Valo 已提交
262 263 264 265
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx data path params");

266 267 268 269 270
	params = kzalloc(sizeof(*params), GFP_KERNEL);
	if (!params) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
271

272 273
	params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
	params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
K
Kalle Valo 已提交
274

275 276
	params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM;
	params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM;
K
Kalle Valo 已提交
277

278
	params->tx_complete_threshold = 1;
K
Kalle Valo 已提交
279

280
	params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE;
K
Kalle Valo 已提交
281

282
	params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT;
K
Kalle Valo 已提交
283

284 285
	ret = wl12xx_cmd_configure(wl, ACX_DATA_PATH_PARAMS,
				   params, sizeof(*params));
K
Kalle Valo 已提交
286
	if (ret < 0)
287
		goto out;
K
Kalle Valo 已提交
288

289
	/* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */
K
Kalle Valo 已提交
290
	ret = wl12xx_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS,
291
				     resp, sizeof(*resp));
K
Kalle Valo 已提交
292 293 294

	if (ret < 0) {
		wl12xx_warning("failed to read data path parameters: %d", ret);
295 296
		goto out;
	} else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) {
K
Kalle Valo 已提交
297
		wl12xx_warning("data path parameter acx status failed");
298 299
		ret = -EIO;
		goto out;
K
Kalle Valo 已提交
300 301
	}

302 303 304
out:
	kfree(params);
	return ret;
K
Kalle Valo 已提交
305 306 307 308
}

int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time)
{
309
	struct acx_rx_msdu_lifetime *acx;
K
Kalle Valo 已提交
310 311 312 313
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx rx msdu life time");

314 315 316 317 318
	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
319

320 321
	ret = wl12xx_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
				   acx, sizeof(*acx));
K
Kalle Valo 已提交
322 323
	if (ret < 0) {
		wl12xx_warning("failed to set rx msdu life time: %d", ret);
324
		goto out;
K
Kalle Valo 已提交
325 326
	}

327 328 329
out:
	kfree(acx);
	return ret;
K
Kalle Valo 已提交
330 331 332 333
}

int wl12xx_acx_rx_config(struct wl12xx *wl, u32 config, u32 filter)
{
334
	struct acx_rx_config *rx_config;
K
Kalle Valo 已提交
335 336 337 338
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx rx config");

339 340 341 342 343 344 345 346
	rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
	if (!rx_config) {
		ret = -ENOMEM;
		goto out;
	}

	rx_config->config_options = config;
	rx_config->filter_options = filter;
K
Kalle Valo 已提交
347

348 349
	ret = wl12xx_cmd_configure(wl, ACX_RX_CFG,
				   rx_config, sizeof(*rx_config));
K
Kalle Valo 已提交
350 351
	if (ret < 0) {
		wl12xx_warning("failed to set rx config: %d", ret);
352
		goto out;
K
Kalle Valo 已提交
353 354
	}

355 356 357
out:
	kfree(rx_config);
	return ret;
K
Kalle Valo 已提交
358 359 360 361
}

int wl12xx_acx_pd_threshold(struct wl12xx *wl)
{
362
	struct acx_packet_detection *pd;
K
Kalle Valo 已提交
363 364 365 366
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx data pd threshold");

367 368 369 370 371 372
	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
	if (!pd) {
		ret = -ENOMEM;
		goto out;
	}

K
Kalle Valo 已提交
373 374
	/* FIXME: threshold value not set */

375
	ret = wl12xx_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
K
Kalle Valo 已提交
376 377
	if (ret < 0) {
		wl12xx_warning("failed to set pd threshold: %d", ret);
378
		goto out;
K
Kalle Valo 已提交
379 380
	}

381 382
out:
	kfree(pd);
K
Kalle Valo 已提交
383 384 385 386 387
	return 0;
}

int wl12xx_acx_slot(struct wl12xx *wl, enum acx_slot_type slot_time)
{
388
	struct acx_slot *slot;
K
Kalle Valo 已提交
389 390 391 392
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx slot");

393 394 395 396 397
	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
	if (!slot) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
398

399 400
	slot->wone_index = STATION_WONE_INDEX;
	slot->slot_time = slot_time;
K
Kalle Valo 已提交
401

402
	ret = wl12xx_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
K
Kalle Valo 已提交
403 404
	if (ret < 0) {
		wl12xx_warning("failed to set slot time: %d", ret);
405
		goto out;
K
Kalle Valo 已提交
406 407
	}

408 409 410
out:
	kfree(slot);
	return ret;
K
Kalle Valo 已提交
411 412 413 414
}

int wl12xx_acx_group_address_tbl(struct wl12xx *wl)
{
415
	struct acx_dot11_grp_addr_tbl *acx;
K
Kalle Valo 已提交
416 417 418 419
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx group address tbl");

420 421 422 423 424
	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
425

426 427 428 429
	/* MAC filtering */
	acx->enabled = 0;
	acx->num_groups = 0;
	memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
K
Kalle Valo 已提交
430

431 432
	ret = wl12xx_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
				   acx, sizeof(*acx));
K
Kalle Valo 已提交
433 434
	if (ret < 0) {
		wl12xx_warning("failed to set group addr table: %d", ret);
435
		goto out;
K
Kalle Valo 已提交
436 437
	}

438 439 440
out:
	kfree(acx);
	return ret;
K
Kalle Valo 已提交
441 442 443 444
}

int wl12xx_acx_service_period_timeout(struct wl12xx *wl)
{
445
	struct acx_rx_timeout *rx_timeout;
K
Kalle Valo 已提交
446 447
	int ret;

448 449 450 451 452
	rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
	if (!rx_timeout) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
453

454
	wl12xx_debug(DEBUG_ACX, "acx service period timeout");
K
Kalle Valo 已提交
455

456 457
	rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
	rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
K
Kalle Valo 已提交
458

459 460
	ret = wl12xx_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
				   rx_timeout, sizeof(*rx_timeout));
K
Kalle Valo 已提交
461 462 463
	if (ret < 0) {
		wl12xx_warning("failed to set service period timeout: %d",
			       ret);
464
		goto out;
K
Kalle Valo 已提交
465 466
	}

467 468 469
out:
	kfree(rx_timeout);
	return ret;
K
Kalle Valo 已提交
470 471 472 473
}

int wl12xx_acx_rts_threshold(struct wl12xx *wl, u16 rts_threshold)
{
474
	struct acx_rts_threshold *rts;
K
Kalle Valo 已提交
475 476 477 478
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx rts threshold");

479 480 481 482 483
	rts = kzalloc(sizeof(*rts), GFP_KERNEL);
	if (!rts) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
484

485
	rts->threshold = rts_threshold;
K
Kalle Valo 已提交
486

487
	ret = wl12xx_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
K
Kalle Valo 已提交
488 489
	if (ret < 0) {
		wl12xx_warning("failed to set rts threshold: %d", ret);
490
		goto out;
K
Kalle Valo 已提交
491 492
	}

493 494 495
out:
	kfree(rts);
	return ret;
K
Kalle Valo 已提交
496 497 498 499
}

int wl12xx_acx_beacon_filter_opt(struct wl12xx *wl)
{
500
	struct acx_beacon_filter_option *beacon_filter;
K
Kalle Valo 已提交
501 502 503 504
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx beacon filter opt");

505 506 507 508 509
	beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
	if (!beacon_filter) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
510

511 512
	beacon_filter->enable = 0;
	beacon_filter->max_num_beacons = 0;
K
Kalle Valo 已提交
513

514 515
	ret = wl12xx_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
				   beacon_filter, sizeof(*beacon_filter));
K
Kalle Valo 已提交
516 517
	if (ret < 0) {
		wl12xx_warning("failed to set beacon filter opt: %d", ret);
518
		goto out;
K
Kalle Valo 已提交
519 520
	}

521 522 523
out:
	kfree(beacon_filter);
	return ret;
K
Kalle Valo 已提交
524 525 526 527
}

int wl12xx_acx_beacon_filter_table(struct wl12xx *wl)
{
528
	struct acx_beacon_filter_ie_table *ie_table;
K
Kalle Valo 已提交
529 530 531 532
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx beacon filter table");

533 534 535 536 537
	ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
	if (!ie_table) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
538

539 540
	ie_table->num_ie = 0;
	memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE);
K
Kalle Valo 已提交
541

542 543
	ret = wl12xx_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
				   ie_table, sizeof(*ie_table));
K
Kalle Valo 已提交
544 545
	if (ret < 0) {
		wl12xx_warning("failed to set beacon filter table: %d", ret);
546
		goto out;
K
Kalle Valo 已提交
547 548
	}

549 550 551
out:
	kfree(ie_table);
	return ret;
K
Kalle Valo 已提交
552 553 554 555
}

int wl12xx_acx_sg_enable(struct wl12xx *wl)
{
556
	struct acx_bt_wlan_coex *pta;
K
Kalle Valo 已提交
557 558 559 560
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx sg enable");

561 562 563 564 565
	pta = kzalloc(sizeof(*pta), GFP_KERNEL);
	if (!pta) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
566

567
	pta->enable = SG_ENABLE;
K
Kalle Valo 已提交
568

569
	ret = wl12xx_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
K
Kalle Valo 已提交
570 571
	if (ret < 0) {
		wl12xx_warning("failed to set softgemini enable: %d", ret);
572
		goto out;
K
Kalle Valo 已提交
573 574
	}

575 576 577
out:
	kfree(pta);
	return ret;
K
Kalle Valo 已提交
578 579 580 581
}

int wl12xx_acx_sg_cfg(struct wl12xx *wl)
{
582
	struct acx_bt_wlan_coex_param *param;
K
Kalle Valo 已提交
583 584 585 586
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx sg cfg");

587 588 589 590 591 592
	param = kzalloc(sizeof(*param), GFP_KERNEL);
	if (!param) {
		ret = -ENOMEM;
		goto out;
	}

K
Kalle Valo 已提交
593
	/* BT-WLAN coext parameters */
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
	param->min_rate = RATE_INDEX_24MBPS;
	param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
	param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
	param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
	param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
	param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
	param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
	param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
	param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
	param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
	param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
	param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
	param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
	param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
	param->antenna_type = PTA_ANTENNA_TYPE_DEF;
	param->signal_type = PTA_SIGNALING_TYPE_DEF;
	param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
	param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
	param->max_cts = PTA_MAX_NUM_CTS_DEF;
	param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
	param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
	param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
	param->wlan_elp_hp = PTA_ELP_HP_DEF;
	param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
	param->ack_mode_dual_ant = PTA_ACK_MODE_DEF;
	param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
	param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
	param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;

	ret = wl12xx_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
K
Kalle Valo 已提交
624 625
	if (ret < 0) {
		wl12xx_warning("failed to set sg config: %d", ret);
626
		goto out;
K
Kalle Valo 已提交
627 628
	}

629 630 631
out:
	kfree(param);
	return ret;
K
Kalle Valo 已提交
632 633 634 635
}

int wl12xx_acx_cca_threshold(struct wl12xx *wl)
{
636
	struct acx_energy_detection *detection;
K
Kalle Valo 已提交
637 638 639 640
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx cca threshold");

641 642 643 644 645
	detection = kzalloc(sizeof(*detection), GFP_KERNEL);
	if (!detection) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
646

647 648
	detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
	detection->tx_energy_detection = 0;
K
Kalle Valo 已提交
649

650 651
	ret = wl12xx_cmd_configure(wl, ACX_CCA_THRESHOLD,
				   detection, sizeof(*detection));
K
Kalle Valo 已提交
652 653 654 655 656
	if (ret < 0) {
		wl12xx_warning("failed to set cca threshold: %d", ret);
		return ret;
	}

657 658 659
out:
	kfree(detection);
	return ret;
K
Kalle Valo 已提交
660 661 662 663
}

int wl12xx_acx_bcn_dtim_options(struct wl12xx *wl)
{
664
	struct acx_beacon_broadcast *bb;
K
Kalle Valo 已提交
665 666 667 668
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx bcn dtim options");

669 670 671 672 673
	bb = kzalloc(sizeof(*bb), GFP_KERNEL);
	if (!bb) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
674

675 676 677 678
	bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
	bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
	bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
	bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
K
Kalle Valo 已提交
679

680
	ret = wl12xx_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
K
Kalle Valo 已提交
681 682
	if (ret < 0) {
		wl12xx_warning("failed to set rx config: %d", ret);
683
		goto out;
K
Kalle Valo 已提交
684 685
	}

686 687 688
out:
	kfree(bb);
	return ret;
K
Kalle Valo 已提交
689 690 691 692
}

int wl12xx_acx_aid(struct wl12xx *wl, u16 aid)
{
693
	struct acx_aid *acx_aid;
K
Kalle Valo 已提交
694 695 696 697
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx aid");

698 699 700 701 702
	acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
	if (!acx_aid) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
703

704
	acx_aid->aid = aid;
K
Kalle Valo 已提交
705

706
	ret = wl12xx_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
K
Kalle Valo 已提交
707 708
	if (ret < 0) {
		wl12xx_warning("failed to set aid: %d", ret);
709
		goto out;
K
Kalle Valo 已提交
710 711
	}

712 713 714
out:
	kfree(acx_aid);
	return ret;
K
Kalle Valo 已提交
715 716 717 718
}

int wl12xx_acx_event_mbox_mask(struct wl12xx *wl, u32 event_mask)
{
719
	struct acx_event_mask *mask;
K
Kalle Valo 已提交
720 721 722 723
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx event mbox mask");

724 725 726 727 728
	mask = kzalloc(sizeof(*mask), GFP_KERNEL);
	if (!mask) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
729 730

	/* high event mask is unused */
731
	mask->high_event_mask = 0xffffffff;
K
Kalle Valo 已提交
732

733
	mask->event_mask = event_mask;
K
Kalle Valo 已提交
734

735 736
	ret = wl12xx_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
				   mask, sizeof(*mask));
K
Kalle Valo 已提交
737
	if (ret < 0) {
738
		wl12xx_warning("failed to set acx_event_mbox_mask: %d", ret);
739
		goto out;
K
Kalle Valo 已提交
740 741
	}

742 743 744
out:
	kfree(mask);
	return ret;
K
Kalle Valo 已提交
745 746 747 748
}

int wl12xx_acx_set_preamble(struct wl12xx *wl, enum acx_preamble_type preamble)
{
749
	struct acx_preamble *acx;
K
Kalle Valo 已提交
750 751 752 753
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx_set_preamble");

754 755 756 757 758
	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}
K
Kalle Valo 已提交
759

760 761 762
	acx->preamble = preamble;

	ret = wl12xx_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
K
Kalle Valo 已提交
763 764
	if (ret < 0) {
		wl12xx_warning("Setting of preamble failed: %d", ret);
765
		goto out;
K
Kalle Valo 已提交
766
	}
767 768 769 770

out:
	kfree(acx);
	return ret;
K
Kalle Valo 已提交
771 772 773 774 775
}

int wl12xx_acx_cts_protect(struct wl12xx *wl,
			   enum acx_ctsprotect_type ctsprotect)
{
776
	struct acx_ctsprotect *acx;
K
Kalle Valo 已提交
777 778 779 780
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx_set_ctsprotect");

781 782 783 784 785 786 787
	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}

	acx->ctsprotect = ctsprotect;
K
Kalle Valo 已提交
788

789
	ret = wl12xx_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
K
Kalle Valo 已提交
790 791
	if (ret < 0) {
		wl12xx_warning("Setting of ctsprotect failed: %d", ret);
792
		goto out;
K
Kalle Valo 已提交
793
	}
794 795 796 797

out:
	kfree(acx);
	return ret;
K
Kalle Valo 已提交
798 799
}

800
int wl12xx_acx_tsf_info(struct wl12xx *wl, u64 *mactime)
K
Kalle Valo 已提交
801
{
802
	struct acx_tsf_info *tsf_info;
K
Kalle Valo 已提交
803 804
	int ret;

805 806
	tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL);
	if (!tsf_info) {
K
Kalle Valo 已提交
807 808 809 810
		ret = -ENOMEM;
		goto out;
	}

811 812
	ret = wl12xx_cmd_interrogate(wl, ACX_TSF_INFO,
				     tsf_info, sizeof(*tsf_info));
K
Kalle Valo 已提交
813
	if (ret < 0) {
814
		wl12xx_warning("ACX_FW_REV interrogate failed");
K
Kalle Valo 已提交
815 816 817
		goto out;
	}

818 819
	*mactime = tsf_info->current_tsf_lsb |
		(tsf_info->current_tsf_msb << 31);
K
Kalle Valo 已提交
820 821

out:
822
	kfree(tsf_info);
K
Kalle Valo 已提交
823 824
	return ret;
}
825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840

int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats)
{
	int ret;

	wl12xx_debug(DEBUG_ACX, "acx statistics");

	ret = wl12xx_cmd_interrogate(wl, ACX_STATISTICS, stats,
				     sizeof(*stats));
	if (ret < 0) {
		wl12xx_warning("acx statistics failed: %d", ret);
		return -ENOMEM;
	}

	return 0;
}