diff --git a/net/ncsi/Kconfig b/net/ncsi/Kconfig
index 08a8a60..baa42501 100644
--- a/net/ncsi/Kconfig
+++ b/net/ncsi/Kconfig
@@ -10,3 +10,12 @@ config NET_NCSI
 	  support. Enable this only if your system connects to a network
 	  device via NCSI and the ethernet driver you're using supports
 	  the protocol explicitly.
+
+config NET_NCSI_DEBUG
+	bool "Enable NCSI debugging"
+	depends on NET_NCSI && DEBUG_FS
+	default n
+	---help---
+	  This enables the interfaces (e.g. debugfs) for NCSI debugging purpose.
+
+	  If unsure, say Y.
diff --git a/net/ncsi/Makefile b/net/ncsi/Makefile
index dd12b56..2897fa0 100644
--- a/net/ncsi/Makefile
+++ b/net/ncsi/Makefile
@@ -2,3 +2,4 @@
 # Makefile for NCSI API
 #
 obj-$(CONFIG_NET_NCSI) += ncsi-cmd.o ncsi-rsp.o ncsi-aen.o ncsi-manage.o
+obj-$(CONFIG_NET_NCSI_DEBUG) += ncsi-debug.o
diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index 1308a56..e9ede4f 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -198,6 +198,9 @@ struct ncsi_channel {
 	} monitor;
 	struct list_head            node;
 	struct list_head            link;
