Commit 3349e4a4 authored by M Chetan Kumar's avatar M Chetan Kumar Committed by David S. Miller

net: wwan: t7xx: Add port for modem logging

The Modem Logging (MDL) port provides an interface to collect modem
logs for debugging purposes. MDL is supported by the relay interface,
and the mtk_t7xx port infrastructure. MDL allows user-space apps to
control logging via mbim command and to collect logs via the relay
interface, while port infrastructure facilitates communication between
the driver and the modem.
Signed-off-by: default avatarMoises Veleta <moises.veleta@linux.intel.com>
Signed-off-by: default avatarM Chetan Kumar <m.chetan.kumar@linux.intel.com>
Signed-off-by: default avatarDevegowda Chandrashekar <chandrashekar.devegowda@intel.com>
Acked-by: default avatarRicardo Martinez <ricardo.martinez@linux.intel.com>
Reviewed-by: default avatarSergey Ryazanov <ryazanov.s.a@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fece7a8c
...@@ -108,6 +108,7 @@ config IOSM ...@@ -108,6 +108,7 @@ config IOSM
config MTK_T7XX config MTK_T7XX
tristate "MediaTek PCIe 5G WWAN modem T7xx device" tristate "MediaTek PCIe 5G WWAN modem T7xx device"
depends on PCI depends on PCI
select RELAY if WWAN_DEBUGFS
help help
Enables MediaTek PCIe based 5G WWAN modem (T7xx series) device. Enables MediaTek PCIe based 5G WWAN modem (T7xx series) device.
Adapts WWAN framework and provides network interface like wwan0 Adapts WWAN framework and provides network interface like wwan0
......
...@@ -18,3 +18,6 @@ mtk_t7xx-y:= t7xx_pci.o \ ...@@ -18,3 +18,6 @@ mtk_t7xx-y:= t7xx_pci.o \
t7xx_hif_dpmaif_rx.o \ t7xx_hif_dpmaif_rx.o \
t7xx_dpmaif.o \ t7xx_dpmaif.o \
t7xx_netdev.o t7xx_netdev.o
mtk_t7xx-$(CONFIG_WWAN_DEBUGFS) += \
t7xx_port_trace.o \
...@@ -1018,6 +1018,8 @@ static int t7xx_cldma_late_init(struct cldma_ctrl *md_ctrl) ...@@ -1018,6 +1018,8 @@ static int t7xx_cldma_late_init(struct cldma_ctrl *md_ctrl)
dev_err(md_ctrl->dev, "control TX ring init fail\n"); dev_err(md_ctrl->dev, "control TX ring init fail\n");
goto err_free_tx_ring; goto err_free_tx_ring;
} }
md_ctrl->tx_ring[i].pkt_size = CLDMA_MTU;
} }
for (j = 0; j < CLDMA_RXQ_NUM; j++) { for (j = 0; j < CLDMA_RXQ_NUM; j++) {
......
...@@ -78,6 +78,9 @@ struct t7xx_pci_dev { ...@@ -78,6 +78,9 @@ struct t7xx_pci_dev {
spinlock_t md_pm_lock; /* Protects PCI resource lock */ spinlock_t md_pm_lock; /* Protects PCI resource lock */
unsigned int sleep_disable_count; unsigned int sleep_disable_count;
struct completion sleep_lock_acquire; struct completion sleep_lock_acquire;
#ifdef CONFIG_WWAN_DEBUGFS
struct dentry *debugfs_dir;
#endif
}; };
enum t7xx_pm_id { enum t7xx_pm_id {
......
...@@ -125,6 +125,9 @@ struct t7xx_port { ...@@ -125,6 +125,9 @@ struct t7xx_port {
struct { struct {
struct wwan_port *wwan_port; struct wwan_port *wwan_port;
} wwan; } wwan;
struct {
struct rchan *relaych;
} log;
}; };
}; };
......
...@@ -70,6 +70,18 @@ static const struct t7xx_port_conf t7xx_md_port_conf[] = { ...@@ -70,6 +70,18 @@ static const struct t7xx_port_conf t7xx_md_port_conf[] = {
.name = "MBIM", .name = "MBIM",
.port_type = WWAN_PORT_MBIM, .port_type = WWAN_PORT_MBIM,
}, { }, {
#ifdef CONFIG_WWAN_DEBUGFS
.tx_ch = PORT_CH_MD_LOG_TX,
.rx_ch = PORT_CH_MD_LOG_RX,
.txq_index = 7,
.rxq_index = 7,
.txq_exp_index = 7,
.rxq_exp_index = 7,
.path_id = CLDMA_ID_MD,
.ops = &t7xx_trace_port_ops,
.name = "mdlog",
}, {
#endif
.tx_ch = PORT_CH_CONTROL_TX, .tx_ch = PORT_CH_CONTROL_TX,
.rx_ch = PORT_CH_CONTROL_RX, .rx_ch = PORT_CH_CONTROL_RX,
.txq_index = Q_IDX_CTRL, .txq_index = Q_IDX_CTRL,
......
...@@ -87,6 +87,10 @@ struct ctrl_msg_header { ...@@ -87,6 +87,10 @@ struct ctrl_msg_header {
extern struct port_ops wwan_sub_port_ops; extern struct port_ops wwan_sub_port_ops;
extern struct port_ops ctl_port_ops; extern struct port_ops ctl_port_ops;
#ifdef CONFIG_WWAN_DEBUGFS
extern struct port_ops t7xx_trace_port_ops;
#endif
void t7xx_port_proxy_reset(struct port_proxy *port_prox); void t7xx_port_proxy_reset(struct port_proxy *port_prox);
void t7xx_port_proxy_uninit(struct port_proxy *port_prox); void t7xx_port_proxy_uninit(struct port_proxy *port_prox);
int t7xx_port_proxy_init(struct t7xx_modem *md); int t7xx_port_proxy_init(struct t7xx_modem *md);
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2022 Intel Corporation.
*/
#include <linux/debugfs.h>
#include <linux/relay.h>
#include <linux/skbuff.h>
#include <linux/wwan.h>
#include "t7xx_port.h"
#include "t7xx_port_proxy.h"
#include "t7xx_state_monitor.h"
#define T7XX_TRC_SUB_BUFF_SIZE 131072
#define T7XX_TRC_N_SUB_BUFF 32
static struct dentry *t7xx_trace_create_buf_file_handler(const char *filename,
struct dentry *parent,
umode_t mode,
struct rchan_buf *buf,
int *is_global)
{
*is_global = 1;
return debugfs_create_file(filename, mode, parent, buf,
&relay_file_operations);
}
static int t7xx_trace_remove_buf_file_handler(struct dentry *dentry)
{
debugfs_remove(dentry);
return 0;
}
static int t7xx_trace_subbuf_start_handler(struct rchan_buf *buf, void *subbuf,
void *prev_subbuf, size_t prev_padding)
{
if (relay_buf_full(buf)) {
pr_err_ratelimited("Relay_buf full dropping traces");
return 0;
}
return 1;
}
static struct rchan_callbacks relay_callbacks = {
.subbuf_start = t7xx_trace_subbuf_start_handler,
.create_buf_file = t7xx_trace_create_buf_file_handler,
.remove_buf_file = t7xx_trace_remove_buf_file_handler,
};
static void t7xx_trace_port_uninit(struct t7xx_port *port)
{
struct dentry *debugfs_dir = port->t7xx_dev->debugfs_dir;
struct rchan *relaych = port->log.relaych;
if (!relaych)
return;
relay_close(relaych);
debugfs_remove_recursive(debugfs_dir);
}
static int t7xx_trace_port_recv_skb(struct t7xx_port *port, struct sk_buff *skb)
{
struct rchan *relaych = port->log.relaych;
if (!relaych)
return -EINVAL;
relay_write(relaych, skb->data, skb->len);
dev_kfree_skb(skb);
return 0;
}
static void t7xx_port_trace_md_state_notify(struct t7xx_port *port, unsigned int state)
{
struct rchan *relaych = port->log.relaych;
struct dentry *debugfs_wwan_dir;
struct dentry *debugfs_dir;
if (state != MD_STATE_READY || relaych)
return;
debugfs_wwan_dir = wwan_get_debugfs_dir(port->dev);
if (IS_ERR(debugfs_wwan_dir))
return;
debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, debugfs_wwan_dir);
if (IS_ERR_OR_NULL(debugfs_dir)) {
wwan_put_debugfs_dir(debugfs_wwan_dir);
dev_err(port->dev, "Unable to create debugfs for trace");
return;
}
relaych = relay_open("relay_ch", debugfs_dir, T7XX_TRC_SUB_BUFF_SIZE,
T7XX_TRC_N_SUB_BUFF, &relay_callbacks, NULL);
if (!relaych)
goto err_rm_debugfs_dir;
wwan_put_debugfs_dir(debugfs_wwan_dir);
port->log.relaych = relaych;
port->t7xx_dev->debugfs_dir = debugfs_dir;
return;
err_rm_debugfs_dir:
debugfs_remove_recursive(debugfs_dir);
wwan_put_debugfs_dir(debugfs_wwan_dir);
dev_err(port->dev, "Unable to create trace port %s", port->port_conf->name);
}
struct port_ops t7xx_trace_port_ops = {
.recv_skb = t7xx_trace_port_recv_skb,
.uninit = t7xx_trace_port_uninit,
.md_state_notify = t7xx_port_trace_md_state_notify,
};
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