Netdev List
 help / color / mirror / Atom feed
* [net-next 00/13][pull request] Intel Wired LAN Driver Updates
From: Jeff Kirsher @ 2012-10-30  7:04 UTC (permalink / raw)
  To: davem; +Cc: Jeff Kirsher, netdev, gospo, sassmann

This series contains updates to ixgbe, ixgbevf, igbvf, igb and
networking core (bridge).  Most notably is the addition of support
for local link multicast addresses in SR-IOV mode to the networking
core.

Also note, the ixgbe patch "ixgbe: Add support for pipeline reset" and
"ixgbe: Fix return value from macvlan filter function" is revised based
on community feedback.

The following are changes since commit a932657f51eadb8280166e82dc7034dfbff3985a:
  net: sierra: shut up sparse restricted type warnings
and are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next master

Alexander Duyck (2):
  ixgbe: Do not decrement budget in ixgbe_clean_rx_irq
  igb: Fix sparse warning in igb_ptp_rx_pktstamp

Carolyn Wyborny (1):
  igb: Update firmware version info for ethtool output.

Don Skidmore (1):
  ixgbe: Add support for pipeline reset

Emil Tantilov (1):
  ixgbe: clean up the condition for turning on/off the laser

Greg Rose (4):
  ixgbe: Fix return value from macvlan filter function
  ixgbe: Return success or failure on VF MAC filter set
  ixgbevf: Do not forward LLDP type frames
  igbvf: Check for error on dma_map_single call

Jiri Benc (1):
  ixgbe: reduce PTP rx path overhead

John Fastabend (1):
  net, ixgbe: handle link local multicast addresses in SR-IOV mode

Josh Hay (1):
  ixgbe: add/update descriptor maps in comments

Matthew Vick (1):
  igb: Enable auto-crossover during forced operation on 82580 and
    above.

 drivers/net/ethernet/intel/igb/e1000_defines.h    |  14 +++
 drivers/net/ethernet/intel/igb/e1000_mac.c        |   4 +
 drivers/net/ethernet/intel/igb/e1000_nvm.c        |  70 +++++++++++++
 drivers/net/ethernet/intel/igb/e1000_nvm.h        |  16 +++
 drivers/net/ethernet/intel/igb/e1000_phy.c        |  29 +++---
 drivers/net/ethernet/intel/igb/igb_main.c         |  76 +++++----------
 drivers/net/ethernet/intel/igb/igb_ptp.c          |   2 +-
 drivers/net/ethernet/intel/igbvf/netdev.c         |  13 +++
 drivers/net/ethernet/intel/ixgbe/ixgbe.h          |   1 +
 drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c    | 114 ++++++++++++++++------
 drivers/net/ethernet/intel/ixgbe/ixgbe_common.c   |  70 ++++++++++++-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     | 103 ++++++++++++-------
 drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c      |   6 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c    |   5 +-
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   5 +
 drivers/net/ethernet/intel/ixgbevf/vf.c           |   3 +
 include/linux/etherdevice.h                       |  19 ++++
 net/bridge/br_device.c                            |   2 +-
 net/bridge/br_input.c                             |  15 ---
 net/bridge/br_private.h                           |   1 -
 net/bridge/br_sysfs_br.c                          |   3 +-
 21 files changed, 419 insertions(+), 152 deletions(-)

-- 
1.7.11.7

^ permalink raw reply

* [net-next 01/13] ixgbe: Add support for pipeline reset
From: Jeff Kirsher @ 2012-10-30  7:04 UTC (permalink / raw)
  To: davem; +Cc: Don Skidmore, netdev, gospo, sassmann, Martin Josefsson,
	Jeff Kirsher
In-Reply-To: <1351580670-8292-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Don Skidmore <donald.c.skidmore@intel.com>

Calling the ixgbe_reset_pipeline_82599 function will ensure a full pipeline
reset on all 82599 devices.  This is necessary to avoid possible link issues.
Since this patch accomplishes this by modifying AUTOC.LMS we need to wrap
all AUTOC writes when LESM is enabled.

v2- fix LMS behaviour based on feedback by Martin Josefsson

CC: Martin Josefsson <gandalf@mjufs.se>
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe.h        |   1 +
 drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c  | 114 ++++++++++++++++++------
 drivers/net/ethernet/intel/ixgbe/ixgbe_common.c |  70 ++++++++++++++-
 3 files changed, 153 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index c64a777..a17116b 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -693,6 +693,7 @@ extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
 						 u16 soft_id);
 extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
 						 union ixgbe_atr_input *mask);
+extern bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
 extern void ixgbe_set_rx_mode(struct net_device *netdev);
 #ifdef CONFIG_IXGBE_DCB
 extern void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index b527813..e75f5a4 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -62,7 +62,6 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
                                          bool autoneg,
                                          bool autoneg_wait_to_complete);
 static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
-static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
 
 static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 {
@@ -99,9 +98,8 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 {
 	s32 ret_val = 0;
-	u32 reg_anlp1 = 0;
-	u32 i = 0;
 	u16 list_offset, data_offset, data_value;
+	bool got_lock = false;
 
 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
 		ixgbe_init_mac_link_ops_82599(hw);
@@ -137,28 +135,36 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 		usleep_range(hw->eeprom.semaphore_delay * 1000,
 			     hw->eeprom.semaphore_delay * 2000);
 
-		/* Now restart DSP by setting Restart_AN and clearing LMS */
-		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((IXGBE_READ_REG(hw,
-		                IXGBE_AUTOC) & ~IXGBE_AUTOC_LMS_MASK) |
-		                IXGBE_AUTOC_AN_RESTART));
-
-		/* Wait for AN to leave state 0 */
-		for (i = 0; i < 10; i++) {
-			usleep_range(4000, 8000);
-			reg_anlp1 = IXGBE_READ_REG(hw, IXGBE_ANLP1);
-			if (reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)
-				break;
+		/* Need SW/FW semaphore around AUTOC writes if LESM on,
+		 * likewise reset_pipeline requires lock as it also writes
+		 * AUTOC.
+		 */
+		if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+			ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+			if (ret_val)
+				goto setup_sfp_out;
+
+			got_lock = true;
+		}
+
+		/* Restart DSP and set SFI mode */
+		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw,
+				IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL));
+
+		ret_val = ixgbe_reset_pipeline_82599(hw);
+
+		if (got_lock) {
+			hw->mac.ops.release_swfw_sync(hw,
+						      IXGBE_GSSR_MAC_CSR_SM);
+			got_lock = false;
 		}
-		if (!(reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)) {
-			hw_dbg(hw, "sfp module setup not complete\n");
+
+		if (ret_val) {
+			hw_dbg(hw, " sfp module setup not complete\n");
 			ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
 			goto setup_sfp_out;
 		}
-
-		/* Restart DSP by setting Restart_AN and return to SFI mode */
-		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw,
-		                IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL |
-		                IXGBE_AUTOC_AN_RESTART));
 	}
 
 setup_sfp_out:
@@ -394,14 +400,26 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
 	u32 links_reg;
 	u32 i;
 	s32 status = 0;
+	bool got_lock = false;
+
+	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+		status = hw->mac.ops.acquire_swfw_sync(hw,
+						IXGBE_GSSR_MAC_CSR_SM);
+		if (status)
+			goto out;
+
+		got_lock = true;
+	}
 
 	/* Restart link */
-	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
-	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+	ixgbe_reset_pipeline_82599(hw);
+
+	if (got_lock)
+		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
 
 	/* Only poll for autoneg to complete if specified to do so */
 	if (autoneg_wait_to_complete) {
+		autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 		if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
 		     IXGBE_AUTOC_LMS_KX4_KX_KR ||
 		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
@@ -425,6 +443,7 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
 	/* Add delay to filter out noises during initial link setup */
 	msleep(50);
 
+out:
 	return status;
 }
 
@@ -779,6 +798,7 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 	u32 links_reg;
 	u32 i;
 	ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
+	bool got_lock = false;
 
 	/* Check to see if speed passed in is supported. */
 	status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities,
@@ -836,9 +856,26 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 	}
 
 	if (autoc != start_autoc) {
+		/* Need SW/FW semaphore around AUTOC writes if LESM is on,
+		 * likewise reset_pipeline requires us to hold this lock as
+		 * it also writes to AUTOC.
+		 */
+		if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+			status = hw->mac.ops.acquire_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+			if (status != 0)
+				goto out;
+
+			got_lock = true;
+		}
+
 		/* Restart link */
-		autoc |= IXGBE_AUTOC_AN_RESTART;
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
+		ixgbe_reset_pipeline_82599(hw);
+
+		if (got_lock)
+			hw->mac.ops.release_swfw_sync(hw,
+						      IXGBE_GSSR_MAC_CSR_SM);
 
 		/* Only poll for autoneg to complete if specified to do so */
 		if (autoneg_wait_to_complete) {
@@ -994,9 +1031,28 @@ mac_reset_top:
 		hw->mac.orig_autoc2 = autoc2;
 		hw->mac.orig_link_settings_stored = true;
 	} else {
-		if (autoc != hw->mac.orig_autoc)
-			IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc |
-			                IXGBE_AUTOC_AN_RESTART));
+		if (autoc != hw->mac.orig_autoc) {
+			/* Need SW/FW semaphore around AUTOC writes if LESM is
+			 * on, likewise reset_pipeline requires us to hold
+			 * this lock as it also writes to AUTOC.
+			 */
+			bool got_lock = false;
+			if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+				status = hw->mac.ops.acquire_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+				if (status)
+					goto reset_hw_out;
+
+				got_lock = true;
+			}
+
+			IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
+			ixgbe_reset_pipeline_82599(hw);
+
+			if (got_lock)
+				hw->mac.ops.release_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+		}
 
 		if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
 		    (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
@@ -1983,7 +2039,7 @@ fw_version_out:
  *  Returns true if the LESM FW module is present and enabled. Otherwise
  *  returns false. Smart Speed must be disabled if LESM FW module is enabled.
  **/
-static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
+bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
 {
 	bool lesm_enabled = false;
 	u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index a2a9bcc..8f285ed 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -90,6 +90,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
 	s32 ret_val = 0;
 	u32 reg = 0, reg_bp = 0;
 	u16 reg_cu = 0;
+	bool got_lock = false;
 
 	/*
 	 * Validate the requested mode.  Strict IEEE mode does not allow
@@ -210,8 +211,29 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
 	 *
 	 */
 	if (hw->phy.media_type == ixgbe_media_type_backplane) {
-		reg_bp |= IXGBE_AUTOC_AN_RESTART;
+		/* Need the SW/FW semaphore around AUTOC writes if 82599 and
+		 * LESM is on, likewise reset_pipeline requries the lock as
+		 * it also writes AUTOC.
+		 */
+		if ((hw->mac.type == ixgbe_mac_82599EB) &&
+		    ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+			ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+			if (ret_val)
+				goto out;
+
+			got_lock = true;
+		}
+
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+
+		if (hw->mac.type == ixgbe_mac_82599EB)
+			ixgbe_reset_pipeline_82599(hw);
+
+		if (got_lock)
+			hw->mac.ops.release_swfw_sync(hw,
+						      IXGBE_GSSR_MAC_CSR_SM);
+
 	} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
 		    (ixgbe_device_supports_autoneg_fc(hw) == 0)) {
 		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
@@ -2616,6 +2638,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 	bool link_up = false;
 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+	s32 ret_val = 0;
 
 	/*
 	 * Link must be up to auto-blink the LEDs;
@@ -2624,10 +2647,28 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
 
 	if (!link_up) {
+		/* Need the SW/FW semaphore around AUTOC writes if 82599 and
+		 * LESM is on.
+		 */
+		bool got_lock = false;
+
+		if ((hw->mac.type == ixgbe_mac_82599EB) &&
+		    ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+			ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+			if (ret_val)
+				goto out;
+
+			got_lock = true;
+		}
 		autoc_reg |= IXGBE_AUTOC_AN_RESTART;
 		autoc_reg |= IXGBE_AUTOC_FLU;
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
 		IXGBE_WRITE_FLUSH(hw);
+
+		if (got_lock)
+			hw->mac.ops.release_swfw_sync(hw,
+						      IXGBE_GSSR_MAC_CSR_SM);
 		usleep_range(10000, 20000);
 	}
 
@@ -2636,7 +2677,8 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
 	IXGBE_WRITE_FLUSH(hw);
 
-	return 0;
+out:
+	return ret_val;
 }
 
 /**
@@ -2648,18 +2690,40 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
 {
 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+	s32 ret_val = 0;
+	bool got_lock = false;
+
+	/* Need the SW/FW semaphore around AUTOC writes if 82599 and
+	 * LESM is on.
+	 */
+	if ((hw->mac.type == ixgbe_mac_82599EB) &&
+	    ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+						IXGBE_GSSR_MAC_CSR_SM);
+		if (ret_val)
+			goto out;
+
+		got_lock = true;
+	}
 
 	autoc_reg &= ~IXGBE_AUTOC_FLU;
 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
 
+	if (hw->mac.type == ixgbe_mac_82599EB)
+		ixgbe_reset_pipeline_82599(hw);
+
+	if (got_lock)
+		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+
 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
 	led_reg &= ~IXGBE_LED_BLINK(index);
 	led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
 	IXGBE_WRITE_FLUSH(hw);
 
