staging: wfx: add tracepoints for I/O access
Some tracepoints are useful for debugging. Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com> Link: https://lore.kernel.org/r/20190919142527.31797-5-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
a794e8b6fa
commit
fee695e3e3
|
@ -1,8 +1,12 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# Necessary for CREATE_TRACE_POINTS
|
||||
CFLAGS_debug.o = -I$(src)
|
||||
|
||||
wfx-y := \
|
||||
hwio.o \
|
||||
main.o
|
||||
main.o \
|
||||
debug.o
|
||||
wfx-$(CONFIG_SPI) += bus_spi.o
|
||||
wfx-$(subst m,y,$(CONFIG_MMC)) += bus_sdio.o
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Debugfs interface.
|
||||
*
|
||||
* Copyright (c) 2017-2019, Silicon Laboratories, Inc.
|
||||
* Copyright (c) 2010, ST-Ericsson
|
||||
*/
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "traces.h"
|
|
@ -12,6 +12,7 @@
|
|||
#include "hwio.h"
|
||||
#include "wfx.h"
|
||||
#include "bus.h"
|
||||
#include "traces.h"
|
||||
|
||||
/*
|
||||
* Internal helpers.
|
||||
|
@ -63,6 +64,7 @@ static int read32_locked(struct wfx_dev *wdev, int reg, u32 *val)
|
|||
|
||||
wdev->hwbus_ops->lock(wdev->hwbus_priv);
|
||||
ret = read32(wdev, reg, val);
|
||||
_trace_io_read32(reg, *val);
|
||||
wdev->hwbus_ops->unlock(wdev->hwbus_priv);
|
||||
return ret;
|
||||
}
|
||||
|
@ -73,6 +75,7 @@ static int write32_locked(struct wfx_dev *wdev, int reg, u32 val)
|
|||
|
||||
wdev->hwbus_ops->lock(wdev->hwbus_priv);
|
||||
ret = write32(wdev, reg, val);
|
||||
_trace_io_write32(reg, val);
|
||||
wdev->hwbus_ops->unlock(wdev->hwbus_priv);
|
||||
return ret;
|
||||
}
|
||||
|
@ -86,11 +89,13 @@ static int write32_bits_locked(struct wfx_dev *wdev, int reg, u32 mask, u32 val)
|
|||
val &= mask;
|
||||
wdev->hwbus_ops->lock(wdev->hwbus_priv);
|
||||
ret = read32(wdev, reg, &val_r);
|
||||
_trace_io_read32(reg, val_r);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
val_w = (val_r & ~mask) | val;
|
||||
if (val_w != val_r) {
|
||||
ret = write32(wdev, reg, val_w);
|
||||
_trace_io_write32(reg, val_w);
|
||||
}
|
||||
err:
|
||||
wdev->hwbus_ops->unlock(wdev->hwbus_priv);
|
||||
|
@ -166,6 +171,7 @@ static int indirect_read_locked(struct wfx_dev *wdev, int reg, u32 addr, void *b
|
|||
|
||||
wdev->hwbus_ops->lock(wdev->hwbus_priv);
|
||||
ret = indirect_read(wdev, reg, addr, buf, len);
|
||||
_trace_io_ind_read(reg, addr, buf, len);
|
||||
wdev->hwbus_ops->unlock(wdev->hwbus_priv);
|
||||
return ret;
|
||||
}
|
||||
|
@ -176,6 +182,7 @@ static int indirect_write_locked(struct wfx_dev *wdev, int reg, u32 addr, const
|
|||
|
||||
wdev->hwbus_ops->lock(wdev->hwbus_priv);
|
||||
ret = indirect_write(wdev, reg, addr, buf, len);
|
||||
_trace_io_ind_write(reg, addr, buf, len);
|
||||
wdev->hwbus_ops->unlock(wdev->hwbus_priv);
|
||||
return ret;
|
||||
}
|
||||
|
@ -190,6 +197,7 @@ static int indirect_read32_locked(struct wfx_dev *wdev, int reg, u32 addr, u32 *
|
|||
wdev->hwbus_ops->lock(wdev->hwbus_priv);
|
||||
ret = indirect_read(wdev, reg, addr, tmp, sizeof(u32));
|
||||
*val = cpu_to_le32(*tmp);
|
||||
_trace_io_ind_read32(reg, addr, *val);
|
||||
wdev->hwbus_ops->unlock(wdev->hwbus_priv);
|
||||
kfree(tmp);
|
||||
return ret;
|
||||
|
@ -205,6 +213,7 @@ static int indirect_write32_locked(struct wfx_dev *wdev, int reg, u32 addr, u32
|
|||
*tmp = cpu_to_le32(val);
|
||||
wdev->hwbus_ops->lock(wdev->hwbus_priv);
|
||||
ret = indirect_write(wdev, reg, addr, tmp, sizeof(u32));
|
||||
_trace_io_ind_write32(reg, addr, val);
|
||||
wdev->hwbus_ops->unlock(wdev->hwbus_priv);
|
||||
kfree(tmp);
|
||||
return ret;
|
||||
|
@ -217,6 +226,7 @@ int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t len)
|
|||
WARN((long) buf & 3, "%s: unaligned buffer", __func__);
|
||||
wdev->hwbus_ops->lock(wdev->hwbus_priv);
|
||||
ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, WFX_REG_IN_OUT_QUEUE, buf, len);
|
||||
_trace_io_read(WFX_REG_IN_OUT_QUEUE, buf, len);
|
||||
wdev->hwbus_ops->unlock(wdev->hwbus_priv);
|
||||
if (ret)
|
||||
dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
|
||||
|
@ -230,6 +240,7 @@ int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t len)
|
|||
WARN((long) buf & 3, "%s: unaligned buffer", __func__);
|
||||
wdev->hwbus_ops->lock(wdev->hwbus_priv);
|
||||
ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, WFX_REG_IN_OUT_QUEUE, buf, len);
|
||||
_trace_io_write(WFX_REG_IN_OUT_QUEUE, buf, len);
|
||||
wdev->hwbus_ops->unlock(wdev->hwbus_priv);
|
||||
if (ret)
|
||||
dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Tracepoints definitions.
|
||||
*
|
||||
* Copyright (c) 2018-2019, Silicon Laboratories, Inc.
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM wfx
|
||||
|
||||
#if !defined(_WFX_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _WFX_TRACE_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
#include "bus.h"
|
||||
|
||||
/* The hell below need some explanations. For each symbolic number, we need to
|
||||
* define it with TRACE_DEFINE_ENUM() and in a list for __print_symbolic.
|
||||
*
|
||||
* 1. Define a new macro that call TRACE_DEFINE_ENUM():
|
||||
*
|
||||
* #define xxx_name(sym) TRACE_DEFINE_ENUM(sym);
|
||||
*
|
||||
* 2. Define list of all symbols:
|
||||
*
|
||||
* #define list_names \
|
||||
* ... \
|
||||
* xxx_name(XXX) \
|
||||
* ...
|
||||
*
|
||||
* 3. Instanciate that list_names:
|
||||
*
|
||||
* list_names
|
||||
*
|
||||
* 4. Redefine xxx_name() as a entry of array for __print_symbolic()
|
||||
*
|
||||
* #undef xxx_name
|
||||
* #define xxx_name(msg) { msg, #msg },
|
||||
*
|
||||
* 5. list_name can now nearlu be used with __print_symbolic() but,
|
||||
* __print_symbolic() dislike last comma of list. So we define a new list
|
||||
* with a dummy element:
|
||||
*
|
||||
* #define list_for_print_symbolic list_names { -1, NULL }
|
||||
*/
|
||||
|
||||
#define wfx_reg_list_enum \
|
||||
wfx_reg_name(WFX_REG_CONFIG, "CONFIG") \
|
||||
wfx_reg_name(WFX_REG_CONTROL, "CONTROL") \
|
||||
wfx_reg_name(WFX_REG_IN_OUT_QUEUE, "QUEUE") \
|
||||
wfx_reg_name(WFX_REG_AHB_DPORT, "AHB") \
|
||||
wfx_reg_name(WFX_REG_BASE_ADDR, "BASE_ADDR") \
|
||||
wfx_reg_name(WFX_REG_SRAM_DPORT, "SRAM") \
|
||||
wfx_reg_name(WFX_REG_SET_GEN_R_W, "SET_GEN_R_W") \
|
||||
wfx_reg_name(WFX_REG_FRAME_OUT, "FRAME_OUT")
|
||||
|
||||
#undef wfx_reg_name
|
||||
#define wfx_reg_name(sym, name) TRACE_DEFINE_ENUM(sym);
|
||||
wfx_reg_list_enum
|
||||
#undef wfx_reg_name
|
||||
#define wfx_reg_name(sym, name) { sym, name },
|
||||
#define wfx_reg_list wfx_reg_list_enum { -1, NULL }
|
||||
|
||||
DECLARE_EVENT_CLASS(io_data,
|
||||
TP_PROTO(int reg, int addr, const void *io_buf, size_t len),
|
||||
TP_ARGS(reg, addr, io_buf, len),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, reg)
|
||||
__field(int, addr)
|
||||
__field(int, msg_len)
|
||||
__field(int, buf_len)
|
||||
__array(u8, buf, 32)
|
||||
__array(u8, addr_str, 10)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->reg = reg;
|
||||
__entry->addr = addr;
|
||||
__entry->msg_len = len;
|
||||
__entry->buf_len = min_t(int, sizeof(__entry->buf), __entry->msg_len);
|
||||
memcpy(__entry->buf, io_buf, __entry->buf_len);
|
||||
if (addr >= 0)
|
||||
snprintf(__entry->addr_str, 10, "/%08x", addr);
|
||||
else
|
||||
__entry->addr_str[0] = 0;
|
||||
),
|
||||
TP_printk("%s%s: %s%s (%d bytes)",
|
||||
__print_symbolic(__entry->reg, wfx_reg_list),
|
||||
__entry->addr_str,
|
||||
__print_hex(__entry->buf, __entry->buf_len),
|
||||
__entry->msg_len > sizeof(__entry->buf) ? " ..." : "",
|
||||
__entry->msg_len
|
||||
)
|
||||
);
|
||||
DEFINE_EVENT(io_data, io_write,
|
||||
TP_PROTO(int reg, int addr, const void *io_buf, size_t len),
|
||||
TP_ARGS(reg, addr, io_buf, len));
|
||||
#define _trace_io_ind_write(reg, addr, io_buf, len) trace_io_write(reg, addr, io_buf, len)
|
||||
#define _trace_io_write(reg, io_buf, len) trace_io_write(reg, -1, io_buf, len)
|
||||
DEFINE_EVENT(io_data, io_read,
|
||||
TP_PROTO(int reg, int addr, const void *io_buf, size_t len),
|
||||
TP_ARGS(reg, addr, io_buf, len));
|
||||
#define _trace_io_ind_read(reg, addr, io_buf, len) trace_io_read(reg, addr, io_buf, len)
|
||||
#define _trace_io_read(reg, io_buf, len) trace_io_read(reg, -1, io_buf, len)
|
||||
|
||||
DECLARE_EVENT_CLASS(io_data32,
|
||||
TP_PROTO(int reg, int addr, u32 val),
|
||||
TP_ARGS(reg, addr, val),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, reg)
|
||||
__field(int, addr)
|
||||
__field(int, val)
|
||||
__array(u8, addr_str, 10)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->reg = reg;
|
||||
__entry->addr = addr;
|
||||
__entry->val = val;
|
||||
if (addr >= 0)
|
||||
snprintf(__entry->addr_str, 10, "/%08x", addr);
|
||||
else
|
||||
__entry->addr_str[0] = 0;
|
||||
),
|
||||
TP_printk("%s%s: %08x",
|
||||
__print_symbolic(__entry->reg, wfx_reg_list),
|
||||
__entry->addr_str,
|
||||
__entry->val
|
||||
)
|
||||
);
|
||||
DEFINE_EVENT(io_data32, io_write32,
|
||||
TP_PROTO(int reg, int addr, u32 val),
|
||||
TP_ARGS(reg, addr, val));
|
||||
#define _trace_io_ind_write32(reg, addr, val) trace_io_write32(reg, addr, val)
|
||||
#define _trace_io_write32(reg, val) trace_io_write32(reg, -1, val)
|
||||
DEFINE_EVENT(io_data32, io_read32,
|
||||
TP_PROTO(int reg, int addr, u32 val),
|
||||
TP_ARGS(reg, addr, val));
|
||||
#define _trace_io_ind_read32(reg, addr, val) trace_io_read32(reg, addr, val)
|
||||
#define _trace_io_read32(reg, val) trace_io_read32(reg, -1, val)
|
||||
|
||||
#endif
|
||||
|
||||
/* This part must be outside protection */
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE traces
|
||||
|
||||
#include <trace/define_trace.h>
|
Loading…
Reference in New Issue