1 /******************************************************************************
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.
8 * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
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.
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.
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,
24 * The full GNU General Public License is included in this distribution
25 * in the file called LICENSE.GPL.
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
33 * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
34 * All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
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
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.
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.
62 *****************************************************************************/
64 #include <linux/init.h>
65 #include <linux/kernel.h>
66 #include <linux/module.h>
67 #include <linux/dma-mapping.h>
68 #include <net/net_namespace.h>
69 #include <linux/netdevice.h>
70 #include <net/cfg80211.h>
71 #include <net/mac80211.h>
72 #include <net/netlink.h>
74 #include "iwl-debug.h"
75 #include "iwl-trans.h"
79 #include "iwl-testmode.h"
81 static int iwl_testmode_send_cmd(struct iwl_op_mode
*op_mode
,
82 struct iwl_host_cmd
*cmd
)
84 struct iwl_priv
*priv
= IWL_OP_MODE_GET_DVM(op_mode
);
85 return iwl_dvm_send_cmd(priv
, cmd
);
88 static bool iwl_testmode_valid_hw_addr(u32 addr
)
90 if (iwlagn_hw_valid_rtc_data_addr(addr
))
93 if (IWLAGN_RTC_INST_LOWER_BOUND
<= addr
&&
94 addr
< IWLAGN_RTC_INST_UPPER_BOUND
)
100 static u32
iwl_testmode_get_fw_ver(struct iwl_op_mode
*op_mode
)
102 struct iwl_priv
*priv
= IWL_OP_MODE_GET_DVM(op_mode
);
103 return priv
->fw
->ucode_ver
;
106 static struct sk_buff
*
107 iwl_testmode_alloc_reply(struct iwl_op_mode
*op_mode
, int len
)
109 struct iwl_priv
*priv
= IWL_OP_MODE_GET_DVM(op_mode
);
110 return cfg80211_testmode_alloc_reply_skb(priv
->hw
->wiphy
, len
);
113 static int iwl_testmode_reply(struct iwl_op_mode
*op_mode
, struct sk_buff
*skb
)
115 return cfg80211_testmode_reply(skb
);
118 static struct sk_buff
*iwl_testmode_alloc_event(struct iwl_op_mode
*op_mode
,
121 struct iwl_priv
*priv
= IWL_OP_MODE_GET_DVM(op_mode
);
122 return cfg80211_testmode_alloc_event_skb(priv
->hw
->wiphy
, len
,
126 static void iwl_testmode_event(struct iwl_op_mode
*op_mode
, struct sk_buff
*skb
)
128 return cfg80211_testmode_event(skb
, GFP_ATOMIC
);
131 static struct iwl_test_ops tst_ops
= {
132 .send_cmd
= iwl_testmode_send_cmd
,
133 .valid_hw_addr
= iwl_testmode_valid_hw_addr
,
134 .get_fw_ver
= iwl_testmode_get_fw_ver
,
135 .alloc_reply
= iwl_testmode_alloc_reply
,
136 .reply
= iwl_testmode_reply
,
137 .alloc_event
= iwl_testmode_alloc_event
,
138 .event
= iwl_testmode_event
,
141 void iwl_testmode_init(struct iwl_priv
*priv
)
143 iwl_test_init(&priv
->tst
, priv
->trans
, &tst_ops
);
146 void iwl_testmode_free(struct iwl_priv
*priv
)
148 iwl_test_free(&priv
->tst
);
151 static int iwl_testmode_cfg_init_calib(struct iwl_priv
*priv
)
153 struct iwl_notification_wait calib_wait
;
154 static const u8 calib_complete
[] = {
155 CALIBRATION_COMPLETE_NOTIFICATION
159 iwl_init_notification_wait(&priv
->notif_wait
, &calib_wait
,
160 calib_complete
, ARRAY_SIZE(calib_complete
),
162 ret
= iwl_init_alive_start(priv
);
164 IWL_ERR(priv
, "Fail init calibration: %d\n", ret
);
165 goto cfg_init_calib_error
;
168 ret
= iwl_wait_notification(&priv
->notif_wait
, &calib_wait
, 2 * HZ
);
170 IWL_ERR(priv
, "Error detecting"
171 " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret
);
174 cfg_init_calib_error
:
175 iwl_remove_notification(&priv
->notif_wait
, &calib_wait
);
180 * This function handles the user application commands for driver.
182 * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
183 * handlers respectively.
185 * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
186 * value of the actual command execution is replied to the user application.
188 * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP
189 * is used for carry the message while IWL_TM_ATTR_COMMAND must set to
190 * IWL_TM_CMD_DEV2APP_SYNC_RSP.
192 * @hw: ieee80211_hw object that represents the device
193 * @tb: gnl message fields from the user space
195 static int iwl_testmode_driver(struct ieee80211_hw
*hw
, struct nlattr
**tb
)
197 struct iwl_priv
*priv
= IWL_MAC80211_GET_DVM(hw
);
198 struct iwl_trans
*trans
= priv
->trans
;
200 unsigned char *rsp_data_ptr
= NULL
;
201 int status
= 0, rsp_data_len
= 0;
202 u32 inst_size
= 0, data_size
= 0;
203 const struct fw_img
*img
;
205 switch (nla_get_u32(tb
[IWL_TM_ATTR_COMMAND
])) {
206 case IWL_TM_CMD_APP2DEV_GET_DEVICENAME
:
207 rsp_data_ptr
= (unsigned char *)priv
->cfg
->name
;
208 rsp_data_len
= strlen(priv
->cfg
->name
);
209 skb
= cfg80211_testmode_alloc_reply_skb(hw
->wiphy
,
212 IWL_ERR(priv
, "Memory allocation fail\n");
215 if (nla_put_u32(skb
, IWL_TM_ATTR_COMMAND
,
216 IWL_TM_CMD_DEV2APP_SYNC_RSP
) ||
217 nla_put(skb
, IWL_TM_ATTR_SYNC_RSP
,
218 rsp_data_len
, rsp_data_ptr
))
219 goto nla_put_failure
;
220 status
= cfg80211_testmode_reply(skb
);
222 IWL_ERR(priv
, "Error sending msg : %d\n", status
);
225 case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW
:
226 status
= iwl_load_ucode_wait_alive(priv
, IWL_UCODE_INIT
);
228 IWL_ERR(priv
, "Error loading init ucode: %d\n", status
);
231 case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB
:
232 iwl_testmode_cfg_init_calib(priv
);
233 priv
->ucode_loaded
= false;
234 iwl_trans_stop_device(trans
);
237 case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW
:
238 status
= iwl_load_ucode_wait_alive(priv
, IWL_UCODE_REGULAR
);
241 "Error loading runtime ucode: %d\n", status
);
244 status
= iwl_alive_start(priv
);
247 "Error starting the device: %d\n", status
);
250 case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW
:
251 iwl_scan_cancel_timeout(priv
, 200);
252 priv
->ucode_loaded
= false;
253 iwl_trans_stop_device(trans
);
254 status
= iwl_load_ucode_wait_alive(priv
, IWL_UCODE_WOWLAN
);
257 "Error loading WOWLAN ucode: %d\n", status
);
260 status
= iwl_alive_start(priv
);
263 "Error starting the device: %d\n", status
);
266 case IWL_TM_CMD_APP2DEV_GET_EEPROM
:
267 if (priv
->eeprom_blob
) {
268 skb
= cfg80211_testmode_alloc_reply_skb(hw
->wiphy
,
269 priv
->eeprom_blob_size
+ 20);
271 IWL_ERR(priv
, "Memory allocation fail\n");
274 if (nla_put_u32(skb
, IWL_TM_ATTR_COMMAND
,
275 IWL_TM_CMD_DEV2APP_EEPROM_RSP
) ||
276 nla_put(skb
, IWL_TM_ATTR_EEPROM
,
277 priv
->eeprom_blob_size
,
279 goto nla_put_failure
;
280 status
= cfg80211_testmode_reply(skb
);
282 IWL_ERR(priv
, "Error sending msg : %d\n",
288 case IWL_TM_CMD_APP2DEV_FIXRATE_REQ
:
289 if (!tb
[IWL_TM_ATTR_FIXRATE
]) {
290 IWL_ERR(priv
, "Missing fixrate setting\n");
293 priv
->tm_fixed_rate
= nla_get_u32(tb
[IWL_TM_ATTR_FIXRATE
]);
296 case IWL_TM_CMD_APP2DEV_GET_FW_INFO
:
297 skb
= cfg80211_testmode_alloc_reply_skb(hw
->wiphy
, 20 + 8);
299 IWL_ERR(priv
, "Memory allocation fail\n");
302 if (!priv
->ucode_loaded
) {
303 IWL_ERR(priv
, "No uCode has not been loaded\n");
306 img
= &priv
->fw
->img
[priv
->cur_ucode
];
307 inst_size
= img
->sec
[IWL_UCODE_SECTION_INST
].len
;
308 data_size
= img
->sec
[IWL_UCODE_SECTION_DATA
].len
;
310 if (nla_put_u32(skb
, IWL_TM_ATTR_FW_TYPE
, priv
->cur_ucode
) ||
311 nla_put_u32(skb
, IWL_TM_ATTR_FW_INST_SIZE
, inst_size
) ||
312 nla_put_u32(skb
, IWL_TM_ATTR_FW_DATA_SIZE
, data_size
))
313 goto nla_put_failure
;
314 status
= cfg80211_testmode_reply(skb
);
316 IWL_ERR(priv
, "Error sending msg : %d\n", status
);
320 IWL_ERR(priv
, "Unknown testmode driver command ID\n");
331 * This function handles the user application switch ucode ownership.
333 * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and
334 * decide who the current owner of the uCode
336 * If the current owner is OWNERSHIP_TM, then the only host command
337 * can deliver to uCode is from testmode, all the other host commands
340 * default driver is the owner of uCode in normal operational mode
342 * @hw: ieee80211_hw object that represents the device
343 * @tb: gnl message fields from the user space
345 static int iwl_testmode_ownership(struct ieee80211_hw
*hw
, struct nlattr
**tb
)
347 struct iwl_priv
*priv
= IWL_MAC80211_GET_DVM(hw
);
350 if (!tb
[IWL_TM_ATTR_UCODE_OWNER
]) {
351 IWL_ERR(priv
, "Missing ucode owner\n");
355 owner
= nla_get_u8(tb
[IWL_TM_ATTR_UCODE_OWNER
]);
356 if (owner
== IWL_OWNERSHIP_DRIVER
) {
357 priv
->ucode_owner
= owner
;
358 iwl_test_enable_notifications(&priv
->tst
, false);
359 } else if (owner
== IWL_OWNERSHIP_TM
) {
360 priv
->ucode_owner
= owner
;
361 iwl_test_enable_notifications(&priv
->tst
, true);
363 IWL_ERR(priv
, "Invalid owner\n");
369 /* The testmode gnl message handler that takes the gnl message from the
370 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
371 * invoke the corresponding handlers.
373 * This function is invoked when there is user space application sending
374 * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated
377 * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before
378 * dispatching it to the corresponding handler.
380 * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application;
381 * -ENOSYS is replied to the user application if the command is unknown;
382 * Otherwise, the command is dispatched to the respective handler.
384 * @hw: ieee80211_hw object that represents the device
385 * @data: pointer to user space message
386 * @len: length in byte of @data
388 int iwlagn_mac_testmode_cmd(struct ieee80211_hw
*hw
, void *data
, int len
)
390 struct nlattr
*tb
[IWL_TM_ATTR_MAX
];
391 struct iwl_priv
*priv
= IWL_MAC80211_GET_DVM(hw
);
394 result
= iwl_test_parse(&priv
->tst
, tb
, data
, len
);
398 /* in case multiple accesses to the device happens */
399 mutex_lock(&priv
->mutex
);
400 switch (nla_get_u32(tb
[IWL_TM_ATTR_COMMAND
])) {
401 case IWL_TM_CMD_APP2DEV_UCODE
:
402 case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32
:
403 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32
:
404 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8
:
405 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE
:
406 case IWL_TM_CMD_APP2DEV_END_TRACE
:
407 case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ
:
408 case IWL_TM_CMD_APP2DEV_NOTIFICATIONS
:
409 case IWL_TM_CMD_APP2DEV_GET_FW_VERSION
:
410 case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID
:
411 case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE
:
412 result
= iwl_test_handle_cmd(&priv
->tst
, tb
);
415 case IWL_TM_CMD_APP2DEV_GET_DEVICENAME
:
416 case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW
:
417 case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB
:
418 case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW
:
419 case IWL_TM_CMD_APP2DEV_GET_EEPROM
:
420 case IWL_TM_CMD_APP2DEV_FIXRATE_REQ
:
421 case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW
:
422 case IWL_TM_CMD_APP2DEV_GET_FW_INFO
:
423 IWL_DEBUG_INFO(priv
, "testmode cmd to driver\n");
424 result
= iwl_testmode_driver(hw
, tb
);
427 case IWL_TM_CMD_APP2DEV_OWNERSHIP
:
428 IWL_DEBUG_INFO(priv
, "testmode change uCode ownership\n");
429 result
= iwl_testmode_ownership(hw
, tb
);
433 IWL_ERR(priv
, "Unknown testmode command\n");
437 mutex_unlock(&priv
->mutex
);
440 IWL_ERR(priv
, "Test cmd failed result=%d\n", result
);
444 int iwlagn_mac_testmode_dump(struct ieee80211_hw
*hw
, struct sk_buff
*skb
,
445 struct netlink_callback
*cb
,
448 struct iwl_priv
*priv
= IWL_MAC80211_GET_DVM(hw
);
453 /* offset by 1 since commands start at 0 */
454 cmd
= cb
->args
[3] - 1;
456 struct nlattr
*tb
[IWL_TM_ATTR_MAX
];
458 result
= iwl_test_parse(&priv
->tst
, tb
, data
, len
);
462 cmd
= nla_get_u32(tb
[IWL_TM_ATTR_COMMAND
]);
463 cb
->args
[3] = cmd
+ 1;
466 /* in case multiple accesses to the device happens */
467 mutex_lock(&priv
->mutex
);
468 result
= iwl_test_dump(&priv
->tst
, cmd
, skb
, cb
);
469 mutex_unlock(&priv
->mutex
);