diff --git a/drivers/net/wwan/Kconfig b/drivers/net/wwan/Kconfig index 9f5111a77da9..609fd4a2c865 100644 --- a/drivers/net/wwan/Kconfig +++ b/drivers/net/wwan/Kconfig @@ -16,6 +16,17 @@ config WWAN if WWAN +config WWAN_DEBUGFS + bool "WWAN devices debugfs interface" if EXPERT + depends on DEBUG_FS + default y + help + Enables debugfs infrastructure for the WWAN core and device drivers. + + If this option is selected, then you can find the debug interface + elements for each WWAN device in a directory that is corresponding to + the device name: debugfs/wwan/wwanX. + config WWAN_HWSIM tristate "Simulated WWAN device" help @@ -85,7 +96,7 @@ config IOSM tristate "IOSM Driver for Intel M.2 WWAN Device" depends on INTEL_IOMMU select NET_DEVLINK - select RELAY + select RELAY if WWAN_DEBUGFS help This driver enables Intel M.2 WWAN Device communication. diff --git a/drivers/net/wwan/iosm/Makefile b/drivers/net/wwan/iosm/Makefile index 5c2528beca2a..fa8d6afd18e1 100644 --- a/drivers/net/wwan/iosm/Makefile +++ b/drivers/net/wwan/iosm/Makefile @@ -21,7 +21,10 @@ iosm-y = \ iosm_ipc_mux_codec.o \ iosm_ipc_devlink.o \ iosm_ipc_flash.o \ - iosm_ipc_coredump.o \ + iosm_ipc_coredump.o + +iosm-$(CONFIG_WWAN_DEBUGFS) += \ + iosm_ipc_debugfs.o \ iosm_ipc_trace.o obj-$(CONFIG_IOSM) := iosm.o diff --git a/drivers/net/wwan/iosm/iosm_ipc_debugfs.c b/drivers/net/wwan/iosm/iosm_ipc_debugfs.c new file mode 100644 index 000000000000..f2f57751a7d2 --- /dev/null +++ b/drivers/net/wwan/iosm/iosm_ipc_debugfs.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020-2021 Intel Corporation. + */ + +#include +#include + +#include "iosm_ipc_imem.h" +#include "iosm_ipc_trace.h" +#include "iosm_ipc_debugfs.h" + +void ipc_debugfs_init(struct iosm_imem *ipc_imem) +{ + struct dentry *debugfs_pdev = wwan_get_debugfs_dir(ipc_imem->dev); + + ipc_imem->debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, + debugfs_pdev); + + ipc_imem->trace = ipc_trace_init(ipc_imem); + if (!ipc_imem->trace) + dev_warn(ipc_imem->dev, "trace channel init failed"); +} + +void ipc_debugfs_deinit(struct iosm_imem *ipc_imem) +{ + ipc_trace_deinit(ipc_imem->trace); + debugfs_remove_recursive(ipc_imem->debugfs_dir); +} diff --git a/drivers/net/wwan/iosm/iosm_ipc_debugfs.h b/drivers/net/wwan/iosm/iosm_ipc_debugfs.h new file mode 100644 index 000000000000..8a84bfa2c14a --- /dev/null +++ b/drivers/net/wwan/iosm/iosm_ipc_debugfs.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (C) 2020-2021 Intel Corporation. + */ + +#ifndef IOSM_IPC_DEBUGFS_H +#define IOSM_IPC_DEBUGFS_H + +#ifdef CONFIG_WWAN_DEBUGFS +void ipc_debugfs_init(struct iosm_imem *ipc_imem); +void ipc_debugfs_deinit(struct iosm_imem *ipc_imem); +#else +static inline void ipc_debugfs_init(struct iosm_imem *ipc_imem) {} +static inline void ipc_debugfs_deinit(struct iosm_imem *ipc_imem) {} +#endif + +#endif diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.c b/drivers/net/wwan/iosm/iosm_ipc_imem.c index 1be07114c85d..2a6ddd7c6c88 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.c +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.c @@ -11,6 +11,7 @@ #include "iosm_ipc_imem.h" #include "iosm_ipc_port.h" #include "iosm_ipc_trace.h" +#include "iosm_ipc_debugfs.h" /* Check the wwan ips if it is valid with Channel as input. */ static int ipc_imem_check_wwan_ips(struct ipc_mem_channel *chnl) @@ -272,8 +273,8 @@ static void ipc_imem_dl_skb_process(struct iosm_imem *ipc_imem, if (port_id == IPC_MEM_CTRL_CHL_ID_7) ipc_imem_sys_devlink_notify_rx(ipc_imem->ipc_devlink, skb); - else if (port_id == ipc_imem->trace->chl_id) - ipc_trace_port_rx(ipc_imem->trace, skb); + else if (ipc_is_trace_channel(ipc_imem, port_id)) + ipc_trace_port_rx(ipc_imem, skb); else wwan_port_rx(ipc_imem->ipc_port[port_id]->iosm_port, skb); @@ -554,11 +555,7 @@ static void ipc_imem_run_state_worker(struct work_struct *instance) ctrl_chl_idx++; } - ipc_imem->trace = ipc_imem_trace_channel_init(ipc_imem); - if (!ipc_imem->trace) { - dev_err(ipc_imem->dev, "trace channel init failed"); - return; - } + ipc_debugfs_init(ipc_imem); ipc_task_queue_send_task(ipc_imem, ipc_imem_send_mdm_rdy_cb, 0, NULL, 0, false); @@ -1175,7 +1172,7 @@ void ipc_imem_cleanup(struct iosm_imem *ipc_imem) if (test_and_clear_bit(FULLY_FUNCTIONAL, &ipc_imem->flag)) { ipc_mux_deinit(ipc_imem->mux); - ipc_trace_deinit(ipc_imem->trace); + ipc_debugfs_deinit(ipc_imem); ipc_wwan_deinit(ipc_imem->wwan); ipc_port_deinit(ipc_imem->ipc_port); } diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.h b/drivers/net/wwan/iosm/iosm_ipc_imem.h index cec38009c44a..86a1ffe61729 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.h +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.h @@ -341,6 +341,7 @@ enum ipc_phase { * @ev_mux_net_transmit_pending:0 means inform the IPC tasklet to pass * @reset_det_n: Reset detect flag * @pcie_wake_n: Pcie wake flag + * @debugfs_dir: Debug FS directory for driver-specific entries */ struct iosm_imem { struct iosm_mmio *mmio; @@ -350,7 +351,9 @@ struct iosm_imem { struct iosm_mux *mux; struct iosm_cdev *ipc_port[IPC_MEM_MAX_CHANNELS]; struct iosm_pcie *pcie; +#ifdef CONFIG_WWAN_DEBUGFS struct iosm_trace *trace; +#endif struct device *dev; enum ipc_mem_device_ipc_state ipc_requested_state; struct ipc_mem_channel channels[IPC_MEM_MAX_CHANNELS]; @@ -380,6 +383,9 @@ struct iosm_imem { ev_mux_net_transmit_pending:1, reset_det_n:1, pcie_wake_n:1; +#ifdef CONFIG_WWAN_DEBUGFS + struct dentry *debugfs_dir; +#endif }; /** diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c index 43f1796a8984..d2072a84ab08 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c +++ b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c @@ -11,7 +11,6 @@ #include "iosm_ipc_imem_ops.h" #include "iosm_ipc_port.h" #include "iosm_ipc_task_queue.h" -#include "iosm_ipc_trace.h" /* Open a packet data online channel between the network layer and CP. */ int ipc_imem_sys_wwan_open(struct iosm_imem *ipc_imem, int if_id) @@ -108,23 +107,6 @@ void ipc_imem_wwan_channel_init(struct iosm_imem *ipc_imem, "failed to register the ipc_wwan interfaces"); } -/** - * ipc_imem_trace_channel_init - Initializes trace channel. - * @ipc_imem: Pointer to iosm_imem struct. - * - * Returns: Pointer to trace instance on success else NULL - */ -struct iosm_trace *ipc_imem_trace_channel_init(struct iosm_imem *ipc_imem) -{ - struct ipc_chnl_cfg chnl_cfg = { 0 }; - - ipc_chnl_cfg_get(&chnl_cfg, IPC_MEM_CTRL_CHL_ID_3); - ipc_imem_channel_init(ipc_imem, IPC_CTYPE_CTRL, chnl_cfg, - IRQ_MOD_OFF); - - return ipc_trace_init(ipc_imem); -} - /* Map SKB to DMA for transfer */ static int ipc_imem_map_skb_to_dma(struct iosm_imem *ipc_imem, struct sk_buff *skb) diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h index e36ee2782629..f8afb217d9e2 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h +++ b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h @@ -141,5 +141,5 @@ int ipc_imem_sys_devlink_read(struct iosm_devlink *ipc_devlink, u8 *data, */ int ipc_imem_sys_devlink_write(struct iosm_devlink *ipc_devlink, unsigned char *buf, int count); -struct iosm_trace *ipc_imem_trace_channel_init(struct iosm_imem *ipc_imem); + #endif diff --git a/drivers/net/wwan/iosm/iosm_ipc_trace.c b/drivers/net/wwan/iosm/iosm_ipc_trace.c index c5fa12599c2b..eeecfa3d10c5 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_trace.c +++ b/drivers/net/wwan/iosm/iosm_ipc_trace.c @@ -17,11 +17,13 @@ /** * ipc_trace_port_rx - Receive trace packet from cp and write to relay buffer - * @ipc_trace: Pointer to the ipc trace data-struct + * @ipc_imem: Pointer to iosm_imem structure * @skb: Pointer to struct sk_buff */ -void ipc_trace_port_rx(struct iosm_trace *ipc_trace, struct sk_buff *skb) +void ipc_trace_port_rx(struct iosm_imem *ipc_imem, struct sk_buff *skb) { + struct iosm_trace *ipc_trace = ipc_imem->trace; + if (ipc_trace->ipc_rchan) relay_write(ipc_trace->ipc_rchan, skb->data, skb->len); @@ -132,9 +134,14 @@ static const struct file_operations ipc_trace_fops = { */ struct iosm_trace *ipc_trace_init(struct iosm_imem *ipc_imem) { - struct iosm_trace *ipc_trace = kzalloc(sizeof(*ipc_trace), GFP_KERNEL); - struct dentry *debugfs_pdev; + struct ipc_chnl_cfg chnl_cfg = { 0 }; + struct iosm_trace *ipc_trace; + ipc_chnl_cfg_get(&chnl_cfg, IPC_MEM_CTRL_CHL_ID_3); + ipc_imem_channel_init(ipc_imem, IPC_CTYPE_CTRL, chnl_cfg, + IRQ_MOD_OFF); + + ipc_trace = kzalloc(sizeof(*ipc_trace), GFP_KERNEL); if (!ipc_trace) return NULL; @@ -144,15 +151,14 @@ struct iosm_trace *ipc_trace_init(struct iosm_imem *ipc_imem) ipc_trace->chl_id = IPC_MEM_CTRL_CHL_ID_3; mutex_init(&ipc_trace->trc_mutex); - debugfs_pdev = wwan_get_debugfs_dir(ipc_imem->dev); ipc_trace->ctrl_file = debugfs_create_file(IOSM_TRC_DEBUGFS_TRACE_CTRL, IOSM_TRC_FILE_PERM, - debugfs_pdev, + ipc_imem->debugfs_dir, ipc_trace, &ipc_trace_fops); ipc_trace->ipc_rchan = relay_open(IOSM_TRC_DEBUGFS_TRACE, - debugfs_pdev, + ipc_imem->debugfs_dir, IOSM_TRC_SUB_BUFF_SIZE, IOSM_TRC_N_SUB_BUFF, &relay_callbacks, NULL); @@ -166,6 +172,9 @@ struct iosm_trace *ipc_trace_init(struct iosm_imem *ipc_imem) */ void ipc_trace_deinit(struct iosm_trace *ipc_trace) { + if (!ipc_trace) + return; + debugfs_remove(ipc_trace->ctrl_file); relay_close(ipc_trace->ipc_rchan); mutex_destroy(&ipc_trace->trc_mutex); diff --git a/drivers/net/wwan/iosm/iosm_ipc_trace.h b/drivers/net/wwan/iosm/iosm_ipc_trace.h index 53346183af9c..5ebe7790585c 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_trace.h +++ b/drivers/net/wwan/iosm/iosm_ipc_trace.h @@ -45,7 +45,30 @@ struct iosm_trace { enum trace_ctrl_mode mode; }; +#ifdef CONFIG_WWAN_DEBUGFS + +static inline bool ipc_is_trace_channel(struct iosm_imem *ipc_mem, u16 chl_id) +{ + return ipc_mem->trace && ipc_mem->trace->chl_id == chl_id; +} + struct iosm_trace *ipc_trace_init(struct iosm_imem *ipc_imem); void ipc_trace_deinit(struct iosm_trace *ipc_trace); -void ipc_trace_port_rx(struct iosm_trace *ipc_trace, struct sk_buff *skb); +void ipc_trace_port_rx(struct iosm_imem *ipc_imem, struct sk_buff *skb); + +#else + +static inline bool ipc_is_trace_channel(struct iosm_imem *ipc_mem, u16 chl_id) +{ + return false; +} + +static inline void ipc_trace_port_rx(struct iosm_imem *ipc_imem, + struct sk_buff *skb) +{ + dev_kfree_skb(skb); +} + +#endif + #endif diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c index 5bf62dc35ac7..1508dc2a497b 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -50,7 +50,9 @@ struct wwan_device { atomic_t port_id; const struct wwan_ops *ops; void *ops_ctxt; +#ifdef CONFIG_WWAN_DEBUGFS struct dentry *debugfs_dir; +#endif }; /** @@ -146,6 +148,7 @@ static struct wwan_device *wwan_dev_get_by_name(const char *name) return to_wwan_dev(dev); } +#ifdef CONFIG_WWAN_DEBUGFS struct dentry *wwan_get_debugfs_dir(struct device *parent) { struct wwan_device *wwandev; @@ -157,6 +160,7 @@ struct dentry *wwan_get_debugfs_dir(struct device *parent) return wwandev->debugfs_dir; } EXPORT_SYMBOL_GPL(wwan_get_debugfs_dir); +#endif /* This function allocates and registers a new WWAN device OR if a WWAN device * already exist for the given parent, it gets a reference and return it. @@ -166,7 +170,6 @@ EXPORT_SYMBOL_GPL(wwan_get_debugfs_dir); static struct wwan_device *wwan_create_dev(struct device *parent) { struct wwan_device *wwandev; - const char *wwandev_name; int err, id; /* The 'find-alloc-register' operation must be protected against @@ -206,9 +209,11 @@ static struct wwan_device *wwan_create_dev(struct device *parent) goto done_unlock; } - wwandev_name = kobject_name(&wwandev->dev.kobj); - wwandev->debugfs_dir = debugfs_create_dir(wwandev_name, - wwan_debugfs_dir); +#ifdef CONFIG_WWAN_DEBUGFS + wwandev->debugfs_dir = + debugfs_create_dir(kobject_name(&wwandev->dev.kobj), + wwan_debugfs_dir); +#endif done_unlock: mutex_unlock(&wwan_register_lock); @@ -240,7 +245,9 @@ static void wwan_remove_dev(struct wwan_device *wwandev) ret = device_for_each_child(&wwandev->dev, NULL, is_wwan_child); if (!ret) { +#ifdef CONFIG_WWAN_DEBUGFS debugfs_remove_recursive(wwandev->debugfs_dir); +#endif device_unregister(&wwandev->dev); } else { put_device(&wwandev->dev); @@ -1140,7 +1147,9 @@ static int __init wwan_init(void) goto destroy; } +#ifdef CONFIG_WWAN_DEBUGFS wwan_debugfs_dir = debugfs_create_dir("wwan", NULL); +#endif return 0; diff --git a/include/linux/wwan.h b/include/linux/wwan.h index 1646aa3e6779..e143c88bf4b0 100644 --- a/include/linux/wwan.h +++ b/include/linux/wwan.h @@ -171,6 +171,13 @@ int wwan_register_ops(struct device *parent, const struct wwan_ops *ops, void wwan_unregister_ops(struct device *parent); +#ifdef CONFIG_WWAN_DEBUGFS struct dentry *wwan_get_debugfs_dir(struct device *parent); +#else +static inline struct dentry *wwan_get_debugfs_dir(struct device *parent) +{ + return ERR_PTR(-ENODEV); +} +#endif #endif /* __WWAN_H */