Merge branch 'wireless-next' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi...
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / iwl-testmode.c
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 - 2012 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 - 2012 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
73 #include "iwl-wifi.h"
74 #include "iwl-dev.h"
75 #include "iwl-core.h"
76 #include "iwl-debug.h"
77 #include "iwl-io.h"
78 #include "iwl-agn.h"
79 #include "iwl-testmode.h"
80 #include "iwl-trans.h"
81 #include "iwl-bus.h"
82 #include "iwl-fh.h"
83
84 /* The TLVs used in the gnl message policy between the kernel module and
85 * user space application. iwl_testmode_gnl_msg_policy is to be carried
86 * through the NL80211_CMD_TESTMODE channel regulated by nl80211.
87 * See iwl-testmode.h
88 */
89 static
90 struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
91 [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, },
92
93 [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, },
94 [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, },
95
96 [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, },
97 [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, },
98 [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, },
99
100 [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, },
101 [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, },
102
103 [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
104
105 [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
106 [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, },
107 [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, },
108
109 [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
110
111 [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, },
112
113 [IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, },
114 [IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, },
115 [IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, },
116
117 [IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, },
118 [IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, },
119 [IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, },
120 [IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, },
121 [IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, },
122 };
123
124 /*
125 * See the struct iwl_rx_packet in iwl-commands.h for the format of the
126 * received events from the device
127 */
128 static inline int get_event_length(struct iwl_rx_mem_buffer *rxb)
129 {
130 struct iwl_rx_packet *pkt = rxb_addr(rxb);
131 if (pkt)
132 return le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
133 else
134 return 0;
135 }
136
137
138 /*
139 * This function multicasts the spontaneous messages from the device to the
140 * user space. It is invoked whenever there is a received messages
141 * from the device. This function is called within the ISR of the rx handlers
142 * in iwlagn driver.
143 *
144 * The parsing of the message content is left to the user space application,
145 * The message content is treated as unattacked raw data and is encapsulated
146 * with IWL_TM_ATTR_UCODE_RX_PKT multicasting to the user space.
147 *
148 * @priv: the instance of iwlwifi device
149 * @rxb: pointer to rx data content received by the ISR
150 *
151 * See the message policies and TLVs in iwl_testmode_gnl_msg_policy[].
152 * For the messages multicasting to the user application, the mandatory
153 * TLV fields are :
154 * IWL_TM_ATTR_COMMAND must be IWL_TM_CMD_DEV2APP_UCODE_RX_PKT
155 * IWL_TM_ATTR_UCODE_RX_PKT for carrying the message content
156 */
157
158 static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
159 struct iwl_rx_mem_buffer *rxb)
160 {
161 struct ieee80211_hw *hw = priv->hw;
162 struct sk_buff *skb;
163 void *data;
164 int length;
165
166 data = (void *)rxb_addr(rxb);
167 length = get_event_length(rxb);
168
169 if (!data || length == 0)
170 return;
171
172 skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length,
173 GFP_ATOMIC);
174 if (skb == NULL) {
175 IWL_DEBUG_INFO(priv,
176 "Run out of memory for messages to user space ?\n");
177 return;
178 }
179 NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
180 NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data);
181 cfg80211_testmode_event(skb, GFP_ATOMIC);
182 return;
183
184 nla_put_failure:
185 kfree_skb(skb);
186 IWL_DEBUG_INFO(priv, "Ouch, overran buffer, check allocation!\n");
187 }
188
189 void iwl_testmode_init(struct iwl_priv *priv)
190 {
191 priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
192 priv->testmode_trace.trace_enabled = false;
193 priv->testmode_sram.sram_readed = false;
194 }
195
196 static void iwl_sram_cleanup(struct iwl_priv *priv)
197 {
198 if (priv->testmode_sram.sram_readed) {
199 kfree(priv->testmode_sram.buff_addr);
200 priv->testmode_sram.buff_addr = NULL;
201 priv->testmode_sram.buff_size = 0;
202 priv->testmode_sram.num_chunks = 0;
203 priv->testmode_sram.sram_readed = false;
204 }
205 }
206
207 static void iwl_trace_cleanup(struct iwl_priv *priv)
208 {
209 if (priv->testmode_trace.trace_enabled) {
210 if (priv->testmode_trace.cpu_addr &&
211 priv->testmode_trace.dma_addr)
212 dma_free_coherent(trans(priv)->dev,
213 priv->testmode_trace.total_size,
214 priv->testmode_trace.cpu_addr,
215 priv->testmode_trace.dma_addr);
216 priv->testmode_trace.trace_enabled = false;
217 priv->testmode_trace.cpu_addr = NULL;
218 priv->testmode_trace.trace_addr = NULL;
219 priv->testmode_trace.dma_addr = 0;
220 priv->testmode_trace.buff_size = 0;
221 priv->testmode_trace.total_size = 0;
222 }
223 }
224
225
226 void iwl_testmode_cleanup(struct iwl_priv *priv)
227 {
228 iwl_trace_cleanup(priv);
229 iwl_sram_cleanup(priv);
230 }
231
232 /*
233 * This function handles the user application commands to the ucode.
234 *
235 * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_CMD_ID and
236 * IWL_TM_ATTR_UCODE_CMD_DATA and calls to the handler to send the
237 * host command to the ucode.
238 *
239 * If any mandatory field is missing, -ENOMSG is replied to the user space
240 * application; otherwise, the actual execution result of the host command to
241 * ucode is replied.
242 *
243 * @hw: ieee80211_hw object that represents the device
244 * @tb: gnl message fields from the user space
245 */
246 static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
247 {
248 struct iwl_priv *priv = hw->priv;
249 struct iwl_host_cmd cmd;
250
251 memset(&cmd, 0, sizeof(struct iwl_host_cmd));
252
253 if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] ||
254 !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) {
255 IWL_DEBUG_INFO(priv,
256 "Error finding ucode command mandatory fields\n");
257 return -ENOMSG;
258 }
259
260 cmd.flags = CMD_ON_DEMAND;
261 cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
262 cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
263 cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
264 cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
265 IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
266 " len %d\n", cmd.id, cmd.flags, cmd.len[0]);
267 /* ok, let's submit the command to ucode */
268 return iwl_trans_send_cmd(trans(priv), &cmd);
269 }
270
271
272 /*
273 * This function handles the user application commands for register access.
274 *
275 * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
276 * handlers respectively.
277 *
278 * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the
279 * mandatory fields(IWL_TM_ATTR_REG_OFFSET,IWL_TM_ATTR_REG_VALUE32,
280 * IWL_TM_ATTR_REG_VALUE8) are missing; Otherwise 0 is replied indicating
281 * the success of the command execution.
282 *
283 * If IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_READ32, the register read
284 * value is returned with IWL_TM_ATTR_REG_VALUE32.
285 *
286 * @hw: ieee80211_hw object that represents the device
287 * @tb: gnl message fields from the user space
288 */
289 static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
290 {
291 struct iwl_priv *priv = hw->priv;
292 u32 ofs, val32, cmd;
293 u8 val8;
294 struct sk_buff *skb;
295 int status = 0;
296
297 if (!tb[IWL_TM_ATTR_REG_OFFSET]) {
298 IWL_DEBUG_INFO(priv, "Error finding register offset\n");
299 return -ENOMSG;
300 }
301 ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]);
302 IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs);
303
304 /* Allow access only to FH/CSR/HBUS in direct mode.
305 Since we don't have the upper bounds for the CSR and HBUS segments,
306 we will use only the upper bound of FH for sanity check. */
307 cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
308 if ((cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32 ||
309 cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 ||
310 cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8) &&
311 (ofs >= FH_MEM_UPPER_BOUND)) {
312 IWL_DEBUG_INFO(priv, "offset out of segment (0x0 - 0x%x)\n",
313 FH_MEM_UPPER_BOUND);
314 return -EINVAL;
315 }
316
317 switch (cmd) {
318 case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
319 val32 = iwl_read_direct32(trans(priv), ofs);
320 IWL_INFO(priv, "32bit value to read 0x%x\n", val32);
321
322 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
323 if (!skb) {
324 IWL_DEBUG_INFO(priv, "Error allocating memory\n");
325 return -ENOMEM;
326 }
327 NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32);
328 status = cfg80211_testmode_reply(skb);
329 if (status < 0)
330 IWL_DEBUG_INFO(priv,
331 "Error sending msg : %d\n", status);
332 break;
333 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
334 if (!tb[IWL_TM_ATTR_REG_VALUE32]) {
335 IWL_DEBUG_INFO(priv,
336 "Error finding value to write\n");
337 return -ENOMSG;
338 } else {
339 val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
340 IWL_INFO(priv, "32bit value to write 0x%x\n", val32);
341 iwl_write_direct32(trans(priv), ofs, val32);
342 }
343 break;
344 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
345 if (!tb[IWL_TM_ATTR_REG_VALUE8]) {
346 IWL_DEBUG_INFO(priv, "Error finding value to write\n");
347 return -ENOMSG;
348 } else {
349 val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]);
350 IWL_INFO(priv, "8bit value to write 0x%x\n", val8);
351 iwl_write8(trans(priv), ofs, val8);
352 }
353 break;
354 case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32:
355 val32 = iwl_read_prph(trans(priv), ofs);
356 IWL_INFO(priv, "32bit value to read 0x%x\n", val32);
357
358 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
359 if (!skb) {
360 IWL_DEBUG_INFO(priv, "Error allocating memory\n");
361 return -ENOMEM;
362 }
363 NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32);
364 status = cfg80211_testmode_reply(skb);
365 if (status < 0)
366 IWL_DEBUG_INFO(priv,
367 "Error sending msg : %d\n", status);
368 break;
369 case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32:
370 if (!tb[IWL_TM_ATTR_REG_VALUE32]) {
371 IWL_DEBUG_INFO(priv,
372 "Error finding value to write\n");
373 return -ENOMSG;
374 } else {
375 val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
376 IWL_INFO(priv, "32bit value to write 0x%x\n", val32);
377 iwl_write_prph(trans(priv), ofs, val32);
378 }
379 break;
380 default:
381 IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n");
382 return -ENOSYS;
383 }
384
385 return status;
386
387 nla_put_failure:
388 kfree_skb(skb);
389 return -EMSGSIZE;
390 }
391
392
393 static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
394 {
395 struct iwl_notification_wait calib_wait;
396 int ret;
397
398 iwl_init_notification_wait(priv->shrd, &calib_wait,
399 CALIBRATION_COMPLETE_NOTIFICATION,
400 NULL, NULL);
401 ret = iwl_init_alive_start(trans(priv));
402 if (ret) {
403 IWL_DEBUG_INFO(priv,
404 "Error configuring init calibration: %d\n", ret);
405 goto cfg_init_calib_error;
406 }
407
408 ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ);
409 if (ret)
410 IWL_DEBUG_INFO(priv, "Error detecting"
411 " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
412 return ret;
413
414 cfg_init_calib_error:
415 iwl_remove_notification(priv->shrd, &calib_wait);
416 return ret;
417 }
418
419 /*
420 * This function handles the user application commands for driver.
421 *
422 * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
423 * handlers respectively.
424 *
425 * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
426 * value of the actual command execution is replied to the user application.
427 *
428 * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP
429 * is used for carry the message while IWL_TM_ATTR_COMMAND must set to
430 * IWL_TM_CMD_DEV2APP_SYNC_RSP.
431 *
432 * @hw: ieee80211_hw object that represents the device
433 * @tb: gnl message fields from the user space
434 */
435 static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
436 {
437 struct iwl_priv *priv = hw->priv;
438 struct iwl_trans *trans = trans(priv);
439 struct sk_buff *skb;
440 unsigned char *rsp_data_ptr = NULL;
441 int status = 0, rsp_data_len = 0;
442 u32 devid, inst_size = 0, data_size = 0;
443
444 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
445 case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
446 rsp_data_ptr = (unsigned char *)cfg(priv)->name;
447 rsp_data_len = strlen(cfg(priv)->name);
448 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
449 rsp_data_len + 20);
450 if (!skb) {
451 IWL_DEBUG_INFO(priv,
452 "Error allocating memory\n");
453 return -ENOMEM;
454 }
455 NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
456 IWL_TM_CMD_DEV2APP_SYNC_RSP);
457 NLA_PUT(skb, IWL_TM_ATTR_SYNC_RSP,
458 rsp_data_len, rsp_data_ptr);
459 status = cfg80211_testmode_reply(skb);
460 if (status < 0)
461 IWL_DEBUG_INFO(priv, "Error sending msg : %d\n",
462 status);
463 break;
464
465 case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
466 status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
467 if (status)
468 IWL_DEBUG_INFO(priv,
469 "Error loading init ucode: %d\n", status);
470 break;
471
472 case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
473 iwl_testmode_cfg_init_calib(priv);
474 iwl_trans_stop_device(trans);
475 break;
476
477 case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
478 status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR);
479 if (status) {
480 IWL_DEBUG_INFO(priv,
481 "Error loading runtime ucode: %d\n", status);
482 break;
483 }
484 status = iwl_alive_start(priv);
485 if (status)
486 IWL_DEBUG_INFO(priv,
487 "Error starting the device: %d\n", status);
488 break;
489
490 case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
491 iwl_scan_cancel_timeout(priv, 200);
492 iwl_trans_stop_device(trans);
493 status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN);
494 if (status) {
495 IWL_DEBUG_INFO(priv,
496 "Error loading WOWLAN ucode: %d\n", status);
497 break;
498 }
499 status = iwl_alive_start(priv);
500 if (status)
501 IWL_DEBUG_INFO(priv,
502 "Error starting the device: %d\n", status);
503 break;
504
505 case IWL_TM_CMD_APP2DEV_GET_EEPROM:
506 if (priv->shrd->eeprom) {
507 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
508 cfg(priv)->base_params->eeprom_size + 20);
509 if (!skb) {
510 IWL_DEBUG_INFO(priv,
511 "Error allocating memory\n");
512 return -ENOMEM;
513 }
514 NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
515 IWL_TM_CMD_DEV2APP_EEPROM_RSP);
516 NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
517 cfg(priv)->base_params->eeprom_size,
518 priv->shrd->eeprom);
519 status = cfg80211_testmode_reply(skb);
520 if (status < 0)
521 IWL_DEBUG_INFO(priv,
522 "Error sending msg : %d\n",
523 status);
524 } else
525 return -EFAULT;
526 break;
527
528 case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
529 if (!tb[IWL_TM_ATTR_FIXRATE]) {
530 IWL_DEBUG_INFO(priv,
531 "Error finding fixrate setting\n");
532 return -ENOMSG;
533 }
534 priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
535 break;
536
537 case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
538 IWL_INFO(priv, "uCode version raw: 0x%x\n", priv->ucode_ver);
539
540 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
541 if (!skb) {
542 IWL_DEBUG_INFO(priv, "Error allocating memory\n");
543 return -ENOMEM;
544 }
545 NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION, priv->ucode_ver);
546 status = cfg80211_testmode_reply(skb);
547 if (status < 0)
548 IWL_DEBUG_INFO(priv,
549 "Error sending msg : %d\n", status);
550 break;
551
552 case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
553 devid = trans(priv)->hw_id;
554 IWL_INFO(priv, "hw version: 0x%x\n", devid);
555
556 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
557 if (!skb) {
558 IWL_DEBUG_INFO(priv, "Error allocating memory\n");
559 return -ENOMEM;
560 }
561 NLA_PUT_U32(skb, IWL_TM_ATTR_DEVICE_ID, devid);
562 status = cfg80211_testmode_reply(skb);
563 if (status < 0)
564 IWL_DEBUG_INFO(priv,
565 "Error sending msg : %d\n", status);
566 break;
567
568 case IWL_TM_CMD_APP2DEV_GET_FW_INFO:
569 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8);
570 if (!skb) {
571 IWL_DEBUG_INFO(priv, "Error allocating memory\n");
572 return -ENOMEM;
573 }
574 switch (priv->shrd->ucode_type) {
575 case IWL_UCODE_REGULAR:
576 inst_size = trans(priv)->ucode_rt.code.len;
577 data_size = trans(priv)->ucode_rt.data.len;
578 break;
579 case IWL_UCODE_INIT:
580 inst_size = trans(priv)->ucode_init.code.len;
581 data_size = trans(priv)->ucode_init.data.len;
582 break;
583 case IWL_UCODE_WOWLAN:
584 inst_size = trans(priv)->ucode_wowlan.code.len;
585 data_size = trans(priv)->ucode_wowlan.data.len;
586 break;
587 case IWL_UCODE_NONE:
588 IWL_DEBUG_INFO(priv, "The uCode has not been loaded\n");
589 break;
590 default:
591 IWL_DEBUG_INFO(priv, "Unsupported uCode type\n");
592 break;
593 }
594 NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type);
595 NLA_PUT_U32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size);
596 NLA_PUT_U32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size);
597 status = cfg80211_testmode_reply(skb);
598 if (status < 0)
599 IWL_DEBUG_INFO(priv,
600 "Error sending msg : %d\n", status);
601 break;
602
603 default:
604 IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n");
605 return -ENOSYS;
606 }
607 return status;
608
609 nla_put_failure:
610 kfree_skb(skb);
611 return -EMSGSIZE;
612 }
613
614
615 /*
616 * This function handles the user application commands for uCode trace
617 *
618 * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
619 * handlers respectively.
620 *
621 * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
622 * value of the actual command execution is replied to the user application.
623 *
624 * @hw: ieee80211_hw object that represents the device
625 * @tb: gnl message fields from the user space
626 */
627 static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
628 {
629 struct iwl_priv *priv = hw->priv;
630 struct sk_buff *skb;
631 int status = 0;
632 struct device *dev = trans(priv)->dev;
633
634 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
635 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
636 if (priv->testmode_trace.trace_enabled)
637 return -EBUSY;
638
639 if (!tb[IWL_TM_ATTR_TRACE_SIZE])
640 priv->testmode_trace.buff_size = TRACE_BUFF_SIZE_DEF;
641 else
642 priv->testmode_trace.buff_size =
643 nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]);
644 if (!priv->testmode_trace.buff_size)
645 return -EINVAL;
646 if (priv->testmode_trace.buff_size < TRACE_BUFF_SIZE_MIN ||
647 priv->testmode_trace.buff_size > TRACE_BUFF_SIZE_MAX)
648 return -EINVAL;
649
650 priv->testmode_trace.total_size =
651 priv->testmode_trace.buff_size + TRACE_BUFF_PADD;
652 priv->testmode_trace.cpu_addr =
653 dma_alloc_coherent(dev,
654 priv->testmode_trace.total_size,
655 &priv->testmode_trace.dma_addr,
656 GFP_KERNEL);
657 if (!priv->testmode_trace.cpu_addr)
658 return -ENOMEM;
659 priv->testmode_trace.trace_enabled = true;
660 priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
661 priv->testmode_trace.cpu_addr, 0x100);
662 memset(priv->testmode_trace.trace_addr, 0x03B,
663 priv->testmode_trace.buff_size);
664 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
665 sizeof(priv->testmode_trace.dma_addr) + 20);
666 if (!skb) {
667 IWL_DEBUG_INFO(priv,
668 "Error allocating memory\n");
669 iwl_trace_cleanup(priv);
670 return -ENOMEM;
671 }
672 NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR,
673 sizeof(priv->testmode_trace.dma_addr),
674 (u64 *)&priv->testmode_trace.dma_addr);
675 status = cfg80211_testmode_reply(skb);
676 if (status < 0) {
677 IWL_DEBUG_INFO(priv,
678 "Error sending msg : %d\n",
679 status);
680 }
681 priv->testmode_trace.num_chunks =
682 DIV_ROUND_UP(priv->testmode_trace.buff_size,
683 DUMP_CHUNK_SIZE);
684 break;
685
686 case IWL_TM_CMD_APP2DEV_END_TRACE:
687 iwl_trace_cleanup(priv);
688 break;
689 default:
690 IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
691 return -ENOSYS;
692 }
693 return status;
694
695 nla_put_failure:
696 kfree_skb(skb);
697 if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) ==
698 IWL_TM_CMD_APP2DEV_BEGIN_TRACE)
699 iwl_trace_cleanup(priv);
700 return -EMSGSIZE;
701 }
702
703 static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
704 struct sk_buff *skb,
705 struct netlink_callback *cb)
706 {
707 struct iwl_priv *priv = hw->priv;
708 int idx, length;
709
710 if (priv->testmode_trace.trace_enabled &&
711 priv->testmode_trace.trace_addr) {
712 idx = cb->args[4];
713 if (idx >= priv->testmode_trace.num_chunks)
714 return -ENOENT;
715 length = DUMP_CHUNK_SIZE;
716 if (((idx + 1) == priv->testmode_trace.num_chunks) &&
717 (priv->testmode_trace.buff_size % DUMP_CHUNK_SIZE))
718 length = priv->testmode_trace.buff_size %
719 DUMP_CHUNK_SIZE;
720
721 NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length,
722 priv->testmode_trace.trace_addr +
723 (DUMP_CHUNK_SIZE * idx));
724 idx++;
725 cb->args[4] = idx;
726 return 0;
727 } else
728 return -EFAULT;
729
730 nla_put_failure:
731 return -ENOBUFS;
732 }
733
734 /*
735 * This function handles the user application switch ucode ownership.
736 *
737 * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and
738 * decide who the current owner of the uCode
739 *
740 * If the current owner is OWNERSHIP_TM, then the only host command
741 * can deliver to uCode is from testmode, all the other host commands
742 * will dropped.
743 *
744 * default driver is the owner of uCode in normal operational mode
745 *
746 * @hw: ieee80211_hw object that represents the device
747 * @tb: gnl message fields from the user space
748 */
749 static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
750 {
751 struct iwl_priv *priv = hw->priv;
752 u8 owner;
753
754 if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
755 IWL_DEBUG_INFO(priv, "Error finding ucode owner\n");
756 return -ENOMSG;
757 }
758
759 owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
760 if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
761 priv->shrd->ucode_owner = owner;
762 else {
763 IWL_DEBUG_INFO(priv, "Invalid owner\n");
764 return -EINVAL;
765 }
766 return 0;
767 }
768
769 /*
770 * This function handles the user application commands for SRAM data dump
771 *
772 * It retrieves the mandatory fields IWL_TM_ATTR_SRAM_ADDR and
773 * IWL_TM_ATTR_SRAM_SIZE to decide the memory area for SRAM data reading
774 *
775 * Several error will be retured, -EBUSY if the SRAM data retrieved by
776 * previous command has not been delivered to userspace, or -ENOMSG if
777 * the mandatory fields (IWL_TM_ATTR_SRAM_ADDR,IWL_TM_ATTR_SRAM_SIZE)
778 * are missing, or -ENOMEM if the buffer allocation fails.
779 *
780 * Otherwise 0 is replied indicating the success of the SRAM reading.
781 *
782 * @hw: ieee80211_hw object that represents the device
783 * @tb: gnl message fields from the user space
784 */
785 static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb)
786 {
787 struct iwl_priv *priv = hw->priv;
788 u32 ofs, size, maxsize;
789
790 if (priv->testmode_sram.sram_readed)
791 return -EBUSY;
792
793 if (!tb[IWL_TM_ATTR_SRAM_ADDR]) {
794 IWL_DEBUG_INFO(priv, "Error finding SRAM offset address\n");
795 return -ENOMSG;
796 }
797 ofs = nla_get_u32(tb[IWL_TM_ATTR_SRAM_ADDR]);
798 if (!tb[IWL_TM_ATTR_SRAM_SIZE]) {
799 IWL_DEBUG_INFO(priv, "Error finding size for SRAM reading\n");
800 return -ENOMSG;
801 }
802 size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]);
803 switch (priv->shrd->ucode_type) {
804 case IWL_UCODE_REGULAR:
805 maxsize = trans(priv)->ucode_rt.data.len;
806 break;
807 case IWL_UCODE_INIT:
808 maxsize = trans(priv)->ucode_init.data.len;
809 break;
810 case IWL_UCODE_WOWLAN:
811 maxsize = trans(priv)->ucode_wowlan.data.len;
812 break;
813 case IWL_UCODE_NONE:
814 IWL_ERR(priv, "Error, uCode does not been loaded\n");
815 return -ENOSYS;
816 default:
817 IWL_ERR(priv, "Error, unsupported uCode type\n");
818 return -ENOSYS;
819 }
820 if ((ofs + size) > (maxsize + SRAM_DATA_SEG_OFFSET)) {
821 IWL_ERR(priv, "Invalid offset/size: out of range\n");
822 return -EINVAL;
823 }
824 priv->testmode_sram.buff_size = (size / 4) * 4;
825 priv->testmode_sram.buff_addr =
826 kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL);
827 if (priv->testmode_sram.buff_addr == NULL) {
828 IWL_ERR(priv, "Error allocating memory\n");
829 return -ENOMEM;
830 }
831 _iwl_read_targ_mem_words(trans(priv), ofs,
832 priv->testmode_sram.buff_addr,
833 priv->testmode_sram.buff_size / 4);
834 priv->testmode_sram.num_chunks =
835 DIV_ROUND_UP(priv->testmode_sram.buff_size, DUMP_CHUNK_SIZE);
836 priv->testmode_sram.sram_readed = true;
837 return 0;
838 }
839
840 static int iwl_testmode_sram_dump(struct ieee80211_hw *hw, struct nlattr **tb,
841 struct sk_buff *skb,
842 struct netlink_callback *cb)
843 {
844 struct iwl_priv *priv = hw->priv;
845 int idx, length;
846
847 if (priv->testmode_sram.sram_readed) {
848 idx = cb->args[4];
849 if (idx >= priv->testmode_sram.num_chunks) {
850 iwl_sram_cleanup(priv);
851 return -ENOENT;
852 }
853 length = DUMP_CHUNK_SIZE;
854 if (((idx + 1) == priv->testmode_sram.num_chunks) &&
855 (priv->testmode_sram.buff_size % DUMP_CHUNK_SIZE))
856 length = priv->testmode_sram.buff_size %
857 DUMP_CHUNK_SIZE;
858
859 NLA_PUT(skb, IWL_TM_ATTR_SRAM_DUMP, length,
860 priv->testmode_sram.buff_addr +
861 (DUMP_CHUNK_SIZE * idx));
862 idx++;
863 cb->args[4] = idx;
864 return 0;
865 } else
866 return -EFAULT;
867
868 nla_put_failure:
869 return -ENOBUFS;
870 }
871
872
873 /* The testmode gnl message handler that takes the gnl message from the
874 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
875 * invoke the corresponding handlers.
876 *
877 * This function is invoked when there is user space application sending
878 * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated
879 * by nl80211.
880 *
881 * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before
882 * dispatching it to the corresponding handler.
883 *
884 * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application;
885 * -ENOSYS is replied to the user application if the command is unknown;
886 * Otherwise, the command is dispatched to the respective handler.
887 *
888 * @hw: ieee80211_hw object that represents the device
889 * @data: pointer to user space message
890 * @len: length in byte of @data
891 */
892 int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
893 {
894 struct nlattr *tb[IWL_TM_ATTR_MAX];
895 struct iwl_priv *priv = hw->priv;
896 int result;
897
898 result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
899 iwl_testmode_gnl_msg_policy);
900 if (result != 0) {
901 IWL_DEBUG_INFO(priv,
902 "Error parsing the gnl message : %d\n", result);
903 return result;
904 }
905
906 /* IWL_TM_ATTR_COMMAND is absolutely mandatory */
907 if (!tb[IWL_TM_ATTR_COMMAND]) {
908 IWL_DEBUG_INFO(priv, "Error finding testmode command type\n");
909 return -ENOMSG;
910 }
911 /* in case multiple accesses to the device happens */
912 mutex_lock(&priv->shrd->mutex);
913
914 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
915 case IWL_TM_CMD_APP2DEV_UCODE:
916 IWL_DEBUG_INFO(priv, "testmode cmd to uCode\n");
917 result = iwl_testmode_ucode(hw, tb);
918 break;
919 case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
920 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
921 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
922 case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32:
923 case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32:
924 IWL_DEBUG_INFO(priv, "testmode cmd to register\n");
925 result = iwl_testmode_reg(hw, tb);
926 break;
927 case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
928 case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
929 case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
930 case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
931 case IWL_TM_CMD_APP2DEV_GET_EEPROM:
932 case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
933 case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
934 case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
935 case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
936 case IWL_TM_CMD_APP2DEV_GET_FW_INFO:
937 IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
938 result = iwl_testmode_driver(hw, tb);
939 break;
940
941 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
942 case IWL_TM_CMD_APP2DEV_END_TRACE:
943 case IWL_TM_CMD_APP2DEV_READ_TRACE:
944 IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n");
945 result = iwl_testmode_trace(hw, tb);
946 break;
947
948 case IWL_TM_CMD_APP2DEV_OWNERSHIP:
949 IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n");
950 result = iwl_testmode_ownership(hw, tb);
951 break;
952
953 case IWL_TM_CMD_APP2DEV_READ_SRAM:
954 IWL_DEBUG_INFO(priv, "testmode sram read cmd to driver\n");
955 result = iwl_testmode_sram(hw, tb);
956 break;
957
958 default:
959 IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
960 result = -ENOSYS;
961 break;
962 }
963
964 mutex_unlock(&priv->shrd->mutex);
965 return result;
966 }
967
968 int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
969 struct netlink_callback *cb,
970 void *data, int len)
971 {
972 struct nlattr *tb[IWL_TM_ATTR_MAX];
973 struct iwl_priv *priv = hw->priv;
974 int result;
975 u32 cmd;
976
977 if (cb->args[3]) {
978 /* offset by 1 since commands start at 0 */
979 cmd = cb->args[3] - 1;
980 } else {
981 result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
982 iwl_testmode_gnl_msg_policy);
983 if (result) {
984 IWL_DEBUG_INFO(priv,
985 "Error parsing the gnl message : %d\n", result);
986 return result;
987 }
988
989 /* IWL_TM_ATTR_COMMAND is absolutely mandatory */
990 if (!tb[IWL_TM_ATTR_COMMAND]) {
991 IWL_DEBUG_INFO(priv,
992 "Error finding testmode command type\n");
993 return -ENOMSG;
994 }
995 cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
996 cb->args[3] = cmd + 1;
997 }
998
999 /* in case multiple accesses to the device happens */
1000 mutex_lock(&priv->shrd->mutex);
1001 switch (cmd) {
1002 case IWL_TM_CMD_APP2DEV_READ_TRACE:
1003 IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
1004 result = iwl_testmode_trace_dump(hw, tb, skb, cb);
1005 break;
1006 case IWL_TM_CMD_APP2DEV_DUMP_SRAM:
1007 IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n");
1008 result = iwl_testmode_sram_dump(hw, tb, skb, cb);
1009 break;
1010 default:
1011 result = -EINVAL;
1012 break;
1013 }
1014
1015 mutex_unlock(&priv->shrd->mutex);
1016 return result;
1017 }
This page took 0.050637 seconds and 6 git commands to generate.