DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 09/31] net/i40e/base: add bus number info
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

Currently i40e_bus_info has PCI device and function info only. However
in log messages slot number (i.e hw->bus.device) is being printed
as bus number. Another field should be added to provide bus number
info and preserve existing information.

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
---
 drivers/net/i40e/base/i40e_type.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/i40e/base/i40e_type.h b/drivers/net/i40e/base/i40e_type.h
index 5a59ce2..530ee5e 100644
--- a/drivers/net/i40e/base/i40e_type.h
+++ b/drivers/net/i40e/base/i40e_type.h
@@ -561,6 +561,7 @@ struct i40e_bus_info {
 	u16 func;
 	u16 device;
 	u16 lan_id;
+	u16 bus_id;
 };
 
 /* Flow control (FC) parameters */
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 08/31] net/i40e/base: add clause22 and clause45 implementation
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

Some external PHYs require Clause22 and Clause45 method for
accessing registers. Mostly used for X722 support.

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
---
 drivers/net/i40e/base/i40e_common.c    | 245 +++++++++++++++++++++++++++------
 drivers/net/i40e/base/i40e_prototype.h |  16 ++-
 drivers/net/i40e/base/i40e_type.h      |  17 ++-
 3 files changed, 226 insertions(+), 52 deletions(-)

diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index 7eea189..85c1c11 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -6022,7 +6022,92 @@ enum i40e_status_code i40e_aq_configure_partition_bw(struct i40e_hw *hw,
 }
 
 /**
- * i40e_read_phy_register
+ * i40e_read_phy_register_clause22
+ * @hw: pointer to the HW structure
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Reads specified PHY register value
+ **/
+enum i40e_status_code i40e_read_phy_register_clause22(struct i40e_hw *hw,
+					u16 reg, u8 phy_addr, u16 *value)
+{
+	enum i40e_status_code status = I40E_ERR_TIMEOUT;
+	u8 port_num = (u8)hw->func_caps.mdio_port_num;
+	u32 command = 0;
+	u16 retry = 1000;
+
+	command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
+		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
+		  (I40E_MDIO_CLAUSE22_OPCODE_READ_MASK) |
+		  (I40E_MDIO_CLAUSE22_STCODE_MASK) |
+		  (I40E_GLGEN_MSCA_MDICMD_MASK);
+	wr32(hw, I40E_GLGEN_MSCA(port_num), command);
+	do {
+		command = rd32(hw, I40E_GLGEN_MSCA(port_num));
+		if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
+			status = I40E_SUCCESS;
+			break;
+		}
+		i40e_usec_delay(10);
+		retry--;
+	} while (retry);
+
+	if (status) {
+		i40e_debug(hw, I40E_DEBUG_PHY,
+			   "PHY: Can't write command to external PHY.\n");
+	} else {
+		command = rd32(hw, I40E_GLGEN_MSRWD(port_num));
+		*value = (command & I40E_GLGEN_MSRWD_MDIRDDATA_MASK) >>
+			 I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT;
+	}
+
+	return status;
+}
+
+/**
+ * i40e_write_phy_register_clause22
+ * @hw: pointer to the HW structure
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Writes specified PHY register value
+ **/
+enum i40e_status_code i40e_write_phy_register_clause22(struct i40e_hw *hw,
+					u16 reg, u8 phy_addr, u16 value)
+{
+	enum i40e_status_code status = I40E_ERR_TIMEOUT;
+	u8 port_num = (u8)hw->func_caps.mdio_port_num;
+	u32 command  = 0;
+	u16 retry = 1000;
+
+	command = value << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT;
+	wr32(hw, I40E_GLGEN_MSRWD(port_num), command);
+
+	command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
+		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
+		  (I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK) |
+		  (I40E_MDIO_CLAUSE22_STCODE_MASK) |
+		  (I40E_GLGEN_MSCA_MDICMD_MASK);
+
+	wr32(hw, I40E_GLGEN_MSCA(port_num), command);
+	do {
+		command = rd32(hw, I40E_GLGEN_MSCA(port_num));
+		if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
+			status = I40E_SUCCESS;
+			break;
+		}
+		i40e_usec_delay(10);
+		retry--;
+	} while (retry);
+
+	return status;
+}
+
+/**
+ * i40e_read_phy_register_clause45
  * @hw: pointer to the HW structure
  * @page: registers page number
  * @reg: register address in the page
@@ -6031,9 +6116,8 @@ enum i40e_status_code i40e_aq_configure_partition_bw(struct i40e_hw *hw,
  *
  * Reads specified PHY register value
  **/
-enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
-					     u8 page, u16 reg, u8 phy_addr,
-					     u16 *value)
+enum i40e_status_code i40e_read_phy_register_clause45(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 *value)
 {
 	enum i40e_status_code status = I40E_ERR_TIMEOUT;
 	u32 command  = 0;
@@ -6043,8 +6127,8 @@ enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
 	command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
 		  (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
 		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-		  (I40E_MDIO_OPCODE_ADDRESS) |
-		  (I40E_MDIO_STCODE) |
+		  (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
+		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |
 		  (I40E_GLGEN_MSCA_MDICMD_MASK) |
 		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
 	wr32(hw, I40E_GLGEN_MSCA(port_num), command);
@@ -6066,8 +6150,8 @@ enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
 
 	command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
 		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-		  (I40E_MDIO_OPCODE_READ) |
-		  (I40E_MDIO_STCODE) |
+		  (I40E_MDIO_CLAUSE45_OPCODE_READ_MASK) |
+		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |
 		  (I40E_GLGEN_MSCA_MDICMD_MASK) |
 		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
 	status = I40E_ERR_TIMEOUT;
@@ -6097,7 +6181,7 @@ enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
 }
 
 /**
- * i40e_write_phy_register
+ * i40e_write_phy_register_clause45
  * @hw: pointer to the HW structure
  * @page: registers page number
  * @reg: register address in the page
@@ -6106,9 +6190,8 @@ enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
  *
  * Writes value to specified PHY register
  **/
-enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
-					      u8 page, u16 reg, u8 phy_addr,
-					      u16 value)
+enum i40e_status_code i40e_write_phy_register_clause45(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 value)
 {
 	enum i40e_status_code status = I40E_ERR_TIMEOUT;
 	u32 command  = 0;
@@ -6118,8 +6201,8 @@ enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
 	command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
 		  (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
 		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-		  (I40E_MDIO_OPCODE_ADDRESS) |
-		  (I40E_MDIO_STCODE) |
+		  (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
+		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |
 		  (I40E_GLGEN_MSCA_MDICMD_MASK) |
 		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
 	wr32(hw, I40E_GLGEN_MSCA(port_num), command);
@@ -6143,8 +6226,8 @@ enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
 
 	command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
 		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-		  (I40E_MDIO_OPCODE_WRITE) |
-		  (I40E_MDIO_STCODE) |
+		  (I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK) |
+		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |
 		  (I40E_GLGEN_MSCA_MDICMD_MASK) |
 		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
 	status = I40E_ERR_TIMEOUT;
@@ -6165,6 +6248,78 @@ enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
 }
 
 /**
+ * i40e_write_phy_register
+ * @hw: pointer to the HW structure
+ * @page: registers page number
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Writes value to specified PHY register
+ **/
+enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 value)
+{
+	enum i40e_status_code status;
+
+	switch (hw->device_id) {
+	case I40E_DEV_ID_1G_BASE_T_X722:
+		status = i40e_write_phy_register_clause22(hw,
+			reg, phy_addr, value);
+		break;
+	case I40E_DEV_ID_10G_BASE_T:
+	case I40E_DEV_ID_10G_BASE_T4:
+	case I40E_DEV_ID_10G_BASE_T_X722:
+	case I40E_DEV_ID_25G_B:
+	case I40E_DEV_ID_25G_SFP28:
+		status = i40e_write_phy_register_clause45(hw,
+			page, reg, phy_addr, value);
+		break;
+	default:
+		status = I40E_ERR_UNKNOWN_PHY;
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * i40e_read_phy_register
+ * @hw: pointer to the HW structure
+ * @page: registers page number
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Reads specified PHY register value
+ **/
+enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 *value)
+{
+	enum i40e_status_code status;
+
+	switch (hw->device_id) {
+	case I40E_DEV_ID_1G_BASE_T_X722:
+		status = i40e_read_phy_register_clause22(hw, reg, phy_addr,
+							 value);
+		break;
+	case I40E_DEV_ID_10G_BASE_T:
+	case I40E_DEV_ID_10G_BASE_T4:
+	case I40E_DEV_ID_10G_BASE_T_X722:
+	case I40E_DEV_ID_25G_B:
+	case I40E_DEV_ID_25G_SFP28:
+		status = i40e_read_phy_register_clause45(hw, page, reg,
+							 phy_addr, value);
+		break;
+	default:
+		status = I40E_ERR_UNKNOWN_PHY;
+		break;
+	}
+
+	return status;
+}
+
+/**
  * i40e_get_phy_address
  * @hw: pointer to the HW structure
  * @dev_num: PHY port num that address we want
@@ -6206,14 +6361,16 @@ enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
 
 	for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
 	     led_addr++) {
-		status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-						led_addr, phy_addr, &led_reg);
+		status = i40e_read_phy_register_clause45(hw,
+							 I40E_PHY_COM_REG_PAGE,
+							 led_addr, phy_addr,
+							 &led_reg);
 		if (status)
 			goto phy_blinking_end;
 		led_ctl = led_reg;
 		if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
 			led_reg = 0;
-			status = i40e_write_phy_register(hw,
+			status = i40e_write_phy_register_clause45(hw,
 							 I40E_PHY_COM_REG_PAGE,
 							 led_addr, phy_addr,
 							 led_reg);
@@ -6225,20 +6382,18 @@ enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
 
 	if (time > 0 && interval > 0) {
 		for (i = 0; i < time * 1000; i += interval) {
-			status = i40e_read_phy_register(hw,
-							I40E_PHY_COM_REG_PAGE,
-							led_addr, phy_addr,
-							&led_reg);
+			status = i40e_read_phy_register_clause45(hw,
+						I40E_PHY_COM_REG_PAGE,
+						led_addr, phy_addr, &led_reg);
 			if (status)
 				goto restore_config;
 			if (led_reg & I40E_PHY_LED_MANUAL_ON)
 				led_reg = 0;
 			else
 				led_reg = I40E_PHY_LED_MANUAL_ON;
-			status = i40e_write_phy_register(hw,
-							 I40E_PHY_COM_REG_PAGE,
-							 led_addr, phy_addr,
-							 led_reg);
+			status = i40e_write_phy_register_clause45(hw,
+						I40E_PHY_COM_REG_PAGE,
+						led_addr, phy_addr, led_reg);
 			if (status)
 				goto restore_config;
 			i40e_msec_delay(interval);
@@ -6246,8 +6401,9 @@ enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
 	}
 
 restore_config:
-	status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
-					 phy_addr, led_ctl);
+	status = i40e_write_phy_register_clause45(hw,
+						  I40E_PHY_COM_REG_PAGE,
+						  led_addr, phy_addr, led_ctl);
 
 phy_blinking_end:
 	return status;
@@ -6278,8 +6434,10 @@ enum i40e_status_code i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
 
 	for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
 	     temp_addr++) {
-		status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-						temp_addr, phy_addr, &reg_val);
+		status = i40e_read_phy_register_clause45(hw,
+							 I40E_PHY_COM_REG_PAGE,
+							 temp_addr, phy_addr,
+							 &reg_val);
 		if (status)
 			return status;
 		*val = reg_val;
@@ -6312,41 +6470,42 @@ enum i40e_status_code i40e_led_set_phy(struct i40e_hw *hw, bool on,
 	i = rd32(hw, I40E_PFGEN_PORTNUM);
 	port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
 	phy_addr = i40e_get_phy_address(hw, port_num);
-
-	status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
-					phy_addr, &led_reg);
+	status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+						 led_addr, phy_addr, &led_reg);
 	if (status)
 		return status;
 	led_ctl = led_reg;
 	if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
 		led_reg = 0;
-		status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-						 led_addr, phy_addr, led_reg);
+		status = i40e_write_phy_register_clause45(hw,
+							  I40E_PHY_COM_REG_PAGE,
+							  led_addr, phy_addr,
+							  led_reg);
 		if (status)
 			return status;
 	}
-	status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-					led_addr, phy_addr, &led_reg);
+	status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+						 led_addr, phy_addr, &led_reg);
 	if (status)
 		goto restore_config;
 	if (on)
 		led_reg = I40E_PHY_LED_MANUAL_ON;
 	else
 		led_reg = 0;
-	status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-					 led_addr, phy_addr, led_reg);
+	status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+						  led_addr, phy_addr, led_reg);
 	if (status)
 		goto restore_config;
 	if (mode & I40E_PHY_LED_MODE_ORIG) {
 		led_ctl = (mode & I40E_PHY_LED_MODE_MASK);
-		status = i40e_write_phy_register(hw,
+		status = i40e_write_phy_register_clause45(hw,
 						 I40E_PHY_COM_REG_PAGE,
 						 led_addr, phy_addr, led_ctl);
 	}
 	return status;
 restore_config:
-	status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
-					 phy_addr, led_ctl);
+	status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+						  led_addr, phy_addr, led_ctl);
 	return status;
 }
 #endif /* PF_DRIVER */
diff --git a/drivers/net/i40e/base/i40e_prototype.h b/drivers/net/i40e/base/i40e_prototype.h
index 3aab5ca..9109cfc 100644
--- a/drivers/net/i40e/base/i40e_prototype.h
+++ b/drivers/net/i40e/base/i40e_prototype.h
@@ -538,10 +538,18 @@ enum i40e_status_code i40e_aq_get_wake_event_reason(struct i40e_hw *hw,
 			u16 *wake_reason,
 			struct i40e_asq_cmd_details *cmd_details);
 #endif
-enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw, u8 page,
-					     u16 reg, u8 phy_addr, u16 *value);
-enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw, u8 page,
-					      u16 reg, u8 phy_addr, u16 value);
+enum i40e_status_code i40e_read_phy_register_clause22(struct i40e_hw *hw,
+					u16 reg, u8 phy_addr, u16 *value);
+enum i40e_status_code i40e_write_phy_register_clause22(struct i40e_hw *hw,
+					u16 reg, u8 phy_addr, u16 value);
+enum i40e_status_code i40e_read_phy_register_clause45(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 *value);
+enum i40e_status_code i40e_write_phy_register_clause45(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 value);
+enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 *value);
+enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 value);
 u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
 enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
 					      u32 time, u32 interval);
