All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] NSCI Improvement
@ 2016-05-09  1:47 Gavin Shan
  2016-05-09  1:47 ` [PATCH 1/8] net/ncsi: Remove netlink support Gavin Shan
                   ` (8 more replies)
  0 siblings, 9 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-09  1:47 UTC (permalink / raw)
  To: openbmc; +Cc: Gavin Shan

This series bases on branch dev-4.4. Couple of things are improved as below:

   * Remove netlink stuff as nobody starts to use it. Lets focus on the core
     for now.
   * The available packages and channels are enumerated for once when user
     brings up the network interface for the first time. Afterwords, less
     time (3 to 4 seconds) are reduced to bring up the interface.
   * Explicitly enable AEN that is disabled by default.
   * The LSC (Link Status Change) AEN handler helps switching active channel
     properly after the packet can be received without problem. In order to
     listen for ingress AEN packet, the MAC has to be ready for reception
     after the interface is brought up.

This series is to fix the bug: https://github.com/openbmc/linux/issues/61
With this series applied (based on dev-4.4), it should fix the issue. Note
that I had the test on palm4-bmc.

   * From uboot, download the kernel image;
   * Unplug the ethernet cable;
   * From uboot, boot the kernel image;
   * Configure the ethernet interface when the kernel boots up completely.
     The NCSI interface should be down;
   * Plug the cable, the NCSI interface is up automatically. The interface
     is pingable from external. 

Gavin Shan (8):
  net/ncsi: Remove netlink support
  net/ncsi: Add NCSI_DEV_PRIV_FLAG_POPULATED
  net/ncsi: Enumerate NCSI channels in advance
  net/ncsi: Remove ncsi_stop_dev()
  net/ncsi: Enable AEN on active channel
  net/ncsi: Improvement for ncsi_dev_suspend()
  net/farady: Keep MAC always active for NCSI packets
  net/ncsi: LSC AEN handler improvement

 drivers/net/ethernet/faraday/ftgmac100.c |   21 +-
 include/net/ncsi.h                       |   10 +-
 include/uapi/linux/netlink.h             |    1 -
 net/ncsi/Makefile                        |    2 +-
 net/ncsi/internal.h                      |   36 +-
 net/ncsi/ncsi-aen.c                      |    6 +-
 net/ncsi/ncsi-cmd.c                      |    8 -
 net/ncsi/ncsi-manage.c                   |  226 ++++---
 net/ncsi/ncsi-netlink.c                  | 1042 ------------------------------
 net/ncsi/ncsi-rsp.c                      |    7 +-
 net/ncsi/ncsi.c                          |   49 --
 11 files changed, 134 insertions(+), 1274 deletions(-)
 delete mode 100644 net/ncsi/ncsi-netlink.c
 delete mode 100644 net/ncsi/ncsi.c

-- 
2.1.0

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/8] net/ncsi: Remove netlink support
  2016-05-09  1:47 [PATCH 0/8] NSCI Improvement Gavin Shan
@ 2016-05-09  1:47 ` Gavin Shan
  2016-05-09  1:47 ` [PATCH 2/8] net/ncsi: Add NCSI_DEV_PRIV_FLAG_POPULATED Gavin Shan
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-09  1:47 UTC (permalink / raw)
  To: openbmc; +Cc: Gavin Shan

This removes NCSI netlink support that was designed as user interface
to retrieve available packages and their associated channels. Until
now, nobody is using this interface. Generally, it reverts commit
4972fc2 ("net/ncsi: Netlink support"). After the NCSI core becomes
stablized, we need revisit the user interface.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 include/uapi/linux/netlink.h |    1 -
 net/ncsi/Makefile            |    2 +-
 net/ncsi/internal.h          |   15 -
 net/ncsi/ncsi-cmd.c          |    8 -
 net/ncsi/ncsi-manage.c       |   10 -
 net/ncsi/ncsi-netlink.c      | 1042 ------------------------------------------
 net/ncsi/ncsi.c              |   49 --
 7 files changed, 1 insertion(+), 1126 deletions(-)
 delete mode 100644 net/ncsi/ncsi-netlink.c
 delete mode 100644 net/ncsi/ncsi.c

diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
index c572cf5..f095155 100644
--- a/include/uapi/linux/netlink.h
+++ b/include/uapi/linux/netlink.h
@@ -27,7 +27,6 @@
 #define NETLINK_ECRYPTFS	19
 #define NETLINK_RDMA		20
 #define NETLINK_CRYPTO		21	/* Crypto layer */
-#define NETLINK_NCSI		22	/* NCSI */
 
 #define NETLINK_INET_DIAG	NETLINK_SOCK_DIAG
 
diff --git a/net/ncsi/Makefile b/net/ncsi/Makefile
index bf9f7a9..e4094c2 100644
--- a/net/ncsi/Makefile
+++ b/net/ncsi/Makefile
@@ -2,4 +2,4 @@
 # Makefile for NCSI API
 #
 obj-$(CONFIG_NET_NCSI) += ncsi-cmd.o ncsi-rsp.o ncsi-aen.o \
-			  ncsi-manage.o ncsi-netlink.o ncsi.o
+			  ncsi-manage.o
diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index e87991b..ac5f129 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -37,14 +37,6 @@ struct ncsi_package {
 	struct list_head	np_node;
 };
 
-struct ncsi_skb_parms {
-	unsigned int		nsp_valid;
-	unsigned int		nsp_portid;
-	struct nlmsghdr		nsp_nlh;
-};
-
-#define NCSI_CB(skb)	(*(struct ncsi_skb_parms*)&((skb)->cb))
-
 struct ncsi_req {
 	unsigned char		nr_id;
 	bool			nr_used;
@@ -107,7 +99,6 @@ struct ncsi_cmd_arg {
 	unsigned char		nca_package;
 	unsigned char		nca_channel;
 	unsigned short		nca_payload;
-	struct nlmsghdr		*nca_nlh;
 	unsigned int		nca_portid;
 	union {
 		unsigned char	nca_bytes[16];
@@ -156,10 +147,4 @@ int ncsi_xmit_cmd(struct ncsi_cmd_arg *nca);
 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);
-
-/* Netlink */
-int __net_init ncsi_netlink_init(struct net *net);
-void __net_exit ncsi_netlink_exit(struct net *net);
-void ncsi_netlink_reply(struct nlmsghdr *h,
-			unsigned int portid, bool timeout);
 #endif /* __NCSI_INTERNAL_H__ */
diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c
index b8503e1..28f297ac 100644
--- a/net/ncsi/ncsi-cmd.c
+++ b/net/ncsi/ncsi-cmd.c
@@ -307,14 +307,6 @@ static struct ncsi_req *ncsi_alloc_cmd_req(struct ncsi_cmd_arg *nca)
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_NCSI);
 
-	if (nca->nca_nlh) {
-		NCSI_CB(skb).nsp_valid = 1;
-		memcpy(&NCSI_CB(skb).nsp_nlh, nca->nca_nlh,
-		       nlmsg_total_size(sizeof(struct ncsi_msg)));
-	} else {
-		NCSI_CB(skb).nsp_valid = 0;
-	}
-
 	return nr;
 }
 
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index ef1de7f..1bb09eb 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -353,13 +353,6 @@ void ncsi_free_req(struct ncsi_req *nr, bool check, bool timeout)
 	nr->nr_used = false;
 	spin_unlock_irqrestore(&ndp->ndp_req_lock, flags);
 
-	/* If the NCSI command was sent because of netlink
-	 * messages, we need reply with the result or error.
-	 */
-	if (check && cmd && NCSI_CB(cmd).nsp_valid)
-		ncsi_netlink_reply(&NCSI_CB(cmd).nsp_nlh,
-				   NCSI_CB(cmd).nsp_portid, timeout);
-
 	if (check && cmd && atomic_dec_return(&ndp->ndp_pending_reqs) == 0)
 		schedule_work(&ndp->ndp_work);
 	/* Release command and response */
@@ -410,7 +403,6 @@ static void ncsi_dev_config(struct ncsi_dev_priv *ndp)
 	int ret;
 
 	nca.nca_ndp = ndp;
-	nca.nca_nlh = NULL;
 
 	/* When we're reconfiguring the active channel, the active package
 	 * should be selected and the old setting on the active channel
@@ -522,7 +514,6 @@ static void ncsi_dev_start(struct ncsi_dev_priv *ndp)
 	int ret;
 
 	nca.nca_ndp = ndp;
-	nca.nca_nlh = NULL;
 	switch (nd->nd_state) {
 	case ncsi_dev_state_start:
 		nd->nd_state = ncsi_dev_state_start_deselect;
@@ -696,7 +687,6 @@ static void ncsi_dev_suspend(struct ncsi_dev_priv *ndp)
 	int ret;
 
 	nca.nca_ndp = ndp;
-	nca.nca_nlh = NULL;
 	switch (nd->nd_state) {
 	case ncsi_dev_state_suspend:
 		/* If there're no active channel, we're done */
diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c
deleted file mode 100644
index bcabd39..0000000
--- a/net/ncsi/ncsi-netlink.c
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- * Copyright Gavin Shan, IBM Corporation 2015.
- *
- * 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/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/netlink.h>
-
-#include <net/ncsi.h>
-#include <net/net_namespace.h>
-#include <net/sock.h>
-
-#include "internal.h"
-#include "ncsi-pkt.h"
-
-static struct sock *ncsi_sock;
-
-static void ncsi_netlink_error(struct nlmsghdr *h,
-			       unsigned int portid,
-			       int errcode)
-{
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct ncsi_msg *src, *dst;
-	int ret;
-
-	skb = nlmsg_new(sizeof(*dst), GFP_ATOMIC);
-	if (!skb)
-		return;
-
-	/* The request might not have the common data instance */
-	nlh = nlmsg_put(skb, h->nlmsg_pid, h->nlmsg_seq,
-			h->nlmsg_type, sizeof(*dst), 0);
-	dst = nlmsg_data(nlh);
-	if (nlmsg_len(h) >= sizeof(*src)) {
-		src = nlmsg_data(h);
-		memcpy(dst, src, sizeof(*dst));
-		dst->nm_flag &= ~NCSI_FLAG_REQUEST;
-		dst->nm_flag |= NCSI_FLAG_RESPONSE;
-		dst->nm_errcode = errcode;
-	} else {
-		memset(dst, 0, sizeof(*dst));
-		dst->nm_flag = NCSI_FLAG_RESPONSE;
-		dst->nm_errcode = errcode;
-	}
-
-	nlmsg_end(skb, nlh);
-	ret = nlmsg_notify(ncsi_sock, skb, portid, 0, 1, 0);
-	if (ret) {
-		pr_warn("%s: Error %d sending message (%d)\n",
-			__func__, ret, errcode);
-		nlmsg_free(skb);
-	}
-}
-
-static struct sk_buff *ncsi_netlink_get_layout(struct nlmsghdr *h,
-					       int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct ncsi_msg nm, *src, *dst;
-	size_t size = sizeof(*dst);;
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	if (!ndp) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-
-	/* Allocate response */
-	NCSI_FOR_EACH_PACKAGE(ndp, np)
-		size += nla_total_size(sizeof(nm)) *
-			atomic_read(&np->np_channel_num);
-	if (size <= sizeof(nm)) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-	skb = nlmsg_new(size, GFP_KERNEL);
-	if (!skb) {
-		*errcode = NCSI_ERR_NO_MEM;
-		return NULL;
-	}
-
-	/* Fill header */
-	nlh = nlmsg_put(skb, h->nlmsg_pid, h->nlmsg_seq,
-			h->nlmsg_type, sizeof(nm), 0);
-	dst = nlmsg_data(nlh);
-	memcpy(dst, src, sizeof(*dst));
-	dst->nm_flag &= ~NCSI_FLAG_REQUEST;
-	dst->nm_flag |= NCSI_FLAG_RESPONSE;
-
-	/* All available channels */
-	NCSI_FOR_EACH_PACKAGE(ndp, np) {
-		NCSI_FOR_EACH_CHANNEL(np, nc) {
-			nm.nm_flag = 0;
-			if (nc == ndp->ndp_active_channel)
-				nm.nm_flag = NCSI_FLAG_ACTIVE_CHANNEL;
-			nm.nm_ifindex = src->nm_ifindex;
-			nm.nm_package_id = np->np_id;
-			nm.nm_channel_id = nc->nc_id;
-			nm.nm_index = 0;
-			nm.nm_index = NCSI_SUCCESS;
-
-			if (nla_put(skb, 0, sizeof(nm), &nm)) {
-				*errcode = NCSI_ERR_INTERNAL;
-				nlmsg_free(skb);
-				return NULL;
-			}
-		}
-	}
-
-	nlmsg_end(skb, nlh);
-	return skb;
-}
-
-static struct sk_buff *ncsi_netlink_get_version(struct nlmsghdr *h,
-						int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct ncsi_channel_version *ncv;
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct ncsi_msg *src, *dst;
-	size_t size = sizeof(*dst);;
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-
-	/* Allocate response */
-	size += nla_total_size(sizeof(*ncv));
-	skb = nlmsg_new(size, GFP_KERNEL);
-	if (!skb) {
-		*errcode = NCSI_ERR_NO_MEM;
-		return NULL;
-	}
-
-	/* Fill header */
-	nlh = nlmsg_put(skb, h->nlmsg_pid, h->nlmsg_seq,
-			h->nlmsg_type, sizeof(*dst), 0);
-	dst = nlmsg_data(nlh);
-	memcpy(dst, src, sizeof(*dst));
-	dst->nm_flag &= ~NCSI_FLAG_REQUEST;
-	dst->nm_flag |= NCSI_FLAG_RESPONSE;
-
-	/* Fill channel version */
-	ncv = &nc->nc_version;
-	if (nla_put(skb, 0, sizeof(*ncv), ncv)) {
-		*errcode = NCSI_ERR_INTERNAL;
-		nlmsg_free(skb);
-		return NULL;
-	}
-
-	nlmsg_end(skb, nlh);
-	return skb;
-}
-
-static struct sk_buff *ncsi_netlink_get_cap(struct nlmsghdr *h,
-					    int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct ncsi_channel_cap *ncc;
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct ncsi_msg *src, *dst;
-	size_t size = sizeof(*dst);
-	int index;
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-
-	/* Allocate response */
-	if (src->nm_index > NCSI_CAP_MAX) {
-		*errcode = NCSI_ERR_PARAM;
-		return NULL;
-	} else if (src->nm_index == NCSI_CAP_MAX) {
-		size += nla_total_size(sizeof(*ncc)) * NCSI_CAP_MAX;
-	} else {
-		size += nla_total_size(sizeof(*ncc));
-	}
-	skb = nlmsg_new(size, GFP_KERNEL);
-	if (!skb) {
-		*errcode = NCSI_ERR_NO_MEM;
-		return NULL;
-	}
-
-	/* Fill header */
-	nlh = nlmsg_put(skb, h->nlmsg_pid, h->nlmsg_seq,
-			h->nlmsg_type, sizeof(*dst), 0);
-	dst = nlmsg_data(nlh);
-	memcpy(dst, src, sizeof(*dst));
-	dst->nm_flag &= ~NCSI_FLAG_REQUEST;
-	dst->nm_flag |= NCSI_FLAG_RESPONSE;
-
-	/* Fill one or all capabilities */
-	for (index = 0; index < NCSI_CAP_MAX; index++) {
-		ncc = &nc->nc_caps[index];
-		if (src->nm_index == NCSI_CAP_MAX ||
-		    src->nm_index == index) {
-			if (nla_put(skb, 0, sizeof(*ncc), ncc)) {
-				*errcode = NCSI_ERR_INTERNAL;
-				nlmsg_free(skb);
-				return NULL;
-			}
-		}
-	}
-
-	nlmsg_end(skb, nlh);
-	return skb;
-}
-
-static struct sk_buff *ncsi_netlink_get_mode(struct nlmsghdr *h,
-					     int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct ncsi_cmd_arg nca;
-	struct ncsi_msg *src;
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-	if (nd->nd_state != ncsi_dev_state_functional ||
-	    ndp->ndp_active_channel != nc) {
-		*errcode = NCSI_ERR_NOT_ACTIVE;
-		return NULL;
-	}
-	if (src->nm_index > NCSI_MODE_MAX) {
-		*errcode = NCSI_ERR_PARAM;
-		return NULL;
-	}
-
-	/* Send NCSI GP command */
-	nca.nca_ndp = ndp;
-	nca.nca_nlh = h;
-	nca.nca_type = NCSI_PKT_CMD_GP;
-	nca.nca_package = np->np_id;
-	nca.nca_channel = nc->nc_id;
-	if (ncsi_xmit_cmd(&nca)) {
-		*errcode = NCSI_ERR_INTERNAL;
-		return NULL;
-	}
-
-	*errcode = NCSI_SUCCESS;
-	return NULL;
-}
-
-static struct sk_buff *ncsi_netlink_get_filter(struct nlmsghdr *h,
-					       int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct ncsi_cmd_arg nca;
-	struct ncsi_msg *src;
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-	if (nd->nd_state != ncsi_dev_state_functional ||
-	    ndp->ndp_active_channel != nc) {
-		*errcode = NCSI_ERR_NOT_ACTIVE;
-		return NULL;
-	}
-	if (src->nm_index > NCSI_FILTER_MAX) {
-		*errcode = NCSI_ERR_PARAM;
-		return NULL;
-	}
-
-	/* Send NCSI GP command */
-	nca.nca_ndp = ndp;
-	nca.nca_nlh = h;
-	nca.nca_type = NCSI_PKT_CMD_GP;
-	nca.nca_package = np->np_id;
-	nca.nca_channel = nc->nc_id;
-	if (ncsi_xmit_cmd(&nca)) {
-		*errcode = NCSI_ERR_INTERNAL;
-		return NULL;
-	}
-
-	*errcode = NCSI_SUCCESS;
-	return NULL;
-}
-
-struct sk_buff *ncsi_netlink_get_stats(struct nlmsghdr *h, int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct ncsi_msg *src;
-	struct ncsi_cmd_arg nca;
-	unsigned char cmd;
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-	if (nd->nd_state != ncsi_dev_state_functional ||
-	    ndp->ndp_active_channel != nc) {
-		*errcode = NCSI_ERR_NOT_ACTIVE;
-		return NULL;
-	}
-	if (src->nm_index > NCSI_FILTER_MAX) {
-		*errcode = NCSI_ERR_PARAM;
-		return NULL;
-	}
-
-	/* Get NIC statistics */
-	nca.nca_ndp = ndp;
-	nca.nca_nlh = NULL;
-	nca.nca_type = NCSI_PKT_CMD_GCPS;
-	nca.nca_package = np->np_id;
-	nca.nca_channel = nc->nc_id;
-	for (cmd = NCSI_PKT_CMD_GCPS; cmd <= NCSI_PKT_CMD_GNPTS; cmd++) {
-		nca.nca_type = cmd;
-		if (cmd == NCSI_PKT_CMD_GNPTS)
-			nca.nca_nlh = h;
-		if (ncsi_xmit_cmd(&nca)) {
-			*errcode = NCSI_ERR_INTERNAL;
-			return NULL;
-		}
-	}
-
-	*errcode = NCSI_SUCCESS;
-	return NULL;
-}
-
-struct sk_buff *ncsi_netlink_set_mode(struct nlmsghdr *h, int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct ncsi_channel_mode *ncm;
-	struct ncsi_msg *src;
-	struct nlattr *nla;
-	struct ncsi_cmd_arg nca;
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-	if (nd->nd_state != ncsi_dev_state_functional ||
-	    ndp->ndp_active_channel != nc) {
-		*errcode = NCSI_ERR_NOT_ACTIVE;
-		return NULL;
-	}
-
-	/* Get NIC statistics */
-	nla = nlmsg_attrdata(h, sizeof(*src));
-	ncm = nla_data(nla);
-
-	nca.nca_ndp = ndp;
-	nca.nca_nlh = h;
-	nca.nca_package = np->np_id;
-	nca.nca_channel = nc->nc_id;
-	switch (src->nm_index) {
-	case NCSI_MODE_ENABLE:
-		if (ncm->ncm_enable) {
-			nca.nca_type = NCSI_PKT_CMD_EC;
-		} else {
-			nca.nca_type = NCSI_PKT_CMD_DC;
-			nca.nca_bytes[0] = ncm->ncm_data[0];
-		}
-		break;
-	case NCSI_MODE_TX_ENABLE:
-		if (ncm->ncm_enable)
-			nca.nca_type = NCSI_PKT_CMD_ECNT;
-		else
-			nca.nca_type = NCSI_PKT_CMD_DCNT;
-		break;
-	case NCSI_MODE_LINK:
-		nca.nca_type = NCSI_PKT_CMD_SL;
-		nca.nca_dwords[0] = ncm->ncm_data[0];
-		nca.nca_dwords[1] = ncm->ncm_data[1];
-		break;
-	case NCSI_MODE_VLAN:
-		if (ncm->ncm_enable) {
-			nca.nca_type = NCSI_PKT_CMD_EV;
-			nca.nca_bytes[0] = ncm->ncm_data[0];
-		} else {
-			nca.nca_type = NCSI_PKT_CMD_DV;
-		}
-		break;
-	case NCSI_MODE_BC:
-		if (ncm->ncm_enable) {
-			nca.nca_type = NCSI_PKT_CMD_EBF;
-			nca.nca_dwords[0] = ncm->ncm_data[0];
-		} else {
-			nca.nca_type = NCSI_PKT_CMD_DBF;
-		}
-		break;
-	case NCSI_MODE_MC:
-		if (ncm->ncm_enable) {
-			nca.nca_type = NCSI_PKT_CMD_EGMF;
-			nca.nca_dwords[0] = ncm->ncm_data[0];
-		} else {
-			nca.nca_type = NCSI_PKT_CMD_DGMF;
-		}
-		break;
-	case NCSI_MODE_AEN:
-		nca.nca_type = NCSI_PKT_CMD_AE;
-		nca.nca_bytes[0] = ncm->ncm_data[0];
-		nca.nca_dwords[1] = ncm->ncm_data[1];
-		break;
-	case NCSI_MODE_FC:
-		nca.nca_type = NCSI_PKT_CMD_SNFC;
-		nca.nca_bytes[0] = ncm->ncm_data[0];
-		break;
-	default:
-		*errcode = NCSI_ERR_PARAM;
-		return NULL;
-	}
-
-	if (ncsi_xmit_cmd(&nca)) {
-		*errcode = NCSI_ERR_INTERNAL;
-		return NULL;
-	}
-
-	*errcode = NCSI_SUCCESS;
-	return NULL;
-}
-
-struct sk_buff *ncsi_netlink_set_filter(struct nlmsghdr *h, int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct ncsi_channel_filter *ncf;
-	struct ncsi_msg *src;
-	struct nlattr *nla;
-	struct ncsi_cmd_arg nca;
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-	if (nd->nd_state != ncsi_dev_state_functional ||
-	    ndp->ndp_active_channel != nc) {
-		*errcode = NCSI_ERR_NOT_ACTIVE;
-		return NULL;
-	}
-
-	/* Get NIC statistics */
-	nla = nlmsg_attrdata(h, sizeof(*src));
-	ncf = nla_data(nla);
-
-	nca.nca_ndp = ndp;
-	nca.nca_nlh = h;
-	nca.nca_package = np->np_id;
-	nca.nca_channel = nc->nc_id;
-	switch (src->nm_index) {
-	case NCSI_FILTER_VLAN:
-		nca.nca_type = NCSI_PKT_CMD_SVF;
-		memcpy(nca.nca_bytes, ncf->ncf_data, 4);
-		break;
-	case NCSI_FILTER_UC:
-	case NCSI_FILTER_MC:
-		memcpy(nca.nca_bytes, ncf->ncf_data, 8);
-		nca.nca_bytes[7] &= 0x1f;
-		if (src->nm_index == NCSI_FILTER_MC)
-			nca.nca_bytes[7] |= 0x20;
-		break;
-	default:
-		*errcode = NCSI_ERR_PARAM;
-		return NULL;
-	}
-
-	if (ncsi_xmit_cmd(&nca)) {
-		*errcode = NCSI_ERR_INTERNAL;
-		return NULL;
-	}
-
-	*errcode = NCSI_SUCCESS;
-	return NULL;
-}
-
-static struct sk_buff *ncsi_netlink_get_mode_reply(struct nlmsghdr *h,
-						   int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct ncsi_channel_mode *ncm;
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct ncsi_msg *src, *dst;
-	size_t size = sizeof(*dst);
-	int index;
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-
-	/* Allocate response */
-	if (src->nm_index > NCSI_MODE_MAX) {
-		*errcode = NCSI_ERR_PARAM;
-		return NULL;
-	} else if (src->nm_index == NCSI_MODE_MAX) {
-		size += nla_total_size(sizeof(*ncm)) * NCSI_MODE_MAX;
-	} else {
-		size += nla_total_size(sizeof(*ncm));
-	}
-	skb = nlmsg_new(size, GFP_ATOMIC);
-	if (!skb) {
-		*errcode = NCSI_ERR_NO_MEM;
-		return NULL;
-	}
-
-	/* Fill header */
-	nlh = nlmsg_put(skb, h->nlmsg_pid, h->nlmsg_seq,
-			h->nlmsg_type, sizeof(*dst), 0);
-	dst = nlmsg_data(nlh);
-	memcpy(dst, src, sizeof(*dst));
-	dst->nm_flag &= ~NCSI_FLAG_REQUEST;
-	dst->nm_flag |= NCSI_FLAG_RESPONSE;
-
-	/* Fill one or all modes */
-	for (index = 0; index < NCSI_MODE_MAX; index++) {
-		ncm = &nc->nc_modes[index];
-		if (src->nm_index == NCSI_MODE_MAX ||
-		    src->nm_index == index) {
-			if (nla_put(skb, 0, sizeof(*ncm), ncm)) {
-				*errcode = NCSI_ERR_INTERNAL;
-				nlmsg_free(skb);
-				return NULL;
-			}
-		}
-	}
-
-	nlmsg_end(skb, nlh);
-	return skb;
-}
-
-static struct sk_buff *ncsi_netlink_get_filter_reply(struct nlmsghdr *h,
-						     int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct ncsi_channel_filter *ncf;
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct ncsi_msg *src, *dst;
-	size_t entry_size, size = sizeof(*dst);
-	int index;
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-
-	/* Allocate response */
-	if (src->nm_index > NCSI_FILTER_MAX) {
-		*errcode = NCSI_ERR_PARAM;
-		return NULL;
-	}
-
-	for (index = 0; index < NCSI_FILTER_MAX; index++) {
-		ncf = nc->nc_filters[index];
-		switch (index) {
-		case NCSI_FILTER_VLAN:
-			entry_size = 2;
-			break;
-		case NCSI_FILTER_UC:
-		case NCSI_FILTER_MC:
-		case NCSI_FILTER_MIXED:
-			entry_size = 6;
-			break;
-		default:
-			continue;
-		}
-
-		if (src->nm_index == NCSI_FILTER_MAX ||
-		    src->nm_index == index) {
-			if (!ncf)
-				continue;
-
-			size += nla_total_size(sizeof(*ncf) +
-					       entry_size * ncf->ncf_total);
-		}
-	}
-
-	skb = nlmsg_new(size, GFP_ATOMIC);
-	if (!skb) {
-		*errcode = NCSI_ERR_NO_MEM;
-		return NULL;
-	}
-
-	/* Fill header */
-	nlh = nlmsg_put(skb, h->nlmsg_pid, h->nlmsg_seq,
-			h->nlmsg_type, sizeof(*dst), 0);
-	dst = nlmsg_data(nlh);
-	memcpy(dst, src, sizeof(*dst));
-	dst->nm_flag &= ~NCSI_FLAG_REQUEST;
-	dst->nm_flag |= NCSI_FLAG_RESPONSE;
-
-	/* Fill one or all filters */
-	for (index = 0; index < NCSI_FILTER_MAX; index++) {
-		ncf = nc->nc_filters[index];
-		switch (index) {
-		case NCSI_FILTER_VLAN:
-			entry_size = 2;
-			break;
-		case NCSI_FILTER_UC:
-		case NCSI_FILTER_MC:
-		case NCSI_FILTER_MIXED:
-			entry_size = 6;
-			break;
-		default:
-			continue;
-		}
-
-		if (src->nm_index == NCSI_FILTER_MAX ||
-		    src->nm_index == index) {
-			if (!ncf)
-				continue;
-
-			size = sizeof(*ncf) + entry_size * ncf->ncf_total;
-			if (nla_put(skb, 0, size, ncf)) {
-				nlmsg_free(skb);
-				*errcode = NCSI_ERR_INTERNAL;
-				return NULL;
-			}
-		}
-	}
-
-	nlmsg_end(skb, nlh);
-	return skb;
-}
-
-struct sk_buff *ncsi_netlink_get_stats_reply(struct nlmsghdr *h, int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct ncsi_channel_stats *ncs;
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct ncsi_msg *src, *dst;
-	size_t size = sizeof(*dst);
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-
-	/* Allocate response */
-	size += nla_total_size(sizeof(*ncs));
-	skb = nlmsg_new(size, GFP_ATOMIC);
-	if (!skb) {
-		*errcode = NCSI_ERR_NO_MEM;
-		return NULL;
-	}
-
-	/* Fill header */
-	nlh = nlmsg_put(skb, h->nlmsg_pid, h->nlmsg_seq,
-			h->nlmsg_type, sizeof(*dst), 0);
-	dst = nlmsg_data(nlh);
-	memcpy(dst, src, sizeof(*dst));
-	dst->nm_flag &= ~NCSI_FLAG_REQUEST;
-	dst->nm_flag |= NCSI_FLAG_RESPONSE;
-
-	/* Fill one or all filters */
-	ncs = &nc->nc_stats;
-	if (nla_put(skb, 0, sizeof(*ncs), ncs)) {
-		nlmsg_free(skb);
-		*errcode = NCSI_ERR_INTERNAL;
-		return NULL;
-	}
-
-	nlmsg_end(skb, nlh);
-	return skb;
-}
-
-struct sk_buff *ncsi_netlink_set_mode_reply(struct nlmsghdr *h, int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct nlattr *nla;
-	struct ncsi_msg *src, *dst;
-	struct ncsi_channel_mode *ncm;
-	size_t size = sizeof(*dst);
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-
-	/* Allocate response */
-	size += nla_total_size(sizeof(*ncm));
-	skb = nlmsg_new(size, GFP_ATOMIC);
-	if (!skb) {
-		*errcode = NCSI_ERR_NO_MEM;
-		return NULL;
-	}
-
-	/* Fill header */
-	nlh = nlmsg_put(skb, h->nlmsg_pid, h->nlmsg_seq,
-			h->nlmsg_type, sizeof(*dst), 0);
-	dst = nlmsg_data(nlh);
-	memcpy(dst, src, sizeof(*dst));
-	dst->nm_flag &= ~NCSI_FLAG_REQUEST;
-	dst->nm_flag |= NCSI_FLAG_RESPONSE;
-
-	/* Fill one or all filters */
-	nla = nlmsg_attrdata(h, sizeof(*dst));
-	ncm = nla_data(nla);
-	if (nla_put(skb, 0, sizeof(*ncm), ncm)) {
-		*errcode = NCSI_ERR_INTERNAL;
-		return NULL;
-	}
-
-	nlmsg_end(skb, nlh);
-	return skb;
-}
-
-struct sk_buff *ncsi_netlink_set_filter_reply(struct nlmsghdr *h, int *errcode)
-{
-	struct net_device *dev;
-	struct ncsi_dev *nd;
-	struct ncsi_dev_priv *ndp;
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct nlattr *nla;
-	struct ncsi_msg *src, *dst;
-	struct ncsi_channel_filter *ncf;
-	size_t extra, size = sizeof(*dst);
-
-	/* Find the NCSI device */
-	src = nlmsg_data(h);
-	dev = dev_get_by_index(ncsi_net, src->nm_ifindex);
-	nd = dev ? ncsi_find_dev(dev) : NULL;
-	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
-	np = ndp ? ncsi_find_package(ndp, src->nm_package_id) : NULL;
-	nc = np ? ncsi_find_channel(np, src->nm_channel_id) : NULL;
-	if (!nc) {
-		*errcode = NCSI_ERR_NO_DEV;
-		return NULL;
-	}
-
-	/* Allocate response */
-	size += nla_total_size(sizeof(*ncf) + 16);
-	skb = nlmsg_new(size, GFP_ATOMIC);
-	if (!skb) {
-		*errcode = NCSI_ERR_NO_MEM;
-		return NULL;
-	}
-
-	/* Fill header */
-	nlh = nlmsg_put(skb, h->nlmsg_pid, h->nlmsg_seq,
-			h->nlmsg_type, sizeof(*dst), 0);
-	dst = nlmsg_data(nlh);
-	memcpy(dst, src, sizeof(*dst));
-	dst->nm_flag &= ~NCSI_FLAG_REQUEST;
-	dst->nm_flag |= NCSI_FLAG_RESPONSE;
-
-	/* Fill one or all filters */
-	nla = nlmsg_attrdata(h, sizeof(*dst));
-	ncf = nla_data(nla);
-	switch(src->nm_index) {
-	case NCSI_FILTER_VLAN:
-		extra = 2;
-		break;
-	case NCSI_FILTER_UC:
-	case NCSI_FILTER_MC:
-		extra = 6;
-		break;
-	default:
-		nlmsg_free(skb);
-		*errcode = NCSI_ERR_PARAM;
-		return NULL;
-	}
-
-	if (nla_put(skb, 0, sizeof(*ncf) + extra, ncf)) {
-		*errcode = NCSI_ERR_INTERNAL;
-		return NULL;
-	}
-
-	nlmsg_end(skb, nlh);
-	return skb;
-}
-
-void ncsi_netlink_reply(struct nlmsghdr *h, unsigned int portid, bool timeout)
-{
-	struct sk_buff *skb;
-	int errcode = NCSI_SUCCESS;
-	struct sk_buff *(*func)(struct nlmsghdr *, int *) = NULL;
-
-	if (timeout) {
-		ncsi_netlink_error(h, portid, NCSI_ERR_INTERNAL);
-		return;
-	}
-
-	switch (h->nlmsg_type) {
-	case NCSI_MSG_GET_MODE:
-		func = ncsi_netlink_get_mode_reply;
-		break;
-	case NCSI_MSG_GET_FILTER:
-		func = ncsi_netlink_get_filter_reply;
-		break;
-	case NCSI_MSG_GET_STATS:
-		func = ncsi_netlink_get_stats_reply;
-		break;
-	case NCSI_MSG_SET_MODE:
-		func = ncsi_netlink_set_mode_reply;
-		break;
-	case NCSI_MSG_SET_FILTER:
-		func = ncsi_netlink_set_filter_reply;
-		break;
-	default:
-		errcode = NCSI_ERR_PARAM;
-		goto out;
-	}
-
-	skb = func(h, &errcode);
-	if (!skb)
-		goto out;
-
-	nlmsg_notify(ncsi_sock, skb, portid, 0, 0, GFP_ATOMIC);
-	return;
-out:
-	ncsi_netlink_error(h, portid, errcode);
-}
-
-static int ncsi_netlink_rcv_msg(struct sk_buff *cmd, struct nlmsghdr *h)
-{
-	struct ncsi_msg *nm;
-	struct sk_buff *skb;
-	int errcode = NCSI_SUCCESS;
-	unsigned int portid = NETLINK_CB(cmd).portid;
-	struct sk_buff *(*func)(struct nlmsghdr *, int *) = NULL;
-
-	if (h->nlmsg_type >= NCSI_MSG_MAX ||
-	    nlmsg_len(h) < sizeof(*nm)) {
-		errcode = NCSI_ERR_PARAM;
-		goto out;
-	}
-
-	nm = nlmsg_data(h);
-	if (!(nm->nm_flag & NCSI_FLAG_REQUEST)) {
-		errcode = NCSI_ERR_PARAM;
-		goto out;
-	}
-
-	switch (h->nlmsg_type) {
-	case NCSI_MSG_GET_LAYOUT:
-		func = ncsi_netlink_get_layout;
-		break;
-	case NCSI_MSG_GET_VERSION:
-		func = ncsi_netlink_get_version;
-		break;
-	case NCSI_MSG_GET_CAP:
-		func = ncsi_netlink_get_cap;
-		break;
-	case NCSI_MSG_GET_MODE:
-		func = ncsi_netlink_get_mode;
-		break;
-	case NCSI_MSG_GET_FILTER:
-		func = ncsi_netlink_get_filter;
-		break;
-	case NCSI_MSG_GET_STATS:
-		func = ncsi_netlink_get_stats;
-		break;
-	case NCSI_MSG_SET_MODE:
-		func = ncsi_netlink_set_mode;
-		break;
-	case NCSI_MSG_SET_FILTER:
-		func = ncsi_netlink_set_filter;
-		break;
-	default:
-		goto out;
-	}
-
-	skb = func(h, &errcode);
-	if (errcode != NCSI_SUCCESS)
-		goto out;
-
-	/* Split transactions */
-	if (!skb)
-		return 0;
-
-	return nlmsg_notify(ncsi_sock, skb, portid, 0, 0, GFP_KERNEL);
-out:
-	ncsi_netlink_error(h, portid, errcode);
-	return -EINTR;
-}
-
-static void ncsi_netlink_rcv(struct sk_buff *skb)
-{
-	netlink_rcv_skb(skb, &ncsi_netlink_rcv_msg);
-}
-
-int __net_init ncsi_netlink_init(struct net *net)
-{
-	struct netlink_kernel_cfg cfg = {
-		.groups   = 0,
-		.flags    = NL_CFG_F_NONROOT_RECV |
-			    NL_CFG_F_NONROOT_SEND,
-		.input    = ncsi_netlink_rcv,
-	};
-
-	ncsi_sock = netlink_kernel_create(net, NETLINK_NCSI, &cfg);
-	return ncsi_sock ? 0 : -ENOMEM;
-}
-
-void __net_exit ncsi_netlink_exit(struct net *net)
-{
-	netlink_kernel_release(ncsi_sock);
-	ncsi_sock = NULL;
-}
diff --git a/net/ncsi/ncsi.c b/net/ncsi/ncsi.c
deleted file mode 100644
index c84939e..0000000
--- a/net/ncsi/ncsi.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright Gavin Shan, IBM Corporation 2015.
- *
- * 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/netdevice.h>
-#include <linux/skbuff.h>
-
-#include <net/ncsi.h>
-#include <net/net_namespace.h>
-#include <net/sock.h>
-
-#include "internal.h"
-
-struct net *ncsi_net = NULL;
-
-static int __net_init ncsi_net_init(struct net *net)
-{
-	ncsi_net = net;
-	return ncsi_netlink_init(net);
-}
-
-static void __net_exit ncsi_net_exit(struct net *net)
-{
-	ncsi_netlink_exit(net);
-	ncsi_net = NULL;
-}
-
-static struct pernet_operations ncsi_net_ops = {
-	.init = ncsi_net_init,
-	.exit = ncsi_net_exit,
-};
-
-static int __init ncsi_init(void)
-{
-	if (ncsi_net)
-		return -EEXIST;
-
-	return register_pernet_subsys(&ncsi_net_ops);
-}
-
-fs_initcall_sync(ncsi_init);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/8] net/ncsi: Add NCSI_DEV_PRIV_FLAG_POPULATED
  2016-05-09  1:47 [PATCH 0/8] NSCI Improvement Gavin Shan
  2016-05-09  1:47 ` [PATCH 1/8] net/ncsi: Remove netlink support Gavin Shan
@ 2016-05-09  1:47 ` Gavin Shan
  2016-05-09  1:47 ` [PATCH 3/8] net/ncsi: Enumerate NCSI channels in advance Gavin Shan
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-09  1:47 UTC (permalink / raw)
  To: openbmc; +Cc: Gavin Shan

This adds another flag (NCSI_DEV_PRIV_FLAG_POPULATED) to ncsi priv
struct. When it's set, the all available packages and channels
associated with the interface have been enumerated. The flag is
going to be used by next patch. No functional changes introduced.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 net/ncsi/internal.h | 3 ++-
 net/ncsi/ncsi-rsp.c | 7 +++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index ac5f129..51b43f5 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -77,7 +77,8 @@ enum {
 struct ncsi_dev_priv {
 	struct ncsi_dev		ndp_ndev;
 	int			ndp_flags;
-#define NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE	0x1
+#define NCSI_DEV_PRIV_FLAG_POPULATED		0x1
+#define NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE	0x2
 	struct ncsi_package	*ndp_active_package;
 	struct ncsi_channel	*ndp_active_channel;
 	atomic_t		ndp_package_num;
diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
index 295f0f8..c34998d 100644
--- a/net/ncsi/ncsi-rsp.c
+++ b/net/ncsi/ncsi-rsp.c
@@ -88,8 +88,8 @@ static int ncsi_rsp_handler_cis(struct ncsi_req *nr)
 
 	rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->nr_rsp);
 	ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel, &np, &nc);
-	if (!np)
-		return -ENODEV;
+	if ((ndp->ndp_flags & NCSI_DEV_PRIV_FLAG_POPULATED) && !nc)
+		return -ENXIO;
 
 	/* Add the channel if necessary */
 	if (!nc)
@@ -122,6 +122,9 @@ static int ncsi_rsp_handler_sp(struct ncsi_req *nr)
 	rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->nr_rsp);
 	ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 				      &np, NULL);
+	if ((ndp->ndp_flags & NCSI_DEV_PRIV_FLAG_POPULATED) && !np)
+		return -ENXIO;
+
 	if (!np) {
 		np = ncsi_add_package(ndp,
 			NCSI_PACKAGE_INDEX(rsp->rsp.common.channel));
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/8] net/ncsi: Enumerate NCSI channels in advance
  2016-05-09  1:47 [PATCH 0/8] NSCI Improvement Gavin Shan
  2016-05-09  1:47 ` [PATCH 1/8] net/ncsi: Remove netlink support Gavin Shan
  2016-05-09  1:47 ` [PATCH 2/8] net/ncsi: Add NCSI_DEV_PRIV_FLAG_POPULATED Gavin Shan
@ 2016-05-09  1:47 ` Gavin Shan
  2016-05-09  1:47 ` [PATCH 4/8] net/ncsi: Remove ncsi_stop_dev() Gavin Shan
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-09  1:47 UTC (permalink / raw)
  To: openbmc; +Cc: Gavin Shan

All NCSI packages and channels are enumerated when user brings up
the interface. The enumeration is heavy task and consumes lots of
time. We can just do it for once when considering the fact: NCSI
physical topology won't change.

This enumerates NCSI packages and channels when user activates the
interface for the first time, meaing the procedure won't be revisited
when user reactivates the interface. The time consumed by it will
be saved and the response time is improved. In order for it, we
replace ncsi_dev_config() with ncsi_dev_probe() that is triggered
on first call to ncsi_start_dev(). Similarly, the NCSI packages and
channels are not released in ncsi_stop_dev() which is triggered when
the interface is closed. It means the release is postponed until the
interface is unregistered.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 include/net/ncsi.h     |   4 +-
 net/ncsi/internal.h    |  17 +++--
 net/ncsi/ncsi-manage.c | 190 ++++++++++++++++++++++++-------------------------
 3 files changed, 105 insertions(+), 106 deletions(-)

diff --git a/include/net/ncsi.h b/include/net/ncsi.h
index dd07b76..bf70b8d 100644
--- a/include/net/ncsi.h
+++ b/include/net/ncsi.h
@@ -17,9 +17,9 @@
 enum {
 	ncsi_dev_state_registered	= 0x0000,
 	ncsi_dev_state_functional	= 0x0100,
-	ncsi_dev_state_start		= 0x0200,
+	ncsi_dev_state_probe		= 0x0200,
 	ncsi_dev_state_config		= 0x0300,
-	ncsi_dev_state_suspend		= 0x0400
+	ncsi_dev_state_suspend		= 0x0400,
 };
 
 struct ncsi_dev {
diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index 51b43f5..cc37d9b 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -50,15 +50,14 @@ struct ncsi_req {
 enum {
 	ncsi_dev_state_major		= 0xff00,
 	ncsi_dev_state_minor		= 0x00ff,
-	ncsi_dev_state_start_deselect	= 0x0201,
-	ncsi_dev_state_start_package,
-	ncsi_dev_state_start_channel,
-	ncsi_dev_state_start_sp,
-	ncsi_dev_state_start_cis,
-	ncsi_dev_state_start_gvi,
-	ncsi_dev_state_start_gc,
-	ncsi_dev_state_start_dp,
-	ncsi_dev_state_start_active,
+	ncsi_dev_state_probe_deselect	= 0x0201,
+	ncsi_dev_state_probe_package,
+	ncsi_dev_state_probe_channel,
+	ncsi_dev_state_probe_cis,
+	ncsi_dev_state_probe_gvi,
+	ncsi_dev_state_probe_gc,
+	ncsi_dev_state_probe_gls,
+	ncsi_dev_state_probe_dp,
 	ncsi_dev_state_config_sp	= 0x0301,
 	ncsi_dev_state_config_cis,
 	ncsi_dev_state_config_sma,
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 1bb09eb..c32a919 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -372,26 +372,6 @@ struct ncsi_dev *ncsi_find_dev(struct net_device *dev)
 	return NULL;
 }
 
-static int ncsi_select_active_channel(struct ncsi_dev_priv *ndp)
-{
-	struct ncsi_package *np;
-	struct ncsi_channel *nc;
-
-	/* For now, we simply choose the first valid channel as active one.
-	 * There might be more factors, like the channel's capacity, can
-	 * be considered to pick the active channel in future.
-	 */
-	NCSI_FOR_EACH_PACKAGE(ndp, np) {
-		NCSI_FOR_EACH_CHANNEL(np, nc) {
-			ndp->ndp_active_package = np;
-			ndp->ndp_active_channel = nc;
-			return 0;
-		}
-	}
-
-	return -ENXIO;
-}
-
 static void ncsi_dev_config(struct ncsi_dev_priv *ndp)
 {
 	struct ncsi_dev *nd = &ndp->ndp_ndev;
@@ -504,7 +484,28 @@ error:
 	nd->nd_handler(nd);
 }
 
-static void ncsi_dev_start(struct ncsi_dev_priv *ndp)
+static void ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
+{
+	struct ncsi_package *np;
+	struct ncsi_channel *nc;
+	struct ncsi_channel_mode *ncm;
+
+	ndp->ndp_active_package = NULL;
+	ndp->ndp_active_channel = NULL;
+	NCSI_FOR_EACH_PACKAGE(ndp, np) {
+		NCSI_FOR_EACH_CHANNEL(np, nc) {
+			ncm = &nc->nc_modes[NCSI_MODE_LINK];
+			if (ndp->ndp_active_channel ||
+			    !(ncm->ncm_data[2] & 0x1))
+				continue;
+
+			ndp->ndp_active_package = np;
+			ndp->ndp_active_channel = nc;
+		}
+	}
+}
+
+static void ncsi_dev_probe(struct ncsi_dev_priv *ndp)
 {
 	struct ncsi_dev *nd = &ndp->ndp_ndev;
 	struct ncsi_package *np;
@@ -515,10 +516,10 @@ static void ncsi_dev_start(struct ncsi_dev_priv *ndp)
 
 	nca.nca_ndp = ndp;
 	switch (nd->nd_state) {
-	case ncsi_dev_state_start:
-		nd->nd_state = ncsi_dev_state_start_deselect;
+	case ncsi_dev_state_probe:
+		nd->nd_state = ncsi_dev_state_probe_deselect;
 		/* Fall through */
-	case ncsi_dev_state_start_deselect:
+	case ncsi_dev_state_probe_deselect:
 		atomic_set(&ndp->ndp_pending_reqs, 8);
 
 		/* Deselect all possible packages */
@@ -531,9 +532,9 @@ static void ncsi_dev_start(struct ncsi_dev_priv *ndp)
 				goto error;
 		}
 
-		nd->nd_state = ncsi_dev_state_start_package;
+		nd->nd_state = ncsi_dev_state_probe_package;
 		break;
-	case ncsi_dev_state_start_package:
+	case ncsi_dev_state_probe_package:
 		atomic_set(&ndp->ndp_pending_reqs, 16);
 
 		/* Select all possible packages */
@@ -556,34 +557,45 @@ static void ncsi_dev_start(struct ncsi_dev_priv *ndp)
 				goto error;
 		}
 
-		nd->nd_state = ncsi_dev_state_start_channel;
+		nd->nd_state = ncsi_dev_state_probe_channel;
 		break;
-	case ncsi_dev_state_start_channel:
-		/* The available packages should have been detected. To
-		 * iterate every package to probe its channels.
+	case ncsi_dev_state_probe_channel:
+		if (!ndp->ndp_active_package)
+			ndp->ndp_active_package = list_first_or_null_rcu(
+							&ndp->ndp_packages,
+							struct ncsi_package,
+							np_node);
+		else if (list_is_last(&ndp->ndp_active_package->np_node,
+				      &ndp->ndp_packages))
+			ndp->ndp_active_package = NULL;
+		else
+			ndp->ndp_active_package = list_next_entry(
+							ndp->ndp_active_package,
+							np_node);
+
+		/*
+		 * All available packages and channels are enumerated. The
+		 * enumeration happens for once when the NCSI interface is
+		 * started. So we need continue to start the interface after
+		 * the enumeration.
+		 *
+		 * We have to choose an active channel before configuring it.
+		 * Note that we possibly don't have active channel in extreme
+		 * situation.
 		 */
 		if (!ndp->ndp_active_package) {
-			ndp->ndp_active_package = list_first_or_null_rcu(
-				&ndp->ndp_packages, struct ncsi_package,
-				np_node);
-			if (!ndp->ndp_active_package)
+			ndp->ndp_flags |= NCSI_DEV_PRIV_FLAG_POPULATED;
+
+			ncsi_choose_active_channel(ndp);
+			if (!ndp->ndp_active_channel)
 				goto error;
-		} else {
-			if (list_is_last(&ndp->ndp_active_package->np_node,
-					 &ndp->ndp_packages)) {
-				nd->nd_state = ncsi_dev_state_start_active;
-				goto choose_active_channel;
-			}
-
-			ndp->ndp_active_package = list_entry_rcu(
-				ndp->ndp_active_package->np_node.next,
-				struct ncsi_package, np_node);
+
+			nd->nd_state = ncsi_dev_state_config;
+			return ncsi_dev_config(ndp);
 		}
-		/* Fall through */
-	case ncsi_dev_state_start_sp:
-		atomic_set(&ndp->ndp_pending_reqs, 1);
 
-		/* Select the specific package */
+		/* Select the active package */
+		atomic_set(&ndp->ndp_pending_reqs, 1);
 		nca.nca_type = NCSI_PKT_CMD_SP;
 		nca.nca_bytes[0] = 1;
 		nca.nca_package = ndp->ndp_active_package->np_id;
@@ -592,9 +604,9 @@ static void ncsi_dev_start(struct ncsi_dev_priv *ndp)
 		if (ret)
 			goto error;
 
-		nd->nd_state = ncsi_dev_state_start_cis;
+		nd->nd_state = ncsi_dev_state_probe_cis;
 		break;
-	case ncsi_dev_state_start_cis:
+	case ncsi_dev_state_probe_cis:
 		atomic_set(&ndp->ndp_pending_reqs, 0x20);
 
 		/* Clear initial state */
@@ -607,22 +619,22 @@ static void ncsi_dev_start(struct ncsi_dev_priv *ndp)
 				goto error;
 		}
 
-		nd->nd_state = ncsi_dev_state_start_gvi;
+		nd->nd_state = ncsi_dev_state_probe_gvi;
 		break;
-	case ncsi_dev_state_start_gvi:
-	case ncsi_dev_state_start_gc:
-		/* The available channels of the active package should have
-		 * been populated.
-		 */
+	case ncsi_dev_state_probe_gvi:
+	case ncsi_dev_state_probe_gc:
+	case ncsi_dev_state_probe_gls:
 		np = ndp->ndp_active_package;
 		atomic_set(&ndp->ndp_pending_reqs,
 			   atomic_read(&np->np_channel_num));
 
 		/* Get version information or get capacity */
-		if (nd->nd_state == ncsi_dev_state_start_gvi)
+		if (nd->nd_state == ncsi_dev_state_probe_gvi)
 			nca.nca_type = NCSI_PKT_CMD_GVI;
-		else
+		else if (nd->nd_state == ncsi_dev_state_probe_gc)
 			nca.nca_type = NCSI_PKT_CMD_GC;
+		else
+			nca.nca_type = NCSI_PKT_CMD_GLS;
 
 		nca.nca_package = np->np_id;
 		NCSI_FOR_EACH_CHANNEL(np, nc) {
@@ -632,12 +644,14 @@ static void ncsi_dev_start(struct ncsi_dev_priv *ndp)
 				goto error;
 		}
 
-		if (nd->nd_state == ncsi_dev_state_start_gvi)
-			nd->nd_state = ncsi_dev_state_start_gc;
+		if (nd->nd_state == ncsi_dev_state_probe_gvi)
+			nd->nd_state = ncsi_dev_state_probe_gc;
+		else if (nd->nd_state == ncsi_dev_state_probe_gc)
+			nd->nd_state = ncsi_dev_state_probe_gls;
 		else
-			nd->nd_state = ncsi_dev_state_start_dp;
+			nd->nd_state = ncsi_dev_state_probe_dp;
 		break;
-	case ncsi_dev_state_start_dp:
+	case ncsi_dev_state_probe_dp:
 		atomic_set(&ndp->ndp_pending_reqs, 1);
 
 		/* Deselect the active package */
@@ -648,31 +662,16 @@ static void ncsi_dev_start(struct ncsi_dev_priv *ndp)
 		if (ret)
 			goto error;
 
-		nd->nd_state = ncsi_dev_state_start_channel;
+		/* Scan channels in next package */
+		nd->nd_state = ncsi_dev_state_probe_channel;
 		break;
-	case ncsi_dev_state_start_active:
-choose_active_channel:
-		/* All packages and channels should have been populated. Also,
-		 * the information for all channels should have been retrieved.
-		 */
-		ndp->ndp_active_package = NULL;
-		ncsi_select_active_channel(ndp);
-		if (!ndp->ndp_active_package ||
-		    !ndp->ndp_active_channel)
-			goto error;
-
-		/* To configure the active channel */
-		nd->nd_state = ncsi_dev_state_config_sma;
-		ncsi_dev_config(ndp);
 	default:
-		pr_debug("%s: Unrecognized NCSI dev state 0x%x\n",
-			 __func__, nd->nd_state);
+		pr_warn("%s: Unrecognized NCSI dev state 0x%x\n",
+			__func__, nd->nd_state);
 	}
 
 	return;
-
 error:
-	ndp->ndp_flags &= ~NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE;
 	nd->nd_state = ncsi_dev_state_functional;
 	nd->nd_link_up = 0;
 	nd->nd_handler(nd);
@@ -745,8 +744,8 @@ done:
 			nd->nd_link_up = 0;
 			nd->nd_handler(nd);
 		} else {
-			nd->nd_state = ncsi_dev_state_start;
-			ncsi_dev_start(ndp);
+			nd->nd_state = ncsi_dev_state_config;
+			ncsi_dev_config(ndp);
 		}
 
 		break;
@@ -763,8 +762,8 @@ static void ncsi_dev_work(struct work_struct *work)
 	struct ncsi_dev *nd = &ndp->ndp_ndev;
 
 	switch (nd->nd_state & ncsi_dev_state_major) {
-	case ncsi_dev_state_start:
-		ncsi_dev_start(ndp);
+	case ncsi_dev_state_probe:
+		ncsi_dev_probe(ndp);
 		break;
 	case ncsi_dev_state_suspend:
 		ncsi_dev_suspend(ndp);
@@ -858,10 +857,18 @@ int ncsi_start_dev(struct ncsi_dev *nd)
 	    nd->nd_state != ncsi_dev_state_functional)
 		return -ENOTTY;
 
-	nd->nd_state = ncsi_dev_state_start;
-	schedule_work(&ndp->ndp_work);
+	if (!(ndp->ndp_flags & NCSI_DEV_PRIV_FLAG_POPULATED)) {
+		nd->nd_state = ncsi_dev_state_probe;
+		schedule_work(&ndp->ndp_work);
+		return 0;
+	}
 
-	return 0;
+	/* Choose active package and channel */
+	ncsi_choose_active_channel(ndp);
+	if (!ndp->ndp_active_channel)
+		return -ENXIO;
+
+	return ncsi_config_dev(nd);
 }
 EXPORT_SYMBOL_GPL(ncsi_start_dev);
 
@@ -894,13 +901,6 @@ EXPORT_SYMBOL_GPL(ncsi_suspend_dev);
 
 void ncsi_stop_dev(struct ncsi_dev *nd)
 {
-	struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
-	struct ncsi_package *tmp, *np;
-
-	spin_lock_bh(&ndp->ndp_package_lock);
-	list_for_each_entry_safe(np, tmp, &ndp->ndp_packages, np_node)
-		ncsi_release_package(np);
-	spin_unlock_bh(&ndp->ndp_package_lock);
 }
 EXPORT_SYMBOL_GPL(ncsi_stop_dev);
 
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/8] net/ncsi: Remove ncsi_stop_dev()
  2016-05-09  1:47 [PATCH 0/8] NSCI Improvement Gavin Shan
                   ` (2 preceding siblings ...)
  2016-05-09  1:47 ` [PATCH 3/8] net/ncsi: Enumerate NCSI channels in advance Gavin Shan
@ 2016-05-09  1:47 ` Gavin Shan
  2016-05-09  1:47 ` [PATCH 5/8] net/ncsi: Enable AEN on active channel Gavin Shan
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-09  1:47 UTC (permalink / raw)
  To: openbmc; +Cc: Gavin Shan

This drops API ncsi_stop_dev() as it does nothing.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 drivers/net/ethernet/faraday/ftgmac100.c | 6 ------
 include/net/ncsi.h                       | 6 ------
 net/ncsi/ncsi-manage.c                   | 5 -----
 3 files changed, 17 deletions(-)

diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 2fcb7f9..87ddc97 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1216,12 +1216,6 @@ static int ftgmac100_stop_dev(struct net_device *netdev)
 
 static int ftgmac100_stop(struct net_device *netdev)
 {
-	struct ftgmac100 *priv = netdev_priv(netdev);
-
-	/* Stop NCSI device */
-	if (priv->use_ncsi)
-		ncsi_stop_dev(priv->ndev);
-
 	return ftgmac100_stop_dev(netdev);
 }
 static int ftgmac100_hard_start_xmit(struct sk_buff *skb,
diff --git a/include/net/ncsi.h b/include/net/ncsi.h
index bf70b8d..fa50ab5 100644
--- a/include/net/ncsi.h
+++ b/include/net/ncsi.h
@@ -34,7 +34,6 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
 				   void (*notifier)(struct ncsi_dev *nd));
 int ncsi_start_dev(struct ncsi_dev *nd);
 int ncsi_suspend_dev(struct ncsi_dev *nd);
-void ncsi_stop_dev(struct ncsi_dev *nd);
 void ncsi_unregister_dev(struct ncsi_dev *nd);
 #else /* !CONFIG_NET_NCSI */
 static inline struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
@@ -53,11 +52,6 @@ static inline int ncsi_suspend_dev(struct ncsi_dev *nd)
 	return -ENOTTY;
 }
 
-static inline void ncsi_stop_dev(struct ncsi_dev *nd)
-{
-
-}
-
 void inline ncsi_unregister_dev(struct ncsi_dev *nd)
 {
 }
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index c32a919..05619f8 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -899,11 +899,6 @@ int ncsi_suspend_dev(struct ncsi_dev *nd)
 }
 EXPORT_SYMBOL_GPL(ncsi_suspend_dev);
 
-void ncsi_stop_dev(struct ncsi_dev *nd)
-{
-}
-EXPORT_SYMBOL_GPL(ncsi_stop_dev);
-
 void ncsi_unregister_dev(struct ncsi_dev *nd)
 {
 	struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 5/8] net/ncsi: Enable AEN on active channel
  2016-05-09  1:47 [PATCH 0/8] NSCI Improvement Gavin Shan
                   ` (3 preceding siblings ...)
  2016-05-09  1:47 ` [PATCH 4/8] net/ncsi: Remove ncsi_stop_dev() Gavin Shan
@ 2016-05-09  1:47 ` Gavin Shan
  2016-05-09  1:47 ` [PATCH 6/8] net/ncsi: Improvement for ncsi_dev_suspend() Gavin Shan
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-09  1:47 UTC (permalink / raw)
  To: openbmc; +Cc: Gavin Shan

NCSI AEN packets are transmitted by far end to notify the network
status change. We had the wrong assumption that the functionality
is enabled in far end by default.

This transmits a AEN enablement packet when configuring the active
channel.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 net/ncsi/internal.h    | 1 +
 net/ncsi/ncsi-manage.c | 6 ++++++
 2 files changed, 7 insertions(+)

diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index cc37d9b..2525229 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -64,6 +64,7 @@ enum {
 	ncsi_dev_state_config_ebf,
 	ncsi_dev_state_config_ecnt,
 	ncsi_dev_state_config_ec,
+	ncsi_dev_state_config_ae,
 	ncsi_dev_state_config_gls,
 	ncsi_dev_state_config_done,
 	ncsi_dev_state_suspend_select	= 0x0401,
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 05619f8..9ed51f2 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -421,6 +421,7 @@ static void ncsi_dev_config(struct ncsi_dev_priv *ndp)
 	case ncsi_dev_state_config_ebf:
 	case ncsi_dev_state_config_ecnt:
 	case ncsi_dev_state_config_ec:
+	case ncsi_dev_state_config_ae:
 	case ncsi_dev_state_config_gls:
 		atomic_set(&ndp->ndp_pending_reqs, 1);
 
@@ -447,6 +448,11 @@ static void ncsi_dev_config(struct ncsi_dev_priv *ndp)
 			nd->nd_state = ncsi_dev_state_config_ec;
 		} else if (nd->nd_state == ncsi_dev_state_config_ec) {
 			nca.nca_type = NCSI_PKT_CMD_EC;
+			nd->nd_state = ncsi_dev_state_config_ae;
+		} else if (nd->nd_state == ncsi_dev_state_config_ae) {
+			nca.nca_type = NCSI_PKT_CMD_AE;
+			nca.nca_bytes[0] = 0;
+			nca.nca_dwords[1] = 0x7;
 			nd->nd_state = ncsi_dev_state_config_gls;
 		} else if (nd->nd_state == ncsi_dev_state_config_gls) {
 			nca.nca_type = NCSI_PKT_CMD_GLS;
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 6/8] net/ncsi: Improvement for ncsi_dev_suspend()
  2016-05-09  1:47 [PATCH 0/8] NSCI Improvement Gavin Shan
                   ` (4 preceding siblings ...)
  2016-05-09  1:47 ` [PATCH 5/8] net/ncsi: Enable AEN on active channel Gavin Shan
@ 2016-05-09  1:47 ` Gavin Shan
  2016-05-09  1:47 ` [PATCH 7/8] net/farady: Keep MAC always active for NCSI packets Gavin Shan
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-09  1:47 UTC (permalink / raw)
  To: openbmc; +Cc: Gavin Shan

The function is used to deconfigure current active channel so that
we can pick another available channel as active. At end of it, the
all available packages and channels are purged. It's not correct.
Also, the new active channel should be finalized before configuring
it using ncsi_dev_config().

This improves the function from above two aspects.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 net/ncsi/ncsi-manage.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 9ed51f2..48575d2 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -686,7 +686,7 @@ error:
 static void ncsi_dev_suspend(struct ncsi_dev_priv *ndp)
 {
 	struct ncsi_dev *nd = &ndp->ndp_ndev;
-	struct ncsi_package *np, *tmp;
+	struct ncsi_package *np;
 	struct ncsi_channel *nc;
 	struct ncsi_cmd_arg nca;
 	int ret;
@@ -740,12 +740,11 @@ static void ncsi_dev_suspend(struct ncsi_dev_priv *ndp)
 		break;
 	case ncsi_dev_state_suspend_done:
 done:
-		spin_lock(&ndp->ndp_package_lock);
-		list_for_each_entry_safe(np, tmp, &ndp->ndp_packages, np_node)
-			ncsi_release_package(np);
-		spin_unlock(&ndp->ndp_package_lock);
+		if (ndp->ndp_flags & NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE)
+			ncsi_choose_active_channel(ndp);
 
-		if (!(ndp->ndp_flags & NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE)) {
+		if (!(ndp->ndp_flags & NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE) ||
+		    !ndp->ndp_active_channel) {
 			nd->nd_state = ncsi_dev_state_functional;
 			nd->nd_link_up = 0;
 			nd->nd_handler(nd);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 7/8] net/farady: Keep MAC always active for NCSI packets
  2016-05-09  1:47 [PATCH 0/8] NSCI Improvement Gavin Shan
                   ` (5 preceding siblings ...)
  2016-05-09  1:47 ` [PATCH 6/8] net/ncsi: Improvement for ncsi_dev_suspend() Gavin Shan
@ 2016-05-09  1:47 ` Gavin Shan
  2016-05-09  1:47 ` [PATCH 8/8] net/ncsi: LSC AEN handler improvement Gavin Shan
  2016-05-11  5:43 ` [PATCH 0/8] NSCI Improvement Joel Stanley
  8 siblings, 0 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-09  1:47 UTC (permalink / raw)
  To: openbmc; +Cc: Gavin Shan

