aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2011-05-31 11:03:02 -0400
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2011-06-11 10:08:23 -0400
commiteb64dca0c9d73e191026ed37d1075f22e48b3f1c (patch)
treec46df5b1e4cf7b7d8822c444def4348d2f278456
parent49b72100165e3b2046be15a8e4f766f5169e708d (diff)
iwlagn: add dumpit support for testmode trace function
For testmode trace function, huge amout of data need to pass to userspace. Use the build-in nl80211 dumpt it function Require nl80211 testmode dumpit support patch. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sv-open.c106
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.h4
5 files changed, 96 insertions, 26 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 099c2795ec0b..6f1edb4f3886 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3352,6 +3352,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
3352 .offchannel_tx = iwl_mac_offchannel_tx, 3352 .offchannel_tx = iwl_mac_offchannel_tx,
3353 .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait, 3353 .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
3354 CFG80211_TESTMODE_CMD(iwl_testmode_cmd) 3354 CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
3355 CFG80211_TESTMODE_DUMP(iwl_testmode_dump)
3355}; 3356};
3356 3357
3357static u32 iwl_hw_detect(struct iwl_priv *priv) 3358static u32 iwl_hw_detect(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index d1716844002e..d074e6c7a575 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -343,6 +343,9 @@ extern int iwl_alive_start(struct iwl_priv *priv);
343/* svtool */ 343/* svtool */
344#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL 344#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
345extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); 345extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len);
346extern int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
347 struct netlink_callback *cb,
348 void *data, int len);
346extern void iwl_testmode_init(struct iwl_priv *priv); 349extern void iwl_testmode_init(struct iwl_priv *priv);
347extern void iwl_testmode_cleanup(struct iwl_priv *priv); 350extern void iwl_testmode_cleanup(struct iwl_priv *priv);
348#else 351#else
@@ -352,6 +355,13 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
352 return -ENOSYS; 355 return -ENOSYS;
353} 356}
354static inline 357static inline
358int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
359 struct netlink_callback *cb,
360 void *data, int len)
361{
362 return -ENOSYS;
363}
364static inline
355void iwl_testmode_init(struct iwl_priv *priv) 365void iwl_testmode_init(struct iwl_priv *priv)
356{ 366{
357} 367}
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index a7d2159537a5..d23430e10004 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1172,6 +1172,7 @@ enum iwl_scan_type {
1172struct iwl_testmode_trace { 1172struct iwl_testmode_trace {
1173 u32 buff_size; 1173 u32 buff_size;
1174 u32 total_size; 1174 u32 total_size;
1175 u32 num_chunks;
1175 u8 *cpu_addr; 1176 u8 *cpu_addr;
1176 u8 *trace_addr; 1177 u8 *trace_addr;
1177 dma_addr_t dma_addr; 1178 dma_addr_t dma_addr;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
index 135c1b5f25ae..038c6961c46a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
@@ -100,7 +100,7 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
100 [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, }, 100 [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
101 101
102 [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, 102 [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
103 [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, }, 103 [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, },
104 [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, }, 104 [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, },
105 105
106 [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, 106 [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
@@ -534,34 +534,14 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
534 "Error sending msg : %d\n", 534 "Error sending msg : %d\n",
535 status); 535 status);
536 } 536 }
537 priv->testmode_trace.num_chunks =
538 DIV_ROUND_UP(priv->testmode_trace.buff_size,
539 TRACE_CHUNK_SIZE);
537 break; 540 break;
538 541
539 case IWL_TM_CMD_APP2DEV_END_TRACE: 542 case IWL_TM_CMD_APP2DEV_END_TRACE:
540 iwl_trace_cleanup(priv); 543 iwl_trace_cleanup(priv);
541 break; 544 break;
542
543 case IWL_TM_CMD_APP2DEV_READ_TRACE:
544 if (priv->testmode_trace.trace_enabled &&
545 priv->testmode_trace.trace_addr) {
546 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
547 20 + priv->testmode_trace.buff_size);
548 if (skb == NULL) {
549 IWL_DEBUG_INFO(priv,
550 "Error allocating memory\n");
551 return -ENOMEM;
552 }
553 NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA,
554 priv->testmode_trace.buff_size,
555 priv->testmode_trace.trace_addr);
556 status = cfg80211_testmode_reply(skb);
557 if (status < 0) {
558 IWL_DEBUG_INFO(priv,
559 "Error sending msg : %d\n", status);
560 }
561 } else
562 return -EFAULT;
563 break;
564
565 default: 545 default:
566 IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n"); 546 IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
567 return -ENOSYS; 547 return -ENOSYS;
@@ -576,6 +556,37 @@ nla_put_failure:
576 return -EMSGSIZE; 556 return -EMSGSIZE;
577} 557}
578 558
559static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
560 struct sk_buff *skb,
561 struct netlink_callback *cb)
562{
563 struct iwl_priv *priv = hw->priv;
564 int idx, length;
565
566 if (priv->testmode_trace.trace_enabled &&
567 priv->testmode_trace.trace_addr) {
568 idx = cb->args[4];
569 if (idx >= priv->testmode_trace.num_chunks)
570 return -ENOENT;
571 length = TRACE_CHUNK_SIZE;
572 if (((idx + 1) == priv->testmode_trace.num_chunks) &&
573 (priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE))
574 length = priv->testmode_trace.buff_size %
575 TRACE_CHUNK_SIZE;
576
577 NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length,
578 priv->testmode_trace.trace_addr +
579 (TRACE_CHUNK_SIZE * idx));
580 idx++;
581 cb->args[4] = idx;
582 return 0;
583 } else
584 return -EFAULT;
585
586 nla_put_failure:
587 return -ENOBUFS;
588}
589
579/* The testmode gnl message handler that takes the gnl message from the 590/* The testmode gnl message handler that takes the gnl message from the
580 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then 591 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
581 * invoke the corresponding handlers. 592 * invoke the corresponding handlers.
@@ -654,3 +665,50 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
654 mutex_unlock(&priv->mutex); 665 mutex_unlock(&priv->mutex);
655 return result; 666 return result;
656} 667}
668
669int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
670 struct netlink_callback *cb,
671 void *data, int len)
672{
673 struct nlattr *tb[IWL_TM_ATTR_MAX];
674 struct iwl_priv *priv = hw->priv;
675 int result;
676 u32 cmd;
677
678 if (cb->args[3]) {
679 /* offset by 1 since commands start at 0 */
680 cmd = cb->args[3] - 1;
681 } else {
682 result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
683 iwl_testmode_gnl_msg_policy);
684 if (result) {
685 IWL_DEBUG_INFO(priv,
686 "Error parsing the gnl message : %d\n", result);
687 return result;
688 }
689
690 /* IWL_TM_ATTR_COMMAND is absolutely mandatory */
691 if (!tb[IWL_TM_ATTR_COMMAND]) {
692 IWL_DEBUG_INFO(priv,
693 "Error finding testmode command type\n");
694 return -ENOMSG;
695 }
696 cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
697 cb->args[3] = cmd + 1;
698 }
699
700 /* in case multiple accesses to the device happens */
701 mutex_lock(&priv->mutex);
702 switch (cmd) {
703 case IWL_TM_CMD_APP2DEV_READ_TRACE:
704 IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
705 result = iwl_testmode_trace_dump(hw, tb, skb, cb);
706 break;
707 default:
708 result = -EINVAL;
709 break;
710 }
711
712 mutex_unlock(&priv->mutex);
713 return result;
714}
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index f3f406e1766e..160911a3716a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h
@@ -166,8 +166,8 @@ enum iwl_tm_attr_t {
166 * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address 166 * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
167 */ 167 */
168 IWL_TM_ATTR_TRACE_ADDR, 168 IWL_TM_ATTR_TRACE_ADDR,
169 IWL_TM_ATTR_TRACE_DATA,
170 IWL_TM_ATTR_TRACE_SIZE, 169 IWL_TM_ATTR_TRACE_SIZE,
170 IWL_TM_ATTR_TRACE_DUMP,
171 171
172 /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ, 172 /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
173 * The mandatory fields are: 173 * The mandatory fields are:
@@ -182,7 +182,7 @@ enum iwl_tm_attr_t {
182#define TRACE_BUFF_SIZE_MAX 0x200000 182#define TRACE_BUFF_SIZE_MAX 0x200000
183#define TRACE_BUFF_SIZE_MIN 0x20000 183#define TRACE_BUFF_SIZE_MIN 0x20000
184#define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN 184#define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN
185
186#define TRACE_BUFF_PADD 0x2000 185#define TRACE_BUFF_PADD 0x2000
186#define TRACE_CHUNK_SIZE (PAGE_SIZE - 1024)
187 187
188#endif 188#endif