diff --git a/drivers/net/i40e/base/i40e_type.h b/drivers/net/i40e/base/i40e_type.h
index b5f72c3..5a59ce2 100644
--- a/drivers/net/i40e/base/i40e_type.h
+++ b/drivers/net/i40e/base/i40e_type.h
@@ -157,15 +157,22 @@ enum i40e_debug_mask {
 #define I40E_PCI_LINK_SPEED_5000	0x2
 #define I40E_PCI_LINK_SPEED_8000	0x3
 
-#define I40E_MDIO_STCODE		I40E_MASK(0, \
+#define I40E_MDIO_CLAUSE22_STCODE_MASK	I40E_MASK(1, \
 						  I40E_GLGEN_MSCA_STCODE_SHIFT)
-#define I40E_MDIO_OPCODE_ADDRESS	I40E_MASK(0, \
+#define I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK	I40E_MASK(1, \
 						  I40E_GLGEN_MSCA_OPCODE_SHIFT)
-#define I40E_MDIO_OPCODE_WRITE		I40E_MASK(1, \
+#define I40E_MDIO_CLAUSE22_OPCODE_READ_MASK	I40E_MASK(2, \
 						  I40E_GLGEN_MSCA_OPCODE_SHIFT)
-#define I40E_MDIO_OPCODE_READ_INC_ADDR	I40E_MASK(2, \
+
+#define I40E_MDIO_CLAUSE45_STCODE_MASK	I40E_MASK(0, \
+						  I40E_GLGEN_MSCA_STCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK	I40E_MASK(0, \
+						  I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK	I40E_MASK(1, \
+						  I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_READ_INC_ADDR_MASK	I40E_MASK(2, \
 						  I40E_GLGEN_MSCA_OPCODE_SHIFT)
-#define I40E_MDIO_OPCODE_READ		I40E_MASK(3, \
+#define I40E_MDIO_CLAUSE45_OPCODE_READ_MASK	I40E_MASK(3, \
 						  I40E_GLGEN_MSCA_OPCODE_SHIFT)
 
 #define I40E_PHY_COM_REG_PAGE			0x1E
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 07/31] net/i40e/base: add media type detection for 25G link
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
---
 drivers/net/i40e/base/i40e_common.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index 2ad9448..7eea189 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -1288,6 +1288,8 @@ STATIC enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
 	case I40E_PHY_TYPE_1000BASE_LX:
 	case I40E_PHY_TYPE_40GBASE_SR4:
 	case I40E_PHY_TYPE_40GBASE_LR4:
+	case I40E_PHY_TYPE_25GBASE_LR:
+	case I40E_PHY_TYPE_25GBASE_SR:
 		media = I40E_MEDIA_TYPE_FIBER;
 		break;
 	case I40E_PHY_TYPE_100BASE_TX:
@@ -1302,6 +1304,7 @@ STATIC enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
 	case I40E_PHY_TYPE_10GBASE_SFPP_CU:
 	case I40E_PHY_TYPE_40GBASE_AOC:
 	case I40E_PHY_TYPE_10GBASE_AOC:
+	case I40E_PHY_TYPE_25GBASE_CR:
 		media = I40E_MEDIA_TYPE_DA;
 		break;
 	case I40E_PHY_TYPE_1000BASE_KX:
@@ -1309,6 +1312,7 @@ STATIC enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
 	case I40E_PHY_TYPE_10GBASE_KR:
 	case I40E_PHY_TYPE_40GBASE_KR4:
 	case I40E_PHY_TYPE_20GBASE_KR2:
+	case I40E_PHY_TYPE_25GBASE_KR:
 		media = I40E_MEDIA_TYPE_BACKPLANE;
 		break;
 	case I40E_PHY_TYPE_SGMII:
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 05/31] net/i40e/base: group base mode VF offload flags
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

Group together the minimum set of offload capabilities that are always
supported by VF in base mode. This define would be used by PF to make
sure VF in base mode gets minimum of base capabilities.

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
---
 drivers/net/i40e/base/i40e_virtchnl.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/i40e/base/i40e_virtchnl.h b/drivers/net/i40e/base/i40e_virtchnl.h
index 07e7472..8fba608 100644
--- a/drivers/net/i40e/base/i40e_virtchnl.h
+++ b/drivers/net/i40e/base/i40e_virtchnl.h
@@ -172,6 +172,10 @@ struct i40e_virtchnl_vsi_resource {
 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF		0X00080000
 #define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM	0X00100000
 
+#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \
+				    I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \
+				    I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)
+
 struct i40e_virtchnl_vf_resource {
 	u16 num_vsis;
 	u16 num_queue_pairs;
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 03/31] net/i40e/base: remove unnecessary code
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

This patch changes some assignments and removing the unnecessary
code to avoid error reported by static analysis tools.

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
---
 drivers/net/i40e/base/i40e_common.c  | 4 ----
 drivers/net/i40e/base/i40e_lan_hmc.c | 5 -----
 2 files changed, 9 deletions(-)

diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index d67ad90..aa346d1 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -3833,7 +3833,6 @@ STATIC void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
 			else
 				p->acpi_prog_method = I40E_ACPI_PROGRAMMING_METHOD_HW_FVL;
 			p->proxy_support = (phys_id & I40E_PROXY_SUPPORT_MASK) ? 1 : 0;
-			p->proxy_support = p->proxy_support;
 			i40e_debug(hw, I40E_DEBUG_INIT,
 				   "HW Capability: WOL proxy filters = %d\n",
 				   hw->num_wol_proxy_filters);
@@ -6008,9 +6007,6 @@ enum i40e_status_code i40e_aq_configure_partition_bw(struct i40e_hw *hw,
 	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
 	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
 
-	if (bwd_size > I40E_AQ_LARGE_BUF)
-		desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB);
-
 	desc.datalen = CPU_TO_LE16(bwd_size);
 
 	status = i40e_asq_send_command(hw, &desc, bw_data, bwd_size, cmd_details);
