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