The status of MAC and NCSI interface are sychronized. When NCSI
interface is down, the MAC is brought down. It means the NCSI
packets (especially AEN packets) cannot be received by the MAC's
driver even they're transmitted by far end. It causes one issue:
the ethernet cable is unplugged initially and system boots up
with down NCSI interface. The MAC stops receiving any ingress
traffic including NCSI packets. At later point, one NCSI (AEN)
packet is sent from far end when the ethernet cable is plugged.
We're going to miss the AEN on local end and the interface has
to be down for ever.

This keeps the receive/transmit buffer, IRQ and NAPI are always
enabled so that we won't miss any NCSI packets even the interrupt
is currently in link down state.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 drivers/net/ethernet/faraday/ftgmac100.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 87ddc97..7eae197 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1320,18 +1320,9 @@ static const struct net_device_ops ftgmac100_netdev_ops = {
 
 static void ftgmac100_ncsi_handler(struct ncsi_dev *nd)
 {
-	struct net_device *netdev = nd->nd_dev;
-
-	if (nd->nd_state != ncsi_dev_state_functional)
-		return;
-
-	if (nd->nd_link_up) {
-		pr_info("NCSI dev is up\n");
-		netif_start_queue(netdev);
-	} else {
-		pr_info("NCSI dev is down\n");
-		ftgmac100_stop_dev(netdev);
-	}
+	if (nd->nd_state == ncsi_dev_state_functional)
+		pr_info("NCSI interface %s\n",
+			nd->nd_link_up ? "up" : "down");
 }
 /******************************************************************************
  * struct platform_driver functions
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 8/8] net/ncsi: LSC AEN handler improvement
  2016-05-09  1:47 [PATCH 0/8] NSCI Improvement Gavin Shan
                   ` (6 preceding siblings ...)
  2016-05-09  1:47 ` [PATCH 7/8] net/farady: Keep MAC always active for NCSI packets Gavin Shan
@ 2016-05-09  1:47 ` Gavin Shan
  2016-05-11  5:43 ` [PATCH 0/8] NSCI Improvement Joel Stanley
  8 siblings, 0 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-09  1:47 UTC (permalink / raw)
  To: openbmc; +Cc: Gavin Shan

This improves the LSC (Link Status Change) AEN handler:

   * The first channel with up link is choosen as active channel.
   * The first channel is choosen as active channel if none of channels
     is link up.
   * The active channel is always configured when its link becomes up
     or it's just picked as new active channel.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 net/ncsi/ncsi-aen.c    |  6 +++---
 net/ncsi/ncsi-manage.c | 22 ++++++++++++----------
 2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/net/ncsi/ncsi-aen.c b/net/ncsi/ncsi-aen.c
index 87caaa8..5bc0873 100644
--- a/net/ncsi/ncsi-aen.c
+++ b/net/ncsi/ncsi-aen.c
@@ -81,14 +81,14 @@ static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
 	ncm->ncm_data[2] = ntohl(lsc->status);
 	ncm->ncm_data[4] = ntohl(lsc->oem_status);
 	if (!ndp->ndp_active_channel ||
-	    ndp->ndp_active_channel != nc ||
-	    ncm->ncm_data[2] & 0x1)
+	    ndp->ndp_active_channel != nc)
 		return 0;
 
 	/* If this channel is the active one and the link is down,
 	 * we have to choose another channel to be active one.
 	 */
-	ndp->ndp_flags |= NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE;
+	if (!(ncm->ncm_data[2] & 0x1))
+		ndp->ndp_flags |= NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE;
 	ncsi_suspend_dev(nd);
 
 	return 0;
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 48575d2..5080f72 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -470,8 +470,7 @@ static void ncsi_dev_config(struct ncsi_dev_priv *ndp)
 		if (nc->nc_modes[NCSI_MODE_LINK].ncm_data[2] & 0x1)
 			nd->nd_link_up = 1;
 
-		if (!(ndp->ndp_flags & NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE))
-			nd->nd_handler(nd);
+		nd->nd_handler(nd);
 		ndp->ndp_flags &= ~NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE;
 
 		break;
@@ -500,13 +499,17 @@ static void ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
 	ndp->ndp_active_channel = NULL;
 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
 		NCSI_FOR_EACH_CHANNEL(np, nc) {
-			ncm = &nc->nc_modes[NCSI_MODE_LINK];
-			if (ndp->ndp_active_channel ||
-			    !(ncm->ncm_data[2] & 0x1))
-				continue;
+			if (!ndp->ndp_active_channel) {
+				ndp->ndp_active_package = np;
+				ndp->ndp_active_channel = nc;
+			}
 
-			ndp->ndp_active_package = np;
-			ndp->ndp_active_channel = nc;
+			ncm = &nc->nc_modes[NCSI_MODE_LINK];
+			if (ncm->ncm_data[2] & 0x1) {
+				ndp->ndp_active_package = np;
+				ndp->ndp_active_channel = nc;
+				return;
+			}
 		}
 	}
 }
