Netdev List
 help / color / mirror / Atom feed
* [ANNOUNCE] ipvsadm release v1.28
From: Jesper Dangaard Brouer @ 2015-02-09  5:55 UTC (permalink / raw)
  To: lvs-devel, lvs-users
  Cc: brouer, netdev, linux-kernel, Ryan O'Hara, Julian Anastasov,
	overcastsky.zhao, formorer, mt, logan, support, Daniel Borkmann,
	Wensong Zhang, Simon Horman, Alex Gartrell


We are happy to announce the release of ipvsadm v1.28.

 ipvsadm is a utility to administer the kernels IPVS/LVS load-balancer service

It has been quite a while since the previous release, v1.27. A number of
fixes and improvements have been made; most noticeably in the area of IPv6.

One big addition is the support for heterogeneous pools (v4 and v6
mixed pools in 3.18), by Alex Gartrell (facebook).

Feature wise the SCTP protocol has been added which is available via the
cmdline parameter "--sctp-service". The kernel has supported SCTP since
kernel 2.6.34 but up until now ipvsadm users have been restricted to using
fwmark-based virtual services for SCTP.

This release is based on the kernel.org git tree:
  https://git.kernel.org/cgit/utils/kernel/ipvsadm/ipvsadm.git/

You can download the tarballs from:
 https://kernel.org/pub/linux/utils/kernel/ipvsadm/

Git tree:
 git://git.kernel.org/pub/scm/utils/kernel/ipvsadm/ipvsadm.git

Shortlog:
 Alex Gartrell (2):
      ipvsadm: specify real server address family to netlink socket
      ipvsadm: do not truncate ipv6 members of v4 services

 Daniel Borkmann (2):
      ipvsadm: fix compile warning in print_largenum
      ipvsadm: fix compile warning in modprobe_ipvs

 Hibari Michiro (1):
      ipvsadm: enable displaying of IPv6 hostnames in listing

 Jesper Dangaard Brouer (1):
      Release: Version 1.28

 Julian Anastasov (3):
      ipvsadm: restrict different address family
      ipvsadm: allow different address family in connection listing
      ipvsadm: add SCTP support

 Ryan O'Hara (2):
      libipvs: Initialize ipvs_service_t variable
      ipvsadm: Fix list daemon to show backup daemon


-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Sr. Network Kernel Developer at Red Hat
  Author of http://www.iptv-analyzer.org
  LinkedIn: http://www.linkedin.com/in/brouer

^ permalink raw reply

* Re: [PATCH net-next] cxgb4: Fix trace observed while dumping clip_tbl
From: David Miller @ 2015-02-09  5:56 UTC (permalink / raw)
  To: hariprasad; +Cc: netdev, leedom, anish, nirranjan, kumaras
In-Reply-To: <1423455430-13444-1-git-send-email-hariprasad@chelsio.com>

From: Hariprasad Shenai <hariprasad@chelsio.com>
Date: Mon,  9 Feb 2015 09:47:10 +0530

> Handle clip_tbl debugfs entry, when clip_tbl isn't allocated.
> In commit b5a02f503caa0837 ("cxgb4: Update ipv6 address handling api") wrong
> argument was passed for single_open for clip_tbl debugfs entry, which led to
> below trace. Fixing it.
 ...
> Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] net:rfs: adjust table size checking
From: David Miller @ 2015-02-09  5:56 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1423456753.31870.175.camel@edumazet-glaptop2.roam.corp.google.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 08 Feb 2015 20:39:13 -0800

> From: Eric Dumazet <edumazet@google.com>
> 
> Make sure root user does not try something stupid.
> 
> Also make sure mask field in struct rps_sock_flow_table
> does not share a cache line with the potentially often dirtied
> flow table.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Fixes: 567e4b79731c ("net: rfs: add hash collision detection")

Applied, thanks Eric.

^ permalink raw reply

* [PATCHv2 net-next 0/3] Add support in ethtool to get expansion ROM version
From: Hariprasad Shenai @ 2015-02-09  6:37 UTC (permalink / raw)
  To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai

Hi

