acx.c 22.1 KB
Newer Older
1
#include "acx.h"
Kalle Valo's avatar
Kalle Valo committed
2 3

#include <linux/module.h>
4
#include <linux/slab.h>
Kalle Valo's avatar
Kalle Valo committed
5 6
#include <linux/crc7.h>

7
#include "wl1251.h"
8 9 10
#include "reg.h"
#include "cmd.h"
#include "ps.h"
Kalle Valo's avatar
Kalle Valo committed
11

12
int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
Kalle Valo's avatar
Kalle Valo committed
13 14
			   u8 mgt_rate, u8 mgt_mod)
{
15
	struct acx_fw_gen_frame_rates *rates;
Kalle Valo's avatar
Kalle Valo committed
16 17
	int ret;

18
	wl1251_debug(DEBUG_ACX, "acx frame rates");
Kalle Valo's avatar
Kalle Valo committed
19

20 21 22 23 24
	rates = kzalloc(sizeof(*rates), GFP_KERNEL);
	if (!rates) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
25

26 27 28 29
	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;
Kalle Valo's avatar
Kalle Valo committed
30

31
	ret = wl1251_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES,
32
				   rates, sizeof(*rates));
Kalle Valo's avatar
Kalle Valo committed
33
	if (ret < 0) {
34
		wl1251_error("Failed to set FW rates and modulation");
35
		goto out;
Kalle Valo's avatar
Kalle Valo committed
36 37
	}

38 39 40
out:
	kfree(rates);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
41 42 43
}


44
int wl1251_acx_station_id(struct wl1251 *wl)
Kalle Valo's avatar
Kalle Valo committed
45
{
46
	struct acx_dot11_station_id *mac;
Kalle Valo's avatar
Kalle Valo committed
47 48
	int ret, i;

49
	wl1251_debug(DEBUG_ACX, "acx dot11_station_id");
Kalle Valo's avatar
Kalle Valo committed
50

51 52 53 54 55
	mac = kzalloc(sizeof(*mac), GFP_KERNEL);
	if (!mac) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
56 57

	for (i = 0; i < ETH_ALEN; i++)
58
		mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
Kalle Valo's avatar
Kalle Valo committed
59

60
	ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac));
Kalle Valo's avatar
Kalle Valo committed
61
	if (ret < 0)
62
		goto out;
Kalle Valo's avatar
Kalle Valo committed
63

64 65 66
out:
	kfree(mac);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
67 68
}

69
int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id)
Kalle Valo's avatar
Kalle Valo committed
70
{
71
	struct acx_dot11_default_key *default_key;
Kalle Valo's avatar
Kalle Valo committed
72 73
	int ret;

74
	wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);
Kalle Valo's avatar
Kalle Valo committed
75

76 77 78 79 80
	default_key = kzalloc(sizeof(*default_key), GFP_KERNEL);
	if (!default_key) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
81

82
	default_key->id = key_id;
Kalle Valo's avatar
Kalle Valo committed
83

84
	ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY,
85
				   default_key, sizeof(*default_key));
Kalle Valo's avatar
Kalle Valo committed
86
	if (ret < 0) {
Stefan Weil's avatar
Stefan Weil committed
87
		wl1251_error("Couldn't set default key");
88
		goto out;
Kalle Valo's avatar
Kalle Valo committed
89 90 91 92
	}

	wl->default_key = key_id;

93 94 95
out:
	kfree(default_key);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
96 97
}

98
int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
99
				  u8 listen_interval)
Kalle Valo's avatar
Kalle Valo committed
100
{
101 102
	struct acx_wake_up_condition *wake_up;
	int ret;
Kalle Valo's avatar
Kalle Valo committed
103

104
	wl1251_debug(DEBUG_ACX, "acx wake up conditions");
Kalle Valo's avatar
Kalle Valo committed
105

106 107 108 109 110
	wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
	if (!wake_up) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
111

112
	wake_up->wake_up_event = wake_up_event;
113
	wake_up->listen_interval = listen_interval;
Kalle Valo's avatar
Kalle Valo committed
114

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

out:
	kfree(wake_up);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
125 126
}

