acx.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. #include "acx.h"
  2. #include <linux/module.h>
  3. #include <linux/crc7.h>
  4. #include <linux/spi/spi.h>
  5. #include "wl12xx.h"
  6. #include "wl12xx_80211.h"
  7. #include "reg.h"
  8. #include "spi.h"
  9. #include "ps.h"
  10. int wl12xx_acx_frame_rates(struct wl12xx *wl, u8 ctrl_rate, u8 ctrl_mod,
  11. u8 mgt_rate, u8 mgt_mod)
  12. {
  13. int ret;
  14. struct acx_fw_gen_frame_rates rates;
  15. wl12xx_debug(DEBUG_ACX, "acx frame rates");
  16. rates.header.id = ACX_FW_GEN_FRAME_RATES;
  17. rates.header.len = sizeof(struct acx_fw_gen_frame_rates) -
  18. sizeof(struct acx_header);
  19. rates.tx_ctrl_frame_rate = ctrl_rate;
  20. rates.tx_ctrl_frame_mod = ctrl_mod;
  21. rates.tx_mgt_frame_rate = mgt_rate;
  22. rates.tx_mgt_frame_mod = mgt_mod;
  23. ret = wl12xx_cmd_configure(wl, &rates, sizeof(rates));
  24. if (ret < 0) {
  25. wl12xx_error("Failed to set FW rates and modulation");
  26. return ret;
  27. }
  28. return 0;
  29. }
  30. int wl12xx_acx_station_id(struct wl12xx *wl)
  31. {
  32. int ret, i;
  33. struct dot11_station_id mac;
  34. wl12xx_debug(DEBUG_ACX, "acx dot11_station_id");
  35. mac.header.id = DOT11_STATION_ID;
  36. mac.header.len = sizeof(mac) - sizeof(struct acx_header);
  37. for (i = 0; i < ETH_ALEN; i++)
  38. mac.mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
  39. ret = wl12xx_cmd_configure(wl, &mac, sizeof(mac));
  40. if (ret < 0)
  41. return ret;
  42. return 0;
  43. }
  44. int wl12xx_acx_default_key(struct wl12xx *wl, u8 key_id)
  45. {
  46. struct acx_dot11_default_key default_key;
  47. int ret;
  48. wl12xx_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);
  49. default_key.header.id = DOT11_DEFAULT_KEY;
  50. default_key.header.len = sizeof(default_key) -
  51. sizeof(struct acx_header);
  52. default_key.id = key_id;
  53. ret = wl12xx_cmd_configure(wl, &default_key, sizeof(default_key));
  54. if (ret < 0) {
  55. wl12xx_error("Couldnt set default key");
  56. return ret;
  57. }
  58. wl->default_key = key_id;
  59. return 0;
  60. }
  61. int wl12xx_acx_wake_up_conditions(struct wl12xx *wl, u8 listen_interval)
  62. {
  63. struct acx_wake_up_condition wake_up;
  64. wl12xx_debug(DEBUG_ACX, "acx wake up conditions");
  65. wake_up.header.id = ACX_WAKE_UP_CONDITIONS;
  66. wake_up.header.len = sizeof(wake_up) - sizeof(struct acx_header);
  67. wake_up.wake_up_event = WAKE_UP_EVENT_DTIM_BITMAP;
  68. wake_up.listen_interval = listen_interval;
  69. return wl12xx_cmd_configure(wl, &wake_up, sizeof(wake_up));
  70. }
  71. int wl12xx_acx_sleep_auth(struct wl12xx *wl, u8 sleep_auth)
  72. {
  73. int ret;
  74. struct acx_sleep_auth auth;
  75. wl12xx_debug(DEBUG_ACX, "acx sleep auth");
  76. auth.header.id = ACX_SLEEP_AUTH;
  77. auth.header.len = sizeof(auth) - sizeof(struct acx_header);
  78. auth.sleep_auth = sleep_auth;
  79. ret = wl12xx_cmd_configure(wl, &auth, sizeof(auth));
  80. if (ret < 0)
  81. return ret;
  82. return 0;
  83. }
  84. int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len)
  85. {
  86. struct wl12xx_command cmd;
  87. struct acx_revision *rev;
  88. int ret;
  89. wl12xx_debug(DEBUG_ACX, "acx fw rev");
  90. memset(&cmd, 0, sizeof(cmd));
  91. ret = wl12xx_cmd_interrogate(wl, ACX_FW_REV, sizeof(*rev), &cmd);
  92. if (ret < 0) {
  93. wl12xx_warning("ACX_FW_REV interrogate failed");
  94. return ret;
  95. }
  96. rev = (struct acx_revision *) &cmd.parameters;
  97. /* be careful with the buffer sizes */
  98. strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
  99. /*
  100. * if the firmware version string is exactly
  101. * sizeof(rev->fw_version) long or fw_len is less than
  102. * sizeof(rev->fw_version) it won't be null terminated
  103. */
  104. buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
  105. return 0;
  106. }
  107. int wl12xx_acx_tx_power(struct wl12xx *wl, int power)
  108. {
  109. struct acx_current_tx_power ie;
  110. int ret;
  111. wl12xx_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
  112. if (power < 0 || power > 25)
  113. return -EINVAL;
  114. memset(&ie, 0, sizeof(ie));
  115. ie.header.id = DOT11_CUR_TX_PWR;
  116. ie.header.len = sizeof(ie) - sizeof(struct acx_header);
  117. ie.current_tx_power = power * 10;
  118. ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie));
  119. if (ret < 0) {
  120. wl12xx_warning("configure of tx power failed: %d", ret);
  121. return ret;
  122. }
  123. return 0;
  124. }
  125. int wl12xx_acx_feature_cfg(struct wl12xx *wl)
  126. {
  127. struct acx_feature_config feature;
  128. int ret;
  129. wl12xx_debug(DEBUG_ACX, "acx feature cfg");
  130. memset(&feature, 0, sizeof(feature));
  131. feature.header.id = ACX_FEATURE_CFG;
  132. feature.header.len = sizeof(feature) - sizeof(struct acx_header);
  133. /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
  134. feature.data_flow_options = 0;
  135. feature.options = 0;
  136. ret = wl12xx_cmd_configure(wl, &feature, sizeof(feature));
  137. if (ret < 0)
  138. wl12xx_error("Couldnt set HW encryption");
  139. return ret;
  140. }
  141. int wl12xx_acx_mem_map(struct wl12xx *wl, void *mem_map, size_t len)
  142. {
  143. struct wl12xx_command cmd;
  144. int ret;
  145. wl12xx_debug(DEBUG_ACX, "acx mem map");
  146. ret = wl12xx_cmd_interrogate(wl, ACX_MEM_MAP, len, &cmd);
  147. if (ret < 0)
  148. return ret;
  149. else if (cmd.status != CMD_STATUS_SUCCESS)
  150. return -EIO;
  151. memcpy(mem_map, &cmd.parameters, len);
  152. return 0;
  153. }
  154. int wl12xx_acx_data_path_params(struct wl12xx *wl,
  155. struct acx_data_path_params_resp *data_path)
  156. {
  157. struct acx_data_path_params params;
  158. struct wl12xx_command cmd;
  159. int ret;
  160. wl12xx_debug(DEBUG_ACX, "acx data path params");
  161. params.rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
  162. params.tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
  163. params.rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM;
  164. params.tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM;
  165. params.tx_complete_threshold = 1;
  166. params.tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE;
  167. params.tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT;
  168. params.header.id = ACX_DATA_PATH_PARAMS;
  169. params.header.len = sizeof(params) - sizeof(struct acx_header);
  170. ret = wl12xx_cmd_configure(wl, &params, sizeof(params));
  171. if (ret < 0)
  172. return ret;
  173. ret = wl12xx_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS,
  174. sizeof(struct acx_data_path_params_resp),
  175. &cmd);
  176. if (ret < 0) {
  177. wl12xx_warning("failed to read data path parameters: %d", ret);
  178. return ret;
  179. } else if (cmd.status != CMD_STATUS_SUCCESS) {
  180. wl12xx_warning("data path parameter acx status failed");
  181. return -EIO;
  182. }
  183. memcpy(data_path, &cmd.parameters, sizeof(*data_path));
  184. return 0;
  185. }
  186. int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time)
  187. {
  188. struct rx_msdu_lifetime msdu_lifetime;
  189. int ret;
  190. wl12xx_debug(DEBUG_ACX, "acx rx msdu life time");
  191. msdu_lifetime.header.id = DOT11_RX_MSDU_LIFE_TIME;
  192. msdu_lifetime.header.len = sizeof(msdu_lifetime) -
  193. sizeof(struct acx_header);
  194. msdu_lifetime.lifetime = life_time;
  195. ret = wl12xx_cmd_configure(wl, &msdu_lifetime, sizeof(msdu_lifetime));
  196. if (ret < 0) {
  197. wl12xx_warning("failed to set rx msdu life time: %d", ret);
  198. return ret;
  199. }
  200. return 0;
  201. }
  202. int wl12xx_acx_rx_config(struct wl12xx *wl, u32 config, u32 filter)
  203. {
  204. struct acx_rx_config rx_config;
  205. int ret;
  206. wl12xx_debug(DEBUG_ACX, "acx rx config");
  207. rx_config.header.id = ACX_RX_CFG;
  208. rx_config.header.len = sizeof(rx_config) - sizeof(struct acx_header);
  209. rx_config.config_options = config;
  210. rx_config.filter_options = filter;
  211. ret = wl12xx_cmd_configure(wl, &rx_config, sizeof(rx_config));
  212. if (ret < 0) {
  213. wl12xx_warning("failed to set rx config: %d", ret);
  214. return ret;
  215. }
  216. return 0;
  217. }
  218. int wl12xx_acx_pd_threshold(struct wl12xx *wl)
  219. {
  220. struct acx_packet_detection packet_detection;
  221. int ret;
  222. wl12xx_debug(DEBUG_ACX, "acx data pd threshold");
  223. /* FIXME: threshold value not set */
  224. packet_detection.header.id = ACX_PD_THRESHOLD;
  225. packet_detection.header.len = sizeof(packet_detection) -
  226. sizeof(struct acx_header);
  227. ret = wl12xx_cmd_configure(wl, &packet_detection,
  228. sizeof(packet_detection));
  229. if (ret < 0) {
  230. wl12xx_warning("failed to set pd threshold: %d", ret);
  231. return ret;
  232. }
  233. return 0;
  234. }
  235. int wl12xx_acx_slot(struct wl12xx *wl, enum acx_slot_type slot_time)
  236. {
  237. struct acx_slot slot;
  238. int ret;
  239. wl12xx_debug(DEBUG_ACX, "acx slot");
  240. slot.header.id = ACX_SLOT;
  241. slot.header.len = sizeof(slot) - sizeof(struct acx_header);
  242. slot.wone_index = STATION_WONE_INDEX;
  243. slot.slot_time = slot_time;
  244. ret = wl12xx_cmd_configure(wl, &slot, sizeof(slot));
  245. if (ret < 0) {
  246. wl12xx_warning("failed to set slot time: %d", ret);
  247. return ret;
  248. }
  249. return 0;
  250. }
  251. int wl12xx_acx_group_address_tbl(struct wl12xx *wl)
  252. {
  253. struct multicast_grp_addr_start multicast;
  254. int ret;
  255. wl12xx_debug(DEBUG_ACX, "acx group address tbl");
  256. /* MAC filtering */
  257. multicast.header.id = DOT11_GROUP_ADDRESS_TBL;
  258. multicast.header.len = sizeof(multicast) - sizeof(struct acx_header);
  259. multicast.enabled = 0;
  260. multicast.num_groups = 0;
  261. memset(multicast.mac_table, 0, ADDRESS_GROUP_MAX_LEN);
  262. ret = wl12xx_cmd_configure(wl, &multicast, sizeof(multicast));
  263. if (ret < 0) {
  264. wl12xx_warning("failed to set group addr table: %d", ret);
  265. return ret;
  266. }
  267. return 0;
  268. }
  269. int wl12xx_acx_service_period_timeout(struct wl12xx *wl)
  270. {
  271. struct acx_rx_timeout rx_timeout;
  272. int ret;
  273. wl12xx_debug(DEBUG_ACX, "acx service period timeout");
  274. /* RX timeout */
  275. rx_timeout.header.id = ACX_SERVICE_PERIOD_TIMEOUT;
  276. rx_timeout.header.len = sizeof(rx_timeout) - sizeof(struct acx_header);
  277. rx_timeout.ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
  278. rx_timeout.upsd_timeout = RX_TIMEOUT_UPSD_DEF;
  279. ret = wl12xx_cmd_configure(wl, &rx_timeout, sizeof(rx_timeout));
  280. if (ret < 0) {
  281. wl12xx_warning("failed to set service period timeout: %d",
  282. ret);
  283. return ret;
  284. }
  285. return 0;
  286. }
  287. int wl12xx_acx_rts_threshold(struct wl12xx *wl, u16 rts_threshold)
  288. {
  289. struct acx_rts_threshold rts;
  290. int ret;
  291. wl12xx_debug(DEBUG_ACX, "acx rts threshold");
  292. rts.header.id = DOT11_RTS_THRESHOLD;
  293. rts.header.len = sizeof(rts) - sizeof(struct acx_header);
  294. rts.threshold = rts_threshold;
  295. ret = wl12xx_cmd_configure(wl, &rts, sizeof(rts));
  296. if (ret < 0) {
  297. wl12xx_warning("failed to set rts threshold: %d", ret);
  298. return ret;
  299. }
  300. return 0;
  301. }
  302. int wl12xx_acx_beacon_filter_opt(struct wl12xx *wl)
  303. {
  304. struct acx_beacon_filter_option beacon_filter;
  305. int ret;
  306. wl12xx_debug(DEBUG_ACX, "acx beacon filter opt");
  307. beacon_filter.header.id = ACX_BEACON_FILTER_OPT;
  308. beacon_filter.header.len = sizeof(beacon_filter) -
  309. sizeof(struct acx_header);
  310. beacon_filter.enable = 0;
  311. beacon_filter.max_num_beacons = 0;
  312. ret = wl12xx_cmd_configure(wl, &beacon_filter, sizeof(beacon_filter));
  313. if (ret < 0) {
  314. wl12xx_warning("failed to set beacon filter opt: %d", ret);
  315. return ret;
  316. }
  317. return 0;
  318. }
  319. int wl12xx_acx_beacon_filter_table(struct wl12xx *wl)
  320. {
  321. struct acx_beacon_filter_ie_table ie_table;
  322. int ret;
  323. wl12xx_debug(DEBUG_ACX, "acx beacon filter table");
  324. ie_table.header.id = ACX_BEACON_FILTER_TABLE;
  325. ie_table.header.len = sizeof(ie_table) - sizeof(struct acx_header);
  326. ie_table.num_ie = 0;
  327. memset(ie_table.table, 0, BEACON_FILTER_TABLE_MAX_SIZE);
  328. ret = wl12xx_cmd_configure(wl, &ie_table, sizeof(ie_table));
  329. if (ret < 0) {
  330. wl12xx_warning("failed to set beacon filter table: %d", ret);
  331. return ret;
  332. }
  333. return 0;
  334. }
  335. int wl12xx_acx_sg_enable(struct wl12xx *wl)
  336. {
  337. struct acx_bt_wlan_coex pta;
  338. int ret;
  339. wl12xx_debug(DEBUG_ACX, "acx sg enable");
  340. pta.header.id = ACX_SG_ENABLE;
  341. pta.header.len = sizeof(pta) - sizeof(struct acx_header);
  342. pta.enable = SG_ENABLE;
  343. ret = wl12xx_cmd_configure(wl, &pta, sizeof(pta));
  344. if (ret < 0) {
  345. wl12xx_warning("failed to set softgemini enable: %d", ret);
  346. return ret;
  347. }
  348. return 0;
  349. }
  350. int wl12xx_acx_sg_cfg(struct wl12xx *wl)
  351. {
  352. struct acx_bt_wlan_coex_param param;
  353. int ret;
  354. wl12xx_debug(DEBUG_ACX, "acx sg cfg");
  355. /* BT-WLAN coext parameters */
  356. param.header.id = ACX_SG_CFG;
  357. param.header.len = sizeof(param) - sizeof(struct acx_header);
  358. param.min_rate = RATE_INDEX_24MBPS;
  359. param.bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
  360. param.wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
  361. param.sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
  362. param.rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
  363. param.tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
  364. param.rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
  365. param.tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
  366. param.wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
  367. param.bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
  368. param.next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
  369. param.wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
  370. param.hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
  371. param.next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
  372. param.antenna_type = PTA_ANTENNA_TYPE_DEF;
  373. param.signal_type = PTA_SIGNALING_TYPE_DEF;
  374. param.afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
  375. param.quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
  376. param.max_cts = PTA_MAX_NUM_CTS_DEF;
  377. param.wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
  378. param.bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
  379. param.missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
  380. param.wlan_elp_hp = PTA_ELP_HP_DEF;
  381. param.bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
  382. param.ack_mode_dual_ant = PTA_ACK_MODE_DEF;
  383. param.pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
  384. param.pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
  385. param.bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
  386. ret = wl12xx_cmd_configure(wl, &param, sizeof(param));
  387. if (ret < 0) {
  388. wl12xx_warning("failed to set sg config: %d", ret);
  389. return ret;
  390. }
  391. return 0;
  392. }
  393. int wl12xx_acx_cca_threshold(struct wl12xx *wl)
  394. {
  395. struct acx_energy_detection detection;
  396. int ret;
  397. wl12xx_debug(DEBUG_ACX, "acx cca threshold");
  398. detection.header.id = ACX_CCA_THRESHOLD;
  399. detection.header.len = sizeof(detection) - sizeof(struct acx_header);
  400. detection.rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
  401. detection.tx_energy_detection = 0;
  402. ret = wl12xx_cmd_configure(wl, &detection, sizeof(detection));
  403. if (ret < 0) {
  404. wl12xx_warning("failed to set cca threshold: %d", ret);
  405. return ret;
  406. }
  407. return 0;
  408. }
  409. int wl12xx_acx_bcn_dtim_options(struct wl12xx *wl)
  410. {
  411. struct acx_beacon_broadcast bb;
  412. int ret;
  413. wl12xx_debug(DEBUG_ACX, "acx bcn dtim options");
  414. bb.header.id = ACX_BCN_DTIM_OPTIONS;
  415. bb.header.len = sizeof(bb) - sizeof(struct acx_header);
  416. bb.beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
  417. bb.broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
  418. bb.rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
  419. bb.ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
  420. ret = wl12xx_cmd_configure(wl, &bb, sizeof(bb));
  421. if (ret < 0) {
  422. wl12xx_warning("failed to set rx config: %d", ret);
  423. return ret;
  424. }
  425. return 0;
  426. }
  427. int wl12xx_acx_aid(struct wl12xx *wl, u16 aid)
  428. {
  429. struct acx_aid acx_aid;
  430. int ret;
  431. wl12xx_debug(DEBUG_ACX, "acx aid");
  432. acx_aid.header.id = ACX_AID;
  433. acx_aid.header.len = sizeof(acx_aid) - sizeof(struct acx_header);
  434. acx_aid.aid = aid;
  435. ret = wl12xx_cmd_configure(wl, &acx_aid, sizeof(acx_aid));
  436. if (ret < 0) {
  437. wl12xx_warning("failed to set aid: %d", ret);
  438. return ret;
  439. }
  440. return 0;
  441. }
  442. int wl12xx_acx_event_mbox_mask(struct wl12xx *wl, u32 event_mask)
  443. {
  444. struct acx_event_mask mask;
  445. int ret;
  446. wl12xx_debug(DEBUG_ACX, "acx event mbox mask");
  447. mask.header.id = ACX_EVENT_MBOX_MASK;
  448. mask.header.len = sizeof(mask) - sizeof(struct acx_header);
  449. /* high event mask is unused */
  450. mask.high_event_mask = 0xffffffff;
  451. mask.event_mask = event_mask;
  452. ret = wl12xx_cmd_configure(wl, &mask, sizeof(mask));
  453. if (ret < 0) {
  454. wl12xx_warning("failed to set aid: %d", ret);
  455. return ret;
  456. }
  457. return 0;
  458. }
  459. int wl12xx_acx_set_preamble(struct wl12xx *wl, enum acx_preamble_type preamble)
  460. {
  461. struct acx_preamble ie;
  462. int ret;
  463. wl12xx_debug(DEBUG_ACX, "acx_set_preamble");
  464. memset(&ie, 0, sizeof(ie));
  465. ie.header.id = ACX_PREAMBLE_TYPE;
  466. ie.header.len = sizeof(ie) - sizeof(struct acx_header);
  467. ie.preamble = preamble;
  468. ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie));
  469. if (ret < 0) {
  470. wl12xx_warning("Setting of preamble failed: %d", ret);
  471. return ret;
  472. }
  473. return 0;
  474. }
  475. int wl12xx_acx_cts_protect(struct wl12xx *wl,
  476. enum acx_ctsprotect_type ctsprotect)
  477. {
  478. struct acx_ctsprotect ie;
  479. int ret;
  480. wl12xx_debug(DEBUG_ACX, "acx_set_ctsprotect");
  481. memset(&ie, 0, sizeof(ie));
  482. ie.header.id = ACX_CTS_PROTECTION;
  483. ie.header.len = sizeof(ie) - sizeof(struct acx_header);
  484. ie.ctsprotect = ctsprotect;
  485. ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie));
  486. if (ret < 0) {
  487. wl12xx_warning("Setting of ctsprotect failed: %d", ret);
  488. return ret;
  489. }
  490. return 0;
  491. }
  492. int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats)
  493. {
  494. struct wl12xx_command *answer;
  495. int ret;
  496. wl12xx_debug(DEBUG_ACX, "acx statistics");
  497. answer = kmalloc(sizeof(*answer), GFP_KERNEL);
  498. if (!answer) {
  499. wl12xx_warning("could not allocate memory for acx statistics");
  500. ret = -ENOMEM;
  501. goto out;
  502. }
  503. ret = wl12xx_cmd_interrogate(wl, ACX_STATISTICS, sizeof(*answer),
  504. answer);
  505. if (ret < 0) {
  506. wl12xx_warning("acx statistics failed: %d", ret);
  507. goto out;
  508. }
  509. memcpy(stats, answer->parameters, sizeof(*stats));
  510. out:
  511. kfree(answer);
  512. return ret;
  513. }