+#ifdef CONFIG_NET_NCSI_DEBUG
+	struct dentry               *dentry;    /* Debugfs directory    */
+#endif
 };
 
 struct ncsi_package {
@@ -208,6 +211,9 @@ struct ncsi_package {
 	unsigned int         channel_num; /* Number of channels     */
 	struct list_head     channels;    /* List of chanels        */
 	struct list_head     node;        /* Form list of packages  */
+#ifdef CONFIG_NET_NCSI_DEBUG
+	struct dentry        *dentry;     /* Debugfs directory       */
+#endif
 };
 
 struct ncsi_request {
@@ -276,6 +282,9 @@ struct ncsi_dev_priv {
 	struct work_struct  work;            /* For channel management     */
 	struct packet_type  ptype;           /* NCSI packet Rx handler     */
 	struct list_head    node;            /* Form NCSI device list      */
+#ifdef CONFIG_NET_NCSI_DEBUG
+	struct dentry       *dentry;         /* Procfs directory           */
+#endif
 };
 
 struct ncsi_cmd_arg {
@@ -337,4 +346,40 @@ int ncsi_rcv_rsp(struct sk_buff *skb, struct net_device *dev,
 		 struct packet_type *pt, struct net_device *orig_dev);
 int ncsi_aen_handler(struct ncsi_dev_priv *ndp, struct sk_buff *skb);
 
+/* Debugging functionality */
+#ifdef CONFIG_NET_NCSI_DEBUG
+int ncsi_dev_init_debug(struct ncsi_dev_priv *ndp);
+void ncsi_dev_release_debug(struct ncsi_dev_priv *ndp);
+int ncsi_package_init_debug(struct ncsi_package *np);
+void ncsi_package_release_debug(struct ncsi_package *np);
+int ncsi_channel_init_debug(struct ncsi_channel *nc);
+void ncsi_channel_release_debug(struct ncsi_channel *nc);
+#else
+static inline int ncsi_dev_init_debug(struct ncsi_dev_priv *ndp)
+{
+	return -ENOTTY;
+}
+
+static inline void ncsi_dev_release_debug(struct ncsi_dev_priv *ndp)
+{
+}
+
+static inline int ncsi_package_init_debug(struct ncsi_package *np)
+{
+	return -ENOTTY;
+}
+
+static inline void ncsi_package_release_debug(struct ncsi_package *np)
+{
+}
+
+static inline int ncsi_channel_init_debug(struct ncsi_channel *nc)
+{
+	return -ENOTTY;
+}
+
+static inline void ncsi_channel_release_debug(struct ncsi_channel *nc)
+{
+}
+#endif /* CONFIG_NET_NCSI_DEBUG */
 #endif /* __NCSI_INTERNAL_H__ */
diff --git a/net/ncsi/ncsi-debug.c b/net/ncsi/ncsi-debug.c
new file mode 100644
index 0000000..f38483d
--- /dev/null
+++ b/net/ncsi/ncsi-debug.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright Gavin Shan, IBM Corporation 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/atomic.h>
+#include <linux/netdevice.h>
+#include <linux/debugfs.h>
+#include <linux/skbuff.h>
+
+#include <net/ncsi.h>
+#include <net/net_namespace.h>
+#include <net/sock.h>
+
+#include "internal.h"
+#include "ncsi-pkt.h"
+
+static struct dentry *ncsi_dentry;
+
+int ncsi_dev_init_debug(struct ncsi_dev_priv *ndp)
+{
+	if (WARN_ON_ONCE(ndp->dentry))
+		return 0;
+
+	if (!ncsi_dentry) {
+		ncsi_dentry = debugfs_create_dir("ncsi", NULL);
+		if (!ncsi_dentry) {
+			pr_debug("Failed to create debugfs directory 'ncsi'\n");
+			return -ENOMEM;
+		}
+	}
+
+	ndp->dentry = debugfs_create_dir(netdev_name(ndp->ndev.dev),
+					 ncsi_dentry);
+	if (!ndp->dentry) {
+		pr_debug("Failed to create debugfs directory 'ncsi/%s'\n",
+			 netdev_name(ndp->ndev.dev));
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void ncsi_dev_release_debug(struct ncsi_dev_priv *ndp)
+{
+	debugfs_remove(ndp->dentry);
+}
+
+int ncsi_package_init_debug(struct ncsi_package *np)
+{
+	struct ncsi_dev_priv *ndp = np->ndp;
+	char name[4];
+
+	if (!ndp->dentry)
+		return -ENOENT;
+
+	sprintf(name, "p%d", np->id);
+	np->dentry = debugfs_create_dir(name, ndp->dentry);
+	if (!np->dentry) {
+		pr_debug("Failed to create debugfs directory ncsi/%s/%s\n",
+			 netdev_name(ndp->ndev.dev), name);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void ncsi_package_release_debug(struct ncsi_package *np)
+{
+	debugfs_remove(np->dentry);
+}
+
+int ncsi_channel_init_debug(struct ncsi_channel *nc)
+{
+	struct ncsi_package *np = nc->package;
+	struct ncsi_dev_priv *ndp = np->ndp;
+	char name[3];
+
+	if (!np->dentry)
+		return -ENOENT;
+
+	sprintf(name, "c%d", nc->id);
+	nc->dentry = debugfs_create_dir(name, np->dentry);
+	if (!nc->dentry) {
+		pr_debug("Failed to create debugfs directory ncsi/%s/p%d/c%d\n",
+			 netdev_name(ndp->ndev.dev), np->id, nc->id);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void ncsi_channel_release_debug(struct ncsi_channel *nc)
+{
+	debugfs_remove(nc->dentry);
+}
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 13ad1f26..84f1405 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -322,6 +322,8 @@ struct ncsi_channel *ncsi_add_channel(struct ncsi_package *np, unsigned char id)
 	np->channel_num++;
 	spin_unlock_irqrestore(&np->lock, flags);
 
+	ncsi_channel_init_debug(nc);
+
 	return nc;
 }
 
@@ -332,6 +334,8 @@ static void ncsi_remove_channel(struct ncsi_channel *nc)
 	unsigned long flags;
 	int i;
 
+	ncsi_channel_release_debug(nc);
+
 	/* Release filters */
 	spin_lock_irqsave(&nc->lock, flags);
 	for (i = 0; i < NCSI_FILTER_MAX; i++) {
@@ -396,6 +400,8 @@ struct ncsi_package *ncsi_add_package(struct ncsi_dev_priv *ndp,
 	ndp->package_num++;
 	spin_unlock_irqrestore(&ndp->lock, flags);
 
+	ncsi_package_init_debug(np);
+
 	return np;
 }
 
@@ -409,6 +415,8 @@ void ncsi_remove_package(struct ncsi_package *np)
 	list_for_each_entry_safe(nc, tmp, &np->channels, node)
 		ncsi_remove_channel(nc);
 
+	ncsi_package_release_debug(np);
+
 	/* Remove and free package */
 	spin_lock_irqsave(&ndp->lock, flags);
 	list_del_rcu(&np->node);
@@ -1280,6 +1288,13 @@ int ncsi_start_dev(struct ncsi_dev *nd)
 		return -ENOTTY;
 
 	if (!(ndp->flags & NCSI_DEV_PROBED)) {
+		/* The debugging functionality should have been initialized
+		 * when registerring the NCSI device. As the network device
+		 * name isn't available that time, we have to delay the work
+		 * to here.
+		 */
+		ncsi_dev_init_debug(ndp);
+
 		nd->state = ncsi_dev_state_probe;
 		schedule_work(&ndp->work);
 		return 0;
@@ -1329,6 +1344,7 @@ void ncsi_unregister_dev(struct ncsi_dev *nd)
 	struct ncsi_package *np, *tmp;
 	unsigned long flags;
 
+	ncsi_dev_release_debug(ndp);
 	dev_remove_pack(&ndp->ptype);
 
 	list_for_each_entry_safe(np, tmp, &ndp->packages, node)