127
int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth)
Kalle Valo's avatar
Kalle Valo committed
128
{
129
	struct acx_sleep_auth *auth;
Kalle Valo's avatar
Kalle Valo committed
130 131
	int ret;

132
	wl1251_debug(DEBUG_ACX, "acx sleep auth");
Kalle Valo's avatar
Kalle Valo committed
133

134 135 136 137 138
	auth = kzalloc(sizeof(*auth), GFP_KERNEL);
	if (!auth) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
139

140
	auth->sleep_auth = sleep_auth;
Kalle Valo's avatar
Kalle Valo committed
141

142
	ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
Kalle Valo's avatar
Kalle Valo committed
143 144 145
	if (ret < 0)
		return ret;

146 147 148
out:
	kfree(auth);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
149 150
}

151
int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len)
Kalle Valo's avatar
Kalle Valo committed
152 153 154 155
{
	struct acx_revision *rev;
	int ret;

156
	wl1251_debug(DEBUG_ACX, "acx fw rev");
Kalle Valo's avatar
Kalle Valo committed
157

158 159 160 161 162
	rev = kzalloc(sizeof(*rev), GFP_KERNEL);
	if (!rev) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
163

164
	ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
Kalle Valo's avatar
Kalle Valo committed
165
	if (ret < 0) {
166
		wl1251_warning("ACX_FW_REV interrogate failed");
167
		goto out;
Kalle Valo's avatar
Kalle Valo committed
168 169 170 171 172 173 174 175 176 177 178 179
	}

	/* 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';

180 181 182
out:
	kfree(rev);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
183 184
}

185
int wl1251_acx_tx_power(struct wl1251 *wl, int power)
Kalle Valo's avatar
Kalle Valo committed
186
{
187
	struct acx_current_tx_power *acx;
Kalle Valo's avatar
Kalle Valo committed
188 189
	int ret;

190
	wl1251_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
Kalle Valo's avatar
Kalle Valo committed
191 192 193 194

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

195 196 197 198 199
	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
200

201
	acx->current_tx_power = power * 10;
Kalle Valo's avatar
Kalle Valo committed
202

203
	ret = wl1251_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
Kalle Valo's avatar
Kalle Valo committed
204
	if (ret < 0) {
205
		wl1251_warning("configure of tx power failed: %d", ret);
206
		goto out;
Kalle Valo's avatar
Kalle Valo committed
207 208
	}

209 210 211
out:
	kfree(acx);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
212 213
}

214
int wl1251_acx_feature_cfg(struct wl1251 *wl)
Kalle Valo's avatar
Kalle Valo committed
215
{
216
	struct acx_feature_config *feature;
Kalle Valo's avatar
Kalle Valo committed
217 218
	int ret;

219
	wl1251_debug(DEBUG_ACX, "acx feature cfg");
Kalle Valo's avatar
Kalle Valo committed
220

221 222 223 224 225
	feature = kzalloc(sizeof(*feature), GFP_KERNEL);
	if (!feature) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
226 227

	/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
228 229
	feature->data_flow_options = 0;
	feature->options = 0;
Kalle Valo's avatar
Kalle Valo committed
230

231
	ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
232 233
				   feature, sizeof(*feature));
	if (ret < 0) {
Stefan Weil's avatar
Stefan Weil committed
234
		wl1251_error("Couldn't set HW encryption");
235 236
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
237

238 239
out:
	kfree(feature);
Kalle Valo's avatar
Kalle Valo committed
240 241 242
	return ret;
}

243
int wl1251_acx_mem_map(struct wl1251 *wl, struct acx_header *mem_map,
244
		       size_t len)
Kalle Valo's avatar
Kalle Valo committed
245 246 247
{
	int ret;

248
	wl1251_debug(DEBUG_ACX, "acx mem map");
Kalle Valo's avatar
Kalle Valo committed
249

250
	ret = wl1251_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
Kalle Valo's avatar
Kalle Valo committed
251 252 253 254 255 256
	if (ret < 0)
		return ret;

	return 0;
}

257
int wl1251_acx_data_path_params(struct wl1251 *wl,
258
				struct acx_data_path_params_resp *resp)
Kalle Valo's avatar
Kalle Valo committed
259
{
260
	struct acx_data_path_params *params;
Kalle Valo's avatar
Kalle Valo committed
261 262
	int ret;

263
	wl1251_debug(DEBUG_ACX, "acx data path params");
Kalle Valo's avatar
Kalle Valo committed
264

265 266 267 268 269
	params = kzalloc(sizeof(*params), GFP_KERNEL);
	if (!params) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
270

271 272
	params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
	params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
Kalle Valo's avatar
Kalle Valo committed
273

274 275
	params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM;
	params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM;
Kalle Valo's avatar
Kalle Valo committed
276

277
	params->tx_complete_threshold = 1;
Kalle Valo's avatar
Kalle Valo committed
278

279
	params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE;
Kalle Valo's avatar
Kalle Valo committed
280

281
	params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT;
Kalle Valo's avatar
Kalle Valo committed
282

283
	ret = wl1251_cmd_configure(wl, ACX_DATA_PATH_PARAMS,
284
				   params, sizeof(*params));
Kalle Valo's avatar
Kalle Valo committed
285
	if (ret < 0)
286
		goto out;
Kalle Valo's avatar
Kalle Valo committed
287

288
	/* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */
289
	ret = wl1251_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS,
290
				     resp, sizeof(*resp));
