aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-09-05 16:34:44 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-10-16 10:30:45 -0400
commitf042c2eb96779944629fee99817718ede40d4970 (patch)
treea4b66d869348a06214c0398da81869a65fe7a2e3
parent2a79e45eed79c9bf0ff4f93f57f6271d7d1bdb19 (diff)
iwlwifi: make data frame tracing optional
When tracing in iwlwifi, we get all data. Most of the time, we don't need it, and it just takes up a lot of extra space in the trace. Make this optional by recording the data into two separate trace events if it is needed. Without it, record only the content of non-data and EAPOL TX frames. As a result, tracing without the data tracepoints will record meta information including the 802.11 headers for all frames but will not record the contents of data frames to reduce trace overhead. Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-devtrace.h95
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h8
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c3
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c4
5 files changed, 103 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 7ff3f143067..963d02bd985 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -1334,6 +1334,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1334 /* Configure transport layer */ 1334 /* Configure transport layer */
1335 iwl_trans_configure(priv->trans, &trans_cfg); 1335 iwl_trans_configure(priv->trans, &trans_cfg);
1336 1336
1337 trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
1338 trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
1339
1337 /* At this point both hw and priv are allocated. */ 1340 /* At this point both hw and priv are allocated. */
1338 1341
1339 SET_IEEE80211_DEV(priv->hw, priv->trans->dev); 1342 SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index 59a5f78402f..678717bf62e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -25,6 +25,39 @@
25 *****************************************************************************/ 25 *****************************************************************************/
26 26
27#if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ) 27#if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
28#include <linux/skbuff.h>
29#include <linux/ieee80211.h>
30#include <net/cfg80211.h>
31#include "iwl-trans.h"
32#if !defined(__IWLWIFI_DEVICE_TRACE)
33static inline bool iwl_trace_data(struct sk_buff *skb)
34{
35 struct ieee80211_hdr *hdr = (void *)skb->data;
36
37 if (ieee80211_is_data(hdr->frame_control))
38 return skb->protocol != cpu_to_be16(ETH_P_PAE);
39 return false;
40}
41
42static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans,
43 void *rxbuf, size_t len)
44{
45 struct iwl_cmd_header *cmd = (void *)((u8 *)rxbuf + sizeof(__le32));
46 struct ieee80211_hdr *hdr;
47
48 if (cmd->cmd != trans->rx_mpdu_cmd)
49 return len;
50
51 hdr = (void *)((u8 *)cmd + sizeof(struct iwl_cmd_header) +
52 trans->rx_mpdu_cmd_hdr_size);
53 if (!ieee80211_is_data(hdr->frame_control))
54 return len;
55 /* maybe try to identify EAPOL frames? */
56 return sizeof(__le32) + sizeof(*cmd) + trans->rx_mpdu_cmd_hdr_size +
57 ieee80211_hdrlen(hdr->frame_control);
58}
59#endif
60
28#define __IWLWIFI_DEVICE_TRACE 61#define __IWLWIFI_DEVICE_TRACE
29 62
30#include <linux/tracepoint.h> 63#include <linux/tracepoint.h>
@@ -235,6 +268,48 @@ TRACE_EVENT(iwlwifi_dbg,
235); 268);
236 269
237#undef TRACE_SYSTEM 270#undef TRACE_SYSTEM
271#define TRACE_SYSTEM iwlwifi_data
272
273TRACE_EVENT(iwlwifi_dev_tx_data,
274 TP_PROTO(const struct device *dev,
275 struct sk_buff *skb,
276 void *data, size_t data_len),
277 TP_ARGS(dev, skb, data, data_len),
278 TP_STRUCT__entry(
279 DEV_ENTRY
280
281 __dynamic_array(u8, data, iwl_trace_data(skb) ? data_len : 0)
282 ),
283 TP_fast_assign(
284 DEV_ASSIGN;
285 if (iwl_trace_data(skb))
286 memcpy(__get_dynamic_array(data), data, data_len);
287 ),
288 TP_printk("[%s] TX frame data", __get_str(dev))
289);
290
291TRACE_EVENT(iwlwifi_dev_rx_data,
292 TP_PROTO(const struct device *dev,
293 const struct iwl_trans *trans,
294 void *rxbuf, size_t len),
295 TP_ARGS(dev, trans, rxbuf, len),
296 TP_STRUCT__entry(
297 DEV_ENTRY
298
299 __dynamic_array(u8, data,
300 len - iwl_rx_trace_len(trans, rxbuf, len))
301 ),
302 TP_fast_assign(
303 size_t offs = iwl_rx_trace_len(trans, rxbuf, len);
304 DEV_ASSIGN;
305 if (offs < len)
306 memcpy(__get_dynamic_array(data),
307 ((u8 *)rxbuf) + offs, len - offs);
308 ),
309 TP_printk("[%s] TX frame data", __get_str(dev))
310);
311
312#undef TRACE_SYSTEM
238#define TRACE_SYSTEM iwlwifi 313#define TRACE_SYSTEM iwlwifi
239 314
240TRACE_EVENT(iwlwifi_dev_hcmd, 315TRACE_EVENT(iwlwifi_dev_hcmd,
@@ -270,25 +345,28 @@ TRACE_EVENT(iwlwifi_dev_hcmd,
270); 345);
271 346
272TRACE_EVENT(iwlwifi_dev_rx, 347TRACE_EVENT(iwlwifi_dev_rx,
273 TP_PROTO(const struct device *dev, void *rxbuf, size_t len), 348 TP_PROTO(const struct device *dev, const struct iwl_trans *trans,
274 TP_ARGS(dev, rxbuf, len), 349 void *rxbuf, size_t len),
350 TP_ARGS(dev, trans, rxbuf, len),
275 TP_STRUCT__entry( 351 TP_STRUCT__entry(
276 DEV_ENTRY 352 DEV_ENTRY
277 __dynamic_array(u8, rxbuf, len) 353 __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len))
278 ), 354 ),
279 TP_fast_assign( 355 TP_fast_assign(
280 DEV_ASSIGN; 356 DEV_ASSIGN;
281 memcpy(__get_dynamic_array(rxbuf), rxbuf, len); 357 memcpy(__get_dynamic_array(rxbuf), rxbuf,
358 iwl_rx_trace_len(trans, rxbuf, len));
282 ), 359 ),
283 TP_printk("[%s] RX cmd %#.2x", 360 TP_printk("[%s] RX cmd %#.2x",
284 __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4]) 361 __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
285); 362);
286 363
287TRACE_EVENT(iwlwifi_dev_tx, 364TRACE_EVENT(iwlwifi_dev_tx,
288 TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen, 365 TP_PROTO(const struct device *dev, struct sk_buff *skb,
366 void *tfd, size_t tfdlen,
289 void *buf0, size_t buf0_len, 367 void *buf0, size_t buf0_len,
290 void *buf1, size_t buf1_len), 368 void *buf1, size_t buf1_len),
291 TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len), 369 TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
292 TP_STRUCT__entry( 370 TP_STRUCT__entry(
293 DEV_ENTRY 371 DEV_ENTRY
294 372
@@ -301,14 +379,15 @@ TRACE_EVENT(iwlwifi_dev_tx,
301 * for the possible padding). 379 * for the possible padding).
302 */ 380 */
303 __dynamic_array(u8, buf0, buf0_len) 381 __dynamic_array(u8, buf0, buf0_len)
304 __dynamic_array(u8, buf1, buf1_len) 382 __dynamic_array(u8, buf1, iwl_trace_data(skb) ? 0 : buf1_len)
305 ), 383 ),
306 TP_fast_assign( 384 TP_fast_assign(
307 DEV_ASSIGN; 385 DEV_ASSIGN;
308 __entry->framelen = buf0_len + buf1_len; 386 __entry->framelen = buf0_len + buf1_len;
309 memcpy(__get_dynamic_array(tfd), tfd, tfdlen); 387 memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
310 memcpy(__get_dynamic_array(buf0), buf0, buf0_len); 388 memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
311 memcpy(__get_dynamic_array(buf1), buf1, buf1_len); 389 if (!iwl_trace_data(skb))
390 memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
312 ), 391 ),
313 TP_printk("[%s] TX %.2x (%zu bytes)", 392 TP_printk("[%s] TX %.2x (%zu bytes)",
314 __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0], 393 __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index ff115423288..f75ea6d73ff 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -444,6 +444,10 @@ enum iwl_trans_state {
444 * @dev_cmd_headroom: room needed for the transport's private use before the 444 * @dev_cmd_headroom: room needed for the transport's private use before the
445 * device_cmd for Tx - for internal use only 445 * device_cmd for Tx - for internal use only
446 * The user should use iwl_trans_{alloc,free}_tx_cmd. 446 * The user should use iwl_trans_{alloc,free}_tx_cmd.
447 * @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before
448 * starting the firmware, used for tracing
449 * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
450 * start of the 802.11 header in the @rx_mpdu_cmd
447 */ 451 */
448struct iwl_trans { 452struct iwl_trans {
449 const struct iwl_trans_ops *ops; 453 const struct iwl_trans_ops *ops;
@@ -457,6 +461,8 @@ struct iwl_trans {
457 u32 hw_id; 461 u32 hw_id;
458 char hw_id_str[52]; 462 char hw_id_str[52];
459 463
464 u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
465
460 bool pm_support; 466 bool pm_support;
461 467
462 wait_queue_head_t wait_command_queue; 468 wait_queue_head_t wait_command_queue;
@@ -516,6 +522,8 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
516{ 522{
517 might_sleep(); 523 might_sleep();
518 524
525 WARN_ON_ONCE(!trans->rx_mpdu_cmd);
526
519 return trans->ops->start_fw(trans, fw); 527 return trans->ops->start_fw(trans, fw);
520} 528}
521 529
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 17c8e5d8268..137af4c46a6 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -411,7 +411,8 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
411 411
412 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; 412 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
413 len += sizeof(u32); /* account for status word */ 413 len += sizeof(u32); /* account for status word */
414 trace_iwlwifi_dev_rx(trans->dev, pkt, len); 414 trace_iwlwifi_dev_rx(trans->dev, trans, pkt, len);
415 trace_iwlwifi_dev_rx_data(trans->dev, trans, pkt, len);
415 416
416 /* Reclaim a command buffer only if this packet is a response 417 /* Reclaim a command buffer only if this packet is a response
417 * to a (driver-originated) command. 418 * to a (driver-originated) command.
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index fe0fffd0430..23490437def 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1385,11 +1385,13 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
1385 dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, 1385 dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
1386 DMA_BIDIRECTIONAL); 1386 DMA_BIDIRECTIONAL);
1387 1387
1388 trace_iwlwifi_dev_tx(trans->dev, 1388 trace_iwlwifi_dev_tx(trans->dev, skb,
1389 &txq->tfds[txq->q.write_ptr], 1389 &txq->tfds[txq->q.write_ptr],
1390 sizeof(struct iwl_tfd), 1390 sizeof(struct iwl_tfd),
1391 &dev_cmd->hdr, firstlen, 1391 &dev_cmd->hdr, firstlen,
1392 skb->data + hdr_len, secondlen); 1392 skb->data + hdr_len, secondlen);
1393 trace_iwlwifi_dev_tx_data(trans->dev, skb,
1394 skb->data + hdr_len, secondlen);
1393 1395
1394 /* start timer if queue currently empty */ 1396 /* start timer if queue currently empty */
1395 if (txq->need_update && q->read_ptr == q->write_ptr && 1397 if (txq->need_update && q->read_ptr == q->write_ptr &&