aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sv-open.c133
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.h15
5 files changed, 165 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index a7054a5ee34a..e027f99f18a5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3659,6 +3659,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
3659 */ 3659 */
3660 set_bit(STATUS_EXIT_PENDING, &priv->status); 3660 set_bit(STATUS_EXIT_PENDING, &priv->status);
3661 3661
3662 iwl_testmode_cleanup(priv);
3662 iwl_leds_exit(priv); 3663 iwl_leds_exit(priv);
3663 3664
3664 if (priv->mac80211_registered) { 3665 if (priv->mac80211_registered) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index fc7dc0628316..2495fe7a58cb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -343,6 +343,7 @@ extern int iwl_alive_start(struct iwl_priv *priv);
343#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL 343#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
344extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); 344extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len);
345extern void iwl_testmode_init(struct iwl_priv *priv); 345extern void iwl_testmode_init(struct iwl_priv *priv);
346extern void iwl_testmode_cleanup(struct iwl_priv *priv);
346#else 347#else
347static inline 348static inline
348int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) 349int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
@@ -353,6 +354,10 @@ static inline
353void iwl_testmode_init(struct iwl_priv *priv) 354void iwl_testmode_init(struct iwl_priv *priv)
354{ 355{
355} 356}
357static inline
358void iwl_testmode_cleanup(struct iwl_priv *priv)
359{
360}
356#endif 361#endif
357 362
358#endif /* __iwl_agn_h__ */ 363#endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 3e3b8b8939d6..12fb2f4ca0b1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1179,6 +1179,14 @@ enum iwl_scan_type {
1179 IWL_SCAN_OFFCH_TX, 1179 IWL_SCAN_OFFCH_TX,
1180}; 1180};
1181 1181
1182#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
1183struct iwl_testmode_trace {
1184 u8 *cpu_addr;
1185 u8 *trace_addr;
1186 dma_addr_t dma_addr;
1187 bool trace_enabled;
1188};
1189#endif
1182struct iwl_priv { 1190struct iwl_priv {
1183 1191
1184 /* ieee device used by generic ieee processing code */ 1192 /* ieee device used by generic ieee processing code */
@@ -1510,6 +1518,9 @@ struct iwl_priv {
1510 struct led_classdev led; 1518 struct led_classdev led;
1511 unsigned long blink_on, blink_off; 1519 unsigned long blink_on, blink_off;
1512 bool led_registered; 1520 bool led_registered;
1521#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
1522 struct iwl_testmode_trace testmode_trace;
1523#endif
1513}; /*iwl_priv */ 1524}; /*iwl_priv */
1514 1525
1515static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) 1526static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
index dd2904aa9be2..b778c3f4b84d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
@@ -97,6 +97,10 @@ 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_TRACE_ADDR] = { .type = NLA_UNSPEC, },
102 [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, },
103
100}; 104};
101 105
102/* 106/*
@@ -167,6 +171,31 @@ nla_put_failure:
167void iwl_testmode_init(struct iwl_priv *priv) 171void iwl_testmode_init(struct iwl_priv *priv)
168{ 172{
169 priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; 173 priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
174 priv->testmode_trace.trace_enabled = false;
175}
176
177static void iwl_trace_cleanup(struct iwl_priv *priv)
178{
179 struct device *dev = &priv->pci_dev->dev;
180
181 if (priv->testmode_trace.trace_enabled) {
182 if (priv->testmode_trace.cpu_addr &&
183 priv->testmode_trace.dma_addr)
184 dma_free_coherent(dev,
185 TRACE_TOTAL_SIZE,
186 priv->testmode_trace.cpu_addr,
187 priv->testmode_trace.dma_addr);
188 priv->testmode_trace.trace_enabled = false;
189 priv->testmode_trace.cpu_addr = NULL;
190 priv->testmode_trace.trace_addr = NULL;
191 priv->testmode_trace.dma_addr = 0;
192 }
193}
194
195
196void iwl_testmode_cleanup(struct iwl_priv *priv)
197{
198 iwl_trace_cleanup(priv);
170} 199}
171 200
172/* 201/*
@@ -400,6 +429,102 @@ nla_put_failure:
400 return -EMSGSIZE; 429 return -EMSGSIZE;
401} 430}
402 431
432
433/*
434 * This function handles the user application commands for uCode trace
435 *
436 * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
437 * handlers respectively.
438 *
439 * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
440 * value of the actual command execution is replied to the user application.
441 *
442 * @hw: ieee80211_hw object that represents the device
443 * @tb: gnl message fields from the user space
444 */
445static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
446{
447 struct iwl_priv *priv = hw->priv;
448 struct sk_buff *skb;
449 int status = 0;
450 struct device *dev = &priv->pci_dev->dev;
451
452 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
453 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
454 if (priv->testmode_trace.trace_enabled)
455 return -EBUSY;
456
457 priv->testmode_trace.cpu_addr =
458 dma_alloc_coherent(dev,
459 TRACE_TOTAL_SIZE,
460 &priv->testmode_trace.dma_addr,
461 GFP_KERNEL);
462 if (!priv->testmode_trace.cpu_addr)
463 return -ENOMEM;
464 priv->testmode_trace.trace_enabled = true;
465 priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
466 priv->testmode_trace.cpu_addr, 0x100);
467 memset(priv->testmode_trace.trace_addr, 0x03B,
468 TRACE_BUFF_SIZE);
469 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
470 sizeof(priv->testmode_trace.dma_addr) + 20);
471 if (!skb) {
472 IWL_DEBUG_INFO(priv,
473 "Error allocating memory\n");
474 iwl_trace_cleanup(priv);
475 return -ENOMEM;
476 }
477 NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR,
478 sizeof(priv->testmode_trace.dma_addr),
479 (u64 *)&priv->testmode_trace.dma_addr);
480 status = cfg80211_testmode_reply(skb);
481 if (status < 0) {
482 IWL_DEBUG_INFO(priv,
483 "Error sending msg : %d\n",
484 status);
485 }
486 break;
487
488 case IWL_TM_CMD_APP2DEV_END_TRACE:
489 iwl_trace_cleanup(priv);
490 break;
491
492 case IWL_TM_CMD_APP2DEV_READ_TRACE:
493 if (priv->testmode_trace.trace_enabled &&
494 priv->testmode_trace.trace_addr) {
495 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
496 20 + TRACE_BUFF_SIZE);
497 if (skb == NULL) {
498 IWL_DEBUG_INFO(priv,
499 "Error allocating memory\n");
500 return -ENOMEM;
501 }
502 NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA,
503 TRACE_BUFF_SIZE,
504 priv->testmode_trace.trace_addr);
505 status = cfg80211_testmode_reply(skb);
506 if (status < 0) {
507 IWL_DEBUG_INFO(priv,
508 "Error sending msg : %d\n", status);
509 }
510 } else
511 return -EFAULT;
512 break;
513
514 default:
515 IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
516 return -ENOSYS;
517 }
518 return status;
519
520nla_put_failure:
521 kfree_skb(skb);
522 if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) ==
523 IWL_TM_CMD_APP2DEV_BEGIN_TRACE)
524 iwl_trace_cleanup(priv);
525 return -EMSGSIZE;
526}
527
403/* The testmode gnl message handler that takes the gnl message from the 528/* The testmode gnl message handler that takes the gnl message from the
404 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then 529 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
405 * invoke the corresponding handlers. 530 * invoke the corresponding handlers.
@@ -459,6 +584,14 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
459 IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); 584 IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
460 result = iwl_testmode_driver(hw, tb); 585 result = iwl_testmode_driver(hw, tb);
461 break; 586 break;
587
588 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
589 case IWL_TM_CMD_APP2DEV_END_TRACE:
590 case IWL_TM_CMD_APP2DEV_READ_TRACE:
591 IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n");
592 result = iwl_testmode_trace(hw, tb);
593 break;
594
462 default: 595 default:
463 IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); 596 IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
464 result = -ENOSYS; 597 result = -ENOSYS;
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index 31f8949f2801..34634eca94ec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h
@@ -91,6 +91,10 @@ enum iwl_tm_cmd_t {
91 /* if there is other new command for the driver layer operation, 91 /* if there is other new command for the driver layer operation,
92 * append them here */ 92 * append them here */
93 93
94 /* commands fom user space for uCode trace operations */
95 IWL_TM_CMD_APP2DEV_BEGIN_TRACE,
96 IWL_TM_CMD_APP2DEV_END_TRACE,
97 IWL_TM_CMD_APP2DEV_READ_TRACE,
94 98
95 /* commands from kernel space to carry the synchronous response 99 /* commands from kernel space to carry the synchronous response
96 * to user application */ 100 * to user application */
@@ -144,8 +148,19 @@ enum iwl_tm_attr_t {
144 * application */ 148 * application */
145 IWL_TM_ATTR_UCODE_RX_PKT, 149 IWL_TM_ATTR_UCODE_RX_PKT,
146 150
151 /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,
152 * The mandatory fields are:
153 * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
154 */
155 IWL_TM_ATTR_TRACE_ADDR,
156 IWL_TM_ATTR_TRACE_DATA,
157
147 IWL_TM_ATTR_MAX, 158 IWL_TM_ATTR_MAX,
148}; 159};
149 160
161/* uCode trace buffer */
162#define TRACE_BUFF_SIZE 0x20000
163#define TRACE_BUFF_PADD 0x2000
164#define TRACE_TOTAL_SIZE (TRACE_BUFF_SIZE + TRACE_BUFF_PADD)
150 165
151#endif 166#endif