-	return 0;
+out:
+	return ret_val;
 }
 
 /**
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH 1/1] net: fix compile warning in af_unix.c
From: Jing Wang @ 2012-10-30  7:16 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Al Viro, Pavel Emelyanov; +Cc: netdev, Jing Wang

This patch fix some compile warning as follows:
net/unix/af_unix.c: In function 'unix_bind':
net/unix/af_unix.c:895: warning: 'path.dentry' may be used uninitialized in this function
net/unix/af_unix.c:895: warning: 'path.mnt' may be used uninitialized in this function

Signed-off-by: Jing Wang <windsdaemon@gmail.com>
---
 net/unix/af_unix.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 5b5c876..9f710ac 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -895,6 +895,8 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 		struct path path;
 		umode_t mode = S_IFSOCK |
 		       (SOCK_INODE(sock)->i_mode & ~current_umask());
+		path.mnt = NULL;
+		path.dentry = NULL;
 		err = unix_mknod(sun_path, mode, &path);
 		if (err) {
 			if (err == -EEXIST)
-- 
1.7.5.4

^ permalink raw reply related

* Re: [PATCH] net: dsa/slave: Fix compilation warnings
From: Viresh Kumar @ 2012-10-30  7:31 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: davem, linaro-dev, patches, netdev, linux-kernel
In-Reply-To: <CAKohponL_3m2KVytiWm8ZHyB5aimk8CzGrqr5J0LMy8MFGodHg@mail.gmail.com>

On 30 October 2012 12:15, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> And so, if we select NET_DSA from these tagging drivers, then only slave.c will
> get compiled. Otherwise slave.c dsa.c dsa_core.c wouldn't be compiled and so
> no warnings.

If my above explanation/assumption is correct, then please review following
patch:

--------------------------x-----------------------x----------------

From: Viresh Kumar <viresh.kumar@linaro.org>
Date: Mon, 29 Oct 2012 22:19:14 +0530
Subject: [PATCH] net: dsa/slave: Fix compilation warnings

Currently when none of CONFIG_NET_DSA_TAG_DSA, CONFIG_NET_DSA_TAG_EDSA and
CONFIG_NET_DSA_TAG_TRAILER is defined, we get following compilation warnings:

net/dsa/slave.c:51:12: warning: 'dsa_slave_init' defined but not used
[-Wunused-function]
net/dsa/slave.c:60:12: warning: 'dsa_slave_open' defined but not used
[-Wunused-function]
net/dsa/slave.c:98:12: warning: 'dsa_slave_close' defined but not used
[-Wunused-function]
net/dsa/slave.c:116:13: warning: 'dsa_slave_change_rx_flags' defined
but not used [-Wunused-function]
net/dsa/slave.c:127:13: warning: 'dsa_slave_set_rx_mode' defined but
not used [-Wunused-function]
net/dsa/slave.c:136:12: warning: 'dsa_slave_set_mac_address' defined
but not used [-Wunused-function]
net/dsa/slave.c:164:12: warning: 'dsa_slave_ioctl' defined but not
used [-Wunused-function]

Earlier approach to fix this was discussed here:

lkml.org/lkml/2012/10/29/549

This is another approach to fix it. This is done by some changes in config
options, which make more sense than the earlier approach. As, atleast one
tagging option must always be selected for using net/dsa/ infrastructure, this
patch selects NET_DSA from tagging configs instead of having it as an selectable
config.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/net/dsa/Kconfig |  1 -
 net/dsa/Kconfig         | 16 +++++++++-------
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index dd151d5..96eae22 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -1,5 +1,4 @@
 menu "Distributed Switch Architecture drivers"
-	depends on NET_DSA

 config NET_DSA_MV88E6XXX
 	tristate
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 274791c..f7c6cef 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -1,5 +1,5 @@
 config NET_DSA
-	tristate "Distributed Switch Architecture support"
+	tristate
 	default n
 	depends on EXPERIMENTAL && NETDEVICES && !S390
 	select PHYLIB
@@ -8,19 +8,21 @@ config NET_DSA
 	  the Distributed Switch Architecture.


-if NET_DSA
+menu "Distributed Switch Architecture support"

 # tagging formats
 config NET_DSA_TAG_DSA
-	bool
+	bool "Original DSA packet tagging format"
+	select NET_DSt
 	default n

 config NET_DSA_TAG_EDSA
-	bool
+	bool "Ethertype DSA packet tagging format"
+	select NET_DSA
 	default n

 config NET_DSA_TAG_TRAILER
-	bool
+	bool "Trailer DSA packet tagging format"
+	select NET_DSA
 	default n
-
-endif
+endmenu

^ permalink raw reply related

* WARNING: at net/core/skbuff.c:573
From: Haggai Eran @ 2012-10-30  7:47 UTC (permalink / raw)
  To: netdev
In-Reply-To: <B855DA7245737D4B83EDD9C0B7698E652B7D29DA@MTRDAG01.mtl.com>

Hi,

Running kernel v3.7-rc2 I'm getting these warnings at
skb_release_head_state. It is called from netconsole, due to printk
from mlx4_core's interrupt handler. The warning is due to the function 
being run in interrupt context. However, according to the documentation,
netconsole is supposed to be fine running from within interrupts.

I'm not sure I can reproduce it reliably though.

Haggai

[73550.981930] ------------[ cut here ]------------
[73550.981933] WARNING: at net/core/skbuff.c:573 skb_release_head_state+0x10f/0x120()
[73550.981933] Hardware name: PowerEdge R710
[73550.981961] Modules linked in: rdma_ucm rdma_cm iw_cm ib_addr ib_ipoib ib_cm ib_uverbs ib_umad mlx4_ib ib_sa ib_mad ib_core mlx4_en mlx4_core mmu_trace(O) mst_pciconf(O) mst_pci(O) netconsole configfs nfsv3 nfs_acl nfsv4 auth_rpcgss nfs fscache lockd autofs4 sunrpc ipv6 dm_mirror dm_region_hash dm_log dm_mod uinput iTCO_wdt iTCO_vendor_support dcdbas sg ses enclosure coretemp hwmon kvm_intel kvm crc32c_intel ghash_clmulni_intel serio_raw pcspkr lpc_ich mfd_core bnx2 ext3 jbd mbcache sr_mod cdrom sd_mod crc_t10dif aesni_intel ablk_helper cryptd lrw aes_x86_64 xts gf128mul pata_acpi ata_generic ata_piix megaraid_sas [last unloaded: mlx4_core]
[73550.981962] Pid: 9167, comm: odp Tainted: G        W  O 3.7.0-rc2-odp+ #8
[73550.981963] Call Trace:
[73550.981965]  <IRQ>  [<ffffffff8104619f>] warn_slowpath_common+0x7f/0xc0
[73550.981967]  [<ffffffff810461fa>] warn_slowpath_null+0x1a/0x20
[73550.981969]  [<ffffffff8147e9ff>] skb_release_head_state+0x10f/0x120
[73550.981971]  [<ffffffff8147e766>] __kfree_skb+0x16/0xa0
[73550.981973]  [<ffffffff8147eab1>] consume_skb+0x31/0xe0
[73550.981978]  [<ffffffffa00f7369>] bnx2_poll_work+0x2d9/0x13f0 [bnx2]
[73550.981980]  [<ffffffff8157ccc9>] ? _raw_spin_lock_irqsave+0x29/0x70
[73550.981982]  [<ffffffff8157d577>] ? _raw_spin_unlock_irqrestore+0x77/0x80
[73550.981984]  [<ffffffff8157ccc9>] ? _raw_spin_lock_irqsave+0x29/0x70
[73550.981986]  [<ffffffff8157d577>] ? _raw_spin_unlock_irqrestore+0x77/0x80
[73550.981988]  [<ffffffff810abc89>] ? trace_hardirqs_off_caller+0x29/0xc0
[73550.981990]  [<ffffffff810abd2d>] ? trace_hardirqs_off+0xd/0x10
[73550.981995]  [<ffffffffa00f84c3>] bnx2_poll_msix+0x43/0xd0 [bnx2]
[73550.981996]  [<ffffffff8157d6cc>] ? _raw_spin_trylock+0x6c/0x80
[73550.981998]  [<ffffffff814a8dce>] netpoll_poll_dev+0x14e/0x7a0
[73550.982001]  [<ffffffff814a972c>] netpoll_send_skb_on_dev+0x30c/0x400
[73550.982003]  [<ffffffff814a9b13>] netpoll_send_udp+0x263/0x2b0
[73550.982006]  [<ffffffffa00812f3>] write_msg+0xc3/0x120 [netconsole]
[73550.982008]  [<ffffffff810483f3>] call_console_drivers.clone.3+0xa3/0x1c0
[73550.982010]  [<ffffffff810487c8>] console_unlock+0x2b8/0x450
[73550.982012]  [<ffffffff81048d7e>] vprintk_emit+0x1de/0x5b0
[73550.982014]  [<ffffffff81579aed>] printk+0x4d/0x4f
[73550.982015]  [<ffffffff8129e41c>] ? ___ratelimit+0xac/0x150
[73550.982020]  [<ffffffffa03f5829>] mlx4_eq_int+0x779/0xc50 [mlx4_core]
[73550.982025]  [<ffffffffa000152f>] ? megasas_isr+0x5f/0x200 [megaraid_sas]
[73550.982027]  [<ffffffff8157ccc9>] ? _raw_spin_lock_irqsave+0x29/0x70
[73550.982029]  [<ffffffff813636c1>] ? add_interrupt_randomness+0x41/0x190
[73550.982034]  [<ffffffffa03f5d14>] mlx4_msi_x_interrupt+0x14/0x20 [mlx4_core]
[73550.982036]  [<ffffffff810e3fd5>] handle_irq_event_percpu+0x95/0x390
[73550.982039]  [<ffffffff8139be30>] ? scsi_get_command+0xc0/0xc0
[73550.982040]  [<ffffffff810e4318>] handle_irq_event+0x48/0x70
[73550.982043]  [<ffffffff810e796d>] handle_edge_irq+0x6d/0x130
[73550.982044]  [<ffffffff8100470c>] handle_irq+0x5c/0x150
[73550.982046]  [<ffffffff8104fdcb>] ? irq_enter+0x1b/0x90
[73550.982048]  [<ffffffff8158855d>] do_IRQ+0x5d/0xe0
[73550.982050]  [<ffffffff8157d9b2>] common_interrupt+0x72/0x72
[73550.982052]  [<ffffffff8157da73>] ? retint_restore_args+0x13/0x13
[73550.982054]  [<ffffffff8157d540>] ? _raw_spin_unlock_irqrestore+0x40/0x80
[73550.982056]  [<ffffffff8157d545>] ? _raw_spin_unlock_irqrestore+0x45/0x80
[73550.982061]  [<ffffffffa00011d7>] megasas_queue_command+0x77/0x170 [megaraid_sas]
[73550.982063]  [<ffffffff8139bfdb>] scsi_dispatch_cmd+0xeb/0x380
[73550.982065]  [<ffffffff813a2f18>] scsi_request_fn+0x408/0x6f0
[73550.982067]  [<ffffffff8127158e>] __blk_run_queue+0x1e/0x20
[73550.982069]  [<ffffffff81273f30>] blk_run_queue+0x30/0x50
[73550.982071]  [<ffffffff813a23e2>] scsi_run_queue+0xd2/0x2a0
[73550.982073]  [<ffffffff810af0ad>] ? trace_hardirqs_on+0xd/0x10
[73550.982075]  [<ffffffff813a3452>] scsi_next_command+0x42/0x60
[73550.982077]  [<ffffffff813a41c6>] scsi_io_completion+0x2b6/0x670
[73550.982079]  [<ffffffff8139b2f9>] scsi_finish_command+0xc9/0x130
[73550.982081]  [<ffffffff813a46e7>] scsi_softirq_done+0x147/0x170
[73550.982083]  [<ffffffff8127e9ea>] blk_done_softirq+0x8a/0xa0
[73550.982086]  [<ffffffff81050810>] __do_softirq+0x110/0x3c0
[73550.982088]  [<ffffffff8139be30>] ? scsi_get_command+0xc0/0xc0
[73550.982090]  [<ffffffff81587e3c>] call_softirq+0x1c/0x30
[73550.982092]  [<ffffffff8100467d>] do_softirq+0xad/0xe0
[73550.982094]  [<ffffffff8104fc75>] irq_exit+0xe5/0x100
[73550.982095]  [<ffffffff81588566>] do_IRQ+0x66/0xe0
[73550.982097]  [<ffffffff8157d9b2>] common_interrupt+0x72/0x72
[73550.982100]  <EOI>  [<ffffffff8157d540>] ? _raw_spin_unlock_irqrestore+0x40/0x80
[73550.982102]  [<ffffffff8157d545>] ? _raw_spin_unlock_irqrestore+0x45/0x80
[73550.982106]  [<ffffffffa00011d7>] megasas_queue_command+0x77/0x170 [megaraid_sas]
[73550.982109]  [<ffffffff8139bfdb>] scsi_dispatch_cmd+0xeb/0x380
[73550.982111]  [<ffffffff813a2f18>] scsi_request_fn+0x408/0x6f0
[73550.982113]  [<ffffffff81293c5c>] ? cfq_insert_request+0x4c/0x630
[73550.982115]  [<ffffffff8127158e>] __blk_run_queue+0x1e/0x20
[73550.982117]  [<ffffffff81293f77>] cfq_insert_request+0x367/0x630
[73550.982118]  [<ffffffff81293c5c>] ? cfq_insert_request+0x4c/0x630
[73550.982121]  [<ffffffff81278db0>] ? blk_flush_plug_list+0x180/0x270
[73550.982123]  [<ffffffff812ad173>] ? debug_object_activate+0x83/0x190
[73550.982125]  [<ffffffff81270e88>] __elv_add_request+0x138/0x2b0
[73550.982127]  [<ffffffff81278de4>] blk_flush_plug_list+0x1b4/0x270
[73550.982129]  [<ffffffff8157c010>] schedule+0x50/0x70
[73550.982130]  [<ffffffff81579cce>] schedule_timeout+0x15e/0x2c0
[73550.982132]  [<ffffffff810581c0>] ? lock_timer_base+0x70/0x70
[73550.982135]  [<ffffffff8157be8b>] wait_for_common+0x12b/0x180
[73550.982136]  [<ffffffff81086c10>] ? try_to_wake_up+0x300/0x300
[73550.982138]  [<ffffffff8157bf93>] wait_for_completion_timeout+0x13/0x20
[73550.982143]  [<ffffffffa03f28f2>] __mlx4_cmd+0x2a2/0x5c0 [mlx4_core]
[73550.982149]  [<ffffffffa04021d6>] mlx4_SYNC_TPT+0x36/0x40 [mlx4_core]
[73550.982151]  [<ffffffff8157a80e>] ? mutex_unlock+0xe/0x10
[73550.982156]  [<ffffffffa0436e3d>] invalidation_handler+0x22d/0x3b0 [mlx4_ib]
[73550.982161]  [<ffffffffa0436c10>] ? mlx4_ib_qp_pfault_action+0x40/0x40 [mlx4_ib]
[73550.982166]  [<ffffffffa043702d>] mlx4_ib_invalidate_page+0x2d/0x30 [mlx4_ib]
[73550.982170]  [<ffffffffa025c764>] invalidate_page_trampoline+0x34/0x50 [ib_core]
[73550.982175]  [<ffffffffa025d7e4>] rbt_ib_umem_for_each_in_range+0xa4/0x150 [ib_core]
[73550.982179]  [<ffffffffa025c730>] ? invalidate_range_start_trampoline+0x60/0x60 [ib_core]
[73550.982183]  [<ffffffffa025cf33>] ib_umem_notifier_invalidate_page+0x63/0x80 [ib_core]
[73550.982185]  [<ffffffff8117ace5>] __mmu_notifier_invalidate_page+0xa5/0x1b0
[73550.982188]  [<ffffffff8117ac40>] ? mmu_notifier_unregister+0x1e0/0x1e0
[73550.982190]  [<ffffffff811660f8>] try_to_unmap_one+0x3f8/0x470
[73550.982192]  [<ffffffff81164ff1>] ? page_lock_anon_vma+0x151/0x2b0
[73550.982194]  [<ffffffff81164ea0>] ? page_get_anon_vma+0x1b0/0x1b0
[73550.982196]  [<ffffffff811668fc>] try_to_unmap_anon+0xbc/0x160
[73550.982198]  [<ffffffff81166a6b>] try_to_unmap+0x6b/0xa0
[73550.982201]  [<ffffffff811407ab>] shrink_page_list+0x3eb/0xa50
[73550.982203]  [<ffffffff8114210f>] shrink_inactive_list+0x17f/0x4c0
[73550.982205]  [<ffffffff811426ec>] ? shrink_active_list+0x29c/0x340
[73550.982207]  [<ffffffff81142c25>] shrink_lruvec+0x495/0x5b0
[73550.982209]  [<ffffffff812943dc>] ? cfq_dispatch_requests+0x19c/0xd20
[73550.982211]  [<ffffffff8157ccc9>] ? _raw_spin_lock_irqsave+0x29/0x70
[73550.982213]  [<ffffffff81142da6>] shrink_zone+0x66/0xc0
[73550.982215]  [<ffffffff8114451b>] do_try_to_free_pages+0xeb/0x630
[73550.982217]  [<ffffffff81144c0b>] try_to_free_mem_cgroup_pages+0xbb/0x200
[73550.982219]  [<ffffffff810aef10>] ? trace_hardirqs_on_caller+0x20/0x1b0
[73550.982221]  [<ffffffff8119069e>] mem_cgroup_reclaim+0x4e/0xe0
[73550.982223]  [<ffffffff8119101c>] __mem_cgroup_try_charge+0x4cc/0x9e0
[73550.982225]  [<ffffffff81194874>] ? swap_cgroup_record+0x34/0x60
[73550.982228]  [<ffffffff81191943>] __mem_cgroup_try_charge_swapin+0xa3/0xc0
[73550.982231]  [<ffffffff811919af>] mem_cgroup_try_charge_swapin+0x4f/0x60
[73550.982232]  [<ffffffff8115b5ec>] handle_pte_fault+0x30c/0x9d0
[73550.982234]  [<ffffffff8119410f>] ? mem_cgroup_count_vm_event+0x1f/0x190
[73550.982236]  [<ffffffff8115bf01>] handle_mm_fault+0x251/0x310
[73550.982238]  [<ffffffff81581943>] __do_page_fault+0x223/0x510
[73550.982240]  [<ffffffff810aef10>] ? trace_hardirqs_on_caller+0x20/0x1b0
[73550.982242]  [<ffffffff810af0ad>] ? trace_hardirqs_on+0xd/0x10
[73550.982244]  [<ffffffff8157d4e0>] ? _raw_spin_unlock_irq+0x30/0x50
[73550.982246]  [<ffffffff81080ee5>] ? finish_task_switch+0x85/0x120
[73550.982248]  [<ffffffff81080ea8>] ? finish_task_switch+0x48/0x120
[73550.982250]  [<ffffffff8157df06>] ? error_sti+0x5/0x6
[73550.982252]  [<ffffffff810abc89>] ? trace_hardirqs_off_caller+0x29/0xc0
[73550.982254]  [<ffffffff812a5ebd>] ? trace_hardirqs_off_thunk+0x3a/0x3c
[73550.982256]  [<ffffffff81581c3e>] do_page_fault+0xe/0x10
[73550.982258]  [<ffffffff8157dcb8>] page_fault+0x28/0x30
[73550.982259] ---[ end trace 12bb14f2b81db036 ]---

^ permalink raw reply

* Re: [PATCH] net: dsa/slave: Fix compilation warnings
From: Daniel Lezcano @ 2012-10-30  7:53 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Ben Hutchings, netdev, linaro-dev, davem, linux-kernel, patches
In-Reply-To: <CAKohponOKk5e2Sxyhjw-XvzVxF3tNp66rsnYCwvwHazAPAauKw@mail.gmail.com>

On 10/30/2012 08:31 AM, Viresh Kumar wrote:
> On 30 October 2012 12:15, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>> And so, if we select NET_DSA from these tagging drivers, then only slave.c will
>> get compiled. Otherwise slave.c dsa.c dsa_core.c wouldn't be compiled and so
>> no warnings.
> 
> If my above explanation/assumption is correct, then please review following
> patch:
> 
> --------------------------x-----------------------x----------------
> 
> From: Viresh Kumar <viresh.kumar@linaro.org>
> Date: Mon, 29 Oct 2012 22:19:14 +0530
> Subject: [PATCH] net: dsa/slave: Fix compilation warnings
> 
> Currently when none of CONFIG_NET_DSA_TAG_DSA, CONFIG_NET_DSA_TAG_EDSA and
> CONFIG_NET_DSA_TAG_TRAILER is defined, we get following compilation warnings:
> 
> net/dsa/slave.c:51:12: warning: 'dsa_slave_init' defined but not used
> [-Wunused-function]
> net/dsa/slave.c:60:12: warning: 'dsa_slave_open' defined but not used
> [-Wunused-function]
> net/dsa/slave.c:98:12: warning: 'dsa_slave_close' defined but not used
> [-Wunused-function]
> net/dsa/slave.c:116:13: warning: 'dsa_slave_change_rx_flags' defined
> but not used [-Wunused-function]
> net/dsa/slave.c:127:13: warning: 'dsa_slave_set_rx_mode' defined but
> not used [-Wunused-function]
> net/dsa/slave.c:136:12: warning: 'dsa_slave_set_mac_address' defined
> but not used [-Wunused-function]
> net/dsa/slave.c:164:12: warning: 'dsa_slave_ioctl' defined but not
> used [-Wunused-function]
> 
> Earlier approach to fix this was discussed here:
> 
> lkml.org/lkml/2012/10/29/549
> 
> This is another approach to fix it. This is done by some changes in config
> options, which make more sense than the earlier approach. As, atleast one
> tagging option must always be selected for using net/dsa/ infrastructure, this
> patch selects NET_DSA from tagging configs instead of having it as an selectable
> config.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  drivers/net/dsa/Kconfig |  1 -
>  net/dsa/Kconfig         | 16 +++++++++-------
>  2 files changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
> index dd151d5..96eae22 100644
> --- a/drivers/net/dsa/Kconfig
> +++ b/drivers/net/dsa/Kconfig
> @@ -1,5 +1,4 @@
>  menu "Distributed Switch Architecture drivers"
> -	depends on NET_DSA
> 
>  config NET_DSA_MV88E6XXX
>  	tristate
> diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
> index 274791c..f7c6cef 100644
> --- a/net/dsa/Kconfig
> +++ b/net/dsa/Kconfig
> @@ -1,5 +1,5 @@
>  config NET_DSA
> -	tristate "Distributed Switch Architecture support"
> +	tristate
>  	default n
>  	depends on EXPERIMENTAL && NETDEVICES && !S390
>  	select PHYLIB
> @@ -8,19 +8,21 @@ config NET_DSA
>  	  the Distributed Switch Architecture.
> 
> 
> -if NET_DSA
> +menu "Distributed Switch Architecture support"
> 
>  # tagging formats
>  config NET_DSA_TAG_DSA
> -	bool
> +	bool "Original DSA packet tagging format"
> +	select NET_DSt

typo NET_DSA

>  	default n
> 
>  config NET_DSA_TAG_EDSA
> -	bool
> +	bool "Ethertype DSA packet tagging format"
> +	select NET_DSA
>  	default n
> 
>  config NET_DSA_TAG_TRAILER
> -	bool
> +	bool "Trailer DSA packet tagging format"
> +	select NET_DSA
>  	default n
> -
> -endif
> +endmenu
> 
> _______________________________________________
> linaro-dev mailing list
> linaro-dev@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/linaro-dev


-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply

* Re: [PATCH] net: dsa/slave: Fix compilation warnings
From: Viresh Kumar @ 2012-10-30  7:55 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: Ben Hutchings, netdev, linaro-dev, davem, linux-kernel, patches
In-Reply-To: <508F8779.8070300@linaro.org>

On 30 October 2012 13:23, Daniel Lezcano <daniel.lezcano@linaro.org> wrote:
>> From: Viresh Kumar <viresh.kumar@linaro.org>

>>  config NET_DSA_TAG_DSA
>> -     bool
>> +     bool "Original DSA packet tagging format"
>> +     select NET_DSt
>
> typo NET_DSA

Unbelievable mistake :(

Will fix it after some reviews now :)

--
viresh

^ permalink raw reply

* Re: [PATCH 3/4] arm: mvebu: add Ethernet controllers using mvneta driver for Armada 370/XP
From: Thomas Petazzoni @ 2012-10-30  8:36 UTC (permalink / raw)
  To: Nobuhiro Iwamatsu
  Cc: David S. Miller, Lennert Buytenhek, Lior Amsalem, Andrew Lunn,
	Jason Cooper, netdev, Maen Suleiman, Gregory Clement,
	linux-arm-kernel
In-Reply-To: <CABMQnVKswTJr9Nd4Etx4Htv0Ckn+pDNqGO8MoPBH-x8y6CwZyA@mail.gmail.com>

Hello,

On Tue, 30 Oct 2012 13:19:15 +0900, Nobuhiro Iwamatsu wrote:

> > diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
> > index 16cc82c..d484492 100644
> > --- a/arch/arm/boot/dts/armada-370-xp.dtsi
> > +++ b/arch/arm/boot/dts/armada-370-xp.dtsi
> > @@ -68,6 +68,20 @@
> >                         compatible = "marvell,armada-addr-decoding-controller";
> >                         reg = <0xd0020000 0x258>;
> >                 };
> > +
> > +                ethernet@d0070000 {
> > +                               compatible = "marvell,armada-370-neta";
> > +                               reg = <0xd0070000 0x2500>;
> > +                               interrupts = <8>;
> > +                               status = "disabled";
> > +                };
> > +
> > +                ethernet@d0074000 {
> > +                               compatible = "marvell,armada-370-neta";
> > +                               reg = <0xd0074000 0x2500>;
> > +                               interrupts = <10>;
> > +                               status = "disabled";
> > +                };
> 
> Could you fit an indent?

Right, thanks, will fix.

Thomas
-- 
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* Re: WARNING: at net/core/skbuff.c:573
From: Cong Wang @ 2012-10-30  8:46 UTC (permalink / raw)
  To: netdev
In-Reply-To: <508F8612.2040301@mellanox.com>

On Tue, 30 Oct 2012 at 07:47 GMT, Haggai Eran <haggaie@mellanox.com> wrote:
> Hi,
>
> Running kernel v3.7-rc2 I'm getting these warnings at
> skb_release_head_state. It is called from netconsole, due to printk
> from mlx4_core's interrupt handler. The warning is due to the function 
> being run in interrupt context. However, according to the documentation,
> netconsole is supposed to be fine running from within interrupts.
>
> I'm not sure I can reproduce it reliably though.

This comes from:

        if (skb->destructor) {
                WARN_ON(in_irq());
                skb->destructor(skb);
        }
						
when mlx4_eq_int() calls printk() in interrupt context, thus
netconsole triggered this warning.

So, I am wondering if you can get netconsole message on the remote
successfully after removing that offending WARN_ON()?

I don't know the reason why we warn for calling sbk destructors in IRQ
context, seems the code is very code.


>
> Haggai
>
> [73550.981930] ------------[ cut here ]------------
> [73550.981933] WARNING: at net/core/skbuff.c:573 skb_release_head_state+0x10f/0x120()
> [73550.981933] Hardware name: PowerEdge R710
> [73550.981961] Modules linked in: rdma_ucm rdma_cm iw_cm ib_addr ib_ipoib ib_cm ib_uverbs ib_umad mlx4_ib ib_sa ib_mad ib_core mlx4_en mlx4_core mmu_trace(O) mst_pciconf(O) mst_pci(O) netconsole configfs nfsv3 nfs_acl nfsv4 auth_rpcgss nfs fscache lockd autofs4 sunrpc ipv6 dm_mirror dm_region_hash dm_log dm_mod uinput iTCO_wdt iTCO_vendor_support dcdbas sg ses enclosure coretemp hwmon kvm_intel kvm crc32c_intel ghash_clmulni_intel serio_raw pcspkr lpc_ich mfd_core bnx2 ext3 jbd mbcache sr_mod cdrom sd_mod crc_t10dif aesni_intel ablk_helper cryptd lrw aes_x86_64 xts gf128mul pata_acpi ata_generic ata_piix megaraid_sas [last unloaded: mlx4_core]
> [73550.981962] Pid: 9167, comm: odp Tainted: G        W  O 3.7.0-rc2-odp+ #8
> [73550.981963] Call Trace:
> [73550.981965]  <IRQ>  [<ffffffff8104619f>] warn_slowpath_common+0x7f/0xc0
> [73550.981967]  [<ffffffff810461fa>] warn_slowpath_null+0x1a/0x20
> [73550.981969]  [<ffffffff8147e9ff>] skb_release_head_state+0x10f/0x120
> [73550.981971]  [<ffffffff8147e766>] __kfree_skb+0x16/0xa0
> [73550.981973]  [<ffffffff8147eab1>] consume_skb+0x31/0xe0
> [73550.981978]  [<ffffffffa00f7369>] bnx2_poll_work+0x2d9/0x13f0 [bnx2]
> [73550.981980]  [<ffffffff8157ccc9>] ? _raw_spin_lock_irqsave+0x29/0x70
> [73550.981982]  [<ffffffff8157d577>] ? _raw_spin_unlock_irqrestore+0x77/0x80
> [73550.981984]  [<ffffffff8157ccc9>] ? _raw_spin_lock_irqsave+0x29/0x70
> [73550.981986]  [<ffffffff8157d577>] ? _raw_spin_unlock_irqrestore+0x77/0x80
> [73550.981988]  [<ffffffff810abc89>] ? trace_hardirqs_off_caller+0x29/0xc0
> [73550.981990]  [<ffffffff810abd2d>] ? trace_hardirqs_off+0xd/0x10
> [73550.981995]  [<ffffffffa00f84c3>] bnx2_poll_msix+0x43/0xd0 [bnx2]
> [73550.981996]  [<ffffffff8157d6cc>] ? _raw_spin_trylock+0x6c/0x80
> [73550.981998]  [<ffffffff814a8dce>] netpoll_poll_dev+0x14e/0x7a0
> [73550.982001]  [<ffffffff814a972c>] netpoll_send_skb_on_dev+0x30c/0x400
> [73550.982003]  [<ffffffff814a9b13>] netpoll_send_udp+0x263/0x2b0
> [73550.982006]  [<ffffffffa00812f3>] write_msg+0xc3/0x120 [netconsole]
> [73550.982008]  [<ffffffff810483f3>] call_console_drivers.clone.3+0xa3/0x1c0
> [73550.982010]  [<ffffffff810487c8>] console_unlock+0x2b8/0x450
> [73550.982012]  [<ffffffff81048d7e>] vprintk_emit+0x1de/0x5b0
> [73550.982014]  [<ffffffff81579aed>] printk+0x4d/0x4f
> [73550.982015]  [<ffffffff8129e41c>] ? ___ratelimit+0xac/0x150
> [73550.982020]  [<ffffffffa03f5829>] mlx4_eq_int+0x779/0xc50 [mlx4_core]
> [73550.982025]  [<ffffffffa000152f>] ? megasas_isr+0x5f/0x200 [megaraid_sas]
> [73550.982027]  [<ffffffff8157ccc9>] ? _raw_spin_lock_irqsave+0x29/0x70
> [73550.982029]  [<ffffffff813636c1>] ? add_interrupt_randomness+0x41/0x190
> [73550.982034]  [<ffffffffa03f5d14>] mlx4_msi_x_interrupt+0x14/0x20 [mlx4_core]
> [73550.982036]  [<ffffffff810e3fd5>] handle_irq_event_percpu+0x95/0x390
> [73550.982039]  [<ffffffff8139be30>] ? scsi_get_command+0xc0/0xc0
> [73550.982040]  [<ffffffff810e4318>] handle_irq_event+0x48/0x70
> [73550.982043]  [<ffffffff810e796d>] handle_edge_irq+0x6d/0x130
> [73550.982044]  [<ffffffff8100470c>] handle_irq+0x5c/0x150
> [73550.982046]  [<ffffffff8104fdcb>] ? irq_enter+0x1b/0x90
> [73550.982048]  [<ffffffff8158855d>] do_IRQ+0x5d/0xe0
> [73550.982050]  [<ffffffff8157d9b2>] common_interrupt+0x72/0x72
> [73550.982052]  [<ffffffff8157da73>] ? retint_restore_args+0x13/0x13
> [73550.982054]  [<ffffffff8157d540>] ? _raw_spin_unlock_irqrestore+0x40/0x80
> [73550.982056]  [<ffffffff8157d545>] ? _raw_spin_unlock_irqrestore+0x45/0x80
> [73550.982061]  [<ffffffffa00011d7>] megasas_queue_command+0x77/0x170 [megaraid_sas]
> [73550.982063]  [<ffffffff8139bfdb>] scsi_dispatch_cmd+0xeb/0x380
> [73550.982065]  [<ffffffff813a2f18>] scsi_request_fn+0x408/0x6f0
> [73550.982067]  [<ffffffff8127158e>] __blk_run_queue+0x1e/0x20
> [73550.982069]  [<ffffffff81273f30>] blk_run_queue+0x30/0x50
> [73550.982071]  [<ffffffff813a23e2>] scsi_run_queue+0xd2/0x2a0
> [73550.982073]  [<ffffffff810af0ad>] ? trace_hardirqs_on+0xd/0x10
> [73550.982075]  [<ffffffff813a3452>] scsi_next_command+0x42/0x60
> [73550.982077]  [<ffffffff813a41c6>] scsi_io_completion+0x2b6/0x670
> [73550.982079]  [<ffffffff8139b2f9>] scsi_finish_command+0xc9/0x130
> [73550.982081]  [<ffffffff813a46e7>] scsi_softirq_done+0x147/0x170
> [73550.982083]  [<ffffffff8127e9ea>] blk_done_softirq+0x8a/0xa0
> [73550.982086]  [<ffffffff81050810>] __do_softirq+0x110/0x3c0
> [73550.982088]  [<ffffffff8139be30>] ? scsi_get_command+0xc0/0xc0
> [73550.982090]  [<ffffffff81587e3c>] call_softirq+0x1c/0x30
> [73550.982092]  [<ffffffff8100467d>] do_softirq+0xad/0xe0
> [73550.982094]  [<ffffffff8104fc75>] irq_exit+0xe5/0x100
> [73550.982095]  [<ffffffff81588566>] do_IRQ+0x66/0xe0
> [73550.982097]  [<ffffffff8157d9b2>] common_interrupt+0x72/0x72
> [73550.982100]  <EOI>  [<ffffffff8157d540>] ? _raw_spin_unlock_irqrestore+0x40/0x80
> [73550.982102]  [<ffffffff8157d545>] ? _raw_spin_unlock_irqrestore+0x45/0x80
> [73550.982106]  [<ffffffffa00011d7>] megasas_queue_command+0x77/0x170 [megaraid_sas]
> [73550.982109]  [<ffffffff8139bfdb>] scsi_dispatch_cmd+0xeb/0x380
> [73550.982111]  [<ffffffff813a2f18>] scsi_request_fn+0x408/0x6f0
> [73550.982113]  [<ffffffff81293c5c>] ? cfq_insert_request+0x4c/0x630
> [73550.982115]  [<ffffffff8127158e>] __blk_run_queue+0x1e/0x20
> [73550.982117]  [<ffffffff81293f77>] cfq_insert_request+0x367/0x630
> [73550.982118]  [<ffffffff81293c5c>] ? cfq_insert_request+0x4c/0x630
> [73550.982121]  [<ffffffff81278db0>] ? blk_flush_plug_list+0x180/0x270
> [73550.982123]  [<ffffffff812ad173>] ? debug_object_activate+0x83/0x190
> [73550.982125]  [<ffffffff81270e88>] __elv_add_request+0x138/0x2b0
> [73550.982127]  [<ffffffff81278de4>] blk_flush_plug_list+0x1b4/0x270
> [73550.982129]  [<ffffffff8157c010>] schedule+0x50/0x70
> [73550.982130]  [<ffffffff81579cce>] schedule_timeout+0x15e/0x2c0
> [73550.982132]  [<ffffffff810581c0>] ? lock_timer_base+0x70/0x70
> [73550.982135]  [<ffffffff8157be8b>] wait_for_common+0x12b/0x180
> [73550.982136]  [<ffffffff81086c10>] ? try_to_wake_up+0x300/0x300
> [73550.982138]  [<ffffffff8157bf93>] wait_for_completion_timeout+0x13/0x20
> [73550.982143]  [<ffffffffa03f28f2>] __mlx4_cmd+0x2a2/0x5c0 [mlx4_core]
> [73550.982149]  [<ffffffffa04021d6>] mlx4_SYNC_TPT+0x36/0x40 [mlx4_core]
> [73550.982151]  [<ffffffff8157a80e>] ? mutex_unlock+0xe/0x10
> [73550.982156]  [<ffffffffa0436e3d>] invalidation_handler+0x22d/0x3b0 [mlx4_ib]
> [73550.982161]  [<ffffffffa0436c10>] ? mlx4_ib_qp_pfault_action+0x40/0x40 [mlx4_ib]
> [73550.982166]  [<ffffffffa043702d>] mlx4_ib_invalidate_page+0x2d/0x30 [mlx4_ib]
> [73550.982170]  [<ffffffffa025c764>] invalidate_page_trampoline+0x34/0x50 [ib_core]
> [73550.982175]  [<ffffffffa025d7e4>] rbt_ib_umem_for_each_in_range+0xa4/0x150 [ib_core]
> [73550.982179]  [<ffffffffa025c730>] ? invalidate_range_start_trampoline+0x60/0x60 [ib_core]
> [73550.982183]  [<ffffffffa025cf33>] ib_umem_notifier_invalidate_page+0x63/0x80 [ib_core]
> [73550.982185]  [<ffffffff8117ace5>] __mmu_notifier_invalidate_page+0xa5/0x1b0
> [73550.982188]  [<ffffffff8117ac40>] ? mmu_notifier_unregister+0x1e0/0x1e0
> [73550.982190]  [<ffffffff811660f8>] try_to_unmap_one+0x3f8/0x470
> [73550.982192]  [<ffffffff81164ff1>] ? page_lock_anon_vma+0x151/0x2b0
> [73550.982194]  [<ffffffff81164ea0>] ? page_get_anon_vma+0x1b0/0x1b0
> [73550.982196]  [<ffffffff811668fc>] try_to_unmap_anon+0xbc/0x160
> [73550.982198]  [<ffffffff81166a6b>] try_to_unmap+0x6b/0xa0
> [73550.982201]  [<ffffffff811407ab>] shrink_page_list+0x3eb/0xa50
> [73550.982203]  [<ffffffff8114210f>] shrink_inactive_list+0x17f/0x4c0
> [73550.982205]  [<ffffffff811426ec>] ? shrink_active_list+0x29c/0x340
> [73550.982207]  [<ffffffff81142c25>] shrink_lruvec+0x495/0x5b0
> [73550.982209]  [<ffffffff812943dc>] ? cfq_dispatch_requests+0x19c/0xd20
> [73550.982211]  [<ffffffff8157ccc9>] ? _raw_spin_lock_irqsave+0x29/0x70
> [73550.982213]  [<ffffffff81142da6>] shrink_zone+0x66/0xc0
> [73550.982215]  [<ffffffff8114451b>] do_try_to_free_pages+0xeb/0x630
> [73550.982217]  [<ffffffff81144c0b>] try_to_free_mem_cgroup_pages+0xbb/0x200
> [73550.982219]  [<ffffffff810aef10>] ? trace_hardirqs_on_caller+0x20/0x1b0
> [73550.982221]  [<ffffffff8119069e>] mem_cgroup_reclaim+0x4e/0xe0
> [73550.982223]  [<ffffffff8119101c>] __mem_cgroup_try_charge+0x4cc/0x9e0
> [73550.982225]  [<ffffffff81194874>] ? swap_cgroup_record+0x34/0x60
> [73550.982228]  [<ffffffff81191943>] __mem_cgroup_try_charge_swapin+0xa3/0xc0
> [73550.982231]  [<ffffffff811919af>] mem_cgroup_try_charge_swapin+0x4f/0x60
> [73550.982232]  [<ffffffff8115b5ec>] handle_pte_fault+0x30c/0x9d0
> [73550.982234]  [<ffffffff8119410f>] ? mem_cgroup_count_vm_event+0x1f/0x190
> [73550.982236]  [<ffffffff8115bf01>] handle_mm_fault+0x251/0x310
> [73550.982238]  [<ffffffff81581943>] __do_page_fault+0x223/0x510
> [73550.982240]  [<ffffffff810aef10>] ? trace_hardirqs_on_caller+0x20/0x1b0
> [73550.982242]  [<ffffffff810af0ad>] ? trace_hardirqs_on+0xd/0x10
> [73550.982244]  [<ffffffff8157d4e0>] ? _raw_spin_unlock_irq+0x30/0x50
> [73550.982246]  [<ffffffff81080ee5>] ? finish_task_switch+0x85/0x120
> [73550.982248]  [<ffffffff81080ea8>] ? finish_task_switch+0x48/0x120
> [73550.982250]  [<ffffffff8157df06>] ? error_sti+0x5/0x6
> [73550.982252]  [<ffffffff810abc89>] ? trace_hardirqs_off_caller+0x29/0xc0
> [73550.982254]  [<ffffffff812a5ebd>] ? trace_hardirqs_off_thunk+0x3a/0x3c
> [73550.982256]  [<ffffffff81581c3e>] do_page_fault+0xe/0x10
> [73550.982258]  [<ffffffff8157dcb8>] page_fault+0x28/0x30
> [73550.982259] ---[ end trace 12bb14f2b81db036 ]---
>
>

^ permalink raw reply

* Re: [PATCH] net: dsa/slave: Fix compilation warnings
From: Daniel Lezcano @ 2012-10-30  9:00 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Ben Hutchings, netdev, linaro-dev, davem, linux-kernel, patches
In-Reply-To: <CAKohpokmfFSFsADmtOyN9JRCX8aVdNs+tDFhUQuM6sSQ+dFfUA@mail.gmail.com>

On 10/30/2012 08:55 AM, Viresh Kumar wrote:
> On 30 October 2012 13:23, Daniel Lezcano <daniel.lezcano@linaro.org> wrote:
>>> From: Viresh Kumar <viresh.kumar@linaro.org>
> 
>>>  config NET_DSA_TAG_DSA
>>> -     bool
>>> +     bool "Original DSA packet tagging format"
>>> +     select NET_DSt
>>
>> typo NET_DSA
> 
> Unbelievable mistake :(
> 
> Will fix it after some reviews now :)

Yeah, has to be ! ;)

It is very curious if we disable all the configs option, a slave
creation raise a BUG (cf. dsa_slave_create). IIUC, booting with NET_DSA
enabled and none of the NET_DSA_TAG* enabled will raise a BUG in the
probe function, right ?

Maybe we should force at least one config when none are set ?

diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 274791c..86326e3 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -1,8 +1,9 @@
-config NET_DSA
+menuconfig NET_DSA
        tristate "Distributed Switch Architecture support"
        default n
        depends on EXPERIMENTAL && NETDEVICES && !S390
        select PHYLIB
+       select NET_DSA_TAG_DSA if (!NET_DSA_TAG_EDSA &&
!NET_DSA_TAG_TRAILER)
        ---help---
          This allows you to use hardware switch chips that use
          the Distributed Switch Architecture.
@@ -12,15 +13,15 @@ if NET_DSA

 # tagging formats
 config NET_DSA_TAG_DSA
-       bool
+       bool "tag dsa"
        default n

 config NET_DSA_TAG_EDSA
-       bool
+       bool "tag edsa"
        default n

 config NET_DSA_TAG_TRAILER
-       bool
+       bool "tag trailer"
        default n

 endif


-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply related

* Re: [PATCH] net: dsa/slave: Fix compilation warnings
From: Viresh Kumar @ 2012-10-30  9:03 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: Ben Hutchings, netdev, linaro-dev, davem, linux-kernel, patches
In-Reply-To: <508F9724.50804@linaro.org>

On 30 October 2012 14:30, Daniel Lezcano <daniel.lezcano@linaro.org> wrote:
> It is very curious if we disable all the configs option, a slave
> creation raise a BUG (cf. dsa_slave_create). IIUC, booting with NET_DSA
> enabled and none of the NET_DSA_TAG* enabled will raise a BUG in the
> probe function, right ?
>
> Maybe we should force at least one config when none are set ?

I thought of it earlier. But found the one which i posted better. As we will not
compile DSA stuff now without these tags.

--
viresh

> diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
> index 274791c..86326e3 100644
> --- a/net/dsa/Kconfig
> +++ b/net/dsa/Kconfig
> @@ -1,8 +1,9 @@
> -config NET_DSA
> +menuconfig NET_DSA
>         tristate "Distributed Switch Architecture support"
>         default n
>         depends on EXPERIMENTAL && NETDEVICES && !S390
>         select PHYLIB
> +       select NET_DSA_TAG_DSA if (!NET_DSA_TAG_EDSA &&
> !NET_DSA_TAG_TRAILER)
>         ---help---
>           This allows you to use hardware switch chips that use
>           the Distributed Switch Architecture.
> @@ -12,15 +13,15 @@ if NET_DSA
>
>  # tagging formats
>  config NET_DSA_TAG_DSA
> -       bool
> +       bool "tag dsa"
>         default n
>
>  config NET_DSA_TAG_EDSA
> -       bool
> +       bool "tag edsa"
>         default n
>
>  config NET_DSA_TAG_TRAILER
> -       bool
> +       bool "tag trailer"
>         default n
>
>  endif
>
>
> --
>  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
>
> Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
> <http://twitter.com/#!/linaroorg> Twitter |
> <http://www.linaro.org/linaro-blog/> Blog
>

^ permalink raw reply

* Re: switching network namespace midway
From: James Chapman @ 2012-10-30  8:55 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: Stephen Hemminger, Benjamin LaHaise, rsa, netdev
In-Reply-To: <87a9v47qsl.fsf@xmission.com>

On 30/10/12 00:21, Eric W. Biederman wrote:
> Stephen Hemminger <shemminger@vyatta.com> writes:
> 
>> On Sat, 27 Oct 2012 22:43:13 -0700
>> ebiederm@xmission.com (Eric W. Biederman) wrote:
>>
>>> Stephen Hemminger <shemminger@vyatta.com> writes:
>>>
>>>> I noticed that the L2TP sockets are not being moved to the correct name
>>>> space.
>>>>
>>>> Something like this is probably needed.
>>>
>>> This is almost right.
>>>
>>> There needs to be a line in l2tp_tunnel_create that verifies
>>> the network namespace of the socket derived from a file descriptor
>>> and the passed in network namespace match.
>>>
>>> For the l2tp_tunnel_sock_create case where we have a socket that is not
>>> exported to userspace using sk_change_net seems appropriate to avoid
>>> reference counting problems.  And it may be worth moving that work into
>>> sk_create_kern.  But we need a network namespace hook that will lookup
>>> all l2tp tunnel sockets when a network namespace is being destroyed and
>>> remove them.  I think we can hit this bug with rmmod as well.
>>
>> Since I don't use netns or L2TP for real, someone else needs to take
>> up the crusade here.
> 
> Let's see if James Chapman is interested.  I don't use L2TP for real either.
> 
> James are you at all interested in the network namespace bugs that have
> been found in the l2tp code?

Very much so, Eric. Thanks for keeping me in the loop. Unfortunately, I
am busy on other things at the moment. It's in my queue. I'll get to it
as soon as I can.

> 
> Eric


-- 
James Chapman
Katalix Systems Ltd
http://www.katalix.com
Catalysts for your Embedded Linux software development

^ permalink raw reply

* IPV6_PKTINFO seems not to be honored correctly by RAW-sockets
From: Steven Barth @ 2012-10-30  8:58 UTC (permalink / raw)
  To: netdev; +Cc: Steven Barth

Hi,

I recently noticed that there might be an unexpected behavior in the 
handling of IPV6_PKTINFO for RAW-sockets. It seems that the given 
destination interface is ignored.

I just reproduced this on 3.7.0-rc3 vanilla but some quick tests with 
2.6.32 and 3.5 distro-kernels on different machines showed the same.

I've noticed this first in my own software but I could also reproduce it 
easily with standard tools like ping6 from iputils:

Have 2 network interfaces with (global) IPv6-addresses assigned (e.g. 
eth0 with fd00::1/64 and eth1 with fd01::1/64) and do a ping6 -I eth1 
fd00::1 (ping6 from iputils uses IPV6_PKTINFO internally).

For me the result was that even though I set the interface to eth1 the 
ECHO was still send to eth0.

Also (although probably unrelated) forwarding for IPv6 was disabled.

If I try something similar with IPv4 and ping -I ... the ECHO doesn't go 
out on eth0 but - as expected - on eth1.

However if I use traceroute(6) with -I (ICMP-traceroute) and the -i 
option to determine the interface, packages seem to be sent through the 
expected interface. Internally it seems that traceroute(6) uses 
SO_BINDTODEVICE instead of IP(V6)_PKTINFO which seems to work.

So it seems there might be something wrong with IPV6_PKTINFO or is this 
expected behavior?


Thanks and Regards,

Steven

^ permalink raw reply

* Re: [uclinux-dist-devel] [PATCH RFC net-next 2/4] bfin_mac: replace sys time stamps with raw ones instead.
From: Bob Liu @ 2012-10-30  9:17 UTC (permalink / raw)
  To: Richard Cochran
  Cc: netdev, Miroslav Lichvar, John Ronciak, John Stultz, Jeff Kirsher,
	device-drivers-devel, Jacob Keller, uclinux-dist-devel,
	Patrick Ohly, David Miller
In-Reply-To: <84396eacd75b4abed36a7819d8c2c33f9ced1ad5.1348851539.git.richardcochran@gmail.com>

On Sat, Sep 29, 2012 at 1:20 AM, Richard Cochran
<richardcochran@gmail.com> wrote:
> This patch replaces the sys time stamps and timecompare code with simple
> raw hardware time stamps in nanosecond resolution. The only tricky bit is
> to find a PTP Hardware Clock period slower than the input clock period
> and a power of two.
>
> Compile tested only.
>
> Signed-off-by: Richard Cochran <richardcochran@gmail.com>
> ---
>  drivers/net/ethernet/adi/bfin_mac.c |   91 ++++++++++-------------------------
>  drivers/net/ethernet/adi/bfin_mac.h |    7 +--
>  2 files changed, 28 insertions(+), 70 deletions(-)
>
> diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
> index 2349abb..393d1b5 100644
> --- a/drivers/net/ethernet/adi/bfin_mac.c
> +++ b/drivers/net/ethernet/adi/bfin_mac.c
> @@ -555,7 +555,7 @@ static int bfin_mac_ethtool_get_ts_info(struct net_device *dev,
>         info->so_timestamping =
>                 SOF_TIMESTAMPING_TX_HARDWARE |
>                 SOF_TIMESTAMPING_RX_HARDWARE |
> -               SOF_TIMESTAMPING_SYS_HARDWARE;
> +               SOF_TIMESTAMPING_RAW_HARDWARE;
>         info->phc_index = -1;
>         info->tx_types =
>                 (1 << HWTSTAMP_TX_OFF) |
> @@ -653,6 +653,20 @@ static int bfin_mac_set_mac_address(struct net_device *dev, void *p)
>  #ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
>  #define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE)
>
> +static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result)
> +{
> +       u32 ipn = 1000000000UL / input_clk;
> +       u32 ppn = 1;
> +       unsigned int shift = 0;
> +
> +       while (ppn <= ipn) {
> +               ppn <<= 1;
> +               shift++;
> +       }
> +       *shift_result = shift;
> +       return 1000000000UL / ppn;
> +}
> +
>  static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
>                 struct ifreq *ifr, int cmd)
>  {
> @@ -802,19 +816,7 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
>                 bfin_read_EMAC_PTP_TXSNAPLO();
>                 bfin_read_EMAC_PTP_TXSNAPHI();
>
> -               /*
> -                * Set registers so that rollover occurs soon to test this.
> -                */
> -               bfin_write_EMAC_PTP_TIMELO(0x00000000);
> -               bfin_write_EMAC_PTP_TIMEHI(0xFF800000);
> -
>                 SSYNC();
> -
> -               lp->compare.last_update = 0;
> -               timecounter_init(&lp->clock,
> -                               &lp->cycles,
> -                               ktime_to_ns(ktime_get_real()));
> -               timecompare_update(&lp->compare, 0);
>         }
>
>         lp->stamp_cfg = config;
> @@ -822,15 +824,6 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
>                 -EFAULT : 0;
>  }
>
> -static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp)
> -{
> -       ktime_t sys = ktime_get_real();
> -
> -       pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n",
> -                       __func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec,
> -                       sys.tv.nsec, cmp->offset, cmp->skew);
> -}
> -
>  static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
>  {
>         struct bfin_mac_local *lp = netdev_priv(netdev);
> @@ -861,15 +854,9 @@ static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
>                         regval = bfin_read_EMAC_PTP_TXSNAPLO();
>                         regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32;
>                         memset(&shhwtstamps, 0, sizeof(shhwtstamps));
> -                       ns = timecounter_cyc2time(&lp->clock,
> -                                       regval);
> -                       timecompare_update(&lp->compare, ns);
> +                       ns = regval >> lp->shift;
>                         shhwtstamps.hwtstamp = ns_to_ktime(ns);
> -                       shhwtstamps.syststamp =
> -                               timecompare_transform(&lp->compare, ns);
>                         skb_tstamp_tx(skb, &shhwtstamps);
> -
> -                       bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare);
>                 }
>         }
>  }
> @@ -892,51 +879,25 @@ static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
>
>         regval = bfin_read_EMAC_PTP_RXSNAPLO();
>         regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32;
> -       ns = timecounter_cyc2time(&lp->clock, regval);
> -       timecompare_update(&lp->compare, ns);
> +       ns = regval >> lp->shift;
>         memset(shhwtstamps, 0, sizeof(*shhwtstamps));
>         shhwtstamps->hwtstamp = ns_to_ktime(ns);
> -       shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns);
> -
> -       bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare);
> -}