Kalle Valo's avatar
Kalle Valo committed
291 292

	if (ret < 0) {
293
		wl1251_warning("failed to read data path parameters: %d", ret);
294 295
		goto out;
	} else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) {
296
		wl1251_warning("data path parameter acx status failed");
297 298
		ret = -EIO;
		goto out;
Kalle Valo's avatar
Kalle Valo committed
299 300
	}

301 302 303
out:
	kfree(params);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
304 305
}

306
int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time)
Kalle Valo's avatar
Kalle Valo committed
307
{
308
	struct acx_rx_msdu_lifetime *acx;
Kalle Valo's avatar
Kalle Valo committed
309 310
	int ret;

311
	wl1251_debug(DEBUG_ACX, "acx rx msdu life time");
Kalle Valo's avatar
Kalle Valo committed
312

313 314 315 316 317
	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
318

319
	acx->lifetime = life_time;
320
	ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
321
				   acx, sizeof(*acx));
Kalle Valo's avatar
Kalle Valo committed
322
	if (ret < 0) {
323
		wl1251_warning("failed to set rx msdu life time: %d", ret);
324
		goto out;
Kalle Valo's avatar
Kalle Valo committed
325 326
	}

327 328 329
out:
	kfree(acx);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
330 331
}

332
int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter)
Kalle Valo's avatar
Kalle Valo committed
333
{
334
	struct acx_rx_config *rx_config;
Kalle Valo's avatar
Kalle Valo committed
335 336
	int ret;

337
	wl1251_debug(DEBUG_ACX, "acx rx config");
Kalle Valo's avatar
Kalle Valo committed
338

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;
Kalle Valo's avatar
Kalle Valo committed
347

348
	ret = wl1251_cmd_configure(wl, ACX_RX_CFG,
349
				   rx_config, sizeof(*rx_config));
Kalle Valo's avatar
Kalle Valo committed
350
	if (ret < 0) {
351
		wl1251_warning("failed to set rx config: %d", ret);
352
		goto out;
Kalle Valo's avatar
Kalle Valo committed
353 354
	}

355 356 357
out:
	kfree(rx_config);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
358 359
}

360
int wl1251_acx_pd_threshold(struct wl1251 *wl)
Kalle Valo's avatar
Kalle Valo committed
361
{
362
	struct acx_packet_detection *pd;
Kalle Valo's avatar
Kalle Valo committed
363 364
	int ret;

365
	wl1251_debug(DEBUG_ACX, "acx data pd threshold");
Kalle Valo's avatar
Kalle Valo committed
366

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

Kalle Valo's avatar
Kalle Valo committed
373 374
	/* FIXME: threshold value not set */

375
	ret = wl1251_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
Kalle Valo's avatar
Kalle Valo committed
376
	if (ret < 0) {
377
		wl1251_warning("failed to set pd threshold: %d", ret);
378
		goto out;
Kalle Valo's avatar
Kalle Valo committed
379 380
	}

381 382
out:
	kfree(pd);
383
	return ret;
Kalle Valo's avatar
Kalle Valo committed
384 385
}

