File Index
Files and directories
Sign in
FILE

t7xx_port_trace.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wwan/t7xx/t7xx_port_trace.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2022 Intel Corporation.
  4 */
  5
  6#include <linux/debugfs.h>
  7#include <linux/relay.h>
  8#include <linux/skbuff.h>
  9#include <linux/wwan.h>
 10
 11#include "t7xx_port.h"
 12#include "t7xx_port_proxy.h"
 13#include "t7xx_state_monitor.h"
 14
 15#define T7XX_TRC_SUB_BUFF_SIZE		131072
 16#define T7XX_TRC_N_SUB_BUFF		32
 17
 18static struct dentry *t7xx_trace_create_buf_file_handler(const char *filename,
 19							 struct dentry *parent,
 20							 umode_t mode,
 21							 struct rchan_buf *buf,
 22							 int *is_global)
 23{
 24	*is_global = 1;
 25	return debugfs_create_file(filename, mode, parent, buf,
 26				   &relay_file_operations);
 27}
 28
 29static int t7xx_trace_remove_buf_file_handler(struct dentry *dentry)
 30{
 31	debugfs_remove(dentry);
 32	return 0;
 33}
 34
 35static int t7xx_trace_subbuf_start_handler(struct rchan_buf *buf, void *subbuf,
 36					   void *prev_subbuf)
 37{
 38	if (relay_buf_full(buf)) {
 39		pr_err_ratelimited("Relay_buf full dropping traces");
 40		return 0;
 41	}
 42
 43	return 1;
 44}
 45
 46static struct rchan_callbacks relay_callbacks = {
 47	.subbuf_start = t7xx_trace_subbuf_start_handler,
 48	.create_buf_file = t7xx_trace_create_buf_file_handler,
 49	.remove_buf_file = t7xx_trace_remove_buf_file_handler,
 50};
 51
 52static void t7xx_trace_port_uninit(struct t7xx_port *port)
 53{
 54	struct dentry *debugfs_dir = port->t7xx_dev->debugfs_dir;
 55	struct rchan *relaych = port->log.relaych;
 56
 57	if (!relaych)
 58		return;
 59
 60	relay_close(relaych);
 61	debugfs_remove_recursive(debugfs_dir);
 62	port->log.relaych = NULL;
 63}
 64
 65static int t7xx_trace_port_recv_skb(struct t7xx_port *port, struct sk_buff *skb)
 66{
 67	struct rchan *relaych = port->log.relaych;
 68
 69	if (!relaych)
 70		return -EINVAL;
 71
 72	relay_write(relaych, skb->data, skb->len);
 73	dev_kfree_skb(skb);
 74	return 0;
 75}
 76
 77static void t7xx_port_trace_md_state_notify(struct t7xx_port *port, unsigned int state)
 78{
 79	struct rchan *relaych = port->log.relaych;
 80	struct dentry *debugfs_wwan_dir;
 81	struct dentry *debugfs_dir;
 82
 83	if (state != MD_STATE_READY || relaych)
 84		return;
 85
 86	debugfs_wwan_dir = wwan_get_debugfs_dir(port->dev);
 87	if (IS_ERR(debugfs_wwan_dir))
 88		return;
 89
 90	debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, debugfs_wwan_dir);
 91	if (IS_ERR_OR_NULL(debugfs_dir)) {
 92		wwan_put_debugfs_dir(debugfs_wwan_dir);
 93		dev_err(port->dev, "Unable to create debugfs for trace");
 94		return;
 95	}
 96
 97	relaych = relay_open("relay_ch", debugfs_dir, T7XX_TRC_SUB_BUFF_SIZE,
 98			     T7XX_TRC_N_SUB_BUFF, &relay_callbacks, NULL);
 99	if (!relaych)
100		goto err_rm_debugfs_dir;
101
102	wwan_put_debugfs_dir(debugfs_wwan_dir);
103	port->log.relaych = relaych;
104	port->t7xx_dev->debugfs_dir = debugfs_dir;
105	return;
106
107err_rm_debugfs_dir:
108	debugfs_remove_recursive(debugfs_dir);
109	wwan_put_debugfs_dir(debugfs_wwan_dir);
110	dev_err(port->dev, "Unable to create trace port %s", port->port_conf->name);
111}
112
113struct port_ops t7xx_trace_port_ops = {
114	.recv_skb = t7xx_trace_port_recv_skb,
115	.uninit = t7xx_trace_port_uninit,
116	.md_state_notify = t7xx_port_trace_md_state_notify,
117};
~/ Read-only file preview.