Implements the driver debugging infrastructure for sending debug prints to the user (based on the configured debug level) with the help of helper functions. These functions are utilized by source files in the driver. Signed-off-by: Gokul Sivakumar --- drivers/net/wireless/infineon/inffmac/debug.c | 117 ++++++++++++ drivers/net/wireless/infineon/inffmac/debug.h | 174 ++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 drivers/net/wireless/infineon/inffmac/debug.c create mode 100644 drivers/net/wireless/infineon/inffmac/debug.h diff --git a/drivers/net/wireless/infineon/inffmac/debug.c b/drivers/net/wireless/infineon/inffmac/debug.c new file mode 100644 index 000000000000..5ddbbb6ab505 --- /dev/null +++ b/drivers/net/wireless/infineon/inffmac/debug.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (c) 2012 Broadcom Corporation + * + * Copyright (c) 2025-2026, Infineon Technologies AG, or an affiliate of Infineon Technologies AG. + * All rights reserved. + */ +#include +#include +#include +#include + +#include "main.h" +#include "bus_proto.h" +#include "debug.h" + +void __inff_dbg(u32 level, const char *func, const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + + va_start(args, fmt); + vaf.va = &args; + if (inff_msg_level & level) + pr_debug("%s %pV", func, &vaf); + va_end(args); +} + +void +__inff_err(struct device *dev, const char *func, const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + + va_start(args, fmt); + vaf.va = &args; + if (dev) + dev_err(dev, "%s: %pV", func, &vaf); + else + pr_err("%s: %pV", func, &vaf); + va_end(args); +} + +/* pretty hex print a pkt buffer chain */ +void inff_prpkt(const char *msg, struct sk_buff *p0) +{ + struct sk_buff *p; + + if (msg && (msg[0] != '\0')) + pr_debug("%s:\n", msg); + + for (p = p0; p; p = p->next) + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len); +} + +void __inff_dbg_hex_dump(const void *data, size_t size, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + pr_debug("%pV", &vaf); + + va_end(args); + + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data, size); +} + +int inff_debug_create_memdump(struct inff_bus *bus, const void *data, + size_t len) +{ + void *dump; + size_t ramsize; + int err; + + ramsize = inff_bus_get_ramsize(bus); + if (!ramsize) + return -EOPNOTSUPP; + + dump = vzalloc(len + ramsize); + if (!dump) + return -ENOMEM; + + if (data && len > 0) + memcpy(dump, data, len); + err = inff_bus_get_memdump(bus, dump + len, ramsize); + if (err) { + vfree(dump); + return err; + } + + dev_coredumpv(bus->dev, dump, len + ramsize, GFP_KERNEL); + + return 0; +} + +struct dentry *inff_debugfs_get_devdir(struct inff_pub *drvr) +{ + return drvr->wiphy->debugfsdir; +} + +void inff_debugfs_add_entry(struct inff_pub *drvr, const char *fn, + int (*read_fn)(struct seq_file *seq, void *data)) +{ + WARN(!drvr->wiphy->debugfsdir, "wiphy not (yet) registered\n"); + debugfs_create_devm_seqfile(drvr->bus_if->dev, fn, + drvr->wiphy->debugfsdir, read_fn); +} diff --git a/drivers/net/wireless/infineon/inffmac/debug.h b/drivers/net/wireless/infineon/inffmac/debug.h new file mode 100644 index 000000000000..9a366ee9111f --- /dev/null +++ b/drivers/net/wireless/infineon/inffmac/debug.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: ISC */ +/* + * Copyright (c) 2010 Broadcom Corporation + * + * Copyright (c) 2025-2026, Infineon Technologies AG, or an affiliate of Infineon Technologies AG. + * All rights reserved. + */ + +#ifndef INFF_DEBUG_H +#define INFF_DEBUG_H + +#include /* net_ratelimit() */ +#include + +/* message levels */ +enum inff_msglvl { + INFF_MSGLVL_TRACE = BIT(1), + INFF_MSGLVL_INFO = BIT(2), + INFF_MSGLVL_DATA = BIT(3), + INFF_MSGLVL_CTL = BIT(4), + INFF_MSGLVL_TIMER = BIT(5), + INFF_MSGLVL_HDRS = BIT(6), + INFF_MSGLVL_BYTES = BIT(7), + INFF_MSGLVL_INTR = BIT(8), + INFF_MSGLVL_GLOM = BIT(9), + INFF_MSGLVL_DEVEVT = BIT(10), + INFF_MSGLVL_BTA = BIT(11), + INFF_MSGLVL_DEVCMD = BIT(12), + INFF_MSGLVL_USB = BIT(13), + INFF_MSGLVL_SCAN = BIT(14), + INFF_MSGLVL_CONN = BIT(15), + INFF_MSGLVL_BCDC = BIT(16), + INFF_MSGLVL_SDIO = BIT(17), + INFF_MSGLVL_MSGBUF = BIT(18), + INFF_MSGLVL_PCIE = BIT(19), + INFF_MSGLVL_FWCON = BIT(20), + INFF_MSGLVL_ULP = BIT(21), + INFF_MSGLVL_TWT = BIT(22), + INFF_MSGLVL_SDIOEXT = BIT(24), + INFF_MSGLVL_ICDC = BIT(25), +}; + +#ifdef DEBUG +#define INFF_MSGLVL_ON(level) (inff_msg_level & INFF_MSGLVL_##level) +#else /* DEBUG */ +#define INFF_MSGLVL_ON(LVL) 0 +#endif /* DEBUG */ + +/* set default print format */ +#undef pr_fmt +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +struct inff_bus; + +__printf(3, 4) +void __inff_err(struct device *dev, const char *func, const char *fmt, ...); +/* Macro for error messages. When debugging / tracing the driver all error + * messages are important to us. + */ +#define inff_err(fmt, ...) \ + do { \ + if (IS_ENABLED(CONFIG_INF_DEBUG) || \ + net_ratelimit()) \ + __inff_err(NULL, __func__, fmt, ##__VA_ARGS__); \ + } while (0) + +#define inff_dev_err(dev, fmt, ...) \ + do { \ + if (IS_ENABLED(CONFIG_INF_DEBUG) || \ + net_ratelimit()) \ + __inff_err(dev, __func__, fmt, ##__VA_ARGS__); \ + } while (0) + +#define iphy_err(drvr, fmt, ...) \ + do { \ + if (IS_ENABLED(CONFIG_INF_DEBUG) || \ + net_ratelimit()) \ + wiphy_err((drvr)->wiphy, "%s: " fmt, __func__, \ + ##__VA_ARGS__); \ + } while (0) + +#define iphy_info_once(drvr, fmt, ...) \ + wiphy_info_once((drvr)->wiphy, "%s: " fmt, __func__, \ + ##__VA_ARGS__) + +#ifdef DEBUG + +/* For debug purposes treat info messages as errors */ +#define inff_info inff_err + +__printf(3, 4) +void __inff_dbg(u32 level, const char *func, const char *fmt, ...); +#define inff_dbg(level, fmt, ...) \ +do { \ + if (IS_ENABLED(CONFIG_INF_DEBUG)) \ + __inff_dbg(INFF_MSGLVL_##level, __func__, \ + fmt, ##__VA_ARGS__); \ +} while (0) + +__printf(3, 4) +void __inff_dbg_hex_dump(const void *data, size_t size, + const char *fmt, ...); +#define inff_dbg_hex_dump(test, data, len, fmt, ...) \ +do { \ + if (test) \ + __inff_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__); \ +} while (0) + +void inff_prpkt(const char *msg, struct sk_buff *p0); + +#else /* DEBUG */ + +#define inff_info(fmt, ...) \ + { \ + pr_info("%s: " fmt, __func__, ##__VA_ARGS__); \ + } + +#define inff_dbg(level, fmt, ...) \ + { \ + UNUSED_PARAMETER(level); \ + no_printk(fmt, ##__VA_ARGS__); \ + } + +#define inff_dbg_hex_dump(test, data, len, fmt, ...) +#define inff_prpkt(a, b) + +#endif /* DEBUG */ + +extern int inff_msg_level; +struct inff_pub; + +#ifdef DEBUG +struct dentry *inff_debugfs_get_devdir(struct inff_pub *drvr); +void inff_debugfs_add_entry(struct inff_pub *drvr, const char *fn, + int (*read_fn)(struct seq_file *seq, void *data)); +int inff_debug_create_memdump(struct inff_bus *bus, const void *data, + size_t len); +#else +static inline struct dentry *inff_debugfs_get_devdir(struct inff_pub *drvr) +{ + return ERR_PTR(-ENOENT); +} + +static inline +void inff_debugfs_add_entry(struct inff_pub *drvr, const char *fn, + int (*read_fn)(struct seq_file *seq, void *data)) +{ } +static inline +int inff_debug_create_memdump(struct inff_bus *bus, const void *data, + size_t len) +{ + return 0; +} +#endif /* DEBUG */ + +#define MSGTRACE_VERSION 1 +#define MSGTRACE_HDR_TYPE_MSG 0 +#define MSGTRACE_HDR_TYPE_LOG 1 + +/* Message trace header */ +struct msgtrace_hdr { + u8 version; + u8 trace_type; + u16 len; /* Len of the trace */ + u32 seqnum; /* Sequence number of message */ + /* Number of discarded bytes because of trace overflow */ + u32 discarded_bytes; + /* Number of discarded printf because of trace overflow */ + u32 discarded_printf; +}; + +#define MSGTRACE_HDRLEN sizeof(struct msgtrace_hdr) + +#endif /* INFF_DEBUG_H */ -- 2.25.1