386
int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time)
Kalle Valo's avatar
Kalle Valo committed
387
{
388
	struct acx_slot *slot;
Kalle Valo's avatar
Kalle Valo committed
389 390
	int ret;

391
	wl1251_debug(DEBUG_ACX, "acx slot");
Kalle Valo's avatar
Kalle Valo committed
392

393 394 395 396 397
	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
	if (!slot) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
398

399 400
	slot->wone_index = STATION_WONE_INDEX;
	slot->slot_time = slot_time;
Kalle Valo's avatar
Kalle Valo committed
401

402
	ret = wl1251_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
Kalle Valo's avatar
Kalle Valo committed
403
	if (ret < 0) {
404
		wl1251_warning("failed to set slot time: %d", ret);
405
		goto out;
Kalle Valo's avatar
Kalle Valo committed
406 407
	}

408 409 410
out:
	kfree(slot);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
411 412
}

413
int wl1251_acx_group_address_tbl(struct wl1251 *wl)
Kalle Valo's avatar
Kalle Valo committed
414
{
415
	struct acx_dot11_grp_addr_tbl *acx;
Kalle Valo's avatar
Kalle Valo committed
416 417
	int ret;

418
	wl1251_debug(DEBUG_ACX, "acx group address tbl");
Kalle Valo's avatar
Kalle Valo committed
419

420 421 422 423 424
	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
425

426 427 428 429
	/* MAC filtering */
	acx->enabled = 0;
	acx->num_groups = 0;
	memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
Kalle Valo's avatar
Kalle Valo committed
430

431
	ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
432
				   acx, sizeof(*acx));
Kalle Valo's avatar
Kalle Valo committed
433
	if (ret < 0) {
434
		wl1251_warning("failed to set group addr table: %d", ret);
435
		goto out;
Kalle Valo's avatar
Kalle Valo committed
436 437
	}

438 439 440
out:
	kfree(acx);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
441 442
}

443
int wl1251_acx_service_period_timeout(struct wl1251 *wl)
Kalle Valo's avatar
Kalle Valo committed
444
{
445
	struct acx_rx_timeout *rx_timeout;
Kalle Valo's avatar
Kalle Valo committed
446 447
	int ret;

448 449 450 451 452
	rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
	if (!rx_timeout) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
453

454
	wl1251_debug(DEBUG_ACX, "acx service period timeout");
Kalle Valo's avatar
Kalle Valo committed
455

456 457
	rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
	rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
Kalle Valo's avatar
Kalle Valo committed
458

459
	ret = wl1251_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
460
				   rx_timeout, sizeof(*rx_timeout));
Kalle Valo's avatar
Kalle Valo committed
461
	if (ret < 0) {
462
		wl1251_warning("failed to set service period timeout: %d",
Kalle Valo's avatar
Kalle Valo committed
463
			       ret);
464
		goto out;
Kalle Valo's avatar
Kalle Valo committed
465 466
	}

467 468 469
out:
	kfree(rx_timeout);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
470 471
}

472
int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold)
Kalle Valo's avatar
Kalle Valo committed
473
{
474
	struct acx_rts_threshold *rts;
Kalle Valo's avatar
Kalle Valo committed
475 476
	int ret;

477
	wl1251_debug(DEBUG_ACX, "acx rts threshold");
Kalle Valo's avatar
Kalle Valo committed
478

479 480 481 482 483
	rts = kzalloc(sizeof(*rts), GFP_KERNEL);
	if (!rts) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
484

485
	rts->threshold = rts_threshold;
Kalle Valo's avatar
Kalle Valo committed
486

487
	ret = wl1251_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
Kalle Valo's avatar
Kalle Valo committed
488
	if (ret < 0) {
489
		wl1251_warning("failed to set rts threshold: %d", ret);
490
		goto out;
Kalle Valo's avatar
Kalle Valo committed
491 492
	}

493 494 495
out:
	kfree(rts);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
496 497
}