This series adds support to get expansion ROM version via ethtool getdrvinfo.
PATCH 1/3 ("ethtool: rename reserved1 memeber in ethtool_drvinfo for expansion
    ROM version") is created against net-next tree.
PATCH 2/3 ("cxgb4: Add support in cxgb4 to get expansion rom version via
ethtool") is created against net-next tree.
PATCH 3/3 ("ethtool: Add support to get expansion ROM version in ethtool
getdrvinfo") is created against ethtool tree.

We have included all the maintainers of respective trees. Kindly review the
change and let us know in case of any review comments.

Thanks

V2: Use MACRO instead of hardcoded value for EROM version string len. Based on
review comment by David Miller.

Hariprasad Shenai (3):
  ethtool: rename reserved1 memeber in ethtool_drvinfo for expansion
    ROM version
  cxgb4: Add support in cxgb4 to get expansion rom version via ethtool
  ethtool: Add support to get expansion ROM version in ethtool getdrvinfo

 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h      |    1 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |    9 +++++
 drivers/net/ethernet/chelsio/cxgb4/t4_hw.c      |   37 +++++++++++++++++++++++
 drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h   |    8 +++++
 include/uapi/linux/ethtool.h                    |    4 ++-
 5 files changed, 58 insertions(+), 1 deletions(-)
---
 ethtool-copy.h |    4 +++-
 ethtool.c      |    2 ++
 2 files changed, 5 insertions(+), 1 deletions(-)

^ permalink raw reply

* [PATCHv2 net-next 1/3] ethtool: rename reserved1 memeber in ethtool_drvinfo for expansion ROM version
From: Hariprasad Shenai @ 2015-02-09  6:37 UTC (permalink / raw)
  To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1423463851-19073-1-git-send-email-hariprasad@chelsio.com>

Renamed the reserved1 member of struct ethtool_drvinfo to erom_version to get
expansion/option ROM version of the adapter if present.

Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
 include/uapi/linux/ethtool.h |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index 5f66d9c..2e49fc8 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -139,6 +139,7 @@ static inline __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep)
 
 #define ETHTOOL_FWVERS_LEN	32
 #define ETHTOOL_BUSINFO_LEN	32
+#define ETHTOOL_EROMVERS_LEN	32
 
 /**
  * struct ethtool_drvinfo - general driver and device information
@@ -148,6 +149,7 @@ static inline __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep)
  *	not be an empty string.
  * @version: Driver version string; may be an empty string
  * @fw_version: Firmware version string; may be an empty string
+ * @erom_version: Expansion ROM version string; may be an empty string
  * @bus_info: Device bus address.  This should match the dev_name()
  *	string for the underlying bus device, if there is one.  May be
  *	an empty string.
@@ -176,7 +178,7 @@ struct ethtool_drvinfo {
 	char	version[32];
 	char	fw_version[ETHTOOL_FWVERS_LEN];
 	char	bus_info[ETHTOOL_BUSINFO_LEN];
-	char	reserved1[32];
+	char	erom_version[ETHTOOL_EROMVERS_LEN];
 	char	reserved2[12];
 	__u32	n_priv_flags;
 	__u32	n_stats;
-- 
1.7.1

^ permalink raw reply related

* [PATCHv2 net-next 2/3] cxgb4: Add support in cxgb4 to get expansion rom version via ethtool
From: Hariprasad Shenai @ 2015-02-09  6:37 UTC (permalink / raw)
  To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1423463851-19073-1-git-send-email-hariprasad@chelsio.com>

Add support to get option/expansion rom version flashed in the adapter via
ethtool getdrvinfo function.

Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h      |    1 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |    9 +++++
 drivers/net/ethernet/chelsio/cxgb4/t4_hw.c      |   37 +++++++++++++++++++++++
 drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h   |    8 +++++
 4 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 0fe3a52..d6cda17 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -1121,6 +1121,7 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
 unsigned int t4_flash_cfg_addr(struct adapter *adapter);
 int t4_get_fw_version(struct adapter *adapter, u32 *vers);
 int t4_get_tp_version(struct adapter *adapter, u32 *vers);
+int t4_get_exprom_version(struct adapter *adapter, u32 *vers);
 int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
 	       const u8 *fw_data, unsigned int fw_size,
 	       struct fw_hdr *card_fw, enum dev_state state, int *reset);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 5db5b4f..a22cf93 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1419,6 +1419,7 @@ static int get_eeprom_len(struct net_device *dev)
 static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	struct adapter *adapter = netdev2adap(dev);
+	u32 exprom_vers;
 
 	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
@@ -1436,6 +1437,14 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 			FW_HDR_FW_VER_MINOR_G(adapter->params.tp_vers),
 			FW_HDR_FW_VER_MICRO_G(adapter->params.tp_vers),
 			FW_HDR_FW_VER_BUILD_G(adapter->params.tp_vers));
+
+	if (!t4_get_exprom_version(adapter, &exprom_vers))
+		snprintf(info->erom_version, sizeof(info->erom_version),
+			 "%u.%u.%u.%u",
+			 FW_HDR_FW_VER_MAJOR_G(exprom_vers),
+			 FW_HDR_FW_VER_MINOR_G(exprom_vers),
+			 FW_HDR_FW_VER_MICRO_G(exprom_vers),
+			 FW_HDR_FW_VER_BUILD_G(exprom_vers));
 }
 
 static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 2c13e80..4d643b6 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -948,6 +948,43 @@ int t4_get_tp_version(struct adapter *adapter, u32 *vers)
 			     1, vers, 0);
 }
 
+/**
+ *	t4_get_exprom_version - return the Expansion ROM version (if any)
+ *	@adapter: the adapter
+ *	@vers: where to place the version
+ *
+ *	Reads the Expansion ROM header from FLASH and returns the version
+ *	number (if present) through the @vers return value pointer.  We return
+ *	this in the Firmware Version Format since it's convenient.  Return
+ *	0 on success, -ENOENT if no Expansion ROM is present.
+ */
+int t4_get_exprom_version(struct adapter *adap, u32 *vers)
+{
+	struct exprom_header {
+		unsigned char hdr_arr[16];	/* must start with 0x55aa */
+		unsigned char hdr_ver[4];	/* Expansion ROM version */
+	} *hdr;
+	u32 exprom_header_buf[DIV_ROUND_UP(sizeof(struct exprom_header),
+					   sizeof(u32))];
+	int ret;
+
+	ret = t4_read_flash(adap, FLASH_EXP_ROM_START,
+			    ARRAY_SIZE(exprom_header_buf), exprom_header_buf,
+			    0);
+	if (ret)
+		return ret;
+
+	hdr = (struct exprom_header *)exprom_header_buf;
+	if (hdr->hdr_arr[0] != 0x55 || hdr->hdr_arr[1] != 0xaa)
+		return -ENOENT;
+
+	*vers = (FW_HDR_FW_VER_MAJOR_V(hdr->hdr_ver[0]) |
+		 FW_HDR_FW_VER_MINOR_V(hdr->hdr_ver[1]) |
+		 FW_HDR_FW_VER_MICRO_V(hdr->hdr_ver[2]) |
+		 FW_HDR_FW_VER_BUILD_V(hdr->hdr_ver[3]));
+	return 0;
+}
+
 /* Is the given firmware API compatible with the one the driver was compiled
  * with?
  */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index 95fc425..9b353a8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -3018,21 +3018,29 @@ enum fw_hdr_chip {
 
 #define FW_HDR_FW_VER_MAJOR_S	24
 #define FW_HDR_FW_VER_MAJOR_M	0xff
+#define FW_HDR_FW_VER_MAJOR_V(x) \
+	((x) << FW_HDR_FW_VER_MAJOR_S)
 #define FW_HDR_FW_VER_MAJOR_G(x) \
 	(((x) >> FW_HDR_FW_VER_MAJOR_S) & FW_HDR_FW_VER_MAJOR_M)
 
 #define FW_HDR_FW_VER_MINOR_S	16
 #define FW_HDR_FW_VER_MINOR_M	0xff
+#define FW_HDR_FW_VER_MINOR_V(x) \
+	((x) << FW_HDR_FW_VER_MINOR_S)
 #define FW_HDR_FW_VER_MINOR_G(x) \
 	(((x) >> FW_HDR_FW_VER_MINOR_S) & FW_HDR_FW_VER_MINOR_M)
 
 #define FW_HDR_FW_VER_MICRO_S	8
 #define FW_HDR_FW_VER_MICRO_M	0xff
+#define FW_HDR_FW_VER_MICRO_V(x) \
+	((x) << FW_HDR_FW_VER_MICRO_S)
 #define FW_HDR_FW_VER_MICRO_G(x) \
 	(((x) >> FW_HDR_FW_VER_MICRO_S) & FW_HDR_FW_VER_MICRO_M)
 
 #define FW_HDR_FW_VER_BUILD_S	0
 #define FW_HDR_FW_VER_BUILD_M	0xff
+#define FW_HDR_FW_VER_BUILD_V(x) \
+	((x) << FW_HDR_FW_VER_BUILD_S)
 #define FW_HDR_FW_VER_BUILD_G(x) \
 	(((x) >> FW_HDR_FW_VER_BUILD_S) & FW_HDR_FW_VER_BUILD_M)
 
-- 
1.7.1

^ permalink raw reply related

* [PATCHv2 ethtool 3/3] ethtool: Add support to get expansion ROM version in ethtool getdrvinfo
From: Hariprasad Shenai @ 2015-02-09  6:37 UTC (permalink / raw)
  To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1423463851-19073-1-git-send-email-hariprasad@chelsio.com>

Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
 ethtool-copy.h |    4 +++-
 ethtool.c      |    2 ++
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/ethtool-copy.h b/ethtool-copy.h
index 61b78fc..7ec0f94 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -139,6 +139,7 @@ static __inline__ __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep)
 
 #define ETHTOOL_FWVERS_LEN	32
 #define ETHTOOL_BUSINFO_LEN	32
+#define ETHTOOL_EROMVERS_LEN	32
 
 /**
  * struct ethtool_drvinfo - general driver and device information
@@ -148,6 +149,7 @@ static __inline__ __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep)
  *	not be an empty string.
  * @version: Driver version string; may be an empty string
  * @fw_version: Firmware version string; may be an empty string
+ * @erom_version: Expansion ROM version string; may be an empty string
  * @bus_info: Device bus address.  This should match the dev_name()
  *	string for the underlying bus device, if there is one.  May be
  *	an empty string.
@@ -176,7 +178,7 @@ struct ethtool_drvinfo {
 	char	version[32];
 	char	fw_version[ETHTOOL_FWVERS_LEN];
 	char	bus_info[ETHTOOL_BUSINFO_LEN];
-	char	reserved1[32];
+	char	erom_version[ETHTOOL_EROMVERS_LEN];
 	char	reserved2[12];
 	__u32	n_priv_flags;
 	__u32	n_stats;
diff --git a/ethtool.c b/ethtool.c
index bf583f3..b7d2206 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -701,6 +701,7 @@ static int dump_drvinfo(struct ethtool_drvinfo *info)
 		"driver: %.*s\n"
 		"version: %.*s\n"
 		"firmware-version: %.*s\n"
+		"expansion-rom-version: %.*s\n"
 		"bus-info: %.*s\n"
 		"supports-statistics: %s\n"
 		"supports-test: %s\n"
@@ -710,6 +711,7 @@ static int dump_drvinfo(struct ethtool_drvinfo *info)
 		(int)sizeof(info->driver), info->driver,
 		(int)sizeof(info->version), info->version,
 		(int)sizeof(info->fw_version), info->fw_version,
+		(int)sizeof(info->erom_version), info->erom_version,
 		(int)sizeof(info->bus_info), info->bus_info,
 		info->n_stats ? "yes" : "no",
 		info->testinfo_len ? "yes" : "no",
-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH 1/3] ixgbe, ixgbevf: Add new mbox API to enable MC promiscuous mode
From: Hiroshi Shimamoto @ 2015-02-09  6:59 UTC (permalink / raw)
  To: Jeff Kirsher
  Cc: e1000-devel@lists.sourceforge.net, Choi, Sy Jong,
	linux-kernel@vger.kernel.org, David Laight, Hayato Momma,
	netdev@vger.kernel.org, Bjørn Mork
In-Reply-To: <1423054641.2589.59.camel@jtkirshe-mobl>

> > Subject: Re: [E1000-devel] [PATCH 1/3] ixgbe, ixgbevf: Add new mbox API to enable MC promiscuous mode
> >
> > On Fri, 2015-01-30 at 11:37 +0000, Hiroshi Shimamoto wrote:
> > > From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
> > >
> > > The limitation of the number of multicast address for VF is not enough
> > > for the large scale server with SR-IOV feature.
> > > IPv6 requires the multicast MAC address for each IP address to handle
> > > the Neighbor Solicitation message.
> > > We couldn't assign over 30 IPv6 addresses to a single VF interface.
> > >
> > > The easy way to solve this is enabling multicast promiscuous mode.
> > > It is good to have a functionality to enable multicast promiscuous
> > > mode
> > > for each VF from VF driver.
> > >
> > > This patch introduces the new mbox API, IXGBE_VF_SET_MC_PROMISC, to
> > > enable/disable multicast promiscuous mode in VF. If multicast
> > > promiscuous
> > > mode is enabled the VF can receive all multicast packets.
> > >
> > > With this patch, the ixgbevf driver automatically enable multicast
> > > promiscuous mode when the number of multicast addresses is over than
> > > 30
> > > if possible.
> > >
> > > This also bump the API version up to 1.2 to check whether the API,
> > > IXGBE_VF_SET_MC_PROMISC is available.
> > >
> > > Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
> > > Reviewed-by: Hayato Momma <h-momma@ce.jp.nec.com>
> > > CC: Choi, Sy Jong <sy.jong.choi@intel.com>
> > > ---
> > >  drivers/net/ethernet/intel/ixgbe/ixgbe.h          |  1 +
> > >  drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h      |  4 +
> > >  drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c    | 89
> > > ++++++++++++++++++++++-
> > >  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 13 +++-
> > >  drivers/net/ethernet/intel/ixgbevf/mbx.h          |  4 +
> > >  drivers/net/ethernet/intel/ixgbevf/vf.c           | 29 +++++++-
> > >  drivers/net/ethernet/intel/ixgbevf/vf.h           |  1 +
> > >  7 files changed, 137 insertions(+), 4 deletions(-)
> >
> > Hiroshi, I tried to apply your patches to my queue but they do not apply
> > cleanly and they are in a DOS file format, not UNIX.  I also noted
> > several checkpatch.pl issues with your patches, so please fix those up
> > as well.
> 
> I'm sorry to bother you.
> Will fix.
> 
> >
> > Can you please fix up your patches based on my tree:
> > git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/queue.git
> 
> Yes. I haven't noticed your tree.
> Will resend patches against it.
> 

I encountered an issue with your tree, the commit id is below.

$ git log | head
commit e6f1649780f8f5a87299bf6af04453f93d1e3d5e
Author: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Date:   Fri Jan 23 20:43:14 2015 -0800

    ethernet: fm10k: Actually drop 4 bits

    The comment explains the intention, but vid has type u16. Before the
    inner shift, it is promoted to int, which has plenty of space for all
    vid's bits, so nothing is dropped. Use a simple mask instead.


I use the kernel from your tree in both host and guest.

Assign an IPv6 for VF in guest.
# ip -6 addr add 2001:db8::18:1/64 dev ens0

Send ping packet from other server to the VM.
# ping6  2001:db8::18:1 -I eth0

The following message was shown.
ixgbevf 0000:00:08.0: partial checksum but l4 proto=3a!

If I did the same operation in the host, I saw the same error message in host too.
ixgbe 0000:2d:00.0: partial checksum but l4 proto=3a!

Do you have any idea about that?

thanks,
Hiroshi
------------------------------------------------------------------------------
Dive into the World of Parallel Programming. The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net/
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply

* [PATCH] ath9k_htc: add adaptive usb receive flow control to repair soft lockup with monitor mode
From: yuweizheng @ 2015-02-09  7:13 UTC (permalink / raw)
  To: linux-kernel, ath9k-devel, linux-wireless, kvalo, ath9k-devel
  Cc: netdev, Yuwei Zheng

From: Yuwei Zheng <yuweizheng@139.com>

In the environment with heavy wifi traffic, set the ar9271 into monitor mode, will
trigger a deadloop panic.
 
The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and ath9k_rx_tasklet excute
on the soft irq context. In other words, the ath9k_hif_usb_rx_cb have more chance to excute than
ath9k_rx_tasklet.  So in the worst condition,  the rx.rxbuf receive list is always full,
and the do {}while(true) loop will not be break. The kernel get a soft lockup panic. 
 
[59011.007210] BUG: soft lockup - CPU#0 stuck for 23s!
[kworker/0:0:30609]
[59011.030560] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
[59013.804486] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
[59013.858522] Kernel panic - not syncing: softlockup: hung tasks
 
[59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
[59014.046834] bc20:                                                       de57b950 60000113
[59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 dc7bb440 df4bbcd0 00000000
[59014.072337] bc60: de57b950 60000113 df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff
[59014.085233] [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10)
[59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc])
[59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) from [<c0036d23>] (tasklet_action+0x3b/0x98)
[59014.134132] [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] (__do_softirq+0x99/0x16c)
[59014.147784] [<c0036709>] (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c)
[59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] (handle_IRQ+0x37/0x78)
[59014.173124] [<c000cfc3>] (handle_IRQ+0x37/0x78) from [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68)
[59014.187225] [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68) from [<c04c28db>](__irq_svc+0x3b/0x5c)
 
This bug can be see with low performance board, such as uniprocessor beagle bone board. 
 
Signed-off-by: Yuwei Zheng <yuweizheng@139.com>

---
 drivers/net/wireless/ath/ath9k/hif_usb.c       | 75 +++++++++++++++++++++++---
 drivers/net/wireless/ath/ath9k/hif_usb.h       |  9 ++++
 drivers/net/wireless/ath/ath9k/htc.h           | 19 +++++++
 drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 53 ++++++++++++++++++
 drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 44 +++++++++++++++
 5 files changed, 193 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 8e7153b..d05cc0b 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -640,6 +640,7 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
 	struct hif_device_usb *hif_dev =
 		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
 	int ret;
+	int delay;
 
 	if (!skb)
 		return;
@@ -658,7 +659,6 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
 	default:
 		goto resubmit;
 	}
-
 	if (likely(urb->actual_length != 0)) {
 		skb_put(skb, urb->actual_length);
 		ath9k_hif_usb_rx_stream(hif_dev, skb);
@@ -667,12 +667,22 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
 resubmit:
 	skb_reset_tail_pointer(skb);
 	skb_trim(skb, 0);
-
-	usb_anchor_urb(urb, &hif_dev->rx_submitted);
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret) {
-		usb_unanchor_urb(urb);
-		goto free;
+	spin_lock(&hif_dev->aurfc_lock);
+	if (atomic_read(&hif_dev->aurfc_submit_delay) > 0 &&
+	    hif_dev->aurfc_active == 1) {
+		usb_anchor_urb(urb, &hif_dev->rx_delayed_submitted);
+		delay = atomic_read(&hif_dev->aurfc_submit_delay);
+		schedule_delayed_work(&hif_dev->aurfc_delayed_work,
+				      msecs_to_jiffies(delay));
+		spin_unlock(&hif_dev->aurfc_lock);
+	} else {
+		spin_unlock(&hif_dev->aurfc_lock);
+		usb_anchor_urb(urb, &hif_dev->rx_submitted);
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+		if (ret) {
+			usb_unanchor_urb(urb);
+			goto free;
+		}
 	}
 
 	return;
@@ -818,9 +828,51 @@ err:
 	return -ENOMEM;
 }
 
+static void aurfc_submit_handler(struct work_struct *work)
+{
+	struct hif_device_usb *hif_dev =
+		container_of(work,
+			     struct hif_device_usb,
+			     aurfc_delayed_work.work);
+	struct urb *urb = NULL;
+	struct sk_buff *skb = NULL;
+	int ret;
+	int loop_times = 0;
+
+	AURFC_STAT_INC(aurfc_called);
+	while (true) {
+		loop_times++;
+		if (loop_times > MAX_RX_URB_NUM)
+			atomic_add(AURFC_STEP,
+				   &hif_dev->aurfc_submit_delay);
+
+		urb = usb_get_from_anchor(
+				&hif_dev->rx_delayed_submitted);
+		if (urb) {
+			skb = (struct sk_buff *)urb->context;
+			ret = usb_submit_urb(urb, GFP_KERNEL);
+			if (ret != 0) {
+				usb_unanchor_urb(urb);
+				dev_kfree_skb_any(skb);
+				urb->context = NULL;
+			}
+		} else {
+			break;
+		}
+	}
+}
+
 static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&hif_dev->aurfc_lock, flags);
+	hif_dev->aurfc_active = 0;
+	mod_delayed_work(system_wq, &hif_dev->aurfc_delayed_work, 0);
+	spin_unlock_irqrestore(&hif_dev->aurfc_lock, flags);
+	flush_delayed_work(&hif_dev->aurfc_delayed_work);
 	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
+	usb_kill_anchored_urbs(&hif_dev->rx_delayed_submitted);
 }
 
 static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
@@ -830,8 +882,17 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
 	int i, ret;
 
 	init_usb_anchor(&hif_dev->rx_submitted);
+	init_usb_anchor(&hif_dev->rx_delayed_submitted);
+
 	spin_lock_init(&hif_dev->rx_lock);
 
+	/* add for adaptive usb receive control*/
+	atomic_set(&hif_dev->aurfc_submit_delay, 0);
+	INIT_DELAYED_WORK(&hif_dev->aurfc_delayed_work,
+			  aurfc_submit_handler);
+	spin_lock_init(&hif_dev->aurfc_lock);
+	hif_dev->aurfc_active = 1;
+
 	for (i = 0; i < MAX_RX_URB_NUM; i++) {
 
 		/* Allocate URB */
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index 51496e7..8e7b67e 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -41,6 +41,7 @@
 #define MAX_RX_URB_NUM  8
 #define MAX_RX_BUF_SIZE 16384
 #define MAX_PKT_NUM_IN_TRANSFER 10
+#define AURFC_STEP 70  /* ms */
 
 #define MAX_REG_OUT_URB_NUM  1
 #define MAX_REG_IN_URB_NUM   64
@@ -98,9 +99,17 @@ struct hif_device_usb {
 	struct hif_usb_tx tx;
 	struct usb_anchor regout_submitted;
 	struct usb_anchor rx_submitted;
+	struct usb_anchor rx_delayed_submitted;
 	struct usb_anchor reg_in_submitted;
 	struct usb_anchor mgmt_submitted;
 	struct sk_buff *remain_skb;
+
+	/* adaptive usb receive flow control */
+	struct delayed_work aurfc_delayed_work;
+	spinlock_t aurfc_lock; /* to protect work */
+	atomic_t  aurfc_submit_delay; /* ms */
+	int aurfc_active;
+
 	const char *fw_name;
 	int rx_remain_len;
 	int rx_pkt_len;
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 9dde265..1586bd2 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -331,6 +331,13 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
 
 #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
 
+#define AURFC_STAT_INC(c) \
+	(hif_dev->htc_handle->drv_priv->debug.aurfc_stats.c++)
+#define AURFC_STAT_ADD(c, a) \
+	(hif_dev->htc_handle->drv_priv->debug.aurfc_stats.c += a)
+#define AURFC_STAT_SET(c, a) \
+	(hif_dev->htc_handle->drv_priv->debug.aurfc_stats.c = a)
+
 void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
 			   struct ath_rx_status *rs);
 
@@ -352,11 +359,20 @@ struct ath_skbrx_stats {
 	u32 skb_dropped;
 };
 
+struct ath_aurfc_stats {
+	u32 aurfc_highwater;
+	u32 aurfc_lowwater;
+	u32 aurfc_wm_triggered;
+	u32 aurfc_submit_delay;
+	u32 aurfc_called;
+};
+
 struct ath9k_debug {
 	struct dentry *debugfs_phy;
 	struct ath_tx_stats tx_stats;
 	struct ath_rx_stats rx_stats;
 	struct ath_skbrx_stats skbrx_stats;
+	struct ath_aurfc_stats aurfc_stats;
 };
 
 void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
@@ -377,6 +393,9 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
 
 #define TX_QSTAT_INC(c) do { } while (0)
 
+#define AURFC_STAT_INC(c) do {} while (0)
+#define AURFC_STAT_ADD(c, a) do {} while (0)
+#define AURFC_STAT_SET(c, a) do {} while (0)
 static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
 					 struct ath_rx_status *rs)
 {
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index 8cef1ed..a6be9be 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -286,6 +286,54 @@ static const struct file_operations fops_skb_rx = {
 	.llseek = default_llseek,
 };
 
+static ssize_t read_file_aurfc(struct file *file,
+			       char __user *user_buf,
+			       size_t count, loff_t *ppos)
+{
+	struct ath9k_htc_priv *priv = file->private_data;
+	char *buf;
+	unsigned int len = 0, size = 1500;
+	ssize_t retval = 0;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "High watermark",
+			priv->debug.aurfc_stats.aurfc_highwater);
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "Low watermark",
+			priv->debug.aurfc_stats.aurfc_lowwater);
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "WM triggered",
+			priv->debug.aurfc_stats.aurfc_wm_triggered);
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "Handler called",
+			priv->debug.aurfc_stats.aurfc_called);
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "Submit delay",
+			priv->debug.aurfc_stats.aurfc_submit_delay);
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count,
+					 ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static const struct file_operations fops_aurfc = {
+	.read = read_file_aurfc,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 static ssize_t read_file_slot(struct file *file, char __user *user_buf,
 			      size_t count, loff_t *ppos)
 {
@@ -518,7 +566,12 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
 	debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
 			    priv, &fops_skb_rx);
 
+	debugfs_create_file("aurfc_stats", S_IRUSR,
+			    priv->debug.debugfs_phy,
+			    priv, &fops_aurfc);
+
 	ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats);
