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:
Jérôme Pouiller 2019-09-19 14:25:38 +00:00 committed by Greg Kroah-Hartman
parent a794e8b6fa
commit fee695e3e3
4 changed files with 175 additions and 1 deletions

View File

@ -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

View File

@ -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"

View File

@ -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);

View File

@ -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>