498
int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter)
Kalle Valo's avatar
Kalle Valo committed
499
{
500
	struct acx_beacon_filter_option *beacon_filter;
Kalle Valo's avatar
Kalle Valo committed
501 502
	int ret;

503
	wl1251_debug(DEBUG_ACX, "acx beacon filter opt");
Kalle Valo's avatar
Kalle Valo committed
504

505 506 507 508 509
	beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
	if (!beacon_filter) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
510

511
	beacon_filter->enable = enable_filter;
512
	beacon_filter->max_num_beacons = 0;
Kalle Valo's avatar
Kalle Valo committed
513

514
	ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
515
				   beacon_filter, sizeof(*beacon_filter));
Kalle Valo's avatar
Kalle Valo committed
516
	if (ret < 0) {
517
		wl1251_warning("failed to set beacon filter opt: %d", ret);
518
		goto out;
Kalle Valo's avatar
Kalle Valo committed
519 520
	}

521 522 523
out:
	kfree(beacon_filter);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
524 525
}

526
int wl1251_acx_beacon_filter_table(struct wl1251 *wl)
Kalle Valo's avatar
Kalle Valo committed
527
{
528
	struct acx_beacon_filter_ie_table *ie_table;
529
	int idx = 0;
Kalle Valo's avatar
Kalle Valo committed
530 531
	int ret;

532
	wl1251_debug(DEBUG_ACX, "acx beacon filter table");
Kalle Valo's avatar
Kalle Valo committed
533

534 535 536 537 538
	ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
	if (!ie_table) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
539

540 541 542 543
	/* configure default beacon pass-through rules */
	ie_table->num_ie = 1;
	ie_table->table[idx++] = BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN;
	ie_table->table[idx++] = BEACON_RULE_PASS_ON_APPEARANCE;
Kalle Valo's avatar
Kalle Valo committed
544

545
	ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
546
				   ie_table, sizeof(*ie_table));
Kalle Valo's avatar
Kalle Valo committed
547
	if (ret < 0) {
548
		wl1251_warning("failed to set beacon filter table: %d", ret);
549
		goto out;
Kalle Valo's avatar
Kalle Valo committed
550 551
	}

552 553 554
out:
	kfree(ie_table);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
555 556
}

557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
int wl1251_acx_conn_monit_params(struct wl1251 *wl)
{
	struct acx_conn_monit_params *acx;
	int ret;

	wl1251_debug(DEBUG_ACX, "acx connection monitor parameters");

	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}

	acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD;
	acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT;

	ret = wl1251_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
				   acx, sizeof(*acx));
	if (ret < 0) {
		wl1251_warning("failed to set connection monitor "
			       "parameters: %d", ret);
		goto out;
	}

out:
	kfree(acx);
	return ret;
}

586
int wl1251_acx_sg_enable(struct wl1251 *wl)
Kalle Valo's avatar
Kalle Valo committed
587
{
588
	struct acx_bt_wlan_coex *pta;
Kalle Valo's avatar
Kalle Valo committed
589 590
	int ret;

591
	wl1251_debug(DEBUG_ACX, "acx sg enable");
Kalle Valo's avatar
Kalle Valo committed
592

593 594 595 596 597
	pta = kzalloc(sizeof(*pta), GFP_KERNEL);
	if (!pta) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
598

599
	pta->enable = SG_ENABLE;
Kalle Valo's avatar
Kalle Valo committed
600

601
	ret = wl1251_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
Kalle Valo's avatar
Kalle Valo committed
602
	if (ret < 0) {
603
		wl1251_warning("failed to set softgemini enable: %d", ret);
604
		goto out;
Kalle Valo's avatar
Kalle Valo committed
605 606
	}

607 608 609
out:
	kfree(pta);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
610 611
}