+
 	ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats);
 
 	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index a0f58e2..939d008 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -1061,7 +1061,28 @@ void ath9k_rx_tasklet(unsigned long data)
 	unsigned long flags;
 	struct ieee80211_hdr *hdr;
 
+	/* add for adaptive usb receive flow control*/
+	int looptimes = 0;
+	int highwatermark = ATH9K_HTC_RXBUF*3/4;
+	int lowwatermark = ATH9K_HTC_RXBUF/32;
+	unsigned int delay = 0;
+
+	struct htc_target *htc = priv->htc;
+	struct hif_device_usb *hif_dev = htc->hif_dev;
+
+	AURFC_STAT_SET(aurfc_highwater, highwatermark);
+	AURFC_STAT_SET(aurfc_lowwater, lowwatermark);
+
 	do {
+		looptimes++;
+		if (looptimes > highwatermark) {
+			delay = looptimes*AURFC_STEP;
+			atomic_set(&hif_dev->aurfc_submit_delay,
+				   delay);
+			AURFC_STAT_INC(aurfc_wm_triggered);
+			AURFC_STAT_SET(aurfc_submit_delay, delay);
+		}
+
 		spin_lock_irqsave(&priv->rx.rxbuflock, flags);
 		list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
 			if (tmp_buf->in_process) {
@@ -1072,6 +1093,22 @@ void ath9k_rx_tasklet(unsigned long data)
 
 		if (rxbuf == NULL) {
 			spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
+			spin_lock_irqsave(&hif_dev->aurfc_lock,
+					  flags);
+			if (atomic_read(
+				&hif_dev->aurfc_submit_delay) > 0 &&
+			    hif_dev->aurfc_active > 0)
+				mod_delayed_work(system_wq,
+					&hif_dev->aurfc_delayed_work,
+						 0);
+			spin_unlock_irqrestore(&hif_dev->aurfc_lock,
+					       flags);
+			if (looptimes < lowwatermark) {
+				atomic_set(&hif_dev->aurfc_submit_delay
+					   , 0);
+				AURFC_STAT_SET(aurfc_submit_delay,
+					       0);
+			}
 			break;
 		}
 
@@ -1114,6 +1151,10 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
 
+	struct htc_target *htc = priv->htc;
+	struct hif_device_usb *hif_dev = htc->hif_dev;
+	int delay = ATH9K_HTC_RXBUF * AURFC_STEP;
+
 	spin_lock(&priv->rx.rxbuflock);
 	list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
 		if (!tmp_buf->in_process) {
@@ -1124,6 +1165,9 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
 	spin_unlock(&priv->rx.rxbuflock);
 
 	if (rxbuf == NULL) {
+		atomic_set(&hif_dev->aurfc_submit_delay, delay);
+		AURFC_STAT_INC(aurfc_wm_triggered);
+		AURFC_STAT_SET(aurfc_submit_delay, delay);
 		ath_dbg(common, ANY, "No free RX buffer\n");
 		goto err;
 	}
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH] net:ethernet:intel:Remove outdated fix me comment in the function,gb_acquire_swfw_sync_i210
From: Andrej Manduch @ 2015-02-09  7:17 UTC (permalink / raw)
  To: Jeff Kirsher, Nicholas Krause
  Cc: jesse.brandeburg, bruce.w.allan, carolyn.wyborny,
	donald.c.skidmore, gregory.v.rose, matthew.vick, john.ronciak,
	mitch.a.williams, linux.nics, e1000-devel, netdev, linux-kernel
In-Reply-To: <1423444889.2589.165.camel@jtkirshe-mobl>

Hi,

Can you please leave full patch with git diff when you're replying to
Nicks e-mails? Nick is banned in *@vger.kernel.org so we cannot see his
patches and rest of the world is seeing only replyies to his e-mail. And
it's really hard to test anything when we don't see changes.

On 02/08/2015 08:21 PM, Jeff Kirsher wrote:
> On Sun, 2015-02-08 at 00:21 -0500, Nicholas Krause wrote:
>> Removes the outdated fix me comment in the
>> function,gb_acquire_swfw_sync_i210
>> for setting the variables, i and timeout to the intended correct
>> values for
>> the function,gb_acquire_swfw_sync_i210 to function correctly. This
>> comment is
>> no longer due to these values having been no changed in the last few
>> years and
>> no known issues have been found for these variables being set to their
>> current
>> values. Due to this the comment can now be removed as the values set
>> for these
>> variables are known to be correct after years of no known issues or
>> bugs related
>> to their current values.
>>
>> Signed-off-by: Nicholas Krause <xerofoify@gmail.com>
>> ---
>>  drivers/net/ethernet/intel/igb/e1000_i210.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> Thank Nick, I will add your patch to my queue.
> 

-- 
Kind regards,
b.

^ permalink raw reply

* Re: [PATCH] ath9k_htc: add adaptive usb receive flow control to repair soft lockup with monitor mode
From: Yuwei Zheng @ 2015-02-09  7:20 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: linux-kernel, ath9k-devel, linux-wireless, kvalo, ath9k-devel,
	netdev, zhengyuwei
In-Reply-To: <54D53F15.8000507@rempel-privat.de>


On 五, 2015-02-06 at 23:24 +0100, Oleksij Rempel wrote:
> formatting of this patch is still badly broken.
> ./scripts/checkpatch.pl ~/Downloads/patch.eml
> ....
> ERROR: DOS line endings
> #442: FILE: drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:1170:
> +^I^IAURFC_STAT_SET(aurfc_submit_delay, delay);^M$
> 
> total: 195 errors, 6 warnings, 1 checks, 310 lines checked


Don't save the email as microsoft eml format.  The mail tool may 
translate it to DOS line endings if you save it as eml format. 

I have tested the patch and save it with Evolution as mobox format. 
The check result is 

total: 0 errors, 0 warnings, 1 checks, 310 lines checked





> 
> 
> Am 06.02.2015 um 11:46 schrieb yuweizheng@139.com:
> > From: Yuwei Zheng <yuweizheng@139.com>
> > 
> > In the environment with heavy wifi traffic, set the ar9271 into monitor mode, will
> > trigger a deadloop panic.
> >  
> > The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and ath9k_rx_tasklet excute
> > on the soft irq context. In other words, the ath9k_hif_usb_rx_cb have more chance to excute than
> > ath9k_rx_tasklet.  So in the worst condition,  the rx.rxbuf receive list is always full,
> > and the do {}while(true) loop will not be break. The kernel get a soft lockup panic. 
> >  
> > [59011.007210] BUG: soft lockup - CPU#0 stuck for 23s!
> > [kworker/0:0:30609]
> > [59011.030560] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
> > [59013.804486] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
> > [59013.858522] Kernel panic - not syncing: softlockup: hung tasks
> >  
> > [59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
> > [59014.046834] bc20:                                                       de57b950 60000113
> > [59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 dc7bb440 df4bbcd0 00000000
> > [59014.072337] bc60: de57b950 60000113 df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff
> > [59014.085233] [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10)
> > [59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc])
> > [59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) from [<c0036d23>] (tasklet_action+0x3b/0x98)
> > [59014.134132] [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] (__do_softirq+0x99/0x16c)
> > [59014.147784] [<c0036709>] (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c)
> > [59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] (handle_IRQ+0x37/0x78)
> > [59014.173124] [<c000cfc3>] (handle_IRQ+0x37/0x78) from [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68)
> > [59014.187225] [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68) from [<c04c28db>](__irq_svc+0x3b/0x5c)
> >  
> > This bug can be see with low performance board, such as uniprocessor beagle bone board. 
> >  
> > Signed-off-by: Yuwei Zheng <yuweizheng@139.com>
> > 
> > ---
> >  drivers/net/wireless/ath/ath9k/hif_usb.c       | 74 +++++++++++++++++++++++---
> >  drivers/net/wireless/ath/ath9k/hif_usb.h       |  9 ++++
> >  drivers/net/wireless/ath/ath9k/htc.h           | 19 +++++++
> >  drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 53 ++++++++++++++++++
> >  drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 44 +++++++++++++++
> >  5 files changed, 192 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
> > index 8e7153b..90ee568 100644
> > --- a/drivers/net/wireless/ath/ath9k/hif_usb.c
> > +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
> > @@ -640,6 +640,7 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
> >  	struct hif_device_usb *hif_dev =
> >  		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
> >  	int ret;
> > +	int delay;
> >  
> >  	if (!skb)
> >  		return;
> > @@ -658,7 +659,6 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
> >  	default:
> >  		goto resubmit;
> >  	}
> > -
> >  	if (likely(urb->actual_length != 0)) {
> >  		skb_put(skb, urb->actual_length);
> >  		ath9k_hif_usb_rx_stream(hif_dev, skb);
> > @@ -667,12 +667,22 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
> >  resubmit:
> >  	skb_reset_tail_pointer(skb);
> >  	skb_trim(skb, 0);
> > -
> > -	usb_anchor_urb(urb, &hif_dev->rx_submitted);
> > -	ret = usb_submit_urb(urb, GFP_ATOMIC);
> > -	if (ret) {
> > -		usb_unanchor_urb(urb);
> > -		goto free;
> > +	spin_lock(&hif_dev->aurfc_lock);
> > +	if (atomic_read(&hif_dev->aurfc_submit_delay) > 0 &&
> > +	    hif_dev->aurfc_active == 1) {
> > +		usb_anchor_urb(urb, &hif_dev->rx_delayed_submitted);
> > +		delay = atomic_read(&hif_dev->aurfc_submit_delay);
> > +		schedule_delayed_work(&hif_dev->aurfc_delayed_work,
> > +				      msecs_to_jiffies(delay));
> > +		spin_unlock(&hif_dev->aurfc_lock);
> > +	} else {
> > +		spin_unlock(&hif_dev->aurfc_lock);
> > +		usb_anchor_urb(urb, &hif_dev->rx_submitted);
> > +		ret = usb_submit_urb(urb, GFP_ATOMIC);
> > +		if (ret) {
> > +			usb_unanchor_urb(urb);
> > +			goto free;
> > +		}
> >  	}
> >  
> >  	return;
> > @@ -818,9 +828,50 @@ err:
> >  	return -ENOMEM;
> >  }
> >  
> > +static void aurfc_submit_handler(struct work_struct *work)
> > +{
> > +	struct hif_device_usb *hif_dev =
> > +		container_of(work,
> > +			     struct hif_device_usb,
> > +			     aurfc_delayed_work.work);
> > +
> > +	struct urb *urb = NULL;
> > +	struct sk_buff *skb = NULL;
> > +	int ret;
> > +	int loop_times = 0;
> > +
> > +	while (true) {
> > +		loop_times++;
> > +		if (loop_times > MAX_RX_URB_NUM)
> > +			atomic_add(AURFC_STEP,
> > +				   &hif_dev->aurfc_submit_delay);
> > +
> > +		urb = usb_get_from_anchor(
> > +				&hif_dev->rx_delayed_submitted);
> > +		if (urb) {
> > +			skb = (struct sk_buff *)urb->context;
> > +			ret = usb_submit_urb(urb, GFP_KERNEL);
> > +			if (ret != 0) {
> > +				usb_unanchor_urb(urb);
> > +				dev_kfree_skb_any(skb);
> > +				urb->context = NULL;
> > +			}
> > +		} else {
> > +			break;
> > +		}
> > +	}
> > +}
> > +
> >  static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
> >  {
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&hif_dev->aurfc_lock, flags);
> > +	hif_dev->aurfc_active = 0;
> > +	mod_delayed_work(system_wq, &hif_dev->aurfc_delayed_work, 0);
> > +	spin_unlock_irqrestore(&hif_dev->aurfc_lock, flags);
> >  	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
> > +	usb_kill_anchored_urbs(&hif_dev->rx_delayed_submitted);
> >  }
> >  
> >  static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
> > @@ -830,8 +881,17 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
> >  	int i, ret;
> >  
> >  	init_usb_anchor(&hif_dev->rx_submitted);
> > +	init_usb_anchor(&hif_dev->rx_delayed_submitted);
> > +
> >  	spin_lock_init(&hif_dev->rx_lock);
> >  
> > +	/* add for adaptive usb receive control*/
> > +	atomic_set(&hif_dev->aurfc_submit_delay, 0);
> > +	INIT_DELAYED_WORK(&hif_dev->aurfc_delayed_work,
> > +			  aurfc_submit_handler);
> > +	spin_lock_init(&hif_dev->aurfc_lock);
> > +	hif_dev->aurfc_active = 1;
> > +
> >  	for (i = 0; i < MAX_RX_URB_NUM; i++) {
> >  
> >  		/* Allocate URB */
> > diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
> > index 51496e7..2050a74 100644
> > --- a/drivers/net/wireless/ath/ath9k/hif_usb.h
> > +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
> > @@ -41,6 +41,7 @@
> >  #define MAX_RX_URB_NUM  8
> >  #define MAX_RX_BUF_SIZE 16384
> >  #define MAX_PKT_NUM_IN_TRANSFER 10
> > +#define AURFC_STEP 10  /* ms */
> >  
> >  #define MAX_REG_OUT_URB_NUM  1
> >  #define MAX_REG_IN_URB_NUM   64
> > @@ -98,9 +99,17 @@ struct hif_device_usb {
> >  	struct hif_usb_tx tx;
> >  	struct usb_anchor regout_submitted;
> >  	struct usb_anchor rx_submitted;
> > +	struct usb_anchor rx_delayed_submitted;
> >  	struct usb_anchor reg_in_submitted;
> >  	struct usb_anchor mgmt_submitted;
> >  	struct sk_buff *remain_skb;
> > +
> > +	/* adaptive usb receive flow control */
> > +	struct delayed_work aurfc_delayed_work;
> > +	spinlock_t aurfc_lock; /* to protect work */
> > +	atomic_t  aurfc_submit_delay; /* ms */
> > +	int aurfc_active;
> > +
> >  	const char *fw_name;
> >  	int rx_remain_len;
> >  	int rx_pkt_len;
> > diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
> > index 9dde265..1586bd2 100644
> > --- a/drivers/net/wireless/ath/ath9k/htc.h
> > +++ b/drivers/net/wireless/ath/ath9k/htc.h
> > @@ -331,6 +331,13 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
> >  
> >  #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
> >  
> > +#define AURFC_STAT_INC(c) \
> > +	(hif_dev->htc_handle->drv_priv->debug.aurfc_stats.c++)
> > +#define AURFC_STAT_ADD(c, a) \
> > +	(hif_dev->htc_handle->drv_priv->debug.aurfc_stats.c += a)
> > +#define AURFC_STAT_SET(c, a) \
> > +	(hif_dev->htc_handle->drv_priv->debug.aurfc_stats.c = a)
> > +
> >  void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
> >  			   struct ath_rx_status *rs);
> >  
> > @@ -352,11 +359,20 @@ struct ath_skbrx_stats {
> >  	u32 skb_dropped;
> >  };
> >  
> > +struct ath_aurfc_stats {
> > +	u32 aurfc_highwater;
> > +	u32 aurfc_lowwater;
> > +	u32 aurfc_wm_triggered;
> > +	u32 aurfc_submit_delay;
> > +	u32 aurfc_called;
> > +};
> > +
> >  struct ath9k_debug {
> >  	struct dentry *debugfs_phy;
> >  	struct ath_tx_stats tx_stats;
> >  	struct ath_rx_stats rx_stats;
> >  	struct ath_skbrx_stats skbrx_stats;
> > +	struct ath_aurfc_stats aurfc_stats;
> >  };
> >  
> >  void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
> > @@ -377,6 +393,9 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
> >  
> >  #define TX_QSTAT_INC(c) do { } while (0)
> >  
> > +#define AURFC_STAT_INC(c) do {} while (0)
> > +#define AURFC_STAT_ADD(c, a) do {} while (0)
> > +#define AURFC_STAT_SET(c, a) do {} while (0)
> >  static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
> >  					 struct ath_rx_status *rs)
> >  {
> > diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> > index 8cef1ed..a6be9be 100644
> > --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> > +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> > @@ -286,6 +286,54 @@ static const struct file_operations fops_skb_rx = {
> >  	.llseek = default_llseek,
> >  };
> >  
> > +static ssize_t read_file_aurfc(struct file *file,
> > +			       char __user *user_buf,
> > +			       size_t count, loff_t *ppos)
> > +{
> > +	struct ath9k_htc_priv *priv = file->private_data;
> > +	char *buf;
> > +	unsigned int len = 0, size = 1500;
> > +	ssize_t retval = 0;
> > +
> > +	buf = kzalloc(size, GFP_KERNEL);
> > +	if (!buf)
> > +		return -ENOMEM;
> > +
> > +	len += scnprintf(buf + len, size - len,
> > +			"%20s : %10u\n", "High watermark",
> > +			priv->debug.aurfc_stats.aurfc_highwater);
> > +	len += scnprintf(buf + len, size - len,
> > +			"%20s : %10u\n", "Low watermark",
> > +			priv->debug.aurfc_stats.aurfc_lowwater);
> > +
> > +	len += scnprintf(buf + len, size - len,
> > +			"%20s : %10u\n", "WM triggered",
> > +			priv->debug.aurfc_stats.aurfc_wm_triggered);
> > +
> > +	len += scnprintf(buf + len, size - len,
> > +			"%20s : %10u\n", "Handler called",
> > +			priv->debug.aurfc_stats.aurfc_called);
> > +
> > +	len += scnprintf(buf + len, size - len,
> > +			"%20s : %10u\n", "Submit delay",
> > +			priv->debug.aurfc_stats.aurfc_submit_delay);
> > +	if (len > size)
> > +		len = size;
> > +
> > +	retval = simple_read_from_buffer(user_buf, count,
> > +					 ppos, buf, len);
> > +	kfree(buf);
> > +
> > +	return retval;
> > +}
> > +
> > +static const struct file_operations fops_aurfc = {
> > +	.read = read_file_aurfc,
> > +	.open = simple_open,
> > +	.owner = THIS_MODULE,
> > +	.llseek = default_llseek,
> > +};
> > +
> >  static ssize_t read_file_slot(struct file *file, char __user *user_buf,
> >  			      size_t count, loff_t *ppos)
> >  {
> > @@ -518,7 +566,12 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
> >  	debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
> >  			    priv, &fops_skb_rx);
> >  
> > +	debugfs_create_file("aurfc_stats", S_IRUSR,
> > +			    priv->debug.debugfs_phy,
> > +			    priv, &fops_aurfc);
> > +
> >  	ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats);
> > +
> >  	ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats);
> >  
> >  	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
> > diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> > index a0f58e2..939d008 100644
> > --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> > +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> > @@ -1061,7 +1061,28 @@ void ath9k_rx_tasklet(unsigned long data)
> >  	unsigned long flags;
> >  	struct ieee80211_hdr *hdr;
> >  
> > +	/* add for adaptive usb receive flow control*/
> > +	int looptimes = 0;
> > +	int highwatermark = ATH9K_HTC_RXBUF*3/4;
> > +	int lowwatermark = ATH9K_HTC_RXBUF/32;
> > +	unsigned int delay = 0;
> > +
> > +	struct htc_target *htc = priv->htc;
> > +	struct hif_device_usb *hif_dev = htc->hif_dev;
> > +
> > +	AURFC_STAT_SET(aurfc_highwater, highwatermark);
> > +	AURFC_STAT_SET(aurfc_lowwater, lowwatermark);
> > +
> >  	do {
> > +		looptimes++;
> > +		if (looptimes > highwatermark) {
> > +			delay = looptimes*AURFC_STEP;
> > +			atomic_set(&hif_dev->aurfc_submit_delay,
> > +				   delay);
> > +			AURFC_STAT_INC(aurfc_wm_triggered);
> > +			AURFC_STAT_SET(aurfc_submit_delay, delay);
> > +		}
> > +
> >  		spin_lock_irqsave(&priv->rx.rxbuflock, flags);
> >  		list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
> >  			if (tmp_buf->in_process) {
> > @@ -1072,6 +1093,22 @@ void ath9k_rx_tasklet(unsigned long data)
> >  
> >  		if (rxbuf == NULL) {
> >  			spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
> > +			spin_lock_irqsave(&hif_dev->aurfc_lock,
> > +					  flags);
> > +			if (atomic_read(
> > +				&hif_dev->aurfc_submit_delay) > 0 &&
> > +			    hif_dev->aurfc_active > 0)
> > +				mod_delayed_work(system_wq,
> > +					&hif_dev->aurfc_delayed_work,
> > +						 0);
> > +			spin_unlock_irqrestore(&hif_dev->aurfc_lock,
> > +					       flags);
> > +			if (looptimes < lowwatermark) {
> > +				atomic_set(&hif_dev->aurfc_submit_delay
> > +					   , 0);
> > +				AURFC_STAT_SET(aurfc_submit_delay,
> > +					       0);
> > +			}
> >  			break;
> >  		}
> >  
> > @@ -1114,6 +1151,10 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
> >  	struct ath_common *common = ath9k_hw_common(ah);
> >  	struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
> >  
> > +	struct htc_target *htc = priv->htc;
> > +	struct hif_device_usb *hif_dev = htc->hif_dev;
> > +	int delay = ATH9K_HTC_RXBUF * AURFC_STEP;
> > +
> >  	spin_lock(&priv->rx.rxbuflock);
> >  	list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
> >  		if (!tmp_buf->in_process) {
> > @@ -1124,6 +1165,9 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
> >  	spin_unlock(&priv->rx.rxbuflock);
> >  
> >  	if (rxbuf == NULL) {
> > +		atomic_set(&hif_dev->aurfc_submit_delay, delay);
> > +		AURFC_STAT_INC(aurfc_wm_triggered);
> > +		AURFC_STAT_SET(aurfc_submit_delay, delay);
> >  		ath_dbg(common, ANY, "No free RX buffer\n");
> >  		goto err;
> >  	}
> > 
> 
> 

^ permalink raw reply

* linux-next: manual merge of the target-updates tree with the net-next tree
From: Stephen Rothwell @ 2015-02-09  8:03 UTC (permalink / raw)
  To: Nicholas A. Bellinger, David Miller, netdev
  Cc: linux-next, linux-kernel, Al Viro

[-- Attachment #1: Type: text/plain, Size: 552 bytes --]

Hi Nicholas,

Today's linux-next merge of the target-updates tree got a conflict in
drivers/vhost/scsi.c between commit 57dd8a0735aa ("vhost:
vhost_scsi_handle_vq() should just use copy_from_user()") from the
net-next tree and commit 09b13fa8c1a1 ("vhost/scsi: Add ANY_LAYOUT
support in vhost_scsi_handle_vq") from the target-updates tree.

I fixed it up (the latter removes the code modified by the former) and
can carry the fix as necessary (no action is required).

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [E1000-devel] [PATCH 1/3] ixgbe, ixgbevf: Add new mbox API to enable MC promiscuous mode
From: Jeff Kirsher @ 2015-02-09  8:20 UTC (permalink / raw)
  To: Hiroshi Shimamoto
  Cc: Alexander Duyck, Skidmore, Donald C, Bjørn Mork,
	e1000-devel@lists.sourceforge.net, netdev@vger.kernel.org,
	Choi, Sy Jong, linux-kernel@vger.kernel.org, David Laight,
	Hayato Momma
In-Reply-To: <7F861DC0615E0C47A872E6F3C5FCDDBD05E26E45@BPXM14GP.gisp.nec.co.jp>

[-- Attachment #1: Type: text/plain, Size: 4096 bytes --]

On Mon, 2015-02-09 at 06:59 +0000, Hiroshi Shimamoto wrote:
> > > Subject: Re: [E1000-devel] [PATCH 1/3] ixgbe, ixgbevf: Add new mbox API to enable MC promiscuous mode
> > >
> > > On Fri, 2015-01-30 at 11:37 +0000, Hiroshi Shimamoto wrote:
> > > > From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
> > > >
> > > > The limitation of the number of multicast address for VF is not enough
> > > > for the large scale server with SR-IOV feature.
> > > > IPv6 requires the multicast MAC address for each IP address to handle
> > > > the Neighbor Solicitation message.
> > > > We couldn't assign over 30 IPv6 addresses to a single VF interface.
> > > >
> > > > The easy way to solve this is enabling multicast promiscuous mode.
> > > > It is good to have a functionality to enable multicast promiscuous
> > > > mode
> > > > for each VF from VF driver.
> > > >
> > > > This patch introduces the new mbox API, IXGBE_VF_SET_MC_PROMISC, to
> > > > enable/disable multicast promiscuous mode in VF. If multicast
> > > > promiscuous
> > > > mode is enabled the VF can receive all multicast packets.
> > > >
> > > > With this patch, the ixgbevf driver automatically enable multicast
> > > > promiscuous mode when the number of multicast addresses is over than
> > > > 30
> > > > if possible.
> > > >
> > > > This also bump the API version up to 1.2 to check whether the API,
> > > > IXGBE_VF_SET_MC_PROMISC is available.
> > > >
> > > > Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
> > > > Reviewed-by: Hayato Momma <h-momma@ce.jp.nec.com>
> > > > CC: Choi, Sy Jong <sy.jong.choi@intel.com>
> > > > ---
> > > >  drivers/net/ethernet/intel/ixgbe/ixgbe.h          |  1 +
> > > >  drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h      |  4 +
> > > >  drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c    | 89
> > > > ++++++++++++++++++++++-
> > > >  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 13 +++-
> > > >  drivers/net/ethernet/intel/ixgbevf/mbx.h          |  4 +
> > > >  drivers/net/ethernet/intel/ixgbevf/vf.c           | 29 +++++++-
> > > >  drivers/net/ethernet/intel/ixgbevf/vf.h           |  1 +
> > > >  7 files changed, 137 insertions(+), 4 deletions(-)
> > >
> > > Hiroshi, I tried to apply your patches to my queue but they do not apply
> > > cleanly and they are in a DOS file format, not UNIX.  I also noted
> > > several checkpatch.pl issues with your patches, so please fix those up
> > > as well.
> > 
> > I'm sorry to bother you.
> > Will fix.
> > 
> > >
> > > Can you please fix up your patches based on my tree:
> > > git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/queue.git
> > 
> > Yes. I haven't noticed your tree.
> > Will resend patches against it.
> > 
> 
> I encountered an issue with your tree, the commit id is below.
> 
> $ git log | head
> commit e6f1649780f8f5a87299bf6af04453f93d1e3d5e
> Author: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> Date:   Fri Jan 23 20:43:14 2015 -0800
> 
>     ethernet: fm10k: Actually drop 4 bits
> 
>     The comment explains the intention, but vid has type u16. Before the
>     inner shift, it is promoted to int, which has plenty of space for all
>     vid's bits, so nothing is dropped. Use a simple mask instead.
> 
> 
> I use the kernel from your tree in both host and guest.
> 
> Assign an IPv6 for VF in guest.
> # ip -6 addr add 2001:db8::18:1/64 dev ens0
> 
> Send ping packet from other server to the VM.
> # ping6  2001:db8::18:1 -I eth0
> 
> The following message was shown.
> ixgbevf 0000:00:08.0: partial checksum but l4 proto=3a!
> 
> If I did the same operation in the host, I saw the same error message in host too.
> ixgbe 0000:2d:00.0: partial checksum but l4 proto=3a!
> 
> Do you have any idea about that?

Ah, sorry about that, try this tree again:
git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/queue.git

That patch was dropped for favor of a patch that Matthew Vick put
together (and recently got pushed upstream).  So my queue no longer has
that patch in the queue, since it got dropped.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH] net:ethernet:intel:Remove outdated fix me comment in the function,gb_acquire_swfw_sync_i210
From: Jeff Kirsher @ 2015-02-09  8:32 UTC (permalink / raw)
  To: Andrej Manduch
  Cc: Nicholas Krause, jesse.brandeburg, bruce.w.allan, carolyn.wyborny,
	donald.c.skidmore, gregory.v.rose, matthew.vick, john.ronciak,
	mitch.a.williams, linux.nics, e1000-devel, netdev, linux-kernel
In-Reply-To: <54D85EFA.3020501@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1689 bytes --]

On Mon, 2015-02-09 at 02:17 -0500, Andrej Manduch wrote:
> Hi,
> 
> Can you please leave full patch with git diff when you're replying to
> Nicks e-mails? Nick is banned in *@vger.kernel.org so we cannot see his
> patches and rest of the world is seeing only replyies to his e-mail. And
> it's really hard to test anything when we don't see changes.

Oh, I am well aware of Nick's current ban on @vger,kernel.org mailing
lists.  If you want to see Nick's patch, feel free to view his patch on
my queue tree:
https://git.kernel.org/cgit/linux/kernel/git/jkirsher/queue.git/

It is the top most patch (i.e. last one applied to my queue).

> 
> On 02/08/2015 08:21 PM, Jeff Kirsher wrote:
> > On Sun, 2015-02-08 at 00:21 -0500, Nicholas Krause wrote:
> >> Removes the outdated fix me comment in the
> >> function,gb_acquire_swfw_sync_i210
> >> for setting the variables, i and timeout to the intended correct
> >> values for
> >> the function,gb_acquire_swfw_sync_i210 to function correctly. This
> >> comment is
> >> no longer due to these values having been no changed in the last few
> >> years and
> >> no known issues have been found for these variables being set to their
> >> current
> >> values. Due to this the comment can now be removed as the values set
> >> for these
> >> variables are known to be correct after years of no known issues or
> >> bugs related
> >> to their current values.
> >>
> >> Signed-off-by: Nicholas Krause <xerofoify@gmail.com>
> >> ---
> >>  drivers/net/ethernet/intel/igb/e1000_i210.c | 2 +-
> >>  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > Thank Nick, I will add your patch to my queue.
> > 
> 



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* [PATCH 3.10 07/17] lib/checksum.c: fix carry in csum_tcpudp_nofold
From: Greg Kroah-Hartman @ 2015-02-09  8:33 UTC (permalink / raw)
  To: linux-kernel
  Cc: Greg Kroah-Hartman, stable, Karl Beldan, Al Viro, Eric Dumazet,
	Arnd Bergmann, Mike Frysinger, netdev, Eric Dumazet,
	David S. Miller
In-Reply-To: <20150209083039.240170510@linuxfoundation.org>

3.10-stable review patch.  If anyone has any objections, please let me know.

------------------

From: karl beldan <karl.beldan@gmail.com>

commit 150ae0e94634714b23919f0c333fee28a5b199d5 upstream.

The carry from the 64->32bits folding was dropped, e.g with:
saddr=0xFFFFFFFF daddr=0xFF0000FF len=0xFFFF proto=0 sum=1,
csum_tcpudp_nofold returned 0 instead of 1.

Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 lib/checksum.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

--- a/lib/checksum.c
+++ b/lib/checksum.c
@@ -47,6 +47,15 @@ static inline unsigned short from32to16(
 	return x;
 }
 
+static inline u32 from64to32(u64 x)
+{
+	/* add up 32-bit and 32-bit for 32+c bit */
+	x = (x & 0xffffffff) + (x >> 32);
+	/* add up carry.. */
+	x = (x & 0xffffffff) + (x >> 32);
+	return (u32)x;
+}
+
 static unsigned int do_csum(const unsigned char *buff, int len)
 {
 	int odd;
@@ -195,8 +204,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr,
 #else
 	s += (proto + len) << 8;
 #endif
-	s += (s >> 32);
-	return (__force __wsum)s;
+	return (__force __wsum)from64to32(s);
 }
 EXPORT_SYMBOL(csum_tcpudp_nofold);
 #endif

^ permalink raw reply

* [PATCH 3.14 10/20] lib/checksum.c: fix carry in csum_tcpudp_nofold
From: Greg Kroah-Hartman @ 2015-02-09  8:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: Greg Kroah-Hartman, stable, Karl Beldan, Al Viro, Eric Dumazet,
	Arnd Bergmann, Mike Frysinger, netdev, Eric Dumazet,
	David S. Miller
In-Reply-To: <20150209083042.033412726@linuxfoundation.org>

3.14-stable review patch.  If anyone has any objections, please let me know.

------------------

From: karl beldan <karl.beldan@gmail.com>

commit 150ae0e94634714b23919f0c333fee28a5b199d5 upstream.

The carry from the 64->32bits folding was dropped, e.g with:
saddr=0xFFFFFFFF daddr=0xFF0000FF len=0xFFFF proto=0 sum=1,
csum_tcpudp_nofold returned 0 instead of 1.

Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 lib/checksum.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

--- a/lib/checksum.c
+++ b/lib/checksum.c
@@ -47,6 +47,15 @@ static inline unsigned short from32to16(
 	return x;
 }
 
+static inline u32 from64to32(u64 x)
+{
+	/* add up 32-bit and 32-bit for 32+c bit */
+	x = (x & 0xffffffff) + (x >> 32);
+	/* add up carry.. */
+	x = (x & 0xffffffff) + (x >> 32);
+	return (u32)x;
+}
+
 static unsigned int do_csum(const unsigned char *buff, int len)
 {
 	int odd;
@@ -195,8 +204,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr,
 #else
 	s += (proto + len) << 8;
 #endif
-	s += (s >> 32);
-	return (__force __wsum)s;
+	return (__force __wsum)from64to32(s);
 }
 EXPORT_SYMBOL(csum_tcpudp_nofold);
 #endif

^ permalink raw reply

* [PATCH 3.18 20/39] lib/checksum.c: fix carry in csum_tcpudp_nofold
From: Greg Kroah-Hartman @ 2015-02-09  8:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: Greg Kroah-Hartman, stable, Karl Beldan, Al Viro, Eric Dumazet,
	Arnd Bergmann, Mike Frysinger, netdev, Eric Dumazet,
	David S. Miller
In-Reply-To: <20150209083328.753647350@linuxfoundation.org>

3.18-stable review patch.  If anyone has any objections, please let me know.

------------------

From: karl beldan <karl.beldan@gmail.com>

commit 150ae0e94634714b23919f0c333fee28a5b199d5 upstream.

The carry from the 64->32bits folding was dropped, e.g with:
saddr=0xFFFFFFFF daddr=0xFF0000FF len=0xFFFF proto=0 sum=1,
csum_tcpudp_nofold returned 0 instead of 1.

Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 lib/checksum.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

--- a/lib/checksum.c
+++ b/lib/checksum.c
@@ -47,6 +47,15 @@ static inline unsigned short from32to16(
 	return x;
 }
 
+static inline u32 from64to32(u64 x)
+{
+	/* add up 32-bit and 32-bit for 32+c bit */
+	x = (x & 0xffffffff) + (x >> 32);
+	/* add up carry.. */
+	x = (x & 0xffffffff) + (x >> 32);
+	return (u32)x;
+}
+
 static unsigned int do_csum(const unsigned char *buff, int len)
 {
 	int odd;
@@ -195,8 +204,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr,
 #else
 	s += (proto + len) << 8;
 #endif
-	s += (s >> 32);
-	return (__force __wsum)s;
+	return (__force __wsum)from64to32(s);
 }
 EXPORT_SYMBOL(csum_tcpudp_nofold);
 #endif

^ permalink raw reply

* Re: [PATCH v2] brcmfmac: avoid duplicated suspend/resume operation
From: Arend van Spriel @ 2015-02-09  8:36 UTC (permalink / raw)
  To: Fu, Zhonghui
  Cc: Kalle Valo, brudley, Franky Lin, meuleman, linville, pieterpg,
	hdegoede, wens, linux-wireless, brcm80211-dev-list, netdev,
	linux-kernel@vger.kernel.org
In-Reply-To: <54D83AF1.2020501@linux.intel.com>

On 02/09/15 05:43, Fu, Zhonghui wrote:
>  From ff39ed4af9f1c50358fe92ec4c8eaac9db183e00 Mon Sep 17 00:00:00 2001
> From: Zhonghui Fu<zhonghui.fu@linux.intel.com>
> Date: Mon, 26 Jan 2015 10:13:21 +0800
> Subject: [PATCH v2] brcmfmac: avoid duplicated suspend/resume operation
>
> WiFi chip has 2 SDIO functions, and PM core will trigger
> twice suspend/resume operations for one WiFi chip to do
> the same things. This patch avoid this case.

Well, another remark from Kalle was that this patch does not apply to 
wireless-drivers-next/master branch. So I tried to apply this patch and 
it failed. Please rebase this patch.

Regards,
Arend

> Acked-by: Arend van Spriel<arend@broadcom.com>
> Signed-off-by: Zhonghui Fu<zhonghui.fu@linux.intel.com>
> ---
> Changes in v2:
>   - Remove two "Acked-by" lines
>
>   drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c |   17 +++++++++++++++--
>   1 files changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
> index 9880dae..618b545 100644
> --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
> +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
> @@ -1139,11 +1139,17 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
>   static int brcmf_ops_sdio_suspend(struct device *dev)
>   {
>   	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
> -	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
> +	struct brcmf_sdio_dev *sdiodev;
>   	mmc_pm_flag_t sdio_flags;
> +	struct sdio_func *func = dev_to_sdio_func(dev);
>
>   	brcmf_dbg(SDIO, "Enter\n");
>
> +	if (func->num == 2)
> +		return 0;
> +
> +	sdiodev = bus_if->bus_priv.sdio;
> +
>   	atomic_set(&sdiodev->suspend, true);
>
>   	if (sdiodev->wowl_enabled) {
> @@ -1164,9 +1170,16 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
>   static int brcmf_ops_sdio_resume(struct device *dev)
>   {
>   	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
> -	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
> +	struct brcmf_sdio_dev *sdiodev;
> +	struct sdio_func *func = dev_to_sdio_func(dev);
>
>   	brcmf_dbg(SDIO, "Enter\n");
> +
> +	if (func->num == 2)
> +		return 0;
> +
> +	sdiodev = bus_if->bus_priv.sdio;
> +
>   	if (sdiodev->pdata&&  sdiodev->pdata->oob_irq_supported)
>   		disable_irq_wake(sdiodev->pdata->oob_irq_nr);
>   	brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
> -- 1.7.1
>

^ permalink raw reply

* [PATCH RFC v5 net-next 0/6] enable tx interrupts for virtio-net
From: Jason Wang @ 2015-02-09  8:39 UTC (permalink / raw)
  To: netdev, linux-kernel, virtualization, mst; +Cc: pagupta

Hi:

This is a new version of trying to enable tx interrupts for
virtio-net.

We used to try to avoid tx interrupts and orphan packets before
transmission for virtio-net. This breaks socket accounting and can
lead serveral other side effects e.g:

- Several other functions which depends on socket accounting can not
  work  correctly (e.g  TCP Small Queue)
- No tx completion which make BQL or packet generator can not work
  correctly.

This series tries to solve the issue by enabling tx interrupts. To
minize the performance impacts of this, several optimizations were
used:

- In guest side, try to use delayed callbacks as much as possible.
- In host side, try to use interrupt coalescing for reduce tx
  interrupts. About 10% - 15% performance were improved with this.

Perforamnce test shows:
- Very few regression (less than 5%) were noticed TCP_RR on 1 vcpu 1
  queue guest.
- CPU utilization is increased in some cases.
- All other cases, tx interrupts can perform equal or better than
  orphaning (much more obvious when testing small packet transmission
  as a byproduct since socket accounting works for TCP packet).

Changes from RFCv4:
- fix the virtqueue_enable_cb_delayed() return value when only 1
  buffer is pending.
- try to disable callbacks by publish event index in
  virtqueue_disable_cb(). Tests shows about 2% - 3% improvement on
  multiple sessions of TCP_RR.
- Revert some of Micahel's tweaks from RFC v1 (see patch 3 for
  details).
- use netif_wake_subqueue() instead of netif_start_subqueue() in
  free_old_xmit_skbs(), since it may be called in tx napi.
- in start_xmit(), try to enable the callback only when current skb is
  the last in the list or tx has already been stopped. This avoid the
  callbacks enabling in heavy load.
- return ns instead of us in vhost_net_check_coalesce_and_signal()
- measure the time interval of real interrupts instead of calls to
  vhost_signal()
- drop bql from the series since it does not affact performance from
  the test result.
Changes from RFC V3:
- Don't free tx packets in ndo_start_xmit()
- Add interrupt coalescing support for virtio-net
Changes from RFC v2:
- clean up code, address issues raised by Jason
Changes from RFC v1:
- address comments by Jason Wang, use delayed cb everywhere
- rebased Jason's patch on top of mine and include it (with some
tweaks)

Test result:

Environment:
Host: net-next.git
Guest: net-next.git
Qemu: qemu.git
CPU: Two Intel(R) Xeon(R) CPU E5620  @ 2.40GHz
Card: Two Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network
Connection (rev 01) connected back to back
Coalescing in host: rx-usecs: 1
Coalescing in guest:
- none if no tx interrupt
- tx-frames 8 tx-usecs 64
Zerocopy disabled for vhost_net

1 VCPU 1 queue:

Guest TX:
sessions/sizes/+-throughput%/+-cpu%/+-per_cpu_throughput%/
1/64/+41.2/-2.6/+45.1/
2/64/+40.8/-2.7/+44.7/
4/64/+38.5/-2.8/+42.5/
8/64/+36.1/-2.1/+38.9/
1/256/+158.5/-5.0/+172.3/
2/256/+155.3/-4.7/+167.9/
4/256/+156.4/-5.3/+170.6/
8/256/+155.4/-4.9/+168.6/
1/512/+276.5/-3.0/+288.3/
2/512/+280.1/-3.3/+293.1/
4/512/+276.1/-2.7/+286.7/
8/512/+267.1/-3.2/+279.1/
1/1024/+344.0/-6.9/+376.9/
2/1024/+362.3/-2.2/+372.8/
4/1024/+370.4/-1.1/+375.8/
8/1024/+374.0/+0.6/+371.1/
1/4096/+15.1/-30.4/+65.5/
2/4096/+6.3/-32.9/+58.4/
4/4096/+6.9/-32.4/+58.3/
8/4096/+6.7/-26.4/+45.0/
1/16384/-0.6/-4.6/+4.2/
2/16384/+0.0/-5.0/+5.4/
4/16384/+0.0/-2.5/+2.6/
8/16384/-0.0/-13.8/+13.2/
1/65535/-0.5/-0.5/0.0/
2/65535/-0.0/+4.0/-3.9/
4/65535/-0.0/+9.4/-8.6/
8/65535/+0.1/+8.6/-7.8/

TCP_RR:
sessions/sizes/+-throughput%/+-cpu%/+-per_cpu_throughput%/
1/1/-2.4/+16.3/-16.6/
50/1/-3.4/-0.2/-3.2/
1/64/+3.3/+0.7/+2.7/
50/64/-3.6/+0.2/-3.8/
1/256/-0.4/+16.6/-14.7/
50/256/-6.1/+0.2/-6.2/

Guest RX:
sessions/sizes/+-throughput%/+-cpu%/+-per_cpu_throughput%/
1/64/+17.3/+4.9/+10.0/
2/64/+13.8/+1.1/+12.3/
4/64/+3.8/+1.0/+2.7/
8/64/+1.4/+2.1/-0.7
1/256/+24.5/-1.3/+19.1/
2/256/-3.9/+3.8/-7.5/
4/256/-1.3/+1.5/-2.8/
8/256/+1.5/+1.7/-0.2/
1/512/+2.9/+12.7/-8.6/
2/512/-0.0/+3.5/-3.4/
4/512/-1.4/+2.6/-4.0/
8/512/-1.3/+3.1/-4.2/
1/1024/-0.2/+6.0/-5.9/
2/1024/+0.0/+3.1/-3.1/
4/1024/+0.1/+0.9/-0.7/
8/1024/-1.1/-4.1/+3.2/
1/4096/-0.6/+4.0/-4.4/
2/4096/-0.0/+3.6/-3.4/
4/4096/+0.7/+3.8/-3.1/
8/4096/-0.5/+2.4/-2.9/
1/16384/-1.1/+4.9/-5.7/
2/16384/-0.0/+2.4/-2.4/
4/16384/-0.1/+4.7/-4.6/
8/16384/+1.3/-2.0/+3.2/
1/65535/+1.9/+6.0/-3.8/
2/65535/+0.0/+3.3/-3.2/
4/65535/+0.1/+5.1/-4.7/
8/65535/-0.7/+8.0/-8.5/

4 VCPU 1 queue:

Guest TX:
sessions/sizes/+-throughput%/+-cpu%/+-per_cpu_throughput%/
1/64/+45.9/+2.7/+41.9/
2/64/+28.8/+0.2/+28.4/
4/64/+11.2/-0.6/+11.9/
8/64/+10.0/-0.5/+10.6/
1/256/+162.4/+1.0/+160.1/
2/256/+99.7/-0.2/+99.9/
4/256/+10.2/-11.3/+24.2/
8/256/-0.0/-13.8/+16.0/
1/512/+232.4/-0.2/+232.8/
2/512/+105.9/-9.9/+128.5/
4/512/+6.7/-18.8/+31.4/
8/512/+0.0/-21.0/+26.6/
1/1024/+285.1/-2.9/+296.9/
2/1024/+99.3/-22.4/+156.8/
4/1024/+3.7/-24.0/+36.4/
8/1024/+0.1/-23.9/+31.6/
1/4096/+35.9/-17.4/+64.6/
2/4096/+11.4/-27.4/+53.4/
4/4096/+0.1/-36.0/+56.3/
8/4096/+0.0/-34.9/+53.7/
1/16384/-1.8/-9.5/+8.5/
2/16384/+0.0/-2.3/+2.4/
4/16384/+0.0/-3.0/+3.1/
8/16384/+0.1/-0.3/+0.4/
1/65535/-1.1/+3.1/-4.0/
2/65535/+0.0/+5.4/-5.1/
4/65535/+0.0/+7.2/-6.7/
8/65535/-0.0/+7.1/-6.7/

TCP_RR:
sessions/sizes/+-throughput%/+-cpu%/+-per_cpu_throughput%/
1/1/-0.5/+11.7/-11.0/
50/1/-1.9/+2.2/-4.1/
1/64/-0.9/+15.5/-14.3/
50/64/-3.3/+1.3/-4.5/
1/256/+0.6/+5.7/-5.5/
50/256/-1.6/+2.3/-3.8/

Guest RX:
sessions/sizes/+-throughput%/+-cpu%/+-per_cpu_throughput%/
1/64/+12.2/+10.7/+1.3/
2/64/-3.0/+1.9/-4.9/
4/64/+0.9/+0.6/+0.2/
8/64/-2.8/+11.9/-13.6/
1/256/+3.6/-1.8/+10.7/
2/256/+1.9/-0.8/+2.8/
4/256/+0.1/+2.1/-1.9/
8/256/+1.1/+4.3/-2.1/
1/512/+1.5/+1.8/-0.9/
2/512/-0.1/+5.5/-5.3/
4/512/+0.5/+12.9/-11.7/
8/512/+5.5/+10.2/-4.0/
1/1024/+2.6/+6.8/-4.0/
2/1024/-0.0/+3.3/-3.3/
4/1024/+0.1/+5.1/-4.7/
8/1024/+3.6/-2.9/+6.5/
1/4096/+1.0/+7.0/-5.7/
2/4096/-0.0/+1.7/-1.5/
4/4096/+0.1/+3.6/-3.4/
8/4096/-1.0/+2.6/-4.0/
1/16384/+0.6/+3.3/-2.7/
2/16384/+0.0/-2.9/+3.3/
4/16384/+1.5/+1.3/+0.7/
8/16384/+0.5/+8.5/-6.9/
1/65535/+0.5/+2.4/-2.0/
2/65535/+0.0/-1.2/+1.5/
4/65535/+0.1/-4.5/+4.9/
8/65535/+1.4/+7.1/-5.7/

4 VCPU 4 queues:

Guest TX:
sessions/sizes/+-throughput%/+-cpu%/+-per_cpu_throughput%/
1/64/+43.6/-7.9/+56.5/
2/64/+41.7/-3.8/+47.3/
4/64/+43.7/-3.7/+49.3/
8/64/+40.2/-3.5/+45.3/
1/256/+155.9/-2.9/+164.2/
2/256/+160.6/-3.2/+169.1/
4/256/+77.5/-23.2/+131.4/
8/256/+82.5/-21.1/+132.4/
1/512/+214.7/-0.7/+217.9/
2/512/+125.2/-10.1/+151.8/
4/512/+30.4/-37.0/+107.6/
8/512/+0.8/-17.1/+22.9/
1/1024/+250.0/+3.1/+239.5/
2/1024/+83.6/-19.7/+129.0/
4/1024/+18.0/-39.4/+95.2/
8/1024/+1.9/-20.5/+30.3/
1/4096/+26.6/-10.9/+42.1/
2/4096/+0.9/-2.3/+3.9/
4/4096/+0.9/-12.6/+16.8/
8/4096/-0.4/-29.4/+42.1/
1/16384/+12.0/-3.1/+15.9/
2/16384/-2.8/-2.1/+0.5/
4/16384/-1.6/-15.3/+18.2/
8/16384/+0.5/-17.9/+34.5/
1/65535/+12.2/-2.9/+15.8/
2/65535/-4.3/+4.7/-8.6/
4/65535/+1.1/-9.8/+15.9/
8/65535/-1.3/-21.8/+34.1/

TCP_RR:
sessions/sizes/+-throughput%/+-cpu%/+-per_cpu_throughput%/
1/1/+5.4/-0.4/+6.6/
50/1/+6.9/+2.8/+3.9/
1/64/+7.8/+8.4/-1.5/
50/64/+11.1/+0.8/+10.4/
1/256/+3.9/-2.9/+10.3/
50/256/+17.4/+2.7/+14.1/

Guest RX:
sessions/sizes/+-throughput%/+-cpu%/+-per_cpu_throughput%/
1/64/+3.9/+3.8/+9.8/
2/64/-11.0/+11.2/-20.4/
4/64/-5.2/+14.4/-16.6/
8/64/-8.2/+17.2/-21.6/
1/256/+37.3/-32.0/+47.7/
2/256/+16.2/-9.7/+27.7/
4/256/+0.7/+1.5/-0.9/
8/256/+2.1/+8.6/-5.8/
1/512/+2.7/-2.2/+5.5/
2/512/+1.5/+9.4/-7.4/
4/512/-0.0/+10.7/-9.6/
8/512/+4.0/+11.6/-7.0/
1/1024/-3.1/-5.7/+3.2/
2/1024/+0.0/+5.5/-4.9/
4/1024/-0.2/+7.0/-6.9/
8/1024/-1.5/+1.3/-2.6/
1/4096/-1.0/-10.5/+10.6/
2/4096/+0.0/-0.3/+1.0/
4/4096/+0.1/+15.1/-13.0/
8/4096/-1.3/+15.5/-14.6/
1/16384/-0.5/-11.6/+12.5/
2/16384/+0.0/+6.1/-5.9/
4/16384/-1.7/+24.2/-20.5/
8/16384/-2.2/+2.8/-2.6/
1/65535/-0.9/-12.4/+13.0/
2/65535/+0.1/+4.7/-4.3/
4/65535/0.0/+10.6/-9.5/
8/65535/-1.8/+9.4/-10.1/

I've also done test on mlx4, almos the same trends. So not post here.

Thanks

Jason Wang (6):
  virtio_ring: fix virtqueue_enable_cb() when only 1 buffers were
    pending
  virtio_ring: try to disable event index callbacks in
    virtqueue_disable_cb()
  virtio_net: enable tx interrupt
  virtio-net: add basic interrupt coalescing support
  vhost: let vhost_signal() returns whether signalled
  vhost_net: interrupt coalescing support

 drivers/net/virtio_net.c        | 203 +++++++++++++++++++++++++++++++---------
 drivers/vhost/net.c             | 199 +++++++++++++++++++++++++++++++++++++--
 drivers/vhost/vhost.c           |   7 +-
 drivers/vhost/vhost.h           |   2 +-
 drivers/virtio/virtio_ring.c    |   7 +-
 include/uapi/linux/vhost.h      |  12 +++
 include/uapi/linux/virtio_net.h |  12 +++
 7 files changed, 383 insertions(+), 59 deletions(-)

-- 
1.8.3.1

^ permalink raw reply

* [PATCH RFC v5 net-next 1/6] virtio_ring: fix virtqueue_enable_cb() when only 1 buffers were pending
From: Jason Wang @ 2015-02-09  8:39 UTC (permalink / raw)
  To: netdev, linux-kernel, virtualization, mst; +Cc: pagupta
In-Reply-To: <1423471165-34243-1-git-send-email-jasowang@redhat.com>

We currently does:

bufs = (avail->idx - last_used_idx) * 3 / 4;

This is ok now since we only try to enable the delayed callbacks when
the queue is about to be full. This may not work well when there is
only one pending buffer in the virtqueue (this may be the case after
tx interrupt was enabled). Since virtqueue_enable_cb() will return
false which may cause unnecessary triggering of napis. This patch
correct this by only calculate the four thirds when bufs is not one.

Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 drivers/virtio/virtio_ring.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 00ec6b3..545fed5 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -636,7 +636,10 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
 	 * entry. Always do both to keep code simple. */
 	vq->vring.avail->flags &= cpu_to_virtio16(_vq->vdev, ~VRING_AVAIL_F_NO_INTERRUPT);
 	/* TODO: tune this threshold */
-	bufs = (u16)(virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) - vq->last_used_idx) * 3 / 4;
+	bufs = (u16)(virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) -
+		                     vq->last_used_idx);
+	if (bufs != 1)
+		bufs = bufs * 3 / 4;
 	vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx + bufs);
 	virtio_mb(vq->weak_barriers);
 	if (unlikely((u16)(virtio16_to_cpu(_vq->vdev, vq->vring.used->idx) - vq->last_used_idx) > bufs)) {
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH RFC v5 net-next 2/6] virtio_ring: try to disable event index callbacks in virtqueue_disable_cb()
From: Jason Wang @ 2015-02-09  8:39 UTC (permalink / raw)
  To: netdev, linux-kernel, virtualization, mst; +Cc: pagupta
In-Reply-To: <1423471165-34243-1-git-send-email-jasowang@redhat.com>

Currently, we do nothing to prevent the callbacks in
virtqueue_disable_cb() when event index is used. This may cause
spurious interrupts which may damage the performance. This patch tries
to publish avail event as the used even to prevent the callbacks.

Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 drivers/virtio/virtio_ring.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 545fed5..e9ffbfb 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -539,6 +539,8 @@ void virtqueue_disable_cb(struct virtqueue *_vq)
 	struct vring_virtqueue *vq = to_vvq(_vq);
 
 	vq->vring.avail->flags |= cpu_to_virtio16(_vq->vdev, VRING_AVAIL_F_NO_INTERRUPT);
+	vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev,
+						       vq->vring.avail->idx);
 }
 EXPORT_SYMBOL_GPL(virtqueue_disable_cb);
 
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH RFC v5 net-next 3/6] virtio_net: enable tx interrupt
From: Jason Wang @ 2015-02-09  8:39 UTC (permalink / raw)
  To: netdev, linux-kernel, virtualization, mst; +Cc: pagupta
In-Reply-To: <1423471165-34243-1-git-send-email-jasowang@redhat.com>

On newer hosts that support delayed tx interrupts,
we probably don't have much to gain from orphaning
packets early.

Note: this might degrade performance for
hosts without event idx support.
Should be addressed by the next patch.

Signed-off-by: Jason Wang <jasowang@redhat.com>
---
Changes from RFCv4:
- change:
        virtqueue_disable_cb(sq->vq);
        napi_schedule(&sq->napi);

  in skb_xmit_done() to:

  if (__napi_schedule_prep(&sq->napi)) {
     virtqueue_diable_cb(sq->vq);
     __napi_schedule(&sq->napi);
  }

  to solve the race on architectures that atomic operations were not
  serialized. And do solve a similar issue in virtnet_poll_tx().
- use netif_wake_subqueue() instead of netif_start_subqueue() in
  free_old_xmit_skbs(), since it may be called in tx napi.
- in start_xmit(), try to enable the callback only when current skb is
  the last in the list or tx has already been stopped. This avoid the
  callbacks enabling in heavy load.
---
 drivers/net/virtio_net.c | 136 +++++++++++++++++++++++++++++++----------------
 1 file changed, 90 insertions(+), 46 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 11e2e81..cc5f5de 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -72,6 +72,8 @@ struct send_queue {
 
 	/* Name of the send queue: output.$index */
 	char name[40];
+
+	struct napi_struct napi;
 };
 
 /* Internal representation of a receive virtqueue */
@@ -140,6 +142,9 @@ struct virtnet_info {
 
 	/* CPU hot plug notifier */
 	struct notifier_block nb;
+
+	/* Budget for polling tx completion */
+	u32 tx_work_limit;
 };
 
 struct padded_vnet_hdr {
@@ -207,15 +212,43 @@ static struct page *get_a_page(struct receive_queue *rq, gfp_t gfp_mask)
 	return p;
 }
 
+static unsigned int free_old_xmit_skbs(struct netdev_queue *txq,
+				       struct send_queue *sq, int budget)
+{
+	struct sk_buff *skb;
+	unsigned int len;
+	struct virtnet_info *vi = sq->vq->vdev->priv;
+	struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
+	unsigned int packets = 0;
+
+	while (packets < budget &&
+	       (skb = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+		pr_debug("Sent skb %p\n", skb);
+
+		u64_stats_update_begin(&stats->tx_syncp);
+		stats->tx_bytes += skb->len;
+		stats->tx_packets++;
+		u64_stats_update_end(&stats->tx_syncp);
+
+		dev_kfree_skb_any(skb);
+		packets++;
+	}
+
+	if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS)
+		netif_wake_subqueue(vi->dev, vq2txq(sq->vq));
+
+	return packets;
+}
+
 static void skb_xmit_done(struct virtqueue *vq)
 {
 	struct virtnet_info *vi = vq->vdev->priv;
+	struct send_queue *sq = &vi->sq[vq2txq(vq)];
 
-	/* Suppress further interrupts. */
-	virtqueue_disable_cb(vq);
-
-	/* We were probably waiting for more output buffers. */
-	netif_wake_subqueue(vi->dev, vq2txq(vq));
+	if (napi_schedule_prep(&sq->napi)) {
+		virtqueue_disable_cb(sq->vq);
+		__napi_schedule(&sq->napi);
+	}
 }
 
 static unsigned int mergeable_ctx_to_buf_truesize(unsigned long mrg_ctx)
@@ -776,6 +809,30 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
 	return received;
 }
 
