aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-sv-open.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-sv-open.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sv-open.c177
1 files changed, 174 insertions, 3 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
index 89b6696622c1..69b7e6bf2d6f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
@@ -97,6 +97,13 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
97 97
98 [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, 98 [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, },
99 [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, 99 [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, },
100
101 [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
102
103 [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
104 [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, },
105
106 [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
100}; 107};
101 108
102/* 109/*
@@ -167,6 +174,31 @@ nla_put_failure:
167void iwl_testmode_init(struct iwl_priv *priv) 174void iwl_testmode_init(struct iwl_priv *priv)
168{ 175{
169 priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; 176 priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
177 priv->testmode_trace.trace_enabled = false;
178}
179
180static void iwl_trace_cleanup(struct iwl_priv *priv)
181{
182 struct device *dev = &priv->pci_dev->dev;
183
184 if (priv->testmode_trace.trace_enabled) {
185 if (priv->testmode_trace.cpu_addr &&
186 priv->testmode_trace.dma_addr)
187 dma_free_coherent(dev,
188 TRACE_TOTAL_SIZE,
189 priv->testmode_trace.cpu_addr,
190 priv->testmode_trace.dma_addr);
191 priv->testmode_trace.trace_enabled = false;
192 priv->testmode_trace.cpu_addr = NULL;
193 priv->testmode_trace.trace_addr = NULL;
194 priv->testmode_trace.dma_addr = 0;
195 }
196}
197
198
199void iwl_testmode_cleanup(struct iwl_priv *priv)
200{
201 iwl_trace_cleanup(priv);
170} 202}
171 203
172/* 204/*
@@ -198,10 +230,11 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
198 } 230 }
199 231
200 cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); 232 cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
201 cmd.data = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); 233 cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
202 cmd.len = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); 234 cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
235 cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
203 IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," 236 IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
204 " len %d\n", cmd.id, cmd.flags, cmd.len); 237 " len %d\n", cmd.id, cmd.flags, cmd.len[0]);
205 /* ok, let's submit the command to ucode */ 238 /* ok, let's submit the command to ucode */
206 return iwl_send_cmd(priv, &cmd); 239 return iwl_send_cmd(priv, &cmd);
207} 240}
@@ -388,6 +421,38 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
388 "Error starting the device: %d\n", status); 421 "Error starting the device: %d\n", status);
389 break; 422 break;
390 423
424 case IWL_TM_CMD_APP2DEV_GET_EEPROM:
425 if (priv->eeprom) {
426 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
427 priv->cfg->base_params->eeprom_size + 20);
428 if (!skb) {
429 IWL_DEBUG_INFO(priv,
430 "Error allocating memory\n");
431 return -ENOMEM;
432 }
433 NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
434 IWL_TM_CMD_DEV2APP_EEPROM_RSP);
435 NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
436 priv->cfg->base_params->eeprom_size,
437 priv->eeprom);
438 status = cfg80211_testmode_reply(skb);
439 if (status < 0)
440 IWL_DEBUG_INFO(priv,
441 "Error sending msg : %d\n",
442 status);
443 } else
444 return -EFAULT;
445 break;
446
447 case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
448 if (!tb[IWL_TM_ATTR_FIXRATE]) {
449 IWL_DEBUG_INFO(priv,
450 "Error finding fixrate setting\n");
451 return -ENOMSG;
452 }
453 priv->dbg_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
454 break;
455
391 default: 456 default:
392 IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); 457 IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n");
393 return -ENOSYS; 458 return -ENOSYS;
@@ -399,6 +464,102 @@ nla_put_failure:
399 return -EMSGSIZE; 464 return -EMSGSIZE;
400} 465}
401 466
467
468/*
469 * This function handles the user application commands for uCode trace
470 *
471 * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
472 * handlers respectively.
473 *
474 * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
475 * value of the actual command execution is replied to the user application.
476 *
477 * @hw: ieee80211_hw object that represents the device
478 * @tb: gnl message fields from the user space
479 */
480static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
481{
482 struct iwl_priv *priv = hw->priv;
483 struct sk_buff *skb;
484 int status = 0;
485 struct device *dev = &priv->pci_dev->dev;
486
487 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
488 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
489 if (priv->testmode_trace.trace_enabled)
490 return -EBUSY;
491
492 priv->testmode_trace.cpu_addr =
493 dma_alloc_coherent(dev,
494 TRACE_TOTAL_SIZE,
495 &priv->testmode_trace.dma_addr,
496 GFP_KERNEL);
497 if (!priv->testmode_trace.cpu_addr)
498 return -ENOMEM;
499 priv->testmode_trace.trace_enabled = true;
500 priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
501 priv->testmode_trace.cpu_addr, 0x100);
502 memset(priv->testmode_trace.trace_addr, 0x03B,
503 TRACE_BUFF_SIZE);
504 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
505 sizeof(priv->testmode_trace.dma_addr) + 20);
506 if (!skb) {
507 IWL_DEBUG_INFO(priv,
508 "Error allocating memory\n");
509 iwl_trace_cleanup(priv);
510 return -ENOMEM;
511 }
512 NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR,
513 sizeof(priv->testmode_trace.dma_addr),
514 (u64 *)&priv->testmode_trace.dma_addr);
515 status = cfg80211_testmode_reply(skb);
516 if (status < 0) {
517 IWL_DEBUG_INFO(priv,
518 "Error sending msg : %d\n",
519 status);
520 }
521 break;
522
523 case IWL_TM_CMD_APP2DEV_END_TRACE:
524 iwl_trace_cleanup(priv);
525 break;
526
527 case IWL_TM_CMD_APP2DEV_READ_TRACE:
528 if (priv->testmode_trace.trace_enabled &&
529 priv->testmode_trace.trace_addr) {
530 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
531 20 + TRACE_BUFF_SIZE);
532 if (skb == NULL) {
533 IWL_DEBUG_INFO(priv,
534 "Error allocating memory\n");
535 return -ENOMEM;
536 }
537 NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA,
538 TRACE_BUFF_SIZE,
539 priv->testmode_trace.trace_addr);
540 status = cfg80211_testmode_reply(skb);
541 if (status < 0) {
542 IWL_DEBUG_INFO(priv,
543 "Error sending msg : %d\n", status);
544 }
545 } else
546 return -EFAULT;
547 break;
548
549 default:
550 IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
551 return -ENOSYS;
552 }
553 return status;
554
555nla_put_failure:
556 kfree_skb(skb);
557 if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) ==
558 IWL_TM_CMD_APP2DEV_BEGIN_TRACE)
559 iwl_trace_cleanup(priv);
560 return -EMSGSIZE;
561}
562
402/* The testmode gnl message handler that takes the gnl message from the 563/* The testmode gnl message handler that takes the gnl message from the
403 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then 564 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
404 * invoke the corresponding handlers. 565 * invoke the corresponding handlers.
@@ -455,9 +616,19 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
455 case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: 616 case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
456 case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: 617 case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
457 case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: 618 case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
619 case IWL_TM_CMD_APP2DEV_GET_EEPROM:
620 case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
458 IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); 621 IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
459 result = iwl_testmode_driver(hw, tb); 622 result = iwl_testmode_driver(hw, tb);
460 break; 623 break;
624
625 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
626 case IWL_TM_CMD_APP2DEV_END_TRACE:
627 case IWL_TM_CMD_APP2DEV_READ_TRACE:
628 IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n");
629 result = iwl_testmode_trace(hw, tb);
630 break;
631
461 default: 632 default:
462 IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); 633 IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
463 result = -ENOSYS; 634 result = -ENOSYS;