In my test,  system time in slave side can't be updated although here
have set shhwtstamps->hwtstamp = ns_to_ktime(ns).
Any idea?

> -
> -/*
> - * bfin_read_clock - read raw cycle counter (to be used by time counter)
> - */
> -static cycle_t bfin_read_clock(const struct cyclecounter *tc)
> -{
> -       u64 stamp;
> -
> -       stamp =  bfin_read_EMAC_PTP_TIMELO();
> -       stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL;
> -
> -       return stamp;
>  }
>
> -#define PTP_CLK 25000000
> -
>  static void bfin_mac_hwtstamp_init(struct net_device *netdev)
>  {
>         struct bfin_mac_local *lp = netdev_priv(netdev);
> -       u64 append;
> +       u64 addend;
> +       u32 input_clk, phc_clk;
>
>         /* Initialize hardware timer */
> -       append = PTP_CLK * (1ULL << 32);
> -       do_div(append, get_sclk());
> -       bfin_write_EMAC_PTP_ADDEND((u32)append);
> -
> -       memset(&lp->cycles, 0, sizeof(lp->cycles));
> -       lp->cycles.read = bfin_read_clock;
> -       lp->cycles.mask = CLOCKSOURCE_MASK(64);
> -       lp->cycles.mult = 1000000000 / PTP_CLK;
> -       lp->cycles.shift = 0;
> -
> -       /* Synchronize our NIC clock against system wall clock */
> -       memset(&lp->compare, 0, sizeof(lp->compare));
> -       lp->compare.source = &lp->clock;
> -       lp->compare.target = ktime_get_real;
> -       lp->compare.num_samples = 10;
> +       input_clk = get_sclk();
> +       phc_clk = bfin_select_phc_clock(input_clk, &lp->shift);
> +       addend = phc_clk * (1ULL << 32);
> +       do_div(addend, input_clk);
> +       bfin_write_EMAC_PTP_ADDEND((u32)addend);
> +
> +       lp->addend = addend;
>
>         /* Initialize hwstamp config */
>         lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
> diff --git a/drivers/net/ethernet/adi/bfin_mac.h b/drivers/net/ethernet/adi/bfin_mac.h
> index 960905c..57f042c 100644
> --- a/drivers/net/ethernet/adi/bfin_mac.h
> +++ b/drivers/net/ethernet/adi/bfin_mac.h
> @@ -11,8 +11,6 @@
>  #define _BFIN_MAC_H_
>
>  #include <linux/net_tstamp.h>
> -#include <linux/clocksource.h>
> -#include <linux/timecompare.h>
>  #include <linux/timer.h>
>  #include <linux/etherdevice.h>
>  #include <linux/bfin_mac.h>
> @@ -94,9 +92,8 @@ struct bfin_mac_local {
>         struct mii_bus *mii_bus;
>
>  #if defined(CONFIG_BFIN_MAC_USE_HWSTAMP)
> -       struct cyclecounter cycles;
> -       struct timecounter clock;
> -       struct timecompare compare;
> +       u32 addend;
> +       unsigned int shift;
>         struct hwtstamp_config stamp_cfg;
>  #endif
>  };
> --
> 1.7.2.5
>
> _______________________________________________
> Uclinux-dist-devel mailing list
> Uclinux-dist-devel@blackfin.uclinux.org
> https://blackfin.uclinux.org/mailman/listinfo/uclinux-dist-devel



-- 
Regards,
--Bob

^ permalink raw reply

* Re: [PATCH] net: dsa/slave: Fix compilation warnings
From: Daniel Lezcano @ 2012-10-30  9:26 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Ben Hutchings, netdev, linaro-dev, davem, linux-kernel, patches
In-Reply-To: <CAKohpon8C5O4U+h3nr=8gaEQ1f-K9pqafw=5jPrhaGup_3re=g@mail.gmail.com>

On 10/30/2012 10:03 AM, Viresh Kumar wrote:
> On 30 October 2012 14:30, Daniel Lezcano <daniel.lezcano@linaro.org> wrote:
>> It is very curious if we disable all the configs option, a slave
>> creation raise a BUG (cf. dsa_slave_create). IIUC, booting with NET_DSA
>> enabled and none of the NET_DSA_TAG* enabled will raise a BUG in the
>> probe function, right ?
>>
>> Maybe we should force at least one config when none are set ?
> 
> I thought of it earlier. But found the one which i posted better. As we will not
> compile DSA stuff now without these tags.

Well, it is the same here, no ? Except, it is up to the user to disable
the option.


> 
> --
> viresh
> 
>> diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
>> index 274791c..86326e3 100644
>> --- a/net/dsa/Kconfig
>> +++ b/net/dsa/Kconfig
>> @@ -1,8 +1,9 @@
>> -config NET_DSA
>> +menuconfig NET_DSA
>>         tristate "Distributed Switch Architecture support"
>>         default n
>>         depends on EXPERIMENTAL && NETDEVICES && !S390
>>         select PHYLIB
>> +       select NET_DSA_TAG_DSA if (!NET_DSA_TAG_EDSA &&
>> !NET_DSA_TAG_TRAILER)
>>         ---help---
>>           This allows you to use hardware switch chips that use
>>           the Distributed Switch Architecture.
>> @@ -12,15 +13,15 @@ if NET_DSA
>>
>>  # tagging formats
>>  config NET_DSA_TAG_DSA
>> -       bool
>> +       bool "tag dsa"
>>         default n
>>
>>  config NET_DSA_TAG_EDSA
>> -       bool
>> +       bool "tag edsa"
>>         default n
>>
>>  config NET_DSA_TAG_TRAILER
>> -       bool
>> +       bool "tag trailer"
>>         default n
>>
>>  endif
>>
>>
>> --
>>  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
>>
>> Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
>> <http://twitter.com/#!/linaroorg> Twitter |
>> <http://www.linaro.org/linaro-blog/> Blog
>>


-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply

* Re: [PATCH v2 1/3] pppoatm: don't send frames to destroyed vcc
From: David Woodhouse @ 2012-10-30  9:35 UTC (permalink / raw)
  To: Krzysztof Mazur; +Cc: davem, netdev, linux-kernel
In-Reply-To: <1350926091-12642-1-git-send-email-krzysiek@podlesie.net>

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

On Mon, 2012-10-22 at 19:14 +0200, Krzysztof Mazur wrote:
> Now pppoatm_send(), like vcc_sendmsg(), checks for vcc flags that
> indicate that vcc is not ready.

I note that vcc_sendmsg() also checks for sock->state == SS_CONNECTED.
Is that check not needed here? Otherwise, looks sane enough.

Acked-By: David Woodhouse <David.Woodhouse@intel.com>

-- 
dwmw2


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6171 bytes --]

