iwl-sv-open.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  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 <net/net_namespace.h>
  67. #include <linux/netdevice.h>
  68. #include <net/cfg80211.h>
  69. #include <net/mac80211.h>
  70. #include <net/netlink.h>
  71. #include "iwl-dev.h"
  72. #include "iwl-core.h"
  73. #include "iwl-debug.h"
  74. #include "iwl-fh.h"
  75. #include "iwl-io.h"
  76. #include "iwl-agn.h"
  77. #include "iwl-testmode.h"
  78. /* The TLVs used in the gnl message policy between the kernel module and
  79. * user space application. iwl_testmode_gnl_msg_policy is to be carried
  80. * through the NL80211_CMD_TESTMODE channel regulated by nl80211.
  81. * See iwl-testmode.h
  82. */
  83. static
  84. struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
  85. [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, },
  86. [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, },
  87. [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, },
  88. [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, },
  89. [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, },
  90. [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, },
  91. [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, },
  92. [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, },
  93. [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
  94. [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
  95. [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, },
  96. [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
  97. };
  98. /*
  99. * See the struct iwl_rx_packet in iwl-commands.h for the format of the
  100. * received events from the device
  101. */
  102. static inline int get_event_length(struct iwl_rx_mem_buffer *rxb)
  103. {
  104. struct iwl_rx_packet *pkt = rxb_addr(rxb);
  105. if (pkt)
  106. return le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
  107. else
  108. return 0;
  109. }
  110. /*
  111. * This function multicasts the spontaneous messages from the device to the
  112. * user space. It is invoked whenever there is a received messages
  113. * from the device. This function is called within the ISR of the rx handlers
  114. * in iwlagn driver.
  115. *
  116. * The parsing of the message content is left to the user space application,
  117. * The message content is treated as unattacked raw data and is encapsulated
  118. * with IWL_TM_ATTR_UCODE_RX_PKT multicasting to the user space.
  119. *
  120. * @priv: the instance of iwlwifi device
  121. * @rxb: pointer to rx data content received by the ISR
  122. *
  123. * See the message policies and TLVs in iwl_testmode_gnl_msg_policy[].
  124. * For the messages multicasting to the user application, the mandatory
  125. * TLV fields are :
  126. * IWL_TM_ATTR_COMMAND must be IWL_TM_CMD_DEV2APP_UCODE_RX_PKT
  127. * IWL_TM_ATTR_UCODE_RX_PKT for carrying the message content
  128. */
  129. static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
  130. struct iwl_rx_mem_buffer *rxb)
  131. {
  132. struct ieee80211_hw *hw = priv->hw;
  133. struct sk_buff *skb;
  134. void *data;
  135. int length;
  136. data = (void *)rxb_addr(rxb);
  137. length = get_event_length(rxb);
  138. if (!data || length == 0)
  139. return;
  140. skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length,
  141. GFP_ATOMIC);
  142. if (skb == NULL) {
  143. IWL_DEBUG_INFO(priv,
  144. "Run out of memory for messages to user space ?\n");
  145. return;
  146. }
  147. NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
  148. NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data);
  149. cfg80211_testmode_event(skb, GFP_ATOMIC);
  150. return;
  151. nla_put_failure:
  152. kfree_skb(skb);
  153. IWL_DEBUG_INFO(priv, "Ouch, overran buffer, check allocation!\n");
  154. }
  155. void iwl_testmode_init(struct iwl_priv *priv)
  156. {
  157. priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
  158. priv->testmode_trace.trace_enabled = false;
  159. }
  160. static void iwl_trace_cleanup(struct iwl_priv *priv)
  161. {
  162. struct device *dev = &priv->pci_dev->dev;
  163. if (priv->testmode_trace.trace_enabled) {
  164. if (priv->testmode_trace.cpu_addr &&
  165. priv->testmode_trace.dma_addr)
  166. dma_free_coherent(dev,
  167. TRACE_TOTAL_SIZE,
  168. priv->testmode_trace.cpu_addr,
  169. priv->testmode_trace.dma_addr);
  170. priv->testmode_trace.trace_enabled = false;
  171. priv->testmode_trace.cpu_addr = NULL;
  172. priv->testmode_trace.trace_addr = NULL;
  173. priv->testmode_trace.dma_addr = 0;
  174. }
  175. }
  176. void iwl_testmode_cleanup(struct iwl_priv *priv)
  177. {
  178. iwl_trace_cleanup(priv);
  179. }
  180. /*
  181. * This function handles the user application commands to the ucode.
  182. *
  183. * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_CMD_ID and
  184. * IWL_TM_ATTR_UCODE_CMD_DATA and calls to the handler to send the
  185. * host command to the ucode.
  186. *
  187. * If any mandatory field is missing, -ENOMSG is replied to the user space
  188. * application; otherwise, the actual execution result of the host command to
  189. * ucode is replied.
  190. *
  191. * @hw: ieee80211_hw object that represents the device
  192. * @tb: gnl message fields from the user space
  193. */
  194. static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
  195. {
  196. struct iwl_priv *priv = hw->priv;
  197. struct iwl_host_cmd cmd;
  198. memset(&cmd, 0, sizeof(struct iwl_host_cmd));
  199. if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] ||
  200. !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) {
  201. IWL_DEBUG_INFO(priv,
  202. "Error finding ucode command mandatory fields\n");
  203. return -ENOMSG;
  204. }
  205. cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
  206. cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
  207. cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
  208. cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
  209. IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
  210. " len %d\n", cmd.id, cmd.flags, cmd.len[0]);
  211. /* ok, let's submit the command to ucode */
  212. return iwl_send_cmd(priv, &cmd);
  213. }
  214. /*
  215. * This function handles the user application commands for register access.
  216. *
  217. * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
  218. * handlers respectively.
  219. *
  220. * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the
  221. * mandatory fields(IWL_TM_ATTR_REG_OFFSET,IWL_TM_ATTR_REG_VALUE32,
  222. * IWL_TM_ATTR_REG_VALUE8) are missing; Otherwise 0 is replied indicating
  223. * the success of the command execution.
  224. *
  225. * If IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_READ32, the register read
  226. * value is returned with IWL_TM_ATTR_REG_VALUE32.
  227. *
  228. * @hw: ieee80211_hw object that represents the device
  229. * @tb: gnl message fields from the user space
  230. */
  231. static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
  232. {
  233. struct iwl_priv *priv = hw->priv;
  234. u32 ofs, val32;
  235. u8 val8;
  236. struct sk_buff *skb;
  237. int status = 0;
  238. if (!tb[IWL_TM_ATTR_REG_OFFSET]) {
  239. IWL_DEBUG_INFO(priv, "Error finding register offset\n");
  240. return -ENOMSG;
  241. }
  242. ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]);
  243. IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs);
  244. switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
  245. case IWL_TM_CMD_APP2DEV_REG_READ32:
  246. val32 = iwl_read32(priv, ofs);
  247. IWL_INFO(priv, "32bit value to read 0x%x\n", val32);
  248. skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
  249. if (!skb) {
  250. IWL_DEBUG_INFO(priv, "Error allocating memory\n");
  251. return -ENOMEM;
  252. }
  253. NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32);
  254. status = cfg80211_testmode_reply(skb);
  255. if (status < 0)
  256. IWL_DEBUG_INFO(priv,
  257. "Error sending msg : %d\n", status);
  258. break;
  259. case IWL_TM_CMD_APP2DEV_REG_WRITE32:
  260. if (!tb[IWL_TM_ATTR_REG_VALUE32]) {
  261. IWL_DEBUG_INFO(priv,
  262. "Error finding value to write\n");
  263. return -ENOMSG;
  264. } else {
  265. val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
  266. IWL_INFO(priv, "32bit value to write 0x%x\n", val32);
  267. iwl_write32(priv, ofs, val32);
  268. }
  269. break;
  270. case IWL_TM_CMD_APP2DEV_REG_WRITE8:
  271. if (!tb[IWL_TM_ATTR_REG_VALUE8]) {
  272. IWL_DEBUG_INFO(priv, "Error finding value to write\n");
  273. return -ENOMSG;
  274. } else {
  275. val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]);
  276. IWL_INFO(priv, "8bit value to write 0x%x\n", val8);
  277. iwl_write8(priv, ofs, val8);
  278. }
  279. break;
  280. default:
  281. IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n");
  282. return -ENOSYS;
  283. }
  284. return status;
  285. nla_put_failure:
  286. kfree_skb(skb);
  287. return -EMSGSIZE;
  288. }
  289. static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
  290. {
  291. struct iwl_notification_wait calib_wait;
  292. int ret;
  293. iwlagn_init_notification_wait(priv, &calib_wait,
  294. CALIBRATION_COMPLETE_NOTIFICATION,
  295. NULL, NULL);
  296. ret = iwlagn_init_alive_start(priv);
  297. if (ret) {
  298. IWL_DEBUG_INFO(priv,
  299. "Error configuring init calibration: %d\n", ret);
  300. goto cfg_init_calib_error;
  301. }
  302. ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ);
  303. if (ret)
  304. IWL_DEBUG_INFO(priv, "Error detecting"
  305. " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
  306. return ret;
  307. cfg_init_calib_error:
  308. iwlagn_remove_notification(priv, &calib_wait);
  309. return ret;
  310. }
  311. /*
  312. * This function handles the user application commands for driver.
  313. *
  314. * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
  315. * handlers respectively.
  316. *
  317. * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
  318. * value of the actual command execution is replied to the user application.
  319. *
  320. * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP
  321. * is used for carry the message while IWL_TM_ATTR_COMMAND must set to
  322. * IWL_TM_CMD_DEV2APP_SYNC_RSP.
  323. *
  324. * @hw: ieee80211_hw object that represents the device
  325. * @tb: gnl message fields from the user space
  326. */
  327. static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
  328. {
  329. struct iwl_priv *priv = hw->priv;
  330. struct sk_buff *skb;
  331. unsigned char *rsp_data_ptr = NULL;
  332. int status = 0, rsp_data_len = 0;
  333. switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
  334. case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
  335. rsp_data_ptr = (unsigned char *)priv->cfg->name;
  336. rsp_data_len = strlen(priv->cfg->name);
  337. skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
  338. rsp_data_len + 20);
  339. if (!skb) {
  340. IWL_DEBUG_INFO(priv,
  341. "Error allocating memory\n");
  342. return -ENOMEM;
  343. }
  344. NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
  345. IWL_TM_CMD_DEV2APP_SYNC_RSP);
  346. NLA_PUT(skb, IWL_TM_ATTR_SYNC_RSP,
  347. rsp_data_len, rsp_data_ptr);
  348. status = cfg80211_testmode_reply(skb);
  349. if (status < 0)
  350. IWL_DEBUG_INFO(priv, "Error sending msg : %d\n",
  351. status);
  352. break;
  353. case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
  354. status = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
  355. UCODE_SUBTYPE_INIT, -1);
  356. if (status)
  357. IWL_DEBUG_INFO(priv,
  358. "Error loading init ucode: %d\n", status);
  359. break;
  360. case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
  361. iwl_testmode_cfg_init_calib(priv);
  362. iwlagn_stop_device(priv);
  363. break;
  364. case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
  365. status = iwlagn_load_ucode_wait_alive(priv,
  366. &priv->ucode_rt,
  367. UCODE_SUBTYPE_REGULAR,
  368. UCODE_SUBTYPE_REGULAR_NEW);
  369. if (status) {
  370. IWL_DEBUG_INFO(priv,
  371. "Error loading runtime ucode: %d\n", status);
  372. break;
  373. }
  374. status = iwl_alive_start(priv);
  375. if (status)
  376. IWL_DEBUG_INFO(priv,
  377. "Error starting the device: %d\n", status);
  378. break;
  379. case IWL_TM_CMD_APP2DEV_GET_EEPROM:
  380. if (priv->eeprom) {
  381. skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
  382. priv->cfg->base_params->eeprom_size + 20);
  383. if (!skb) {
  384. IWL_DEBUG_INFO(priv,
  385. "Error allocating memory\n");
  386. return -ENOMEM;
  387. }
  388. NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
  389. IWL_TM_CMD_DEV2APP_EEPROM_RSP);
  390. NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
  391. priv->cfg->base_params->eeprom_size,
  392. priv->eeprom);
  393. status = cfg80211_testmode_reply(skb);
  394. if (status < 0)
  395. IWL_DEBUG_INFO(priv,
  396. "Error sending msg : %d\n",
  397. status);
  398. } else
  399. return -EFAULT;
  400. break;
  401. case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
  402. if (!tb[IWL_TM_ATTR_FIXRATE]) {
  403. IWL_DEBUG_INFO(priv,
  404. "Error finding fixrate setting\n");
  405. return -ENOMSG;
  406. }
  407. priv->dbg_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
  408. break;
  409. default:
  410. IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n");
  411. return -ENOSYS;
  412. }
  413. return status;
  414. nla_put_failure:
  415. kfree_skb(skb);
  416. return -EMSGSIZE;
  417. }
  418. /*
  419. * This function handles the user application commands for uCode trace
  420. *
  421. * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
  422. * handlers respectively.
  423. *
  424. * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
  425. * value of the actual command execution is replied to the user application.
  426. *
  427. * @hw: ieee80211_hw object that represents the device
  428. * @tb: gnl message fields from the user space
  429. */
  430. static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
  431. {
  432. struct iwl_priv *priv = hw->priv;
  433. struct sk_buff *skb;
  434. int status = 0;
  435. struct device *dev = &priv->pci_dev->dev;
  436. switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
  437. case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
  438. if (priv->testmode_trace.trace_enabled)
  439. return -EBUSY;
  440. priv->testmode_trace.cpu_addr =
  441. dma_alloc_coherent(dev,
  442. TRACE_TOTAL_SIZE,
  443. &priv->testmode_trace.dma_addr,
  444. GFP_KERNEL);
  445. if (!priv->testmode_trace.cpu_addr)
  446. return -ENOMEM;
  447. priv->testmode_trace.trace_enabled = true;
  448. priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
  449. priv->testmode_trace.cpu_addr, 0x100);
  450. memset(priv->testmode_trace.trace_addr, 0x03B,
  451. TRACE_BUFF_SIZE);
  452. skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
  453. sizeof(priv->testmode_trace.dma_addr) + 20);
  454. if (!skb) {
  455. IWL_DEBUG_INFO(priv,
  456. "Error allocating memory\n");
  457. iwl_trace_cleanup(priv);
  458. return -ENOMEM;
  459. }
  460. NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR,
  461. sizeof(priv->testmode_trace.dma_addr),
  462. (u64 *)&priv->testmode_trace.dma_addr);
  463. status = cfg80211_testmode_reply(skb);
  464. if (status < 0) {
  465. IWL_DEBUG_INFO(priv,
  466. "Error sending msg : %d\n",
  467. status);
  468. }
  469. break;
  470. case IWL_TM_CMD_APP2DEV_END_TRACE:
  471. iwl_trace_cleanup(priv);
  472. break;
  473. case IWL_TM_CMD_APP2DEV_READ_TRACE:
  474. if (priv->testmode_trace.trace_enabled &&
  475. priv->testmode_trace.trace_addr) {
  476. skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
  477. 20 + TRACE_BUFF_SIZE);
  478. if (skb == NULL) {
  479. IWL_DEBUG_INFO(priv,
  480. "Error allocating memory\n");
  481. return -ENOMEM;
  482. }
  483. NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA,
  484. TRACE_BUFF_SIZE,
  485. priv->testmode_trace.trace_addr);
  486. status = cfg80211_testmode_reply(skb);
  487. if (status < 0) {
  488. IWL_DEBUG_INFO(priv,
  489. "Error sending msg : %d\n", status);
  490. }
  491. } else
  492. return -EFAULT;
  493. break;
  494. default:
  495. IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
  496. return -ENOSYS;
  497. }
  498. return status;
  499. nla_put_failure:
  500. kfree_skb(skb);
  501. if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) ==
  502. IWL_TM_CMD_APP2DEV_BEGIN_TRACE)
  503. iwl_trace_cleanup(priv);
  504. return -EMSGSIZE;
  505. }
  506. /* The testmode gnl message handler that takes the gnl message from the
  507. * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
  508. * invoke the corresponding handlers.
  509. *
  510. * This function is invoked when there is user space application sending
  511. * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated
  512. * by nl80211.
  513. *
  514. * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before
  515. * dispatching it to the corresponding handler.
  516. *
  517. * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application;
  518. * -ENOSYS is replied to the user application if the command is unknown;
  519. * Otherwise, the command is dispatched to the respective handler.
  520. *
  521. * @hw: ieee80211_hw object that represents the device
  522. * @data: pointer to user space message
  523. * @len: length in byte of @data
  524. */
  525. int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
  526. {
  527. struct nlattr *tb[IWL_TM_ATTR_MAX - 1];
  528. struct iwl_priv *priv = hw->priv;
  529. int result;
  530. result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
  531. iwl_testmode_gnl_msg_policy);
  532. if (result != 0) {
  533. IWL_DEBUG_INFO(priv,
  534. "Error parsing the gnl message : %d\n", result);
  535. return result;
  536. }
  537. /* IWL_TM_ATTR_COMMAND is absolutely mandatory */
  538. if (!tb[IWL_TM_ATTR_COMMAND]) {
  539. IWL_DEBUG_INFO(priv, "Error finding testmode command type\n");
  540. return -ENOMSG;
  541. }
  542. /* in case multiple accesses to the device happens */
  543. mutex_lock(&priv->mutex);
  544. switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
  545. case IWL_TM_CMD_APP2DEV_UCODE:
  546. IWL_DEBUG_INFO(priv, "testmode cmd to uCode\n");
  547. result = iwl_testmode_ucode(hw, tb);
  548. break;
  549. case IWL_TM_CMD_APP2DEV_REG_READ32:
  550. case IWL_TM_CMD_APP2DEV_REG_WRITE32:
  551. case IWL_TM_CMD_APP2DEV_REG_WRITE8:
  552. IWL_DEBUG_INFO(priv, "testmode cmd to register\n");
  553. result = iwl_testmode_reg(hw, tb);
  554. break;
  555. case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
  556. case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
  557. case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
  558. case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
  559. case IWL_TM_CMD_APP2DEV_GET_EEPROM:
  560. case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
  561. IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
  562. result = iwl_testmode_driver(hw, tb);
  563. break;
  564. case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
  565. case IWL_TM_CMD_APP2DEV_END_TRACE:
  566. case IWL_TM_CMD_APP2DEV_READ_TRACE:
  567. IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n");
  568. result = iwl_testmode_trace(hw, tb);
  569. break;
  570. default:
  571. IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
  572. result = -ENOSYS;
  573. break;
  574. }
  575. mutex_unlock(&priv->mutex);
  576. return result;
  577. }