612
int wl1251_acx_sg_cfg(struct wl1251 *wl)
Kalle Valo's avatar
Kalle Valo committed
613
{
614
	struct acx_bt_wlan_coex_param *param;
Kalle Valo's avatar
Kalle Valo committed
615 616
	int ret;

617
	wl1251_debug(DEBUG_ACX, "acx sg cfg");
Kalle Valo's avatar
Kalle Valo committed
618

619 620 621 622 623 624
	param = kzalloc(sizeof(*param), GFP_KERNEL);
	if (!param) {
		ret = -ENOMEM;
		goto out;
	}

Kalle Valo's avatar
Kalle Valo committed
625
	/* BT-WLAN coext parameters */
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
	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;

655
	ret = wl1251_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
Kalle Valo's avatar
Kalle Valo committed
656
	if (ret < 0) {
657
		wl1251_warning("failed to set sg config: %d", ret);
658
		goto out;
Kalle Valo's avatar
Kalle Valo committed
659 660
	}

661 662 663
out:
	kfree(param);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
664 665
}

666
int wl1251_acx_cca_threshold(struct wl1251 *wl)
Kalle Valo's avatar
Kalle Valo committed
667
{
668
	struct acx_energy_detection *detection;
Kalle Valo's avatar
Kalle Valo committed
669 670
	int ret;

671
	wl1251_debug(DEBUG_ACX, "acx cca threshold");
Kalle Valo's avatar
Kalle Valo committed
672

673 674 675 676 677
	detection = kzalloc(sizeof(*detection), GFP_KERNEL);
	if (!detection) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
678

679 680
	detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
	detection->tx_energy_detection = 0;
Kalle Valo's avatar
Kalle Valo committed
681

682
	ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD,
683
				   detection, sizeof(*detection));
Kalle Valo's avatar
Kalle Valo committed
684
	if (ret < 0) {
685
		wl1251_warning("failed to set cca threshold: %d", ret);
Kalle Valo's avatar
Kalle Valo committed
686 687 688
		return ret;
	}

689 690 691
out:
	kfree(detection);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
692 693
}

694
int wl1251_acx_bcn_dtim_options(struct wl1251 *wl)
Kalle Valo's avatar
Kalle Valo committed
695
{
696
	struct acx_beacon_broadcast *bb;
Kalle Valo's avatar
Kalle Valo committed
697 698
	int ret;

699
	wl1251_debug(DEBUG_ACX, "acx bcn dtim options");
Kalle Valo's avatar
Kalle Valo committed
700

701 702 703 704 705
	bb = kzalloc(sizeof(*bb), GFP_KERNEL);
	if (!bb) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
706

707 708 709 710
	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;
Kalle Valo's avatar
Kalle Valo committed
711

712
	ret = wl1251_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
Kalle Valo's avatar
Kalle Valo committed
713
	if (ret < 0) {
714
		wl1251_warning("failed to set rx config: %d", ret);
715
		goto out;
Kalle Valo's avatar
Kalle Valo committed
716 717
	}

718 719 720
out:
	kfree(bb);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
721 722
}

723
int wl1251_acx_aid(struct wl1251 *wl, u16 aid)
Kalle Valo's avatar
Kalle Valo committed
724
{
725
	struct acx_aid *acx_aid;
Kalle Valo's avatar
Kalle Valo committed
726 727
	int ret;

728
	wl1251_debug(DEBUG_ACX, "acx aid");
Kalle Valo's avatar
Kalle Valo committed
729

730 731 732 733 734
	acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
	if (!acx_aid) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
735

736
	acx_aid->aid = aid;
Kalle Valo's avatar
Kalle Valo committed
737

738
	ret = wl1251_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
Kalle Valo's avatar
Kalle Valo committed
739
	if (ret < 0) {
740
		wl1251_warning("failed to set aid: %d", ret);
741
		goto out;
Kalle Valo's avatar
Kalle Valo committed
742 743
	}

744 745 746
out:
	kfree(acx_aid);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
747 748
}

749
int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask)
Kalle Valo's avatar
Kalle Valo committed
750
{
751
	struct acx_event_mask *mask;
Kalle Valo's avatar
Kalle Valo committed
752 753
	int ret;

754
	wl1251_debug(DEBUG_ACX, "acx event mbox mask");
Kalle Valo's avatar
Kalle Valo committed
755

756 757 758 759 760
	mask = kzalloc(sizeof(*mask), GFP_KERNEL);
	if (!mask) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
761 762

	/* high event mask is unused */
763
	mask->high_event_mask = 0xffffffff;
Kalle Valo's avatar
Kalle Valo committed
764

765
	mask->event_mask = event_mask;
Kalle Valo's avatar
Kalle Valo committed
766

767
	ret = wl1251_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
768
				   mask, sizeof(*mask));