diff --git a/drivers/net/i40e/base/i40e_lan_hmc.c b/drivers/net/i40e/base/i40e_lan_hmc.c
index 2260648..f03f381 100644
--- a/drivers/net/i40e/base/i40e_lan_hmc.c
+++ b/drivers/net/i40e/base/i40e_lan_hmc.c
@@ -1239,11 +1239,6 @@ enum i40e_status_code i40e_hmc_get_object_va(struct i40e_hw *hw,
 	u64 obj_offset_in_fpm;
 	u32 sd_idx, sd_lmt;
 
-	if (NULL == hmc_info) {
-		ret_code = I40E_ERR_BAD_PTR;
-		DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info ptr\n");
-		goto exit;
-	}
 	if (NULL == hmc_info->hmc_obj) {
 		ret_code = I40E_ERR_BAD_PTR;
 		DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->hmc_obj ptr\n");
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 01/31] net/i40e/base: add encap csum VF offload flag
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

Add ENCAP_CSUM offload negotiation flag. Currently VF assumes checksum
offload for encapsulated packets is supported by default. Going forward,
this feature needs to be negotiated with PF before advertising to the
stack. Hence, we need a flag to control it.

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
---
 drivers/net/i40e/base/i40e_virtchnl.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/i40e/base/i40e_virtchnl.h b/drivers/net/i40e/base/i40e_virtchnl.h
index fd51ec3..07e7472 100644
--- a/drivers/net/i40e/base/i40e_virtchnl.h
+++ b/drivers/net/i40e/base/i40e_virtchnl.h
@@ -170,6 +170,7 @@ struct i40e_virtchnl_vsi_resource {
 #define I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING	0x00020000
 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2	0x00040000
 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF		0X00080000
+#define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM	0X00100000
 
 struct i40e_virtchnl_vf_resource {
 	u16 num_vsis;
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 00/31] net/i40e: base code update
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang
In-Reply-To: <1481294364-83505-1-git-send-email-jingjing.wu@intel.com>

i40e base code upate. The main changes are:
 - add clause22 and clause45 implementation for PHY registers accessing
 - replace existing legacy memcpy() calls with i40e_memcpy() calls.
 - use BIT() macro instead of bit fields
 - add clear all WoL filters implementation
 - add ERROR state for NVM update state machine
 - add broadcast promiscuous control per VLAN
 - remove unused X722_SUPPORT and I40E_NDIS_SUPPORT MARCOs

v3:
 * update commit log of few patches as issue fix

v2:
 * comments rework
 * complie issue fix
 * rebase to dpdk-next-net

Jingjing Wu (31):
  net/i40e/base: add encap csum VF offload flag
  net/i40e/base: fix flow control set for 25G
  net/i40e/base: remove unnecessary code
  net/i40e/base: fix bit test mask
  net/i40e/base: group base mode VF offload flags
  net/i40e/base: fix long link down notification time
  net/i40e/base: add media type detection for 25G link
  net/i40e/base: add clause22 and clause45 implementation
  net/i40e/base: add bus number info
  net/i40e/base: add protocols when discover capabilities
  net/i40e/base: fix unknown PHYs incorrect identification
  net/i40e/base: replace memcpy
  net/i40e/base: deprecating unused macro
  net/i40e/base: remove FPK HyperV VF device ID
  net/i40e/base: add FEC bits to PHY capabilities
  net/i40e/base: use BIT() macro instead of bit fields
  net/i40e/base: adjust 25G PHY type values
  net/i40e/base: implement clear all WoL filters
  net/i40e/base: implement set VSI full promisc mode
  net/i40e/base: fix wol failure on PF reset
  net/i40e/base: save link FEC info from link up event
  net/i40e/base: fix NVM access intefering
  net/i40e/base: change shift values to hex
  net/i40e/base: comment that udp port must be in Host order
  net/i40e/base: remove duplicate definitions
  net/i40e/base: add ERROR state for NVM update state machine
  net/i40e/base: add broadcast promiscuous control per VLAN
  net/i40e/base: fix division by zero
  net/i40e/base: fix byte order
  net/i40e/base: remove unused macro
  net/i40e: remove unused macro from PMD

 drivers/net/i40e/Makefile               |   2 +-
 drivers/net/i40e/base/i40e_adminq.c     |   4 +-
 drivers/net/i40e/base/i40e_adminq_cmd.h |  51 ++--
 drivers/net/i40e/base/i40e_common.c     | 425 ++++++++++++++++++++++++++------
 drivers/net/i40e/base/i40e_devids.h     |   3 -
 drivers/net/i40e/base/i40e_lan_hmc.c    |   5 -
 drivers/net/i40e/base/i40e_nvm.c        |  52 ++--
 drivers/net/i40e/base/i40e_prototype.h  |  30 ++-
 drivers/net/i40e/base/i40e_register.h   |   2 -
 drivers/net/i40e/base/i40e_type.h       |  94 +++----
 drivers/net/i40e/base/i40e_virtchnl.h   |   5 +
 drivers/net/i40e/i40e_ethdev.c          |  42 +---
 drivers/net/i40e/i40e_ethdev_vf.c       |   1 -
 13 files changed, 468 insertions(+), 248 deletions(-)

-- 
2.4.11

^ permalink raw reply

* [PATCH v3 29/31] net/i40e/base: fix byte order
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang, stable
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

Big Endian platform will accidentally send the wrong
data to the firmware command. This patch fixes the issue.

Fixes: 788fc17b2dec ("i40e/base: support proxy config for X722")
Fixes: 3c89193a36fd ("i40e/base: support WOL config for X722")

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
CC: stable@dpdk.org
---
 drivers/net/i40e/base/i40e_common.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index fdf9d9b..6a0362d 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -6852,7 +6852,7 @@ enum i40e_status_code i40e_aq_set_arp_proxy_config(struct i40e_hw *hw,
 				  CPU_TO_LE32(I40E_HI_DWORD((u64)proxy_config));
 	desc.params.external.addr_low =
 				  CPU_TO_LE32(I40E_LO_DWORD((u64)proxy_config));
-	desc.datalen = sizeof(struct i40e_aqc_arp_proxy_data);
+	desc.datalen = CPU_TO_LE16(sizeof(struct i40e_aqc_arp_proxy_data));
 
 	status = i40e_asq_send_command(hw, &desc, proxy_config,
 				       sizeof(struct i40e_aqc_arp_proxy_data),
@@ -6889,7 +6889,7 @@ enum i40e_status_code i40e_aq_set_ns_proxy_table_entry(struct i40e_hw *hw,
 		CPU_TO_LE32(I40E_HI_DWORD((u64)ns_proxy_table_entry));
 	desc.params.external.addr_low =
 		CPU_TO_LE32(I40E_LO_DWORD((u64)ns_proxy_table_entry));
-	desc.datalen = sizeof(struct i40e_aqc_ns_proxy_data);
+	desc.datalen = CPU_TO_LE16(sizeof(struct i40e_aqc_ns_proxy_data));
 
 	status = i40e_asq_send_command(hw, &desc, ns_proxy_table_entry,
 				       sizeof(struct i40e_aqc_ns_proxy_data),
@@ -6952,7 +6952,7 @@ enum i40e_status_code i40e_aq_set_clear_wol_filter(struct i40e_hw *hw,
 	cmd->valid_flags = CPU_TO_LE16(valid_flags);
 
 	buff_len = sizeof(*filter);
-	desc.datalen = buff_len;
+	desc.datalen = CPU_TO_LE16(buff_len);
 
 	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
 	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 28/31] net/i40e/base: fix division by zero
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang, stable
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

For some cases when reading from device are incorrect or image is
incorrect, this part of code causes crash due to division by zero.

Fixes: 8db9e2a1b232 ("i40e: base driver")

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
CC: stable@dpdk.org
---
 drivers/net/i40e/base/i40e_common.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index 14aaac6..fdf9d9b 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -3967,8 +3967,10 @@ STATIC void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
 	/* partition id is 1-based, and functions are evenly spread
 	 * across the ports as partitions
 	 */
-	hw->partition_id = (hw->pf_id / hw->num_ports) + 1;
-	hw->num_partitions = num_functions / hw->num_ports;
+	if (hw->num_ports != 0) {
+		hw->partition_id = (hw->pf_id / hw->num_ports) + 1;
+		hw->num_partitions = num_functions / hw->num_ports;
+	}
 
 	/* additional HW specific goodies that might
 	 * someday be HW version specific
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 22/31] net/i40e/base: fix NVM access intefering
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang, stable
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

Acquire NVM lock before reads on all devices.  Previously, locks were
only used for X722 and later.  Fixes an issue where simultaneous X710
NVM accesses were interfering with each other.

Fixes: 8db9e2a1b232 ("i40e: base driver")

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
CC: stable@dpdk.org
---
 drivers/net/i40e/base/i40e_nvm.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/i40e/base/i40e_nvm.c b/drivers/net/i40e/base/i40e_nvm.c
index eb69e49..1f345a5 100644
--- a/drivers/net/i40e/base/i40e_nvm.c
+++ b/drivers/net/i40e/base/i40e_nvm.c
@@ -219,19 +219,19 @@ enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
 {
 	enum i40e_status_code ret_code = I40E_SUCCESS;
 
+	ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+	if (!ret_code) {
 #ifdef X722_SUPPORT
-	if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
-		ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
-		if (!ret_code) {
+		if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
 			ret_code = i40e_read_nvm_word_aq(hw, offset, data);
-			i40e_release_nvm(hw);
+		} else {
+			ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
 		}
-	} else {
-		ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
-	}
 #else
-	ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
+		ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
 #endif
+		i40e_release_nvm(hw);
+	}
 	return ret_code;
 }
 
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 20/31] net/i40e/base: fix wol failure on PF reset
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang, stable
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

By default the device clears all MAC filter information on PF Reset.
However, this will cause Wake-On-LAN to fail because the wake filters
are deleted on transition to D3 power state. To get around this,
firmware is adding functionality to preserve certain MAC filters during
PFR. These bits allow the driver tell the FW which filters to preserve.

Set the datalen field and add I40E_AQ_FLAG_BUF/I40E_AQ_FLAG_RD flags in the
desc struct for the WoL/Proxy AQ descriptors. The WoL/Proxy AQ commands
were failing because these were missing.

Fixes: 3c89193a36fd ("i40e/base: support WOL config for X722")

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
CC: stable@dpdk.org
---
 drivers/net/i40e/base/i40e_adminq_cmd.h |  5 ++++-
 drivers/net/i40e/base/i40e_common.c     | 16 +++++++++++++++-
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/base/i40e_adminq_cmd.h b/drivers/net/i40e/base/i40e_adminq_cmd.h
index 19af8b5..d4d2a7a 100644
--- a/drivers/net/i40e/base/i40e_adminq_cmd.h
+++ b/drivers/net/i40e/base/i40e_adminq_cmd.h
@@ -541,7 +541,8 @@ struct i40e_aqc_mac_address_read {
 #define I40E_AQC_PORT_ADDR_VALID	0x40
 #define I40E_AQC_WOL_ADDR_VALID		0x80
 #define I40E_AQC_MC_MAG_EN_VALID	0x100
-#define I40E_AQC_ADDR_VALID_MASK	0x1F0
+#define I40E_AQC_WOL_PRESERVE_STATUS	0x200
+#define I40E_AQC_ADDR_VALID_MASK	0x3F0
 	u8	reserved[6];
 	__le32	addr_high;
 	__le32	addr_low;
@@ -562,6 +563,7 @@ I40E_CHECK_STRUCT_LEN(24, i40e_aqc_mac_address_read_data);
 struct i40e_aqc_mac_address_write {
 	__le16	command_flags;
 #define I40E_AQC_MC_MAG_EN		0x0100
+#define I40E_AQC_WOL_PRESERVE_ON_PFR	0x0200
 #define I40E_AQC_WRITE_TYPE_LAA_ONLY	0x0000
 #define I40E_AQC_WRITE_TYPE_LAA_WOL	0x4000
 #define I40E_AQC_WRITE_TYPE_PORT	0x8000
@@ -601,6 +603,7 @@ struct i40e_aqc_set_wol_filter {
 	__le16 cmd_flags;
 #define I40E_AQC_SET_WOL_FILTER				0x8000
 #define I40E_AQC_SET_WOL_FILTER_NO_TCO_WOL		0x4000
+#define I40E_AQC_SET_WOL_FILTER_WOL_PRESERVE_ON_PFR	0x2000
 #define I40E_AQC_SET_WOL_FILTER_ACTION_CLEAR		0
 #define I40E_AQC_SET_WOL_FILTER_ACTION_SET		1
 	__le16 valid_flags;
diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index 1095e68..e9376dd 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -6804,10 +6804,13 @@ enum i40e_status_code i40e_aq_set_arp_proxy_config(struct i40e_hw *hw,
 
 	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_proxy_config);
 
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
 	desc.params.external.addr_high =
 				  CPU_TO_LE32(I40E_HI_DWORD((u64)proxy_config));
 	desc.params.external.addr_low =
 				  CPU_TO_LE32(I40E_LO_DWORD((u64)proxy_config));
+	desc.datalen = sizeof(struct i40e_aqc_arp_proxy_data);
 
 	status = i40e_asq_send_command(hw, &desc, proxy_config,
 				       sizeof(struct i40e_aqc_arp_proxy_data),
@@ -6838,10 +6841,13 @@ enum i40e_status_code i40e_aq_set_ns_proxy_table_entry(struct i40e_hw *hw,
 	i40e_fill_default_direct_cmd_desc(&desc,
 				i40e_aqc_opc_set_ns_proxy_table_entry);
 
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
 	desc.params.external.addr_high =
 		CPU_TO_LE32(I40E_HI_DWORD((u64)ns_proxy_table_entry));
 	desc.params.external.addr_low =
 		CPU_TO_LE32(I40E_LO_DWORD((u64)ns_proxy_table_entry));
+	desc.datalen = sizeof(struct i40e_aqc_ns_proxy_data);
 
 	status = i40e_asq_send_command(hw, &desc, ns_proxy_table_entry,
 				       sizeof(struct i40e_aqc_ns_proxy_data),
@@ -6888,9 +6894,11 @@ enum i40e_status_code i40e_aq_set_clear_wol_filter(struct i40e_hw *hw,
 	if (set_filter) {
 		if (!filter)
 			return  I40E_ERR_PARAM;
+
 		cmd_flags |= I40E_AQC_SET_WOL_FILTER;
-		buff_len = sizeof(*filter);
+		cmd_flags |= I40E_AQC_SET_WOL_FILTER_WOL_PRESERVE_ON_PFR;
 	}
+
 	if (no_wol_tco)
 		cmd_flags |= I40E_AQC_SET_WOL_FILTER_NO_TCO_WOL;
 	cmd->cmd_flags = CPU_TO_LE16(cmd_flags);
@@ -6901,6 +6909,12 @@ enum i40e_status_code i40e_aq_set_clear_wol_filter(struct i40e_hw *hw,
 		valid_flags |= I40E_AQC_SET_WOL_FILTER_NO_TCO_ACTION_VALID;
 	cmd->valid_flags = CPU_TO_LE16(valid_flags);
 
+	buff_len = sizeof(*filter);
+	desc.datalen = buff_len;
+
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
+	desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
+
 	cmd->address_high = CPU_TO_LE32(I40E_HI_DWORD((u64)filter));
 	cmd->address_low = CPU_TO_LE32(I40E_LO_DWORD((u64)filter));
 
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 11/31] net/i40e/base: fix unknown PHYs incorrect identification
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang, stable
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

The PHY type value for unrecognized PHYs and cables was changed
based on firmware version number. Newer hardware use lower firmware
version numbers and this was causing some PHYs to be identified
as type 0x16 instead of 0xe (unknown).

Without this patch, newer card will incorrectly identify unknown
PHYs and cables.

This change adds hardware type to the check for firmware version
so the PHY type is reported correctly.

Fixes: 8db9e2a1b232 ("i40e: base driver")

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
CC: stable@dpdk.org
---
 drivers/net/i40e/base/i40e_common.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index 9591428..fbaa0be 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -1984,7 +1984,8 @@ enum i40e_status_code i40e_aq_get_link_info(struct i40e_hw *hw,
 	else
 		hw_link_info->lse_enable = false;
 
-	if ((hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 &&
+	if ((hw->mac.type == I40E_MAC_XL710) &&
+	    (hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 &&
 	     hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
 		hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU;
 
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 06/31] net/i40e/base: fix long link down notification time
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang, stable
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

This patch fixes a problem where it could take a very
long time (>100 msec) to print the link down notification.
This problem is fixed by changing how often we update link
info from fw, when link is down. Without this patch, it can
take over 100msec to notify user link is down.

Fixes: e6691b428eb1 ("i40e/base: fix PHY NVM interaction")

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
CC: stable@dpdk.org
---
 drivers/net/i40e/base/i40e_common.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index a2661cf..2ad9448 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -2746,7 +2746,10 @@ enum i40e_status_code i40e_update_link_info(struct i40e_hw *hw)
 	if (status)
 		return status;
 
-	if (hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) {
+	/* extra checking needed to ensure link info to user is timely */
+	if ((hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) &&
+	    ((hw->phy.link_info.link_info & I40E_AQ_LINK_UP) ||
+	     !(hw->phy.link_info_old.link_info & I40E_AQ_LINK_UP))) {
 		status = i40e_aq_get_phy_capabilities(hw, false, false,
 						      &abilities, NULL);
 		if (status)
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 04/31] net/i40e/base: fix bit test mask
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang, stable
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

Incorrect bit mask was used for testing "get link status" response.
Instead of I40E_AQ_LSE_ENABLE (which is actually 0x03) it should
be I40E_AQ_LSE_IS_ENABLED (which is defined as 0x01).

Fixes: 8db9e2a1b232 ("i40e: base driver")

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
CC: stable@dpdk.org
---
 drivers/net/i40e/base/i40e_common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index aa346d1..a2661cf 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -1975,7 +1975,7 @@ enum i40e_status_code i40e_aq_get_link_info(struct i40e_hw *hw,
 	else
 		hw_link_info->crc_enable = false;
 
-	if (resp->command_flags & CPU_TO_LE16(I40E_AQ_LSE_ENABLE))
+	if (resp->command_flags & CPU_TO_LE16(I40E_AQ_LSE_IS_ENABLED))
 		hw_link_info->lse_enable = true;
 	else
 		hw_link_info->lse_enable = false;
-- 
2.4.11

^ permalink raw reply related

* [PATCH v3 02/31] net/i40e/base: fix flow control set for 25G
From: Jingjing Wu @ 2016-12-10 11:24 UTC (permalink / raw)
  To: dev; +Cc: jingjing.wu, helin.zhang, stable
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

Add phy_type_ext copied from old setting to rpevents 25G PHY
types from being disabled when setting the flow control modes.

Fixes: 51131ae119 ("net/i40e/base: get PHY abilities for 25G")

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
CC: stable@dpdk.org
---
 drivers/net/i40e/base/i40e_common.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index 9a6b3ed..d67ad90 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c
@@ -1789,6 +1789,7 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
 			config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
 		/* Copy over all the old settings */
 		config.phy_type = abilities.phy_type;
+		config.phy_type_ext = abilities.phy_type_ext;
 		config.link_speed = abilities.link_speed;
 		config.eee_capability = abilities.eee_capability;
 		config.eeer = abilities.eeer_val;
-- 
2.4.11

^ permalink raw reply related

* dpdk16.07 and virtio "Cannot mmap IO port resource"
From: Gopakumar Choorakkot Edakkunni @ 2016-12-10  4:30 UTC (permalink / raw)
  To: dev

I tried to load up dpdk (bound to uio_pci_generic, tried igb_uio also!) on
a virtio interface. Dpdk exits with the "Cannot mmap IO port resource"
complaint - the call chain is
legacy_virtio_resource_init()-->pci_uio_ioport_map().

If anyone can give any clues/pointers as to what might be wrong, that can
greatly help in getting me on the right track fast !

---
EAL:   probe driver: 1af4:1000 rte_virtio_pmd
EAL: PCI device 0000:00:05.0 on NUMA socket 0
EAL:   probe driver: 1af4:1000 r[  330.753458] ------------[ cut here
]------------
rte_virtio_pmd
[  330.754430] WARNING: CPU: 0 PID: 8063 at drivers/pci/pci-sysfs.c:984
pci_mmap_resource.isra.14+0x113/0x1b0()
[  330.756083] process "dpdk_master" tried to map 0x0000d000 bytes at page
0x00000000 on 0000:00:05.0 BAR 0 (start 0x            c080, size
0x              20)
[  330.758272] Modules linked in: rte_kni igb_uio pppoe ppp_async
iptable_nat cdc_mbim sierra_net rndis_host qmi_wwan qcserial pppox
ppp_generic option nf_nat_pptp nf_nat_ipv4 nf_nat_amanda nf_conntrack_pptp
nf_conntrack_ipv4 nf_conntrack_amanda ipt_MASQUERADE huawei_cdc_ncm
cdc_subset cdc_ncm cdc_ether cdc_eem ax88179_178a asix xt_u32 xt_time
xt_tcpmss xt_string xt_statistic xt_state xt_socket xt_recent xt_quota
xt_pkttype xt_physdev xt_owner xt_nat xt_multiport xt_mark xt_mac xt_limit
xt_length xt_iprange xt_id xt_hl xt_helper xt_hashlimit xt_esp xt_ecn
xt_dscp xt_conntrack xt_connmark xt_connlimit xt_connbytes xt_comment
xt_addrtype xt_TPROXY xt_TEE xt_TCPMSS xt_REDIRECT xt_NETMAP xt_LOG xt_LED
xt_HL xt_DSCP xt_CT xt_CLASSIFY usbnet usb_wwan ts_kmp ts_fsm ts_bm slhc
sierra pl2303 nfnetlink_queue nfnetlink_log nf_nat_tftp nf_nat_snmp_basic
nf_nat_sip nf_nat_proto_gre nf_nat_irc nf_nat_h323 nf_nat_ftp nf_nat
nf_defrag_ipv4 nf_conntrack_tftp nf_conntrack_snmp nf_conntrack_sip
nf_conntrack_proto_gre nf_conntrack_netlink nf_conntrack_irc
nf_conntrack_h323 nf_conntrack_ftp nf_conntrack_broadcast
lib80211_crypt_wep lib80211_crypt_tkip lib80211_crypt_ccmp lib80211
iptable_raw iptable_mangle iptable_filter ipt_ah ipt_ULOG ipt_REJECT
ipt_ECN hso ftdi_sio crc8 crc7 crc_itu_t crc_ccitt cp210x cordic
compat_xtables cdc_wdm cdc_acm arptable_filter arpt_mangle arp_tables
sch_teql sch_tbf sch_sfq sch_red sch_prio sch_netem sch_htb sch_gred
sch_dsmark sch_codel em_text em_nbyte em_meta em_cmp cls_basic act_police
act_ipt act_connmark act_skbedit act_mirred em_u32 cls_u32 cls_tcindex
cls_flow cls_route cls_fw sch_hfsc sch_ingress evdev xt_NFQUEUE xt_set
ip_set_list_set ip_set_hash_netport ip_set_hash_netiface ip_set_hash_net
ip_set_hash_ipportnet ip_set_hash_ipportip ip_set_hash_ipport
ip_set_hash_ip ip_set_bitmap_port ip_set_bitmap_ipmac ip_set_bitmap_ip
ip_set nfnetlink sr_mod cdrom ip6t_REJECT ip6table_raw ip6table_mangle
ip6table_filter ip6_tables nf_conntrack_ipv6 nf_conntrack nf_defrag_ipv6
ifb ipip ip6_tunnel tunnel6 tunnel4 ip_tunnel tun mdio loop vfat fat isofs
nls_utf8 nls_iso8859_15 nls_iso8859_1 nls_cp850 nls_cp437 rfkill virtio_rng
sha512_generic sha256_generic sha1_generic md5 arc4 ath10k_pci ath10k_core
ath9k ath9k_common ath9k_hw ath mac80211 cfg80211 compat pcnet32 e1000
virtio_net ohci_hcd ixgbevf ixgbe hwmon igbvf igb dsa_core mii [last
unloaded: igb_uio]
[  330.805110] CPU: 0 PID: 8063 Comm: dpdk_master Tainted: G        W
3.14.67 #1
[  330.806104] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
Bochs 01/01/2011
[  330.806104]  0000000000000286 0000000000000000 ffffffff814e167c
0000000000000006
[  330.806104]  ffff88008b573cd8 ffffffff81259d73 ffffffff81061b72
ffff88013b24fae0
[  330.806104]  ffff88013b24f800 0000000000000000 ffff88013a498000
ffff88013b24f8a8
[  330.806104] Call Trace:
[  330.806104]  [<ffffffff814e167c>] ? dump_stack+0x5e/0x7a
[  330.806104]  [<ffffffff81259d73>] ? pci_mmap_resource.isra.14+0x113/0x1b0
[  330.806104]  [<ffffffff81061b72>] ? warn_slowpath_common+0x82/0xb0
[  330.806104]  [<ffffffff81061c55>] ? warn_slowpath_fmt+0x45/0x50
[  330.806104]  [<ffffffff81120321>] ? do_last.isra.58+0xac1/0xc00
[  330.806104]  [<ffffffff81259d73>] ? pci_mmap_resource.isra.14+0x113/0x1b0
[  330.806104]  [<ffffffff8116da79>] ? kernfs_fop_mmap+0x69/0x100
[  330.806104]  [<ffffffff810f4018>] ? mmap_region+0x2e8/0x560
[  330.806104]  [<ffffffff810f45a8>] ? do_mmap_pgoff+0x318/0x3b0
[  330.806104]  [<ffffffff810e1724>] ? vm_mmap_pgoff+0x74/0xc0
[  330.806104]  [<ffffffff810f2d1a>] ? SyS_mmap_pgoff+0x18a/0x1e0
[  330.806104]  [<ffffffff814e7759>] ? system_call_fastpath+0x16/0x1b
[  330.823897] ---[ end trace c6106b67c768d501 ]---
EAL: Cannot mmap IO port resource: Invalid argument
EAL: Error - exiting with code: 1
  Cause: Requested device 0000:00:05.0 cannot be used

^ permalink raw reply

* Re: After a port is bound to dpdk, when 'ip addr' or 'ip link add ~vlan' command against non-dpdk port , Linux kernel hangs
From: Joo Kim @ 2016-12-10  4:27 UTC (permalink / raw)
  To: dev
In-Reply-To: <CAFj4wcKhyjE+uW95ELR-oXPB7gEo5TenN21mQFOUgXkyBCtqkg@mail.gmail.com>

This issue(https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1570195
)seems to be some similar  to what I am facing.
So, I tried its fix patches
(
https://github.com/openstack/fuel-plugin-ovs/blob/master/ovs_build/dpdk_2.2.0/debian/patches/ubuntu-backport-36-pci-identify-devices-not-managed-by-any-kernel-drive.patch
https://github.com/openstack/fuel-plugin-ovs/blob/master/ovs_build/dpdk_2.2.0/debian/patches/ubuntu-backport-37-pci-ignore-devices-already-managed-in-Linux-when-map.patch
)
But, it didnot help.

BTW,  what I meant by 'Linux kernel hangs' is soft lockup.
(I see following msg in dmesg
[252460.127003] BUG: soft lockup - CPU#1 stuck for 22s! [ifconfig:25322]
[252488.127003] BUG: soft lockup - CPU#1 stuck for 22s! [ifconfig:25322]
[252493.698003] INFO: rcu_sched self-detected stall on CPU { 1}  (t=60001
jiffies g=9321477 c=9321476 q=0)
[252493.699003] INFO: rcu_sched detected stalls on CPUs/tasks:
[252520.127002] BUG: soft lockup - CPU#1 stuck for 22s! [ifconfig:25322]
[252548.127003] BUG: soft lockup - CPU#1 stuck for 22s! [ifconfig:25322]

)

On Fri, Dec 9, 2016 at 3:27 PM, Joo Kim <itsolution@gmail.com> wrote:

> Hello,
> I am using dpdk 2.2.0 in this VM where several NIC ports are available.
>
> Also, uio, kni drivers are installed.
> [root@mylinux]# lsmod | grep uio
> igb_uio                13224  0
> uio                    19259  1 igb_uio
> [root@mylinux]# lsmod | grep kni
> rte_kni               294375  0
> i2c_core               40325  2 i2c_dev,rte_kni
> [root@mylinux]# uname -r
> 3.10.0-229.20.1.el7.x86_64
>
> Weirdly,  once I bind a network port to dpdk,   after that, when I run 'ip
> addr' or 'ip link add ~vlan' command against non-dpdk port ,  this VM's
> Linux kernel hangs.
>
> For example, when I run  'ip link add ~vlan' command, then  following
> dmesg is seen and Linux hangs.
>
> Any idea on root cause/how to fix?
>
> {noformat}
> [ 4884.158003]  virtio dm_mirror dm_region_hash dm_log dm_mod loop [last
> unloaded: openvswitch]
> [ 4884.158003] CPU: 3 PID: 15060 Comm: dpdk_nic_bind.p Tainted: GF
> O--------------   3.10.0-229.20.1.el7.x86_64 #1
> [ 4884.158003] Hardware name: Bochs ovs-cloudinit-vm, BIOS Bochs 01/01/2011
> [ 4884.158003] task: ffff88038d045b00 ti: ffff880390e34000 task.ti:
> ffff880390e34000
> [ 4884.158003] RIP: 0010:[<ffffffffa006f173>]  [<ffffffffa006f173>]
> virtnet_send_command.constprop.29+0x103/0x160 [virtio_net]
> [ 4884.158003] RSP: 0018:ffff880390e379f8  EFLAGS: 00000246
> [ 4884.158003] RAX: 0000000000000000 RBX: 00000000000163e0 RCX:
> ffff88038fbd3000
> [ 4884.158003] RDX: 000000000000c0f0 RSI: ffff880390e379fc RDI:
> ffff88038e140000
> [ 4884.158003] RBP: ffff880390e37a90 R08: 00000000000163e0 R09:
> ffffffffa005059c
> [ 4884.158003] R10: 0000000000000003 R11: 0000000000000000 R12:
> 0000000000000003
> [ 4884.158003] R13: 0000000000000000 R14: 0000000000000003 R15:
> ffff880390e379e8
> [ 4884.158003] FS:  00007fc39b216740(0000) GS:ffff8803a80c0000(0000) knl
> GS:0000000000000000
> [ 4884.158003] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
> [ 4884.158003] CR2: 00007fc39b221000 CR3: 000000038cb6f000 CR4:
> 00000000000007e0
> [ 4884.158003] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
> 0000000000000000
> [ 4884.158003] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7:
> 0000000000000400
> [ 4884.158003] Stack:
> [ 4884.158003]  000000000102ff46 ffff880390e37a20 ffff880390e37aa8
> ffff880390e37a40
> [ 4884.158003]  ffffffff815bb3ae ffffea000e438dc2 00000002000009fa
> 0000000000000000
> [ 4884.158003]  0000000000000000 ffffea000e438dc2 00000001000009f9
> 0000000000000000
> [ 4884.158003] Call Trace:
> [ 4884.158003]  [<ffffffff815bb3ae>] ? fib6_clean_all+0xae/0x100
> [ 4884.158003]  [<ffffffffa006f3f0>] virtnet_vlan_rx_kill_vid+0x50/0x90
> [virtio_net]
> [ 4884.158003]  [<ffffffff815e67e3>] vlan_vid_del+0x113/0x170
> [ 4884.158003]  [<ffffffffa02b681b>] vlan_device_event+0x65b/0x690 [8021q]
> [ 4884.158003]  [<ffffffff8160fdec>] notifier_call_chain+0x4c/0x70
> [ 4884.158003]  [<ffffffff8109d456>] raw_notifier_call_chain+0x16/0x20
> [ 4884.158003]  [<ffffffff814f78fd>] call_netdevice_notifiers+0x2d/0x60
> [ 4884.158003]  [<ffffffff814f7bac>] dev_close_many+0xcc/0x120
> [ 4884.158003]  [<ffffffff814f8ee8>] rollback_registered_many+0xa8/0x220
> [ 4884.158003]  [<ffffffff814f90a0>] rollback_registered+0x40/0x70
> [ 4884.158003]  [<ffffffff814fa388>] unregister_netdevice_queue+0x48/0x80
> [ 4884.158003]  [<ffffffff814fa3dc>] unregister_netdev+0x1c/0x30
> [ 4884.158003]  [<ffffffffa006e0e3>] virtnet_remove+0x43/0x80 [virtio_net]
> [ 4884.158003]  [<ffffffffa002f119>] virtio_dev_remove+0x49/0xd0 [virtio]
> [ 4884.158003]  [<ffffffff813d2cbf>] __device_release_driver+0x7f/0xf0
> [ 4884.158003]  [<ffffffff813d2d53>] device_release_driver+0x23/0x30
> [ 4884.158003]  [<ffffffff813d24c8>] bus_remove_device+0x108/0x180
> [ 4884.158003]  [<ffffffff813ce9e5>] device_del+0x135/0x1f0
> [ 4884.158003]  [<ffffffff813ceabe>] device_unregister+0x1e/0x60
> [ 4884.158003]  [<ffffffffa002f426>] unregister_virtio_device+0x16/0x30
> [virtio]
> [ 4884.158003]  [<ffffffffa01c852b>] virtio_pci_remove+0x2b/0x70
> [virtio_pci]
> [ 4884.158003]  [<ffffffff813097bb>] pci_device_remove+0x3b/0xb0
> [ 4884.158003]  [<ffffffff813d2cbf>] __device_release_driver+0x7f/0xf0
> [ 4884.158003]  [<ffffffff813d2d53>] device_release_driver+0x23/0x30
> [ 4884.158003]  [<ffffffff813d16bd>] driver_unbind+0xbd/0xe0
> [ 4884.158003]  [<ffffffff813d0bf4>] drv_attr_store+0x24/0x40
> [ 4884.158003]  [<ffffffff8123cfc6>] sysfs_write_file+0xc6/0x140
> [ 4884.158003]  [<ffffffff811c6a2d>] vfs_write+0xbd/0x1e0
> [ 4884.158003]  [<ffffffff8160fce3>] ? trace_do_page_fault+0x43/0x100
> [ 4884.158003]  [<ffffffff811c7478>] SyS_write+0x58/0xb0
> [ 4884.158003]  [<ffffffff81614409>] system_call_fastpath+0x16/0x1b
> [ 4884.158003] Code: c5 70 ff ff ff e8 2e 11 fe ff 48 8b 7b 08 e8 c5 02 fe
> ff eb 12 0f 1f 00 48 8b 7b 08 e8 77 ff fd ff 84 c0 75 17 f3 90 48 8b 7b 08
> <48> 8d b5 6c ff ff ff e8 01 01 fe ff 48 85 c0 74 dc 80 bd 69 ff
> {noformat}
>

^ permalink raw reply

* After a port is bound to dpdk, when 'ip addr' or 'ip link add ~vlan' command against non-dpdk port , Linux kernel hangs
From: Joo Kim @ 2016-12-09 23:27 UTC (permalink / raw)
  To: dev

Hello,
I am using dpdk 2.2.0 in this VM where several NIC ports are available.

Also, uio, kni drivers are installed.
[root@mylinux]# lsmod | grep uio
igb_uio                13224  0
uio                    19259  1 igb_uio
[root@mylinux]# lsmod | grep kni
rte_kni               294375  0
i2c_core               40325  2 i2c_dev,rte_kni
[root@mylinux]# uname -r
3.10.0-229.20.1.el7.x86_64

Weirdly,  once I bind a network port to dpdk,   after that, when I run 'ip
addr' or 'ip link add ~vlan' command against non-dpdk port ,  this VM's
Linux kernel hangs.

For example, when I run  'ip link add ~vlan' command, then  following dmesg
is seen and Linux hangs.

Any idea on root cause/how to fix?

{noformat}
[ 4884.158003]  virtio dm_mirror dm_region_hash dm_log dm_mod loop [last
unloaded: openvswitch]
[ 4884.158003] CPU: 3 PID: 15060 Comm: dpdk_nic_bind.p Tainted: GF
O--------------   3.10.0-229.20.1.el7.x86_64 #1
[ 4884.158003] Hardware name: Bochs ovs-cloudinit-vm, BIOS Bochs 01/01/2011
[ 4884.158003] task: ffff88038d045b00 ti: ffff880390e34000 task.ti:
ffff880390e34000
[ 4884.158003] RIP: 0010:[<ffffffffa006f173>]  [<ffffffffa006f173>]
virtnet_send_command.constprop.29+0x103/0x160 [virtio_net]
[ 4884.158003] RSP: 0018:ffff880390e379f8  EFLAGS: 00000246
[ 4884.158003] RAX: 0000000000000000 RBX: 00000000000163e0 RCX:
ffff88038fbd3000
[ 4884.158003] RDX: 000000000000c0f0 RSI: ffff880390e379fc RDI:
ffff88038e140000
[ 4884.158003] RBP: ffff880390e37a90 R08: 00000000000163e0 R09:
ffffffffa005059c
[ 4884.158003] R10: 0000000000000003 R11: 0000000000000000 R12:
0000000000000003
[ 4884.158003] R13: 0000000000000000 R14: 0000000000000003 R15:
ffff880390e379e8
[ 4884.158003] FS:  00007fc39b216740(0000) GS:ffff8803a80c0000(0000) knl
GS:0000000000000000
[ 4884.158003] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 4884.158003] CR2: 00007fc39b221000 CR3: 000000038cb6f000 CR4:
00000000000007e0
[ 4884.158003] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
0000000000000000
[ 4884.158003] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7:
0000000000000400
[ 4884.158003] Stack:
[ 4884.158003]  000000000102ff46 ffff880390e37a20 ffff880390e37aa8
ffff880390e37a40
[ 4884.158003]  ffffffff815bb3ae ffffea000e438dc2 00000002000009fa
0000000000000000
[ 4884.158003]  0000000000000000 ffffea000e438dc2 00000001000009f9
0000000000000000
[ 4884.158003] Call Trace:
[ 4884.158003]  [<ffffffff815bb3ae>] ? fib6_clean_all+0xae/0x100
[ 4884.158003]  [<ffffffffa006f3f0>] virtnet_vlan_rx_kill_vid+0x50/0x90
[virtio_net]
[ 4884.158003]  [<ffffffff815e67e3>] vlan_vid_del+0x113/0x170
[ 4884.158003]  [<ffffffffa02b681b>] vlan_device_event+0x65b/0x690 [8021q]
[ 4884.158003]  [<ffffffff8160fdec>] notifier_call_chain+0x4c/0x70
[ 4884.158003]  [<ffffffff8109d456>] raw_notifier_call_chain+0x16/0x20
[ 4884.158003]  [<ffffffff814f78fd>] call_netdevice_notifiers+0x2d/0x60
[ 4884.158003]  [<ffffffff814f7bac>] dev_close_many+0xcc/0x120
[ 4884.158003]  [<ffffffff814f8ee8>] rollback_registered_many+0xa8/0x220
[ 4884.158003]  [<ffffffff814f90a0>] rollback_registered+0x40/0x70
[ 4884.158003]  [<ffffffff814fa388>] unregister_netdevice_queue+0x48/0x80
[ 4884.158003]  [<ffffffff814fa3dc>] unregister_netdev+0x1c/0x30
[ 4884.158003]  [<ffffffffa006e0e3>] virtnet_remove+0x43/0x80 [virtio_net]
[ 4884.158003]  [<ffffffffa002f119>] virtio_dev_remove+0x49/0xd0 [virtio]
[ 4884.158003]  [<ffffffff813d2cbf>] __device_release_driver+0x7f/0xf0
[ 4884.158003]  [<ffffffff813d2d53>] device_release_driver+0x23/0x30
[ 4884.158003]  [<ffffffff813d24c8>] bus_remove_device+0x108/0x180
[ 4884.158003]  [<ffffffff813ce9e5>] device_del+0x135/0x1f0
[ 4884.158003]  [<ffffffff813ceabe>] device_unregister+0x1e/0x60
[ 4884.158003]  [<ffffffffa002f426>] unregister_virtio_device+0x16/0x30
[virtio]
[ 4884.158003]  [<ffffffffa01c852b>] virtio_pci_remove+0x2b/0x70
[virtio_pci]
[ 4884.158003]  [<ffffffff813097bb>] pci_device_remove+0x3b/0xb0
[ 4884.158003]  [<ffffffff813d2cbf>] __device_release_driver+0x7f/0xf0
[ 4884.158003]  [<ffffffff813d2d53>] device_release_driver+0x23/0x30
[ 4884.158003]  [<ffffffff813d16bd>] driver_unbind+0xbd/0xe0
[ 4884.158003]  [<ffffffff813d0bf4>] drv_attr_store+0x24/0x40
[ 4884.158003]  [<ffffffff8123cfc6>] sysfs_write_file+0xc6/0x140
[ 4884.158003]  [<ffffffff811c6a2d>] vfs_write+0xbd/0x1e0
[ 4884.158003]  [<ffffffff8160fce3>] ? trace_do_page_fault+0x43/0x100
[ 4884.158003]  [<ffffffff811c7478>] SyS_write+0x58/0xb0
[ 4884.158003]  [<ffffffff81614409>] system_call_fastpath+0x16/0x1b
[ 4884.158003] Code: c5 70 ff ff ff e8 2e 11 fe ff 48 8b 7b 08 e8 c5 02 fe
ff eb 12 0f 1f 00 48 8b 7b 08 e8 77 ff fd ff 84 c0 75 17 f3 90 48 8b 7b 08
<48> 8d b5 6c ff ff ff e8 01 01 fe ff 48 85 c0 74 dc 80 bd 69 ff
{noformat}

^ permalink raw reply

* Linux dcbnl like support for dpdk
From: Ram pratap Yadav @ 2016-12-09 22:49 UTC (permalink / raw)
  To: dev@dpdk.org

Hi DEV,
Are we planning to support Linux dcbnl like interface for dpdk to configure
NIC Dcb using ixgbe according to IEEE 802.1Qaz?

Thanks,
Ram

^ permalink raw reply

* [PATCH v11] drivers/net:new TUN/TAP device PMD
From: Keith Wiles @ 2016-12-09 19:05 UTC (permalink / raw)
  To: dev; +Cc: pmatilai, yuanhan.liu, ferruh.yigit, john.mcnamara
In-Reply-To: <1476396234-44694-1-git-send-email-keith.wiles@intel.com>

The PMD allows for DPDK and the host to communicate using a raw
device interface on the host and in the DPDK application. The device
created is a Tap device with a L2 packet header.

v11- Add the tap.rst to the nic/index.rst file
v10- Change the string name used to allow for multiple devices.
v9 - Fix up the docs to use correct syntax
v8 - Fix issue with tap_tx_queue_setup() not return zero on success.
v7 - Reword the comment in common_base and fix the data->name issue
v6 - fixed the checkpatch issues
v5 - merge in changes from list review see related emails
     fixed many minor edits
v4 - merge with latest driver changes
v3 - fix includes by removing ifdef for other type besides Linux
     Fix the copyright notice in the Makefile
v2 - merge all of the patches into one patch
     Fix a typo on naming the tap device
     Update the maintainers list

Signed-off-by: Keith Wiles <keith.wiles@intel.com>
---
 MAINTAINERS                             |   5 +
 config/common_base                      |   9 +
 config/common_linuxapp                  |   1 +
 doc/guides/nics/index.rst               |   1 +
 doc/guides/nics/tap.rst                 | 136 ++++++
 drivers/net/Makefile                    |   1 +
 drivers/net/tap/Makefile                |  57 +++
 drivers/net/tap/rte_eth_tap.c           | 765 ++++++++++++++++++++++++++++++++
 drivers/net/tap/rte_pmd_tap_version.map |   4 +
 mk/rte.app.mk                           |   1 +
 10 files changed, 980 insertions(+)
 create mode 100644 doc/guides/nics/tap.rst
 create mode 100644 drivers/net/tap/Makefile
 create mode 100644 drivers/net/tap/rte_eth_tap.c
 create mode 100644 drivers/net/tap/rte_pmd_tap_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 26d9590..842fb6d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -398,6 +398,11 @@ F: doc/guides/nics/pcap_ring.rst
 F: app/test/test_pmd_ring.c
 F: app/test/test_pmd_ring_perf.c
 
+Tap PMD
+M: Keith Wiles <keith.wiles@intel.com>
+F: drivers/net/tap
+F: doc/guides/nics/tap.rst
+
 Null Networking PMD
 M: Tetsuya Mukawa <mtetsuyah@gmail.com>
 F: drivers/net/null/
diff --git a/config/common_base b/config/common_base
index 652a839..eb51cdb 100644
--- a/config/common_base
+++ b/config/common_base
@@ -590,3 +590,12 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the TAP PMD
+#
+# The TAP PMD is currently only built for Linux and the
+# option is enabled by default in common_linuxapp file,
+# set to 'n' in the common_base file.
+#
+CONFIG_RTE_LIBRTE_PMD_TAP=n
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 2483dfa..782b503 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -44,3 +44,4 @@ CONFIG_RTE_LIBRTE_PMD_VHOST=y
 CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
 CONFIG_RTE_LIBRTE_POWER=y
 CONFIG_RTE_VIRTIO_USER=y
+CONFIG_RTE_LIBRTE_PMD_TAP=y
diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst
index 92d56a5..af92529 100644
--- a/doc/guides/nics/index.rst
+++ b/doc/guides/nics/index.rst
@@ -51,6 +51,7 @@ Network Interface Controller Drivers
     nfp
     qede
     szedata2
+    tap
     thunderx
     virtio
     vhost
diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst
new file mode 100644
index 0000000..622b9e7
--- /dev/null
+++ b/doc/guides/nics/tap.rst
@@ -0,0 +1,136 @@
+..  BSD LICENSE
+    Copyright(c) 2016 Intel Corporation. All rights reserved.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+    * Neither the name of Intel Corporation nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Tun/Tap Poll Mode Driver
+========================
+
+The ``rte_eth_tap.c`` PMD creates a device using TUN/TAP interfaces on the
+local host. The PMD allows for DPDK and the host to communicate using a raw
+device interface on the host and in the DPDK application.
+
+The device created is a TAP device, which sends/receives packet in a raw
+format with a L2 header. The usage for a TAP PMD is for connectivity to the
+local host using a TAP interface. When the TAP PMD is initialized it will
+create a number of tap devices in the host accessed via ``ifconfig -a`` or
+``ip`` command. The commands can be used to assign and query the virtual like
+device.
+
+These TAP interfaces can be used with Wireshark or tcpdump or Pktgen-DPDK
+along with being able to be used as a network connection to the DPDK
+application. The method enable one or more interfaces is to use the
+``--vdev=net_tap`` option on the DPDK application command line. Each
+``--vdev=net_tap`` option give will create an interface named dtap0, dtap1,
+and so on.
+
+The interfaced name can be changed by adding the ``iface=foo0``, for example::
+
+   --vdev=net_tap,iface=foo0 --vdev=net_tap,iface=foo1, ...
+
+Also the speed of the interface can be changed from 10G to whatever number
+needed, but the interface does not enforce that speed, for example::
+
+   --vdev=net_tap,iface=foo0,speed=25000
+
+After the DPDK application is started you can send and receive packets on the
+interface using the standard rx_burst/tx_burst APIs in DPDK. From the host
+point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
+and others to communicate with the DPDK application. The DPDK application may
+not understand network protocols like IPv4/6, UDP or TCP unless the
+application has been written to understand these protocols.
+
+If you need the interface as a real network interface meaning running and has
+a valid IP address then you can do this with the following commands::
+
+   sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
+   sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
+
+Please change the IP addresses as you see fit.
+
+If routing is enabled on the host you can also communicate with the DPDK App
+over the internet via a standard socket layer application as long as you
+account for the protocol handing in the application.
+
+If you have a Network Stack in your DPDK application or something like it you
+can utilize that stack to handle the network protocols. Plus you would be able
+to address the interface using an IP address assigned to the internal
+interface.
+
+Example
+-------
+
+The following is a simple example of using the TUN/TAP PMD with the Pktgen
+packet generator. It requires that the ``socat`` utility is installed on the
+test system.
+
+Build DPDK, then pull down Pktgen and build pktgen using the DPDK SDK/Target
+used to build the dpdk you pulled down.
+
+Run pktgen from the pktgen directory in a terminal with a commandline like the
+following::
+
+    sudo ./app/app/x86_64-native-linuxapp-gcc/app/pktgen -l 1-5 -n 4        \
+     --proc-type auto --log-level 8 --socket-mem 512,512 --file-prefix pg   \
+     --vdev=net_tap --vdev=net_tap -b 05:00.0 -b 05:00.1                    \
+     -b 04:00.0 -b 04:00.1 -b 04:00.2 -b 04:00.3                            \
+     -b 81:00.0 -b 81:00.1 -b 81:00.2 -b 81:00.3                            \
+     -b 82:00.0 -b 83:00.0 -- -T -P -m [2:3].0 -m [4:5].1                   \
+     -f themes/black-yellow.theme
+
+.. Note:
+
+   Change the ``-b`` options to blacklist all of your physical ports. The
+   following command line is all one line.
+
+   Also, ``-f themes/black-yellow.theme`` is optional if the default colors
+   work on your system configuration. See the Pktgen docs for more
+   information.
+
+Verify with ``ifconfig -a`` command in a different xterm window, should have a
+``dtap0`` and ``dtap1`` interfaces created.
+
+Next set the links for the two interfaces to up via the commands below::
+
+    sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
+    sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
+
+Then use socat to create a loopback for the two interfaces::
+
+    sudo socat interface:dtap0 interface:dtap1
+
+Then on the Pktgen command line interface you can start sending packets using
+the commands ``start 0`` and ``start 1`` or you can start both at the same
+time with ``start all``. The command ``str`` is an alias for ``start all`` and
+``stp`` is an alias for ``stop all``.
+
+While running you should see the 64 byte counters increasing to verify the
+traffic is being looped back. You can use ``set all size XXX`` to change the
+size of the packets after you stop the traffic. Use the pktgen ``help``
+command to see a list of all commands. You can also use the ``-f`` option to
+load commands at startup.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index bc93230..e366a85 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += pcap
 DIRS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += ring
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += szedata2
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap
 DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
 DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
diff --git a/drivers/net/tap/Makefile b/drivers/net/tap/Makefile
new file mode 100644
index 0000000..e18f30c
--- /dev/null
+++ b/drivers/net/tap/Makefile
@@ -0,0 +1,57 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 Intel Corporation. All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_tap.a
+
+EXPORT_MAP := rte_pmd_tap_version.map
+
+LIBABIVER := 1
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += rte_eth_tap.c
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mempool
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
new file mode 100644
index 0000000..d5e2fc3
--- /dev/null
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -0,0 +1,765 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_vdev.h>
+#include <rte_kvargs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <poll.h>
+#include <arpa/inet.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/if_ether.h>
+#include <fcntl.h>
+
+/* Linux based path to the TUN device */
+#define TUN_TAP_DEV_PATH        "/dev/net/tun"
+#define DEFAULT_TAP_NAME        "dtap"
+
+#define ETH_TAP_IFACE_ARG       "iface"
+#define ETH_TAP_SPEED_ARG       "speed"
+
+#define RTE_PMD_TAP_MAX_QUEUES	16
+
+static const char *valid_arguments[] = {
+	ETH_TAP_IFACE_ARG,
+	ETH_TAP_SPEED_ARG,
+	NULL
+};
+
+static const char *drivername = "Tap PMD";
+static int tap_unit;
+
+static struct rte_eth_link pmd_link = {
+	.link_speed = ETH_SPEED_NUM_10G,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = ETH_LINK_DOWN,
+	.link_autoneg = ETH_LINK_SPEED_AUTONEG
+};
+
+struct pkt_stats {
+	uint64_t opackets;		/* Number of output packets */
+	uint64_t ipackets;		/* Number of input packets */
+	uint64_t obytes;		/* Number of bytes on output */
+	uint64_t ibytes;		/* Number of bytes on input */
+	uint64_t errs;			/* Number of error packets */
+};
+
+struct rx_queue {
+	struct rte_mempool *mp;		/* Mempool for RX packets */
+	uint16_t in_port;		/* Port ID */
+	int fd;
+
+	struct pkt_stats stats;		/* Stats for this RX queue */
+};
+
+struct tx_queue {
+	int fd;
+	struct pkt_stats stats;		/* Stats for this TX queue */
+};
+
+struct pmd_internals {
+	char name[RTE_ETH_NAME_MAX_LEN];	/* Internal Tap device name */
+	uint16_t nb_queues;		/* Number of queues supported */
+	struct ether_addr eth_addr;	/* Mac address of the device port */
+
+	int if_index;			/* IF_INDEX for the port */
+	int fds[RTE_PMD_TAP_MAX_QUEUES]; /* List of all file descriptors */
+
+	struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES];	/* List of RX queues */
+	struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES];	/* List of TX queues */
+};
+
+/* Tun/Tap allocation routine
+ *
+ * name is the number of the interface to use, unless NULL to take the host
+ * supplied name.
+ */
+static int
+tun_alloc(char *name)
+{
+	struct ifreq ifr;
+	unsigned int features;
+	int fd;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+
+	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+	if (name && name[0])
+		strncpy(ifr.ifr_name, name, IFNAMSIZ);
+
+	fd = open(TUN_TAP_DEV_PATH, O_RDWR);
+	if (fd < 0) {
+		RTE_LOG(ERR, PMD, "Unable to create TAP interface");
+		goto error;
+	}
+
+	/* Grab the TUN features to verify we can work */
+	if (ioctl(fd, TUNGETFEATURES, &features) < 0) {
+		RTE_LOG(ERR, PMD, "Unable to get TUN/TAP features\n");
+		goto error;
+	}
+	RTE_LOG(DEBUG, PMD, "TUN/TAP Features %08x\n", features);
+
+	if (!(features & IFF_MULTI_QUEUE) && (RTE_PMD_TAP_MAX_QUEUES > 1)) {
+		RTE_LOG(DEBUG, PMD, "TUN/TAP device only one queue\n");
+		goto error;
+	} else if ((features & IFF_ONE_QUEUE) &&
+			(RTE_PMD_TAP_MAX_QUEUES == 1)) {
+		ifr.ifr_flags |= IFF_ONE_QUEUE;
+		RTE_LOG(DEBUG, PMD, "Single queue only support\n");
+	} else {
+		ifr.ifr_flags |= IFF_MULTI_QUEUE;
+		RTE_LOG(DEBUG, PMD, "Multi-queue support for %d queues\n",
+			RTE_PMD_TAP_MAX_QUEUES);
+	}
+
+	/* Set the TUN/TAP configuration and get the name if needed */
+	if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
+		RTE_LOG(ERR, PMD, "Unable to set TUNSETIFF for %s\n",
+			ifr.ifr_name);
+		perror("TUNSETIFF");
+		goto error;
+	}
+
+	/* Always set the file descriptor to non-blocking */
+	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+		RTE_LOG(ERR, PMD, "Unable to set to nonblocking\n");
+		perror("F_SETFL, NONBLOCK");
+		goto error;
+	}
+
+	/* If the name is different that new name as default */
+	if (name && strcmp(name, ifr.ifr_name))
+		snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", ifr.ifr_name);
+
+	return fd;
+
+error:
+	if (fd > 0)
+		close(fd);
+	return -1;
+}
+
+/* Callback to handle the rx burst of packets to the correct interface and
+ * file descriptor(s) in a multi-queue setup.
+ */
+static uint16_t
+pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+	int len;
+	struct rte_mbuf *mbuf;
+	struct rx_queue *rxq = queue;
+	uint16_t num_rx;
+	unsigned long num_rx_bytes = 0;
+
+	for (num_rx = 0; num_rx < nb_pkts; ) {
+		/* allocate the next mbuf */
+		mbuf = rte_pktmbuf_alloc(rxq->mp);
+		if (unlikely(!mbuf)) {
+			RTE_LOG(WARNING, PMD, "Unable to allocate mbuf\n");
+			break;
+		}
+
+		len = read(rxq->fd, rte_pktmbuf_mtod(mbuf, char *),
+			   rte_pktmbuf_tailroom(mbuf));
+		if (len <= 0) {
+			rte_pktmbuf_free(mbuf);
+			break;
+		}
+
+		mbuf->data_len = len;
+		mbuf->pkt_len = len;
+		mbuf->port = rxq->in_port;
+
+		/* account for the receive frame */
+		bufs[num_rx++] = mbuf;
+		num_rx_bytes += mbuf->pkt_len;
+	}
+	rxq->stats.ipackets += num_rx;
+	rxq->stats.ibytes += num_rx_bytes;
+
+	return num_rx;
+}
+
+/* Callback to handle sending packets from the tap interface
+ */
+static uint16_t
+pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+	struct rte_mbuf *mbuf;
+	struct tx_queue *txq = queue;
+	struct pollfd pfd;
+	uint16_t num_tx = 0;
+	unsigned long num_tx_bytes = 0;
+	int i, n;
+
+	if (unlikely(nb_pkts == 0))
+		return 0;
+
+	pfd.events = POLLOUT;
+	pfd.fd = txq->fd;
+	for (i = 0; i < nb_pkts; i++) {
+		n = poll(&pfd, 1, 0);
+
+		if (n <= 0)
+			break;
+
+		if (pfd.revents & POLLOUT) {
+			/* copy the tx frame data */
+			mbuf = bufs[num_tx];
+			n = write(pfd.fd, rte_pktmbuf_mtod(mbuf, void*),
+				  rte_pktmbuf_pkt_len(mbuf));
+			if (n <= 0)
+				break;
+
+			num_tx++;
+			num_tx_bytes += mbuf->pkt_len;
+			rte_pktmbuf_free(mbuf);
+		}
+	}
+
+	txq->stats.opackets += num_tx;
+	txq->stats.errs += nb_pkts - num_tx;
+	txq->stats.obytes += num_tx_bytes;
+
+	return num_tx;
+}
+
+static int
+tap_dev_start(struct rte_eth_dev *dev)
+{
+	/* Force the Link up */
+	dev->data->dev_link.link_status = ETH_LINK_UP;
+
+	return 0;
+}
+
+/* This function gets called when the current port gets stopped.
+ */
+static void
+tap_dev_stop(struct rte_eth_dev *dev)
+{
+	int i;
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	for (i = 0; i < internals->nb_queues; i++)
+		if (internals->fds[i] != -1)
+			close(internals->fds[i]);
+
+	dev->data->dev_link.link_status = ETH_LINK_DOWN;
+}
+
+static int
+tap_dev_configure(struct rte_eth_dev *dev __rte_unused)
+{
+	return 0;
+}
+
+static void
+tap_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	dev_info->driver_name = drivername;
+	dev_info->if_index = internals->if_index;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)ETHER_MAX_VLAN_FRAME_LEN;
+	dev_info->max_rx_queues = internals->nb_queues;
+	dev_info->max_tx_queues = internals->nb_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+tap_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *tap_stats)
+{
+	unsigned int i, imax;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	unsigned long rx_bytes_total = 0, tx_bytes_total = 0;
+	const struct pmd_internals *pmd = dev->data->dev_private;
+
+	imax = (pmd->nb_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
+		pmd->nb_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS;
+
+	for (i = 0; i < imax; i++) {
+		tap_stats->q_ipackets[i] = pmd->rxq[i].stats.ipackets;
+		tap_stats->q_ibytes[i] = pmd->rxq[i].stats.ibytes;
+		rx_total += tap_stats->q_ipackets[i];
+		rx_bytes_total += tap_stats->q_ibytes[i];
+	}
+
+	for (i = 0; i < imax; i++) {
+		tap_stats->q_opackets[i] = pmd->txq[i].stats.opackets;
+		tap_stats->q_errors[i] = pmd->txq[i].stats.errs;
+		tap_stats->q_obytes[i] = pmd->txq[i].stats.obytes;
+		tx_total += tap_stats->q_opackets[i];
+		tx_err_total += tap_stats->q_errors[i];
+		tx_bytes_total += tap_stats->q_obytes[i];
+	}
+
+	tap_stats->ipackets = rx_total;
+	tap_stats->ibytes = rx_bytes_total;
+	tap_stats->opackets = tx_total;
+	tap_stats->oerrors = tx_err_total;
+	tap_stats->obytes = tx_bytes_total;
+}
+
+static void
+tap_stats_reset(struct rte_eth_dev *dev)
+{
+	int i;
+	struct pmd_internals *pmd = dev->data->dev_private;
+
+	for (i = 0; i < pmd->nb_queues; i++) {
+		pmd->rxq[i].stats.ipackets = 0;
+		pmd->rxq[i].stats.ibytes = 0;
+	}
+
+	for (i = 0; i < pmd->nb_queues; i++) {
+		pmd->txq[i].stats.opackets = 0;
+		pmd->txq[i].stats.errs = 0;
+		pmd->txq[i].stats.obytes = 0;
+	}
+}
+
+static void
+tap_dev_close(struct rte_eth_dev *dev __rte_unused)
+{
+}
+
+static void
+tap_rx_queue_release(void *queue)
+{
+	struct rx_queue *rxq = queue;
+
+	if (rxq && (rxq->fd > 0)) {
+		close(rxq->fd);
+		rxq->fd = -1;
+	}
+}
+
+static void
+tap_tx_queue_release(void *queue)
+{
+	struct tx_queue *txq = queue;
+
+	if (txq && (txq->fd > 0)) {
+		close(txq->fd);
+		txq->fd = -1;
+	}
+}
+
+static int
+tap_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused)
+{
+	return 0;
+}
+
+static int
+tap_setup_queue(struct rte_eth_dev *dev,
+		struct pmd_internals *internals,
+		uint16_t qid)
+{
+	struct rx_queue *rx = &internals->rxq[qid];
+	struct tx_queue *tx = &internals->txq[qid];
+	int fd;
+
+	fd = rx->fd;
+	if (fd < 0) {
+		fd = tx->fd;
+		if (fd < 0) {
+			RTE_LOG(INFO, PMD, "Add queue to TAP %s for qid %d\n",
+				dev->data->name, qid);
+			fd = tun_alloc(dev->data->name);
+			if (fd < 0) {
+				RTE_LOG(ERR, PMD, "tun_alloc(%s) failed\n",
+					dev->data->name);
+				return -1;
+			}
+		}
+	}
+	dev->data->rx_queues[qid] = rx;
+	dev->data->tx_queues[qid] = tx;
+
+	rx->fd = fd;
+	tx->fd = fd;
+
+	return fd;
+}
+
+static int
+tap_rx_queue_setup(struct rte_eth_dev *dev,
+		   uint16_t rx_queue_id,
+		   uint16_t nb_rx_desc __rte_unused,
+		   unsigned int socket_id __rte_unused,
+		   const struct rte_eth_rxconf *rx_conf __rte_unused,
+		   struct rte_mempool *mp)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+	uint16_t buf_size;
+	int fd;
+
+	if ((rx_queue_id >= internals->nb_queues) || !mp) {
+		RTE_LOG(ERR, PMD, "nb_queues %d mp %p\n",
+			internals->nb_queues, mp);
+		return -1;
+	}
+
+	internals->rxq[rx_queue_id].mp = mp;
+	internals->rxq[rx_queue_id].in_port = dev->data->port_id;
+
+	/* Now get the space available for data in the mbuf */
+	buf_size = (uint16_t)(rte_pktmbuf_data_room_size(mp) -
+				RTE_PKTMBUF_HEADROOM);
+
+	if (buf_size < ETH_FRAME_LEN) {
+		RTE_LOG(ERR, PMD,
+			"%s: %d bytes will not fit in mbuf (%d bytes)\n",
+			dev->data->name, ETH_FRAME_LEN, buf_size);
+		return -ENOMEM;
+	}
+
+	fd = tap_setup_queue(dev, internals, rx_queue_id);
+	if (fd == -1)
+		return -1;
+
+	internals->fds[rx_queue_id] = fd;
+	RTE_LOG(INFO, PMD, "RX TAP device name %s, qid %d on fd %d\n",
+		dev->data->name, rx_queue_id, internals->rxq[rx_queue_id].fd);
+
+	return 0;
+}
+
+static int
+tap_tx_queue_setup(struct rte_eth_dev *dev,
+		   uint16_t tx_queue_id,
+		   uint16_t nb_tx_desc __rte_unused,
+		   unsigned int socket_id __rte_unused,
+		   const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+	int ret;
+
+	if (tx_queue_id >= internals->nb_queues)
+		return -1;
+
+	ret = tap_setup_queue(dev, internals, tx_queue_id);
+	if (ret == -1)
+		return -1;
+
+	RTE_LOG(INFO, PMD, "TX TAP device name %s, qid %d on fd %d\n",
+		dev->data->name, tx_queue_id, internals->txq[tx_queue_id].fd);
+
+	return 0;
+}
+
+static const struct eth_dev_ops ops = {
+	.dev_start              = tap_dev_start,
+	.dev_stop               = tap_dev_stop,
+	.dev_close              = tap_dev_close,
+	.dev_configure          = tap_dev_configure,
+	.dev_infos_get          = tap_dev_info,
+	.rx_queue_setup         = tap_rx_queue_setup,
+	.tx_queue_setup         = tap_tx_queue_setup,
+	.rx_queue_release       = tap_rx_queue_release,
+	.tx_queue_release       = tap_tx_queue_release,
+	.link_update            = tap_link_update,
+	.stats_get              = tap_stats_get,
+	.stats_reset            = tap_stats_reset,
+};
+
+static int
+pmd_mac_address(int fd, struct rte_eth_dev *dev, struct ether_addr *addr)
+{
+	struct ifreq ifr;
+
+	if ((fd <= 0) || !dev || !addr)
+		return -1;
+
+	memset(&ifr, 0, sizeof(ifr));
+
+	if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
+		RTE_LOG(ERR, PMD, "ioctl failed (SIOCGIFHWADDR) (%s)\n",
+			ifr.ifr_name);
+		return -1;
+	}
+
+	/* Set the host based MAC address to this special MAC format */
+	ifr.ifr_hwaddr.sa_data[0] = 'T';
+	ifr.ifr_hwaddr.sa_data[1] = 'a';
+	ifr.ifr_hwaddr.sa_data[2] = 'p';
+	ifr.ifr_hwaddr.sa_data[3] = '-';
+	ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
+	ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
+	if (ioctl(fd, SIOCSIFHWADDR, &ifr) == -1) {
+		RTE_LOG(ERR, PMD, "%s: ioctl failed (SIOCSIFHWADDR) (%s)\n",
+			dev->data->name, ifr.ifr_name);
+		return -1;
+	}
+
+	/* Set the local application MAC address, needs to be different then
+	 * the host based MAC address.
+	 */
+	ifr.ifr_hwaddr.sa_data[0] = 'd';
+	ifr.ifr_hwaddr.sa_data[1] = 'n';
+	ifr.ifr_hwaddr.sa_data[2] = 'e';
+	ifr.ifr_hwaddr.sa_data[3] = 't';
+	ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
+	ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
+	rte_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+	return 0;
+}
+
+static int
+eth_dev_tap_create(const char *name, char *tap_name)
+{
+	int numa_node = rte_socket_id();
+	struct rte_eth_dev *dev = NULL;
+	struct pmd_internals *pmd = NULL;
+	struct rte_eth_dev_data *data = NULL;
+	int i, fd = -1;
+
+	RTE_LOG(INFO, PMD,
+		"%s: Create TAP Ethernet device with %d queues on numa %u\n",
+		 name, RTE_PMD_TAP_MAX_QUEUES, rte_socket_id());
+
+	data = rte_zmalloc_socket(tap_name, sizeof(*data), 0, numa_node);
+	if (!data) {
+		RTE_LOG(INFO, PMD, "Failed to allocate data\n");
+		goto error_exit;
+	}
+
+	pmd = rte_zmalloc_socket(tap_name, sizeof(*pmd), 0, numa_node);
+	if (!pmd) {
+		RTE_LOG(INFO, PMD, "Unable to allocate internal struct\n");
+		goto error_exit;
+	}
+
+	/* Use the name and not the tap_name */
+	dev = rte_eth_dev_allocate(tap_name);
+	if (!dev) {
+		RTE_LOG(INFO, PMD, "Unable to allocate device struct\n");
+		goto error_exit;
+	}
+
+	snprintf(pmd->name, sizeof(pmd->name), "%s", tap_name);
+
+	pmd->nb_queues = RTE_PMD_TAP_MAX_QUEUES;
+
+	/* Setup some default values */
+	data->dev_private = pmd;
+	data->port_id = dev->data->port_id;
+	data->dev_flags = RTE_ETH_DEV_DETACHABLE;
+	data->kdrv = RTE_KDRV_NONE;
+	data->drv_name = drivername;
+	data->numa_node = numa_node;
+
+	data->dev_link = pmd_link;
+	data->mac_addrs = &pmd->eth_addr;
+	data->nb_rx_queues = pmd->nb_queues;
+	data->nb_tx_queues = pmd->nb_queues;
+	data->drv_name = drivername;
+
+	dev->data = data;
+	dev->dev_ops = &ops;
+	dev->driver = NULL;
+	dev->rx_pkt_burst = pmd_rx_burst;
+	dev->tx_pkt_burst = pmd_tx_burst;
+	snprintf(dev->data->name, sizeof(dev->data->name), "%s", name);
+
+	/* Create the first Tap device */
+	fd = tun_alloc(tap_name);
+	if (fd < 0) {
+		RTE_LOG(INFO, PMD, "tun_alloc() failed\n");
+		goto error_exit;
+	}
+
+	/* Presetup the fds to -1 as being not working */
+	for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
+		pmd->fds[i] = -1;
+		pmd->rxq[i].fd = -1;
+		pmd->txq[i].fd = -1;
+	}
+
+	/* Take the TUN/TAP fd and place in the first location */
+	pmd->rxq[0].fd = fd;
+	pmd->txq[0].fd = fd;
+	pmd->fds[0] = fd;
+
+	if (pmd_mac_address(fd, dev, &pmd->eth_addr) < 0) {
+		RTE_LOG(INFO, PMD, "Unable to get MAC address\n");
+		goto error_exit;
+	}
+
+	return 0;
+
+error_exit:
+	RTE_PMD_DEBUG_TRACE("Unable to initialize %s\n", name);
+
+	rte_free(data);
+	rte_free(pmd);
+
+	rte_eth_dev_release_port(dev);
+
+	return -EINVAL;
+}
+
+static int
+set_interface_name(const char *key __rte_unused,
+		   const char *value,
+		   void *extra_args)
+{
+	char *name = (char *)extra_args;
+
+	if (value)
+		snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", value);
+	else
+		snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s%d",
+			 DEFAULT_TAP_NAME, (tap_unit - 1));
+
+	return 0;
+}
+
+static int
+set_interface_speed(const char *key __rte_unused,
+		    const char *value,
+		    void *extra_args)
+{
+	*(int *)extra_args = (value) ? atoi(value) : ETH_SPEED_NUM_10G;
+
+	return 0;
+}
+
+/* Open a TAP interface device.
+ */
+static int
+rte_pmd_tap_probe(const char *name, const char *params)
+{
+	int ret;
+	struct rte_kvargs *kvlist = NULL;
+	int speed;
+	char tap_name[RTE_ETH_NAME_MAX_LEN];
+
+	speed = ETH_SPEED_NUM_10G;
+	snprintf(tap_name, sizeof(tap_name), "%s%d",
+		 DEFAULT_TAP_NAME, tap_unit++);
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_tap for %s as %s\n",
+		name, tap_name);
+
+	if (params && (params[0] != '\0')) {
+		RTE_LOG(INFO, PMD, "paramaters (%s)\n", params);
+
+		kvlist = rte_kvargs_parse(params, valid_arguments);
+		if (kvlist) {
+			if (rte_kvargs_count(kvlist, ETH_TAP_SPEED_ARG) == 1) {
+				ret = rte_kvargs_process(kvlist,
+							 ETH_TAP_SPEED_ARG,
+							 &set_interface_speed,
+							 &speed);
+				if (ret == -1)
+					goto leave;
+			}
+
+			if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
+				ret = rte_kvargs_process(kvlist,
+							 ETH_TAP_IFACE_ARG,
+							 &set_interface_name,
+							 tap_name);
+				if (ret == -1)
+					goto leave;
+			}
+		}
+	}
+	pmd_link.link_speed = speed;
+
+	ret = eth_dev_tap_create(name, tap_name);
+
+leave:
+	if (ret == -1) {
+		RTE_LOG(INFO, PMD, "Failed to create pmd for %s as %s\n",
+			name, tap_name);
+		tap_unit--;		/* Restore the unit number */
+	}
+	rte_kvargs_free(kvlist);
+
+	return ret;
+}
+
+/* detach a TAP device.
+ */
+static int
+rte_pmd_tap_remove(const char *name)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+	struct pmd_internals *internals;
+	int i;
+
+	RTE_LOG(INFO, PMD, "Closing TUN/TAP Ethernet device on numa %u\n",
+		rte_socket_id());
+
+	/* find the ethdev entry */
+	eth_dev = rte_eth_dev_allocated(name);
+	if (!eth_dev)
+		return 0;
+
+	internals = eth_dev->data->dev_private;
+	for (i = 0; i < internals->nb_queues; i++)
+		if (internals->fds[i] != -1)
+			close(internals->fds[i]);
+
+	rte_free(eth_dev->data->dev_private);
+	rte_free(eth_dev->data);
+
+	rte_eth_dev_release_port(eth_dev);
+
+	return 0;
+}
+
+static struct rte_vdev_driver pmd_tap_drv = {
+	.probe = rte_pmd_tap_probe,
+	.remove = rte_pmd_tap_remove,
+};
+RTE_PMD_REGISTER_VDEV(net_tap, pmd_tap_drv);
+RTE_PMD_REGISTER_PARAM_STRING(net_tap, "iface=<string>,speed=N");
diff --git a/drivers/net/tap/rte_pmd_tap_version.map b/drivers/net/tap/rte_pmd_tap_version.map
new file mode 100644
index 0000000..61463bf
--- /dev/null
+++ b/drivers/net/tap/rte_pmd_tap_version.map
@@ -0,0 +1,4 @@
+DPDK_16.11 {
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..02c32ae 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -124,6 +124,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP)       += -lrte_pmd_pcap -lpcap
 _LDLIBS-$(CONFIG_RTE_LIBRTE_QEDE_PMD)       += -lrte_pmd_qede
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_RING)       += -lrte_pmd_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2)   += -lrte_pmd_szedata2 -lsze2
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_TAP)        += -lrte_pmd_tap
 _LDLIBS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += -lrte_pmd_thunderx_nicvf -lm
 _LDLIBS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD)     += -lrte_pmd_virtio
 ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y)
-- 
2.8.0.GIT

^ permalink raw reply related

* Re: [PATCH v10] drivers/net:new TUN/TAP device PMD
From: Ferruh Yigit @ 2016-12-09 18:16 UTC (permalink / raw)
  To: Keith Wiles, dev; +Cc: pmatilai, yuanhan.liu, john.mcnamara
In-Reply-To: <20161207193844.41193-1-keith.wiles@intel.com>

On 12/7/2016 7:38 PM, Keith Wiles wrote:
> The PMD allows for DPDK and the host to communicate using a raw
> device interface on the host and in the DPDK application. The device
> created is a Tap device with a L2 packet header.
> 
> v10- Change the string name used to allow for multiple devices.
> v9 - Fix up the docs to use correct syntax
> v8 - Fix issue with tap_tx_queue_setup() not return zero on success.
> v7 - Reword the comment in common_base and fix the data->name issue
> v6 - fixed the checkpatch issues
> v5 - merge in changes from list review see related emails
>      fixed many minor edits
> v4 - merge with latest driver changes
> v3 - fix includes by removing ifdef for other type besides Linux
>      Fix the copyright notice in the Makefile
> v2 - merge all of the patches into one patch
>      Fix a typo on naming the tap device
>      Update the maintainers list
> 
> Signed-off-by: Keith Wiles <keith.wiles@intel.com>
> ---
>  MAINTAINERS                             |   5 +
>  config/common_base                      |   9 +
>  config/common_linuxapp                  |   1 +
>  doc/guides/nics/tap.rst                 | 136 ++++++

This is giving following warning [1], this file needs to be added into
doc/guides/nics/index.rst

[1]
doc/guides/nics/tap.rst:: WARNING: document isn't included in any toctree

>  drivers/net/Makefile                    |   1 +
>  drivers/net/tap/Makefile                |  57 +++
>  drivers/net/tap/rte_eth_tap.c           | 765 ++++++++++++++++++++++++++++++++
>  drivers/net/tap/rte_pmd_tap_version.map |   4 +
>  mk/rte.app.mk                           |   1 +
>  9 files changed, 979 insertions(+)
>  create mode 100644 doc/guides/nics/tap.rst
>  create mode 100644 drivers/net/tap/Makefile
>  create mode 100644 drivers/net/tap/rte_eth_tap.c
>  create mode 100644 drivers/net/tap/rte_pmd_tap_version.map
> 
<...>

> diff --git a/drivers/net/tap/rte_pmd_tap_version.map b/drivers/net/tap/rte_pmd_tap_version.map
> new file mode 100644
> index 0000000..61463bf
> --- /dev/null
> +++ b/drivers/net/tap/rte_pmd_tap_version.map
> @@ -0,0 +1,4 @@
> +DPDK_16.11 {

17.02

> +
> +	local: *;
> +};

<...>

^ permalink raw reply

* Re: [PATCH v2 8/9] librte_ether: remove the set VF API's
From: Ferruh Yigit @ 2016-12-09 18:00 UTC (permalink / raw)
  To: Bernard Iremonger, thomas.monjalon, dev
In-Reply-To: <1481304361-16032-9-git-send-email-bernard.iremonger@intel.com>

On 12/9/2016 5:26 PM, Bernard Iremonger wrote:
> remove the following API's:
> 
> rte_eth_dev_set_vf_rxmode
> rte_eth_dev_set_vf_rx
> rte_eth_dev_set_vf_tx
> rte_eth_dev_set_vf_vlan_filter
> rte_eth_dev_set_vf_rate_limit

This patch should also remove above function definitions from
rte_ethdev.h and rte_ether_version.map too.

And it may be good to squash next patch (remove deprecation notice) to
this one to show what caused to notice removal.

Also need to increase LIBABIVER, and update release notes for ABI
breakage, somewhere in this patchset, I would do in this patch but not
quite sure.

> 
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> ---
>  lib/librte_ether/rte_ethdev.c | 129 ------------------------------------------
>  lib/librte_ether/rte_ethdev.h |  33 -----------
>  2 files changed, 162 deletions(-)
> 

<...>

^ permalink raw reply

* Re: [PATCH 00/25] net/qede: update qede pmd to 2.0.0.1
From: Mody, Rasesh @ 2016-12-09 17:48 UTC (permalink / raw)
  To: Ferruh Yigit, dev@dpdk.org; +Cc: Dept-Eng DPDK Dev
In-Reply-To: <c0c4192e-0570-d3bd-d194-1406b84deb97@intel.com>

Hi Ferruh,

> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
> Sent: Friday, December 09, 2016 8:53 AM
> 
> On 12/3/2016 9:11 AM, Rasesh Mody wrote:
> > Hi,
> >
> > This patch set consists of enhancements, new 8.14.x.x firmware support
> > and semantic changes. It update the QEDE PMD version to 2.0.0.1.
> >
> > Please include in DPDK 17.02 release.
> 
> Hi Rasesh,
> 
> This patchset seems depends to both [1] and [2], can you confirm?
> 
> [1] http://dpdk.org/ml/archives/dev/2016-December/051260.html
> [2] http://dpdk.org/ml/archives/dev/2016-December/051253.html

That's correct, sorry missed to mention that.

Thanks!
Rasesh
> 
> Thanks,
> ferruh
> 
> >
> > Thanks!
> > Rasesh
> >
> <...>

^ permalink raw reply

* Re: [PATCH v1 0/4] app: make python apps python2/3 compliant
From: Mcnamara, John @ 2016-12-09 17:41 UTC (permalink / raw)
  To: Neil Horman; +Cc: dev@dpdk.org, mkletzan@redhat.com
In-Reply-To: <20161209170610.GB23061@hmsreliant.think-freely.org>



