iwl-sv-open.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. /******************************************************************************
  2. *
  3. * This file is provided under a dual BSD/GPLv2 license. When using or
  4. * redistributing this file, you may do so under either license.
  5. *
  6. * GPL LICENSE SUMMARY
  7. *
  8. * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved.
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of version 2 of the GNU General Public License as
  12. * published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  22. * USA
  23. *
  24. * The full GNU General Public License is included in this distribution
  25. * in the file called LICENSE.GPL.
  26. *
  27. * Contact Information:
  28. * Intel Linux Wireless <ilw@linux.intel.com>
  29. * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  30. *
  31. * BSD LICENSE
  32. *
  33. * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved.
  34. * All rights reserved.
  35. *
  36. * Redistribution and use in source and binary forms, with or without
  37. * modification, are permitted provided that the following conditions
  38. * are met:
  39. *
  40. * * Redistributions of source code must retain the above copyright
  41. * notice, this list of conditions and the following disclaimer.
  42. * * Redistributions in binary form must reproduce the above copyright
  43. * notice, this list of conditions and the following disclaimer in
  44. * the documentation and/or other materials provided with the
  45. * distribution.
  46. * * Neither the name Intel Corporation nor the names of its
  47. * contributors may be used to endorse or promote products derived
  48. * from this software without specific prior written permission.
  49. *
  50. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  51. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  52. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  53. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  54. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  55. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  56. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  57. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  58. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  59. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  60. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  61. *
  62. *****************************************************************************/
  63. #include <linux/init.h>
  64. #include <linux/kernel.h>
  65. #include <linux/module.h>
  66. #include <linux/dma-mapping.h>
  67. #include <net/net_namespace.h>
  68. #include <linux/netdevice.h>
  69. #include <net/cfg80211.h>
  70. #include <net/mac80211.h>
  71. #include <net/netlink.h>
  72. #include "iwl-dev.h"
  73. #include "iwl-core.h"
  74. #include "iwl-debug.h"
  75. #include "iwl-io.h"
  76. #include "iwl-agn.h"
  77. #include "iwl-testmode.h"
  78. #include "iwl-trans.h"
  79. /* The TLVs used in the gnl message policy between the kernel module and
  80. * user space application. iwl_testmode_gnl_msg_policy is to be carried
  81. * through the NL80211_CMD_TESTMODE channel regulated by nl80211.
  82. * See iwl-testmode.h
  83. */
  84. static
  85. struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
  86. [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, },
  87. [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, },
  88. [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, },
  89. [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, },
  90. [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, },
  91. [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, },
  92. [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, },
  93. [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, },
  94. [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
  95. [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
  96. [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, },
  97. [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, },
  98. [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
  99. [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, },
  100. };
  101. /*
  102. * See the struct iwl_rx_packet in iwl-commands.h for the format of the
  103. * received events from the device
  104. */
  105. static inline int get_event_length(struct iwl_rx_mem_buffer *rxb)
  106. {
  107. struct iwl_rx_packet *pkt = rxb_addr(rxb);
  108. if (pkt)
  109. return le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
  110. else
  111. return 0;
  112. }
  113. /*
  114. * This function multicasts the spontaneous messages from the device to the
  115. * user space. It is invoked whenever there is a received messages
  116. * from the device. This function is called within the ISR of the rx handlers
  117. * in iwlagn driver.
  118. *
  119. * The parsing of the message content is left to the user space application,
  120. * The message content is treated as unattacked raw data and is encapsulated
  121. * with IWL_TM_ATTR_UCODE_RX_PKT multicasting to the user space.
  122. *
  123. * @priv: the instance of iwlwifi device
  124. * @rxb: pointer to rx data content received by the ISR
  125. *
  126. * See the message policies and TLVs in iwl_testmode_gnl_msg_policy[].
  127. * For the messages multicasting to the user application, the mandatory
  128. * TLV fields are :
  129. * IWL_TM_ATTR_COMMAND must be IWL_TM_CMD_DEV2APP_UCODE_RX_PKT
  130. * IWL_TM_ATTR_UCODE_RX_PKT for carrying the message content
  131. */
  132. static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
  133. struct iwl_rx_mem_buffer *rxb)
  134. {
  135. struct ieee80211_hw *hw = priv->hw;
  136. struct sk_buff *skb;
  137. void *data;
  138. int length;
  139. data = (void *)rxb_addr(rxb);
  140. length = get_event_length(rxb);
  141. if (!data || length == 0)
  142. return;
  143. skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length,
  144. GFP_ATOMIC);
  145. if (skb == NULL) {
  146. IWL_DEBUG_INFO(priv,
  147. "Run out of memory for messages to user space ?\n");
  148. return;
  149. }
  150. NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
  151. NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data);
  152. cfg80211_testmode_event(skb, GFP_ATOMIC);
  153. return;
  154. nla_put_failure:
  155. kfree_skb(skb);
  156. IWL_DEBUG_INFO(priv, "Ouch, overran buffer, check allocation!\n");
  157. }
  158. void iwl_testmode_init(struct iwl_priv *priv)
  159. {
  160. priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
  161. priv->testmode_trace.trace_enabled = false;
  162. }
  163. static void iwl_trace_cleanup(struct iwl_priv *priv)
  164. {
  165. if (priv->testmode_trace.trace_enabled) {
  166. if (priv->testmode_trace.cpu_addr &&
  167. priv->testmode_trace.dma_addr)
  168. dma_free_coherent(bus(priv)->dev,
  169. priv->testmode_trace.total_size,
  170. priv->testmode_trace.cpu_addr,
  171. priv->testmode_trace.dma_addr);
  172. priv->testmode_trace.trace_enabled = false;
  173. priv->testmode_trace.cpu_addr = NULL;
  174. priv->testmode_trace.trace_addr = NULL;
  175. priv->testmode_trace.dma_addr = 0;
  176. priv->testmode_trace.buff_size = 0;
  177. priv->testmode_trace.total_size = 0;
  178. }
  179. }
  180. void iwl_testmode_cleanup(struct iwl_priv *priv)
  181. {
  182. iwl_trace_cleanup(priv);
  183. }
  184. /*
  185. * This function handles the user application commands to the ucode.
  186. *
  187. * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_CMD_ID and
  188. * IWL_TM_ATTR_UCODE_CMD_DATA and calls to the handler to send the
  189. * host command to the ucode.
  190. *
  191. * If any mandatory field is missing, -ENOMSG is replied to the user space
  192. * application; otherwise, the actual execution result of the host command to
  193. * ucode is replied.
  194. *
  195. * @hw: ieee80211_hw object that represents the device
  196. * @tb: gnl message fields from the user space
  197. */
  198. static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
  199. {
  200. struct iwl_priv *priv = hw->priv;
  201. struct iwl_host_cmd cmd;
  202. memset(&cmd, 0, sizeof(struct iwl_host_cmd));
  203. if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] ||
  204. !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) {
  205. IWL_DEBUG_INFO(priv,
  206. "Error finding ucode command mandatory fields\n");
  207. return -ENOMSG;
  208. }
  209. cmd.flags = CMD_ON_DEMAND;
  210. cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
  211. cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
  212. cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
  213. cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
  214. IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
  215. " len %d\n", cmd.id, cmd.flags, cmd.len[0]);
  216. /* ok, let's submit the command to ucode */
  217. return iwl_trans_send_cmd(trans(priv), &cmd);
  218. }
  219. /*
  220. * This function handles the user application commands for register access.
  221. *
  222. * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
  223. * handlers respectively.
  224. *
  225. * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the
  226. * mandatory fields(IWL_TM_ATTR_REG_OFFSET,IWL_TM_ATTR_REG_VALUE32,
  227. * IWL_TM_ATTR_REG_VALUE8) are missing; Otherwise 0 is replied indicating
  228. * the success of the command execution.
  229. *
  230. * If IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_READ32, the register read
  231. * value is returned with IWL_TM_ATTR_REG_VALUE32.
  232. *
  233. * @hw: ieee80211_hw object that represents the device
  234. * @tb: gnl message fields from the user space
  235. */
  236. static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
  237. {
  238. struct iwl_priv *priv = hw->priv;
  239. u32 ofs, val32;
  240. u8 val8;
  241. struct sk_buff *skb;
  242. int status = 0;
  243. if (!tb[IWL_TM_ATTR_REG_OFFSET]) {
  244. IWL_DEBUG_INFO(priv, "Error finding register offset\n");
  245. return -ENOMSG;
  246. }
  247. ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]);
  248. IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs);
  249. switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
  250. case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
  251. val32 = iwl_read32(bus(priv), ofs);
  252. IWL_INFO(priv, "32bit value to read 0x%x\n", val32);
  253. skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
  254. if (!skb) {
  255. IWL_DEBUG_INFO(priv, "Error allocating memory\n");
  256. return -ENOMEM;
  257. }
  258. NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32);
  259. status = cfg80211_testmode_reply(skb);
  260. if (status < 0)
  261. IWL_DEBUG_INFO(priv,
  262. "Error sending msg : %d\n", status);
  263. break;
  264. case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
  265. if (!tb[IWL_TM_ATTR_REG_VALUE32]) {
  266. IWL_DEBUG_INFO(priv,
  267. "Error finding value to write\n");
  268. return -ENOMSG;
  269. } else {
  270. val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
  271. IWL_INFO(priv, "32bit value to write 0x%x\n", val32);
  272. iwl_write32(bus(priv), ofs, val32);
  273. }
  274. break;
  275. case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
  276. if (!tb[IWL_TM_ATTR_REG_VALUE8]) {
  277. IWL_DEBUG_INFO(priv, "Error finding value to write\n");
  278. return -ENOMSG;
  279. } else {
  280. val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]);
  281. IWL_INFO(priv, "8bit value to write 0x%x\n", val8);
  282. iwl_write8(bus(priv), ofs, val8);
  283. }
  284. break;
  285. case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32:
  286. val32 = iwl_read_prph(bus(priv), ofs);
  287. IWL_INFO(priv, "32bit value to read 0x%x\n", val32);
  288. skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
  289. if (!skb) {
  290. IWL_DEBUG_INFO(priv, "Error allocating memory\n");
  291. return -ENOMEM;
  292. }
  293. NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32);
  294. status = cfg80211_testmode_reply(skb);
  295. if (status < 0)
  296. IWL_DEBUG_INFO(priv,
  297. "Error sending msg : %d\n", status);
  298. break;
  299. case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32:
  300. if (!tb[IWL_TM_ATTR_REG_VALUE32]) {
  301. IWL_DEBUG_INFO(priv,
  302. "Error finding value to write\n");
  303. return -ENOMSG;
  304. } else {
  305. val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
  306. IWL_INFO(priv, "32bit value to write 0x%x\n", val32);
  307. iwl_write_prph(bus(priv), ofs, val32);
  308. }
  309. break;
  310. default:
  311. IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n");
  312. return -ENOSYS;
  313. }
  314. return status;
  315. nla_put_failure:
  316. kfree_skb(skb);
  317. return -EMSGSIZE;
  318. }
  319. static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
  320. {
  321. struct iwl_notification_wait calib_wait;
  322. int ret;
  323. iwlagn_init_notification_wait(priv, &calib_wait,
  324. CALIBRATION_COMPLETE_NOTIFICATION,
  325. NULL, NULL);
  326. ret = iwlagn_init_alive_start(priv);
  327. if (ret) {
  328. IWL_DEBUG_INFO(priv,
  329. "Error configuring init calibration: %d\n", ret);
  330. goto cfg_init_calib_error;
  331. }
  332. ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ);
  333. if (ret)
  334. IWL_DEBUG_INFO(priv, "Error detecting"
  335. " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
  336. return ret;
  337. cfg_init_calib_error:
  338. iwlagn_remove_notification(priv, &calib_wait);
  339. return ret;
  340. }
  341. /*
  342. * This function handles the user application commands for driver.
  343. *
  344. * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
  345. * handlers respectively.
  346. *
  347. * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
  348. * value of the actual command execution is replied to the user application.
  349. *
  350. * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP
  351. * is used for carry the message while IWL_TM_ATTR_COMMAND must set to
  352. * IWL_TM_CMD_DEV2APP_SYNC_RSP.
  353. *
  354. * @hw: ieee80211_hw object that represents the device
  355. * @tb: gnl message fields from the user space
  356. */
  357. static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
  358. {
  359. struct iwl_priv *priv = hw->priv;
  360. struct sk_buff *skb;
  361. unsigned char *rsp_data_ptr = NULL;
  362. int status = 0, rsp_data_len = 0;
  363. switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
  364. case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
  365. rsp_data_ptr = (unsigned char *)priv->cfg->name;
  366. rsp_data_len = strlen(priv->cfg->name);
  367. skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
  368. rsp_data_len + 20);
  369. if (!skb) {
  370. IWL_DEBUG_INFO(priv,
  371. "Error allocating memory\n");
  372. return -ENOMEM;
  373. }
  374. NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
  375. IWL_TM_CMD_DEV2APP_SYNC_RSP);
  376. NLA_PUT(skb, IWL_TM_ATTR_SYNC_RSP,
  377. rsp_data_len, rsp_data_ptr);
  378. status = cfg80211_testmode_reply(skb);
  379. if (status < 0)
  380. IWL_DEBUG_INFO(priv, "Error sending msg : %d\n",
  381. status);
  382. break;
  383. case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
  384. status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
  385. if (status)
  386. IWL_DEBUG_INFO(priv,
  387. "Error loading init ucode: %d\n", status);
  388. break;
  389. case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
  390. iwl_testmode_cfg_init_calib(priv);
  391. iwl_trans_stop_device(trans(priv));
  392. break;
  393. case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
  394. status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
  395. if (status) {
  396. IWL_DEBUG_INFO(priv,
  397. "Error loading runtime ucode: %d\n", status);
  398. break;
  399. }
  400. status = iwl_alive_start(priv);
  401. if (status)
  402. IWL_DEBUG_INFO(priv,
  403. "Error starting the device: %d\n", status);
  404. break;
  405. case IWL_TM_CMD_APP2DEV_GET_EEPROM:
  406. if (priv->eeprom) {
  407. skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
  408. priv->cfg->base_params->eeprom_size + 20);
  409. if (!skb) {
  410. IWL_DEBUG_INFO(priv,
  411. "Error allocating memory\n");
  412. return -ENOMEM;
  413. }
  414. NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
  415. IWL_TM_CMD_DEV2APP_EEPROM_RSP);
  416. NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
  417. priv->cfg->base_params->eeprom_size,
  418. priv->eeprom);
  419. status = cfg80211_testmode_reply(skb);
  420. if (status < 0)
  421. IWL_DEBUG_INFO(priv,
  422. "Error sending msg : %d\n",
  423. status);
  424. } else
  425. return -EFAULT;
  426. break;
  427. case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
  428. if (!tb[IWL_TM_ATTR_FIXRATE]) {
  429. IWL_DEBUG_INFO(priv,
  430. "Error finding fixrate setting\n");
  431. return -ENOMSG;
  432. }
  433. priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
  434. break;
  435. default:
  436. IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n");
  437. return -ENOSYS;
  438. }
  439. return status;
  440. nla_put_failure:
  441. kfree_skb(skb);
  442. return -EMSGSIZE;
  443. }
  444. /*
  445. * This function handles the user application commands for uCode trace
  446. *
  447. * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
  448. * handlers respectively.
  449. *
  450. * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
  451. * value of the actual command execution is replied to the user application.
  452. *
  453. * @hw: ieee80211_hw object that represents the device
  454. * @tb: gnl message fields from the user space
  455. */
  456. static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
  457. {
  458. struct iwl_priv *priv = hw->priv;
  459. struct sk_buff *skb;
  460. int status = 0;
  461. struct device *dev = bus(priv)->dev;
  462. switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
  463. case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
  464. if (priv->testmode_trace.trace_enabled)
  465. return -EBUSY;
  466. if (!tb[IWL_TM_ATTR_TRACE_SIZE])
  467. priv->testmode_trace.buff_size = TRACE_BUFF_SIZE_DEF;
  468. else
  469. priv->testmode_trace.buff_size =
  470. nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]);
  471. if (!priv->testmode_trace.buff_size)
  472. return -EINVAL;
  473. if (priv->testmode_trace.buff_size < TRACE_BUFF_SIZE_MIN ||
  474. priv->testmode_trace.buff_size > TRACE_BUFF_SIZE_MAX)
  475. return -EINVAL;
  476. priv->testmode_trace.total_size =
  477. priv->testmode_trace.buff_size + TRACE_BUFF_PADD;
  478. priv->testmode_trace.cpu_addr =
  479. dma_alloc_coherent(dev,
  480. priv->testmode_trace.total_size,
  481. &priv->testmode_trace.dma_addr,
  482. GFP_KERNEL);
  483. if (!priv->testmode_trace.cpu_addr)
  484. return -ENOMEM;
  485. priv->testmode_trace.trace_enabled = true;
  486. priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
  487. priv->testmode_trace.cpu_addr, 0x100);
  488. memset(priv->testmode_trace.trace_addr, 0x03B,
  489. priv->testmode_trace.buff_size);
  490. skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
  491. sizeof(priv->testmode_trace.dma_addr) + 20);
  492. if (!skb) {
  493. IWL_DEBUG_INFO(priv,
  494. "Error allocating memory\n");
  495. iwl_trace_cleanup(priv);
  496. return -ENOMEM;
  497. }
  498. NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR,
  499. sizeof(priv->testmode_trace.dma_addr),
  500. (u64 *)&priv->testmode_trace.dma_addr);
  501. status = cfg80211_testmode_reply(skb);
  502. if (status < 0) {
  503. IWL_DEBUG_INFO(priv,
  504. "Error sending msg : %d\n",
  505. status);
  506. }
  507. priv->testmode_trace.num_chunks =
  508. DIV_ROUND_UP(priv->testmode_trace.buff_size,
  509. TRACE_CHUNK_SIZE);
  510. break;
  511. case IWL_TM_CMD_APP2DEV_END_TRACE:
  512. iwl_trace_cleanup(priv);
  513. break;
  514. default:
  515. IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
  516. return -ENOSYS;
  517. }
  518. return status;
  519. nla_put_failure:
  520. kfree_skb(skb);
  521. if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) ==
  522. IWL_TM_CMD_APP2DEV_BEGIN_TRACE)
  523. iwl_trace_cleanup(priv);
  524. return -EMSGSIZE;
  525. }
  526. static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
  527. struct sk_buff *skb,
  528. struct netlink_callback *cb)
  529. {
  530. struct iwl_priv *priv = hw->priv;
  531. int idx, length;
  532. if (priv->testmode_trace.trace_enabled &&
  533. priv->testmode_trace.trace_addr) {
  534. idx = cb->args[4];
  535. if (idx >= priv->testmode_trace.num_chunks)
  536. return -ENOENT;
  537. length = TRACE_CHUNK_SIZE;
  538. if (((idx + 1) == priv->testmode_trace.num_chunks) &&
  539. (priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE))
  540. length = priv->testmode_trace.buff_size %
  541. TRACE_CHUNK_SIZE;
  542. NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length,
  543. priv->testmode_trace.trace_addr +
  544. (TRACE_CHUNK_SIZE * idx));
  545. idx++;
  546. cb->args[4] = idx;
  547. return 0;
  548. } else
  549. return -EFAULT;
  550. nla_put_failure:
  551. return -ENOBUFS;
  552. }
  553. /*
  554. * This function handles the user application switch ucode ownership.
  555. *
  556. * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and
  557. * decide who the current owner of the uCode
  558. *
  559. * If the current owner is OWNERSHIP_TM, then the only host command
  560. * can deliver to uCode is from testmode, all the other host commands
  561. * will dropped.
  562. *
  563. * default driver is the owner of uCode in normal operational mode
  564. *
  565. * @hw: ieee80211_hw object that represents the device
  566. * @tb: gnl message fields from the user space
  567. */
  568. static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
  569. {
  570. struct iwl_priv *priv = hw->priv;
  571. u8 owner;
  572. if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
  573. IWL_DEBUG_INFO(priv, "Error finding ucode owner\n");
  574. return -ENOMSG;
  575. }
  576. owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
  577. if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
  578. priv->shrd->ucode_owner = owner;
  579. else {
  580. IWL_DEBUG_INFO(priv, "Invalid owner\n");
  581. return -EINVAL;
  582. }
  583. return 0;
  584. }
  585. /* The testmode gnl message handler that takes the gnl message from the
  586. * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
  587. * invoke the corresponding handlers.
  588. *
  589. * This function is invoked when there is user space application sending
  590. * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated
  591. * by nl80211.
  592. *
  593. * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before
  594. * dispatching it to the corresponding handler.
  595. *
  596. * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application;
  597. * -ENOSYS is replied to the user application if the command is unknown;
  598. * Otherwise, the command is dispatched to the respective handler.
  599. *
  600. * @hw: ieee80211_hw object that represents the device
  601. * @data: pointer to user space message
  602. * @len: length in byte of @data
  603. */
  604. int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
  605. {
  606. struct nlattr *tb[IWL_TM_ATTR_MAX];
  607. struct iwl_priv *priv = hw->priv;
  608. int result;
  609. result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
  610. iwl_testmode_gnl_msg_policy);
  611. if (result != 0) {
  612. IWL_DEBUG_INFO(priv,
  613. "Error parsing the gnl message : %d\n", result);
  614. return result;
  615. }
  616. /* IWL_TM_ATTR_COMMAND is absolutely mandatory */
  617. if (!tb[IWL_TM_ATTR_COMMAND]) {
  618. IWL_DEBUG_INFO(priv, "Error finding testmode command type\n");
  619. return -ENOMSG;
  620. }
  621. /* in case multiple accesses to the device happens */
  622. mutex_lock(&priv->shrd->mutex);
  623. switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
  624. case IWL_TM_CMD_APP2DEV_UCODE:
  625. IWL_DEBUG_INFO(priv, "testmode cmd to uCode\n");
  626. result = iwl_testmode_ucode(hw, tb);
  627. break;
  628. case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
  629. case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
  630. case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
  631. case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32:
  632. case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32:
  633. IWL_DEBUG_INFO(priv, "testmode cmd to register\n");
  634. result = iwl_testmode_reg(hw, tb);
  635. break;
  636. case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
  637. case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
  638. case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
  639. case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
  640. case IWL_TM_CMD_APP2DEV_GET_EEPROM:
  641. case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
  642. IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
  643. result = iwl_testmode_driver(hw, tb);
  644. break;
  645. case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
  646. case IWL_TM_CMD_APP2DEV_END_TRACE:
  647. case IWL_TM_CMD_APP2DEV_READ_TRACE:
  648. IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n");
  649. result = iwl_testmode_trace(hw, tb);
  650. break;
  651. case IWL_TM_CMD_APP2DEV_OWNERSHIP:
  652. IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n");
  653. result = iwl_testmode_ownership(hw, tb);
  654. break;
  655. default:
  656. IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
  657. result = -ENOSYS;
  658. break;
  659. }
  660. mutex_unlock(&priv->shrd->mutex);
  661. return result;
  662. }
  663. int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
  664. struct netlink_callback *cb,
  665. void *data, int len)
  666. {
  667. struct nlattr *tb[IWL_TM_ATTR_MAX];
  668. struct iwl_priv *priv = hw->priv;
  669. int result;
  670. u32 cmd;
  671. if (cb->args[3]) {
  672. /* offset by 1 since commands start at 0 */
  673. cmd = cb->args[3] - 1;
  674. } else {
  675. result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
  676. iwl_testmode_gnl_msg_policy);
  677. if (result) {
  678. IWL_DEBUG_INFO(priv,
  679. "Error parsing the gnl message : %d\n", result);
  680. return result;
  681. }
  682. /* IWL_TM_ATTR_COMMAND is absolutely mandatory */
  683. if (!tb[IWL_TM_ATTR_COMMAND]) {
  684. IWL_DEBUG_INFO(priv,
  685. "Error finding testmode command type\n");
  686. return -ENOMSG;
  687. }
  688. cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
  689. cb->args[3] = cmd + 1;
  690. }
  691. /* in case multiple accesses to the device happens */
  692. mutex_lock(&priv->shrd->mutex);
  693. switch (cmd) {
  694. case IWL_TM_CMD_APP2DEV_READ_TRACE:
  695. IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
  696. result = iwl_testmode_trace_dump(hw, tb, skb, cb);
  697. break;
  698. default:
  699. result = -EINVAL;
  700. break;
  701. }
  702. mutex_unlock(&priv->shrd->mutex);
  703. return result;
  704. }