+static int virtnet_poll_tx(struct napi_struct *napi, int budget)
+{
+	struct send_queue *sq =
+		container_of(napi, struct send_queue, napi);
+	struct virtnet_info *vi = sq->vq->vdev->priv;
+	struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, vq2txq(sq->vq));
+	u32 limit = vi->tx_work_limit;
+	unsigned int r, sent;
+
+	__netif_tx_lock(txq, smp_processor_id());
+	sent = free_old_xmit_skbs(txq, sq, limit);
+	if (sent < limit) {
+		r = virtqueue_enable_cb_prepare(sq->vq);
+		napi_complete(napi);
+		if (unlikely(virtqueue_poll(sq->vq, r)) &&
+		    napi_schedule_prep(napi)) {
+			virtqueue_disable_cb(sq->vq);
+			__napi_schedule(napi);
+		}
+	}
+	__netif_tx_unlock(txq);
+	return sent < limit ? 0 : budget;
+}
+
 #ifdef CONFIG_NET_RX_BUSY_POLL
 /* must be called with local_bh_disable()d */
 static int virtnet_busy_poll(struct napi_struct *napi)
@@ -824,30 +881,12 @@ static int virtnet_open(struct net_device *dev)
 			if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL))
 				schedule_delayed_work(&vi->refill, 0);
 		virtnet_napi_enable(&vi->rq[i]);