^ permalink raw reply

* Re: [PATCH v2 2/3] pppoatm: fix race condition with destroying of vcc
From: David Woodhouse @ 2012-10-30  9:37 UTC (permalink / raw)
  To: Krzysztof Mazur; +Cc: davem, netdev, linux-kernel
In-Reply-To: <1350926091-12642-2-git-send-email-krzysiek@podlesie.net>

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

On Mon, 2012-10-22 at 19:14 +0200, Krzysztof Mazur wrote:
> The pppoatm_send() calls vcc->send() and now also checks for
> some vcc flags that indicate destroyed vcc without proper locking.
> 
> The vcc_sendmsg() uses lock_sock(sk). This lock is used by
> vcc_release(), so vcc_destroy_socket() will not be called between
> check and during ->send(). The vcc_release_async() sets ATM_VF_CLOSE,
> but it should be safe to call ->send() after it, because
> vcc->dev->ops->close() is not called.
> 
> The pppoatm_send() is called with BH disabled, so bh_lock_sock()
> should be used instead of lock_sock().

Should we be locking it earlier, so that the atm_may_send() call is also
covered by the lock?

Either way, it's an obvious improvement on what we had before — and even
if the answer to my question above is 'yes', exceeding the configured
size by one packet is both harmless and almost never going to happen
since we now limit ourselves to two packets anyway. So:

Acked-By: David Woodhouse <David.Woodhouse@intel.com>

-- 
dwmw2


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6171 bytes --]

^ permalink raw reply

* Re: [PATCH v2 3/3] pppoatm: protect against freeing of vcc
From: David Woodhouse @ 2012-10-30  9:39 UTC (permalink / raw)
  To: Krzysztof Mazur; +Cc: davem, netdev, linux-kernel
In-Reply-To: <1350926091-12642-3-git-send-email-krzysiek@podlesie.net>

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

On Mon, 2012-10-22 at 19:14 +0200, Krzysztof Mazur wrote:
> The pppoatm gets a reference to atmvcc, but does not increment vcc
> usage count. The vcc uses vcc->sk socket for reference counting,
> so sock_hold() and sock_put() should be used by pppoatm.
> 
> Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
> Cc: David Woodhouse <dwmw2@infradead.org>

Acked-By: David Woodhouse <David.Woodhouse@intel.com>

But did you spot what's in the end of the context of the first hunk...?

> --- a/net/atm/pppoatm.c
> +++ b/net/atm/pppoatm.c
> @@ -154,6 +154,7 @@ static void pppoatm_unassign_vcc(struct atm_vcc
> *atmvcc)
>         tasklet_kill(&pvcc->wakeup_tasklet);
>         ppp_unregister_channel(&pvcc->chan);
>         atmvcc->user_back = NULL;
> +       sock_put(sk_atm(pvcc->atmvcc));
>         kfree(pvcc);
>         /* Gee, I hope we have the big kernel lock here... */
>         module_put(THIS_MODULE);

Fairly sure that hope is unfounded these days... :)

-- 
dwmw2


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6171 bytes --]

^ permalink raw reply

* [PATCH 1/1] l2tp: fix oops in l2tp_eth_create() error path
From: Tom Parkin @ 2012-10-30  9:41 UTC (permalink / raw)
  To: netdev; +Cc: jchapman, Tom Parkin

When creating an L2TPv3 Ethernet session, if register_netdev() should fail for
any reason (for example, automatic naming for "l2tpeth%d" interfaces hits the
32k-interface limit), the netdev is freed in the error path.  However, the
l2tp_eth_sess structure's dev pointer is left uncleared, and this results in
l2tp_eth_delete() then attempting to unregister the same netdev later in the
session teardown.  This results in an oops.

To avoid this, clear the session dev pointer in the error path.

Signed-off-by: Tom Parkin <tparkin@katalix.com>
---
 net/l2tp/l2tp_eth.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index 37b8b8b..76125c5 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
 
 out_del_dev:
 	free_netdev(dev);
+	spriv->dev = NULL;
 out_del_session:
 	l2tp_session_delete(session);
 out:
-- 
1.7.9.5

^ permalink raw reply related

* Re: [PATCH] net: dsa/slave: Fix compilation warnings
From: Viresh Kumar @ 2012-10-30  9:45 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: Ben Hutchings, netdev, linaro-dev, davem, linux-kernel, patches
In-Reply-To: <508F9D5C.2020802@linaro.org>

On 30 October 2012 14:56, Daniel Lezcano <daniel.lezcano@linaro.org> wrote:
> Well, it is the same here, no ? Except, it is up to the user to disable
> the option.

I didn't wanted to add code like this:

>> +       select NET_DSA_TAG_DSA if (!NET_DSA_TAG_EDSA &&
>> !NET_DSA_TAG_TRAILER)

Why should we select NET_DSA_TAG_DSA by default? What made us
select that?

For this reason, i went to the solution i offered.

Anyway, i just wanted to get rid of the warning. Whatever maintainer
feels is better must be selected.

--
viresh

^ permalink raw reply

* Re: [PATCH 1/1] net: macb: add pinctrl consumer support
From: Nicolas Ferre @ 2012-10-30 10:47 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: linux-arm-kernel, netdev
In-Reply-To: <1351352997-31116-1-git-send-email-plagnioj@jcrosoft.com>

On 10/27/2012 05:49 PM, Jean-Christophe PLAGNIOL-VILLARD :
> If no pinctrl available just report a warning as some architecture may not
> need to do anything.
> 
> Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
> Cc: netdev@vger.kernel.org
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> ---
>  drivers/net/ethernet/cadence/macb.c |   13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
> index 033064b..e5fdf8a 100644
> --- a/drivers/net/ethernet/cadence/macb.c
> +++ b/drivers/net/ethernet/cadence/macb.c
> @@ -26,6 +26,9 @@
>  #include <linux/of.h>
>  #include <linux/of_device.h>
>  #include <linux/of_net.h>
> +#include <linux/of_gpio.h>
> +#include <linux/gpio.h>
> +#include <linux/pinctrl/consumer.h>
>  
>  #include "macb.h"
>  
> @@ -1306,6 +1309,7 @@ static int __init macb_probe(struct platform_device *pdev)
>  	struct phy_device *phydev;
>  	u32 config;
>  	int err = -ENXIO;
> +	struct pinctrl *pinctrl;
>  
>  	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	if (!regs) {
> @@ -1313,6 +1317,15 @@ static int __init macb_probe(struct platform_device *pdev)
>  		goto err_out;
>  	}
>  
> +	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
> +	if (IS_ERR(pinctrl)) {
> +		err = PTR_ERR(pinctrl);
> +		if (err == -EPROBE_DEFER)
> +			return err;

I will modify this to be consistent with error path before and after
this change => goto err_out.
Do not bother to re-submit a patch, I will include this one in my
upcoming patch series.

Thanks,

> +
> +		dev_warn(&pdev->dev, "No pinctrl provided\n");
> +	}
> +
>  	err = -ENOMEM;
>  	dev = alloc_etherdev(sizeof(*bp));
>  	if (!dev)
> 


-- 
Nicolas Ferre

^ permalink raw reply

* Re: [PATCH v4] Network driver for the Armada 370 and Armada XP ARM Marvell SoCs
From: Thomas Petazzoni @ 2012-10-30  9:51 UTC (permalink / raw)
  To: Eric Dumazet, David S. Miller, Lennert Buytenhek, Francois Romieu
  Cc: netdev, linux-arm-kernel, Jason Cooper, Andrew Lunn,
	Gregory Clement, Lior Amsalem, Maen Suleiman
In-Reply-To: <1351245804-31478-1-git-send-email-thomas.petazzoni@free-electrons.com>

Hello,

On Fri, 26 Oct 2012 12:03:20 +0200, Thomas Petazzoni wrote:

> This patch set adds a new network driver for the network unit
> available in the newest Marvell ARM SoCs Armada 370 and Armada XP, as
> well as the necessary Device Tree information to use this driver in
> the two evaluation platforms of those SoCs.

Besides Nobuhiro's small comment on the Device Tree part, are there any
comments on the driver itself, or is the code good to go?

I can send a fifth version with just the fix for Nobuhiro's comment,
but it probably makes sense to take into account a few more comments
(if any) at the same time.

Thanks for your review,

Thomas
-- 
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [rfc net-next v6 0/3] Multiqueue virtio-net
From: Jason Wang @ 2012-10-30 10:03 UTC (permalink / raw)
  To: mst, davem, virtualization, linux-kernel, netdev, rusty, krkumar2; +Cc: kvm

Hi all:

This series is an update version of multiqueue virtio-net driver based on
Krishna Kumar's work to let virtio-net use multiple rx/tx queues to do the
packets reception and transmission. Please review and comments.

Changes from v5:
- Align the implementation with the RFC spec update v4
- Switch the mode between single mode and multiqueue mode without reset
- Remove the 256 limitation of queues
- Use helpers to do the mapping between virtqueues and tx/rx queues
- Use commbined channels instead of separated rx/tx queus when do the queue
number configuartion
- Other coding style comments from Michael

Reference:
- A protype implementation of qemu-kvm support could by found in
git://github.com/jasowang/qemu-kvm-mq.git
- V5 could be found at http://lwn.net/Articles/505388/
- V4 could be found at https://lkml.org/lkml/2012/6/25/120
- V2 could be found at http://lwn.net/Articles/467283/
- Michael virtio-spec: http://www.spinics.net/lists/netdev/msg209986.html

Perf Numbers:

- Pktgen test shows the receiving capability of the multiqueue virtio-net were
  dramatically improved.
- Netperf result shows latency were greately improved according to the test
result. The throughput were kept or improved when transfter with large
packets. But we get regression with small packet (<1500)
transmission/receiving. According to the satistics, TCP tends batch less when mq
is enabled which means much more but smaller pakcets were sent/received whcih
lead much higher cpu utilization and degradate the throughput. In the future,
either tuning of TCP or automatic switch bettwen mq and sq is needed.

Test environment:
- Intel(R) Xeon(R) CPU E5620 @ 2.40GHz, 8 cores 2 numa nodes
- Two directed connected 82599
- Host/Guest kenrel: net-next with the mq virtio-net patches and mq tuntap
patches

Pktgen test:
- Local host generate 64 byte UDP packet to guest.
- average of 20 runs

20 runs
#q #vcpu   kpps     +improvement
1q 1vcpu:  264kpps  +0%
2q 2vcpu:  451kpps  +70%
3q 3vcpu:  661kpps  +150%
4q 4vcpu:  941kpps  +250%

Netperf Local VM to VM test:
- VM1 and its vcpu/vhost thread in numa node 0
- VM2 and its vcpu/vhost thread in numa node 1
- a script is used to lauch the netperf with demo mode and do the postprocessing
  to measure the aggreagte result with the help of timestamp
- average of 3 runs

