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