+		napi_enable(&vi->sq[i].napi);
 	}
 
 	return 0;
 }
 
-static void free_old_xmit_skbs(struct send_queue *sq)
-{
-	struct sk_buff *skb;
-	unsigned int len;
-	struct virtnet_info *vi = sq->vq->vdev->priv;
-	struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
-
-	while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) {
-		pr_debug("Sent skb %p\n", skb);
-
-		u64_stats_update_begin(&stats->tx_syncp);
-		stats->tx_bytes += skb->len;
-		stats->tx_packets++;
-		u64_stats_update_end(&stats->tx_syncp);
-
-		dev_kfree_skb_any(skb);
-	}
-}
-
 static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
 {
 	struct virtio_net_hdr_mrg_rxbuf *hdr;
@@ -910,7 +949,9 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
 		sg_set_buf(sq->sg, hdr, hdr_len);
 		num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1;
 	}
-	return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC);
+
+	return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb,
+				    GFP_ATOMIC);
 }
 
 static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -922,8 +963,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct netdev_queue *txq = netdev_get_tx_queue(dev, qnum);
 	bool kick = !skb->xmit_more;
 
-	/* Free up any pending old buffers before queueing new ones. */
-	free_old_xmit_skbs(sq);
+	virtqueue_disable_cb(sq->vq);
 
 	/* Try to transmit */
 	err = xmit_skb(sq, skb);