TCP_RR:
size/session/+lat%/+normalize%
    1/     1/    0%/    0%
    1/    10/  +52%/   +6%
    1/    20/  +27%/   +5%
   64/     1/    0%/    0%
   64/    10/  +45%/   +4%
   64/    20/  +28%/   +7%
  256/     1/   -1%/    0%
  256/    10/  +38%/   +2%
  256/    20/  +27%/   +6%
TCP_CRR:
size/session/+lat%/+normalize%
    1/     1/   -7%/  -12%
    1/    10/  +34%/   +3%
    1/    20/   +3%/   -8%
   64/     1/   -7%/   -3%
   64/    10/  +32%/   +1%
   64/    20/   +4%/   -7%
  256/     1/   -6%/  -18%
  256/    10/  +33%/    0%
  256/    20/   +4%/   -8%
STREAM:
size/session/+thu%/+normalize%
    1/     1/   -3%/    0%
    1/     2/   -1%/    0%
    1/     4/   -2%/    0%
   64/     1/    0%/   +1%
   64/     2/   -6%/   -6%
   64/     4/   -8%/  -14%
  256/     1/    0%/    0%
  256/     2/  -48%/  -52%
  256/     4/  -50%/  -55%
  512/     1/   +4%/   +5%
  512/     2/  -29%/  -33%
  512/     4/  -37%/  -49%
 1024/     1/   +6%/   +7%
 1024/     2/  -46%/  -51%
 1024/     4/  -15%/  -17%
 4096/     1/   +1%/   +1%
 4096/     2/  +16%/   -2%
 4096/     4/  +31%/  -10%
16384/     1/    0%/    0%
16384/     2/  +16%/   +9%
16384/     4/  +17%/   -9%

Netperf test between external host and guest over 10gb(ixgbe):
- VM thread and vhost threads were pinned int the node 0
- a script is used to lauch the netperf with demo mode and do the postprocessing
  to measure the aggreagte result with the help of timestamp
- average of 3 runs

TCP_RR:
size/session/+lat%/+normalize%
    1/     1/    0%/   +6%
    1/    10/  +41%/   +2%
    1/    20/  +10%/   -3%
   64/     1/    0%/  -10%
   64/    10/  +39%/   +1%
   64/    20/  +22%/   +2%
  256/     1/    0%/   +2%
  256/    10/  +26%/  -17%
  256/    20/  +24%/  +10%
TCP_CRR:
size/session/+lat%/+normalize%
    1/     1/   -3%/   -3%
    1/    10/  +34%/   -3%
    1/    20/    0%/  -15%
   64/     1/   -3%/   -3%
   64/    10/  +34%/   -3%
   64/    20/   -1%/  -16%
  256/     1/   -1%/   -3%
  256/    10/  +38%/   -2%
  256/    20/   -2%/  -17%
TCP_STREAM:(guest receiving)
size/session/+thu%/+normalize%
    1/     1/   +1%/  +14%
    1/     2/    0%/   +4%
    1/     4/   -2%/  -24%
   64/     1/   -6%/   +1%
   64/     2/   +1%/   +1%
   64/     4/   -1%/  -11%
  256/     1/   +3%/   +4%
  256/     2/    0%/   -1%
  256/     4/    0%/  -15%
  512/     1/   +4%/    0%
  512/     2/  -10%/  -12%
  512/     4/    0%/  -11%
 1024/     1/   -5%/    0%
 1024/     2/  -11%/  -16%
 1024/     4/   +3%/  -11%
 4096/     1/  +27%/   +6%
 4096/     2/    0%/  -12%
 4096/     4/    0%/  -20%
16384/     1/    0%/   -2%
16384/     2/    0%/   -9%
16384/     4/  +10%/   -2%
TCP_MAERTS:(guest sending)
    1/     1/   -1%/    0%
    1/     2/    0%/    0%
    1/     4/   -5%/    0%
   64/     1/    0%/    0%
   64/     2/   -7%/   -8%
   64/     4/   -7%/   -8%
  256/     1/    0%/    0%
  256/     2/  -28%/  -28%
  256/     4/  -28%/  -29%
  512/     1/    0%/    0%
  512/     2/  -15%/  -13%
  512/     4/  -53%/  -59%
 1024/     1/   +4%/  +13%
 1024/     2/   -7%/  -18%
 1024/     4/   +1%/  -18%
 4096/     1/   +2%/    0%
 4096/     2/   +3%/  -19%
 4096/     4/   -1%/  -19%
16384/     1/   -3%/   -1%
16384/     2/    0%/  -12%
16384/     4/    0%/  -10%

Jason Wang (2):
  virtio_net: multiqueue support
  virtio-net: change the number of queues through ethtool

Krishna Kumar (1):
  virtio_net: Introduce VIRTIO_NET_F_MULTIQUEUE

 drivers/net/virtio_net.c        |  790 ++++++++++++++++++++++++++++-----------
 include/uapi/linux/virtio_net.h |   19 +
 2 files changed, 594 insertions(+), 215 deletions(-)

^ permalink raw reply

* [rfc net-next v6 1/3] virtio_net: Introduce VIRTIO_NET_F_MULTIQUEUE
From: Jason Wang @ 2012-10-30 10:03 UTC (permalink / raw)
  To: mst, davem, virtualization, linux-kernel, netdev, rusty, krkumar2; +Cc: kvm
In-Reply-To: <1351591403-23065-1-git-send-email-jasowang@redhat.com>

From: Krishna Kumar <krkumar2@in.ibm.com>

Introduce VIRTIO_NET_F_MULTIQUEUE.

Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 include/uapi/linux/virtio_net.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index 2470f54..1bc7e30 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -51,6 +51,7 @@
 #define VIRTIO_NET_F_CTRL_RX_EXTRA 20	/* Extra RX mode control support */
 #define VIRTIO_NET_F_GUEST_ANNOUNCE 21	/* Guest can announce device on the
 					 * network */
+#define VIRTIO_NET_F_MULTIQUEUE	22	/* Device supports multiple TXQ/RXQ */
 
 #define VIRTIO_NET_S_LINK_UP	1	/* Link is up */
 #define VIRTIO_NET_S_ANNOUNCE	2	/* Announcement is needed */
-- 
1.7.1

^ permalink raw reply related

* [rfc net-next v6 2/3] virtio_net: multiqueue support
From: Jason Wang @ 2012-10-30 10:03 UTC (permalink / raw)
  To: mst, davem, virtualization, linux-kernel, netdev, rusty, krkumar2; +Cc: kvm
In-Reply-To: <1351591403-23065-1-git-send-email-jasowang@redhat.com>

This addes multiqueue support to virtio_net driver. There's two mode supported:
single queue pair mode and multiple queue pairs mode. An obvious difference
compared with a physical mq card is that virtio-net reserve first two virtqueues
when it is working in multiqueue mode, this is used for implementing adaptive
mode switching in the future. The virtqueues that were in both mq and sq mode
were initialized and only one queue pair (single queue mode) were used at
default. User could use ethtool -L to switch to multiqueue mode withe the next
patch.

In multiple queue modes, the driver expects the number of queue paris is equal
to the number of vcpus. In the case, each vcpu would have its private virtqueue
pairs through:

- select the txq based on the smp processor id.
- smp affinity hint were set to the vcpu that owns the queue pairs.

To make sure a single vcpu is handling the packets from the same flow, driver
would let the device (usually tuntap) to use the 'rx follows tx' packet steering
rules when working in multiqueue mode. In this mode, the device would select the
rxq based on the last queue where the packet of the flow were sent.

Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 drivers/net/virtio_net.c        |  747 ++++++++++++++++++++++++++++-----------
 include/uapi/linux/virtio_net.h |   18 +
 2 files changed, 550 insertions(+), 215 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index cbf8b06..8cc43e5 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -26,6 +26,7 @@
 #include <linux/scatterlist.h>
 #include <linux/if_vlan.h>
 #include <linux/slab.h>
+#include <linux/interrupt.h>
 
 static int napi_weight = 128;
 module_param(napi_weight, int, 0444);
@@ -51,43 +52,70 @@ struct virtnet_stats {
 	u64 rx_packets;
 };
 
-struct virtnet_info {
-	struct virtio_device *vdev;
-	struct virtqueue *rvq, *svq, *cvq;
-	struct net_device *dev;
+/* Internal representation of a send virtqueue */
+struct send_queue {
+	/* Virtqueue associated with this send _queue */
+	struct virtqueue *vq;
+
+	/* TX: fragments + linear part + virtio header */
+	struct scatterlist sg[MAX_SKB_FRAGS + 2];
+};
+
+/* Internal representation of a receive virtqueue */
+struct receive_queue {
+	/* Virtqueue associated with this receive_queue */
+	struct virtqueue *vq;
+
+	/* Back pointer to the virtnet_info */
+	struct virtnet_info *vi;
+
 	struct napi_struct napi;
-	unsigned int status;
 
 	/* Number of input buffers, and max we've ever had. */
 	unsigned int num, max;
 
+	/* Work struct for refilling if we run low on memory. */
+	struct delayed_work refill;
+
+	/* Chain pages by the private ptr. */
+	struct page *pages;
+
+	/* RX: fragments + linear part + virtio header */
+	struct scatterlist sg[MAX_SKB_FRAGS + 2];
+};
+
+struct virtnet_info {
+	u16 num_queue_pairs;		/* # of RX/TX vq pairs */
+	u16 total_queue_pairs;
+
+	struct send_queue *sq;
+	struct receive_queue *rq;
+	struct virtqueue *cvq;
+
+	struct virtio_device *vdev;
+	struct net_device *dev;
+	unsigned int status;
+
 	/* I like... big packets and I cannot lie! */
 	bool big_packets;
 
 	/* Host will merge rx buffers for big packets (shake it! shake it!) */
 	bool mergeable_rx_bufs;
 
+	/* Has control virtqueue */
+	bool has_cvq;
+
 	/* enable config space updates */
 	bool config_enable;
 
 	/* Active statistics */
 	struct virtnet_stats __percpu *stats;
 
-	/* Work struct for refilling if we run low on memory. */
-	struct delayed_work refill;
-
 	/* Work struct for config space updates */
 	struct work_struct config_work;
 
 	/* Lock for config space updates */
 	struct mutex config_lock;
-
-	/* Chain pages by the private ptr. */
-	struct page *pages;
-
-	/* fragments + linear part + virtio header */
-	struct scatterlist rx_sg[MAX_SKB_FRAGS + 2];
-	struct scatterlist tx_sg[MAX_SKB_FRAGS + 2];
 };
 
 struct skb_vnet_hdr {
@@ -108,6 +136,30 @@ struct padded_vnet_hdr {
 	char padding[6];
 };
 
+static const struct ethtool_ops virtnet_ethtool_ops;
+
+static inline int vq2txq(struct virtqueue *vq)
+{
+	int index = virtqueue_get_queue_index(vq);
+	return index == 1 ? 0 : (index - 3) / 2;
+}
+
+static inline int txq2vq(int txq)
+{
+	return txq ? 2 * txq + 3 : 1;
+}
+
+static inline int vq2rxq(struct virtqueue *vq)
+{
+	int index = virtqueue_get_queue_index(vq);
+	return index ? (index - 2) / 2 : 0;
+}
+
+static inline int rxq2vq(int rxq)
+{
+	return rxq ? 2 * rxq + 2 : 0;
+}
+
 static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
 {
 	return (struct skb_vnet_hdr *)skb->cb;
@@ -117,22 +169,22 @@ static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
  * private is used to chain pages for big packets, put the whole
  * most recent used list in the beginning for reuse
  */
-static void give_pages(struct virtnet_info *vi, struct page *page)
+static void give_pages(struct receive_queue *rq, struct page *page)
 {
 	struct page *end;
 
 	/* Find end of list, sew whole thing into vi->pages. */
 	for (end = page; end->private; end = (struct page *)end->private);
-	end->private = (unsigned long)vi->pages;
-	vi->pages = page;
+	end->private = (unsigned long)rq->pages;
+	rq->pages = page;
 }
 
-static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
+static struct page *get_a_page(struct receive_queue *rq, gfp_t gfp_mask)
 {
-	struct page *p = vi->pages;
+	struct page *p = rq->pages;
 
 	if (p) {
-		vi->pages = (struct page *)p->private;
+		rq->pages = (struct page *)p->private;
 		/* clear private here, it is used to chain pages */
 		p->private = 0;
 	} else
@@ -140,15 +192,15 @@ static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
 	return p;
 }
 
-static void skb_xmit_done(struct virtqueue *svq)
+static void skb_xmit_done(struct virtqueue *vq)
 {
-	struct virtnet_info *vi = svq->vdev->priv;
+	struct virtnet_info *vi = vq->vdev->priv;
 
 	/* Suppress further interrupts. */
-	virtqueue_disable_cb(svq);
+	virtqueue_disable_cb(vq);
 
 	/* We were probably waiting for more output buffers. */
-	netif_wake_queue(vi->dev);
+	netif_wake_subqueue(vi->dev, vq2txq(vq));
 }
 
 static void set_skb_frag(struct sk_buff *skb, struct page *page,
@@ -167,9 +219,10 @@ static void set_skb_frag(struct sk_buff *skb, struct page *page,
 }
 
 /* Called from bottom half context */
-static struct sk_buff *page_to_skb(struct virtnet_info *vi,
+static struct sk_buff *page_to_skb(struct receive_queue *rq,
 				   struct page *page, unsigned int len)
 {
+	struct virtnet_info *vi = rq->vi;
 	struct sk_buff *skb;
 	struct skb_vnet_hdr *hdr;
 	unsigned int copy, hdr_len, offset;
@@ -225,12 +278,12 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
 	}
 
 	if (page)
-		give_pages(vi, page);
+		give_pages(rq, page);
 
 	return skb;
 }
 
-static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
+static int receive_mergeable(struct receive_queue *rq, struct sk_buff *skb)
 {
 	struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
 	struct page *page;
@@ -244,7 +297,7 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
 			skb->dev->stats.rx_length_errors++;
 			return -EINVAL;
 		}
-		page = virtqueue_get_buf(vi->rvq, &len);
+		page = virtqueue_get_buf(rq->vq, &len);
 		if (!page) {
 			pr_debug("%s: rx error: %d buffers missing\n",
 				 skb->dev->name, hdr->mhdr.num_buffers);
@@ -257,13 +310,14 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
 
 		set_skb_frag(skb, page, 0, &len);
 
-		--vi->num;
+		--rq->num;
 	}
 	return 0;
 }
 
-static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
+static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
 {
+	struct net_device *dev = rq->vi->dev;
 	struct virtnet_info *vi = netdev_priv(dev);
 	struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
 	struct sk_buff *skb;
@@ -274,7 +328,7 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
 		pr_debug("%s: short packet %i\n", dev->name, len);
 		dev->stats.rx_length_errors++;
 		if (vi->mergeable_rx_bufs || vi->big_packets)
-			give_pages(vi, buf);
+			give_pages(rq, buf);
 		else
 			dev_kfree_skb(buf);
 		return;
@@ -286,14 +340,14 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
 		skb_trim(skb, len);
 	} else {
 		page = buf;
-		skb = page_to_skb(vi, page, len);
+		skb = page_to_skb(rq, page, len);
 		if (unlikely(!skb)) {
 			dev->stats.rx_dropped++;
-			give_pages(vi, page);
+			give_pages(rq, page);
 			return;
 		}
 		if (vi->mergeable_rx_bufs)
-			if (receive_mergeable(vi, skb)) {
+			if (receive_mergeable(rq, skb)) {
 				dev_kfree_skb(skb);
 				return;
 			}
@@ -363,90 +417,91 @@ frame_err:
 	dev_kfree_skb(skb);
 }
 
-static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
+static int add_recvbuf_small(struct receive_queue *rq, gfp_t gfp)
 {
 	struct sk_buff *skb;
 	struct skb_vnet_hdr *hdr;
 	int err;
 
-	skb = __netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN, gfp);
+	skb = __netdev_alloc_skb_ip_align(rq->vi->dev, MAX_PACKET_LEN, gfp);
 	if (unlikely(!skb))
 		return -ENOMEM;
 
 	skb_put(skb, MAX_PACKET_LEN);
 
 	hdr = skb_vnet_hdr(skb);
-	sg_set_buf(vi->rx_sg, &hdr->hdr, sizeof hdr->hdr);
+	sg_set_buf(rq->sg, &hdr->hdr, sizeof hdr->hdr);
+
+	skb_to_sgvec(skb, rq->sg + 1, 0, skb->len);
 
-	skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len);
+	err = virtqueue_add_buf(rq->vq, rq->sg, 0, 2, skb, gfp);
 
-	err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 2, skb, gfp);
 	if (err < 0)
 		dev_kfree_skb(skb);
 
 	return err;
 }
 
-static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
+static int add_recvbuf_big(struct receive_queue *rq, gfp_t gfp)
 {
 	struct page *first, *list = NULL;
 	char *p;
 	int i, err, offset;
 
-	/* page in vi->rx_sg[MAX_SKB_FRAGS + 1] is list tail */
+	/* page in rq->sg[MAX_SKB_FRAGS + 1] is list tail */
 	for (i = MAX_SKB_FRAGS + 1; i > 1; --i) {
-		first = get_a_page(vi, gfp);
+		first = get_a_page(rq, gfp);
 		if (!first) {
 			if (list)
-				give_pages(vi, list);
+				give_pages(rq, list);
 			return -ENOMEM;
 		}
-		sg_set_buf(&vi->rx_sg[i], page_address(first), PAGE_SIZE);
+		sg_set_buf(&rq->sg[i], page_address(first), PAGE_SIZE);
 
 		/* chain new page in list head to match sg */
 		first->private = (unsigned long)list;
 		list = first;
 	}
 
-	first = get_a_page(vi, gfp);
+	first = get_a_page(rq, gfp);
 	if (!first) {
-		give_pages(vi, list);
+		give_pages(rq, list);
 		return -ENOMEM;
 	}
 	p = page_address(first);
 
-	/* vi->rx_sg[0], vi->rx_sg[1] share the same page */
-	/* a separated vi->rx_sg[0] for virtio_net_hdr only due to QEMU bug */
-	sg_set_buf(&vi->rx_sg[0], p, sizeof(struct virtio_net_hdr));
+	/* rq->sg[0], rq->sg[1] share the same page */
+	/* a separated rq->sg[0] for virtio_net_hdr only due to QEMU bug */
+	sg_set_buf(&rq->sg[0], p, sizeof(struct virtio_net_hdr));
 
-	/* vi->rx_sg[1] for data packet, from offset */
+	/* rq->sg[1] for data packet, from offset */
 	offset = sizeof(struct padded_vnet_hdr);
-	sg_set_buf(&vi->rx_sg[1], p + offset, PAGE_SIZE - offset);
+	sg_set_buf(&rq->sg[1], p + offset, PAGE_SIZE - offset);
 
 	/* chain first in list head */
 	first->private = (unsigned long)list;
-	err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
+	err = virtqueue_add_buf(rq->vq, rq->sg, 0, MAX_SKB_FRAGS + 2,
 				first, gfp);
 	if (err < 0)
-		give_pages(vi, first);
+		give_pages(rq, first);
 
 	return err;
 }
 
-static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
+static int add_recvbuf_mergeable(struct receive_queue *rq, gfp_t gfp)
 {
 	struct page *page;
 	int err;
 
-	page = get_a_page(vi, gfp);
+	page = get_a_page(rq, gfp);
 	if (!page)
 		return -ENOMEM;
 
-	sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE);
+	sg_init_one(rq->sg, page_address(page), PAGE_SIZE);
 
-	err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 1, page, gfp);
+	err = virtqueue_add_buf(rq->vq, rq->sg, 0, 1, page, gfp);
 	if (err < 0)
