18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include "acx.h"
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/module.h>
58c2ecf20Sopenharmony_ci#include <linux/slab.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "wl1251.h"
88c2ecf20Sopenharmony_ci#include "reg.h"
98c2ecf20Sopenharmony_ci#include "cmd.h"
108c2ecf20Sopenharmony_ci#include "ps.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ciint wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
138c2ecf20Sopenharmony_ci			   u8 mgt_rate, u8 mgt_mod)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	struct acx_fw_gen_frame_rates *rates;
168c2ecf20Sopenharmony_ci	int ret;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx frame rates");
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	rates = kzalloc(sizeof(*rates), GFP_KERNEL);
218c2ecf20Sopenharmony_ci	if (!rates)
228c2ecf20Sopenharmony_ci		return -ENOMEM;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	rates->tx_ctrl_frame_rate = ctrl_rate;
258c2ecf20Sopenharmony_ci	rates->tx_ctrl_frame_mod = ctrl_mod;
268c2ecf20Sopenharmony_ci	rates->tx_mgt_frame_rate = mgt_rate;
278c2ecf20Sopenharmony_ci	rates->tx_mgt_frame_mod = mgt_mod;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES,
308c2ecf20Sopenharmony_ci				   rates, sizeof(*rates));
318c2ecf20Sopenharmony_ci	if (ret < 0) {
328c2ecf20Sopenharmony_ci		wl1251_error("Failed to set FW rates and modulation");
338c2ecf20Sopenharmony_ci		goto out;
348c2ecf20Sopenharmony_ci	}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ciout:
378c2ecf20Sopenharmony_ci	kfree(rates);
388c2ecf20Sopenharmony_ci	return ret;
398c2ecf20Sopenharmony_ci}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ciint wl1251_acx_station_id(struct wl1251 *wl)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	struct acx_dot11_station_id *mac;
458c2ecf20Sopenharmony_ci	int ret, i;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx dot11_station_id");
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	mac = kzalloc(sizeof(*mac), GFP_KERNEL);
508c2ecf20Sopenharmony_ci	if (!mac)
518c2ecf20Sopenharmony_ci		return -ENOMEM;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	for (i = 0; i < ETH_ALEN; i++)
548c2ecf20Sopenharmony_ci		mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac));
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	kfree(mac);
598c2ecf20Sopenharmony_ci	return ret;
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ciint wl1251_acx_default_key(struct wl1251 *wl, u8 key_id)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	struct acx_dot11_default_key *default_key;
658c2ecf20Sopenharmony_ci	int ret;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	default_key = kzalloc(sizeof(*default_key), GFP_KERNEL);
708c2ecf20Sopenharmony_ci	if (!default_key)
718c2ecf20Sopenharmony_ci		return -ENOMEM;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	default_key->id = key_id;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY,
768c2ecf20Sopenharmony_ci				   default_key, sizeof(*default_key));
778c2ecf20Sopenharmony_ci	if (ret < 0) {
788c2ecf20Sopenharmony_ci		wl1251_error("Couldn't set default key");
798c2ecf20Sopenharmony_ci		goto out;
808c2ecf20Sopenharmony_ci	}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	wl->default_key = key_id;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ciout:
858c2ecf20Sopenharmony_ci	kfree(default_key);
868c2ecf20Sopenharmony_ci	return ret;
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ciint wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
908c2ecf20Sopenharmony_ci				  u8 listen_interval)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	struct acx_wake_up_condition *wake_up;
938c2ecf20Sopenharmony_ci	int ret;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx wake up conditions");
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
988c2ecf20Sopenharmony_ci	if (!wake_up)
998c2ecf20Sopenharmony_ci		return -ENOMEM;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	wake_up->wake_up_event = wake_up_event;
1028c2ecf20Sopenharmony_ci	wake_up->listen_interval = listen_interval;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
1058c2ecf20Sopenharmony_ci				   wake_up, sizeof(*wake_up));
1068c2ecf20Sopenharmony_ci	if (ret < 0) {
1078c2ecf20Sopenharmony_ci		wl1251_warning("could not set wake up conditions: %d", ret);
1088c2ecf20Sopenharmony_ci		goto out;
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ciout:
1128c2ecf20Sopenharmony_ci	kfree(wake_up);
1138c2ecf20Sopenharmony_ci	return ret;
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ciint wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	struct acx_sleep_auth *auth;
1198c2ecf20Sopenharmony_ci	int ret;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx sleep auth");
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	auth = kzalloc(sizeof(*auth), GFP_KERNEL);
1248c2ecf20Sopenharmony_ci	if (!auth)
1258c2ecf20Sopenharmony_ci		return -ENOMEM;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	auth->sleep_auth = sleep_auth;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	kfree(auth);
1328c2ecf20Sopenharmony_ci	return ret;
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ciint wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	struct acx_revision *rev;
1388c2ecf20Sopenharmony_ci	int ret;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx fw rev");
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	rev = kzalloc(sizeof(*rev), GFP_KERNEL);
1438c2ecf20Sopenharmony_ci	if (!rev)
1448c2ecf20Sopenharmony_ci		return -ENOMEM;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
1478c2ecf20Sopenharmony_ci	if (ret < 0) {
1488c2ecf20Sopenharmony_ci		wl1251_warning("ACX_FW_REV interrogate failed");
1498c2ecf20Sopenharmony_ci		goto out;
1508c2ecf20Sopenharmony_ci	}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	/* be careful with the buffer sizes */
1538c2ecf20Sopenharmony_ci	strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	/*
1568c2ecf20Sopenharmony_ci	 * if the firmware version string is exactly
1578c2ecf20Sopenharmony_ci	 * sizeof(rev->fw_version) long or fw_len is less than
1588c2ecf20Sopenharmony_ci	 * sizeof(rev->fw_version) it won't be null terminated
1598c2ecf20Sopenharmony_ci	 */
1608c2ecf20Sopenharmony_ci	buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ciout:
1638c2ecf20Sopenharmony_ci	kfree(rev);
1648c2ecf20Sopenharmony_ci	return ret;
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ciint wl1251_acx_tx_power(struct wl1251 *wl, int power)
1688c2ecf20Sopenharmony_ci{
1698c2ecf20Sopenharmony_ci	struct acx_current_tx_power *acx;
1708c2ecf20Sopenharmony_ci	int ret;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	if (power < 0 || power > 25)
1758c2ecf20Sopenharmony_ci		return -EINVAL;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1788c2ecf20Sopenharmony_ci	if (!acx)
1798c2ecf20Sopenharmony_ci		return -ENOMEM;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	acx->current_tx_power = power * 10;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
1848c2ecf20Sopenharmony_ci	if (ret < 0) {
1858c2ecf20Sopenharmony_ci		wl1251_warning("configure of tx power failed: %d", ret);
1868c2ecf20Sopenharmony_ci		goto out;
1878c2ecf20Sopenharmony_ci	}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ciout:
1908c2ecf20Sopenharmony_ci	kfree(acx);
1918c2ecf20Sopenharmony_ci	return ret;
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ciint wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	struct acx_feature_config *feature;
1978c2ecf20Sopenharmony_ci	int ret;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx feature cfg");
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	feature = kzalloc(sizeof(*feature), GFP_KERNEL);
2028c2ecf20Sopenharmony_ci	if (!feature)
2038c2ecf20Sopenharmony_ci		return -ENOMEM;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE can be set */
2068c2ecf20Sopenharmony_ci	feature->data_flow_options = data_flow_options;
2078c2ecf20Sopenharmony_ci	feature->options = 0;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
2108c2ecf20Sopenharmony_ci				   feature, sizeof(*feature));
2118c2ecf20Sopenharmony_ci	if (ret < 0) {
2128c2ecf20Sopenharmony_ci		wl1251_error("Couldn't set HW encryption");
2138c2ecf20Sopenharmony_ci		goto out;
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ciout:
2178c2ecf20Sopenharmony_ci	kfree(feature);
2188c2ecf20Sopenharmony_ci	return ret;
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ciint wl1251_acx_mem_map(struct wl1251 *wl, struct acx_header *mem_map,
2228c2ecf20Sopenharmony_ci		       size_t len)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	int ret;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx mem map");
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	ret = wl1251_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
2298c2ecf20Sopenharmony_ci	if (ret < 0)
2308c2ecf20Sopenharmony_ci		return ret;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	return 0;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ciint wl1251_acx_data_path_params(struct wl1251 *wl,
2368c2ecf20Sopenharmony_ci				struct acx_data_path_params_resp *resp)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	struct acx_data_path_params *params;
2398c2ecf20Sopenharmony_ci	int ret;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx data path params");
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	params = kzalloc(sizeof(*params), GFP_KERNEL);
2448c2ecf20Sopenharmony_ci	if (!params)
2458c2ecf20Sopenharmony_ci		return -ENOMEM;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
2488c2ecf20Sopenharmony_ci	params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM;
2518c2ecf20Sopenharmony_ci	params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	params->tx_complete_threshold = 1;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_DATA_PATH_PARAMS,
2608c2ecf20Sopenharmony_ci				   params, sizeof(*params));
2618c2ecf20Sopenharmony_ci	if (ret < 0)
2628c2ecf20Sopenharmony_ci		goto out;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	/* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */
2658c2ecf20Sopenharmony_ci	ret = wl1251_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS,
2668c2ecf20Sopenharmony_ci				     resp, sizeof(*resp));
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	if (ret < 0) {
2698c2ecf20Sopenharmony_ci		wl1251_warning("failed to read data path parameters: %d", ret);
2708c2ecf20Sopenharmony_ci		goto out;
2718c2ecf20Sopenharmony_ci	} else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) {
2728c2ecf20Sopenharmony_ci		wl1251_warning("data path parameter acx status failed");
2738c2ecf20Sopenharmony_ci		ret = -EIO;
2748c2ecf20Sopenharmony_ci		goto out;
2758c2ecf20Sopenharmony_ci	}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ciout:
2788c2ecf20Sopenharmony_ci	kfree(params);
2798c2ecf20Sopenharmony_ci	return ret;
2808c2ecf20Sopenharmony_ci}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ciint wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time)
2838c2ecf20Sopenharmony_ci{
2848c2ecf20Sopenharmony_ci	struct acx_rx_msdu_lifetime *acx;
2858c2ecf20Sopenharmony_ci	int ret;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx rx msdu life time");
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
2908c2ecf20Sopenharmony_ci	if (!acx)
2918c2ecf20Sopenharmony_ci		return -ENOMEM;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	acx->lifetime = life_time;
2948c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
2958c2ecf20Sopenharmony_ci				   acx, sizeof(*acx));
2968c2ecf20Sopenharmony_ci	if (ret < 0) {
2978c2ecf20Sopenharmony_ci		wl1251_warning("failed to set rx msdu life time: %d", ret);
2988c2ecf20Sopenharmony_ci		goto out;
2998c2ecf20Sopenharmony_ci	}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ciout:
3028c2ecf20Sopenharmony_ci	kfree(acx);
3038c2ecf20Sopenharmony_ci	return ret;
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ciint wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter)
3078c2ecf20Sopenharmony_ci{
3088c2ecf20Sopenharmony_ci	struct acx_rx_config *rx_config;
3098c2ecf20Sopenharmony_ci	int ret;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx rx config");
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
3148c2ecf20Sopenharmony_ci	if (!rx_config)
3158c2ecf20Sopenharmony_ci		return -ENOMEM;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	rx_config->config_options = config;
3188c2ecf20Sopenharmony_ci	rx_config->filter_options = filter;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_RX_CFG,
3218c2ecf20Sopenharmony_ci				   rx_config, sizeof(*rx_config));
3228c2ecf20Sopenharmony_ci	if (ret < 0) {
3238c2ecf20Sopenharmony_ci		wl1251_warning("failed to set rx config: %d", ret);
3248c2ecf20Sopenharmony_ci		goto out;
3258c2ecf20Sopenharmony_ci	}
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ciout:
3288c2ecf20Sopenharmony_ci	kfree(rx_config);
3298c2ecf20Sopenharmony_ci	return ret;
3308c2ecf20Sopenharmony_ci}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ciint wl1251_acx_pd_threshold(struct wl1251 *wl)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	struct acx_packet_detection *pd;
3358c2ecf20Sopenharmony_ci	int ret;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx data pd threshold");
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
3408c2ecf20Sopenharmony_ci	if (!pd)
3418c2ecf20Sopenharmony_ci		return -ENOMEM;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	/* FIXME: threshold value not set */
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
3468c2ecf20Sopenharmony_ci	if (ret < 0) {
3478c2ecf20Sopenharmony_ci		wl1251_warning("failed to set pd threshold: %d", ret);
3488c2ecf20Sopenharmony_ci		goto out;
3498c2ecf20Sopenharmony_ci	}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ciout:
3528c2ecf20Sopenharmony_ci	kfree(pd);
3538c2ecf20Sopenharmony_ci	return ret;
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ciint wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	struct acx_slot *slot;
3598c2ecf20Sopenharmony_ci	int ret;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx slot");
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
3648c2ecf20Sopenharmony_ci	if (!slot)
3658c2ecf20Sopenharmony_ci		return -ENOMEM;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	slot->wone_index = STATION_WONE_INDEX;
3688c2ecf20Sopenharmony_ci	slot->slot_time = slot_time;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
3718c2ecf20Sopenharmony_ci	if (ret < 0) {
3728c2ecf20Sopenharmony_ci		wl1251_warning("failed to set slot time: %d", ret);
3738c2ecf20Sopenharmony_ci		goto out;
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ciout:
3778c2ecf20Sopenharmony_ci	kfree(slot);
3788c2ecf20Sopenharmony_ci	return ret;
3798c2ecf20Sopenharmony_ci}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ciint wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
3828c2ecf20Sopenharmony_ci				 void *mc_list, u32 mc_list_len)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	struct acx_dot11_grp_addr_tbl *acx;
3858c2ecf20Sopenharmony_ci	int ret;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx group address tbl");
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
3908c2ecf20Sopenharmony_ci	if (!acx)
3918c2ecf20Sopenharmony_ci		return -ENOMEM;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	/* MAC filtering */
3948c2ecf20Sopenharmony_ci	acx->enabled = enable;
3958c2ecf20Sopenharmony_ci	acx->num_groups = mc_list_len;
3968c2ecf20Sopenharmony_ci	memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
3998c2ecf20Sopenharmony_ci				   acx, sizeof(*acx));
4008c2ecf20Sopenharmony_ci	if (ret < 0) {
4018c2ecf20Sopenharmony_ci		wl1251_warning("failed to set group addr table: %d", ret);
4028c2ecf20Sopenharmony_ci		goto out;
4038c2ecf20Sopenharmony_ci	}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ciout:
4068c2ecf20Sopenharmony_ci	kfree(acx);
4078c2ecf20Sopenharmony_ci	return ret;
4088c2ecf20Sopenharmony_ci}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ciint wl1251_acx_service_period_timeout(struct wl1251 *wl)
4118c2ecf20Sopenharmony_ci{
4128c2ecf20Sopenharmony_ci	struct acx_rx_timeout *rx_timeout;
4138c2ecf20Sopenharmony_ci	int ret;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
4168c2ecf20Sopenharmony_ci	if (!rx_timeout)
4178c2ecf20Sopenharmony_ci		return -ENOMEM;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx service period timeout");
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
4228c2ecf20Sopenharmony_ci	rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
4258c2ecf20Sopenharmony_ci				   rx_timeout, sizeof(*rx_timeout));
4268c2ecf20Sopenharmony_ci	if (ret < 0) {
4278c2ecf20Sopenharmony_ci		wl1251_warning("failed to set service period timeout: %d",
4288c2ecf20Sopenharmony_ci			       ret);
4298c2ecf20Sopenharmony_ci		goto out;
4308c2ecf20Sopenharmony_ci	}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ciout:
4338c2ecf20Sopenharmony_ci	kfree(rx_timeout);
4348c2ecf20Sopenharmony_ci	return ret;
4358c2ecf20Sopenharmony_ci}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ciint wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold)
4388c2ecf20Sopenharmony_ci{
4398c2ecf20Sopenharmony_ci	struct acx_rts_threshold *rts;
4408c2ecf20Sopenharmony_ci	int ret;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx rts threshold");
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	rts = kzalloc(sizeof(*rts), GFP_KERNEL);
4458c2ecf20Sopenharmony_ci	if (!rts)
4468c2ecf20Sopenharmony_ci		return -ENOMEM;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	rts->threshold = rts_threshold;
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
4518c2ecf20Sopenharmony_ci	if (ret < 0) {
4528c2ecf20Sopenharmony_ci		wl1251_warning("failed to set rts threshold: %d", ret);
4538c2ecf20Sopenharmony_ci		goto out;
4548c2ecf20Sopenharmony_ci	}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ciout:
4578c2ecf20Sopenharmony_ci	kfree(rts);
4588c2ecf20Sopenharmony_ci	return ret;
4598c2ecf20Sopenharmony_ci}
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ciint wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	struct acx_beacon_filter_option *beacon_filter;
4648c2ecf20Sopenharmony_ci	int ret;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx beacon filter opt");
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
4698c2ecf20Sopenharmony_ci	if (!beacon_filter)
4708c2ecf20Sopenharmony_ci		return -ENOMEM;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	beacon_filter->enable = enable_filter;
4738c2ecf20Sopenharmony_ci	beacon_filter->max_num_beacons = 0;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
4768c2ecf20Sopenharmony_ci				   beacon_filter, sizeof(*beacon_filter));
4778c2ecf20Sopenharmony_ci	if (ret < 0) {
4788c2ecf20Sopenharmony_ci		wl1251_warning("failed to set beacon filter opt: %d", ret);
4798c2ecf20Sopenharmony_ci		goto out;
4808c2ecf20Sopenharmony_ci	}
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ciout:
4838c2ecf20Sopenharmony_ci	kfree(beacon_filter);
4848c2ecf20Sopenharmony_ci	return ret;
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ciint wl1251_acx_beacon_filter_table(struct wl1251 *wl)
4888c2ecf20Sopenharmony_ci{
4898c2ecf20Sopenharmony_ci	struct acx_beacon_filter_ie_table *ie_table;
4908c2ecf20Sopenharmony_ci	int idx = 0;
4918c2ecf20Sopenharmony_ci	int ret;
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx beacon filter table");
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
4968c2ecf20Sopenharmony_ci	if (!ie_table)
4978c2ecf20Sopenharmony_ci		return -ENOMEM;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	/* configure default beacon pass-through rules */
5008c2ecf20Sopenharmony_ci	ie_table->num_ie = 1;
5018c2ecf20Sopenharmony_ci	ie_table->table[idx++] = BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN;
5028c2ecf20Sopenharmony_ci	ie_table->table[idx++] = BEACON_RULE_PASS_ON_APPEARANCE;
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
5058c2ecf20Sopenharmony_ci				   ie_table, sizeof(*ie_table));
5068c2ecf20Sopenharmony_ci	if (ret < 0) {
5078c2ecf20Sopenharmony_ci		wl1251_warning("failed to set beacon filter table: %d", ret);
5088c2ecf20Sopenharmony_ci		goto out;
5098c2ecf20Sopenharmony_ci	}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ciout:
5128c2ecf20Sopenharmony_ci	kfree(ie_table);
5138c2ecf20Sopenharmony_ci	return ret;
5148c2ecf20Sopenharmony_ci}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ciint wl1251_acx_conn_monit_params(struct wl1251 *wl)
5178c2ecf20Sopenharmony_ci{
5188c2ecf20Sopenharmony_ci	struct acx_conn_monit_params *acx;
5198c2ecf20Sopenharmony_ci	int ret;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx connection monitor parameters");
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
5248c2ecf20Sopenharmony_ci	if (!acx)
5258c2ecf20Sopenharmony_ci		return -ENOMEM;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD;
5288c2ecf20Sopenharmony_ci	acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
5318c2ecf20Sopenharmony_ci				   acx, sizeof(*acx));
5328c2ecf20Sopenharmony_ci	if (ret < 0) {
5338c2ecf20Sopenharmony_ci		wl1251_warning("failed to set connection monitor "
5348c2ecf20Sopenharmony_ci			       "parameters: %d", ret);
5358c2ecf20Sopenharmony_ci		goto out;
5368c2ecf20Sopenharmony_ci	}
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ciout:
5398c2ecf20Sopenharmony_ci	kfree(acx);
5408c2ecf20Sopenharmony_ci	return ret;
5418c2ecf20Sopenharmony_ci}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ciint wl1251_acx_sg_enable(struct wl1251 *wl)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	struct acx_bt_wlan_coex *pta;
5468c2ecf20Sopenharmony_ci	int ret;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx sg enable");
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	pta = kzalloc(sizeof(*pta), GFP_KERNEL);
5518c2ecf20Sopenharmony_ci	if (!pta)
5528c2ecf20Sopenharmony_ci		return -ENOMEM;
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	pta->enable = SG_ENABLE;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
5578c2ecf20Sopenharmony_ci	if (ret < 0) {
5588c2ecf20Sopenharmony_ci		wl1251_warning("failed to set softgemini enable: %d", ret);
5598c2ecf20Sopenharmony_ci		goto out;
5608c2ecf20Sopenharmony_ci	}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ciout:
5638c2ecf20Sopenharmony_ci	kfree(pta);
5648c2ecf20Sopenharmony_ci	return ret;
5658c2ecf20Sopenharmony_ci}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ciint wl1251_acx_sg_cfg(struct wl1251 *wl)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	struct acx_bt_wlan_coex_param *param;
5708c2ecf20Sopenharmony_ci	int ret;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx sg cfg");
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	param = kzalloc(sizeof(*param), GFP_KERNEL);
5758c2ecf20Sopenharmony_ci	if (!param)
5768c2ecf20Sopenharmony_ci		return -ENOMEM;
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	/* BT-WLAN coext parameters */
5798c2ecf20Sopenharmony_ci	param->min_rate = RATE_INDEX_24MBPS;
5808c2ecf20Sopenharmony_ci	param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
5818c2ecf20Sopenharmony_ci	param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
5828c2ecf20Sopenharmony_ci	param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
5838c2ecf20Sopenharmony_ci	param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
5848c2ecf20Sopenharmony_ci	param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
5858c2ecf20Sopenharmony_ci	param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
5868c2ecf20Sopenharmony_ci	param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
5878c2ecf20Sopenharmony_ci	param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
5888c2ecf20Sopenharmony_ci	param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
5898c2ecf20Sopenharmony_ci	param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
5908c2ecf20Sopenharmony_ci	param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
5918c2ecf20Sopenharmony_ci	param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
5928c2ecf20Sopenharmony_ci	param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
5938c2ecf20Sopenharmony_ci	param->antenna_type = PTA_ANTENNA_TYPE_DEF;
5948c2ecf20Sopenharmony_ci	param->signal_type = PTA_SIGNALING_TYPE_DEF;
5958c2ecf20Sopenharmony_ci	param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
5968c2ecf20Sopenharmony_ci	param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
5978c2ecf20Sopenharmony_ci	param->max_cts = PTA_MAX_NUM_CTS_DEF;
5988c2ecf20Sopenharmony_ci	param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
5998c2ecf20Sopenharmony_ci	param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
6008c2ecf20Sopenharmony_ci	param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
6018c2ecf20Sopenharmony_ci	param->wlan_elp_hp = PTA_ELP_HP_DEF;
6028c2ecf20Sopenharmony_ci	param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
6038c2ecf20Sopenharmony_ci	param->ack_mode_dual_ant = PTA_ACK_MODE_DEF;
6048c2ecf20Sopenharmony_ci	param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
6058c2ecf20Sopenharmony_ci	param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
6068c2ecf20Sopenharmony_ci	param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
6098c2ecf20Sopenharmony_ci	if (ret < 0) {
6108c2ecf20Sopenharmony_ci		wl1251_warning("failed to set sg config: %d", ret);
6118c2ecf20Sopenharmony_ci		goto out;
6128c2ecf20Sopenharmony_ci	}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ciout:
6158c2ecf20Sopenharmony_ci	kfree(param);
6168c2ecf20Sopenharmony_ci	return ret;
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ciint wl1251_acx_cca_threshold(struct wl1251 *wl)
6208c2ecf20Sopenharmony_ci{
6218c2ecf20Sopenharmony_ci	struct acx_energy_detection *detection;
6228c2ecf20Sopenharmony_ci	int ret;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx cca threshold");
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	detection = kzalloc(sizeof(*detection), GFP_KERNEL);
6278c2ecf20Sopenharmony_ci	if (!detection)
6288c2ecf20Sopenharmony_ci		return -ENOMEM;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
6318c2ecf20Sopenharmony_ci	detection->tx_energy_detection = 0;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD,
6348c2ecf20Sopenharmony_ci				   detection, sizeof(*detection));
6358c2ecf20Sopenharmony_ci	if (ret < 0)
6368c2ecf20Sopenharmony_ci		wl1251_warning("failed to set cca threshold: %d", ret);
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	kfree(detection);
6398c2ecf20Sopenharmony_ci	return ret;
6408c2ecf20Sopenharmony_ci}
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ciint wl1251_acx_bcn_dtim_options(struct wl1251 *wl)
6438c2ecf20Sopenharmony_ci{
6448c2ecf20Sopenharmony_ci	struct acx_beacon_broadcast *bb;
6458c2ecf20Sopenharmony_ci	int ret;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx bcn dtim options");
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	bb = kzalloc(sizeof(*bb), GFP_KERNEL);
6508c2ecf20Sopenharmony_ci	if (!bb)
6518c2ecf20Sopenharmony_ci		return -ENOMEM;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
6548c2ecf20Sopenharmony_ci	bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
6558c2ecf20Sopenharmony_ci	bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
6568c2ecf20Sopenharmony_ci	bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
6598c2ecf20Sopenharmony_ci	if (ret < 0) {
6608c2ecf20Sopenharmony_ci		wl1251_warning("failed to set rx config: %d", ret);
6618c2ecf20Sopenharmony_ci		goto out;
6628c2ecf20Sopenharmony_ci	}
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ciout:
6658c2ecf20Sopenharmony_ci	kfree(bb);
6668c2ecf20Sopenharmony_ci	return ret;
6678c2ecf20Sopenharmony_ci}
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ciint wl1251_acx_aid(struct wl1251 *wl, u16 aid)
6708c2ecf20Sopenharmony_ci{
6718c2ecf20Sopenharmony_ci	struct acx_aid *acx_aid;
6728c2ecf20Sopenharmony_ci	int ret;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx aid");
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
6778c2ecf20Sopenharmony_ci	if (!acx_aid)
6788c2ecf20Sopenharmony_ci		return -ENOMEM;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	acx_aid->aid = aid;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
6838c2ecf20Sopenharmony_ci	if (ret < 0) {
6848c2ecf20Sopenharmony_ci		wl1251_warning("failed to set aid: %d", ret);
6858c2ecf20Sopenharmony_ci		goto out;
6868c2ecf20Sopenharmony_ci	}
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ciout:
6898c2ecf20Sopenharmony_ci	kfree(acx_aid);
6908c2ecf20Sopenharmony_ci	return ret;
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ciint wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask)
6948c2ecf20Sopenharmony_ci{
6958c2ecf20Sopenharmony_ci	struct acx_event_mask *mask;
6968c2ecf20Sopenharmony_ci	int ret;
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx event mbox mask");
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	mask = kzalloc(sizeof(*mask), GFP_KERNEL);
7018c2ecf20Sopenharmony_ci	if (!mask)
7028c2ecf20Sopenharmony_ci		return -ENOMEM;
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	/* high event mask is unused */
7058c2ecf20Sopenharmony_ci	mask->high_event_mask = 0xffffffff;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	mask->event_mask = event_mask;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
7108c2ecf20Sopenharmony_ci				   mask, sizeof(*mask));
7118c2ecf20Sopenharmony_ci	if (ret < 0) {
7128c2ecf20Sopenharmony_ci		wl1251_warning("failed to set acx_event_mbox_mask: %d", ret);
7138c2ecf20Sopenharmony_ci		goto out;
7148c2ecf20Sopenharmony_ci	}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ciout:
7178c2ecf20Sopenharmony_ci	kfree(mask);
7188c2ecf20Sopenharmony_ci	return ret;
7198c2ecf20Sopenharmony_ci}
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ciint wl1251_acx_low_rssi(struct wl1251 *wl, s8 threshold, u8 weight,
7228c2ecf20Sopenharmony_ci			u8 depth, enum wl1251_acx_low_rssi_type type)
7238c2ecf20Sopenharmony_ci{
7248c2ecf20Sopenharmony_ci	struct acx_low_rssi *rssi;
7258c2ecf20Sopenharmony_ci	int ret;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx low rssi");
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	rssi = kzalloc(sizeof(*rssi), GFP_KERNEL);
7308c2ecf20Sopenharmony_ci	if (!rssi)
7318c2ecf20Sopenharmony_ci		return -ENOMEM;
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	rssi->threshold = threshold;
7348c2ecf20Sopenharmony_ci	rssi->weight = weight;
7358c2ecf20Sopenharmony_ci	rssi->depth = depth;
7368c2ecf20Sopenharmony_ci	rssi->type = type;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_LOW_RSSI, rssi, sizeof(*rssi));
7398c2ecf20Sopenharmony_ci	if (ret < 0)
7408c2ecf20Sopenharmony_ci		wl1251_warning("failed to set low rssi threshold: %d", ret);
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	kfree(rssi);
7438c2ecf20Sopenharmony_ci	return ret;
7448c2ecf20Sopenharmony_ci}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ciint wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble)
7478c2ecf20Sopenharmony_ci{
7488c2ecf20Sopenharmony_ci	struct acx_preamble *acx;
7498c2ecf20Sopenharmony_ci	int ret;
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx_set_preamble");
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
7548c2ecf20Sopenharmony_ci	if (!acx)
7558c2ecf20Sopenharmony_ci		return -ENOMEM;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	acx->preamble = preamble;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
7608c2ecf20Sopenharmony_ci	if (ret < 0) {
7618c2ecf20Sopenharmony_ci		wl1251_warning("Setting of preamble failed: %d", ret);
7628c2ecf20Sopenharmony_ci		goto out;
7638c2ecf20Sopenharmony_ci	}
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ciout:
7668c2ecf20Sopenharmony_ci	kfree(acx);
7678c2ecf20Sopenharmony_ci	return ret;
7688c2ecf20Sopenharmony_ci}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ciint wl1251_acx_cts_protect(struct wl1251 *wl,
7718c2ecf20Sopenharmony_ci			   enum acx_ctsprotect_type ctsprotect)
7728c2ecf20Sopenharmony_ci{
7738c2ecf20Sopenharmony_ci	struct acx_ctsprotect *acx;
7748c2ecf20Sopenharmony_ci	int ret;
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect");
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
7798c2ecf20Sopenharmony_ci	if (!acx)
7808c2ecf20Sopenharmony_ci		return -ENOMEM;
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	acx->ctsprotect = ctsprotect;
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
7858c2ecf20Sopenharmony_ci	if (ret < 0) {
7868c2ecf20Sopenharmony_ci		wl1251_warning("Setting of ctsprotect failed: %d", ret);
7878c2ecf20Sopenharmony_ci		goto out;
7888c2ecf20Sopenharmony_ci	}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ciout:
7918c2ecf20Sopenharmony_ci	kfree(acx);
7928c2ecf20Sopenharmony_ci	return ret;
7938c2ecf20Sopenharmony_ci}
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ciint wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime)
7968c2ecf20Sopenharmony_ci{
7978c2ecf20Sopenharmony_ci	struct acx_tsf_info *tsf_info;
7988c2ecf20Sopenharmony_ci	int ret;
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL);
8018c2ecf20Sopenharmony_ci	if (!tsf_info)
8028c2ecf20Sopenharmony_ci		return -ENOMEM;
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO,
8058c2ecf20Sopenharmony_ci				     tsf_info, sizeof(*tsf_info));
8068c2ecf20Sopenharmony_ci	if (ret < 0) {
8078c2ecf20Sopenharmony_ci		wl1251_warning("ACX_FW_REV interrogate failed");
8088c2ecf20Sopenharmony_ci		goto out;
8098c2ecf20Sopenharmony_ci	}
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	*mactime = tsf_info->current_tsf_lsb |
8128c2ecf20Sopenharmony_ci		((u64)tsf_info->current_tsf_msb << 32);
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ciout:
8158c2ecf20Sopenharmony_ci	kfree(tsf_info);
8168c2ecf20Sopenharmony_ci	return ret;
8178c2ecf20Sopenharmony_ci}
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ciint wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats)
8208c2ecf20Sopenharmony_ci{
8218c2ecf20Sopenharmony_ci	int ret;
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx statistics");
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	ret = wl1251_cmd_interrogate(wl, ACX_STATISTICS, stats,
8268c2ecf20Sopenharmony_ci				     sizeof(*stats));
8278c2ecf20Sopenharmony_ci	if (ret < 0) {
8288c2ecf20Sopenharmony_ci		wl1251_warning("acx statistics failed: %d", ret);
8298c2ecf20Sopenharmony_ci		return -ENOMEM;
8308c2ecf20Sopenharmony_ci	}
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	return 0;
8338c2ecf20Sopenharmony_ci}
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ciint wl1251_acx_rate_policies(struct wl1251 *wl)
8368c2ecf20Sopenharmony_ci{
8378c2ecf20Sopenharmony_ci	struct acx_rate_policy *acx;
8388c2ecf20Sopenharmony_ci	int ret = 0;
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx rate policies");
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
8438c2ecf20Sopenharmony_ci	if (!acx)
8448c2ecf20Sopenharmony_ci		return -ENOMEM;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	/* configure one default (one-size-fits-all) rate class */
8478c2ecf20Sopenharmony_ci	acx->rate_class_cnt = 2;
8488c2ecf20Sopenharmony_ci	acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
8498c2ecf20Sopenharmony_ci	acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
8508c2ecf20Sopenharmony_ci	acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
8518c2ecf20Sopenharmony_ci	acx->rate_class[0].aflags = 0;
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	/* no-retry rate class */
8548c2ecf20Sopenharmony_ci	acx->rate_class[1].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
8558c2ecf20Sopenharmony_ci	acx->rate_class[1].short_retry_limit = 0;
8568c2ecf20Sopenharmony_ci	acx->rate_class[1].long_retry_limit = 0;
8578c2ecf20Sopenharmony_ci	acx->rate_class[1].aflags = 0;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
8608c2ecf20Sopenharmony_ci	if (ret < 0) {
8618c2ecf20Sopenharmony_ci		wl1251_warning("Setting of rate policies failed: %d", ret);
8628c2ecf20Sopenharmony_ci		goto out;
8638c2ecf20Sopenharmony_ci	}
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ciout:
8668c2ecf20Sopenharmony_ci	kfree(acx);
8678c2ecf20Sopenharmony_ci	return ret;
8688c2ecf20Sopenharmony_ci}
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ciint wl1251_acx_mem_cfg(struct wl1251 *wl)
8718c2ecf20Sopenharmony_ci{
8728c2ecf20Sopenharmony_ci	struct wl1251_acx_config_memory *mem_conf;
8738c2ecf20Sopenharmony_ci	int ret, i;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx mem cfg");
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
8788c2ecf20Sopenharmony_ci	if (!mem_conf)
8798c2ecf20Sopenharmony_ci		return -ENOMEM;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	/* memory config */
8828c2ecf20Sopenharmony_ci	mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
8838c2ecf20Sopenharmony_ci	mem_conf->mem_config.rx_mem_block_num = 35;
8848c2ecf20Sopenharmony_ci	mem_conf->mem_config.tx_min_mem_block_num = 64;
8858c2ecf20Sopenharmony_ci	mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES;
8868c2ecf20Sopenharmony_ci	mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING;
8878c2ecf20Sopenharmony_ci	mem_conf->mem_config.num_ssid_profiles = 1;
8888c2ecf20Sopenharmony_ci	mem_conf->mem_config.debug_buffer_size =
8898c2ecf20Sopenharmony_ci		cpu_to_le16(TRACE_BUFFER_MAX_SIZE);
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci	/* RX queue config */
8928c2ecf20Sopenharmony_ci	mem_conf->rx_queue_config.dma_address = 0;
8938c2ecf20Sopenharmony_ci	mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF;
8948c2ecf20Sopenharmony_ci	mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY;
8958c2ecf20Sopenharmony_ci	mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	/* TX queue config */
8988c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_TX_QUEUES; i++) {
8998c2ecf20Sopenharmony_ci		mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF;
9008c2ecf20Sopenharmony_ci		mem_conf->tx_queue_config[i].attributes = i;
9018c2ecf20Sopenharmony_ci	}
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
9048c2ecf20Sopenharmony_ci				   sizeof(*mem_conf));
9058c2ecf20Sopenharmony_ci	if (ret < 0) {
9068c2ecf20Sopenharmony_ci		wl1251_warning("wl1251 mem config failed: %d", ret);
9078c2ecf20Sopenharmony_ci		goto out;
9088c2ecf20Sopenharmony_ci	}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ciout:
9118c2ecf20Sopenharmony_ci	kfree(mem_conf);
9128c2ecf20Sopenharmony_ci	return ret;
9138c2ecf20Sopenharmony_ci}
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ciint wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim)
9168c2ecf20Sopenharmony_ci{
9178c2ecf20Sopenharmony_ci	struct wl1251_acx_wr_tbtt_and_dtim *acx;
9188c2ecf20Sopenharmony_ci	int ret;
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx tbtt and dtim");
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
9238c2ecf20Sopenharmony_ci	if (!acx)
9248c2ecf20Sopenharmony_ci		return -ENOMEM;
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	acx->tbtt = tbtt;
9278c2ecf20Sopenharmony_ci	acx->dtim = dtim;
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_WR_TBTT_AND_DTIM,
9308c2ecf20Sopenharmony_ci				   acx, sizeof(*acx));
9318c2ecf20Sopenharmony_ci	if (ret < 0) {
9328c2ecf20Sopenharmony_ci		wl1251_warning("failed to set tbtt and dtim: %d", ret);
9338c2ecf20Sopenharmony_ci		goto out;
9348c2ecf20Sopenharmony_ci	}
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ciout:
9378c2ecf20Sopenharmony_ci	kfree(acx);
9388c2ecf20Sopenharmony_ci	return ret;
9398c2ecf20Sopenharmony_ci}
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ciint wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
9428c2ecf20Sopenharmony_ci			  u8 max_consecutive)
9438c2ecf20Sopenharmony_ci{
9448c2ecf20Sopenharmony_ci	struct wl1251_acx_bet_enable *acx;
9458c2ecf20Sopenharmony_ci	int ret;
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx bet enable");
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
9508c2ecf20Sopenharmony_ci	if (!acx)
9518c2ecf20Sopenharmony_ci		return -ENOMEM;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	acx->enable = mode;
9548c2ecf20Sopenharmony_ci	acx->max_consecutive = max_consecutive;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
9578c2ecf20Sopenharmony_ci	if (ret < 0) {
9588c2ecf20Sopenharmony_ci		wl1251_warning("wl1251 acx bet enable failed: %d", ret);
9598c2ecf20Sopenharmony_ci		goto out;
9608c2ecf20Sopenharmony_ci	}
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ciout:
9638c2ecf20Sopenharmony_ci	kfree(acx);
9648c2ecf20Sopenharmony_ci	return ret;
9658c2ecf20Sopenharmony_ci}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ciint wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	struct wl1251_acx_arp_filter *acx;
9708c2ecf20Sopenharmony_ci	int ret;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
9758c2ecf20Sopenharmony_ci	if (!acx)
9768c2ecf20Sopenharmony_ci		return -ENOMEM;
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	acx->version = ACX_IPV4_VERSION;
9798c2ecf20Sopenharmony_ci	acx->enable = enable;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	if (enable)
9828c2ecf20Sopenharmony_ci		memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_ARP_IP_FILTER,
9858c2ecf20Sopenharmony_ci				   acx, sizeof(*acx));
9868c2ecf20Sopenharmony_ci	if (ret < 0)
9878c2ecf20Sopenharmony_ci		wl1251_warning("failed to set arp ip filter: %d", ret);
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci	kfree(acx);
9908c2ecf20Sopenharmony_ci	return ret;
9918c2ecf20Sopenharmony_ci}
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ciint wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
9948c2ecf20Sopenharmony_ci		      u8 aifs, u16 txop)
9958c2ecf20Sopenharmony_ci{
9968c2ecf20Sopenharmony_ci	struct wl1251_acx_ac_cfg *acx;
9978c2ecf20Sopenharmony_ci	int ret = 0;
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d "
10008c2ecf20Sopenharmony_ci		     "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop);
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
10038c2ecf20Sopenharmony_ci	if (!acx)
10048c2ecf20Sopenharmony_ci		return -ENOMEM;
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	acx->ac = ac;
10078c2ecf20Sopenharmony_ci	acx->cw_min = cw_min;
10088c2ecf20Sopenharmony_ci	acx->cw_max = cw_max;
10098c2ecf20Sopenharmony_ci	acx->aifsn = aifs;
10108c2ecf20Sopenharmony_ci	acx->txop_limit = txop;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
10138c2ecf20Sopenharmony_ci	if (ret < 0) {
10148c2ecf20Sopenharmony_ci		wl1251_warning("acx ac cfg failed: %d", ret);
10158c2ecf20Sopenharmony_ci		goto out;
10168c2ecf20Sopenharmony_ci	}
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ciout:
10198c2ecf20Sopenharmony_ci	kfree(acx);
10208c2ecf20Sopenharmony_ci	return ret;
10218c2ecf20Sopenharmony_ci}
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ciint wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
10248c2ecf20Sopenharmony_ci		       enum wl1251_acx_channel_type type,
10258c2ecf20Sopenharmony_ci		       u8 tsid, enum wl1251_acx_ps_scheme ps_scheme,
10268c2ecf20Sopenharmony_ci		       enum wl1251_acx_ack_policy ack_policy)
10278c2ecf20Sopenharmony_ci{
10288c2ecf20Sopenharmony_ci	struct wl1251_acx_tid_cfg *acx;
10298c2ecf20Sopenharmony_ci	int ret = 0;
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d "
10328c2ecf20Sopenharmony_ci		     "ps_scheme %d ack_policy %d", queue, type, tsid,
10338c2ecf20Sopenharmony_ci		     ps_scheme, ack_policy);
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
10368c2ecf20Sopenharmony_ci	if (!acx)
10378c2ecf20Sopenharmony_ci		return -ENOMEM;
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	acx->queue = queue;
10408c2ecf20Sopenharmony_ci	acx->type = type;
10418c2ecf20Sopenharmony_ci	acx->tsid = tsid;
10428c2ecf20Sopenharmony_ci	acx->ps_scheme = ps_scheme;
10438c2ecf20Sopenharmony_ci	acx->ack_policy = ack_policy;
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
10468c2ecf20Sopenharmony_ci	if (ret < 0) {
10478c2ecf20Sopenharmony_ci		wl1251_warning("acx tid cfg failed: %d", ret);
10488c2ecf20Sopenharmony_ci		goto out;
10498c2ecf20Sopenharmony_ci	}
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ciout:
10528c2ecf20Sopenharmony_ci	kfree(acx);
10538c2ecf20Sopenharmony_ci	return ret;
10548c2ecf20Sopenharmony_ci}
1055