wl1271_acx.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  1. /*
  2. * This file is part of wl1271
  3. *
  4. * Copyright (C) 2008-2009 Nokia Corporation
  5. *
  6. * Contact: Luciano Coelho <luciano.coelho@nokia.com>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * version 2 as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA
  21. *
  22. */
  23. #include "wl1271_acx.h"
  24. #include <linux/module.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/crc7.h>
  27. #include <linux/spi/spi.h>
  28. #include "wl1271.h"
  29. #include "wl12xx_80211.h"
  30. #include "wl1271_reg.h"
  31. #include "wl1271_spi.h"
  32. #include "wl1271_ps.h"
  33. int wl1271_acx_wake_up_conditions(struct wl1271 *wl)
  34. {
  35. struct acx_wake_up_condition *wake_up;
  36. int ret;
  37. wl1271_debug(DEBUG_ACX, "acx wake up conditions");
  38. wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
  39. if (!wake_up) {
  40. ret = -ENOMEM;
  41. goto out;
  42. }
  43. wake_up->wake_up_event = wl->conf.conn.wake_up_event;
  44. wake_up->listen_interval = wl->conf.conn.listen_interval;
  45. ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
  46. wake_up, sizeof(*wake_up));
  47. if (ret < 0) {
  48. wl1271_warning("could not set wake up conditions: %d", ret);
  49. goto out;
  50. }
  51. out:
  52. kfree(wake_up);
  53. return ret;
  54. }
  55. int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
  56. {
  57. struct acx_sleep_auth *auth;
  58. int ret;
  59. wl1271_debug(DEBUG_ACX, "acx sleep auth");
  60. auth = kzalloc(sizeof(*auth), GFP_KERNEL);
  61. if (!auth) {
  62. ret = -ENOMEM;
  63. goto out;
  64. }
  65. auth->sleep_auth = sleep_auth;
  66. ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
  67. if (ret < 0)
  68. return ret;
  69. out:
  70. kfree(auth);
  71. return ret;
  72. }
  73. int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len)
  74. {
  75. struct acx_revision *rev;
  76. int ret;
  77. wl1271_debug(DEBUG_ACX, "acx fw rev");
  78. rev = kzalloc(sizeof(*rev), GFP_KERNEL);
  79. if (!rev) {
  80. ret = -ENOMEM;
  81. goto out;
  82. }
  83. ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
  84. if (ret < 0) {
  85. wl1271_warning("ACX_FW_REV interrogate failed");
  86. goto out;
  87. }
  88. /* be careful with the buffer sizes */
  89. strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
  90. /*
  91. * if the firmware version string is exactly
  92. * sizeof(rev->fw_version) long or fw_len is less than
  93. * sizeof(rev->fw_version) it won't be null terminated
  94. */
  95. buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
  96. out:
  97. kfree(rev);
  98. return ret;
  99. }
  100. int wl1271_acx_tx_power(struct wl1271 *wl, int power)
  101. {
  102. struct acx_current_tx_power *acx;
  103. int ret;
  104. wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
  105. if (power < 0 || power > 25)
  106. return -EINVAL;
  107. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  108. if (!acx) {
  109. ret = -ENOMEM;
  110. goto out;
  111. }
  112. /*
  113. * FIXME: This is a workaround needed while we don't the correct
  114. * calibration, to avoid distortions
  115. */
  116. /* acx->current_tx_power = power * 10; */
  117. acx->current_tx_power = 120;
  118. ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
  119. if (ret < 0) {
  120. wl1271_warning("configure of tx power failed: %d", ret);
  121. goto out;
  122. }
  123. out:
  124. kfree(acx);
  125. return ret;
  126. }
  127. int wl1271_acx_feature_cfg(struct wl1271 *wl)
  128. {
  129. struct acx_feature_config *feature;
  130. int ret;
  131. wl1271_debug(DEBUG_ACX, "acx feature cfg");
  132. feature = kzalloc(sizeof(*feature), GFP_KERNEL);
  133. if (!feature) {
  134. ret = -ENOMEM;
  135. goto out;
  136. }
  137. /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
  138. feature->data_flow_options = 0;
  139. feature->options = 0;
  140. ret = wl1271_cmd_configure(wl, ACX_FEATURE_CFG,
  141. feature, sizeof(*feature));
  142. if (ret < 0) {
  143. wl1271_error("Couldnt set HW encryption");
  144. goto out;
  145. }
  146. out:
  147. kfree(feature);
  148. return ret;
  149. }
  150. int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map,
  151. size_t len)
  152. {
  153. int ret;
  154. wl1271_debug(DEBUG_ACX, "acx mem map");
  155. ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
  156. if (ret < 0)
  157. return ret;
  158. return 0;
  159. }
  160. int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl)
  161. {
  162. struct acx_rx_msdu_lifetime *acx;
  163. int ret;
  164. wl1271_debug(DEBUG_ACX, "acx rx msdu life time");
  165. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  166. if (!acx) {
  167. ret = -ENOMEM;
  168. goto out;
  169. }
  170. acx->lifetime = cpu_to_le32(wl->conf.rx.rx_msdu_life_time);
  171. ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
  172. acx, sizeof(*acx));
  173. if (ret < 0) {
  174. wl1271_warning("failed to set rx msdu life time: %d", ret);
  175. goto out;
  176. }
  177. out:
  178. kfree(acx);
  179. return ret;
  180. }
  181. int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter)
  182. {
  183. struct acx_rx_config *rx_config;
  184. int ret;
  185. wl1271_debug(DEBUG_ACX, "acx rx config");
  186. rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
  187. if (!rx_config) {
  188. ret = -ENOMEM;
  189. goto out;
  190. }
  191. rx_config->config_options = cpu_to_le32(config);
  192. rx_config->filter_options = cpu_to_le32(filter);
  193. ret = wl1271_cmd_configure(wl, ACX_RX_CFG,
  194. rx_config, sizeof(*rx_config));
  195. if (ret < 0) {
  196. wl1271_warning("failed to set rx config: %d", ret);
  197. goto out;
  198. }
  199. out:
  200. kfree(rx_config);
  201. return ret;
  202. }
  203. int wl1271_acx_pd_threshold(struct wl1271 *wl)
  204. {
  205. struct acx_packet_detection *pd;
  206. int ret;
  207. wl1271_debug(DEBUG_ACX, "acx data pd threshold");
  208. pd = kzalloc(sizeof(*pd), GFP_KERNEL);
  209. if (!pd) {
  210. ret = -ENOMEM;
  211. goto out;
  212. }
  213. pd->threshold = cpu_to_le32(wl->conf.rx.packet_detection_threshold);
  214. ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
  215. if (ret < 0) {
  216. wl1271_warning("failed to set pd threshold: %d", ret);
  217. goto out;
  218. }
  219. out:
  220. kfree(pd);
  221. return 0;
  222. }
  223. int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
  224. {
  225. struct acx_slot *slot;
  226. int ret;
  227. wl1271_debug(DEBUG_ACX, "acx slot");
  228. slot = kzalloc(sizeof(*slot), GFP_KERNEL);
  229. if (!slot) {
  230. ret = -ENOMEM;
  231. goto out;
  232. }
  233. slot->wone_index = STATION_WONE_INDEX;
  234. slot->slot_time = slot_time;
  235. ret = wl1271_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
  236. if (ret < 0) {
  237. wl1271_warning("failed to set slot time: %d", ret);
  238. goto out;
  239. }
  240. out:
  241. kfree(slot);
  242. return ret;
  243. }
  244. int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
  245. void *mc_list, u32 mc_list_len)
  246. {
  247. struct acx_dot11_grp_addr_tbl *acx;
  248. int ret;
  249. wl1271_debug(DEBUG_ACX, "acx group address tbl");
  250. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  251. if (!acx) {
  252. ret = -ENOMEM;
  253. goto out;
  254. }
  255. /* MAC filtering */
  256. acx->enabled = enable;
  257. acx->num_groups = mc_list_len;
  258. memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
  259. ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
  260. acx, sizeof(*acx));
  261. if (ret < 0) {
  262. wl1271_warning("failed to set group addr table: %d", ret);
  263. goto out;
  264. }
  265. out:
  266. kfree(acx);
  267. return ret;
  268. }
  269. int wl1271_acx_service_period_timeout(struct wl1271 *wl)
  270. {
  271. struct acx_rx_timeout *rx_timeout;
  272. int ret;
  273. rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
  274. if (!rx_timeout) {
  275. ret = -ENOMEM;
  276. goto out;
  277. }
  278. wl1271_debug(DEBUG_ACX, "acx service period timeout");
  279. rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout);
  280. rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout);
  281. ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
  282. rx_timeout, sizeof(*rx_timeout));
  283. if (ret < 0) {
  284. wl1271_warning("failed to set service period timeout: %d",
  285. ret);
  286. goto out;
  287. }
  288. out:
  289. kfree(rx_timeout);
  290. return ret;
  291. }
  292. int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold)
  293. {
  294. struct acx_rts_threshold *rts;
  295. int ret;
  296. wl1271_debug(DEBUG_ACX, "acx rts threshold");
  297. rts = kzalloc(sizeof(*rts), GFP_KERNEL);
  298. if (!rts) {
  299. ret = -ENOMEM;
  300. goto out;
  301. }
  302. rts->threshold = cpu_to_le16(rts_threshold);
  303. ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
  304. if (ret < 0) {
  305. wl1271_warning("failed to set rts threshold: %d", ret);
  306. goto out;
  307. }
  308. out:
  309. kfree(rts);
  310. return ret;
  311. }
  312. int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
  313. {
  314. struct acx_beacon_filter_option *beacon_filter = NULL;
  315. int ret = 0;
  316. wl1271_debug(DEBUG_ACX, "acx beacon filter opt");
  317. if (enable_filter &&
  318. wl->conf.conn.bcn_filt_mode == CONF_BCN_FILT_MODE_DISABLED)
  319. goto out;
  320. beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
  321. if (!beacon_filter) {
  322. ret = -ENOMEM;
  323. goto out;
  324. }
  325. beacon_filter->enable = enable_filter;
  326. /*
  327. * When set to zero, and the filter is enabled, beacons
  328. * without the unicast TIM bit set are dropped.
  329. */
  330. beacon_filter->max_num_beacons = 0;
  331. ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
  332. beacon_filter, sizeof(*beacon_filter));
  333. if (ret < 0) {
  334. wl1271_warning("failed to set beacon filter opt: %d", ret);
  335. goto out;
  336. }
  337. out:
  338. kfree(beacon_filter);
  339. return ret;
  340. }
  341. int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
  342. {
  343. struct acx_beacon_filter_ie_table *ie_table;
  344. int i, idx = 0;
  345. int ret;
  346. bool vendor_spec = false;
  347. wl1271_debug(DEBUG_ACX, "acx beacon filter table");
  348. ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
  349. if (!ie_table) {
  350. ret = -ENOMEM;
  351. goto out;
  352. }
  353. /* configure default beacon pass-through rules */
  354. ie_table->num_ie = 0;
  355. for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) {
  356. struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]);
  357. ie_table->table[idx++] = r->ie;
  358. ie_table->table[idx++] = r->rule;
  359. if (r->ie == WLAN_EID_VENDOR_SPECIFIC) {
  360. /* only one vendor specific ie allowed */
  361. if (vendor_spec)
  362. continue;
  363. /* for vendor specific rules configure the
  364. additional fields */
  365. memcpy(&(ie_table->table[idx]), r->oui,
  366. CONF_BCN_IE_OUI_LEN);
  367. idx += CONF_BCN_IE_OUI_LEN;
  368. ie_table->table[idx++] = r->type;
  369. memcpy(&(ie_table->table[idx]), r->version,
  370. CONF_BCN_IE_VER_LEN);
  371. idx += CONF_BCN_IE_VER_LEN;
  372. vendor_spec = true;
  373. }
  374. ie_table->num_ie++;
  375. }
  376. ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
  377. ie_table, sizeof(*ie_table));
  378. if (ret < 0) {
  379. wl1271_warning("failed to set beacon filter table: %d", ret);
  380. goto out;
  381. }
  382. out:
  383. kfree(ie_table);
  384. return ret;
  385. }
  386. int wl1271_acx_conn_monit_params(struct wl1271 *wl)
  387. {
  388. struct acx_conn_monit_params *acx;
  389. int ret;
  390. wl1271_debug(DEBUG_ACX, "acx connection monitor parameters");
  391. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  392. if (!acx) {
  393. ret = -ENOMEM;
  394. goto out;
  395. }
  396. acx->synch_fail_thold = cpu_to_le32(wl->conf.conn.synch_fail_thold);
  397. acx->bss_lose_timeout = cpu_to_le32(wl->conf.conn.bss_lose_timeout);
  398. ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
  399. acx, sizeof(*acx));
  400. if (ret < 0) {
  401. wl1271_warning("failed to set connection monitor "
  402. "parameters: %d", ret);
  403. goto out;
  404. }
  405. out:
  406. kfree(acx);
  407. return ret;
  408. }
  409. int wl1271_acx_sg_enable(struct wl1271 *wl)
  410. {
  411. struct acx_bt_wlan_coex *pta;
  412. int ret;
  413. wl1271_debug(DEBUG_ACX, "acx sg enable");
  414. pta = kzalloc(sizeof(*pta), GFP_KERNEL);
  415. if (!pta) {
  416. ret = -ENOMEM;
  417. goto out;
  418. }
  419. pta->enable = SG_ENABLE;
  420. ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
  421. if (ret < 0) {
  422. wl1271_warning("failed to set softgemini enable: %d", ret);
  423. goto out;
  424. }
  425. out:
  426. kfree(pta);
  427. return ret;
  428. }
  429. int wl1271_acx_sg_cfg(struct wl1271 *wl)
  430. {
  431. struct acx_bt_wlan_coex_param *param;
  432. struct conf_sg_settings *c = &wl->conf.sg;
  433. int ret;
  434. wl1271_debug(DEBUG_ACX, "acx sg cfg");
  435. param = kzalloc(sizeof(*param), GFP_KERNEL);
  436. if (!param) {
  437. ret = -ENOMEM;
  438. goto out;
  439. }
  440. /* BT-WLAN coext parameters */
  441. param->per_threshold = cpu_to_le32(c->per_threshold);
  442. param->max_scan_compensation_time =
  443. cpu_to_le32(c->max_scan_compensation_time);
  444. param->nfs_sample_interval = cpu_to_le16(c->nfs_sample_interval);
  445. param->load_ratio = c->load_ratio;
  446. param->auto_ps_mode = c->auto_ps_mode;
  447. param->probe_req_compensation = c->probe_req_compensation;
  448. param->scan_window_compensation = c->scan_window_compensation;
  449. param->antenna_config = c->antenna_config;
  450. param->beacon_miss_threshold = c->beacon_miss_threshold;
  451. param->rate_adaptation_threshold =
  452. cpu_to_le32(c->rate_adaptation_threshold);
  453. param->rate_adaptation_snr = c->rate_adaptation_snr;
  454. ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
  455. if (ret < 0) {
  456. wl1271_warning("failed to set sg config: %d", ret);
  457. goto out;
  458. }
  459. out:
  460. kfree(param);
  461. return ret;
  462. }
  463. int wl1271_acx_cca_threshold(struct wl1271 *wl)
  464. {
  465. struct acx_energy_detection *detection;
  466. int ret;
  467. wl1271_debug(DEBUG_ACX, "acx cca threshold");
  468. detection = kzalloc(sizeof(*detection), GFP_KERNEL);
  469. if (!detection) {
  470. ret = -ENOMEM;
  471. goto out;
  472. }
  473. detection->rx_cca_threshold = cpu_to_le16(wl->conf.rx.rx_cca_threshold);
  474. detection->tx_energy_detection = wl->conf.tx.tx_energy_detection;
  475. ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD,
  476. detection, sizeof(*detection));
  477. if (ret < 0) {
  478. wl1271_warning("failed to set cca threshold: %d", ret);
  479. return ret;
  480. }
  481. out:
  482. kfree(detection);
  483. return ret;
  484. }
  485. int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
  486. {
  487. struct acx_beacon_broadcast *bb;
  488. int ret;
  489. wl1271_debug(DEBUG_ACX, "acx bcn dtim options");
  490. bb = kzalloc(sizeof(*bb), GFP_KERNEL);
  491. if (!bb) {
  492. ret = -ENOMEM;
  493. goto out;
  494. }
  495. bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout);
  496. bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout);
  497. bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps;
  498. bb->ps_poll_threshold = wl->conf.conn.ps_poll_threshold;
  499. ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
  500. if (ret < 0) {
  501. wl1271_warning("failed to set rx config: %d", ret);
  502. goto out;
  503. }
  504. out:
  505. kfree(bb);
  506. return ret;
  507. }
  508. int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
  509. {
  510. struct acx_aid *acx_aid;
  511. int ret;
  512. wl1271_debug(DEBUG_ACX, "acx aid");
  513. acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
  514. if (!acx_aid) {
  515. ret = -ENOMEM;
  516. goto out;
  517. }
  518. acx_aid->aid = cpu_to_le16(aid);
  519. ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
  520. if (ret < 0) {
  521. wl1271_warning("failed to set aid: %d", ret);
  522. goto out;
  523. }
  524. out:
  525. kfree(acx_aid);
  526. return ret;
  527. }
  528. int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask)
  529. {
  530. struct acx_event_mask *mask;
  531. int ret;
  532. wl1271_debug(DEBUG_ACX, "acx event mbox mask");
  533. mask = kzalloc(sizeof(*mask), GFP_KERNEL);
  534. if (!mask) {
  535. ret = -ENOMEM;
  536. goto out;
  537. }
  538. /* high event mask is unused */
  539. mask->high_event_mask = cpu_to_le32(0xffffffff);
  540. mask->event_mask = cpu_to_le32(event_mask);
  541. ret = wl1271_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
  542. mask, sizeof(*mask));
  543. if (ret < 0) {
  544. wl1271_warning("failed to set acx_event_mbox_mask: %d", ret);
  545. goto out;
  546. }
  547. out:
  548. kfree(mask);
  549. return ret;
  550. }
  551. int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
  552. {
  553. struct acx_preamble *acx;
  554. int ret;
  555. wl1271_debug(DEBUG_ACX, "acx_set_preamble");
  556. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  557. if (!acx) {
  558. ret = -ENOMEM;
  559. goto out;
  560. }
  561. acx->preamble = preamble;
  562. ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
  563. if (ret < 0) {
  564. wl1271_warning("Setting of preamble failed: %d", ret);
  565. goto out;
  566. }
  567. out:
  568. kfree(acx);
  569. return ret;
  570. }
  571. int wl1271_acx_cts_protect(struct wl1271 *wl,
  572. enum acx_ctsprotect_type ctsprotect)
  573. {
  574. struct acx_ctsprotect *acx;
  575. int ret;
  576. wl1271_debug(DEBUG_ACX, "acx_set_ctsprotect");
  577. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  578. if (!acx) {
  579. ret = -ENOMEM;
  580. goto out;
  581. }
  582. acx->ctsprotect = ctsprotect;
  583. ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
  584. if (ret < 0) {
  585. wl1271_warning("Setting of ctsprotect failed: %d", ret);
  586. goto out;
  587. }
  588. out:
  589. kfree(acx);
  590. return ret;
  591. }
  592. int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
  593. {
  594. int ret;
  595. wl1271_debug(DEBUG_ACX, "acx statistics");
  596. ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats,
  597. sizeof(*stats));
  598. if (ret < 0) {
  599. wl1271_warning("acx statistics failed: %d", ret);
  600. return -ENOMEM;
  601. }
  602. return 0;
  603. }
  604. int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates)
  605. {
  606. struct acx_rate_policy *acx;
  607. struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
  608. int ret = 0;
  609. wl1271_debug(DEBUG_ACX, "acx rate policies");
  610. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  611. if (!acx) {
  612. ret = -ENOMEM;
  613. goto out;
  614. }
  615. /* configure one default (one-size-fits-all) rate class */
  616. acx->rate_class_cnt = cpu_to_le32(1);
  617. acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates);
  618. acx->rate_class[0].short_retry_limit = c->short_retry_limit;
  619. acx->rate_class[0].long_retry_limit = c->long_retry_limit;
  620. acx->rate_class[0].aflags = c->aflags;
  621. ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
  622. if (ret < 0) {
  623. wl1271_warning("Setting of rate policies failed: %d", ret);
  624. goto out;
  625. }
  626. out:
  627. kfree(acx);
  628. return ret;
  629. }
  630. int wl1271_acx_ac_cfg(struct wl1271 *wl)
  631. {
  632. struct acx_ac_cfg *acx;
  633. int i, ret = 0;
  634. wl1271_debug(DEBUG_ACX, "acx access category config");
  635. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  636. if (!acx) {
  637. ret = -ENOMEM;
  638. goto out;
  639. }
  640. for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
  641. struct conf_tx_ac_category *c = &(wl->conf.tx.ac_conf[i]);
  642. acx->ac = c->ac;
  643. acx->cw_min = c->cw_min;
  644. acx->cw_max = cpu_to_le16(c->cw_max);
  645. acx->aifsn = c->aifsn;
  646. acx->reserved = 0;
  647. acx->tx_op_limit = cpu_to_le16(c->tx_op_limit);
  648. ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
  649. if (ret < 0) {
  650. wl1271_warning("Setting of access category "
  651. "config: %d", ret);
  652. goto out;
  653. }
  654. }
  655. out:
  656. kfree(acx);
  657. return ret;
  658. }
  659. int wl1271_acx_tid_cfg(struct wl1271 *wl)
  660. {
  661. struct acx_tid_config *acx;
  662. int i, ret = 0;
  663. wl1271_debug(DEBUG_ACX, "acx tid config");
  664. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  665. if (!acx) {
  666. ret = -ENOMEM;
  667. goto out;
  668. }
  669. for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
  670. struct conf_tx_tid *c = &(wl->conf.tx.tid_conf[i]);
  671. acx->queue_id = c->queue_id;
  672. acx->channel_type = c->channel_type;
  673. acx->tsid = c->tsid;
  674. acx->ps_scheme = c->ps_scheme;
  675. acx->ack_policy = c->ack_policy;
  676. acx->apsd_conf[0] = cpu_to_le32(c->apsd_conf[0]);
  677. acx->apsd_conf[1] = cpu_to_le32(c->apsd_conf[1]);
  678. ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
  679. if (ret < 0) {
  680. wl1271_warning("Setting of tid config failed: %d", ret);
  681. goto out;
  682. }
  683. }
  684. out:
  685. kfree(acx);
  686. return ret;
  687. }
  688. int wl1271_acx_frag_threshold(struct wl1271 *wl)
  689. {
  690. struct acx_frag_threshold *acx;
  691. int ret = 0;
  692. wl1271_debug(DEBUG_ACX, "acx frag threshold");
  693. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  694. if (!acx) {
  695. ret = -ENOMEM;
  696. goto out;
  697. }
  698. acx->frag_threshold = cpu_to_le16(wl->conf.tx.frag_threshold);
  699. ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx));
  700. if (ret < 0) {
  701. wl1271_warning("Setting of frag threshold failed: %d", ret);
  702. goto out;
  703. }
  704. out:
  705. kfree(acx);
  706. return ret;
  707. }
  708. int wl1271_acx_tx_config_options(struct wl1271 *wl)
  709. {
  710. struct acx_tx_config_options *acx;
  711. int ret = 0;
  712. wl1271_debug(DEBUG_ACX, "acx tx config options");
  713. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  714. if (!acx) {
  715. ret = -ENOMEM;
  716. goto out;
  717. }
  718. acx->tx_compl_timeout = cpu_to_le16(wl->conf.tx.tx_compl_timeout);
  719. acx->tx_compl_threshold = cpu_to_le16(wl->conf.tx.tx_compl_threshold);
  720. ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx));
  721. if (ret < 0) {
  722. wl1271_warning("Setting of tx options failed: %d", ret);
  723. goto out;
  724. }
  725. out:
  726. kfree(acx);
  727. return ret;
  728. }
  729. int wl1271_acx_mem_cfg(struct wl1271 *wl)
  730. {
  731. struct wl1271_acx_config_memory *mem_conf;
  732. int ret;
  733. wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
  734. mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
  735. if (!mem_conf) {
  736. ret = -ENOMEM;
  737. goto out;
  738. }
  739. /* memory config */
  740. mem_conf->num_stations = DEFAULT_NUM_STATIONS;
  741. mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
  742. mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
  743. mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
  744. mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
  745. ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
  746. sizeof(*mem_conf));
  747. if (ret < 0) {
  748. wl1271_warning("wl1271 mem config failed: %d", ret);
  749. goto out;
  750. }
  751. out:
  752. kfree(mem_conf);
  753. return ret;
  754. }
  755. int wl1271_acx_init_mem_config(struct wl1271 *wl)
  756. {
  757. int ret;
  758. ret = wl1271_acx_mem_cfg(wl);
  759. if (ret < 0)
  760. return ret;
  761. wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map),
  762. GFP_KERNEL);
  763. if (!wl->target_mem_map) {
  764. wl1271_error("couldn't allocate target memory map");
  765. return -ENOMEM;
  766. }
  767. /* we now ask for the firmware built memory map */
  768. ret = wl1271_acx_mem_map(wl, (void *)wl->target_mem_map,
  769. sizeof(struct wl1271_acx_mem_map));
  770. if (ret < 0) {
  771. wl1271_error("couldn't retrieve firmware memory map");
  772. kfree(wl->target_mem_map);
  773. wl->target_mem_map = NULL;
  774. return ret;
  775. }
  776. /* initialize TX block book keeping */
  777. wl->tx_blocks_available =
  778. le32_to_cpu(wl->target_mem_map->num_tx_mem_blocks);
  779. wl1271_debug(DEBUG_TX, "available tx blocks: %d",
  780. wl->tx_blocks_available);
  781. return 0;
  782. }
  783. int wl1271_acx_init_rx_interrupt(struct wl1271 *wl)
  784. {
  785. struct wl1271_acx_rx_config_opt *rx_conf;
  786. int ret;
  787. wl1271_debug(DEBUG_ACX, "wl1271 rx interrupt config");
  788. rx_conf = kzalloc(sizeof(*rx_conf), GFP_KERNEL);
  789. if (!rx_conf) {
  790. ret = -ENOMEM;
  791. goto out;
  792. }
  793. rx_conf->threshold = cpu_to_le16(wl->conf.rx.irq_pkt_threshold);
  794. rx_conf->timeout = cpu_to_le16(wl->conf.rx.irq_timeout);
  795. rx_conf->mblk_threshold = cpu_to_le16(wl->conf.rx.irq_blk_threshold);
  796. rx_conf->queue_type = wl->conf.rx.queue_type;
  797. ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf,
  798. sizeof(*rx_conf));
  799. if (ret < 0) {
  800. wl1271_warning("wl1271 rx config opt failed: %d", ret);
  801. goto out;
  802. }
  803. out:
  804. kfree(rx_conf);
  805. return ret;
  806. }
  807. int wl1271_acx_smart_reflex(struct wl1271 *wl)
  808. {
  809. struct acx_smart_reflex_state *sr_state = NULL;
  810. struct acx_smart_reflex_config_params *sr_param = NULL;
  811. int i, ret;
  812. wl1271_debug(DEBUG_ACX, "acx smart reflex");
  813. sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL);
  814. if (!sr_param) {
  815. ret = -ENOMEM;
  816. goto out;
  817. }
  818. for (i = 0; i < CONF_SR_ERR_TBL_COUNT; i++) {
  819. struct conf_mart_reflex_err_table *e =
  820. &(wl->conf.init.sr_err_tbl[i]);
  821. sr_param->error_table[i].len = e->len;
  822. sr_param->error_table[i].upper_limit = e->upper_limit;
  823. memcpy(sr_param->error_table[i].values, e->values, e->len);
  824. }
  825. ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS,
  826. sr_param, sizeof(*sr_param));
  827. if (ret < 0) {
  828. wl1271_warning("failed to set smart reflex params: %d", ret);
  829. goto out;
  830. }
  831. sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL);
  832. if (!sr_state) {
  833. ret = -ENOMEM;
  834. goto out;
  835. }
  836. /* enable smart reflex */
  837. sr_state->enable = wl->conf.init.sr_enable;
  838. ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE,
  839. sr_state, sizeof(*sr_state));
  840. if (ret < 0) {
  841. wl1271_warning("failed to set smart reflex params: %d", ret);
  842. goto out;
  843. }
  844. out:
  845. kfree(sr_state);
  846. kfree(sr_param);
  847. return ret;
  848. }
  849. int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
  850. {
  851. struct wl1271_acx_bet_enable *acx = NULL;
  852. int ret = 0;
  853. wl1271_debug(DEBUG_ACX, "acx bet enable");
  854. if (enable && wl->conf.conn.bet_enable == CONF_BET_MODE_DISABLE)
  855. goto out;
  856. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  857. if (!acx) {
  858. ret = -ENOMEM;
  859. goto out;
  860. }
  861. acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE;
  862. acx->max_consecutive = wl->conf.conn.bet_max_consecutive;
  863. ret = wl1271_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
  864. if (ret < 0) {
  865. wl1271_warning("acx bet enable failed: %d", ret);
  866. goto out;
  867. }
  868. out:
  869. kfree(acx);
  870. return ret;
  871. }
  872. int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
  873. u8 version)
  874. {
  875. struct wl1271_acx_arp_filter *acx;
  876. int ret;
  877. wl1271_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
  878. acx = kzalloc(sizeof(*acx), GFP_KERNEL);
  879. if (!acx) {
  880. ret = -ENOMEM;
  881. goto out;
  882. }
  883. acx->version = version;
  884. acx->enable = enable;
  885. if (enable == true) {
  886. if (version == ACX_IPV4_VERSION)
  887. memcpy(acx->address, address, ACX_IPV4_ADDR_SIZE);
  888. else if (version == ACX_IPV6_VERSION)
  889. memcpy(acx->address, address, sizeof(acx->address));
  890. else
  891. wl1271_error("Invalid IP version");
  892. }
  893. ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER,
  894. acx, sizeof(*acx));
  895. if (ret < 0) {
  896. wl1271_warning("failed to set arp ip filter: %d", ret);
  897. goto out;
  898. }
  899. out:
  900. kfree(acx);
  901. return ret;
  902. }