All of lore.kernel.org
 help / color / mirror / Atom feed
From: Inaky Perez-Gonzalez <inaky@linux.intel.com>
To: netdev@vger.kernel.org
Cc: wimax@linuxwimax.org, greg@kroah.com
Subject: [PATCH 18/29] i2400m: debugfs controls
Date: Mon, 15 Dec 2008 04:58:13 -0800	[thread overview]
Message-ID: <25128ccc0c011eb030bfb2958f75de013dd66020.1229345779.git.inaky@linux.intel.com> (raw)
In-Reply-To: <cover.1229345769.git.inaky@linux.intel.com>

Expose knobs to control the device (induce reset, power saving,
querying tx or rx stats, internal debug information and debug level
manipulation).

Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
---
 drivers/net/wimax/i2400m/debugfs.c |  392 ++++++++++++++++++++++++++++++++++++
 1 files changed, 392 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/wimax/i2400m/debugfs.c

diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c
new file mode 100644
index 0000000..6266329
--- /dev/null
+++ b/drivers/net/wimax/i2400m/debugfs.c
@@ -0,0 +1,392 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Debugfs interfaces to manipulate driver and device information
+ *
+ *
+ * Copyright (C) 2007 Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include "i2400m.h"
+
+
+#define D_SUBMODULE debugfs
+#include "debug-levels.h"
+
+static
+int debugfs_netdev_queue_stopped_get(void *data, u64 *val)
+{
+	struct i2400m *i2400m = data;
+	*val = netif_queue_stopped(i2400m->wimax_dev.net_dev);
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_netdev_queue_stopped,
+			debugfs_netdev_queue_stopped_get,
+			NULL, "%llu\n");
+
+
+static
+struct dentry *debugfs_create_netdev_queue_stopped(
+	const char *name, struct dentry *parent, struct i2400m *i2400m)
+{
+	return debugfs_create_file(name, 0400, parent, i2400m,
+				   &fops_netdev_queue_stopped);
+}
+
+
+/*
+ * inode->i_private has the @data argument to debugfs_create_file()
+ */
+static
+int i2400m_stats_open(struct inode *inode, struct file *filp)
+{
+	filp->private_data = inode->i_private;
+	return 0;
+}
+
+/*
+ * We don't allow partial reads of this file, as then the reader would
+ * get weirdly confused data as it is updated.
+ *
+ * So or you read it all or nothing; if you try to read with an offset
+ * != 0, we consider you are done reading.
+ */
+static
+ssize_t i2400m_rx_stats_read(struct file *filp, char __user *buffer,
+			     size_t count, loff_t *ppos)
+{
+	struct i2400m *i2400m = filp->private_data;
+	char buf[128];
+	unsigned long flags;
+
+	if (*ppos != 0)
+		return 0;
+	if (count < sizeof(buf))
+		return -ENOSPC;
+	spin_lock_irqsave(&i2400m->rx_lock, flags);
+	snprintf(buf, sizeof(buf), "%u %u %u %u %u %u %u\n",
+		 i2400m->rx_pl_num, i2400m->rx_pl_min,
+		 i2400m->rx_pl_max, i2400m->rx_num,
+		 i2400m->rx_size_acc,
+		 i2400m->rx_size_min, i2400m->rx_size_max);
+	spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+	return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
+}
+
+
+/* Any write clears the stats */
+static
+ssize_t i2400m_rx_stats_write(struct file *filp, const char __user *buffer,
+			      size_t count, loff_t *ppos)
+{
+	struct i2400m *i2400m = filp->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i2400m->rx_lock, flags);
+	i2400m->rx_pl_num = 0;
+	i2400m->rx_pl_max = 0;
+	i2400m->rx_pl_min = UINT_MAX;
+	i2400m->rx_num = 0;
+	i2400m->rx_size_acc = 0;
+	i2400m->rx_size_min = UINT_MAX;
+	i2400m->rx_size_max = 0;
+	spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+	return count;
+}
+
+static
+const struct file_operations i2400m_rx_stats_fops = {
+	.owner =	THIS_MODULE,
+	.open =		i2400m_stats_open,
+	.read =		i2400m_rx_stats_read,
+	.write =	i2400m_rx_stats_write,
+};
+
+
+/* See i2400m_rx_stats_read() */
+static
+ssize_t i2400m_tx_stats_read(struct file *filp, char __user *buffer,
+			     size_t count, loff_t *ppos)
+{
+	struct i2400m *i2400m = filp->private_data;
+	char buf[128];
+	unsigned long flags;
+
+	if (*ppos != 0)
+		return 0;
+	if (count < sizeof(buf))
+		return -ENOSPC;
+	spin_lock_irqsave(&i2400m->tx_lock, flags);
+	snprintf(buf, sizeof(buf), "%u %u %u %u %u %u %u\n",
+		 i2400m->tx_pl_num, i2400m->tx_pl_min,
+		 i2400m->tx_pl_max, i2400m->tx_num,
+		 i2400m->tx_size_acc,
+		 i2400m->tx_size_min, i2400m->tx_size_max);
+	spin_unlock_irqrestore(&i2400m->tx_lock, flags);
+	return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
+}
+
+/* Any write clears the stats */
+static
+ssize_t i2400m_tx_stats_write(struct file *filp, const char __user *buffer,
+			      size_t count, loff_t *ppos)
+{
+	struct i2400m *i2400m = filp->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i2400m->tx_lock, flags);
+	i2400m->tx_pl_num = 0;
+	i2400m->tx_pl_max = 0;
+	i2400m->tx_pl_min = UINT_MAX;
+	i2400m->tx_num = 0;
+	i2400m->tx_size_acc = 0;
+	i2400m->tx_size_min = UINT_MAX;
+	i2400m->tx_size_max = 0;
+	spin_unlock_irqrestore(&i2400m->tx_lock, flags);
+	return count;
+}
+
+static
+const struct file_operations i2400m_tx_stats_fops = {
+	.owner =	THIS_MODULE,
+	.open =		i2400m_stats_open,
+	.read =		i2400m_tx_stats_read,
+	.write =	i2400m_tx_stats_write,
+};
+
+
+/* Write 1 to ask the device to go into suspend */
+static
+int debugfs_i2400m_suspend_set(void *data, u64 val)
+{
+	int result;
+	struct i2400m *i2400m = data;
+	result = i2400m_cmd_enter_powersave(i2400m);
+	if (result >= 0)
+		result = 0;
+	return result;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_suspend,
+			NULL, debugfs_i2400m_suspend_set,
+			"%llu\n");
+
+static
+struct dentry *debugfs_create_i2400m_suspend(
+	const char *name, struct dentry *parent, struct i2400m *i2400m)
+{
+	return debugfs_create_file(name, 0200, parent, i2400m,
+				   &fops_i2400m_suspend);
+}
+
+
+/*
+ * Reset the device
+ *
+ * Write 0 to ask the device to soft reset, 1 to cold reset, 2 to bus
+ * reset (as defined by enum i2400m_reset_type).
+ */
+static
+int debugfs_i2400m_reset_set(void *data, u64 val)
+{
+	int result;
+	struct i2400m *i2400m = data;
+	enum i2400m_reset_type rt = val;
+	switch(rt) {
+	case I2400M_RT_WARM:
+	case I2400M_RT_COLD:
+	case I2400M_RT_BUS:
+		result = i2400m->bus_reset(i2400m, rt);
+		if (result >= 0)
+			result = 0;
+	default:
+		result = -EINVAL;
+	}
+	return result;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_reset,
+			NULL, debugfs_i2400m_reset_set,
+			"%llu\n");
+
+static
+struct dentry *debugfs_create_i2400m_reset(
+	const char *name, struct dentry *parent, struct i2400m *i2400m)
+{
+	return debugfs_create_file(name, 0200, parent, i2400m,
+				   &fops_i2400m_reset);
+}
+
+/*
+ * Debug levels control; see debug.h
+ */
+struct d_level D_LEVEL[] = {
+	D_SUBMODULE_DEFINE(control),
+	D_SUBMODULE_DEFINE(driver),
+	D_SUBMODULE_DEFINE(debugfs),
+	D_SUBMODULE_DEFINE(fw),
+	D_SUBMODULE_DEFINE(netdev),
+	D_SUBMODULE_DEFINE(rfkill),
+	D_SUBMODULE_DEFINE(rx),
+	D_SUBMODULE_DEFINE(tx),
+};
+size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
+
+#define __debugfs_register(prefix, name, parent)			\
+do {									\
+	result = d_level_register_debugfs(prefix, name, parent);	\
+	if (result < 0)							\
+		goto error;						\
+} while (0)
+
+
+int i2400m_debugfs_add(struct i2400m *i2400m)
+{
+	int result;
+	struct device *dev = i2400m_dev(i2400m);
+	struct dentry *dentry = i2400m->wimax_dev.debugfs_dentry;
+	struct dentry *fd;
+
+	dentry = debugfs_create_dir("i2400m", dentry);
+	result = PTR_ERR(dentry);
+	if (IS_ERR(dentry)) {
+		if (result == -ENODEV)
+			result = 0;	/* No debugfs support */
+		goto error;
+	}
+	i2400m->debugfs_dentry = dentry;
+	__debugfs_register("dl_", control, dentry);
+	__debugfs_register("dl_", driver, dentry);
+	__debugfs_register("dl_", debugfs, dentry);
+	__debugfs_register("dl_", fw, dentry);
+	__debugfs_register("dl_", netdev, dentry);
+	__debugfs_register("dl_", rfkill, dentry);
+	__debugfs_register("dl_", rx, dentry);
+	__debugfs_register("dl_", tx, dentry);
+
+	fd = debugfs_create_size_t("tx_in", 0400, dentry,
+				   &i2400m->tx_in);
+	result = PTR_ERR(fd);
+	if (IS_ERR(fd) && result != -ENODEV) {
+		dev_err(dev, "Can't create debugfs entry "
+			"tx_in: %d\n", result);
+		goto error;
+	}
+
+	fd = debugfs_create_size_t("tx_out", 0400, dentry,
+				   &i2400m->tx_out);
+	result = PTR_ERR(fd);
+	if (IS_ERR(fd) && result != -ENODEV) {
+		dev_err(dev, "Can't create debugfs entry "
+			"tx_out: %d\n", result);
+		goto error;
+	}
+
+	fd = debugfs_create_u32("state", 0600, dentry,
+				&i2400m->state);
+	result = PTR_ERR(fd);
+	if (IS_ERR(fd) && result != -ENODEV) {
+		dev_err(dev, "Can't create debugfs entry "
+			"state: %d\n", result);
+		goto error;
+	}
+
+	/*
+	 * Trace received messages from user space
+	 *
+	 * In order to tap the bidirectional message stream in the
+	 * 'msg' pipe, user space can read from the 'msg' pipe;
+	 * however, due to limitations in libnl, we can't know what
+	 * the different applications are sending down to the kernel.
+	 *
+	 * So we have this hack where the driver will echo any message
+	 * received on the msg pipe from user space [through a call to
+	 * wimax_dev->op_msg_from_user() into
+	 * i2400m_op_msg_from_user()] into the 'trace' pipe that this
+	 * driver creates.
+	 *
+	 * So then, reading from both the 'trace' and 'msg' pipes in
+	 * user space will provide a full dump of the traffic.
+	 *
+	 * Write 1 to activate, 0 to clear.
+	 *
+	 * It is not really very atomic, but it is also not too
+	 * critical.
+	 */
+	fd = debugfs_create_u8("trace_msg_from_user", 0600, dentry,
+			       &i2400m->trace_msg_from_user);
+	result = PTR_ERR(fd);
+	if (IS_ERR(fd) && result != -ENODEV) {
+		dev_err(dev, "Can't create debugfs entry "
+			"trace_msg_from_user: %d\n", result);
+		goto error;
+	}
+
+	fd = debugfs_create_netdev_queue_stopped("netdev_queue_stopped",
+						 dentry, i2400m);
+	result = PTR_ERR(fd);
+	if (IS_ERR(fd) && result != -ENODEV) {
+		dev_err(dev, "Can't create debugfs entry "
+			"netdev_queue_stopped: %d\n", result);
+		goto error;
+	}
+
+	fd = debugfs_create_file("rx_stats", 0600, dentry, i2400m,
+				 &i2400m_rx_stats_fops);
+	result = PTR_ERR(fd);
+	if (IS_ERR(fd) && result != -ENODEV) {
+		dev_err(dev, "Can't create debugfs entry "
+			"rx_stats: %d\n", result);
+		goto error;
+	}
+
+	fd = debugfs_create_file("tx_stats", 0600, dentry, i2400m,
+				 &i2400m_tx_stats_fops);
+	result = PTR_ERR(fd);
+	if (IS_ERR(fd) && result != -ENODEV) {
+		dev_err(dev, "Can't create debugfs entry "
+			"tx_stats: %d\n", result);
+		goto error;
+	}
+
+	fd = debugfs_create_i2400m_suspend("suspend", dentry, i2400m);
+	result = PTR_ERR(fd);
+	if (IS_ERR(fd) && result != -ENODEV) {
+		dev_err(dev, "Can't create debugfs entry suspend: %d\n",
+			result);
+		goto error;
+	}
+
+	fd = debugfs_create_i2400m_reset("reset", dentry, i2400m);
+	result = PTR_ERR(fd);
+	if (IS_ERR(fd) && result != -ENODEV) {
+		dev_err(dev, "Can't create debugfs entry reset: %d\n", result);
+		goto error;
+	}
+
+	result = 0;
+error:
+	return result;
+}
+
+void i2400m_debugfs_rm(struct i2400m *i2400m)
+{
+	debugfs_remove_recursive(i2400m->debugfs_dentry);
+}
-- 
1.5.6.5


  parent reply	other threads:[~2008-12-15 13:29 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-15 12:57 [PATCH 00/29] merge request for WiMAX kernel stack and i2400m driver v6 Inaky Perez-Gonzalez
2008-12-15 12:57 ` [PATCH 01/29] wimax: documentation for the stack Inaky Perez-Gonzalez
2008-12-15 12:57 ` [PATCH 02/29] wimax: headers for kernel API and user space interaction Inaky Perez-Gonzalez
2008-12-16  3:43   ` Wang Chen
2008-12-17 17:44     ` Inaky Perez-Gonzalez
2008-12-15 12:57 ` [PATCH 03/29] wimax: internal API for the kernel space WiMAX stack Inaky Perez-Gonzalez
2008-12-15 12:57 ` [PATCH 04/29] wimax: debug macros and debug settings for the " Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 05/29] wimax: generic device management (registration, deregistration, lookup) Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 06/29] genetlink: export genl_unregister_mc_group() Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 07/29] wimax: basic API: kernel/user messaging, rfkill and reset Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 08/29] debugfs: add helpers for exporting a size_t simple value Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 09/29] wimax: debugfs controls Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 10/29] wimax: Makefile, Kconfig and docbook linkage for the stack Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 11/29] i2400m: documentation and instructions for usage Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 12/29] i2400m: host/device procotol and core driver definitions Inaky Perez-Gonzalez
2008-12-16  3:43   ` Wang Chen
2008-12-15 12:58 ` [PATCH 13/29] i2400m: Generic probe/disconnect, reset and message passing Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 14/29] i2400m: linkage to the networking stack Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 15/29] i2400m: firmware loading and bootrom initialization Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 16/29] i2400m: RX and TX data/control paths Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 17/29] i2400m: various functions for device management Inaky Perez-Gonzalez
2008-12-15 12:58 ` Inaky Perez-Gonzalez [this message]
2008-12-15 12:58 ` [PATCH 19/29] i2400m/USB: header for the USB bus driver Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 20/29] i2400m/USB: probe/disconnect, dev init/shutdown and reset backends Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 21/29] i2400m/USB: firmware upload backend Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 22/29] i2400m/USB: TX and RX path backends Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 23/29] i2400m/SDIO: header for the SDIO subdriver Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 24/29] i2400m/SDIO: probe/disconnect, dev init/shutdown and reset backends Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 25/29] i2400m/SDIO: firmware upload backend Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 26/29] i2400m/SDIO: TX and RX path backends Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 27/29] i2400m: Makefile and Kconfig Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 28/29] wimax: export linux/wimax.h and linux/wimax/i2400m.h with headers_install Inaky Perez-Gonzalez
2008-12-15 12:58 ` [PATCH 29/29] wimax/i2400m: add CREDITS and MAINTAINERS entries Inaky Perez-Gonzalez
2008-12-15 22:54 ` [PATCH 00/29] merge request for WiMAX kernel stack and i2400m driver v6 David Miller
2008-12-17 17:37   ` Inaky Perez-Gonzalez
  -- strict thread matches above, loose matches on Subject: below --
2008-12-21  0:57 [PATCH 00/29] merge request for WiMAX kernel stack and i2400m driver v7 Inaky Perez-Gonzalez
2008-12-21  0:57 ` [PATCH 18/29] i2400m: debugfs controls Inaky Perez-Gonzalez
2008-12-10 23:12 [PATCH 00/29] merge request for WiMAX kernel stack and i2400m driver v4 Inaky Perez-Gonzalez
2008-12-10 23:12 ` [PATCH 18/29] i2400m: debugfs controls Inaky Perez-Gonzalez
2008-12-08 19:09 [PATCH 00/29] merge request for WiMAX kernel stack and i2400m driver v3 Inaky Perez-Gonzalez
2008-12-08 19:09 ` [PATCH 18/29] i2400m: debugfs controls Inaky Perez-Gonzalez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=25128ccc0c011eb030bfb2958f75de013dd66020.1229345779.git.inaky@linux.intel.com \
    --to=inaky@linux.intel.com \
    --cc=greg@kroah.com \
    --cc=netdev@vger.kernel.org \
    --cc=wimax@linuxwimax.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.