@@ -743,8 +746,7 @@ done:
 		if (ndp->ndp_flags & NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE)
 			ncsi_choose_active_channel(ndp);
 
-		if (!(ndp->ndp_flags & NCSI_DEV_PRIV_FLAG_CHANGE_ACTIVE) ||
-		    !ndp->ndp_active_channel) {
+		if (!ndp->ndp_active_channel) {
 			nd->nd_state = ncsi_dev_state_functional;
 			nd->nd_link_up = 0;
 			nd->nd_handler(nd);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/8] NSCI Improvement
  2016-05-09  1:47 [PATCH 0/8] NSCI Improvement Gavin Shan
                   ` (7 preceding siblings ...)
  2016-05-09  1:47 ` [PATCH 8/8] net/ncsi: LSC AEN handler improvement Gavin Shan
@ 2016-05-11  5:43 ` Joel Stanley
  2016-05-12  6:34   ` Gavin Shan
  8 siblings, 1 reply; 14+ messages in thread
From: Joel Stanley @ 2016-05-11  5:43 UTC (permalink / raw)
  To: Gavin Shan; +Cc: OpenBMC Maillist

On Mon, May 9, 2016 at 11:17 AM, Gavin Shan <gwshan@linux.vnet.ibm.com> wrote:
> This series bases on branch dev-4.4. Couple of things are improved as below:
>
>    * Remove netlink stuff as nobody starts to use it. Lets focus on the core
>      for now.
>    * The available packages and channels are enumerated for once when user
>      brings up the network interface for the first time. Afterwords, less
>      time (3 to 4 seconds) are reduced to bring up the interface.
>    * Explicitly enable AEN that is disabled by default.
>    * The LSC (Link Status Change) AEN handler helps switching active channel
>      properly after the packet can be received without problem. In order to
>      listen for ingress AEN packet, the MAC has to be ready for reception
>      after the interface is brought up.
>
> This series is to fix the bug: https://github.com/openbmc/linux/issues/61
> With this series applied (based on dev-4.4), it should fix the issue. Note
> that I had the test on palm4-bmc.
>
>    * From uboot, download the kernel image;
>    * Unplug the ethernet cable;
>    * From uboot, boot the kernel image;
>    * Configure the ethernet interface when the kernel boots up completely.
>      The NCSI interface should be down;
>    * Plug the cable, the NCSI interface is up automatically. The interface
>      is pingable from external.

Great work Gavin. Thanks for getting to the bottom of this and testing
the patches.

I've applied them to dev-4.4 and tagged a release that includes your changes:

 https://github.com/openbmc/linux/releases/tag/openbmc-20160511-1

Cheers,

Joel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/8] NSCI Improvement
  2016-05-11  5:43 ` [PATCH 0/8] NSCI Improvement Joel Stanley
@ 2016-05-12  6:34   ` Gavin Shan
  2016-05-12  7:02     ` Joel Stanley
  0 siblings, 1 reply; 14+ messages in thread
From: Gavin Shan @ 2016-05-12  6:34 UTC (permalink / raw)
  To: Joel Stanley; +Cc: Gavin Shan, OpenBMC Maillist

On Wed, May 11, 2016 at 03:13:40PM +0930, Joel Stanley wrote:
>On Mon, May 9, 2016 at 11:17 AM, Gavin Shan <gwshan@linux.vnet.ibm.com> wrote:
>> This series bases on branch dev-4.4. Couple of things are improved as below:
>>
>>    * Remove netlink stuff as nobody starts to use it. Lets focus on the core
>>      for now.
>>    * The available packages and channels are enumerated for once when user
>>      brings up the network interface for the first time. Afterwords, less
>>      time (3 to 4 seconds) are reduced to bring up the interface.
>>    * Explicitly enable AEN that is disabled by default.
>>    * The LSC (Link Status Change) AEN handler helps switching active channel
>>      properly after the packet can be received without problem. In order to
>>      listen for ingress AEN packet, the MAC has to be ready for reception
>>      after the interface is brought up.
>>
>> This series is to fix the bug: https://github.com/openbmc/linux/issues/61
>> With this series applied (based on dev-4.4), it should fix the issue. Note
>> that I had the test on palm4-bmc.
>>
>>    * From uboot, download the kernel image;
>>    * Unplug the ethernet cable;
>>    * From uboot, boot the kernel image;
>>    * Configure the ethernet interface when the kernel boots up completely.
>>      The NCSI interface should be down;
>>    * Plug the cable, the NCSI interface is up automatically. The interface
>>      is pingable from external.
>
>Great work Gavin. Thanks for getting to the bottom of this and testing
>the patches.
>
>I've applied them to dev-4.4 and tagged a release that includes your changes:
>
> https://github.com/openbmc/linux/releases/tag/openbmc-20160511-1
>

Thanks, Joel. Note that I had no chance to test it out on barreleye where
the issue was reported. I cannot find a barreleye BMC in local lab. could
you please tell if I can access any one of this kind of machine in case
you know one?

Thanks,
Gavin

>Cheers,
>
>Joel
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/8] NSCI Improvement
  2016-05-12  6:34   ` Gavin Shan
@ 2016-05-12  7:02     ` Joel Stanley
  2016-05-12  7:12       ` Gavin Shan
  2016-05-20  6:56       ` Gavin Shan
  0 siblings, 2 replies; 14+ messages in thread
From: Joel Stanley @ 2016-05-12  7:02 UTC (permalink / raw)
  To: Gavin Shan; +Cc: OpenBMC Maillist

On Thu, May 12, 2016 at 4:04 PM, Gavin Shan <gwshan@linux.vnet.ibm.com> wrote:
> Thanks, Joel. Note that I had no chance to test it out on barreleye where
> the issue was reported. I cannot find a barreleye BMC in local lab. could
> you please tell if I can access any one of this kind of machine in case
> you know one?

Currently the only ones we have access to are in a lab at IBM in
Austin. I'll send you the details.

I think we should have another go at sending the patches upstream. Can
you create a series against 4.6? I'm looking in to finding us some
reviewers; I'll let you know when I hear something.

Cheers,

Joel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/8] NSCI Improvement
  2016-05-12  7:02     ` Joel Stanley
@ 2016-05-12  7:12       ` Gavin Shan
  2016-05-20  6:56       ` Gavin Shan
  1 sibling, 0 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-12  7:12 UTC (permalink / raw)
  To: Joel Stanley; +Cc: Gavin Shan, OpenBMC Maillist