-		give_pages(vi, page);
+		give_pages(rq, page);
 
 	return err;
 }
@@ -458,97 +513,104 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
  * before we're receiving packets, or from refill_work which is
  * careful to disable receiving (using napi_disable).
  */
-static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
+static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp)
 {
+	struct virtnet_info *vi = rq->vi;
 	int err;
 	bool oom;
 
 	do {
 		if (vi->mergeable_rx_bufs)
-			err = add_recvbuf_mergeable(vi, gfp);
+			err = add_recvbuf_mergeable(rq, gfp);
 		else if (vi->big_packets)
-			err = add_recvbuf_big(vi, gfp);
+			err = add_recvbuf_big(rq, gfp);
 		else
-			err = add_recvbuf_small(vi, gfp);
+			err = add_recvbuf_small(rq, gfp);
 
 		oom = err == -ENOMEM;
 		if (err < 0)
 			break;
-		++vi->num;
+		++rq->num;
 	} while (err > 0);
-	if (unlikely(vi->num > vi->max))
-		vi->max = vi->num;
-	virtqueue_kick(vi->rvq);
+	if (unlikely(rq->num > rq->max))
+		rq->max = rq->num;
+	virtqueue_kick(rq->vq);
 	return !oom;
 }
 
-static void skb_recv_done(struct virtqueue *rvq)
+static void skb_recv_done(struct virtqueue *vq)
 {
-	struct virtnet_info *vi = rvq->vdev->priv;
+	struct virtnet_info *vi = vq->vdev->priv;
+	struct napi_struct *napi = &vi->rq[vq2rxq(vq)].napi;
+
 	/* Schedule NAPI, Suppress further interrupts if successful. */
-	if (napi_schedule_prep(&vi->napi)) {
-		virtqueue_disable_cb(rvq);
-		__napi_schedule(&vi->napi);
+	if (napi_schedule_prep(napi)) {
+		virtqueue_disable_cb(vq);
+		__napi_schedule(napi);
 	}
 }
 
-static void virtnet_napi_enable(struct virtnet_info *vi)
+static void virtnet_napi_enable(struct receive_queue *rq)
 {
-	napi_enable(&vi->napi);
+	napi_enable(&rq->napi);
 
 	/* If all buffers were filled by other side before we napi_enabled, we
 	 * won't get another interrupt, so process any outstanding packets
 	 * now.  virtnet_poll wants re-enable the queue, so we disable here.
 	 * We synchronize against interrupts via NAPI_STATE_SCHED */
-	if (napi_schedule_prep(&vi->napi)) {
-		virtqueue_disable_cb(vi->rvq);
+	if (napi_schedule_prep(&rq->napi)) {
+		virtqueue_disable_cb(rq->vq);
 		local_bh_disable();
-		__napi_schedule(&vi->napi);
+		__napi_schedule(&rq->napi);
 		local_bh_enable();
 	}
 }
 
 static void refill_work(struct work_struct *work)
 {
-	struct virtnet_info *vi;
+	struct napi_struct *napi;
+	struct receive_queue *rq;
 	bool still_empty;
 
-	vi = container_of(work, struct virtnet_info, refill.work);
-	napi_disable(&vi->napi);
-	still_empty = !try_fill_recv(vi, GFP_KERNEL);
-	virtnet_napi_enable(vi);
+	rq = container_of(work, struct receive_queue, refill.work);
+	napi = &rq->napi;
+
+	napi_disable(napi);
+	still_empty = !try_fill_recv(rq, GFP_KERNEL);
+	virtnet_napi_enable(rq);
 
 	/* In theory, this can happen: if we don't get any buffers in
 	 * we will *never* try to fill again. */
 	if (still_empty)
-		schedule_delayed_work(&vi->refill, HZ/2);
+		schedule_delayed_work(&rq->refill, HZ/2);
 }
 
 static int virtnet_poll(struct napi_struct *napi, int budget)
 {
-	struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
+	struct receive_queue *rq = container_of(napi, struct receive_queue,
+						napi);
 	void *buf;
 	unsigned int len, received = 0;
 
 again:
 	while (received < budget &&
-	       (buf = virtqueue_get_buf(vi->rvq, &len)) != NULL) {
-		receive_buf(vi->dev, buf, len);
-		--vi->num;
+	       (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
+		receive_buf(rq, buf, len);
+		--rq->num;
 		received++;
 	}
 
-	if (vi->num < vi->max / 2) {
-		if (!try_fill_recv(vi, GFP_ATOMIC))
-			schedule_delayed_work(&vi->refill, 0);
+	if (rq->num < rq->max / 2) {
+		if (!try_fill_recv(rq, GFP_ATOMIC))
+			schedule_delayed_work(&rq->refill, 0);
 	}
 
 	/* Out of packets? */
 	if (received < budget) {
 		napi_complete(napi);
-		if (unlikely(!virtqueue_enable_cb(vi->rvq)) &&
+		if (unlikely(!virtqueue_enable_cb(rq->vq)) &&
 		    napi_schedule_prep(napi)) {
-			virtqueue_disable_cb(vi->rvq);
+			virtqueue_disable_cb(rq->vq);
 			__napi_schedule(napi);
 			goto again;
 		}
@@ -557,13 +619,14 @@ again:
 	return received;
 }
 
-static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
+static unsigned int free_old_xmit_skbs(struct virtnet_info *vi,
+				       struct virtqueue *vq)
 {
 	struct sk_buff *skb;
 	unsigned int len, tot_sgs = 0;
 	struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
 
-	while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) {
+	while ((skb = virtqueue_get_buf(vq, &len)) != NULL) {
 		pr_debug("Sent skb %p\n", skb);
 
 		u64_stats_update_begin(&stats->tx_syncp);
@@ -577,7 +640,8 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
 	return tot_sgs;
 }
 
-static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
+static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb,
+		    struct virtqueue *vq, struct scatterlist *sg)
 {
 	struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
 	const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
@@ -615,44 +679,47 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
 
 	/* Encode metadata header at front. */
 	if (vi->mergeable_rx_bufs)
-		sg_set_buf(vi->tx_sg, &hdr->mhdr, sizeof hdr->mhdr);
+		sg_set_buf(sg, &hdr->mhdr, sizeof hdr->mhdr);
 	else
-		sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr);
+		sg_set_buf(sg, &hdr->hdr, sizeof hdr->hdr);
 
-	hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
-	return virtqueue_add_buf(vi->svq, vi->tx_sg, hdr->num_sg,
+	hdr->num_sg = skb_to_sgvec(skb, sg + 1, 0, skb->len) + 1;
+	return virtqueue_add_buf(vq, sg, hdr->num_sg,
 				 0, skb, GFP_ATOMIC);
 }
 
 static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
+	int qnum = skb_get_queue_mapping(skb);
+	struct virtqueue *vq = vi->sq[qnum].vq;
 	int capacity;
 
 	/* Free up any pending old buffers before queueing new ones. */
-	free_old_xmit_skbs(vi);
+	free_old_xmit_skbs(vi, vq);
 
 	/* Try to transmit */
-	capacity = xmit_skb(vi, skb);
+	capacity = xmit_skb(vi, skb, vq, vi->sq[qnum].sg);
 
 	/* This can happen with OOM and indirect buffers. */
 	if (unlikely(capacity < 0)) {
 		if (likely(capacity == -ENOMEM)) {
 			if (net_ratelimit())
 				dev_warn(&dev->dev,
-					 "TX queue failure: out of memory\n");
+					"TXQ (%d) failure: out of memory\n",
+					qnum);
 		} else {
 			dev->stats.tx_fifo_errors++;
 			if (net_ratelimit())
 				dev_warn(&dev->dev,
-					 "Unexpected TX queue failure: %d\n",
-					 capacity);
+					"Unexpected TXQ (%d) failure: %d\n",
+					qnum, capacity);
 		}
 		dev->stats.tx_dropped++;
 		kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
-	virtqueue_kick(vi->svq);
+	virtqueue_kick(vq);
 
 	/* Don't wait up for transmitted skbs to be freed. */
 	skb_orphan(skb);
@@ -661,13 +728,13 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Apparently nice girls don't return TX_BUSY; stop the queue
 	 * before it gets out of hand.  Naturally, this wastes entries. */
 	if (capacity < 2+MAX_SKB_FRAGS) {
-		netif_stop_queue(dev);
-		if (unlikely(!virtqueue_enable_cb_delayed(vi->svq))) {
+		netif_stop_subqueue(dev, qnum);
+		if (unlikely(!virtqueue_enable_cb_delayed(vq))) {
 			/* More just got used, free them then recheck. */
-			capacity += free_old_xmit_skbs(vi);
+			capacity += free_old_xmit_skbs(vi, vq);
 			if (capacity >= 2+MAX_SKB_FRAGS) {
-				netif_start_queue(dev);
-				virtqueue_disable_cb(vi->svq);
+				netif_start_subqueue(dev, qnum);
+				virtqueue_disable_cb(vq);
 			}
 		}
 	}
@@ -700,7 +767,8 @@ static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev,
 	unsigned int start;
 
 	for_each_possible_cpu(cpu) {
-		struct virtnet_stats *stats = per_cpu_ptr(vi->stats, cpu);
+		struct virtnet_stats __percpu *stats
+			= per_cpu_ptr(vi->stats, cpu);
 		u64 tpackets, tbytes, rpackets, rbytes;
 
 		do {
@@ -734,23 +802,13 @@ static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev,
 static void virtnet_netpoll(struct net_device *dev)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
+	int i;
 
-	napi_schedule(&vi->napi);
+	for (i = 0; i < vi->num_queue_pairs; i++)
+		napi_schedule(&vi->rq[i].napi);
 }
 #endif
 
-static int virtnet_open(struct net_device *dev)
-{
-	struct virtnet_info *vi = netdev_priv(dev);
-
-	/* Make sure we have some buffers: if oom use wq. */
-	if (!try_fill_recv(vi, GFP_KERNEL))
-		schedule_delayed_work(&vi->refill, 0);
-
-	virtnet_napi_enable(vi);
-	return 0;
-}
-
 /*
  * Send command via the control virtqueue and check status.  Commands
  * supported by the hypervisor, as indicated by feature bits, should
@@ -806,13 +864,63 @@ static void virtnet_ack_link_announce(struct virtnet_info *vi)
 	rtnl_unlock();
 }
 
+static int virtnet_set_queues(struct virtnet_info *vi)
+{
+	struct scatterlist sg;
+	struct virtio_net_ctrl_steering s;
+	struct net_device *dev = vi->dev;
+
+	if (vi->num_queue_pairs == 1) {
+		s.current_steering_rule = VIRTIO_NET_CTRL_STEERING_SINGLE;
+		s.current_steering_param = 1;
+	} else {
+		s.current_steering_rule =
+			VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX;
+		s.current_steering_param = vi->num_queue_pairs;
+	}
+	sg_init_one(&sg, &s, sizeof(s));
+
+	if (!vi->has_cvq)
+		return -EINVAL;
+
+	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_STEERING,
+				  VIRTIO_NET_CTRL_STEERING_SET, &sg, 1, 0)){
+		dev_warn(&dev->dev, "Fail to set the number of queue pairs to"
+			 " %d\n", vi->num_queue_pairs);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int virtnet_open(struct net_device *dev)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
+	int i;
+
+	for (i = 0; i < vi->total_queue_pairs; i++) {
+		/* Make sure we have some buffers: if oom use wq. */
+		if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+			schedule_delayed_work(&vi->rq[i].refill, 0);
+		virtnet_napi_enable(&vi->rq[i]);
+	}
+
+	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_MULTIQUEUE))
+		virtnet_set_queues(vi);
+
+	return 0;
+}
+
 static int virtnet_close(struct net_device *dev)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
+	int i;
 
 	/* Make sure refill_work doesn't re-enable napi! */
-	cancel_delayed_work_sync(&vi->refill);
-	napi_disable(&vi->napi);
+	for (i = 0; i < vi->total_queue_pairs; i++) {
+		cancel_delayed_work_sync(&vi->rq[i].refill);
+		napi_disable(&vi->rq[i].napi);
+	}
 
 	return 0;
 }
@@ -924,11 +1032,10 @@ static void virtnet_get_ringparam(struct net_device *dev,
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 
-	ring->rx_max_pending = virtqueue_get_vring_size(vi->rvq);
-	ring->tx_max_pending = virtqueue_get_vring_size(vi->svq);
+	ring->rx_max_pending = virtqueue_get_vring_size(vi->rq[0].vq);
+	ring->tx_max_pending = virtqueue_get_vring_size(vi->sq[0].vq);
 	ring->rx_pending = ring->rx_max_pending;
 	ring->tx_pending = ring->tx_max_pending;
-
 }
 
 
@@ -944,12 +1051,6 @@ static void virtnet_get_drvinfo(struct net_device *dev,
 
 }
 
-static const struct ethtool_ops virtnet_ethtool_ops = {
-	.get_drvinfo = virtnet_get_drvinfo,
-	.get_link = ethtool_op_get_link,
-	.get_ringparam = virtnet_get_ringparam,
-};
-
 #define MIN_MTU 68
 #define MAX_MTU 65535
 
@@ -961,6 +1062,22 @@ static int virtnet_change_mtu(struct net_device *dev, int new_mtu)
 	return 0;
 }
 
+/* To avoid contending a lock hold by a vcpu who would exit to host, select the
+ * txq based on the processor id.
+ */
+static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+	int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) :
+		  smp_processor_id();
+	int limit = dev->real_num_tx_queues - 1;
+
+	while (unlikely(txq >= limit))
+		txq -= limit;
+
+	/* queue 0 is reserved for single queue mode */
+	return txq + 1;
+}
+
 static const struct net_device_ops virtnet_netdev = {
 	.ndo_open            = virtnet_open,
 	.ndo_stop   	     = virtnet_close,
@@ -972,6 +1089,7 @@ static const struct net_device_ops virtnet_netdev = {
 	.ndo_get_stats64     = virtnet_stats,
 	.ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
+	.ndo_select_queue     = virtnet_select_queue,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = virtnet_netpoll,
 #endif
@@ -1007,10 +1125,10 @@ static void virtnet_config_changed_work(struct work_struct *work)
 
 	if (vi->status & VIRTIO_NET_S_LINK_UP) {
 		netif_carrier_on(vi->dev);
-		netif_wake_queue(vi->dev);
+		netif_tx_wake_all_queues(vi->dev);
 	} else {
 		netif_carrier_off(vi->dev);
-		netif_stop_queue(vi->dev);
+		netif_tx_stop_all_queues(vi->dev);
 	}
 done:
 	mutex_unlock(&vi->config_lock);
@@ -1023,41 +1141,216 @@ static void virtnet_config_changed(struct virtio_device *vdev)
 	schedule_work(&vi->config_work);
 }
 
-static int init_vqs(struct virtnet_info *vi)
+static void free_receive_bufs(struct virtnet_info *vi)
 {
-	struct virtqueue *vqs[3];
-	vq_callback_t *callbacks[] = { skb_recv_done, skb_xmit_done, NULL};
-	const char *names[] = { "input", "output", "control" };
-	int nvqs, err;
+	int i;
 
-	/* We expect two virtqueues, receive then send,
-	 * and optionally control. */
-	nvqs = virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2;
+	for (i = 0; i < vi->total_queue_pairs; i++) {
+		while (vi->rq[i].pages)
+			__free_pages(get_a_page(&vi->rq[i], GFP_KERNEL), 0);
+	}
+}
 
-	err = vi->vdev->config->find_vqs(vi->vdev, nvqs, vqs, callbacks, names);
-	if (err)
-		return err;
+/* Free memory allocated for send and receive queues */
+static void virtnet_free_queues(struct virtnet_info *vi)
+{
+	kfree(vi->rq);
+	vi->rq = NULL;
+	kfree(vi->sq);
+	vi->sq = NULL;
+}
+
+static void free_unused_bufs(struct virtnet_info *vi)
+{
+	void *buf;
+	int i;
+
+	for (i = 0; i < vi->total_queue_pairs; i++) {
+		struct virtqueue *vq = vi->sq[i].vq;
+
+		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL)
+			dev_kfree_skb(buf);
+	}
+
+	for (i = 0; i < vi->total_queue_pairs; i++) {
+		struct virtqueue *vq = vi->rq[i].vq;
+
+		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
+			if (vi->mergeable_rx_bufs || vi->big_packets)
+				give_pages(&vi->rq[i], buf);
+			else
+				dev_kfree_skb(buf);
+			--vi->rq[i].num;
+		}
+		BUG_ON(vi->rq[i].num != 0);
+	}
+}
+
+static void virtnet_set_affinity(struct virtnet_info *vi, bool set)
+{
+	int i;
+
+	for (i = 1; i < vi->total_queue_pairs; i++) {
+		int cpu = set ? i - 1 : -1;
+		virtqueue_set_affinity(vi->rq[i].vq, cpu);
+		virtqueue_set_affinity(vi->sq[i].vq, cpu);
+	}
+}
+
+static void virtnet_del_vqs(struct virtnet_info *vi)
+{
+	struct virtio_device *vdev = vi->vdev;
+
+	virtnet_set_affinity(vi, false);
+
+	vdev->config->del_vqs(vdev);
+
+	virtnet_free_queues(vi);
+}
+
+static int virtnet_find_vqs(struct virtnet_info *vi)
+{
+	vq_callback_t **callbacks;
+	struct virtqueue **vqs;
+	int ret = -ENOMEM;
+	int i, total_vqs;
+	char **names;
 
-	vi->rvq = vqs[0];
-	vi->svq = vqs[1];
+	/*
+	 * We expect 1 RX virtqueue followed by 1 TX virtqueue, followd by
+	 * possible control virtqueue, followed by 1 reserved vq, followed
+	 * by RX/TX queue pairs used in multiqueue mode.
+	 */
+	if (vi->total_queue_pairs == 1)
+		total_vqs = 2 + virtio_has_feature(vi->vdev,
+						   VIRTIO_NET_F_CTRL_VQ);
+	else
+		total_vqs = 2 * vi->total_queue_pairs + 2;
+
+	/* Allocate space for find_vqs parameters */
+	vqs = kzalloc(total_vqs * sizeof(*vqs), GFP_KERNEL);
+	callbacks = kzalloc(total_vqs * sizeof(*callbacks), GFP_KERNEL);
+	if (!vqs || !callbacks)
+		goto err_mem;
+	names = kzalloc(total_vqs * sizeof(*names), GFP_KERNEL);
+	if (!names)
+		goto err_mem;
+
+	/* Parameters for control virtqueue, if any */
+	if (vi->has_cvq) {
+		callbacks[2] = NULL;
+		names[2] = kasprintf(GFP_KERNEL, "control");
+	}
 
-	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
+	/* Allocate/initialize parameters for send/receive virtqueues */
+	for (i = 0; i < vi->total_queue_pairs; i++) {
+		callbacks[rxq2vq(i)] = skb_recv_done;
+		callbacks[txq2vq(i)] = skb_xmit_done;
+		names[rxq2vq(i)] = kasprintf(GFP_KERNEL, "input.%d", i);
+		names[txq2vq(i)] = kasprintf(GFP_KERNEL, "output.%d", i);
+	}
+
+	ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks,
+					 (const char **)names);
+	if (ret)
+		goto err_names;
+
+	if (vi->has_cvq)
 		vi->cvq = vqs[2];
 