@@ -939,27 +979,19 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 		return NETDEV_TX_OK;
 	}
 
-	/* Don't wait up for transmitted skbs to be freed. */
-	skb_orphan(skb);
-	nf_reset(skb);
-
 	/* Apparently nice girls don't return TX_BUSY; stop the queue
 	 * before it gets out of hand.  Naturally, this wastes entries. */
-	if (sq->vq->num_free < 2+MAX_SKB_FRAGS) {
+	if (sq->vq->num_free < 2+MAX_SKB_FRAGS)
 		netif_stop_subqueue(dev, qnum);
-		if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
-			/* More just got used, free them then recheck. */
-			free_old_xmit_skbs(sq);
-			if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
-				netif_start_subqueue(dev, qnum);
-				virtqueue_disable_cb(sq->vq);
-			}
-		}
-	}
 
-	if (kick || netif_xmit_stopped(txq))
+	if (kick || netif_xmit_stopped(txq)) {
 		virtqueue_kick(sq->vq);
-
+		if (!virtqueue_enable_cb_delayed(sq->vq) &&
+		    napi_schedule_prep(&sq->napi)) {
+			virtqueue_disable_cb(sq->vq);
+			__napi_schedule(&sq->napi);
+		}
+	}
 	return NETDEV_TX_OK;
 }
 