On Thu, May 12, 2016 at 04:32:26PM +0930, Joel Stanley wrote:
>On Thu, May 12, 2016 at 4:04 PM, Gavin Shan <gwshan@linux.vnet.ibm.com> wrote:
>> Thanks, Joel. Note that I had no chance to test it out on barreleye where
>> the issue was reported. I cannot find a barreleye BMC in local lab. could
>> you please tell if I can access any one of this kind of machine in case
>> you know one?
>
>Currently the only ones we have access to are in a lab at IBM in
>Austin. I'll send you the details.
>
>I think we should have another go at sending the patches upstream. Can
>you create a series against 4.6? I'm looking in to finding us some
>reviewers; I'll let you know when I hear something.
>

Sure, I will do that after finishing the PCI hotplug stuff at hand.
Thanks for your helps (machine access & code review), Joel.

Thanks,
Gavin

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/8] NSCI Improvement
  2016-05-12  7:02     ` Joel Stanley
  2016-05-12  7:12       ` Gavin Shan
@ 2016-05-20  6:56       ` Gavin Shan
  1 sibling, 0 replies; 14+ messages in thread
From: Gavin Shan @ 2016-05-20  6:56 UTC (permalink / raw)
  To: Joel Stanley; +Cc: Gavin Shan, openbmc

On Thu, May 12, 2016 at 04:32:26PM +0930, Joel Stanley wrote:
>On Thu, May 12, 2016 at 4:04 PM, Gavin Shan <gwshan@linux.vnet.ibm.com> wrote:
>> Thanks, Joel. Note that I had no chance to test it out on barreleye where
>> the issue was reported. I cannot find a barreleye BMC in local lab. could
>> you please tell if I can access any one of this kind of machine in case
>> you know one?
>
>Currently the only ones we have access to are in a lab at IBM in
>Austin. I'll send you the details.
>

Joel, it seems you forgot sending the details (barreleye) machine. It
would be nice if you can tell who I should talk to before grabbing it,
to avoid conllision :-)

Thanks,
Gavin

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2016-05-20  6:58 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-09  1:47 [PATCH 0/8] NSCI Improvement Gavin Shan
2016-05-09  1:47 ` [PATCH 1/8] net/ncsi: Remove netlink support Gavin Shan
2016-05-09  1:47 ` [PATCH 2/8] net/ncsi: Add NCSI_DEV_PRIV_FLAG_POPULATED Gavin Shan
2016-05-09  1:47 ` [PATCH 3/8] net/ncsi: Enumerate NCSI channels in advance Gavin Shan
2016-05-09  1:47 ` [PATCH 4/8] net/ncsi: Remove ncsi_stop_dev() Gavin Shan
2016-05-09  1:47 ` [PATCH 5/8] net/ncsi: Enable AEN on active channel Gavin Shan
2016-05-09  1:47 ` [PATCH 6/8] net/ncsi: Improvement for ncsi_dev_suspend() Gavin Shan
2016-05-09  1:47 ` [PATCH 7/8] net/farady: Keep MAC always active for NCSI packets Gavin Shan
2016-05-09  1:47 ` [PATCH 8/8] net/ncsi: LSC AEN handler improvement Gavin Shan
2016-05-11  5:43 ` [PATCH 0/8] NSCI Improvement Joel Stanley
2016-05-12  6:34   ` Gavin Shan
2016-05-12  7:02     ` Joel Stanley
2016-05-12  7:12       ` Gavin Shan
2016-05-20  6:56       ` Gavin Shan

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.