diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sv-open.c | 106 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-testmode.h | 4 |
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 | ||
3357 | static u32 iwl_hw_detect(struct iwl_priv *priv) | 3358 | static 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 |
345 | extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); | 345 | extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); |
346 | extern int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
347 | struct netlink_callback *cb, | ||
348 | void *data, int len); | ||
346 | extern void iwl_testmode_init(struct iwl_priv *priv); | 349 | extern void iwl_testmode_init(struct iwl_priv *priv); |
347 | extern void iwl_testmode_cleanup(struct iwl_priv *priv); | 350 | extern 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 | } |
354 | static inline | 357 | static inline |
358 | int 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 | } | ||
364 | static inline | ||
355 | void iwl_testmode_init(struct iwl_priv *priv) | 365 | void 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 { | |||
1172 | struct iwl_testmode_trace { | 1172 | struct 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 | ||
559 | static 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 | |||
669 | int 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 |