Kalle Valo's avatar
Kalle Valo committed
769
	if (ret < 0) {
770
		wl1251_warning("failed to set acx_event_mbox_mask: %d", ret);
771
		goto out;
Kalle Valo's avatar
Kalle Valo committed
772 773
	}

774 775 776
out:
	kfree(mask);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
777 778
}

779
int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble)
Kalle Valo's avatar
Kalle Valo committed
780
{
781
	struct acx_preamble *acx;
Kalle Valo's avatar
Kalle Valo committed
782 783
	int ret;

784
	wl1251_debug(DEBUG_ACX, "acx_set_preamble");
Kalle Valo's avatar
Kalle Valo committed
785

786 787 788 789 790
	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}
Kalle Valo's avatar
Kalle Valo committed
791

792 793
	acx->preamble = preamble;

794
	ret = wl1251_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
Kalle Valo's avatar
Kalle Valo committed
795
	if (ret < 0) {
796
		wl1251_warning("Setting of preamble failed: %d", ret);
797
		goto out;
Kalle Valo's avatar
Kalle Valo committed
798
	}
799 800 801 802

out:
	kfree(acx);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
803 804
}

805
int wl1251_acx_cts_protect(struct wl1251 *wl,
Kalle Valo's avatar
Kalle Valo committed
806 807
			   enum acx_ctsprotect_type ctsprotect)
{
808
	struct acx_ctsprotect *acx;
Kalle Valo's avatar
Kalle Valo committed
809 810
	int ret;

811
	wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect");
Kalle Valo's avatar
Kalle Valo committed
812

813 814 815 816 817 818 819
	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}

	acx->ctsprotect = ctsprotect;
Kalle Valo's avatar
Kalle Valo committed
820

821
	ret = wl1251_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
Kalle Valo's avatar
Kalle Valo committed
822
	if (ret < 0) {
823
		wl1251_warning("Setting of ctsprotect failed: %d", ret);
824
		goto out;
Kalle Valo's avatar
Kalle Valo committed
825
	}
826 827 828 829

out:
	kfree(acx);
	return ret;
Kalle Valo's avatar
Kalle Valo committed
830 831
}

832
int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime)
Kalle Valo's avatar
Kalle Valo committed
833
{
834
	struct acx_tsf_info *tsf_info;
Kalle Valo's avatar
Kalle Valo committed
835 836
	int ret;

837 838
	tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL);
	if (!tsf_info) {
Kalle Valo's avatar
Kalle Valo committed
839 840 841 842
		ret = -ENOMEM;
		goto out;
	}

843
	ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO,
844
				     tsf_info, sizeof(*tsf_info));
Kalle Valo's avatar
Kalle Valo committed
845
	if (ret < 0) {
846
		wl1251_warning("ACX_FW_REV interrogate failed");
Kalle Valo's avatar
Kalle Valo committed
847 848 849
		goto out;
	}

850 851
	*mactime = tsf_info->current_tsf_lsb |
		(tsf_info->current_tsf_msb << 31);
Kalle Valo's avatar
Kalle Valo committed
852 853

out:
854
	kfree(tsf_info);
Kalle Valo's avatar
Kalle Valo committed
855 856
	return ret;
}
857

858
int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats)
859 860 861
{
	int ret;

862
	wl1251_debug(DEBUG_ACX, "acx statistics");
863

864
	ret = wl1251_cmd_interrogate(wl, ACX_STATISTICS, stats,
865 866
				     sizeof(*stats));
	if (ret < 0) {
867
		wl1251_warning("acx statistics failed: %d", ret);
868 869 870 871 872
		return -ENOMEM;
	}

	return 0;
}
Kalle Valo's avatar
Kalle Valo committed
873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951