@@ -1137,8 +1169,10 @@ static int virtnet_close(struct net_device *dev)
 	/* Make sure refill_work doesn't re-enable napi! */
 	cancel_delayed_work_sync(&vi->refill);
 
-	for (i = 0; i < vi->max_queue_pairs; i++)
+	for (i = 0; i < vi->max_queue_pairs; i++) {
 		napi_disable(&vi->rq[i].napi);
+		napi_disable(&vi->sq[i].napi);
+	}
 
 	return 0;
 }
@@ -1451,8 +1485,10 @@ static void virtnet_free_queues(struct virtnet_info *vi)
 {
 	int i;
 
-	for (i = 0; i < vi->max_queue_pairs; i++)
+	for (i = 0; i < vi->max_queue_pairs; i++) {
 		netif_napi_del(&vi->rq[i].napi);
+		netif_napi_del(&vi->sq[i].napi);
+	}
 
 	kfree(vi->rq);
 	kfree(vi->sq);
@@ -1606,6 +1642,8 @@ static int virtnet_alloc_queues(struct virtnet_info *vi)
 		netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll,
 			       napi_weight);
 		napi_hash_add(&vi->rq[i].napi);
+		netif_napi_add(vi->dev, &vi->sq[i].napi, virtnet_poll_tx,
+			       napi_weight);
 
 		sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg));
 		ewma_init(&vi->rq[i].mrg_avg_pkt_len, 1, RECEIVE_AVG_WEIGHT);
@@ -1830,6 +1868,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 	if (err)
 		goto free_stats;
 
+	vi->tx_work_limit = napi_weight;
+
 #ifdef CONFIG_SYSFS
 	if (vi->mergeable_rx_bufs)
 		dev->sysfs_rx_queue_group = &virtio_net_mrg_rx_group;
@@ -1944,8 +1984,10 @@ static int virtnet_freeze(struct virtio_device *vdev)
 	if (netif_running(vi->dev)) {
 		for (i = 0; i < vi->max_queue_pairs; i++) {
 			napi_disable(&vi->rq[i].napi);
+			napi_disable(&vi->sq[i].napi);
 			napi_hash_del(&vi->rq[i].napi);
 			netif_napi_del(&vi->rq[i].napi);
+			netif_napi_del(&vi->sq[i].napi);
 		}
 	}
 
@@ -1970,8 +2012,10 @@ static int virtnet_restore(struct virtio_device *vdev)
 			if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL))
 				schedule_delayed_work(&vi->refill, 0);
 
-		for (i = 0; i < vi->max_queue_pairs; i++)
+		for (i = 0; i < vi->max_queue_pairs; i++) {
 			virtnet_napi_enable(&vi->rq[i]);
+			napi_enable(&vi->sq[i].napi);
+		}
 	}
 
 	netif_device_attach(vi->dev);
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH RFC v5 net-next 4/6] virtio-net: add basic interrupt coalescing support
From: Jason Wang @ 2015-02-09  8:39 UTC (permalink / raw)
  To: netdev, linux-kernel, virtualization, mst; +Cc: pagupta
In-Reply-To: <1423471165-34243-1-git-send-email-jasowang@redhat.com>

This patch enables the interrupt coalescing setting through ethtool.

Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 drivers/net/virtio_net.c        | 67 +++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/virtio_net.h | 12 ++++++++
 2 files changed, 79 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index cc5f5de..2b958fb 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -145,6 +145,11 @@ struct virtnet_info {
 
 	/* Budget for polling tx completion */
 	u32 tx_work_limit;
+
+	__u32 rx_coalesce_usecs;
+	__u32 rx_max_coalesced_frames;
+	__u32 tx_coalesce_usecs;
+	__u32 tx_max_coalesced_frames;
 };
 
 struct padded_vnet_hdr {
@@ -1404,12 +1409,73 @@ static void virtnet_get_channels(struct net_device *dev,
 	channels->other_count = 0;
 }
 
+static int virtnet_set_coalesce(struct net_device *dev,
+				struct ethtool_coalesce *ec)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
+	struct scatterlist sg;
+	struct virtio_net_ctrl_coalesce c;
+
+	if (!vi->has_cvq ||
+	    !virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_COALESCE))
+		return -EOPNOTSUPP;
+	if (vi->rx_coalesce_usecs != ec->rx_coalesce_usecs ||
+	    vi->rx_max_coalesced_frames != ec->rx_max_coalesced_frames) {
+		c.coalesce_usecs = ec->rx_coalesce_usecs;
+		c.max_coalesced_frames = ec->rx_max_coalesced_frames;
+		sg_init_one(&sg, &c, sizeof(c));
+		if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_COALESCE,
+					  VIRTIO_NET_CTRL_COALESCE_RX_SET,
+					  &sg)) {
+			dev_warn(&dev->dev, "Fail to set rx coalescing\n");
+			return -EINVAL;
+		}
+		vi->rx_coalesce_usecs = ec->rx_coalesce_usecs;
+		vi->rx_max_coalesced_frames = ec->rx_max_coalesced_frames;
+	}
+
+	if (vi->tx_coalesce_usecs != ec->tx_coalesce_usecs ||
+	    vi->tx_max_coalesced_frames != ec->tx_max_coalesced_frames) {
+		c.coalesce_usecs = ec->tx_coalesce_usecs;
+		c.max_coalesced_frames = ec->tx_max_coalesced_frames;
+		sg_init_one(&sg, &c, sizeof(c));
+		if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_COALESCE,
+					  VIRTIO_NET_CTRL_COALESCE_TX_SET,
+					  &sg)) {
+			dev_warn(&dev->dev, "Fail to set tx coalescing\n");
+			return -EINVAL;
+		}
+		vi->tx_coalesce_usecs = ec->tx_coalesce_usecs;
+		vi->tx_max_coalesced_frames = ec->tx_max_coalesced_frames;
+	}
+
+	vi->tx_work_limit = ec->tx_max_coalesced_frames_irq;
+
+	return 0;
+}
+
+static int virtnet_get_coalesce(struct net_device *dev,
+				struct ethtool_coalesce *ec)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
+
+	ec->rx_coalesce_usecs = vi->rx_coalesce_usecs;
+	ec->rx_max_coalesced_frames = vi->rx_max_coalesced_frames;
+	ec->tx_coalesce_usecs = vi->tx_coalesce_usecs;
+	ec->tx_max_coalesced_frames = vi->tx_max_coalesced_frames;
+	ec->tx_max_coalesced_frames_irq = vi->tx_work_limit;
+
+	return 0;
+}
+
 static const struct ethtool_ops virtnet_ethtool_ops = {
 	.get_drvinfo = virtnet_get_drvinfo,
 	.get_link = ethtool_op_get_link,
 	.get_ringparam = virtnet_get_ringparam,
 	.set_channels = virtnet_set_channels,
 	.get_channels = virtnet_get_channels,
+	.set_coalesce = virtnet_set_coalesce,
+	.get_coalesce = virtnet_get_coalesce,
 };
 
 #define MIN_MTU 68
@@ -2048,6 +2114,7 @@ static unsigned int features[] = {
 	VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,
 	VIRTIO_NET_F_CTRL_MAC_ADDR,
 	VIRTIO_F_ANY_LAYOUT,
+	VIRTIO_NET_F_CTRL_COALESCE,
 };
 
 static struct virtio_driver virtio_net_driver = {
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index b5f1677..332009d 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -34,6 +34,7 @@
 /* The feature bitmap for virtio net */
 #define VIRTIO_NET_F_CSUM	0	/* Host handles pkts w/ partial csum */
 #define VIRTIO_NET_F_GUEST_CSUM	1	/* Guest handles pkts w/ partial csum */
+#define VIRTIO_NET_F_CTRL_COALESCE 3	/* Set coalescing */
 #define VIRTIO_NET_F_MAC	5	/* Host has given MAC address. */
 #define VIRTIO_NET_F_GSO	6	/* Host handles pkts w/ any GSO type */
 #define VIRTIO_NET_F_GUEST_TSO4	7	/* Guest can handle TSOv4 in. */
@@ -202,4 +203,15 @@ struct virtio_net_ctrl_mq {
  #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN        1
  #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX        0x8000
 
+struct virtio_net_ctrl_coalesce {
+	__u32 coalesce_usecs;
+	__u32 max_coalesced_frames;
+};
+
+#define VIRTIO_NET_CTRL_COALESCE 6
+ #define VIRTIO_NET_CTRL_COALESCE_TX_SET 0
+ #define VIRTIO_NET_CTRL_COALESCE_TX_GET 1
+ #define VIRTIO_NET_CTRL_COALESCE_RX_SET 2
+ #define VIRTIO_NET_CTRL_COALESCE_RX_GET 3
+
 #endif /* _LINUX_VIRTIO_NET_H */
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH RFC v5 net-next 5/6] vhost: let vhost_signal() returns whether signalled
From: Jason Wang @ 2015-02-09  8:39 UTC (permalink / raw)
  To: netdev, linux-kernel, virtualization, mst; +Cc: pagupta, Jason Wang
In-Reply-To: <1423471165-34243-1-git-send-email-jasowang@redhat.com>

Let vhost_signal() return whether or not vhost has injected an
interrupt to guest. This is used for interrupt coalescing
implementation to calculate the interval between two interrupts.

Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 drivers/vhost/vhost.c | 7 +++++--
 drivers/vhost/vhost.h | 2 +-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index cb807d0..20d6b84 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1480,11 +1480,14 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
 }
 
 /* This actually signals the guest, using eventfd. */
-void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq)
+bool vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq)
 {
 	/* Signal the Guest tell them we used something up. */
-	if (vq->call_ctx && vhost_notify(dev, vq))
+	if (vq->call_ctx && vhost_notify(dev, vq)) {
 		eventfd_signal(vq->call_ctx, 1);
+		return true;
+	}
+	return false;
 }
 EXPORT_SYMBOL_GPL(vhost_signal);
 
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 8c1c792..a482563 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -148,7 +148,7 @@ void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *,
 			       unsigned int id, int len);
 void vhost_add_used_and_signal_n(struct vhost_dev *, struct vhost_virtqueue *,
 			       struct vring_used_elem *heads, unsigned count);
-void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
+bool vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
 void vhost_disable_notify(struct vhost_dev *, struct vhost_virtqueue *);
 bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
 
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH RFC v5 net-next 6/6] vhost_net: interrupt coalescing support
From: Jason Wang @ 2015-02-09  8:39 UTC (permalink / raw)
  To: netdev, linux-kernel, virtualization, mst; +Cc: pagupta
In-Reply-To: <1423471165-34243-1-git-send-email-jasowang@redhat.com>

This patch implements interrupt coalescing support for vhost_net. And provides
ioctl()s for userspace to get and set coalescing parameters. Two kinds of
parameters were allowed to be set:

- max_coalesced_frames: which is the maximum numbers of packets were allowed
  before issuing an irq.
- coalesced_usecs: which is the maximum number of micro seconds were allowed
  before issuing an irq if at least one packet were pending.

A per virtqueue hrtimer were used for coalesced_usecs.

Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
Changes from RFCv4:
- return ns instead of us in vhost_net_check_coalesce_and_signal()
- measure the time interval of real interrupts instead of calls to vhost_signal().
---
 drivers/vhost/net.c        | 199 +++++++++++++++++++++++++++++++++++++++++++--
 include/uapi/linux/vhost.h |  12 +++
 2 files changed, 202 insertions(+), 9 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 6906f76..3222ac9 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -18,6 +18,7 @@
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/timer.h>
 
 #include <linux/net.h>
 #include <linux/if_packet.h>
@@ -62,7 +63,8 @@ enum {
 	VHOST_NET_FEATURES = VHOST_FEATURES |
 			 (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) |
 			 (1ULL << VIRTIO_NET_F_MRG_RXBUF) |
-			 (1ULL << VIRTIO_F_VERSION_1),
+			 (1ULL << VIRTIO_F_VERSION_1) |
+			 (1ULL << VIRTIO_NET_F_CTRL_COALESCE),
 };
 
 enum {
@@ -100,6 +102,15 @@ struct vhost_net_virtqueue {
 	/* Reference counting for outstanding ubufs.
 	 * Protected by vq mutex. Writers must also take device mutex. */
 	struct vhost_net_ubuf_ref *ubufs;
+	/* Microseconds after at least 1 paket is processed before
+	 * generating an interrupt.
+	 */
+	__u32 coalesce_usecs;
+	/* Packets are processed before genearting an interrupt. */
+	__u32 max_coalesced_frames;
+	__u32 coalesced;
+	ktime_t last_signal;
+	struct hrtimer c_timer;
 };
 
 struct vhost_net {
@@ -197,11 +208,16 @@ static void vhost_net_vq_reset(struct vhost_net *n)
 	vhost_net_clear_ubuf_info(n);
 
 	for (i = 0; i < VHOST_NET_VQ_MAX; i++) {
+		hrtimer_cancel(&n->vqs[i].c_timer);
 		n->vqs[i].done_idx = 0;
 		n->vqs[i].upend_idx = 0;
 		n->vqs[i].ubufs = NULL;
 		n->vqs[i].vhost_hlen = 0;
 		n->vqs[i].sock_hlen = 0;
+		n->vqs[i].max_coalesced_frames = 0;
+		n->vqs[i].coalesce_usecs = 0;
+		n->vqs[i].last_signal = ktime_get();
+		n->vqs[i].coalesced = 0;
 	}
 
 }
@@ -273,6 +289,55 @@ static void copy_iovec_hdr(const struct iovec *from, struct iovec *to,
 	}
 }
 
+static int vhost_net_check_coalesce_and_signal(struct vhost_dev *dev,
+					       struct vhost_net_virtqueue *nvq)
+{
+	struct vhost_virtqueue *vq = &nvq->vq;
+	int left = 0;
+	ktime_t now;
+
+	if (nvq->coalesced) {
+		now = ktime_get();
+		left = nvq->coalesce_usecs -
+		       ktime_to_us(ktime_sub(now, nvq->last_signal));
+		if (left <= 0) {
+			vhost_signal(dev, vq);
+			nvq->last_signal = now;
+			nvq->coalesced = 0;
+		}
+	}
+
+	return left * NSEC_PER_USEC;
+}
+
+static bool vhost_net_add_used_and_signal_n(struct vhost_dev *dev,
+					    struct vhost_net_virtqueue *nvq,
+					    struct vring_used_elem *heads,
+					    unsigned count)
+{
+	struct vhost_virtqueue *vq = &nvq->vq;
+	bool can_coalesce = nvq->max_coalesced_frames && nvq->coalesce_usecs;
+	bool ret = false;
+
+	vhost_add_used_n(vq, heads, count);
+
+	if (can_coalesce) {
+		ktime_t now = ktime_get();
+
+		nvq->coalesced += count;
+		if (((nvq->coalesced >= nvq->max_coalesced_frames) ||
+		     (ktime_to_us(ktime_sub(now, nvq->last_signal)) >=
+		      nvq->coalesce_usecs)) && vhost_signal(dev, vq)) {
+			nvq->coalesced = 0;
+			nvq->last_signal = now;
+			ret = true;
+		}
+	} else {
+		vhost_signal(dev, vq);
+	}
+	return ret;
+}
+
 /* In case of DMA done not in order in lower device driver for some reason.
  * upend_idx is used to track end of used idx, done_idx is used to track head
  * of used idx. Once lower device DMA done contiguously, we will signal KVM
@@ -297,8 +362,8 @@ static void vhost_zerocopy_signal_used(struct vhost_net *net,
 	}
 	while (j) {
 		add = min(UIO_MAXIOV - nvq->done_idx, j);
-		vhost_add_used_and_signal_n(vq->dev, vq,
-					    &vq->heads[nvq->done_idx], add);
+		vhost_net_add_used_and_signal_n(vq->dev, nvq,
+						&vq->heads[nvq->done_idx], add);
 		nvq->done_idx = (nvq->done_idx + add) % UIO_MAXIOV;
 		j -= add;
 	}
@@ -351,6 +416,7 @@ static void handle_tx(struct vhost_net *net)
 	struct socket *sock;
 	struct vhost_net_ubuf_ref *uninitialized_var(ubufs);
 	bool zcopy, zcopy_used;
+	int left;
 
 	mutex_lock(&vq->mutex);
 	sock = vq->private_data;
@@ -362,6 +428,8 @@ static void handle_tx(struct vhost_net *net)
 	hdr_size = nvq->vhost_hlen;
 	zcopy = nvq->ubufs;
 
+	vhost_net_check_coalesce_and_signal(&net->dev, nvq);
+
 	for (;;) {
 		/* Release DMAs done buffers first */
 		if (zcopy)
@@ -444,10 +512,15 @@ static void handle_tx(struct vhost_net *net)
 		if (err != len)
 			pr_debug("Truncated TX packet: "
 				 " len %d != %zd\n", err, len);
-		if (!zcopy_used)
-			vhost_add_used_and_signal(&net->dev, vq, head, 0);
-		else
+
+		if (!zcopy_used) {
+			struct vring_used_elem heads = { head, 0 };
+
+			vhost_net_add_used_and_signal_n(&net->dev,
+							nvq, &heads, 1);
+		} else {
 			vhost_zerocopy_signal_used(net, vq);
+		}
 		total_len += len;
 		vhost_net_tx_packet(net);
 		if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
@@ -455,6 +528,12 @@ static void handle_tx(struct vhost_net *net)
 			break;
 		}
 	}
+
+	left = vhost_net_check_coalesce_and_signal(&net->dev, nvq);
+	if (left > 0)
+		hrtimer_start(&nvq->c_timer, ns_to_ktime(left),
+			      HRTIMER_MODE_REL);
+
 out:
 	mutex_unlock(&vq->mutex);
 }
@@ -574,7 +653,7 @@ static void handle_rx(struct vhost_net *net)
 		.hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
 	};
 	size_t total_len = 0;
-	int err, mergeable;
+	int err, mergeable, left;
 	s16 headcount;
 	size_t vhost_hlen, sock_hlen;
 	size_t vhost_len, sock_len;
@@ -593,6 +672,8 @@ static void handle_rx(struct vhost_net *net)
 		vq->log : NULL;
 	mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF);
 
+	vhost_net_check_coalesce_and_signal(&net->dev, nvq);
+
 	while ((sock_len = peek_head_len(sock->sk))) {
 		sock_len += sock_hlen;
 		vhost_len = sock_len + vhost_hlen;
@@ -658,8 +739,10 @@ static void handle_rx(struct vhost_net *net)
 			vhost_discard_vq_desc(vq, headcount);
 			break;
 		}
-		vhost_add_used_and_signal_n(&net->dev, vq, vq->heads,
-					    headcount);
+
+		vhost_net_add_used_and_signal_n(&net->dev, nvq,
+						vq->heads, headcount);
+
 		if (unlikely(vq_log))
 			vhost_log_write(vq, vq_log, log, vhost_len);
 		total_len += vhost_len;
@@ -668,6 +751,12 @@ static void handle_rx(struct vhost_net *net)
 			break;
 		}
 	}
+
+	left = vhost_net_check_coalesce_and_signal(&net->dev, nvq);
+	if (left > 0)
+		hrtimer_start(&nvq->c_timer, ms_to_ktime(left),
+			HRTIMER_MODE_REL);
+
 out:
 	mutex_unlock(&vq->mutex);
 }
@@ -704,6 +793,18 @@ static void handle_rx_net(struct vhost_work *work)
 	handle_rx(net);
 }
 
+static enum hrtimer_restart vhost_net_timer_handler(struct hrtimer *timer)
+{
+	struct vhost_net_virtqueue *nvq = container_of(timer,
+						struct vhost_net_virtqueue,
+						c_timer);
+	struct vhost_virtqueue *vq = &nvq->vq;
+
+	vhost_poll_queue(&vq->poll);
+
+	return HRTIMER_NORESTART;
+}
+
 static int vhost_net_open(struct inode *inode, struct file *f)
 {
 	struct vhost_net *n;
@@ -735,6 +836,13 @@ static int vhost_net_open(struct inode *inode, struct file *f)
 		n->vqs[i].done_idx = 0;
 		n->vqs[i].vhost_hlen = 0;
 		n->vqs[i].sock_hlen = 0;
+		n->vqs[i].max_coalesced_frames = 0;
+		n->vqs[i].coalesce_usecs = 0;
+		n->vqs[i].last_signal = ktime_get();
+		n->vqs[i].coalesced = 0;
+		hrtimer_init(&n->vqs[i].c_timer, CLOCK_MONOTONIC,
+			     HRTIMER_MODE_REL);
+		n->vqs[i].c_timer.function = vhost_net_timer_handler;
 	}
 	vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX);
 
@@ -911,6 +1019,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
 	struct vhost_virtqueue *vq;
 	struct vhost_net_virtqueue *nvq;
 	struct vhost_net_ubuf_ref *ubufs, *oldubufs = NULL;
+	unsigned int coalesced;
 	int r;
 
 	mutex_lock(&n->dev.mutex);
@@ -939,6 +1048,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
 
 	/* start polling new socket */
 	oldsock = vq->private_data;
+	coalesced = nvq->coalesced;
 	if (sock != oldsock) {
 		ubufs = vhost_net_ubuf_alloc(vq,
 					     sock && vhost_sock_zcopy(sock));
@@ -973,6 +1083,12 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
 		mutex_unlock(&vq->mutex);
 	}
 
+	if (coalesced) {
+		mutex_lock(&vq->mutex);
+		vhost_signal(&n->dev, vq);
+		mutex_unlock(&vq->mutex);
+	}
+
 	if (oldsock) {
 		vhost_net_flush_vq(n, index);
 		sockfd_put(oldsock);
@@ -1080,6 +1196,67 @@ out:
 	return r;
 }
 
+static long vhost_net_set_vring_coalesce(struct vhost_dev *d, void __user *argp)
+{
+	u32 __user *idxp = argp;
+	u32 idx;
+	int r;
+	struct vhost_virtqueue *vq;
+	struct vhost_net_vring_coalesce c;
+	struct vhost_net_virtqueue *nvq;
+
+	r = get_user(idx, idxp);
+	if (r < 0)
+		return r;
+	if (idx >= d->nvqs)
+		return -ENOBUFS;
+
+	vq = d->vqs[idx];
+	nvq = container_of(vq, struct vhost_net_virtqueue, vq);
+
+	r = copy_from_user(&c, argp, sizeof(c));
+	if (r < 0)
+		return r;
+
+	mutex_lock(&vq->mutex);
+	nvq->coalesce_usecs = c.coalesce_usecs;
+	nvq->max_coalesced_frames = c.max_coalesced_frames;
+	mutex_unlock(&vq->mutex);
+
+	return 0;
+}
+
+static long vhost_net_get_vring_coalesce(struct vhost_dev *d, void __user *argp)
+{
+	u32 __user *idxp = argp;
+	u32 idx;
+	int r;
+	struct vhost_virtqueue *vq;
+	struct vhost_net_vring_coalesce c;
+	struct vhost_net_virtqueue *nvq;
+
+	r = get_user(idx, idxp);
+	if (r < 0)
+		return r;
+	if (idx >= d->nvqs)
+		return -ENOBUFS;
+
+	vq = d->vqs[idx];
+	nvq = container_of(vq, struct vhost_net_virtqueue, vq);
+
+	mutex_lock(&vq->mutex);
+	c.index = idx;
+	c.coalesce_usecs = nvq->coalesce_usecs;
+	c.max_coalesced_frames = nvq->max_coalesced_frames;
+	mutex_unlock(&vq->mutex);
+
+	r = copy_to_user(argp, &c, sizeof(c));
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
 static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
 			    unsigned long arg)
 {
@@ -1110,6 +1287,10 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
 		return vhost_net_reset_owner(n);
 	case VHOST_SET_OWNER:
 		return vhost_net_set_owner(n);
+	case VHOST_NET_SET_VRING_COALESCE:
+		return vhost_net_set_vring_coalesce(&n->dev, argp);
+	case VHOST_NET_GET_VRING_COALESCE:
+		return vhost_net_get_vring_coalesce(&n->dev, argp);
 	default:
 		mutex_lock(&n->dev.mutex);
 		r = vhost_dev_ioctl(&n->dev, ioctl, argp);
diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
index bb6a5b4..6799cc1 100644
--- a/include/uapi/linux/vhost.h
+++ b/include/uapi/linux/vhost.h
@@ -27,6 +27,12 @@ struct vhost_vring_file {
 
 };
 
+struct vhost_net_vring_coalesce {
+	unsigned int index;
+	__u32 coalesce_usecs;
+	__u32 max_coalesced_frames;
+};
+
 struct vhost_vring_addr {
 	unsigned int index;
 	/* Option flags. */
@@ -121,6 +127,12 @@ struct vhost_memory {
  * device.  This can be used to stop the ring (e.g. for migration). */
 #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
 
+/* Setting interrupt coalescing parameters. */
+#define VHOST_NET_SET_VRING_COALESCE \
+	_IOW(VHOST_VIRTIO, 0x31, struct vhost_net_vring_coalesce)
+/* Getting interrupt coalescing parameters. */
+#define VHOST_NET_GET_VRING_COALESCE \
+	_IOW(VHOST_VIRTIO, 0x32, struct vhost_net_vring_coalesce)
 /* Feature bits */
 /* Log all write descriptors. Can be changed while device is active. */
 #define VHOST_F_LOG_ALL 26
-- 
1.8.3.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox