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