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