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