int wl1251_acx_rate_policies(struct wl1251 *wl)
{
	struct acx_rate_policy *acx;
	int ret = 0;

	wl1251_debug(DEBUG_ACX, "acx rate policies");

	acx = kzalloc(sizeof(*acx), GFP_KERNEL);

	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}

	/* configure one default (one-size-fits-all) rate class */
	acx->rate_class_cnt = 1;
	acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
	acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
	acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
	acx->rate_class[0].aflags = 0;

	ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
	if (ret < 0) {
		wl1251_warning("Setting of rate policies failed: %d", ret);
		goto out;
	}

out:
	kfree(acx);
	return ret;
}

int wl1251_acx_mem_cfg(struct wl1251 *wl)
{
	struct wl1251_acx_config_memory *mem_conf;
	int ret, i;

	wl1251_debug(DEBUG_ACX, "acx mem cfg");

	mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
	if (!mem_conf) {
		ret = -ENOMEM;
		goto out;
	}

	/* memory config */
	mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
	mem_conf->mem_config.rx_mem_block_num = 35;
	mem_conf->mem_config.tx_min_mem_block_num = 64;
	mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES;
	mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING;
	mem_conf->mem_config.num_ssid_profiles = 1;
	mem_conf->mem_config.debug_buffer_size =
		cpu_to_le16(TRACE_BUFFER_MAX_SIZE);

	/* RX queue config */
	mem_conf->rx_queue_config.dma_address = 0;
	mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF;
	mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY;
	mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE;

	/* TX queue config */
	for (i = 0; i < MAX_TX_QUEUES; i++) {
		mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF;
		mem_conf->tx_queue_config[i].attributes = i;
	}

	ret = wl1251_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
				   sizeof(*mem_conf));
	if (ret < 0) {
		wl1251_warning("wl1251 mem config failed: %d", ret);
		goto out;
	}

out:
	kfree(mem_conf);
	return ret;
}
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979

int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim)
{
	struct wl1251_acx_wr_tbtt_and_dtim *acx;
	int ret;

	wl1251_debug(DEBUG_ACX, "acx tbtt and dtim");

	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}

	acx->tbtt = tbtt;
	acx->dtim = dtim;

	ret = wl1251_cmd_configure(wl, ACX_WR_TBTT_AND_DTIM,
				   acx, sizeof(*acx));
	if (ret < 0) {
		wl1251_warning("failed to set tbtt and dtim: %d", ret);
		goto out;
	}

out:
	kfree(acx);
	return ret;
}
980

981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
			  u8 max_consecutive)
{
	struct wl1251_acx_bet_enable *acx;
	int ret;

	wl1251_debug(DEBUG_ACX, "acx bet enable");

	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}

	acx->enable = mode;
	acx->max_consecutive = max_consecutive;

	ret = wl1251_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
	if (ret < 0) {
		wl1251_warning("wl1251 acx bet enable failed: %d", ret);
		goto out;
	}

out:
	kfree(acx);
	return ret;
}

1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
		      u8 aifs, u16 txop)
{
	struct wl1251_acx_ac_cfg *acx;
	int ret = 0;

	wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d "
		     "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop);

	acx = kzalloc(sizeof(*acx), GFP_KERNEL);

	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}

	acx->ac = ac;
	acx->cw_min = cw_min;
	acx->cw_max = cw_max;
	acx->aifsn = aifs;
	acx->txop_limit = txop;

	ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
	if (ret < 0) {
		wl1251_warning("acx ac cfg failed: %d", ret);
		goto out;
	}

out:
	kfree(acx);
	return ret;
}
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076

int 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)
{
	struct wl1251_acx_tid_cfg *acx;
	int ret = 0;

	wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d "
		     "ps_scheme %d ack_policy %d", queue, type, tsid,
		     ps_scheme, ack_policy);

	acx = kzalloc(sizeof(*acx), GFP_KERNEL);

	if (!acx) {
		ret = -ENOMEM;
		goto out;
	}

	acx->queue = queue;
	acx->type = type;
	acx->tsid = tsid;
	acx->ps_scheme = ps_scheme;
	acx->ack_policy = ack_policy;

	ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
	if (ret < 0) {
		wl1251_warning("acx tid cfg failed: %d", ret);
		goto out;
	}

out:
	kfree(acx);
	return ret;
}