Commit 34dd5feb authored by Zhu Yi's avatar Zhu Yi Committed by John W. Linville

iwmc3200wifi: add ftrace event tracing support

Add event tracer for iwmc3200wifi driver. When enabled, all the
commands and responses between the driver and firmware (also
including Tx/Rx frames) will be recorded in the ftrace ring buffer.
Signed-off-by: default avatarZhu Yi <yi.zhu@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 04d1c227
...@@ -17,7 +17,7 @@ config IWM ...@@ -17,7 +17,7 @@ config IWM
config IWM_DEBUG config IWM_DEBUG
bool "Enable full debugging output in iwmc3200wifi" bool "Enable full debugging output in iwmc3200wifi"
depends on IWM && DEBUG_FS depends on IWM && DEBUG_FS
---help--- help
This option will enable debug tracing and setting for iwm This option will enable debug tracing and setting for iwm
You can set the debug level and module through debugfs. By You can set the debug level and module through debugfs. By
...@@ -30,3 +30,10 @@ config IWM_DEBUG ...@@ -30,3 +30,10 @@ config IWM_DEBUG
Or, if you want the full debug, for all modules: Or, if you want the full debug, for all modules:
echo 0xff > /sys/kernel/debug/iwm/phyN/debug/level echo 0xff > /sys/kernel/debug/iwm/phyN/debug/level
echo 0xff > /sys/kernel/debug/iwm/phyN/debug/modules echo 0xff > /sys/kernel/debug/iwm/phyN/debug/modules
config IWM_TRACING
bool "Enable event tracing for iwmc3200wifi"
depends on IWM && EVENT_TRACING
help
Say Y here to trace all the commands and responses between
the driver and firmware (including TX/RX frames) with ftrace.
...@@ -3,3 +3,6 @@ iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o ...@@ -3,3 +3,6 @@ iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o
iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o
CFLAGS_trace.o := -I$(src)
...@@ -104,6 +104,7 @@ ...@@ -104,6 +104,7 @@
#include "hal.h" #include "hal.h"
#include "umac.h" #include "umac.h"
#include "debug.h" #include "debug.h"
#include "trace.h"
static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm, static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm,
struct iwm_nonwifi_cmd *cmd, struct iwm_nonwifi_cmd *cmd,
...@@ -276,6 +277,7 @@ static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm, ...@@ -276,6 +277,7 @@ static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm,
udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr, udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr,
udma_cmd->op1_sz, udma_cmd->op2); udma_cmd->op1_sz, udma_cmd->op2);
trace_iwm_tx_nonwifi_cmd(iwm, udma_hdr);
return iwm_bus_send_chunk(iwm, buf->start, buf->len); return iwm_bus_send_chunk(iwm, buf->start, buf->len);
} }
...@@ -362,6 +364,7 @@ static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm, ...@@ -362,6 +364,7 @@ static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm,
return ret; return ret;
} }
trace_iwm_tx_wifi_cmd(iwm, umac_hdr);
return iwm_bus_send_chunk(iwm, buf->start, buf->len); return iwm_bus_send_chunk(iwm, buf->start, buf->len);
} }
......
...@@ -75,7 +75,8 @@ do { \ ...@@ -75,7 +75,8 @@ do { \
/* UDMA IN OP CODE -- cmd bits [3:0] */ /* UDMA IN OP CODE -- cmd bits [3:0] */
#define UDMA_IN_OPCODE_MASK 0xF #define UDMA_HDI_IN_NW_CMD_OPCODE_POS 0
#define UDMA_HDI_IN_NW_CMD_OPCODE_SEED 0xF
#define UDMA_IN_OPCODE_GENERAL_RESP 0x0 #define UDMA_IN_OPCODE_GENERAL_RESP 0x0
#define UDMA_IN_OPCODE_READ_RESP 0x1 #define UDMA_IN_OPCODE_READ_RESP 0x1
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "umac.h" #include "umac.h"
#include "lmac.h" #include "lmac.h"
#include "eeprom.h" #include "eeprom.h"
#include "trace.h"
#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation" #define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation"
#define IWM_AUTHOR "<ilw@linux.intel.com>" #define IWM_AUTHOR "<ilw@linux.intel.com>"
......
...@@ -1235,18 +1235,24 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf, ...@@ -1235,18 +1235,24 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
u8 source, cmd_id; u8 source, cmd_id;
u16 seq_num; u16 seq_num;
u32 count; u32 count;
u8 resp;
wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
cmd_id = wifi_hdr->sw_hdr.cmd.cmd; cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
if (source >= IWM_SRC_NUM) { if (source >= IWM_SRC_NUM) {
IWM_CRIT(iwm, "invalid source %d\n", source); IWM_CRIT(iwm, "invalid source %d\n", source);
return -EINVAL; return -EINVAL;
} }
count = (GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT)); if (cmd_id == REPLY_RX_MPDU_CMD)
trace_iwm_rx_packet(iwm, buf, buf_size);
else if ((cmd_id == UMAC_NOTIFY_OPCODE_RX_TICKET) &&
(source == UMAC_HDI_IN_SOURCE_FW))
trace_iwm_rx_ticket(iwm, buf, buf_size);
else
trace_iwm_rx_wifi_cmd(iwm, wifi_hdr);
count = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT);
count += sizeof(struct iwm_umac_wifi_in_hdr) - count += sizeof(struct iwm_umac_wifi_in_hdr) -
sizeof(struct iwm_dev_cmd_hdr); sizeof(struct iwm_dev_cmd_hdr);
if (count > buf_size) { if (count > buf_size) {
...@@ -1254,8 +1260,6 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf, ...@@ -1254,8 +1260,6 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
return -EINVAL; return -EINVAL;
} }
resp = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_STATUS);
seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n", IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n",
...@@ -1330,6 +1334,7 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf, ...@@ -1330,6 +1334,7 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf,
struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf; struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf;
struct iwm_nonwifi_cmd *cmd; struct iwm_nonwifi_cmd *cmd;
trace_iwm_rx_nonwifi_cmd(iwm, buf, buf_size);
seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
/* /*
......
#include "iwm.h"
#define CREATE_TRACE_POINTS
#include "trace.h"
#if !defined(__IWM_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
#define __IWM_TRACE_H__
#include <linux/tracepoint.h>
#if !defined(CONFIG_IWM_TRACING)
#undef TRACE_EVENT
#define TRACE_EVENT(name, proto, ...) \
static inline void trace_ ## name(proto) {}
#endif
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwm
#define IWM_ENTRY __array(char, ndev_name, 16)
#define IWM_ASSIGN strlcpy(__entry->ndev_name, iwm_to_ndev(iwm)->name, 16)
#define IWM_PR_FMT "%s"
#define IWM_PR_ARG __entry->ndev_name
TRACE_EVENT(iwm_tx_nonwifi_cmd,
TP_PROTO(struct iwm_priv *iwm, struct iwm_udma_out_nonwifi_hdr *hdr),
TP_ARGS(iwm, hdr),
TP_STRUCT__entry(
IWM_ENTRY
__field(u8, opcode)
__field(u8, resp)
__field(u8, eot)
__field(u8, hw)
__field(u16, seq)
__field(u32, addr)
__field(u32, op1)
__field(u32, op2)
),
TP_fast_assign(
IWM_ASSIGN;
__entry->opcode = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE);
__entry->resp = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP);
__entry->eot = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT);
__entry->hw = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW);
__entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM);
__entry->addr = le32_to_cpu(hdr->addr);
__entry->op1 = le32_to_cpu(hdr->op1_sz);
__entry->op2 = le32_to_cpu(hdr->op2);
),
TP_printk(
IWM_PR_FMT " Tx TARGET CMD: opcode 0x%x, resp %d, eot %d, "
"hw %d, seq 0x%x, addr 0x%x, op1 0x%x, op2 0x%x",
IWM_PR_ARG, __entry->opcode, __entry->resp, __entry->eot,
__entry->hw, __entry->seq, __entry->addr, __entry->op1,
__entry->op2
)
);
TRACE_EVENT(iwm_tx_wifi_cmd,
TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_out_hdr *hdr),
TP_ARGS(iwm, hdr),
TP_STRUCT__entry(
IWM_ENTRY
__field(u8, opcode)
__field(u8, lmac)
__field(u8, resp)
__field(u8, eot)
__field(u8, ra_tid)
__field(u8, credit_group)
__field(u8, color)
__field(u16, seq)
),
TP_fast_assign(
IWM_ASSIGN;
__entry->opcode = hdr->sw_hdr.cmd.cmd;
__entry->lmac = 0;
__entry->seq = hdr->sw_hdr.cmd.seq_num;
__entry->resp = GET_VAL8(hdr->sw_hdr.cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ);
__entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);
__entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT);
__entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID);
__entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP);
if (__entry->opcode == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH ||
__entry->opcode == UMAC_CMD_OPCODE_WIFI_IF_WRAPPER) {
__entry->lmac = 1;
__entry->opcode = ((struct iwm_lmac_hdr *)(hdr + 1))->id;
}
),
TP_printk(
IWM_PR_FMT " Tx %cMAC CMD: opcode 0x%x, resp %d, eot %d, "
"seq 0x%x, sta_color 0x%x, ra_tid 0x%x, credit_group 0x%x",
IWM_PR_ARG, __entry->lmac ? 'L' : 'U', __entry->opcode,
__entry->resp, __entry->eot, __entry->seq, __entry->color,
__entry->ra_tid, __entry->credit_group
)
);
TRACE_EVENT(iwm_tx_packets,
TP_PROTO(struct iwm_priv *iwm, u8 *buf, int len),
TP_ARGS(iwm, buf, len),
TP_STRUCT__entry(
IWM_ENTRY
__field(u8, eot)
__field(u8, ra_tid)
__field(u8, credit_group)
__field(u8, color)
__field(u16, seq)
__field(u8, npkt)
__field(u32, bytes)
),
TP_fast_assign(
struct iwm_umac_wifi_out_hdr *hdr =
(struct iwm_umac_wifi_out_hdr *)buf;
IWM_ASSIGN;
__entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT);
__entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID);
__entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP);
__entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);
__entry->seq = hdr->sw_hdr.cmd.seq_num;
__entry->npkt = 1;
__entry->bytes = len;
if (!__entry->eot) {
int count;
u8 *ptr = buf;
__entry->npkt = 0;
while (ptr < buf + len) {
count = GET_VAL32(hdr->sw_hdr.meta_data,
UMAC_FW_CMD_BYTE_COUNT);
ptr += ALIGN(sizeof(*hdr) + count, 16);
hdr = (struct iwm_umac_wifi_out_hdr *)ptr;
__entry->npkt++;
}
}
),
TP_printk(
IWM_PR_FMT " Tx %spacket: eot %d, seq 0x%x, sta_color 0x%x, "
"ra_tid 0x%x, credit_group 0x%x, embeded_packets %d, %d bytes",
IWM_PR_ARG, !__entry->eot ? "concatenated " : "",
__entry->eot, __entry->seq, __entry->color, __entry->ra_tid,
__entry->credit_group, __entry->npkt, __entry->bytes
)
);
TRACE_EVENT(iwm_rx_nonwifi_cmd,
TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
TP_ARGS(iwm, buf, len),
TP_STRUCT__entry(
IWM_ENTRY
__field(u8, opcode)
__field(u16, seq)
__field(u32, len)
),
TP_fast_assign(
struct iwm_udma_in_hdr *hdr = buf;
IWM_ASSIGN;
__entry->opcode = GET_VAL32(hdr->cmd, UDMA_HDI_IN_NW_CMD_OPCODE);
__entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
__entry->len = len;
),
TP_printk(
IWM_PR_FMT " Rx TARGET RESP: opcode 0x%x, seq 0x%x, len 0x%x",
IWM_PR_ARG, __entry->opcode, __entry->seq, __entry->len
)
);
TRACE_EVENT(iwm_rx_wifi_cmd,
TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_in_hdr *hdr),
TP_ARGS(iwm, hdr),
TP_STRUCT__entry(
IWM_ENTRY
__field(u8, cmd)
__field(u8, source)
__field(u16, seq)
__field(u32, count)
),
TP_fast_assign(
IWM_ASSIGN;
__entry->cmd = hdr->sw_hdr.cmd.cmd;
__entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
__entry->count = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT);
__entry->seq = le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
),
TP_printk(
IWM_PR_FMT " Rx %s RESP: cmd 0x%x, seq 0x%x, count 0x%x",
IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ? "LMAC" :
__entry->source == UMAC_HDI_IN_SOURCE_FW ? "UMAC" : "UDMA",
__entry->cmd, __entry->seq, __entry->count
)
);
#define iwm_ticket_action_symbol \
{ IWM_RX_TICKET_DROP, "DROP" }, \
{ IWM_RX_TICKET_RELEASE, "RELEASE" }, \
{ IWM_RX_TICKET_SNIFFER, "SNIFFER" }, \
{ IWM_RX_TICKET_ENQUEUE, "ENQUEUE" }
TRACE_EVENT(iwm_rx_ticket,
TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
TP_ARGS(iwm, buf, len),
TP_STRUCT__entry(
IWM_ENTRY
__field(u8, action)
__field(u8, reason)
__field(u16, id)
__field(u16, flags)
),
TP_fast_assign(
struct iwm_rx_ticket *ticket =
((struct iwm_umac_notif_rx_ticket *)buf)->tickets;
IWM_ASSIGN;
__entry->id = le16_to_cpu(ticket->id);
__entry->action = le16_to_cpu(ticket->action);
__entry->flags = le16_to_cpu(ticket->flags);
__entry->reason = (__entry->flags & IWM_RX_TICKET_DROP_REASON_MSK) >> IWM_RX_TICKET_DROP_REASON_POS;
),
TP_printk(
IWM_PR_FMT " Rx ticket: id 0x%x, action %s, %s 0x%x%s",
IWM_PR_ARG, __entry->id,
__print_symbolic(__entry->action, iwm_ticket_action_symbol),
__entry->reason ? "reason" : "flags",
__entry->reason ? __entry->reason : __entry->flags,
__entry->flags & IWM_RX_TICKET_AMSDU_MSK ? ", AMSDU frame" : ""
)
);
TRACE_EVENT(iwm_rx_packet,
TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
TP_ARGS(iwm, buf, len),
TP_STRUCT__entry(
IWM_ENTRY
__field(u8, source)
__field(u16, id)
__field(u32, len)
),
TP_fast_assign(
struct iwm_umac_wifi_in_hdr *hdr = buf;
IWM_ASSIGN;
__entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
__entry->id = le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
__entry->len = len - sizeof(*hdr);
),
TP_printk(
IWM_PR_FMT " Rx %s packet: id 0x%x, %d bytes",
IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ?
"LMAC" : "UMAC", __entry->id, __entry->len
)
);
#endif
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
#include <trace/define_trace.h>
...@@ -346,6 +346,7 @@ static int iwm_tx_send_concat_packets(struct iwm_priv *iwm, ...@@ -346,6 +346,7 @@ static int iwm_tx_send_concat_packets(struct iwm_priv *iwm,
/* mark EOP for the last packet */ /* mark EOP for the last packet */
iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1); iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1);
trace_iwm_tx_packets(iwm, txq->concat_buf, txq->concat_count);
ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count); ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count);
txq->concat_count = 0; txq->concat_count = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment