* [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior
@ 2017-08-04 13:52 Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 02/12] i40e: Fix reporting of supported link modes Alice Michael
` (12 more replies)
0 siblings, 13 replies; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Mariusz Stachura <mariusz.stachura@intel.com>
Instead of accessing register directly, use newly added AQC in
order to blink LEDs. Introduce and utilize a new flag to prevent
excessive API version checking.
Signed-off-by: Mariusz Stachura <mariusz.stachura@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_adminq.c | 6 ++
drivers/net/ethernet/intel/i40e/i40e_common.c | 148 ++++++++++++++++++++------
drivers/net/ethernet/intel/i40e/i40e_type.h | 1 +
drivers/net/ethernet/intel/i40evf/i40e_type.h | 2 +
4 files changed, 122 insertions(+), 35 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index ba04988..340e5a2 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -607,6 +607,12 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
&oem_lo);
hw->nvm.oem_ver = ((u32)oem_hi << 16) | oem_lo;
+ if (hw->mac.type == I40E_MAC_XL710 &&
+ hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
+ hw->aq.api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710) {
+ hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
+ }
+
if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) {
ret_code = I40E_ERR_FIRMWARE_API_VERSION;
goto init_adminq_free_arq;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index e4e86e0..e9f30b8 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -4849,24 +4849,38 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
u16 temp_addr;
u8 port_num;
u32 i;
-
- temp_addr = I40E_PHY_LED_PROV_REG_1;
- 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);
-
- for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
- temp_addr++) {
- status = i40e_read_phy_register_clause45(hw,
+ u32 reg_val_aq;
+
+ if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+ status =
+ i40e_aq_get_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+ I40E_PHY_COM_REG_PAGE,
+ I40E_PHY_LED_PROV_REG_1,
+ ®_val_aq, NULL);
+ if (status)
+ return status;
+ *val = (u16)reg_val_aq;
+ } else {
+ temp_addr = I40E_PHY_LED_PROV_REG_1;
+ 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);
+
+ for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
+ temp_addr++) {
+ status =
+ i40e_read_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE,
temp_addr, phy_addr,
®_val);
- if (status)
- return status;
- *val = reg_val;
- if (reg_val & I40E_PHY_LED_LINK_MODE_MASK) {
- *led_addr = temp_addr;
- break;
+ if (status)
+ return status;
+ *val = reg_val;
+ if (reg_val & I40E_PHY_LED_LINK_MODE_MASK) {
+ *led_addr = temp_addr;
+ break;
+ }
}
}
return status;
@@ -4884,51 +4898,115 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,
u16 led_addr, u32 mode)
{
i40e_status status = 0;
- u16 led_ctl = 0;
- u16 led_reg = 0;
+ u32 led_ctl = 0;
+ u32 led_reg = 0;
u8 phy_addr = 0;
u8 port_num;
u32 i;
- 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_clause45(hw, I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, &led_reg);
+ if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+ status =
+ i40e_aq_get_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+ I40E_PHY_COM_REG_PAGE,
+ I40E_PHY_LED_PROV_REG_1,
+ &led_reg, NULL);
+ } else {
+ 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_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr,
+ (u16 *)&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_clause45(hw,
- I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr,
- led_reg);
+ if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
+ hw->aq.api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710) {
+ status = i40e_aq_set_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+ I40E_PHY_COM_REG_PAGE,
+ I40E_PHY_LED_PROV_REG_1,
+ led_reg, NULL);
+ } else {
+ status = i40e_write_phy_register_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr,
+ (u16)led_reg);
+ }
if (status)
return status;
}
- status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, &led_reg);
+ if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+ status =
+ i40e_aq_get_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+ I40E_PHY_COM_REG_PAGE,
+ I40E_PHY_LED_PROV_REG_1,
+ &led_reg, NULL);
+ } else {
+ status = i40e_read_phy_register_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr,
+ (u16 *)&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_clause45(hw, I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, led_reg);
+
+ if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+ status =
+ i40e_aq_set_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+ I40E_PHY_COM_REG_PAGE,
+ I40E_PHY_LED_PROV_REG_1,
+ led_reg, NULL);
+ } else {
+ status =
+ i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr,
+ (u16)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_clause45(hw,
- I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, led_ctl);
+ if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+ status = i40e_aq_set_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+ I40E_PHY_COM_REG_PAGE,
+ I40E_PHY_LED_PROV_REG_1,
+ led_ctl, NULL);
+ } else {
+ status = i40e_write_phy_register_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr,
+ (u16)led_ctl);
+ }
}
return status;
restore_config:
- status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, led_ctl);
+ if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+ status =
+ i40e_aq_set_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
+ I40E_PHY_COM_REG_PAGE,
+ I40E_PHY_LED_PROV_REG_1,
+ led_ctl, NULL);
+ } else {
+ status =
+ i40e_write_phy_register_clause45(hw,
+ I40E_PHY_COM_REG_PAGE,
+ led_addr, phy_addr,
+ (u16)led_ctl);
+ }
return status;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index fd4bbdd..78fda11 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -598,6 +598,7 @@ struct i40e_hw {
struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */
#define I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE BIT_ULL(0)
+#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE BIT_ULL(2)
u64 flags;
/* debug mask */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
index 2ea919d..412a32c 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
@@ -556,6 +556,8 @@ struct i40e_hw {
/* LLDP/DCBX Status */
u16 dcbx_status;
+#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE BIT_ULL(2)
+
/* DCBX info */
struct i40e_dcbx_config local_dcbx_config; /* Oper/Local Cfg */
struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 02/12] i40e: Fix reporting of supported link modes
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-07 17:18 ` Shannon Nelson
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 03/12] i40e: Add support for 'ethtool -m' Alice Michael
` (11 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Filip Sadowski <filip.sadowski@intel.com>
This patch fixes incorrect reporting of supported link modes on some NICs.
Signed-off-by: Filip Sadowski <filip.sadowski@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 20 ++++++++++++++++++--
drivers/net/ethernet/intel/i40e/i40e_common.c | 8 +++++++-
drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 20 ++++++++++++++++++--
3 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
index e2a9ec8..5d0291c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
@@ -1734,6 +1734,8 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_10GBASE_CR1_CU = 0xB,
I40E_PHY_TYPE_10GBASE_AOC = 0xC,
I40E_PHY_TYPE_40GBASE_AOC = 0xD,
+ I40E_PHY_TYPE_UNRECOGNIZED = 0xE,
+ I40E_PHY_TYPE_UNSUPPORTED = 0xF,
I40E_PHY_TYPE_100BASE_TX = 0x11,
I40E_PHY_TYPE_1000BASE_T = 0x12,
I40E_PHY_TYPE_10GBASE_T = 0x13,
@@ -1752,6 +1754,8 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_25GBASE_CR = 0x20,
I40E_PHY_TYPE_25GBASE_SR = 0x21,
I40E_PHY_TYPE_25GBASE_LR = 0x22,
+ I40E_PHY_TYPE_EMPTY = 0xFE,
+ I40E_PHY_TYPE_DEFAULT = 0xFF,
I40E_PHY_TYPE_MAX
};
@@ -1942,19 +1946,31 @@ struct i40e_aqc_get_link_status {
#define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
#define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
+/* Since firmware API 1.7 loopback field keeps power class info as well */
+#define I40E_AQ_LOOPBACK_MASK 0x07
+#define I40E_AQ_PWR_CLASS_SHIFT_LB 6
+#define I40E_AQ_PWR_CLASS_MASK_LB (0x03 << I40E_AQ_PWR_CLASS_SHIFT_LB)
__le16 max_frame_size;
u8 config;
#define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
#define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
#define I40E_AQ_CONFIG_CRC_ENA 0x04
#define I40E_AQ_CONFIG_PACING_MASK 0x78
- u8 power_desc;
+ union {
+ struct {
+ u8 power_desc;
#define I40E_AQ_LINK_POWER_CLASS_1 0x00
#define I40E_AQ_LINK_POWER_CLASS_2 0x01
#define I40E_AQ_LINK_POWER_CLASS_3 0x02
#define I40E_AQ_LINK_POWER_CLASS_4 0x03
#define I40E_AQ_PWR_CLASS_MASK 0x03
- u8 reserved[4];
+ u8 reserved[4];
+ };
+ struct {
+ u8 link_type[4];
+ u8 link_type_ext;
+ };
+ };
};
I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index e9f30b8..c0aeda7 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -1826,7 +1826,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
hw_link_info->fec_info = resp->config & (I40E_AQ_CONFIG_FEC_KR_ENA |
I40E_AQ_CONFIG_FEC_RS_ENA);
hw_link_info->ext_info = resp->ext_info;
- hw_link_info->loopback = resp->loopback;
+ hw_link_info->loopback = resp->loopback & I40E_AQ_LOOPBACK_MASK;
hw_link_info->max_frame_size = le16_to_cpu(resp->max_frame_size);
hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK;
@@ -1857,6 +1857,12 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU;
+ if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
+ hw->aq.api_min_ver >= 7) {
+ hw->phy.phy_types = le32_to_cpu(*(__le32 *)resp->link_type);
+ hw->phy.phy_types |= ((u64)resp->link_type_ext << 32);
+ }
+
/* save link status information */
if (link)
*link = *hw_link_info;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
index f9f48d1..709d114 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
@@ -1730,6 +1730,8 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_10GBASE_CR1_CU = 0xB,
I40E_PHY_TYPE_10GBASE_AOC = 0xC,
I40E_PHY_TYPE_40GBASE_AOC = 0xD,
+ I40E_PHY_TYPE_UNRECOGNIZED = 0xE,
+ I40E_PHY_TYPE_UNSUPPORTED = 0xF,
I40E_PHY_TYPE_100BASE_TX = 0x11,
I40E_PHY_TYPE_1000BASE_T = 0x12,
I40E_PHY_TYPE_10GBASE_T = 0x13,
@@ -1748,6 +1750,8 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_25GBASE_CR = 0x20,
I40E_PHY_TYPE_25GBASE_SR = 0x21,
I40E_PHY_TYPE_25GBASE_LR = 0x22,
+ I40E_PHY_TYPE_EMPTY = 0xFE,
+ I40E_PHY_TYPE_DEFAULT = 0xFF,
I40E_PHY_TYPE_MAX
};
@@ -1938,19 +1942,31 @@ struct i40e_aqc_get_link_status {
#define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
#define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
+/* Since firmware API 1.7 loopback field keeps power class info as well */
+#define I40E_AQ_LOOPBACK_MASK 0x07
+#define I40E_AQ_PWR_CLASS_SHIFT_LB 6
+#define I40E_AQ_PWR_CLASS_MASK_LB (0x03 << I40E_AQ_PWR_CLASS_SHIFT_LB)
__le16 max_frame_size;
u8 config;
#define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
#define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
#define I40E_AQ_CONFIG_CRC_ENA 0x04
#define I40E_AQ_CONFIG_PACING_MASK 0x78
- u8 power_desc;
+ union {
+ struct {
+ u8 power_desc;
#define I40E_AQ_LINK_POWER_CLASS_1 0x00
#define I40E_AQ_LINK_POWER_CLASS_2 0x01
#define I40E_AQ_LINK_POWER_CLASS_3 0x02
#define I40E_AQ_LINK_POWER_CLASS_4 0x03
#define I40E_AQ_PWR_CLASS_MASK 0x03
- u8 reserved[4];
+ u8 reserved[4];
+ };
+ struct {
+ u8 link_type[4];
+ u8 link_type_ext;
+ };
+ };
};
I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 03/12] i40e: Add support for 'ethtool -m'
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 02/12] i40e: Fix reporting of supported link modes Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-07 17:19 ` Shannon Nelson
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 04/12] i40e: don't hold spinlock while resetting VF Alice Michael
` (10 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Filip Sadowski <filip.sadowski@intel.com>
This patch adds support for 'ethtool -m' command which displays
information about (Q)SFP+ module plugged into NIC's cage.
Signed-off-by: Filip Sadowski <filip.sadowski@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 18 +++
drivers/net/ethernet/intel/i40e/i40e_common.c | 69 +++++++++
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 154 +++++++++++++++++++++
drivers/net/ethernet/intel/i40e/i40e_prototype.h | 9 ++
drivers/net/ethernet/intel/i40e/i40e_type.h | 12 ++
.../net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 18 +++
drivers/net/ethernet/intel/i40evf/i40e_common.c | 69 +++++++++
drivers/net/ethernet/intel/i40evf/i40e_prototype.h | 9 ++
drivers/net/ethernet/intel/i40evf/i40e_type.h | 12 ++
9 files changed, 370 insertions(+)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
index 5d0291c..8fcbbd8 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
@@ -244,6 +244,8 @@ enum i40e_admin_queue_opc {
i40e_aqc_opc_set_phy_debug = 0x0622,
i40e_aqc_opc_upload_ext_phy_fm = 0x0625,
i40e_aqc_opc_run_phy_activity = 0x0626,
+ i40e_aqc_opc_set_phy_register = 0x0628,
+ i40e_aqc_opc_get_phy_register = 0x0629,
/* NVM commands */
i40e_aqc_opc_nvm_read = 0x0701,
@@ -2053,6 +2055,22 @@ struct i40e_aqc_run_phy_activity {
I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity);
+/* Set PHY Register command (0x0628) */
+/* Get PHY Register command (0x0629) */
+struct i40e_aqc_phy_register_access {
+ u8 phy_interface;
+#define I40E_AQ_PHY_REG_ACCESS_INTERNAL 0
+#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL 1
+#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE 2
+ u8 dev_address;
+ u8 reserved1[2];
+ u32 reg_address;
+ u32 reg_value;
+ u8 reserved2[4];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_phy_register_access);
+
/* NVM Read command (indirect 0x0701)
* NVM Erase commands (direct 0x0702)
* NVM Update commands (indirect 0x0703)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index c0aeda7..6b7712c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -5143,6 +5143,75 @@ void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val)
}
/**
+ * i40e_aq_set_phy_register
+ * @hw: pointer to the hw struct
+ * @phy_select: select which phy should be accessed
+ * @dev_addr: PHY device address
+ * @reg_addr: PHY register address
+ * @reg_val: new register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Write the external PHY register.
+ **/
+i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw,
+ u8 phy_select, u8 dev_addr,
+ u32 reg_addr, u32 reg_val,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_phy_register_access *cmd =
+ (struct i40e_aqc_phy_register_access *)&desc.params.raw;
+ i40e_status status;
+
+ i40e_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_set_phy_register);
+
+ cmd->phy_interface = phy_select;
+ cmd->dev_address = dev_addr;
+ cmd->reg_address = reg_addr;
+ cmd->reg_value = reg_val;
+
+ status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+ return status;
+}
+
+/**
+ * i40e_aq_get_phy_register
+ * @hw: pointer to the hw struct
+ * @phy_select: select which phy should be accessed
+ * @dev_addr: PHY device address
+ * @reg_addr: PHY register address
+ * @reg_val: read register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Read the external PHY register.
+ **/
+i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw,
+ u8 phy_select, u8 dev_addr,
+ u32 reg_addr, u32 *reg_val,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_phy_register_access *cmd =
+ (struct i40e_aqc_phy_register_access *)&desc.params.raw;
+ i40e_status status;
+
+ i40e_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_get_phy_register);
+
+ cmd->phy_interface = phy_select;
+ cmd->dev_address = dev_addr;
+ cmd->reg_address = reg_addr;
+
+ status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+ if (!status)
+ *reg_val = cmd->reg_value;
+
+ return status;
+}
+
+/**
* i40e_aq_write_ppp - Write pipeline personalization profile (ppp)
* @hw: pointer to the hw struct
* @buff: command buffer (size in bytes = buff_size)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 326fc18..72910c5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -4202,6 +4202,158 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
return 0;
}
+/**
+ * i40e_get_module_info - get (Q)SFP+ module type info
+ * @netdev: network interface device structure
+ * @modinfo: module EEPROM size and layout information structure
+ **/
+static int i40e_get_module_info(struct net_device *netdev,
+ struct ethtool_modinfo *modinfo)
+{
+ i40e_status status;
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_pf *pf = vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ u32 sff8472_comp = 0;
+ u32 sff8472_swap = 0;
+ u32 sff8636_rev = 0;
+ u32 type = 0;
+
+ /* Check if firmware supports reading module EEPROM. */
+ if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
+ netdev_err(vsi->netdev, "Module EEPROM memory read not supported. Please update the NVM image.\n");
+ return -EINVAL;
+ }
+
+ status = i40e_update_link_info(hw);
+ if (status)
+ return -EIO;
+
+ if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
+ netdev_err(vsi->netdev, "Cannot read module EEPROM memory. No module connected.\n");
+ return -EINVAL;
+ }
+
+ type = hw->phy.link_info.module_type[0];
+
+ switch (type) {
+ case I40E_MODULE_TYPE_SFP:
+ status = i40e_aq_get_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+ I40E_I2C_EEPROM_DEV_ADDR,
+ I40E_MODULE_SFF_8472_COMP,
+ &sff8472_comp, NULL);
+ if (status)
+ return -EIO;
+
+ status = i40e_aq_get_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+ I40E_I2C_EEPROM_DEV_ADDR,
+ I40E_MODULE_SFF_8472_SWAP,
+ &sff8472_swap, NULL);
+ if (status)
+ return -EIO;
+
+ /* Check if the module requires address swap to access
+ * the other EEPROM memory page.
+ */
+ if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
+ netdev_warn(vsi->netdev, "Module address swap to access page 0xA2 is not supported.\n");
+ modinfo->type = ETH_MODULE_SFF_8079;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+ } else if (sff8472_comp == 0x00) {
+ /* Module is not SFF-8472 compliant */
+ modinfo->type = ETH_MODULE_SFF_8079;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+ } else {
+ modinfo->type = ETH_MODULE_SFF_8472;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+ }
+ break;
+ case I40E_MODULE_TYPE_QSFP_PLUS:
+ /* Read from memory page 0. */
+ status = i40e_aq_get_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+ 0,
+ I40E_MODULE_REVISION_ADDR,
+ &sff8636_rev, NULL);
+ if (status)
+ return -EIO;
+ /* Determine revision compliance byte */
+ if (sff8636_rev > 0x02) {
+ /* Module is SFF-8636 compliant */
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+ } else {
+ modinfo->type = ETH_MODULE_SFF_8436;
+ modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+ }
+ break;
+ case I40E_MODULE_TYPE_QSFP28:
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+ break;
+ default:
+ netdev_err(vsi->netdev, "Module type unrecognized\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/**
+ * i40e_get_module_eeprom - fills buffer with (Q)SFP+ module memory contents
+ * @netdev: network interface device structure
+ * @ee: EEPROM dump request structure
+ * @data: buffer to be filled with EEPROM contents
+ **/
+static int i40e_get_module_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *ee,
+ u8 *data)
+{
+ i40e_status status;
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_pf *pf = vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ bool is_sfp = false;
+ u32 value = 0;
+ int i;
+
+ if (!ee || !ee->len || !data)
+ return -EINVAL;
+
+ if (hw->phy.link_info.module_type[0] == I40E_MODULE_TYPE_SFP)
+ is_sfp = true;
+
+ for (i = 0; i < ee->len; i++) {
+ u32 offset = i + ee->offset;
+ u32 addr = is_sfp ? I40E_I2C_EEPROM_DEV_ADDR : 0;
+
+ /* Check if we need to access the other memory page */
+ if (is_sfp) {
+ if (offset >= ETH_MODULE_SFF_8079_LEN) {
+ offset -= ETH_MODULE_SFF_8079_LEN;
+ addr = I40E_I2C_EEPROM_DEV_ADDR2;
+ }
+ } else {
+ while (offset >= ETH_MODULE_SFF_8436_LEN) {
+ /* Compute memory page number and offset. */
+ offset -= ETH_MODULE_SFF_8436_LEN / 2;
+ addr++;
+ }
+ }
+
+ status = i40e_aq_get_phy_register(hw,
+ I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+ addr, offset, &value, NULL);
+ if (status)
+ return -EIO;
+ data[i] = value;
+ }
+ return 0;
+}
+
static const struct ethtool_ops i40e_ethtool_ops = {
.get_drvinfo = i40e_get_drvinfo,
.get_regs_len = i40e_get_regs_len,
@@ -4234,6 +4386,8 @@ static const struct ethtool_ops i40e_ethtool_ops = {
.set_rxfh = i40e_set_rxfh,
.get_channels = i40e_get_channels,
.set_channels = i40e_set_channels,
+ .get_module_info = i40e_get_module_info,
+ .get_module_eeprom = i40e_get_module_eeprom,
.get_ts_info = i40e_get_ts_info,
.get_priv_flags = i40e_get_priv_flags,
.set_priv_flags = i40e_set_priv_flags,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
index df613ea..6254ad5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
@@ -362,6 +362,15 @@ i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw,
u32 reg_addr, u32 reg_val,
struct i40e_asq_cmd_details *cmd_details);
void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
+i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw,
+ u8 phy_select, u8 dev_addr,
+ u32 reg_addr, u32 reg_val,
+ struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw,
+ u8 phy_select, u8 dev_addr,
+ u32 reg_addr, u32 *reg_val,
+ struct i40e_asq_cmd_details *cmd_details);
+
i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
u16 reg, u8 phy_addr, u16 *value);
i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index 78fda11..8b0b9f8 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -428,6 +428,18 @@ struct i40e_nvm_access {
u8 data[1];
};
+/* (Q)SFP module access definitions */
+#define I40E_I2C_EEPROM_DEV_ADDR 0xA0
+#define I40E_I2C_EEPROM_DEV_ADDR2 0xA2
+#define I40E_MODULE_TYPE_ADDR 0x00
+#define I40E_MODULE_REVISION_ADDR 0x01
+#define I40E_MODULE_SFF_8472_COMP 0x5E
+#define I40E_MODULE_SFF_8472_SWAP 0x5C
+#define I40E_MODULE_SFF_ADDR_MODE 0x04
+#define I40E_MODULE_TYPE_QSFP_PLUS 0x0D
+#define I40E_MODULE_TYPE_QSFP28 0x11
+#define I40E_MODULE_QSFP_MAX_LEN 640
+
/* PCI bus types */
enum i40e_bus_type {
i40e_bus_type_unknown = 0,
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
index 709d114..b7715d4 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
@@ -244,6 +244,8 @@ enum i40e_admin_queue_opc {
i40e_aqc_opc_set_phy_debug = 0x0622,
i40e_aqc_opc_upload_ext_phy_fm = 0x0625,
i40e_aqc_opc_run_phy_activity = 0x0626,
+ i40e_aqc_opc_set_phy_register = 0x0628,
+ i40e_aqc_opc_get_phy_register = 0x0629,
/* NVM commands */
i40e_aqc_opc_nvm_read = 0x0701,
@@ -2046,6 +2048,22 @@ struct i40e_aqc_run_phy_activity {
I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity);
+/* Set PHY Register command (0x0628) */
+/* Get PHY Register command (0x0629) */
+struct i40e_aqc_phy_register_access {
+ u8 phy_interface;
+#define I40E_AQ_PHY_REG_ACCESS_INTERNAL 0
+#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL 1
+#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE 2
+ u8 dev_address;
+ u8 reserved1[2];
+ u32 reg_address;
+ u32 reg_value;
+ u8 reserved2[4];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_phy_register_access);
+
/* NVM Read command (indirect 0x0701)
* NVM Erase commands (direct 0x0702)
* NVM Update commands (indirect 0x0703)
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c
index 8d3a2bf..7df4610 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c
@@ -1042,6 +1042,75 @@ void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val)
}
/**
+ * i40evf_aq_set_phy_register
+ * @hw: pointer to the hw struct
+ * @phy_select: select which phy should be accessed
+ * @dev_addr: PHY device address
+ * @reg_addr: PHY register address
+ * @reg_val: new register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Reset the external PHY.
+ **/
+i40e_status i40evf_aq_set_phy_register(struct i40e_hw *hw,
+ u8 phy_select, u8 dev_addr,
+ u32 reg_addr, u32 reg_val,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_phy_register_access *cmd =
+ (struct i40e_aqc_phy_register_access *)&desc.params.raw;
+ i40e_status status;
+
+ i40evf_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_set_phy_register);
+
+ cmd->phy_interface = phy_select;
+ cmd->dev_address = dev_addr;
+ cmd->reg_address = reg_addr;
+ cmd->reg_value = reg_val;
+
+ status = i40evf_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+ return status;
+}
+
+/**
+ * i40evf_aq_get_phy_register
+ * @hw: pointer to the hw struct
+ * @phy_select: select which phy should be accessed
+ * @dev_addr: PHY device address
+ * @reg_addr: PHY register address
+ * @reg_val: read register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Reset the external PHY.
+ **/
+i40e_status i40evf_aq_get_phy_register(struct i40e_hw *hw,
+ u8 phy_select, u8 dev_addr,
+ u32 reg_addr, u32 *reg_val,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_phy_register_access *cmd =
+ (struct i40e_aqc_phy_register_access *)&desc.params.raw;
+ i40e_status status;
+
+ i40evf_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_get_phy_register);
+
+ cmd->phy_interface = phy_select;
+ cmd->dev_address = dev_addr;
+ cmd->reg_address = reg_addr;
+
+ status = i40evf_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+ if (!status)
+ *reg_val = cmd->reg_value;
+
+ return status;
+}
+
+/**
* i40e_aq_send_msg_to_pf
* @hw: pointer to the hardware structure
* @v_opcode: opcodes for VF-PF communication
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
index c9836bb..b624b59 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
@@ -111,6 +111,15 @@ i40e_status i40evf_aq_rx_ctl_write_register(struct i40e_hw *hw,
u32 reg_addr, u32 reg_val,
struct i40e_asq_cmd_details *cmd_details);
void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
+i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw,
+ u8 phy_select, u8 dev_addr,
+ u32 reg_addr, u32 reg_val,
+ struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw,
+ u8 phy_select, u8 dev_addr,
+ u32 reg_addr, u32 *reg_val,
+ struct i40e_asq_cmd_details *cmd_details);
+
i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,
u16 reg, u8 phy_addr, u16 *value);
i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
index 412a32c..48eacf5 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
@@ -401,6 +401,18 @@ struct i40e_nvm_access {
u8 data[1];
};
+/* (Q)SFP module access definitions */
+#define I40E_I2C_EEPROM_DEV_ADDR 0xA0
+#define I40E_I2C_EEPROM_DEV_ADDR2 0xA2
+#define I40E_MODULE_TYPE_ADDR 0x00
+#define I40E_MODULE_REVISION_ADDR 0x01
+#define I40E_MODULE_SFF_8472_COMP 0x5E
+#define I40E_MODULE_SFF_8472_SWAP 0x5C
+#define I40E_MODULE_SFF_ADDR_MODE 0x04
+#define I40E_MODULE_TYPE_QSFP_PLUS 0x0D
+#define I40E_MODULE_TYPE_QSFP28 0x11
+#define I40E_MODULE_QSFP_MAX_LEN 640
+
/* PCI bus types */
enum i40e_bus_type {
i40e_bus_type_unknown = 0,
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 04/12] i40e: don't hold spinlock while resetting VF
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 02/12] i40e: Fix reporting of supported link modes Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 03/12] i40e: Add support for 'ethtool -m' Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 05/12] i40e: drop i40e_pf *pf from i40e_vc_disable_vf() Alice Michael
` (9 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Jacob Keller <jacob.e.keller@intel.com>
When we refactored handling of the PVID in commit 9af52f60b2d9
("i40e: use (add|rm)_vlan_all_mac helper functions when changing PVID")
we introduced a scheduling while atomic regression.
This occurred because we now held the spinlock across a call to
i40e_reset_vf(), which results in a usleep_range() call that triggers
a scheduling while atomic bug. This was rare as it only occurred if the
user configured a VLAN on a VF and also attempted to reconfigure the VF
from the host system with a port VLAN.
We do need to hold the lock while calling i40e_is_vsi_in_vlan(), but we
should not be holding it while we reset the VF.
We'll fix this by introducing a separate helper function
i40e_vsi_has_vlans which checks whether we have a PVID and whether the
VSI has configured VLANs. This helper function will manage its own need
for the mac_filter_hash_lock.
Then, we can move the acquiring of the spinlock until after we reset the
VF, which ensures that we do not sleep while holding the lock.
Using a separate function like this makes the code more clear and is
easier to read than attempting to release and re-acquire the spinlock
when we reset the VF.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 36 +++++++++++++++++++---
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index f78aa7e..fd85dd8 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -2922,6 +2922,34 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
}
/**
+ * i40e_vsi_has_vlans - True if VSI has configured VLANs
+ * @vsi: pointer to the vsi
+ *
+ * Check if a VSI has configured any VLANs. False if we have a port VLAN or if
+ * we have no configured VLANs. Do not call while holding the
+ * mac_filter_hash_lock.
+ */
+static bool i40e_vsi_has_vlans(struct i40e_vsi *vsi)
+{
+ bool have_vlans;
+
+ /* If we have a port VLAN, then the VSI cannot have any VLANs
+ * configured, as all MAC/VLAN filters will be assigned to the PVID.
+ */
+ if (vsi->info.pvid)
+ return false;
+
+ /* Since we don't have a PVID, we know that if the device is in VLAN
+ * mode it must be because of a VLAN filter configured on this VSI.
+ */
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ have_vlans = i40e_is_vsi_in_vlan(vsi);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+ return have_vlans;
+}
+
+/**
* i40e_ndo_set_vf_port_vlan
* @netdev: network interface device structure
* @vf_id: VF identifier
@@ -2973,10 +3001,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
/* duplicate request, so just return success */
goto error_pvid;
- /* Locked once because multiple functions below iterate list */
- spin_lock_bh(&vsi->mac_filter_hash_lock);
-
- if (le16_to_cpu(vsi->info.pvid) == 0 && i40e_is_vsi_in_vlan(vsi)) {
+ if (i40e_vsi_has_vlans(vsi)) {
dev_err(&pf->pdev->dev,
"VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n",
vf_id);
@@ -2989,6 +3014,9 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
vsi = pf->vsi[vf->lan_vsi_idx];
}
+ /* Locked once because multiple functions below iterate list */
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+
/* Check for condition where there was already a port VLAN ID
* filter set and now it is being deleted by setting it to zero.
* Additionally check for the condition where there was a port
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 05/12] i40e: drop i40e_pf *pf from i40e_vc_disable_vf()
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
` (2 preceding siblings ...)
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 04/12] i40e: don't hold spinlock while resetting VF Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 06/12] i40e: make use of i40e_vc_disable_vf Alice Michael
` (8 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Jacob Keller <jacob.e.keller@intel.com>
It's never used, and the vf structure could get back to the PF if
necessary. Lets just drop the extra unneeded parameter.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index fd85dd8..2adcc7f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -154,12 +154,11 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
/**
* i40e_vc_disable_vf
- * @pf: pointer to the PF info
* @vf: pointer to the VF info
*
* Disable the VF through a SW reset
**/
-static inline void i40e_vc_disable_vf(struct i40e_pf *pf, struct i40e_vf *vf)
+static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
{
i40e_vc_notify_vf_reset(vf);
i40e_reset_vf(vf, false);
@@ -2914,7 +2913,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
}
/* Force the VF driver stop so it has to reload with new MAC address */
- i40e_vc_disable_vf(pf, vf);
+ i40e_vc_disable_vf(vf);
dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n");
error_param:
@@ -3009,7 +3008,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
* the right thing by reconfiguring his network correctly
* and then reloading the VF driver.
*/
- i40e_vc_disable_vf(pf, vf);
+ i40e_vc_disable_vf(vf);
/* During reset the VF got a new VSI, so refresh the pointer. */
vsi = pf->vsi[vf->lan_vsi_idx];
}
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 06/12] i40e: make use of i40e_vc_disable_vf
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
` (3 preceding siblings ...)
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 05/12] i40e: drop i40e_pf *pf from i40e_vc_disable_vf() Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 07/12] i40e: ensure reset occurs when disabling VF Alice Michael
` (7 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Jacob Keller <jacob.e.keller@intel.com>
Replace i40e_vc_notify_vf_reset and i40e_reset_vf with a call to
i40e_vc_disable_vf which does this exact thing. This matches similar
code patterns throughout the driver.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 2adcc7f..c9898cb 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -3345,8 +3345,7 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting)
goto out;
vf->trusted = setting;
- i40e_vc_notify_vf_reset(vf);
- i40e_reset_vf(vf, false);
+ i40e_vc_disable_vf(vf);
dev_info(&pf->pdev->dev, "VF %u is now %strusted\n",
vf_id, setting ? "" : "un");
out:
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 07/12] i40e: ensure reset occurs when disabling VF
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
` (4 preceding siblings ...)
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 06/12] i40e: make use of i40e_vc_disable_vf Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 08/12] i40evf: Enable VF to request an alternate queue allocation Alice Michael
` (6 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Jacob Keller <jacob.e.keller@intel.com>
It is possible although rare that we may not reset when
i40e_vc_disable_vf() is called. This can lead to some weird
circumstances with some values not being properly set. Modify
i40e_reset_vf() to return a code indicating whether it reset or not.
Now, i40e_vc_disable_vf() can wait until a reset actually occurs. If it
fails to free up within a reasonable timeframe we'll display a warning
message.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 42 +++++++++++++++++-----
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 4 +--
2 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index c9898cb..c7f1819 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -156,12 +156,28 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
* i40e_vc_disable_vf
* @vf: pointer to the VF info
*
- * Disable the VF through a SW reset
+ * Disable the VF through a SW reset.
**/
static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
{
+ int i;
+
i40e_vc_notify_vf_reset(vf);
- i40e_reset_vf(vf, false);
+
+ /* We want to ensure that an actual reset occurs initiated after this
+ * function was called. However, we do not want to wait forever, so
+ * we'll give a reasonable time and print a message if we failed to
+ * ensure a reset.
+ */
+ for (i = 0; i < 20; i++) {
+ if (i40e_reset_vf(vf, false))
+ return;
+ usleep_range(10000, 20000);
+ }
+
+ dev_warn(&vf->pf->pdev->dev,
+ "Failed to initiate reset for VF %d after 200 milliseconds\n",
+ vf->vf_id);
}
/**
@@ -1048,9 +1064,9 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf)
* @vf: pointer to the VF structure
* @flr: VFLR was issued or not
*
- * reset the VF
+ * Returns true if the VF is reset, false otherwise.
**/
-void i40e_reset_vf(struct i40e_vf *vf, bool flr)
+bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
{
struct i40e_pf *pf = vf->pf;
struct i40e_hw *hw = &pf->hw;
@@ -1058,9 +1074,11 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
u32 reg;
int i;
- /* If VFs have been disabled, there is no need to reset */
+ /* If the VFs have been disabled, this means something else is
+ * resetting the VF, so we shouldn't continue.
+ */
if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
- return;
+ return false;
i40e_trigger_vf_reset(vf, flr);
@@ -1097,6 +1115,8 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
i40e_flush(hw);
clear_bit(__I40E_VF_DISABLE, pf->state);
+
+ return true;
}
/**
@@ -1108,8 +1128,10 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
* VF, then do all the waiting in one chunk, and finally finish restoring each
* VF after the wait. This is useful during PF routines which need to reset
* all VFs, as otherwise it must perform these resets in a serialized fashion.
+ *
+ * Returns true if any VFs were reset, and false otherwise.
**/
-void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
+bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
{
struct i40e_hw *hw = &pf->hw;
struct i40e_vf *vf;
@@ -1118,11 +1140,11 @@ void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
/* If we don't have any VFs, then there is nothing to reset */
if (!pf->num_alloc_vfs)
- return;
+ return false;
/* If VFs have been disabled, there is no need to reset */
if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
- return;
+ return false;
/* Begin reset on all VFs at once */
for (v = 0; v < pf->num_alloc_vfs; v++)
@@ -1197,6 +1219,8 @@ void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
i40e_flush(hw);
clear_bit(__I40E_VF_DISABLE, pf->state);
+
+ return true;
}
/**
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
index 5111d05..5ea42ad 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
@@ -122,8 +122,8 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs);
int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
u32 v_retval, u8 *msg, u16 msglen);
int i40e_vc_process_vflr_event(struct i40e_pf *pf);
-void i40e_reset_vf(struct i40e_vf *vf, bool flr);
-void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
+bool i40e_reset_vf(struct i40e_vf *vf, bool flr);
+bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
void i40e_vc_notify_vf_reset(struct i40e_vf *vf);
/* VF configuration related iplink handlers */
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 08/12] i40evf: Enable VF to request an alternate queue allocation
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
` (5 preceding siblings ...)
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 07/12] i40e: ensure reset occurs when disabling VF Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-07 17:19 ` Shannon Nelson
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 09/12] i40e: make i40evf_map_rings_to_vectors void Alice Michael
` (5 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Alan Brady <alan.brady@intel.com>
Currently the VF gets a default number of allocated queues from HW on
init and it could choose to enable or disable those allocated queues.
This makes it such that the VF can request more or less underlying
allocated queues from the PF.
First the VF negotiates the number of queues it wants that can be
supported by the PF and if successful asks for a reset. During reset
the PF will reallocate the HW queues for the VF and will then remap the
new queues.
Signed-off-by: Alan Brady <alan.brady@intel.com>
---
drivers/net/ethernet/intel/i40evf/i40evf.h | 4 +
drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 38 ++++++++-
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 94 ++++++++++++++++++++--
.../net/ethernet/intel/i40evf/i40evf_virtchnl.c | 44 +++++++++-
4 files changed, 173 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h
index a1af9b1..de0af52 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf.h
+++ b/drivers/net/ethernet/intel/i40evf/i40evf.h
@@ -102,6 +102,7 @@ struct i40e_vsi {
#define I40E_TX_CTXTDESC(R, i) \
(&(((struct i40e_tx_context_desc *)((R)->desc))[i]))
#define MAX_QUEUES 16
+#define I40EVF_MAX_REQ_QUEUES 4
#define I40EVF_HKEY_ARRAY_SIZE ((I40E_VFQF_HKEY_MAX_INDEX + 1) * 4)
#define I40EVF_HLUT_ARRAY_SIZE ((I40E_VFQF_HLUT_MAX_INDEX + 1) * 4)
@@ -200,6 +201,7 @@ struct i40evf_adapter {
struct list_head vlan_filter_list;
char misc_vector_name[IFNAMSIZ + 9];
int num_active_queues;
+ int num_req_queues;
/* TX */
struct i40e_ring *tx_rings;
@@ -235,6 +237,7 @@ struct i40evf_adapter {
#define I40EVF_FLAG_PROMISC_ON BIT(13)
#define I40EVF_FLAG_ALLMULTI_ON BIT(14)
#define I40EVF_FLAG_LEGACY_RX BIT(15)
+#define I40EVF_FLAG_REINIT_ITR_NEEDED BIT(16)
/* duplicates for common code */
#define I40E_FLAG_DCB_ENABLED 0
#define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED
@@ -349,6 +352,7 @@ void i40evf_deconfigure_queues(struct i40evf_adapter *adapter);
void i40evf_enable_queues(struct i40evf_adapter *adapter);
void i40evf_disable_queues(struct i40evf_adapter *adapter);
void i40evf_map_queues(struct i40evf_adapter *adapter);
+int i40evf_request_queues(struct i40evf_adapter *adapter, int num);
void i40evf_add_ether_addrs(struct i40evf_adapter *adapter);
void i40evf_del_ether_addrs(struct i40evf_adapter *adapter);
void i40evf_add_vlans(struct i40evf_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index 65874d6..da006fa 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -669,7 +669,7 @@ static void i40evf_get_channels(struct net_device *netdev,
struct i40evf_adapter *adapter = netdev_priv(netdev);
/* Report maximum channels */
- ch->max_combined = adapter->num_active_queues;
+ ch->max_combined = I40EVF_MAX_REQ_QUEUES;
ch->max_other = NONQ_VECS;
ch->other_count = NONQ_VECS;
@@ -678,6 +678,41 @@ static void i40evf_get_channels(struct net_device *netdev,
}
/**
+ * i40evf_set_channels: set the new channel count
+ * @netdev: network interface device structure
+ * @ch: channel information structure
+ *
+ * Negotiate a new number of channels with the PF then do a reset. During
+ * reset we'll realloc queues and fix the RSS table. Returns 0 on success,
+ * negative on failure.
+ **/
+static int i40evf_set_channels(struct net_device *netdev,
+ struct ethtool_channels *ch)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ int num_req = ch->combined_count;
+
+ if (num_req != adapter->num_active_queues &&
+ !(adapter->vf_res->vf_cap_flags &
+ VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)) {
+ dev_info(&adapter->pdev->dev, "PF is not capable of queue negotiation.\n");
+ return -EINVAL;
+ }
+
+ /* All of these should have already been checked by ethtool before this
+ * even gets to us, but just to be sure.
+ */
+ if (num_req <= 0 || num_req > I40EVF_MAX_REQ_QUEUES)
+ return -EINVAL;
+
+ if (ch->rx_count || ch->tx_count || ch->other_count != NONQ_VECS)
+ return -EINVAL;
+
+ adapter->num_req_queues = num_req;
+ return i40evf_request_queues(adapter, num_req);
+}
+
+/**
* i40evf_get_rxfh_key_size - get the RSS hash key size
* @netdev: network interface device structure
*
@@ -785,6 +820,7 @@ static const struct ethtool_ops i40evf_ethtool_ops = {
.get_rxfh = i40evf_get_rxfh,
.set_rxfh = i40evf_set_rxfh,
.get_channels = i40evf_get_channels,
+ .set_channels = i40evf_set_channels,
.get_rxfh_key_size = i40evf_get_rxfh_key_size,
.get_link_ksettings = i40evf_get_link_ksettings,
};
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index a216fd2..a803c6b 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -1189,9 +1189,18 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter)
{
int i, num_active_queues;
- num_active_queues = min_t(int,
- adapter->vsi_res->num_queue_pairs,
- (int)(num_online_cpus()));
+ /* If we're in reset reallocating queues we don't actually know yet for
+ * certain the PF gave us the number of queues we asked for but we'll
+ * assume it did. Once basic reset is finished we'll confirm once we
+ * start negotiating config with PF.
+ */
+ if (adapter->num_req_queues)
+ num_active_queues = adapter->num_req_queues;
+ else
+ num_active_queues = min_t(int,
+ adapter->vsi_res->num_queue_pairs,
+ (int)(num_online_cpus()));
+
adapter->tx_rings = kcalloc(num_active_queues,
sizeof(struct i40e_ring), GFP_KERNEL);
@@ -1540,6 +1549,48 @@ static void i40evf_free_rss(struct i40evf_adapter *adapter)
}
/**
+ * i40evf_reinit_interrupt_scheme - Reallocate queues and vectors
+ * @adapter: board private structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int i40evf_reinit_interrupt_scheme(struct i40evf_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err;
+
+ if (netif_running(netdev))
+ i40evf_free_traffic_irqs(adapter);
+ i40evf_free_misc_irq(adapter);
+ i40evf_reset_interrupt_capability(adapter);
+ i40evf_free_q_vectors(adapter);
+ i40evf_free_queues(adapter);
+
+ err = i40evf_init_interrupt_scheme(adapter);
+ if (err)
+ goto err;
+
+ netif_tx_stop_all_queues(netdev);
+
+ err = i40evf_request_misc_irq(adapter);
+ if (err)
+ goto err;
+
+ set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
+
+ err = i40evf_map_rings_to_vectors(adapter);
+ if (err)
+ goto err;
+
+ if (RSS_AQ(adapter))
+ adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_RSS;
+ else
+ err = i40evf_init_rss(adapter);
+err:
+ return err;
+}
+
+/**
* i40evf_watchdog_timer - Periodic call-back timer
* @data: pointer to adapter disguised as unsigned long
**/
@@ -1885,8 +1936,15 @@ static void i40evf_reset_task(struct work_struct *work)
if (err)
dev_info(&adapter->pdev->dev, "Failed to init adminq: %d\n",
err);
+ adapter->aq_required = 0;
- adapter->aq_required = I40EVF_FLAG_AQ_GET_CONFIG;
+ if (adapter->flags & I40EVF_FLAG_REINIT_ITR_NEEDED) {
+ err = i40evf_reinit_interrupt_scheme(adapter);
+ if (err)
+ goto reset_err;
+ }
+
+ adapter->aq_required |= I40EVF_FLAG_AQ_GET_CONFIG;
adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
/* re-add all MAC filters */
@@ -1916,6 +1974,15 @@ static void i40evf_reset_task(struct work_struct *work)
if (err)
goto reset_err;
+ if (adapter->flags & I40EVF_FLAG_REINIT_ITR_NEEDED) {
+ err = i40evf_request_traffic_irqs(adapter,
+ netdev->name);
+ if (err)
+ goto reset_err;
+
+ adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
+ }
+
i40evf_configure(adapter);
i40evf_up_complete(adapter);
@@ -2432,9 +2499,9 @@ static int i40evf_check_reset_complete(struct i40e_hw *hw)
int i40evf_process_config(struct i40evf_adapter *adapter)
{
struct virtchnl_vf_resource *vfres = adapter->vf_res;
+ int i, num_req_queues = adapter->num_req_queues;
struct net_device *netdev = adapter->netdev;
struct i40e_vsi *vsi = &adapter->vsi;
- int i;
netdev_features_t hw_enc_features;
netdev_features_t hw_features;
@@ -2448,6 +2515,23 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
return -ENODEV;
}
+ if (num_req_queues &&
+ num_req_queues != adapter->vsi_res->num_queue_pairs) {
+ /* Problem. The PF gave us fewer queues than what we had
+ * negotiated in our request. Need a reset to see if we can't
+ * get back to a working state.
+ */
+ dev_err(&adapter->pdev->dev,
+ "Requested %d queues, but PF only gave us %d.\n",
+ num_req_queues,
+ adapter->vsi_res->num_queue_pairs);
+ adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
+ adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
+ i40evf_schedule_reset(adapter);
+ return -ENODEV;
+ }
+ adapter->num_req_queues = 0;
+
hw_enc_features = NETIF_F_SG |
NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM |
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
index 2bb0fe0..2bb81c3 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
@@ -160,7 +160,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
VIRTCHNL_VF_OFFLOAD_WB_ON_ITR |
VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 |
VIRTCHNL_VF_OFFLOAD_ENCAP |
- VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM;
+ VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
+ VIRTCHNL_VF_OFFLOAD_REQ_QUEUES;
adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG;
@@ -385,6 +386,32 @@ void i40evf_map_queues(struct i40evf_adapter *adapter)
}
/**
+ * i40evf_request_queues
+ * @adapter: adapter structure
+ * @num: number of requested queues
+ *
+ * We get a default number of queues from the PF. This enables us to request a
+ * different number. Returns 0 on success, negative on failure
+ **/
+int i40evf_request_queues(struct i40evf_adapter *adapter, int num)
+{
+ struct virtchnl_vf_res_request vfres;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot request queues, command %d pending\n",
+ adapter->current_op);
+ return -EBUSY;
+ }
+
+ vfres.num_queue_pairs = num;
+
+ adapter->current_op = VIRTCHNL_OP_REQUEST_QUEUES;
+ return i40evf_send_pf_msg(adapter, VIRTCHNL_OP_REQUEST_QUEUES,
+ (u8 *)&vfres, sizeof(vfres));
+}
+
+/**
* i40evf_add_ether_addrs
* @adapter: adapter structure
* @addrs: the MAC address filters to add (contiguous)
@@ -1068,6 +1095,21 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
"Invalid message %d from PF\n", v_opcode);
}
break;
+ case VIRTCHNL_OP_REQUEST_QUEUES: {
+ struct virtchnl_vf_res_request *vfres =
+ (struct virtchnl_vf_res_request *)msg;
+ if (vfres->num_queue_pairs == adapter->num_req_queues) {
+ adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
+ i40evf_schedule_reset(adapter);
+ } else {
+ dev_info(&adapter->pdev->dev,
+ "Requested %d queues, PF can support %d\n",
+ adapter->num_req_queues,
+ vfres->num_queue_pairs);
+ adapter->num_req_queues = 0;
+ }
+ }
+ break;
default:
if (adapter->current_op && (v_opcode != adapter->current_op))
dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 09/12] i40e: make i40evf_map_rings_to_vectors void
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
` (6 preceding siblings ...)
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 08/12] i40evf: Enable VF to request an alternate queue allocation Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 10/12] i40e: fix handling of vf_states variable Alice Michael
` (4 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Mitch Williams <mitch.a.williams@intel.com>
This function cannot fail, so why is it returning a value? And why are
we checking it? Why shouldn't we just make it void? Why is this commit
message made up of only questions?
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
---
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index a803c6b..85e66db 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -430,12 +430,11 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)
* group the rings as "efficiently" as possible. You would add new
* mapping configurations in here.
**/
-static int i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter)
+static void i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter)
{
int rings_remaining = adapter->num_active_queues;
int ridx = 0, vidx = 0;
int q_vectors;
- int err = 0;
q_vectors = adapter->num_msix_vectors - NONQ_VECS;
@@ -451,8 +450,6 @@ static int i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter)
}
adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
-
- return err;
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1578,9 +1575,7 @@ static int i40evf_reinit_interrupt_scheme(struct i40evf_adapter *adapter)
set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
- err = i40evf_map_rings_to_vectors(adapter);
- if (err)
- goto err;
+ i40evf_map_rings_to_vectors(adapter);
if (RSS_AQ(adapter))
adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_RSS;
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 10/12] i40e: fix handling of vf_states variable
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
` (7 preceding siblings ...)
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 09/12] i40e: make i40evf_map_rings_to_vectors void Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 11/12] i40e: fix client notify of VF reset Alice Michael
` (3 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Alan Brady <alan.brady@intel.com>
Currently we inappropriately clear the vf_states variable with a null
assignment. This is problematic because we should be using atomic
bitops on this variable and we don't actually want to clear all the
flags. We should just clear the ones we know we want to clear.
Additionally remove the I40E_VF_STATE_FCOEENA bit because it is no
longer being used.
Signed-off-by: Alan Brady <alan.brady@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 5 ++++-
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 1 -
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index c7f1819..e65ecaf 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -876,7 +876,8 @@ static void i40e_free_vf_res(struct i40e_vf *vf)
}
/* reset some of the state variables keeping track of the resources */
vf->num_queue_pairs = 0;
- vf->vf_states = 0;
+ clear_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states);
+ clear_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states);
}
/**
@@ -1582,6 +1583,8 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_IWARP)) {
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_IWARP;
set_bit(I40E_VF_STATE_IWARPENA, &vf->vf_states);
+ } else {
+ clear_bit(I40E_VF_STATE_IWARPENA, &vf->vf_states);
}
if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
index 5ea42ad..5efc4f9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
@@ -56,7 +56,6 @@ enum i40e_vf_states {
I40E_VF_STATE_INIT = 0,
I40E_VF_STATE_ACTIVE,
I40E_VF_STATE_IWARPENA,
- I40E_VF_STATE_FCOEENA,
I40E_VF_STATE_DISABLED,
I40E_VF_STATE_MC_PROMISC,
I40E_VF_STATE_UC_PROMISC,
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 11/12] i40e: fix client notify of VF reset
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
` (8 preceding siblings ...)
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 10/12] i40e: fix handling of vf_states variable Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 12/12] i40e: Stop dropping 802.1ad tags (eth proto 0x88a8) Alice Michael
` (2 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Alan Brady <alan.brady@intel.com>
Currently there is a bug in which the PF driver fails to inform clients
of a VF reset which then causes clients to leak resources. The bug
exists because we were incorrectly checking the I40E_VF_STATE_PRE_ENABLE
bit.
When a VF is first init we go through a reset to initialize variables
and allocate resources but we don't want to inform clients of this first
reset since the client isn't fully enabled yet so we set a state bit
signifying we're in a "pre-enabled" client state. During the first
reset we should be clearing the bit, allowing all following resets to
notify the client of the reset when the bit is not set. This patch
fixes the issue by negating the 'test_and_clear_bit' check to accurately
reflect the behavior we want.
Signed-off-by: Alan Brady <alan.brady@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index e65ecaf..137254e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -1047,8 +1047,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf)
set_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states);
clear_bit(I40E_VF_STATE_DISABLED, &vf->vf_states);
/* Do not notify the client during VF init */
- if (test_and_clear_bit(I40E_VF_STATE_PRE_ENABLE,
- &vf->vf_states))
+ if (!test_and_clear_bit(I40E_VF_STATE_PRE_ENABLE,
+ &vf->vf_states))
i40e_notify_client_of_vf_reset(pf, abs_vf_id);
vf->num_vlan = 0;
}
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 12/12] i40e: Stop dropping 802.1ad tags (eth proto 0x88a8)
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
` (9 preceding siblings ...)
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 11/12] i40e: fix client notify of VF reset Alice Michael
@ 2017-08-04 13:52 ` Alice Michael
2017-08-06 7:02 ` [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior kbuild test robot
2017-08-07 17:18 ` Shannon Nelson
12 siblings, 0 replies; 19+ messages in thread
From: Alice Michael @ 2017-08-04 13:52 UTC (permalink / raw)
To: intel-wired-lan
From: Scott Peterson <scott.d.peterson@intel.com>
Enable i40e to pass traffic with VLAN tags using the 802.1ad ethernet
protocol ID (0x88a8).
This requires NIC firmware providing version 1.7 of the API. With
older NIC firmware 802.1ad tagged packets will continue to be dropped.
No VLAN offloads nor RSS are supported for 802.1ad VLANs.
Signed-off-by: Scott Peterson <scott.d.peterson@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_adminq.c | 6 ++++++
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 17 ++++++++++++++++-
drivers/net/ethernet/intel/i40e/i40e_common.c | 6 +++++-
drivers/net/ethernet/intel/i40e/i40e_main.c | 7 +++++++
drivers/net/ethernet/intel/i40e/i40e_type.h | 6 ++++++
drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 17 ++++++++++++++++-
drivers/net/ethernet/intel/i40evf/i40e_type.h | 6 ++++++
7 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index 340e5a2..8553f2b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -613,6 +613,12 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
}
+ /* The ability to RX (not drop) 802.1ad frames was added in API 1.7 */
+ if ((hw->aq.api_maj_ver > 1) ||
+ ((hw->aq.api_maj_ver == 1) &&
+ (hw->aq.api_min_ver >= 7)))
+ hw->flags |= I40E_HW_FLAG_802_1AD_CAPABLE;
+
if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) {
ret_code = I40E_ERR_FIRMWARE_API_VERSION;
goto init_adminq_free_arq;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
index 8fcbbd8..b59e8a7 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
@@ -775,7 +775,22 @@ struct i40e_aqc_set_switch_config {
#define I40E_AQ_SET_SWITCH_CFG_PROMISC 0x0001
#define I40E_AQ_SET_SWITCH_CFG_L2_FILTER 0x0002
__le16 valid_flags;
- u8 reserved[12];
+ /* The ethertype in switch_tag is dropped on ingress and used
+ * internally by the switch. Set this to zero for the default
+ * of 0x88a8 (802.1ad). Should be zero for firmware API
+ * versions lower than 1.7.
+ */
+ __le16 switch_tag;
+ /* The ethertypes in first_tag and second_tag are used to
+ * match the outer and inner VLAN tags (respectively) when HW
+ * double VLAN tagging is enabled via the set port parameters
+ * AQ command. Otherwise these are both ignored. Set them to
+ * zero for their defaults of 0x8100 (802.1Q). Should be zero
+ * for firmware API versions lower than 1.7.
+ */
+ __le16 first_tag;
+ __le16 second_tag;
+ u8 reserved[6];
};
I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index 6b7712c..46db282 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -2404,7 +2404,11 @@ enum i40e_status_code i40e_aq_set_switch_config(struct i40e_hw *hw,
i40e_aqc_opc_set_switch_config);
scfg->flags = cpu_to_le16(flags);
scfg->valid_flags = cpu_to_le16(valid_flags);
-
+ if (hw->flags & I40E_HW_FLAG_802_1AD_CAPABLE) {
+ scfg->switch_tag = cpu_to_le16(hw->switch_tag);
+ scfg->first_tag = cpu_to_le16(hw->first_tag);
+ scfg->second_tag = cpu_to_le16(hw->second_tag);
+ }
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
return status;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 370ce9f..17dc8e2 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -12451,6 +12451,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->bus.bus_id = pdev->bus->number;
pf->instance = pfs_found;
+ /* Select something other than the 802.1ad ethertype for the
+ * switch to use internally and drop on ingress.
+ */
+ hw->switch_tag = 0xffff;
+ hw->first_tag = ETH_P_8021AD;
+ hw->second_tag = ETH_P_8021Q;
+
INIT_LIST_HEAD(&pf->l3_flex_pit_list);
INIT_LIST_HEAD(&pf->l4_flex_pit_list);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index 8b0b9f8..4b32b1d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -610,9 +610,15 @@ struct i40e_hw {
struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */
#define I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE BIT_ULL(0)
+#define I40E_HW_FLAG_802_1AD_CAPABLE BIT_ULL(1)
#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE BIT_ULL(2)
u64 flags;
+ /* Used in set switch config AQ command */
+ u16 switch_tag;
+ u16 first_tag;
+ u16 second_tag;
+
/* debug mask */
u32 debug_mask;
char err_str[16];
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
index b7715d4..3a498d5 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
@@ -771,7 +771,22 @@ struct i40e_aqc_set_switch_config {
#define I40E_AQ_SET_SWITCH_CFG_PROMISC 0x0001
#define I40E_AQ_SET_SWITCH_CFG_L2_FILTER 0x0002
__le16 valid_flags;
- u8 reserved[12];
+ /* The ethertype in switch_tag is dropped on ingress and used
+ * internally by the switch. Set this to zero for the default
+ * of 0x88a8 (802.1ad). Should be zero for firmware API
+ * versions lower than 1.7.
+ */
+ __le16 switch_tag;
+ /* The ethertypes in first_tag and second_tag are used to
+ * match the outer and inner VLAN tags (respectively) when HW
+ * double VLAN tagging is enabled via the set port parameters
+ * AQ command. Otherwise these are both ignored. Set them to
+ * zero for their defaults of 0x8100 (802.1Q). Should be zero
+ * for firmware API versions lower than 1.7.
+ */
+ __le16 first_tag;
+ __le16 second_tag;
+ u8 reserved[6];
};
I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config);
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
index 48eacf5..9364b67 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
@@ -568,6 +568,7 @@ struct i40e_hw {
/* LLDP/DCBX Status */
u16 dcbx_status;
+#define I40E_HW_FLAG_802_1AD_CAPABLE BIT_ULL(1)
#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE BIT_ULL(2)
/* DCBX info */
@@ -575,6 +576,11 @@ struct i40e_hw {
struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */
struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */
+ /* Used in set switch config AQ command */
+ u16 switch_tag;
+ u16 first_tag;
+ u16 second_tag;
+
/* debug mask */
u32 debug_mask;
char err_str[16];
--
2.9.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
` (10 preceding siblings ...)
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 12/12] i40e: Stop dropping 802.1ad tags (eth proto 0x88a8) Alice Michael
@ 2017-08-06 7:02 ` kbuild test robot
2017-08-07 17:18 ` Shannon Nelson
12 siblings, 0 replies; 19+ messages in thread
From: kbuild test robot @ 2017-08-06 7:02 UTC (permalink / raw)
To: intel-wired-lan
Hi Mariusz,
[auto build test ERROR on jkirsher-next-queue/dev-queue]
[also build test ERROR on v4.13-rc3 next-20170804]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Alice-Michael/i40e-use-admin-queue-for-setting-LEDs-behavior/20170806-044014
base: https://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue.git dev-queue
config: x86_64-rhel (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
Note: the linux-review/Alice-Michael/i40e-use-admin-queue-for-setting-LEDs-behavior/20170806-044014 HEAD e6b14a85521c0cd2de206efff3ed84a86f94b5e2 builds fine.
It only hurts bisectibility.
All errors (new ones prefixed by >>):
drivers/net/ethernet/intel/i40e/i40e_common.c: In function 'i40e_led_get_phy':
>> drivers/net/ethernet/intel/i40e/i40e_common.c:4856:9: error: implicit declaration of function 'i40e_aq_get_phy_register' [-Werror=implicit-function-declaration]
i40e_aq_get_phy_register(hw,
^~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/ethernet/intel/i40e/i40e_common.c:4857:13: error: 'I40E_AQ_PHY_REG_ACCESS_EXTERNAL' undeclared (first use in this function)
I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/intel/i40e/i40e_common.c:4857:13: note: each undeclared identifier is reported only once for each function it appears in
drivers/net/ethernet/intel/i40e/i40e_common.c: In function 'i40e_led_set_phy':
drivers/net/ethernet/intel/i40e/i40e_common.c:4910:13: error: 'I40E_AQ_PHY_REG_ACCESS_EXTERNAL' undeclared (first use in this function)
I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/ethernet/intel/i40e/i40e_common.c:4930:13: error: implicit declaration of function 'i40e_aq_set_phy_register' [-Werror=implicit-function-declaration]
status = i40e_aq_set_phy_register(hw,
^~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +/i40e_aq_get_phy_register +4856 drivers/net/ethernet/intel/i40e/i40e_common.c
4834
4835 /**
4836 * i40e_led_get_phy - return current on/off mode
4837 * @hw: pointer to the hw struct
4838 * @led_addr: address of led register to use
4839 * @val: original value of register to use
4840 *
4841 **/
4842 i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
4843 u16 *val)
4844 {
4845 i40e_status status = 0;
4846 u16 gpio_led_port;
4847 u8 phy_addr = 0;
4848 u16 reg_val;
4849 u16 temp_addr;
4850 u8 port_num;
4851 u32 i;
4852 u32 reg_val_aq;
4853
4854 if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
4855 status =
> 4856 i40e_aq_get_phy_register(hw,
> 4857 I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
4858 I40E_PHY_COM_REG_PAGE,
4859 I40E_PHY_LED_PROV_REG_1,
4860 ®_val_aq, NULL);
4861 if (status)
4862 return status;
4863 *val = (u16)reg_val_aq;
4864 } else {
4865 temp_addr = I40E_PHY_LED_PROV_REG_1;
4866 i = rd32(hw, I40E_PFGEN_PORTNUM);
4867 port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
4868 phy_addr = i40e_get_phy_address(hw, port_num);
4869
4870 for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
4871 temp_addr++) {
4872 status =
4873 i40e_read_phy_register_clause45(hw,
4874 I40E_PHY_COM_REG_PAGE,
4875 temp_addr, phy_addr,
4876 ®_val);
4877 if (status)
4878 return status;
4879 *val = reg_val;
4880 if (reg_val & I40E_PHY_LED_LINK_MODE_MASK) {
4881 *led_addr = temp_addr;
4882 break;
4883 }
4884 }
4885 }
4886 return status;
4887 }
4888
4889 /**
4890 * i40e_led_set_phy
4891 * @hw: pointer to the HW structure
4892 * @on: true or false
4893 * @mode: original val plus bit for set or ignore
4894 * Set led's on or off when controlled by the PHY
4895 *
4896 **/
4897 i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,
4898 u16 led_addr, u32 mode)
4899 {
4900 i40e_status status = 0;
4901 u32 led_ctl = 0;
4902 u32 led_reg = 0;
4903 u8 phy_addr = 0;
4904 u8 port_num;
4905 u32 i;
4906
4907 if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
4908 status =
4909 i40e_aq_get_phy_register(hw,
4910 I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
4911 I40E_PHY_COM_REG_PAGE,
4912 I40E_PHY_LED_PROV_REG_1,
4913 &led_reg, NULL);
4914 } else {
4915 i = rd32(hw, I40E_PFGEN_PORTNUM);
4916 port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
4917 phy_addr = i40e_get_phy_address(hw, port_num);
4918 status = i40e_read_phy_register_clause45(hw,
4919 I40E_PHY_COM_REG_PAGE,
4920 led_addr, phy_addr,
4921 (u16 *)&led_reg);
4922 }
4923 if (status)
4924 return status;
4925 led_ctl = led_reg;
4926 if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
4927 led_reg = 0;
4928 if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
4929 hw->aq.api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710) {
> 4930 status = i40e_aq_set_phy_register(hw,
4931 I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
4932 I40E_PHY_COM_REG_PAGE,
4933 I40E_PHY_LED_PROV_REG_1,
4934 led_reg, NULL);
4935 } else {
4936 status = i40e_write_phy_register_clause45(hw,
4937 I40E_PHY_COM_REG_PAGE,
4938 led_addr, phy_addr,
4939 (u16)led_reg);
4940 }
4941 if (status)
4942 return status;
4943 }
4944 if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
4945 status =
4946 i40e_aq_get_phy_register(hw,
4947 I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
4948 I40E_PHY_COM_REG_PAGE,
4949 I40E_PHY_LED_PROV_REG_1,
4950 &led_reg, NULL);
4951 } else {
4952 status = i40e_read_phy_register_clause45(hw,
4953 I40E_PHY_COM_REG_PAGE,
4954 led_addr, phy_addr,
4955 (u16 *)&led_reg);
4956 }
4957 if (status)
4958 goto restore_config;
4959 if (on)
4960 led_reg = I40E_PHY_LED_MANUAL_ON;
4961 else
4962 led_reg = 0;
4963
4964 if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
4965 status =
4966 i40e_aq_set_phy_register(hw,
4967 I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
4968 I40E_PHY_COM_REG_PAGE,
4969 I40E_PHY_LED_PROV_REG_1,
4970 led_reg, NULL);
4971 } else {
4972 status =
4973 i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
4974 led_addr, phy_addr,
4975 (u16)led_reg);
4976 }
4977 if (status)
4978 goto restore_config;
4979 if (mode & I40E_PHY_LED_MODE_ORIG) {
4980 led_ctl = (mode & I40E_PHY_LED_MODE_MASK);
4981 if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
4982 status = i40e_aq_set_phy_register(hw,
4983 I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
4984 I40E_PHY_COM_REG_PAGE,
4985 I40E_PHY_LED_PROV_REG_1,
4986 led_ctl, NULL);
4987 } else {
4988 status = i40e_write_phy_register_clause45(hw,
4989 I40E_PHY_COM_REG_PAGE,
4990 led_addr, phy_addr,
4991 (u16)led_ctl);
4992 }
4993 }
4994 return status;
4995 restore_config:
4996 if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
4997 status =
4998 i40e_aq_set_phy_register(hw,
4999 I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
5000 I40E_PHY_COM_REG_PAGE,
5001 I40E_PHY_LED_PROV_REG_1,
5002 led_ctl, NULL);
5003 } else {
5004 status =
5005 i40e_write_phy_register_clause45(hw,
5006 I40E_PHY_COM_REG_PAGE,
5007 led_addr, phy_addr,
5008 (u16)led_ctl);
5009 }
5010 return status;
5011 }
5012
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 39611 bytes
Desc: not available
URL: <http://lists.osuosl.org/pipermail/intel-wired-lan/attachments/20170806/8d56bd6a/attachment-0001.bin>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
` (11 preceding siblings ...)
2017-08-06 7:02 ` [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior kbuild test robot
@ 2017-08-07 17:18 ` Shannon Nelson
12 siblings, 0 replies; 19+ messages in thread
From: Shannon Nelson @ 2017-08-07 17:18 UTC (permalink / raw)
To: intel-wired-lan
On 8/4/2017 6:52 AM, Alice Michael wrote:
> From: Mariusz Stachura <mariusz.stachura@intel.com>
>
> Instead of accessing register directly, use newly added AQC in
> order to blink LEDs. Introduce and utilize a new flag to prevent
> excessive API version checking.
>
> Signed-off-by: Mariusz Stachura <mariusz.stachura@intel.com>
> ---
> drivers/net/ethernet/intel/i40e/i40e_adminq.c | 6 ++
> drivers/net/ethernet/intel/i40e/i40e_common.c | 148 ++++++++++++++++++++------
> drivers/net/ethernet/intel/i40e/i40e_type.h | 1 +
> drivers/net/ethernet/intel/i40evf/i40e_type.h | 2 +
> 4 files changed, 122 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
> index ba04988..340e5a2 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
> @@ -607,6 +607,12 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
> &oem_lo);
> hw->nvm.oem_ver = ((u32)oem_hi << 16) | oem_lo;
>
> + if (hw->mac.type == I40E_MAC_XL710 &&
Extra space after ==
> + hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
> + hw->aq.api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710) {
> + hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
> + }
> +
> if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) {
> ret_code = I40E_ERR_FIRMWARE_API_VERSION;
> goto init_adminq_free_arq;
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
> index e4e86e0..e9f30b8 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_common.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
> @@ -4849,24 +4849,38 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
> u16 temp_addr;
> u8 port_num;
> u32 i;
> -
> - temp_addr = I40E_PHY_LED_PROV_REG_1;
> - 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);
> -
> - for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
> - temp_addr++) {
> - status = i40e_read_phy_register_clause45(hw,
> + u32 reg_val_aq;
> +
> + if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
> + status =
> + i40e_aq_get_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
> + I40E_PHY_COM_REG_PAGE,
> + I40E_PHY_LED_PROV_REG_1,
> + ®_val_aq, NULL);
Since this call doesn't exist yet, please re-order this patchset so that
"i40e: Add support for 'ethtool -m'" comes first.
> + if (status)
> + return status;
> + *val = (u16)reg_val_aq;
The diffs below would be greatly simplified by doing the return here and
not shifting the rest into an else block. Something like this and the
rest can be left alone:
if (!status)
*val = (u16)reg_val_aq;
return status;
}
> + } else {
> + temp_addr = I40E_PHY_LED_PROV_REG_1;
> + 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);
> +
> + for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
> + temp_addr++) {
> + status =
> + i40e_read_phy_register_clause45(hw,
> I40E_PHY_COM_REG_PAGE,
> temp_addr, phy_addr,
> ®_val);
> - if (status)
> - return status;
> - *val = reg_val;
> - if (reg_val & I40E_PHY_LED_LINK_MODE_MASK) {
> - *led_addr = temp_addr;
> - break;
> + if (status)
> + return status;
> + *val = reg_val;
> + if (reg_val & I40E_PHY_LED_LINK_MODE_MASK) {
> + *led_addr = temp_addr;
> + break;
> + }
> }
> }
> return status;
> @@ -4884,51 +4898,115 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,
> u16 led_addr, u32 mode)
> {
> i40e_status status = 0;
> - u16 led_ctl = 0;
> - u16 led_reg = 0;
> + u32 led_ctl = 0;
> + u32 led_reg = 0;
> u8 phy_addr = 0;
> u8 port_num;
> u32 i;
>
> - 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_clause45(hw, I40E_PHY_COM_REG_PAGE,
> - led_addr, phy_addr, &led_reg);
> + if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
> + status =
> + i40e_aq_get_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
> + I40E_PHY_COM_REG_PAGE,
> + I40E_PHY_LED_PROV_REG_1,
> + &led_reg, NULL);
> + } else {
> + 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_clause45(hw,
> + I40E_PHY_COM_REG_PAGE,
> + led_addr, phy_addr,
> + (u16 *)&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_clause45(hw,
> - I40E_PHY_COM_REG_PAGE,
> - led_addr, phy_addr,
> - led_reg);
> + if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
> + hw->aq.api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710) {
Why are you not using the I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE here?
> + status = i40e_aq_set_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
> + I40E_PHY_COM_REG_PAGE,
> + I40E_PHY_LED_PROV_REG_1,
> + led_reg, NULL);
> + } else {
> + status = i40e_write_phy_register_clause45(hw,
> + I40E_PHY_COM_REG_PAGE,
> + led_addr, phy_addr,
> + (u16)led_reg);
> + }
> if (status)
> return status;
> }
> - status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
> - led_addr, phy_addr, &led_reg);
> + if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
> + status =
> + i40e_aq_get_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
> + I40E_PHY_COM_REG_PAGE,
> + I40E_PHY_LED_PROV_REG_1,
> + &led_reg, NULL);
> + } else {
> + status = i40e_read_phy_register_clause45(hw,
> + I40E_PHY_COM_REG_PAGE,
> + led_addr, phy_addr,
> + (u16 *)&led_reg);
> + }
Please abstract these read/write structures into helper functions
instead of repeating this if/else so many times.
> if (status)
> goto restore_config;
> if (on)
> led_reg = I40E_PHY_LED_MANUAL_ON;
> else
> led_reg = 0;
> - status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
> - led_addr, phy_addr, led_reg);
> +
> + if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
> + status =
> + i40e_aq_set_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
> + I40E_PHY_COM_REG_PAGE,
> + I40E_PHY_LED_PROV_REG_1,
> + led_reg, NULL);
> + } else {
> + status =
> + i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
> + led_addr, phy_addr,
> + (u16)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_clause45(hw,
> - I40E_PHY_COM_REG_PAGE,
> - led_addr, phy_addr, led_ctl);
> + if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
> + status = i40e_aq_set_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
> + I40E_PHY_COM_REG_PAGE,
> + I40E_PHY_LED_PROV_REG_1,
> + led_ctl, NULL);
> + } else {
> + status = i40e_write_phy_register_clause45(hw,
> + I40E_PHY_COM_REG_PAGE,
> + led_addr, phy_addr,
> + (u16)led_ctl);
> + }
> }
> return status;
> restore_config:
> - status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
> - led_addr, phy_addr, led_ctl);
> + if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
> + status =
> + i40e_aq_set_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
> + I40E_PHY_COM_REG_PAGE,
> + I40E_PHY_LED_PROV_REG_1,
> + led_ctl, NULL);
> + } else {
> + status =
> + i40e_write_phy_register_clause45(hw,
> + I40E_PHY_COM_REG_PAGE,
> + led_addr, phy_addr,
> + (u16)led_ctl);
> + }
> return status;
> }
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
> index fd4bbdd..78fda11 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_type.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
> @@ -598,6 +598,7 @@ struct i40e_hw {
> struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */
>
> #define I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE BIT_ULL(0)
> +#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE BIT_ULL(2)
> u64 flags;
>
> /* debug mask */
> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
> index 2ea919d..412a32c 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
> +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
> @@ -556,6 +556,8 @@ struct i40e_hw {
> /* LLDP/DCBX Status */
> u16 dcbx_status;
>
> +#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE BIT_ULL(2)
> +
> /* DCBX info */
> struct i40e_dcbx_config local_dcbx_config; /* Oper/Local Cfg */
> struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 02/12] i40e: Fix reporting of supported link modes
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 02/12] i40e: Fix reporting of supported link modes Alice Michael
@ 2017-08-07 17:18 ` Shannon Nelson
0 siblings, 0 replies; 19+ messages in thread
From: Shannon Nelson @ 2017-08-07 17:18 UTC (permalink / raw)
To: intel-wired-lan
On 8/4/2017 6:52 AM, Alice Michael wrote:
> From: Filip Sadowski <filip.sadowski@intel.com>
>
> This patch fixes incorrect reporting of supported link modes on some NICs.
>
> Signed-off-by: Filip Sadowski <filip.sadowski@intel.com>
> ---
> drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 20 ++++++++++++++++++--
> drivers/net/ethernet/intel/i40e/i40e_common.c | 8 +++++++-
> drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 20 ++++++++++++++++++--
> 3 files changed, 43 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> index e2a9ec8..5d0291c 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> @@ -1734,6 +1734,8 @@ enum i40e_aq_phy_type {
> I40E_PHY_TYPE_10GBASE_CR1_CU = 0xB,
> I40E_PHY_TYPE_10GBASE_AOC = 0xC,
> I40E_PHY_TYPE_40GBASE_AOC = 0xD,
> + I40E_PHY_TYPE_UNRECOGNIZED = 0xE,
> + I40E_PHY_TYPE_UNSUPPORTED = 0xF,
> I40E_PHY_TYPE_100BASE_TX = 0x11,
> I40E_PHY_TYPE_1000BASE_T = 0x12,
> I40E_PHY_TYPE_10GBASE_T = 0x13,
> @@ -1752,6 +1754,8 @@ enum i40e_aq_phy_type {
> I40E_PHY_TYPE_25GBASE_CR = 0x20,
> I40E_PHY_TYPE_25GBASE_SR = 0x21,
> I40E_PHY_TYPE_25GBASE_LR = 0x22,
> + I40E_PHY_TYPE_EMPTY = 0xFE,
> + I40E_PHY_TYPE_DEFAULT = 0xFF,
> I40E_PHY_TYPE_MAX
> };
>
> @@ -1942,19 +1946,31 @@ struct i40e_aqc_get_link_status {
> #define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
> #define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
> u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
> +/* Since firmware API 1.7 loopback field keeps power class info as well */
> +#define I40E_AQ_LOOPBACK_MASK 0x07
> +#define I40E_AQ_PWR_CLASS_SHIFT_LB 6
> +#define I40E_AQ_PWR_CLASS_MASK_LB (0x03 << I40E_AQ_PWR_CLASS_SHIFT_LB)
> __le16 max_frame_size;
> u8 config;
> #define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
> #define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
> #define I40E_AQ_CONFIG_CRC_ENA 0x04
> #define I40E_AQ_CONFIG_PACING_MASK 0x78
> - u8 power_desc;
> + union {
> + struct {
> + u8 power_desc;
> #define I40E_AQ_LINK_POWER_CLASS_1 0x00
> #define I40E_AQ_LINK_POWER_CLASS_2 0x01
> #define I40E_AQ_LINK_POWER_CLASS_3 0x02
> #define I40E_AQ_LINK_POWER_CLASS_4 0x03
> #define I40E_AQ_PWR_CLASS_MASK 0x03
> - u8 reserved[4];
> + u8 reserved[4];
> + };
> + struct {
> + u8 link_type[4];
Wait, is this a 32-bit value on an odd-byte alignment? No, no, no... we
worked hard early on to not let the HW folks do this.
> + u8 link_type_ext;
> + };
> + };
> };
>
> I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
> index e9f30b8..c0aeda7 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_common.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
> @@ -1826,7 +1826,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
> hw_link_info->fec_info = resp->config & (I40E_AQ_CONFIG_FEC_KR_ENA |
> I40E_AQ_CONFIG_FEC_RS_ENA);
> hw_link_info->ext_info = resp->ext_info;
> - hw_link_info->loopback = resp->loopback;
> + hw_link_info->loopback = resp->loopback & I40E_AQ_LOOPBACK_MASK;
> hw_link_info->max_frame_size = le16_to_cpu(resp->max_frame_size);
> hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK;
>
> @@ -1857,6 +1857,12 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
> hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
> hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU;
>
> + if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
> + hw->aq.api_min_ver >= 7) {
> + hw->phy.phy_types = le32_to_cpu(*(__le32 *)resp->link_type);
Reading a 32-bit word from an odd byte boundary will cause a non-x86
machine (e.g. SPARC) a bit of heartburn, kernel log messages, and
possibly a few customer complaints. You're going to need a memcpy() to
get it out of the funky memory address, then you can add in the byteswap.
u32 tmp;
memcpy(&tmp, &resp->link_type, sizeof(tmp));
hw->phy.phy_types = le32_to_cpu(tmp);
> + hw->phy.phy_types |= ((u64)resp->link_type_ext << 32);
> + }
> +
> /* save link status information */
> if (link)
> *link = *hw_link_info;
> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> index f9f48d1..709d114 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> @@ -1730,6 +1730,8 @@ enum i40e_aq_phy_type {
> I40E_PHY_TYPE_10GBASE_CR1_CU = 0xB,
> I40E_PHY_TYPE_10GBASE_AOC = 0xC,
> I40E_PHY_TYPE_40GBASE_AOC = 0xD,
> + I40E_PHY_TYPE_UNRECOGNIZED = 0xE,
> + I40E_PHY_TYPE_UNSUPPORTED = 0xF,
> I40E_PHY_TYPE_100BASE_TX = 0x11,
> I40E_PHY_TYPE_1000BASE_T = 0x12,
> I40E_PHY_TYPE_10GBASE_T = 0x13,
> @@ -1748,6 +1750,8 @@ enum i40e_aq_phy_type {
> I40E_PHY_TYPE_25GBASE_CR = 0x20,
> I40E_PHY_TYPE_25GBASE_SR = 0x21,
> I40E_PHY_TYPE_25GBASE_LR = 0x22,
> + I40E_PHY_TYPE_EMPTY = 0xFE,
> + I40E_PHY_TYPE_DEFAULT = 0xFF,
> I40E_PHY_TYPE_MAX
> };
>
> @@ -1938,19 +1942,31 @@ struct i40e_aqc_get_link_status {
> #define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
> #define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
> u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
> +/* Since firmware API 1.7 loopback field keeps power class info as well */
> +#define I40E_AQ_LOOPBACK_MASK 0x07
> +#define I40E_AQ_PWR_CLASS_SHIFT_LB 6
> +#define I40E_AQ_PWR_CLASS_MASK_LB (0x03 << I40E_AQ_PWR_CLASS_SHIFT_LB)
> __le16 max_frame_size;
> u8 config;
> #define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
> #define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
> #define I40E_AQ_CONFIG_CRC_ENA 0x04
> #define I40E_AQ_CONFIG_PACING_MASK 0x78
> - u8 power_desc;
> + union {
> + struct {
> + u8 power_desc;
> #define I40E_AQ_LINK_POWER_CLASS_1 0x00
> #define I40E_AQ_LINK_POWER_CLASS_2 0x01
> #define I40E_AQ_LINK_POWER_CLASS_3 0x02
> #define I40E_AQ_LINK_POWER_CLASS_4 0x03
> #define I40E_AQ_PWR_CLASS_MASK 0x03
> - u8 reserved[4];
> + u8 reserved[4];
> + };
> + struct {
> + u8 link_type[4];
> + u8 link_type_ext;
> + };
> + };
> };
>
> I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 03/12] i40e: Add support for 'ethtool -m'
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 03/12] i40e: Add support for 'ethtool -m' Alice Michael
@ 2017-08-07 17:19 ` Shannon Nelson
0 siblings, 0 replies; 19+ messages in thread
From: Shannon Nelson @ 2017-08-07 17:19 UTC (permalink / raw)
To: intel-wired-lan
On 8/4/2017 6:52 AM, Alice Michael wrote:
> From: Filip Sadowski <filip.sadowski@intel.com>
>
> This patch adds support for 'ethtool -m' command which displays
> information about (Q)SFP+ module plugged into NIC's cage.
>
> Signed-off-by: Filip Sadowski <filip.sadowski@intel.com>
> ---
> drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 18 +++
> drivers/net/ethernet/intel/i40e/i40e_common.c | 69 +++++++++
> drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 154 +++++++++++++++++++++
> drivers/net/ethernet/intel/i40e/i40e_prototype.h | 9 ++
> drivers/net/ethernet/intel/i40e/i40e_type.h | 12 ++
> .../net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 18 +++
> drivers/net/ethernet/intel/i40evf/i40e_common.c | 69 +++++++++
> drivers/net/ethernet/intel/i40evf/i40e_prototype.h | 9 ++
> drivers/net/ethernet/intel/i40evf/i40e_type.h | 12 ++
> 9 files changed, 370 insertions(+)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> index 5d0291c..8fcbbd8 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> @@ -244,6 +244,8 @@ enum i40e_admin_queue_opc {
> i40e_aqc_opc_set_phy_debug = 0x0622,
> i40e_aqc_opc_upload_ext_phy_fm = 0x0625,
> i40e_aqc_opc_run_phy_activity = 0x0626,
> + i40e_aqc_opc_set_phy_register = 0x0628,
> + i40e_aqc_opc_get_phy_register = 0x0629,
>
> /* NVM commands */
> i40e_aqc_opc_nvm_read = 0x0701,
> @@ -2053,6 +2055,22 @@ struct i40e_aqc_run_phy_activity {
>
> I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity);
>
> +/* Set PHY Register command (0x0628) */
> +/* Get PHY Register command (0x0629) */
> +struct i40e_aqc_phy_register_access {
> + u8 phy_interface;
> +#define I40E_AQ_PHY_REG_ACCESS_INTERNAL 0
> +#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL 1
> +#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE 2
> + u8 dev_address;
> + u8 reserved1[2];
> + u32 reg_address;
> + u32 reg_value;
> + u8 reserved2[4];
> +};
> +
> +I40E_CHECK_CMD_LENGTH(i40e_aqc_phy_register_access);
> +
> /* NVM Read command (indirect 0x0701)
> * NVM Erase commands (direct 0x0702)
> * NVM Update commands (indirect 0x0703)
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
> index c0aeda7..6b7712c 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_common.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
> @@ -5143,6 +5143,75 @@ void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val)
> }
>
> /**
> + * i40e_aq_set_phy_register
> + * @hw: pointer to the hw struct
> + * @phy_select: select which phy should be accessed
> + * @dev_addr: PHY device address
> + * @reg_addr: PHY register address
> + * @reg_val: new register value
> + * @cmd_details: pointer to command details structure or NULL
> + *
> + * Write the external PHY register.
> + **/
> +i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw,
> + u8 phy_select, u8 dev_addr,
> + u32 reg_addr, u32 reg_val,
> + struct i40e_asq_cmd_details *cmd_details)
> +{
> + struct i40e_aq_desc desc;
> + struct i40e_aqc_phy_register_access *cmd =
> + (struct i40e_aqc_phy_register_access *)&desc.params.raw;
> + i40e_status status;
> +
> + i40e_fill_default_direct_cmd_desc(&desc,
> + i40e_aqc_opc_set_phy_register);
> +
> + cmd->phy_interface = phy_select;
> + cmd->dev_address = dev_addr;
> + cmd->reg_address = reg_addr;
> + cmd->reg_value = reg_val;
Byteswapping?
> +
> + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
> +
> + return status;
> +}
> +
> +/**
> + * i40e_aq_get_phy_register
> + * @hw: pointer to the hw struct
> + * @phy_select: select which phy should be accessed
> + * @dev_addr: PHY device address
> + * @reg_addr: PHY register address
> + * @reg_val: read register value
> + * @cmd_details: pointer to command details structure or NULL
> + *
> + * Read the external PHY register.
> + **/
> +i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw,
> + u8 phy_select, u8 dev_addr,
> + u32 reg_addr, u32 *reg_val,
> + struct i40e_asq_cmd_details *cmd_details)
> +{
> + struct i40e_aq_desc desc;
> + struct i40e_aqc_phy_register_access *cmd =
> + (struct i40e_aqc_phy_register_access *)&desc.params.raw;
> + i40e_status status;
> +
> + i40e_fill_default_direct_cmd_desc(&desc,
> + i40e_aqc_opc_get_phy_register);
> +
> + cmd->phy_interface = phy_select;
> + cmd->dev_address = dev_addr;
> + cmd->reg_address = reg_addr;
Byteswapping?
> +
> + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
> + if (!status)
> + *reg_val = cmd->reg_value;
Byteswapping?
> +
> + return status;
> +}
> +
> +/**
> * i40e_aq_write_ppp - Write pipeline personalization profile (ppp)
> * @hw: pointer to the hw struct
> * @buff: command buffer (size in bytes = buff_size)
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> index 326fc18..72910c5 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> @@ -4202,6 +4202,158 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
> return 0;
> }
>
> +/**
> + * i40e_get_module_info - get (Q)SFP+ module type info
> + * @netdev: network interface device structure
> + * @modinfo: module EEPROM size and layout information structure
> + **/
> +static int i40e_get_module_info(struct net_device *netdev,
> + struct ethtool_modinfo *modinfo)
> +{
> + i40e_status status;
> + struct i40e_netdev_priv *np = netdev_priv(netdev);
> + struct i40e_vsi *vsi = np->vsi;
> + struct i40e_pf *pf = vsi->back;
> + struct i40e_hw *hw = &pf->hw;
> + u32 sff8472_comp = 0;
> + u32 sff8472_swap = 0;
> + u32 sff8636_rev = 0;
> + u32 type = 0;
> +
> + /* Check if firmware supports reading module EEPROM. */
> + if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
> + netdev_err(vsi->netdev, "Module EEPROM memory read not supported. Please update the NVM image.\n");
> + return -EINVAL;
> + }
> +
> + status = i40e_update_link_info(hw);
> + if (status)
> + return -EIO;
> +
> + if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
> + netdev_err(vsi->netdev, "Cannot read module EEPROM memory. No module connected.\n");
> + return -EINVAL;
> + }
> +
> + type = hw->phy.link_info.module_type[0];
> +
> + switch (type) {
> + case I40E_MODULE_TYPE_SFP:
> + status = i40e_aq_get_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
> + I40E_I2C_EEPROM_DEV_ADDR,
> + I40E_MODULE_SFF_8472_COMP,
> + &sff8472_comp, NULL);
> + if (status)
> + return -EIO;
> +
> + status = i40e_aq_get_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
> + I40E_I2C_EEPROM_DEV_ADDR,
> + I40E_MODULE_SFF_8472_SWAP,
> + &sff8472_swap, NULL);
> + if (status)
> + return -EIO;
> +
> + /* Check if the module requires address swap to access
> + * the other EEPROM memory page.
> + */
> + if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
> + netdev_warn(vsi->netdev, "Module address swap to access page 0xA2 is not supported.\n");
> + modinfo->type = ETH_MODULE_SFF_8079;
> + modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
> + } else if (sff8472_comp == 0x00) {
> + /* Module is not SFF-8472 compliant */
> + modinfo->type = ETH_MODULE_SFF_8079;
> + modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
> + } else {
> + modinfo->type = ETH_MODULE_SFF_8472;
> + modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
> + }
> + break;
> + case I40E_MODULE_TYPE_QSFP_PLUS:
> + /* Read from memory page 0. */
> + status = i40e_aq_get_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
> + 0,
> + I40E_MODULE_REVISION_ADDR,
> + &sff8636_rev, NULL);
> + if (status)
> + return -EIO;
> + /* Determine revision compliance byte */
> + if (sff8636_rev > 0x02) {
> + /* Module is SFF-8636 compliant */
> + modinfo->type = ETH_MODULE_SFF_8636;
> + modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
> + } else {
> + modinfo->type = ETH_MODULE_SFF_8436;
> + modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
> + }
> + break;
> + case I40E_MODULE_TYPE_QSFP28:
> + modinfo->type = ETH_MODULE_SFF_8636;
> + modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
> + break;
> + default:
> + netdev_err(vsi->netdev, "Module type unrecognized\n");
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> +/**
> + * i40e_get_module_eeprom - fills buffer with (Q)SFP+ module memory contents
> + * @netdev: network interface device structure
> + * @ee: EEPROM dump request structure
> + * @data: buffer to be filled with EEPROM contents
> + **/
> +static int i40e_get_module_eeprom(struct net_device *netdev,
> + struct ethtool_eeprom *ee,
> + u8 *data)
> +{
> + i40e_status status;
> + struct i40e_netdev_priv *np = netdev_priv(netdev);
> + struct i40e_vsi *vsi = np->vsi;
> + struct i40e_pf *pf = vsi->back;
> + struct i40e_hw *hw = &pf->hw;
> + bool is_sfp = false;
> + u32 value = 0;
> + int i;
> +
> + if (!ee || !ee->len || !data)
> + return -EINVAL;
> +
> + if (hw->phy.link_info.module_type[0] == I40E_MODULE_TYPE_SFP)
> + is_sfp = true;
> +
> + for (i = 0; i < ee->len; i++) {
> + u32 offset = i + ee->offset;
> + u32 addr = is_sfp ? I40E_I2C_EEPROM_DEV_ADDR : 0;
> +
> + /* Check if we need to access the other memory page */
> + if (is_sfp) {
> + if (offset >= ETH_MODULE_SFF_8079_LEN) {
> + offset -= ETH_MODULE_SFF_8079_LEN;
> + addr = I40E_I2C_EEPROM_DEV_ADDR2;
> + }
> + } else {
> + while (offset >= ETH_MODULE_SFF_8436_LEN) {
> + /* Compute memory page number and offset. */
> + offset -= ETH_MODULE_SFF_8436_LEN / 2;
> + addr++;
> + }
> + }
> +
> + status = i40e_aq_get_phy_register(hw,
> + I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
> + addr, offset, &value, NULL);
> + if (status)
> + return -EIO;
> + data[i] = value;
> + }
> + return 0;
> +}
> +
> static const struct ethtool_ops i40e_ethtool_ops = {
> .get_drvinfo = i40e_get_drvinfo,
> .get_regs_len = i40e_get_regs_len,
> @@ -4234,6 +4386,8 @@ static const struct ethtool_ops i40e_ethtool_ops = {
> .set_rxfh = i40e_set_rxfh,
> .get_channels = i40e_get_channels,
> .set_channels = i40e_set_channels,
> + .get_module_info = i40e_get_module_info,
> + .get_module_eeprom = i40e_get_module_eeprom,
> .get_ts_info = i40e_get_ts_info,
> .get_priv_flags = i40e_get_priv_flags,
> .set_priv_flags = i40e_set_priv_flags,
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
> index df613ea..6254ad5 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
> @@ -362,6 +362,15 @@ i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw,
> u32 reg_addr, u32 reg_val,
> struct i40e_asq_cmd_details *cmd_details);
> void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
> +i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw,
> + u8 phy_select, u8 dev_addr,
> + u32 reg_addr, u32 reg_val,
> + struct i40e_asq_cmd_details *cmd_details);
> +i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw,
> + u8 phy_select, u8 dev_addr,
> + u32 reg_addr, u32 *reg_val,
> + struct i40e_asq_cmd_details *cmd_details);
> +
> i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
> u16 reg, u8 phy_addr, u16 *value);
> i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
> index 78fda11..8b0b9f8 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_type.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
> @@ -428,6 +428,18 @@ struct i40e_nvm_access {
> u8 data[1];
> };
>
> +/* (Q)SFP module access definitions */
> +#define I40E_I2C_EEPROM_DEV_ADDR 0xA0
> +#define I40E_I2C_EEPROM_DEV_ADDR2 0xA2
> +#define I40E_MODULE_TYPE_ADDR 0x00
> +#define I40E_MODULE_REVISION_ADDR 0x01
> +#define I40E_MODULE_SFF_8472_COMP 0x5E
> +#define I40E_MODULE_SFF_8472_SWAP 0x5C
> +#define I40E_MODULE_SFF_ADDR_MODE 0x04
> +#define I40E_MODULE_TYPE_QSFP_PLUS 0x0D
> +#define I40E_MODULE_TYPE_QSFP28 0x11
> +#define I40E_MODULE_QSFP_MAX_LEN 640
> +
> /* PCI bus types */
> enum i40e_bus_type {
> i40e_bus_type_unknown = 0,
> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> index 709d114..b7715d4 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> @@ -244,6 +244,8 @@ enum i40e_admin_queue_opc {
> i40e_aqc_opc_set_phy_debug = 0x0622,
> i40e_aqc_opc_upload_ext_phy_fm = 0x0625,
> i40e_aqc_opc_run_phy_activity = 0x0626,
> + i40e_aqc_opc_set_phy_register = 0x0628,
> + i40e_aqc_opc_get_phy_register = 0x0629,
>
> /* NVM commands */
> i40e_aqc_opc_nvm_read = 0x0701,
> @@ -2046,6 +2048,22 @@ struct i40e_aqc_run_phy_activity {
>
> I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity);
>
> +/* Set PHY Register command (0x0628) */
> +/* Get PHY Register command (0x0629) */
> +struct i40e_aqc_phy_register_access {
> + u8 phy_interface;
> +#define I40E_AQ_PHY_REG_ACCESS_INTERNAL 0
> +#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL 1
> +#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE 2
> + u8 dev_address;
> + u8 reserved1[2];
> + u32 reg_address;
> + u32 reg_value;
> + u8 reserved2[4];
> +};
> +
> +I40E_CHECK_CMD_LENGTH(i40e_aqc_phy_register_access);
> +
> /* NVM Read command (indirect 0x0701)
> * NVM Erase commands (direct 0x0702)
> * NVM Update commands (indirect 0x0703)
> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c
> index 8d3a2bf..7df4610 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c
> +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c
> @@ -1042,6 +1042,75 @@ void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val)
> }
>
> /**
> + * i40evf_aq_set_phy_register
> + * @hw: pointer to the hw struct
> + * @phy_select: select which phy should be accessed
> + * @dev_addr: PHY device address
> + * @reg_addr: PHY register address
> + * @reg_val: new register value
> + * @cmd_details: pointer to command details structure or NULL
> + *
> + * Reset the external PHY.
> + **/
> +i40e_status i40evf_aq_set_phy_register(struct i40e_hw *hw,
> + u8 phy_select, u8 dev_addr,
> + u32 reg_addr, u32 reg_val,
> + struct i40e_asq_cmd_details *cmd_details)
> +{
> + struct i40e_aq_desc desc;
> + struct i40e_aqc_phy_register_access *cmd =
> + (struct i40e_aqc_phy_register_access *)&desc.params.raw;
> + i40e_status status;
> +
> + i40evf_fill_default_direct_cmd_desc(&desc,
> + i40e_aqc_opc_set_phy_register);
> +
> + cmd->phy_interface = phy_select;
> + cmd->dev_address = dev_addr;
> + cmd->reg_address = reg_addr;
> + cmd->reg_value = reg_val;
Same byteswapping comments...
> +
> + status = i40evf_asq_send_command(hw, &desc, NULL, 0, cmd_details);
> +
> + return status;
> +}
> +
> +/**
> + * i40evf_aq_get_phy_register
> + * @hw: pointer to the hw struct
> + * @phy_select: select which phy should be accessed
> + * @dev_addr: PHY device address
> + * @reg_addr: PHY register address
> + * @reg_val: read register value
> + * @cmd_details: pointer to command details structure or NULL
> + *
> + * Reset the external PHY.
> + **/
> +i40e_status i40evf_aq_get_phy_register(struct i40e_hw *hw,
> + u8 phy_select, u8 dev_addr,
> + u32 reg_addr, u32 *reg_val,
> + struct i40e_asq_cmd_details *cmd_details)
> +{
> + struct i40e_aq_desc desc;
> + struct i40e_aqc_phy_register_access *cmd =
> + (struct i40e_aqc_phy_register_access *)&desc.params.raw;
> + i40e_status status;
> +
> + i40evf_fill_default_direct_cmd_desc(&desc,
> + i40e_aqc_opc_get_phy_register);
> +
> + cmd->phy_interface = phy_select;
> + cmd->dev_address = dev_addr;
> + cmd->reg_address = reg_addr;
> +
> + status = i40evf_asq_send_command(hw, &desc, NULL, 0, cmd_details);
> + if (!status)
> + *reg_val = cmd->reg_value;
> +
> + return status;
> +}
> +
> +/**
> * i40e_aq_send_msg_to_pf
> * @hw: pointer to the hardware structure
> * @v_opcode: opcodes for VF-PF communication
> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
> index c9836bb..b624b59 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
> +++ b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
> @@ -111,6 +111,15 @@ i40e_status i40evf_aq_rx_ctl_write_register(struct i40e_hw *hw,
> u32 reg_addr, u32 reg_val,
> struct i40e_asq_cmd_details *cmd_details);
> void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
> +i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw,
> + u8 phy_select, u8 dev_addr,
> + u32 reg_addr, u32 reg_val,
> + struct i40e_asq_cmd_details *cmd_details);
> +i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw,
> + u8 phy_select, u8 dev_addr,
> + u32 reg_addr, u32 *reg_val,
> + struct i40e_asq_cmd_details *cmd_details);
> +
> i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,
> u16 reg, u8 phy_addr, u16 *value);
> i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,
> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
> index 412a32c..48eacf5 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
> +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
> @@ -401,6 +401,18 @@ struct i40e_nvm_access {
> u8 data[1];
> };
>
> +/* (Q)SFP module access definitions */
> +#define I40E_I2C_EEPROM_DEV_ADDR 0xA0
> +#define I40E_I2C_EEPROM_DEV_ADDR2 0xA2
> +#define I40E_MODULE_TYPE_ADDR 0x00
> +#define I40E_MODULE_REVISION_ADDR 0x01
> +#define I40E_MODULE_SFF_8472_COMP 0x5E
> +#define I40E_MODULE_SFF_8472_SWAP 0x5C
> +#define I40E_MODULE_SFF_ADDR_MODE 0x04
> +#define I40E_MODULE_TYPE_QSFP_PLUS 0x0D
> +#define I40E_MODULE_TYPE_QSFP28 0x11
> +#define I40E_MODULE_QSFP_MAX_LEN 640
> +
> /* PCI bus types */
> enum i40e_bus_type {
> i40e_bus_type_unknown = 0,
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 08/12] i40evf: Enable VF to request an alternate queue allocation
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 08/12] i40evf: Enable VF to request an alternate queue allocation Alice Michael
@ 2017-08-07 17:19 ` Shannon Nelson
2017-08-07 17:31 ` Brady, Alan
0 siblings, 1 reply; 19+ messages in thread
From: Shannon Nelson @ 2017-08-07 17:19 UTC (permalink / raw)
To: intel-wired-lan
On 8/4/2017 6:52 AM, Alice Michael wrote:
> From: Alan Brady <alan.brady@intel.com>
>
> Currently the VF gets a default number of allocated queues from HW on
> init and it could choose to enable or disable those allocated queues.
> This makes it such that the VF can request more or less underlying
> allocated queues from the PF.
>
> First the VF negotiates the number of queues it wants that can be
> supported by the PF and if successful asks for a reset. During reset
> the PF will reallocate the HW queues for the VF and will then remap the
> new queues.
>
> Signed-off-by: Alan Brady <alan.brady@intel.com>
> ---
> drivers/net/ethernet/intel/i40evf/i40evf.h | 4 +
> drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 38 ++++++++-
> drivers/net/ethernet/intel/i40evf/i40evf_main.c | 94 ++++++++++++++++++++--
> .../net/ethernet/intel/i40evf/i40evf_virtchnl.c | 44 +++++++++-
> 4 files changed, 173 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h
> index a1af9b1..de0af52 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40evf.h
> +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h
> @@ -102,6 +102,7 @@ struct i40e_vsi {
> #define I40E_TX_CTXTDESC(R, i) \
> (&(((struct i40e_tx_context_desc *)((R)->desc))[i]))
> #define MAX_QUEUES 16
> +#define I40EVF_MAX_REQ_QUEUES 4
Why can you only request 4 queues if a VF can have up to 16 queues?
>
> #define I40EVF_HKEY_ARRAY_SIZE ((I40E_VFQF_HKEY_MAX_INDEX + 1) * 4)
> #define I40EVF_HLUT_ARRAY_SIZE ((I40E_VFQF_HLUT_MAX_INDEX + 1) * 4)
> @@ -200,6 +201,7 @@ struct i40evf_adapter {
> struct list_head vlan_filter_list;
> char misc_vector_name[IFNAMSIZ + 9];
> int num_active_queues;
> + int num_req_queues;
>
> /* TX */
> struct i40e_ring *tx_rings;
> @@ -235,6 +237,7 @@ struct i40evf_adapter {
> #define I40EVF_FLAG_PROMISC_ON BIT(13)
> #define I40EVF_FLAG_ALLMULTI_ON BIT(14)
> #define I40EVF_FLAG_LEGACY_RX BIT(15)
> +#define I40EVF_FLAG_REINIT_ITR_NEEDED BIT(16)
> /* duplicates for common code */
> #define I40E_FLAG_DCB_ENABLED 0
> #define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED
> @@ -349,6 +352,7 @@ void i40evf_deconfigure_queues(struct i40evf_adapter *adapter);
> void i40evf_enable_queues(struct i40evf_adapter *adapter);
> void i40evf_disable_queues(struct i40evf_adapter *adapter);
> void i40evf_map_queues(struct i40evf_adapter *adapter);
> +int i40evf_request_queues(struct i40evf_adapter *adapter, int num);
> void i40evf_add_ether_addrs(struct i40evf_adapter *adapter);
> void i40evf_del_ether_addrs(struct i40evf_adapter *adapter);
> void i40evf_add_vlans(struct i40evf_adapter *adapter);
> diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
> index 65874d6..da006fa 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
> +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
> @@ -669,7 +669,7 @@ static void i40evf_get_channels(struct net_device *netdev,
> struct i40evf_adapter *adapter = netdev_priv(netdev);
>
> /* Report maximum channels */
> - ch->max_combined = adapter->num_active_queues;
> + ch->max_combined = I40EVF_MAX_REQ_QUEUES;
>
> ch->max_other = NONQ_VECS;
> ch->other_count = NONQ_VECS;
> @@ -678,6 +678,41 @@ static void i40evf_get_channels(struct net_device *netdev,
> }
>
> /**
> + * i40evf_set_channels: set the new channel count
> + * @netdev: network interface device structure
> + * @ch: channel information structure
> + *
> + * Negotiate a new number of channels with the PF then do a reset. During
> + * reset we'll realloc queues and fix the RSS table. Returns 0 on success,
> + * negative on failure.
> + **/
> +static int i40evf_set_channels(struct net_device *netdev,
> + struct ethtool_channels *ch)
> +{
> + struct i40evf_adapter *adapter = netdev_priv(netdev);
> + int num_req = ch->combined_count;
> +
> + if (num_req != adapter->num_active_queues &&
> + !(adapter->vf_res->vf_cap_flags &
> + VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)) {
> + dev_info(&adapter->pdev->dev, "PF is not capable of queue negotiation.\n");
> + return -EINVAL;
> + }
> +
> + /* All of these should have already been checked by ethtool before this
> + * even gets to us, but just to be sure.
> + */
> + if (num_req <= 0 || num_req > I40EVF_MAX_REQ_QUEUES)
> + return -EINVAL;
> +
> + if (ch->rx_count || ch->tx_count || ch->other_count != NONQ_VECS)
> + return -EINVAL;
> +
> + adapter->num_req_queues = num_req;
> + return i40evf_request_queues(adapter, num_req);
> +}
> +
> +/**
> * i40evf_get_rxfh_key_size - get the RSS hash key size
> * @netdev: network interface device structure
> *
> @@ -785,6 +820,7 @@ static const struct ethtool_ops i40evf_ethtool_ops = {
> .get_rxfh = i40evf_get_rxfh,
> .set_rxfh = i40evf_set_rxfh,
> .get_channels = i40evf_get_channels,
> + .set_channels = i40evf_set_channels,
> .get_rxfh_key_size = i40evf_get_rxfh_key_size,
> .get_link_ksettings = i40evf_get_link_ksettings,
> };
> diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
> index a216fd2..a803c6b 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
> +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
> @@ -1189,9 +1189,18 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter)
> {
> int i, num_active_queues;
>
> - num_active_queues = min_t(int,
> - adapter->vsi_res->num_queue_pairs,
> - (int)(num_online_cpus()));
> + /* If we're in reset reallocating queues we don't actually know yet for
> + * certain the PF gave us the number of queues we asked for but we'll
> + * assume it did. Once basic reset is finished we'll confirm once we
> + * start negotiating config with PF.
> + */
> + if (adapter->num_req_queues)
> + num_active_queues = adapter->num_req_queues;
> + else
> + num_active_queues = min_t(int,
> + adapter->vsi_res->num_queue_pairs,
> + (int)(num_online_cpus()));
> +
>
> adapter->tx_rings = kcalloc(num_active_queues,
> sizeof(struct i40e_ring), GFP_KERNEL);
> @@ -1540,6 +1549,48 @@ static void i40evf_free_rss(struct i40evf_adapter *adapter)
> }
>
> /**
> + * i40evf_reinit_interrupt_scheme - Reallocate queues and vectors
> + * @adapter: board private structure
> + *
> + * Returns 0 on success, negative on failure
> + **/
> +static int i40evf_reinit_interrupt_scheme(struct i40evf_adapter *adapter)
> +{
> + struct net_device *netdev = adapter->netdev;
> + int err;
> +
> + if (netif_running(netdev))
> + i40evf_free_traffic_irqs(adapter);
> + i40evf_free_misc_irq(adapter);
> + i40evf_reset_interrupt_capability(adapter);
> + i40evf_free_q_vectors(adapter);
> + i40evf_free_queues(adapter);
> +
> + err = i40evf_init_interrupt_scheme(adapter);
> + if (err)
> + goto err;
> +
> + netif_tx_stop_all_queues(netdev);
> +
> + err = i40evf_request_misc_irq(adapter);
> + if (err)
> + goto err;
> +
> + set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
> +
> + err = i40evf_map_rings_to_vectors(adapter);
> + if (err)
> + goto err;
> +
> + if (RSS_AQ(adapter))
> + adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_RSS;
> + else
> + err = i40evf_init_rss(adapter);
> +err:
> + return err;
> +}
> +
> +/**
> * i40evf_watchdog_timer - Periodic call-back timer
> * @data: pointer to adapter disguised as unsigned long
> **/
> @@ -1885,8 +1936,15 @@ static void i40evf_reset_task(struct work_struct *work)
> if (err)
> dev_info(&adapter->pdev->dev, "Failed to init adminq: %d\n",
> err);
> + adapter->aq_required = 0;
>
> - adapter->aq_required = I40EVF_FLAG_AQ_GET_CONFIG;
> + if (adapter->flags & I40EVF_FLAG_REINIT_ITR_NEEDED) {
> + err = i40evf_reinit_interrupt_scheme(adapter);
> + if (err)
> + goto reset_err;
> + }
> +
> + adapter->aq_required |= I40EVF_FLAG_AQ_GET_CONFIG;
> adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
>
> /* re-add all MAC filters */
> @@ -1916,6 +1974,15 @@ static void i40evf_reset_task(struct work_struct *work)
> if (err)
> goto reset_err;
>
> + if (adapter->flags & I40EVF_FLAG_REINIT_ITR_NEEDED) {
> + err = i40evf_request_traffic_irqs(adapter,
> + netdev->name);
> + if (err)
> + goto reset_err;
> +
> + adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
> + }
> +
> i40evf_configure(adapter);
>
> i40evf_up_complete(adapter);
> @@ -2432,9 +2499,9 @@ static int i40evf_check_reset_complete(struct i40e_hw *hw)
> int i40evf_process_config(struct i40evf_adapter *adapter)
> {
> struct virtchnl_vf_resource *vfres = adapter->vf_res;
> + int i, num_req_queues = adapter->num_req_queues;
> struct net_device *netdev = adapter->netdev;
> struct i40e_vsi *vsi = &adapter->vsi;
> - int i;
> netdev_features_t hw_enc_features;
> netdev_features_t hw_features;
>
> @@ -2448,6 +2515,23 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
> return -ENODEV;
> }
>
> + if (num_req_queues &&
> + num_req_queues != adapter->vsi_res->num_queue_pairs) {
> + /* Problem. The PF gave us fewer queues than what we had
> + * negotiated in our request. Need a reset to see if we can't
> + * get back to a working state.
> + */
> + dev_err(&adapter->pdev->dev,
> + "Requested %d queues, but PF only gave us %d.\n",
> + num_req_queues,
> + adapter->vsi_res->num_queue_pairs);
> + adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
> + adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
> + i40evf_schedule_reset(adapter);
> + return -ENODEV;
> + }
> + adapter->num_req_queues = 0;
> +
> hw_enc_features = NETIF_F_SG |
> NETIF_F_IP_CSUM |
> NETIF_F_IPV6_CSUM |
> diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
> index 2bb0fe0..2bb81c3 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
> +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
> @@ -160,7 +160,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
> VIRTCHNL_VF_OFFLOAD_WB_ON_ITR |
> VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 |
> VIRTCHNL_VF_OFFLOAD_ENCAP |
> - VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM;
> + VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
> + VIRTCHNL_VF_OFFLOAD_REQ_QUEUES;
>
> adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
> adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG;
> @@ -385,6 +386,32 @@ void i40evf_map_queues(struct i40evf_adapter *adapter)
> }
>
> /**
> + * i40evf_request_queues
> + * @adapter: adapter structure
> + * @num: number of requested queues
> + *
> + * We get a default number of queues from the PF. This enables us to request a
> + * different number. Returns 0 on success, negative on failure
> + **/
> +int i40evf_request_queues(struct i40evf_adapter *adapter, int num)
> +{
> + struct virtchnl_vf_res_request vfres;
> +
> + if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
> + /* bail because we already have a command pending */
> + dev_err(&adapter->pdev->dev, "Cannot request queues, command %d pending\n",
> + adapter->current_op);
> + return -EBUSY;
> + }
> +
> + vfres.num_queue_pairs = num;
> +
> + adapter->current_op = VIRTCHNL_OP_REQUEST_QUEUES;
> + return i40evf_send_pf_msg(adapter, VIRTCHNL_OP_REQUEST_QUEUES,
> + (u8 *)&vfres, sizeof(vfres));
> +}
> +
> +/**
> * i40evf_add_ether_addrs
> * @adapter: adapter structure
> * @addrs: the MAC address filters to add (contiguous)
> @@ -1068,6 +1095,21 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
> "Invalid message %d from PF\n", v_opcode);
> }
> break;
> + case VIRTCHNL_OP_REQUEST_QUEUES: {
> + struct virtchnl_vf_res_request *vfres =
> + (struct virtchnl_vf_res_request *)msg;
> + if (vfres->num_queue_pairs == adapter->num_req_queues) {
> + adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
> + i40evf_schedule_reset(adapter);
> + } else {
> + dev_info(&adapter->pdev->dev,
> + "Requested %d queues, PF can support %d\n",
> + adapter->num_req_queues,
> + vfres->num_queue_pairs);
> + adapter->num_req_queues = 0;
> + }
> + }
> + break;
> default:
> if (adapter->current_op && (v_opcode != adapter->current_op))
> dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 08/12] i40evf: Enable VF to request an alternate queue allocation
2017-08-07 17:19 ` Shannon Nelson
@ 2017-08-07 17:31 ` Brady, Alan
2017-08-07 17:40 ` Shannon Nelson
0 siblings, 1 reply; 19+ messages in thread
From: Brady, Alan @ 2017-08-07 17:31 UTC (permalink / raw)
To: intel-wired-lan
> -----Original Message-----
> From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of
> Shannon Nelson
> Sent: Monday, August 7, 2017 10:19 AM
> To: Michael, Alice <alice.michael@intel.com>; intel-wired-lan at lists.osuosl.org
> Subject: Re: [Intel-wired-lan] [next PATCH S78-V4 08/12] i40evf: Enable VF to
> request an alternate queue allocation
>
> On 8/4/2017 6:52 AM, Alice Michael wrote:
> > From: Alan Brady <alan.brady@intel.com>
> >
> > Currently the VF gets a default number of allocated queues from HW on
> > init and it could choose to enable or disable those allocated queues.
> > This makes it such that the VF can request more or less underlying
> > allocated queues from the PF.
> >
> > First the VF negotiates the number of queues it wants that can be
> > supported by the PF and if successful asks for a reset. During reset
> > the PF will reallocate the HW queues for the VF and will then remap
> > the new queues.
> >
> > Signed-off-by: Alan Brady <alan.brady@intel.com>
> > ---
> > drivers/net/ethernet/intel/i40evf/i40evf.h | 4 +
> > drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 38 ++++++++-
> > drivers/net/ethernet/intel/i40evf/i40evf_main.c | 94
> ++++++++++++++++++++--
> > .../net/ethernet/intel/i40evf/i40evf_virtchnl.c | 44 +++++++++-
> > 4 files changed, 173 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h
> > b/drivers/net/ethernet/intel/i40evf/i40evf.h
> > index a1af9b1..de0af52 100644
> > --- a/drivers/net/ethernet/intel/i40evf/i40evf.h
> > +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h
> > @@ -102,6 +102,7 @@ struct i40e_vsi {
> > #define I40E_TX_CTXTDESC(R, i) \
> > (&(((struct i40e_tx_context_desc *)((R)->desc))[i]))
> > #define MAX_QUEUES 16
> > +#define I40EVF_MAX_REQ_QUEUES 4
>
> Why can you only request 4 queues if a VF can have up to 16 queues?
>
Hey Shannon,
Thanks for the feedback. So the differentiation here comes down to vectors. The hardware can support up to 16 queues for a VF, but currently we're limited to 4 traffic vectors (+1 misc vector). So we want to limit the user's ability to request more queues than that as it provides no benefit to have more queues than vectors with just RSS. However, there are other features which can use more than 4 queues and the differentiation should become clearer with future patches.
> [...]
-ATB
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Intel-wired-lan] [next PATCH S78-V4 08/12] i40evf: Enable VF to request an alternate queue allocation
2017-08-07 17:31 ` Brady, Alan
@ 2017-08-07 17:40 ` Shannon Nelson
0 siblings, 0 replies; 19+ messages in thread
From: Shannon Nelson @ 2017-08-07 17:40 UTC (permalink / raw)
To: intel-wired-lan
On 8/7/2017 10:31 AM, Brady, Alan wrote:
>> -----Original Message-----
>> From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of
>> Shannon Nelson
>> Sent: Monday, August 7, 2017 10:19 AM
>> To: Michael, Alice <alice.michael@intel.com>; intel-wired-lan at lists.osuosl.org
>> Subject: Re: [Intel-wired-lan] [next PATCH S78-V4 08/12] i40evf: Enable VF to
>> request an alternate queue allocation
>>
>> On 8/4/2017 6:52 AM, Alice Michael wrote:
>>> From: Alan Brady <alan.brady@intel.com>
>>>
>>> Currently the VF gets a default number of allocated queues from HW on
>>> init and it could choose to enable or disable those allocated queues.
>>> This makes it such that the VF can request more or less underlying
>>> allocated queues from the PF.
>>>
>>> First the VF negotiates the number of queues it wants that can be
>>> supported by the PF and if successful asks for a reset. During reset
>>> the PF will reallocate the HW queues for the VF and will then remap
>>> the new queues.
>>>
>>> Signed-off-by: Alan Brady <alan.brady@intel.com>
>>> ---
>>> drivers/net/ethernet/intel/i40evf/i40evf.h | 4 +
>>> drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 38 ++++++++-
>>> drivers/net/ethernet/intel/i40evf/i40evf_main.c | 94
>> ++++++++++++++++++++--
>>> .../net/ethernet/intel/i40evf/i40evf_virtchnl.c | 44 +++++++++-
>>> 4 files changed, 173 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h
>>> b/drivers/net/ethernet/intel/i40evf/i40evf.h
>>> index a1af9b1..de0af52 100644
>>> --- a/drivers/net/ethernet/intel/i40evf/i40evf.h
>>> +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h
>>> @@ -102,6 +102,7 @@ struct i40e_vsi {
>>> #define I40E_TX_CTXTDESC(R, i) \
>>> (&(((struct i40e_tx_context_desc *)((R)->desc))[i]))
>>> #define MAX_QUEUES 16
>>> +#define I40EVF_MAX_REQ_QUEUES 4
>>
>> Why can you only request 4 queues if a VF can have up to 16 queues?
>>
>
> Hey Shannon,
>
> Thanks for the feedback. So the differentiation here comes down to vectors. The hardware can support up to 16 queues for a VF, but currently we're limited to 4 traffic vectors (+1 misc vector). So we want to limit the user's ability to request more queues than that as it provides no benefit to have more queues than vectors with just RSS. However, there are other features which can use more than 4 queues and the differentiation should become clearer with future patches.
You might stick a little comment in there, something like
#define I40EVF_MAX_REQ_QUEUES 4 /* no more than irq's available */
sln
>
>> [...]
>
> -ATB
>
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2017-08-07 17:40 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-04 13:52 [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 02/12] i40e: Fix reporting of supported link modes Alice Michael
2017-08-07 17:18 ` Shannon Nelson
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 03/12] i40e: Add support for 'ethtool -m' Alice Michael
2017-08-07 17:19 ` Shannon Nelson
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 04/12] i40e: don't hold spinlock while resetting VF Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 05/12] i40e: drop i40e_pf *pf from i40e_vc_disable_vf() Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 06/12] i40e: make use of i40e_vc_disable_vf Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 07/12] i40e: ensure reset occurs when disabling VF Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 08/12] i40evf: Enable VF to request an alternate queue allocation Alice Michael
2017-08-07 17:19 ` Shannon Nelson
2017-08-07 17:31 ` Brady, Alan
2017-08-07 17:40 ` Shannon Nelson
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 09/12] i40e: make i40evf_map_rings_to_vectors void Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 10/12] i40e: fix handling of vf_states variable Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 11/12] i40e: fix client notify of VF reset Alice Michael
2017-08-04 13:52 ` [Intel-wired-lan] [next PATCH S78-V4 12/12] i40e: Stop dropping 802.1ad tags (eth proto 0x88a8) Alice Michael
2017-08-06 7:02 ` [Intel-wired-lan] [next PATCH S78-V4 01/12] i40e: use admin queue for setting LEDs behavior kbuild test robot
2017-08-07 17:18 ` Shannon Nelson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.