-		if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
-			vi->dev->features |= NETIF_F_HW_VLAN_FILTER;
+	for (i = 0; i < vi->total_queue_pairs; i++) {
+		vi->rq[i].vq = vqs[rxq2vq(i)];
+		vi->sq[i].vq = vqs[txq2vq(i)];
 	}
+
+	kfree(callbacks);
+	kfree(vqs);
+
 	return 0;
+
+err_names:
+	for (i = 0; i < total_vqs * 2; i ++)
+		kfree(names[i]);
+	kfree(names);
+
+err_mem:
+	kfree(callbacks);
+	kfree(vqs);
+
+	return ret;
+}
+
+static int virtnet_alloc_queues(struct virtnet_info *vi)
+{
+	int i;
+
+	vi->sq = kzalloc(sizeof(vi->sq[0]) * vi->total_queue_pairs, GFP_KERNEL);
+	vi->rq = kzalloc(sizeof(vi->rq[0]) * vi->total_queue_pairs, GFP_KERNEL);
+	if (!vi->rq || !vi->sq)
+		goto err;
+
+	/* setup initial receive and send queue parameters */
+	for (i = 0; i < vi->total_queue_pairs; i++) {
+		vi->rq[i].vi = vi;
+		vi->rq[i].pages = NULL;
+		INIT_DELAYED_WORK(&vi->rq[i].refill, refill_work);
+		netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll,
+			       napi_weight);
+
+		sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg));
+		sg_init_table(vi->sq[i].sg, ARRAY_SIZE(vi->sq[i].sg));
+	}
+
+
+	return 0;
+
+err:
+	virtnet_free_queues(vi);
+	return -ENOMEM;
+}
+
+static int virtnet_setup_vqs(struct virtnet_info *vi)
+{
+	int ret;
+
+	/* Allocate send & receive queues */
+	ret = virtnet_alloc_queues(vi);
+	if (ret)
+		goto err;
+
+	ret = virtnet_find_vqs(vi);
+	if (ret)
+		goto err_free;
+
+	virtnet_set_affinity(vi, true);
+	return 0;
+
+err_free:
+	virtnet_free_queues(vi);
+err:
+	return ret;
 }
 
 static int virtnet_probe(struct virtio_device *vdev)
 {
-	int err;
+	int i, err;
 	struct net_device *dev;
 	struct virtnet_info *vi;
+	u16 num_queue_pairs;
+
+	/* Find if host supports multiqueue virtio_net device */
+	err = virtio_config_val(vdev, VIRTIO_NET_F_MULTIQUEUE,
+				offsetof(struct virtio_net_config,
+				max_virtqueue_pairs), &num_queue_pairs);
+
+	/* We need at least 2 queue's */
+	if (err)
+		num_queue_pairs = 1;
+	if (num_queue_pairs > 1)
+		num_queue_pairs ++;
 
 	/* Allocate ourselves a network device with room for our info */
-	dev = alloc_etherdev(sizeof(struct virtnet_info));
+	dev = alloc_etherdev_mq(sizeof(struct virtnet_info), num_queue_pairs);
 	if (!dev)
 		return -ENOMEM;
 
@@ -1103,22 +1396,17 @@ static int virtnet_probe(struct virtio_device *vdev)
 
 	/* Set up our device-specific information */
 	vi = netdev_priv(dev);
-	netif_napi_add(dev, &vi->napi, virtnet_poll, napi_weight);
 	vi->dev = dev;
 	vi->vdev = vdev;
 	vdev->priv = vi;
-	vi->pages = NULL;
 	vi->stats = alloc_percpu(struct virtnet_stats);
 	err = -ENOMEM;
 	if (vi->stats == NULL)
-		goto free;
+		goto free_netdev;
 
-	INIT_DELAYED_WORK(&vi->refill, refill_work);
 	mutex_init(&vi->config_lock);
 	vi->config_enable = true;
 	INIT_WORK(&vi->config_work, virtnet_config_changed_work);
-	sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
-	sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
 
 	/* If we can receive ANY GSO packets, we must allocate large ones. */
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
@@ -1129,10 +1417,25 @@ static int virtnet_probe(struct virtio_device *vdev)
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
 		vi->mergeable_rx_bufs = true;
 
-	err = init_vqs(vi);
+	if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ))
+		vi->has_cvq = true;
+
+	/* Use single tx/rx queue pair as default */
+	vi->num_queue_pairs = 1;
+	vi->total_queue_pairs = num_queue_pairs;
+
+	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
+	err = virtnet_setup_vqs(vi);
 	if (err)
 		goto free_stats;
 
+	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) &&
+	    virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
+		dev->features |= NETIF_F_HW_VLAN_FILTER;
+
+	netif_set_real_num_tx_queues(dev, 1);
+	netif_set_real_num_rx_queues(dev, 1);
+
 	err = register_netdev(dev);
 	if (err) {
 		pr_debug("virtio_net: registering device failed\n");
@@ -1140,12 +1443,15 @@ static int virtnet_probe(struct virtio_device *vdev)
 	}
 
 	/* Last of all, set up some receive buffers. */
-	try_fill_recv(vi, GFP_KERNEL);
-
-	/* If we didn't even get one input buffer, we're useless. */
-	if (vi->num == 0) {
-		err = -ENOMEM;
-		goto unregister;
+	for (i = 0; i < vi->total_queue_pairs; i++) {
+		try_fill_recv(&vi->rq[i], GFP_KERNEL);
+
+		/* If we didn't even get one input buffer, we're useless. */
+		if (vi->rq[i].num == 0) {
+			free_unused_bufs(vi);
+			err = -ENOMEM;
+			goto free_recv_bufs;
+		}
 	}
 
 	/* Assume link up if device can't report link status,
@@ -1158,42 +1464,28 @@ static int virtnet_probe(struct virtio_device *vdev)
 		netif_carrier_on(dev);
 	}
 
-	pr_debug("virtnet: registered device %s\n", dev->name);
+	pr_debug("virtnet: registered device %s with %d RX and TX vq's\n",
+		 dev->name, num_queue_pairs);
+
 	return 0;
 
-unregister:
+free_recv_bufs:
+	free_receive_bufs(vi);
 	unregister_netdev(dev);
+
 free_vqs:
-	vdev->config->del_vqs(vdev);
+	for (i = 0; i <num_queue_pairs; i++)
+		cancel_delayed_work_sync(&vi->rq[i].refill);
+	virtnet_del_vqs(vi);
+
 free_stats:
 	free_percpu(vi->stats);
-free:
+
+free_netdev:
 	free_netdev(dev);
 	return err;
 }
 
-static void free_unused_bufs(struct virtnet_info *vi)
-{
-	void *buf;
-	while (1) {
-		buf = virtqueue_detach_unused_buf(vi->svq);
-		if (!buf)
-			break;
-		dev_kfree_skb(buf);
-	}
-	while (1) {
-		buf = virtqueue_detach_unused_buf(vi->rvq);
-		if (!buf)
-			break;
-		if (vi->mergeable_rx_bufs || vi->big_packets)
-			give_pages(vi, buf);
-		else
-			dev_kfree_skb(buf);
-		--vi->num;
-	}
-	BUG_ON(vi->num != 0);
-}
-
 static void remove_vq_common(struct virtnet_info *vi)
 {
 	vi->vdev->config->reset(vi->vdev);
@@ -1201,10 +1493,9 @@ static void remove_vq_common(struct virtnet_info *vi)
 	/* Free unused buffers in both send and recv, if any. */
 	free_unused_bufs(vi);
 
-	vi->vdev->config->del_vqs(vi->vdev);
+	free_receive_bufs(vi);
 
-	while (vi->pages)
-		__free_pages(get_a_page(vi, GFP_KERNEL), 0);
+	virtnet_del_vqs(vi);
 }
 
 static void __devexit virtnet_remove(struct virtio_device *vdev)
@@ -1226,10 +1517,9 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
 	free_netdev(vi->dev);
 }
 
-#ifdef CONFIG_PM
-static int virtnet_freeze(struct virtio_device *vdev)
+static void virtnet_stop(struct virtnet_info *vi)
 {
-	struct virtnet_info *vi = vdev->priv;
+	int i;
 
 	/* Prevent config work handler from accessing the device */
 	mutex_lock(&vi->config_lock);
@@ -1237,34 +1527,32 @@ static int virtnet_freeze(struct virtio_device *vdev)
 	mutex_unlock(&vi->config_lock);
 
 	netif_device_detach(vi->dev);
-	cancel_delayed_work_sync(&vi->refill);
+	for (i = 0; i < vi->total_queue_pairs; i++)
+		cancel_delayed_work_sync(&vi->rq[i].refill);
 
 	if (netif_running(vi->dev))
-		napi_disable(&vi->napi);
-
-	remove_vq_common(vi);
+		for (i = 0; i < vi->total_queue_pairs; i++)
+			napi_disable(&vi->rq[i].napi);
 
-	flush_work(&vi->config_work);
-
-	return 0;
 }
 
-static int virtnet_restore(struct virtio_device *vdev)
+static int virtnet_start(struct virtnet_info *vi)
 {
-	struct virtnet_info *vi = vdev->priv;
-	int err;
+	int err, i;
 
-	err = init_vqs(vi);
+	err = virtnet_setup_vqs(vi);
 	if (err)
 		return err;
 
 	if (netif_running(vi->dev))
-		virtnet_napi_enable(vi);
+		for (i = 0; i < vi->total_queue_pairs; i++)
+			virtnet_napi_enable(&vi->rq[i]);
 
 	netif_device_attach(vi->dev);
 
-	if (!try_fill_recv(vi, GFP_KERNEL))
-		schedule_delayed_work(&vi->refill, 0);
+	for (i = 0; i < vi->total_queue_pairs; i++)
+		if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+			schedule_delayed_work(&vi->rq[i].refill, 0);
 
 	mutex_lock(&vi->config_lock);
 	vi->config_enable = true;
@@ -1272,6 +1560,29 @@ static int virtnet_restore(struct virtio_device *vdev)
 
 	return 0;
 }
+
+#ifdef CONFIG_PM
+static int virtnet_freeze(struct virtio_device *vdev)
+{
+	struct virtnet_info *vi = vdev->priv;
+
+	virtnet_stop(vi);
+
+	remove_vq_common(vi);
+
+	flush_work(&vi->config_work);
+
+	return 0;
+}
+
+static int virtnet_restore(struct virtio_device *vdev)
+{
+	struct virtnet_info *vi = vdev->priv;
+
+	virtnet_start(vi);
+
+	return 0;
+}
 #endif
 
 static struct virtio_device_id id_table[] = {
@@ -1287,7 +1598,7 @@ static unsigned int features[] = {
 	VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
 	VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
 	VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
-	VIRTIO_NET_F_GUEST_ANNOUNCE,
+	VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MULTIQUEUE,
 };
 
 static struct virtio_driver virtio_net_driver = {
@@ -1305,6 +1616,12 @@ static struct virtio_driver virtio_net_driver = {
 #endif
 };
 
+static const struct ethtool_ops virtnet_ethtool_ops = {
+	.get_drvinfo = virtnet_get_drvinfo,
+	.get_link = ethtool_op_get_link,
+	.get_ringparam = virtnet_get_ringparam,
+};
+
 static int __init init(void)
 {
 	return register_virtio_driver(&virtio_net_driver);
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index 1bc7e30..a43caeb 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -61,6 +61,8 @@ struct virtio_net_config {
 	__u8 mac[6];
 	/* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
 	__u16 status;
+	/* Total number of RX/TX queues */
+	__u16 max_virtqueue_pairs;
 } __attribute__((packed));
 
 /* This is the first element of the scatter-gather list.  If you don't
@@ -167,4 +169,20 @@ struct virtio_net_ctrl_mac {
 #define VIRTIO_NET_CTRL_ANNOUNCE       3
  #define VIRTIO_NET_CTRL_ANNOUNCE_ACK         0
 
+/*
+ * Control multiqueue
+ *
+ */
+#define VIRTIO_NET_CTRL_STEERING       4
+ #define VIRTIO_NET_CTRL_STEERING_SET         0
+
+#define VIRTIO_NET_CTRL_STEERING_SINGLE 0
+#define VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX 1
+
+struct virtio_net_ctrl_steering {
+	u8 current_steering_rule;
+	u8 reserved;
+	u16 current_steering_param;
+};
+
 #endif /* _LINUX_VIRTIO_NET_H */
-- 
1.7.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