> -----Original Message-----
> From: Neil Horman [mailto:nhorman@tuxdriver.com]
> Sent: Friday, December 9, 2016 5:06 PM
> To: Mcnamara, John <john.mcnamara@intel.com>
> Cc: dev@dpdk.org; mkletzan@redhat.com
> Subject: Re: [dpdk-dev] [PATCH v1 0/4] app: make python apps python2/3
> compliant
> 
> On Fri, Dec 09, 2016 at 05:00:19PM +0000, Mcnamara, John wrote:
> >
> >
> > > -----Original Message-----
> > > From: Neil Horman [mailto:nhorman@tuxdriver.com]
> > > Sent: Friday, December 9, 2016 3:29 PM
> > > To: Mcnamara, John <john.mcnamara@intel.com>
> > > Cc: dev@dpdk.org; mkletzan@redhat.com
> > > Subject: Re: [dpdk-dev] [PATCH v1 0/4] app: make python apps
> > > python2/3 compliant
> > >
> > > On Thu, Dec 08, 2016 at 03:51:01PM +0000, John McNamara wrote:
> > > > These patches refactor the DPDK Python applications to make them
> > > > Python 2/3 compatible.
> > > >
> > > > In order to do this the patchset starts by making the apps PEP8
> > > > compliant in accordance with the DPDK Coding guidelines:
> > > >
> > > >
> > > > http://dpdk.org/doc/guides/contributing/coding_style.html#python-c
> > > > ode
> > > >
> > > > Implementing PEP8 and Python 2/3 compliance means that we can
> > > > check all future Python patches for consistency. Python 2/3
> > > > support also makes downstream packaging easier as more distros
> > > > move to Python 3 as
> > > the system python.
> > > >
> > > > See the previous discussion about Python2/3 compatibilty here:
> > > >
> > > >     http://dpdk.org/ml/archives/dev/2016-December/051683.html
> > > >
> > > > I've tested that the apps compile with python 2 and 3 and I've
> > > > tested some of the apps for consistent output but it needs
> additional testing.
> > > >
> > > > John McNamara (4):
> > > >   app: make python apps pep8 compliant
> > > >   app: make python apps python2/3 compliant
> > > >   app: give python apps a consistent shebang line
> > > >   doc: add required python versions to coding guidelines
> > > >
> > > ...
> >
> > And just to be clear, I don't think this patchset should be merged until
> all of the apps have been functionally tested. I'll put something in the
> final patchset to indicate that the modified apps have been tested.
> >
> I completely agree that the utilities should be functionally compatible
> with python 3, but in regards to this patch set, all I'm really asking for
> is that the changelog reflect that its just making stylistic changes to
> comply with pep8 (i.e. not fixing python 2/3 compatibility issues).  The
> latter can be handled in subsequent patches piecemeal.
> 

Hi Neil,

Sorry if I'm missing something, but isn't that how the changelog is structured?

>From above:

 John McNamara (4):
   app: make python apps pep8 compliant
   app: make python apps python2/3 compliant
   app: give python apps a consistent shebang line
   doc: add required python versions to coding guidelines

The PEP8 changes are made in 1/4. The Python 2/3 changes are made in 2/4.

Also, the pmdinfo issue was easier to resolve than I feared. The following should fix the exception (on top of the other patches). I tested the output with a couple of pmds but maybe
you could verify it as well.

John

$ git diff
diff --git a/tools/dpdk-pmdinfo.py b/tools/dpdk-pmdinfo.py
index 097982e..d4e51aa 100755
--- a/tools/dpdk-pmdinfo.py
+++ b/tools/dpdk-pmdinfo.py
@@ -434,7 +434,7 @@ def process_dt_needed_entries(self):
 
         for tag in dynsec.iter_tags():
             if tag.entry.d_tag == 'DT_NEEDED':
-                rc = tag.needed.find("librte_pmd")
+                rc = tag.needed.find(b"librte_pmd")
                 if (rc != -1):
                     library = search_file(tag.needed,

^ permalink raw reply related

* Re: [PATCH 00/31] Support more features in Solarflare PMD
From: Ferruh Yigit @ 2016-12-09 17:34 UTC (permalink / raw)
  To: Andrew Rybchenko, dev
In-Reply-To: <1480664691-26561-1-git-send-email-arybchenko@solarflare.com>

On 12/2/2016 7:44 AM, Andrew Rybchenko wrote:
> The patch series adds a number of features to Solarflare libefx-based
> PMD. Basically one patch per feature.
> 
> The patches are grouped into one series since they touch nearby lines
> in either PMD feature list, or dev_ops structure, or documentation.
> So, patches cannot be applied in arbitrary order.
> 
> The patch series should be applied after
> [PATCH v2 00/55] Solarflare libefx-based PMD
> (Message-ID: 1480436367-20749-1-git-send-email-arybchenko@solarflare.com)
> 
> 
> Andrew Rybchenko (16):
>   net/sfc: implement MCDI logging callback
>   net/sfc: support parameter to choose performance profile
>   net/sfc: implement ethdev hook to get basic statistics
>   net/sfc: support extended statistics
>   net/sfc: support flow control settings get/set
>   net/sfc: support link status change interrupt
>   net/sfc: implement device operation to change MTU
>   net/sfc: support link speed and duplex settings
>   net/sfc: support checksum offloads on receive
>   net/sfc: handle received packet type info provided by HW
>   net/sfc: support callback to get receive queue information
>   net/sfc: support Rx free threshold
>   net/sfc: add callback to get RxQ pending descriptors count
>   net/sfc: add RxQ descriptor done callback
>   net/sfc: support scattered Rx DMA
>   net/sfc: support deferred start of receive queues
> 
> Artem Andreev (1):
>   net/sfc: support link up/down
> 
> Ivan Malov (14):
>   net/sfc: support promiscuous and all-multicast control
>   net/sfc: support main (the first) MAC address change
>   net/sfc: support multicast addresses list controls
>   net/sfc: add callback to get transmit queue information
>   net/sfc: support Tx free threshold
>   net/sfc: support deferred start of transmit queues
>   net/sfc: support VLAN offload on transmit path
>   net/sfc: add basic stubs for RSS support on driver attach
>   net/sfc: support RSS hash offload
>   net/sfc: add callback to query RSS key and hash types config
>   net/sfc: add callback to set RSS key and hash types config
>   net/sfc: add callback to query RSS redirection table
>   net/sfc: add callback to update RSS redirection table
>   net/sfc: support firmware-assisted TSOv2

Hi Andrew,

I am getting following build errors for clang [1] and ICC [2]. I have
not investigated the root cause, just copy-pasting here.

For ICC, since you explicitly noted it is not supported, and reported
warning is known, I believe it is safe the ignore this warning via
"-wd188" CFLAGS option in the Makefile.

Thanks,
ferruh



[1] clang
.../drivers/net/sfc/sfc_ethdev.c:1143:4: error: format specifies type
'unsigned short' but the argument has type 'int' [-Werror,-Wformat]
                        EFX_RSS_TBL_SIZE);
                        ^~~~~~~~~~~~~~~~
.../drivers/net/sfc/base/efx.h:1866:26: note: expanded from macro
'EFX_RSS_TBL_SIZE'
#define EFX_RSS_TBL_SIZE        128     /* Rows in RX indirection table */
                                ^~~
.../drivers/net/sfc/sfc_log.h:51:19: note: expanded from macro 'sfc_err'
        SFC_LOG(sa, ERR, __VA_ARGS__)
                         ^~~~~~~~~~~
.../drivers/net/sfc/sfc_log.h:47:18: note: expanded from macro 'SFC_LOG'
                                RTE_FMT_TAIL(__VA_ARGS__,)));           \
                                             ^~~~~~~~~~~
.../x86_64-native-linuxapp-clang/include/rte_common.h:345:32: note:
expanded from macro 'RTE_FMT_TAIL'
#define RTE_FMT_TAIL(fmt, ...) __VA_ARGS__
                               ^~~~~~~~~~~
.../x86_64-native-linuxapp-clang/include/rte_common.h:343:39: note:
expanded from macro 'RTE_FMT'
#define RTE_FMT(fmt, ...) fmt "%.0s", __VA_ARGS__ ""
                                      ^~~~~~~~~~~
.../x86_64-native-linuxapp-clang/include/rte_log.h:258:32: note:
expanded from macro 'RTE_LOG'
                 RTE_LOGTYPE_ ## t, # t ": " __VA_ARGS__)
                                             ^~~~~~~~~~~



[2] ICC
.../drivers/net/sfc/sfc_ethdev.c(1063): error #188: enumerated type
mixed with another type
                                   efx_hash_types, B_TRUE);
                                   ^

.../drivers/net/sfc/sfc_ethdev.c(1086): error #188: enumerated type
mixed with another type
                                  sa->rss_hash_types, B_TRUE) != 0)
                                  ^

compilation aborted for .../drivers/net/sfc/sfc_ethdev.c (code 2)
make[7]: *** [sfc_ethdev.o] Error 2
make[7]: *** Waiting for unfinished jobs....
.../drivers/net/sfc/sfc_rx.c(820): error #188: enumerated type mixed
with another type
                                           sa->rss_hash_types, B_TRUE);
                                           ^

compilation aborted for .../drivers/net/sfc/sfc_rx.c (code 2)

^ permalink raw reply


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