* [PATCH v2 net-next 4/7] qede: Add ethtool support for Energy efficient ethernet.
From: Manish Chopra @ 2017-07-26 13:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Yuval.Mintz, rahul.verma, sudarsana.kalluru
In-Reply-To: <20170726130715.12976-1-manish.chopra@cavium.com>
From: Sudarsana Reddy Kalluru <sudarsana.kalluru@cavium.com>
The patch adds ethtool callback implementations for querying/configuring
the Energy Efficient Ethernet (EEE) parameters.
Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Yuval Mintz <yuval.mintz@cavium.com>
---
drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 84 +++++++++++++++++++++++
1 files changed, 84 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index e31266d..55fa2ef 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -1631,6 +1631,87 @@ static int qede_get_tunable(struct net_device *dev,
return 0;
}
+static int qede_get_eee(struct net_device *dev, struct ethtool_eee *edata)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+ struct qed_link_output current_link;
+
+ memset(¤t_link, 0, sizeof(current_link));
+ edev->ops->common->get_link(edev->cdev, ¤t_link);
+
+ if (!current_link.eee_supported) {
+ DP_INFO(edev, "EEE is not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (current_link.eee.adv_caps & QED_EEE_1G_ADV)
+ edata->advertised = ADVERTISED_1000baseT_Full;
+ if (current_link.eee.adv_caps & QED_EEE_10G_ADV)
+ edata->advertised |= ADVERTISED_10000baseT_Full;
+ if (current_link.sup_caps & QED_EEE_1G_ADV)
+ edata->supported = ADVERTISED_1000baseT_Full;
+ if (current_link.sup_caps & QED_EEE_10G_ADV)
+ edata->supported |= ADVERTISED_10000baseT_Full;
+ if (current_link.eee.lp_adv_caps & QED_EEE_1G_ADV)
+ edata->lp_advertised = ADVERTISED_1000baseT_Full;
+ if (current_link.eee.lp_adv_caps & QED_EEE_10G_ADV)
+ edata->lp_advertised |= ADVERTISED_10000baseT_Full;
+
+ edata->tx_lpi_timer = current_link.eee.tx_lpi_timer;
+ edata->eee_enabled = current_link.eee.enable;
+ edata->tx_lpi_enabled = current_link.eee.tx_lpi_enable;
+ edata->eee_active = current_link.eee_active;
+
+ return 0;
+}
+
+static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+ struct qed_link_output current_link;
+ struct qed_link_params params;
+
+ if (!edev->ops->common->can_link_change(edev->cdev)) {
+ DP_INFO(edev, "Link settings are not allowed to be changed\n");
+ return -EOPNOTSUPP;
+ }
+
+ memset(¤t_link, 0, sizeof(current_link));
+ edev->ops->common->get_link(edev->cdev, ¤t_link);
+
+ if (!current_link.eee_supported) {
+ DP_INFO(edev, "EEE is not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ memset(¶ms, 0, sizeof(params));
+ params.override_flags |= QED_LINK_OVERRIDE_EEE_CONFIG;
+
+ if (!(edata->advertised & (ADVERTISED_1000baseT_Full |
+ ADVERTISED_10000baseT_Full)) ||
+ ((edata->advertised & (ADVERTISED_1000baseT_Full |
+ ADVERTISED_10000baseT_Full)) !=
+ edata->advertised)) {
+ DP_VERBOSE(edev, QED_MSG_DEBUG,
+ "Invalid advertised capabilities %d\n",
+ edata->advertised);
+ return -EINVAL;
+ }
+
+ if (edata->advertised & ADVERTISED_1000baseT_Full)
+ params.eee.adv_caps = QED_EEE_1G_ADV;
+ if (edata->advertised & ADVERTISED_10000baseT_Full)
+ params.eee.adv_caps |= QED_EEE_10G_ADV;
+ params.eee.enable = edata->eee_enabled;
+ params.eee.tx_lpi_enable = edata->tx_lpi_enabled;
+ params.eee.tx_lpi_timer = edata->tx_lpi_timer;
+
+ params.link_up = true;
+ edev->ops->common->set_link(edev->cdev, ¶ms);
+
+ return 0;
+}
+
static const struct ethtool_ops qede_ethtool_ops = {
.get_link_ksettings = qede_get_link_ksettings,
.set_link_ksettings = qede_set_link_ksettings,
@@ -1664,6 +1745,9 @@ static int qede_get_tunable(struct net_device *dev,
.get_channels = qede_get_channels,
.set_channels = qede_set_channels,
.self_test = qede_self_test,
+ .get_eee = qede_get_eee,
+ .set_eee = qede_set_eee,
+
.get_tunable = qede_get_tunable,
.set_tunable = qede_set_tunable,
};
--
1.7.1
^ permalink raw reply related
* [PATCH v2 net-next 3/7] qed: Add support for Energy efficient ethernet.
From: Manish Chopra @ 2017-07-26 13:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Yuval.Mintz, rahul.verma, sudarsana.kalluru
In-Reply-To: <20170726130715.12976-1-manish.chopra@cavium.com>
From: Sudarsana Reddy Kalluru <sudarsana.kalluru@cavium.com>
The patch adds required driver support for reading/configuring the
Energy Efficient Ethernet (EEE) parameters.
Signed-off-by: Sudarsana Reddy Kalluru <sudarsana.kalluru@cavium.com>
Signed-off-by: Yuval Mintz <yuval.mintz@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_dev.c | 72 ++++++++++++++++++++++++++--
drivers/net/ethernet/qlogic/qed/qed_hsi.h | 49 +++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_main.c | 19 +++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 66 +++++++++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 37 +++++++++++++-
include/linux/qed/qed_if.h | 20 ++++++++
6 files changed, 256 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 6c87bed..f545607 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -1684,6 +1684,8 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
"Load request was sent. Load code: 0x%x\n",
load_code);
+ qed_mcp_set_capabilities(p_hwfn, p_hwfn->p_main_ptt);
+
qed_reset_mb_shadow(p_hwfn, p_hwfn->p_main_ptt);
p_hwfn->first_on_engine = (load_code ==
@@ -2472,6 +2474,7 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
u32 port_cfg_addr, link_temp, nvm_cfg_addr, device_capabilities;
u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg;
+ struct qed_mcp_link_capabilities *p_caps;
struct qed_mcp_link_params *link;
/* Read global nvm_cfg address */
@@ -2534,6 +2537,7 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
/* Read default link configuration */
link = &p_hwfn->mcp_info->link_input;
+ p_caps = &p_hwfn->mcp_info->link_capabilities;
port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
offsetof(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]);
link_temp = qed_rd(p_hwfn, p_ptt,
@@ -2588,10 +2592,45 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX);
link->loopback_mode = 0;
- DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
- "Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x\n",
- link->speed.forced_speed, link->speed.advertised_speeds,
- link->speed.autoneg, link->pause.autoneg);
+ if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE) {
+ link_temp = qed_rd(p_hwfn, p_ptt, port_cfg_addr +
+ offsetof(struct nvm_cfg1_port, ext_phy));
+ link_temp &= NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_MASK;
+ link_temp >>= NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_OFFSET;
+ p_caps->default_eee = QED_MCP_EEE_ENABLED;
+ link->eee.enable = true;
+ switch (link_temp) {
+ case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_DISABLED:
+ p_caps->default_eee = QED_MCP_EEE_DISABLED;
+ link->eee.enable = false;
+ break;
+ case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_BALANCED:
+ p_caps->eee_lpi_timer = EEE_TX_TIMER_USEC_BALANCED_TIME;
+ break;
+ case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_AGGRESSIVE:
+ p_caps->eee_lpi_timer =
+ EEE_TX_TIMER_USEC_AGGRESSIVE_TIME;
+ break;
+ case NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_LOW_LATENCY:
+ p_caps->eee_lpi_timer = EEE_TX_TIMER_USEC_LATENCY_TIME;
+ break;
+ }
+
+ link->eee.tx_lpi_timer = p_caps->eee_lpi_timer;
+ link->eee.tx_lpi_enable = link->eee.enable;
+ link->eee.adv_caps = QED_EEE_1G_ADV | QED_EEE_10G_ADV;
+ } else {
+ p_caps->default_eee = QED_MCP_EEE_UNSUPPORTED;
+ }
+
+ DP_VERBOSE(p_hwfn,
+ NETIF_MSG_LINK,
+ "Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x EEE: %02x [%08x usec]\n",
+ link->speed.forced_speed,
+ link->speed.advertised_speeds,
+ link->speed.autoneg,
+ link->pause.autoneg,
+ p_caps->default_eee, p_caps->eee_lpi_timer);
/* Read Multi-function information from shmem */
addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
@@ -2751,6 +2790,27 @@ static void qed_hw_info_port_num(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
qed_hw_info_port_num_ah(p_hwfn, p_ptt);
}
+static void qed_get_eee_caps(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
+{
+ struct qed_mcp_link_capabilities *p_caps;
+ u32 eee_status;
+
+ p_caps = &p_hwfn->mcp_info->link_capabilities;
+ if (p_caps->default_eee == QED_MCP_EEE_UNSUPPORTED)
+ return;
+
+ p_caps->eee_speed_caps = 0;
+ eee_status = qed_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
+ offsetof(struct public_port, eee_status));
+ eee_status = (eee_status & EEE_SUPPORTED_SPEED_MASK) >>
+ EEE_SUPPORTED_SPEED_OFFSET;
+
+ if (eee_status & EEE_1G_SUPPORTED)
+ p_caps->eee_speed_caps |= QED_EEE_1G_ADV;
+ if (eee_status & EEE_10G_ADV)
+ p_caps->eee_speed_caps |= QED_EEE_10G_ADV;
+}
+
static int
qed_get_hw_info(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
@@ -2767,6 +2827,8 @@ static void qed_hw_info_port_num(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
qed_hw_info_port_num(p_hwfn, p_ptt);
+ qed_mcp_get_capabilities(p_hwfn, p_ptt);
+
qed_hw_get_nvm_info(p_hwfn, p_ptt);
rc = qed_int_igu_read_cam(p_hwfn, p_ptt);
@@ -2785,6 +2847,8 @@ static void qed_hw_info_port_num(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
p_hwfn->mcp_info->func_info.ovlan;
qed_mcp_cmd_port_init(p_hwfn, p_ptt);
+
+ qed_get_eee_caps(p_hwfn, p_ptt);
}
if (qed_mcp_is_init(p_hwfn)) {
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index 31fb0bf..3427fe7 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -10825,6 +10825,17 @@ struct eth_phy_cfg {
#define ETH_LOOPBACK_EXT (3)
#define ETH_LOOPBACK_MAC (4)
+ u32 eee_cfg;
+#define EEE_CFG_EEE_ENABLED BIT(0)
+#define EEE_CFG_TX_LPI BIT(1)
+#define EEE_CFG_ADV_SPEED_1G BIT(2)
+#define EEE_CFG_ADV_SPEED_10G BIT(3)
+#define EEE_TX_TIMER_USEC_MASK (0xfffffff0)
+#define EEE_TX_TIMER_USEC_OFFSET 4
+#define EEE_TX_TIMER_USEC_BALANCED_TIME (0xa00)
+#define EEE_TX_TIMER_USEC_AGGRESSIVE_TIME (0x100)
+#define EEE_TX_TIMER_USEC_LATENCY_TIME (0x6000)
+
u32 feature_config_flags;
#define ETH_EEE_MODE_ADV_LPI (1 << 0)
};
@@ -11242,6 +11253,25 @@ struct public_port {
u32 wol_pkt_len;
u32 wol_pkt_details;
struct dcb_dscp_map dcb_dscp_map;
+
+ u32 eee_status;
+#define EEE_ACTIVE_BIT BIT(0)
+#define EEE_LD_ADV_STATUS_MASK 0x000000f0
+#define EEE_LD_ADV_STATUS_OFFSET 4
+#define EEE_1G_ADV BIT(1)
+#define EEE_10G_ADV BIT(2)
+#define EEE_LP_ADV_STATUS_MASK 0x00000f00
+#define EEE_LP_ADV_STATUS_OFFSET 8
+#define EEE_SUPPORTED_SPEED_MASK 0x0000f000
+#define EEE_SUPPORTED_SPEED_OFFSET 12
+#define EEE_1G_SUPPORTED BIT(1)
+#define EEE_10G_SUPPORTED BIT(2)
+
+ u32 eee_remote;
+#define EEE_REMOTE_TW_TX_MASK 0x0000ffff
+#define EEE_REMOTE_TW_TX_OFFSET 0
+#define EEE_REMOTE_TW_RX_MASK 0xffff0000
+#define EEE_REMOTE_TW_RX_OFFSET 16
};
struct public_func {
@@ -11570,6 +11600,9 @@ struct public_drv_mb {
#define DRV_MSG_CODE_GET_PF_RDMA_PROTOCOL 0x002b0000
#define DRV_MSG_CODE_OS_WOL 0x002e0000
+#define DRV_MSG_CODE_FEATURE_SUPPORT 0x00300000
+#define DRV_MSG_CODE_GET_MFW_FEATURE_SUPPORT 0x00310000
+
#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff
u32 drv_mb_param;
@@ -11653,6 +11686,10 @@ struct public_drv_mb {
#define DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT 8
#define DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_MASK 0x0000FF00
+#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_MASK 0x0000FFFF
+#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_OFFSET 0
+#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE 0x00000002
+
u32 fw_mb_header;
#define FW_MSG_CODE_MASK 0xffff0000
#define FW_MSG_CODE_UNSUPPORTED 0x00000000
@@ -11696,6 +11733,9 @@ struct public_drv_mb {
#define FW_MB_PARAM_GET_PF_RDMA_IWARP 0x2
#define FW_MB_PARAM_GET_PF_RDMA_BOTH 0x3
+/* get MFW feature support response */
+#define FW_MB_PARAM_FEATURE_SUPPORT_EEE 0x00000002
+
#define FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR (1 << 0)
u32 drv_pulse_mb;
@@ -11891,7 +11931,16 @@ struct nvm_cfg1_port {
#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX 0x4
u32 phy_cfg;
u32 mgmt_traffic;
+
u32 ext_phy;
+ /* EEE power saving mode */
+#define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_MASK 0x00FF0000
+#define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_OFFSET 16
+#define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_DISABLED 0x0
+#define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_BALANCED 0x1
+#define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_AGGRESSIVE 0x2
+#define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_LOW_LATENCY 0x3
+
u32 mba_cfg1;
u32 mba_cfg2;
u32 vf_cfg;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 1bddf93..0a06683 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -1297,6 +1297,10 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
}
}
+ if (params->override_flags & QED_LINK_OVERRIDE_EEE_CONFIG)
+ memcpy(&link_params->eee, ¶ms->eee,
+ sizeof(link_params->eee));
+
rc = qed_mcp_set_link(hwfn, ptt, params->link_up);
qed_ptt_release(hwfn, ptt);
@@ -1483,6 +1487,21 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE ||
link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE)
if_link->lp_caps |= QED_LM_Asym_Pause_BIT;
+
+ if (link_caps.default_eee == QED_MCP_EEE_UNSUPPORTED) {
+ if_link->eee_supported = false;
+ } else {
+ if_link->eee_supported = true;
+ if_link->eee_active = link.eee_active;
+ if_link->sup_caps = link_caps.eee_speed_caps;
+ /* MFW clears adv_caps on eee disable; use configured value */
+ if_link->eee.adv_caps = link.eee_adv_caps ? link.eee_adv_caps :
+ params.eee.adv_caps;
+ if_link->eee.lp_adv_caps = link.eee_lp_adv_caps;
+ if_link->eee.enable = params.eee.enable;
+ if_link->eee.tx_lpi_enable = params.eee.tx_lpi_enable;
+ if_link->eee.tx_lpi_timer = params.eee.tx_lpi_timer;
+ }
}
static void qed_get_current_link(struct qed_dev *cdev,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 9da9104..c1ecce6 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1097,6 +1097,31 @@ static void qed_mcp_handle_transceiver_change(struct qed_hwfn *p_hwfn,
DP_NOTICE(p_hwfn, "Transceiver is unplugged.\n");
}
+static void qed_mcp_read_eee_config(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct qed_mcp_link_state *p_link)
+{
+ u32 eee_status, val;
+
+ p_link->eee_adv_caps = 0;
+ p_link->eee_lp_adv_caps = 0;
+ eee_status = qed_rd(p_hwfn,
+ p_ptt,
+ p_hwfn->mcp_info->port_addr +
+ offsetof(struct public_port, eee_status));
+ p_link->eee_active = !!(eee_status & EEE_ACTIVE_BIT);
+ val = (eee_status & EEE_LD_ADV_STATUS_MASK) >> EEE_LD_ADV_STATUS_OFFSET;
+ if (val & EEE_1G_ADV)
+ p_link->eee_adv_caps |= QED_EEE_1G_ADV;
+ if (val & EEE_10G_ADV)
+ p_link->eee_adv_caps |= QED_EEE_10G_ADV;
+ val = (eee_status & EEE_LP_ADV_STATUS_MASK) >> EEE_LP_ADV_STATUS_OFFSET;
+ if (val & EEE_1G_ADV)
+ p_link->eee_lp_adv_caps |= QED_EEE_1G_ADV;
+ if (val & EEE_10G_ADV)
+ p_link->eee_lp_adv_caps |= QED_EEE_10G_ADV;
+}
+
static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, bool b_reset)
{
@@ -1228,6 +1253,9 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn,
p_link->sfp_tx_fault = !!(status & LINK_STATUS_SFP_TX_FAULT);
+ if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE)
+ qed_mcp_read_eee_config(p_hwfn, p_ptt, p_link);
+
qed_link_update(p_hwfn);
out:
spin_unlock_bh(&p_hwfn->mcp_info->link_lock);
@@ -1251,6 +1279,19 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up)
phy_cfg.pause |= (params->pause.forced_tx) ? ETH_PAUSE_TX : 0;
phy_cfg.adv_speed = params->speed.advertised_speeds;
phy_cfg.loopback_mode = params->loopback_mode;
+ if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE) {
+ if (params->eee.enable)
+ phy_cfg.eee_cfg |= EEE_CFG_EEE_ENABLED;
+ if (params->eee.tx_lpi_enable)
+ phy_cfg.eee_cfg |= EEE_CFG_TX_LPI;
+ if (params->eee.adv_caps & QED_EEE_1G_ADV)
+ phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_1G;
+ if (params->eee.adv_caps & QED_EEE_10G_ADV)
+ phy_cfg.eee_cfg |= EEE_CFG_ADV_SPEED_10G;
+ phy_cfg.eee_cfg |= (params->eee.tx_lpi_timer <<
+ EEE_TX_TIMER_USEC_OFFSET) &
+ EEE_TX_TIMER_USEC_MASK;
+ }
p_hwfn->b_drv_link_init = b_up;
@@ -2822,3 +2863,28 @@ void qed_mcp_resc_lock_default_init(struct qed_resc_lock_params *p_lock,
p_unlock->resource = resource;
}
}
+
+int qed_mcp_get_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
+{
+ u32 mcp_resp;
+ int rc;
+
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GET_MFW_FEATURE_SUPPORT,
+ 0, &mcp_resp, &p_hwfn->mcp_info->capabilities);
+ if (!rc)
+ DP_VERBOSE(p_hwfn, (QED_MSG_SP | NETIF_MSG_PROBE),
+ "MFW supported features: %08x\n",
+ p_hwfn->mcp_info->capabilities);
+
+ return rc;
+}
+
+int qed_mcp_set_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
+{
+ u32 mcp_resp, mcp_param, features;
+
+ features = DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE;
+
+ return qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_FEATURE_SUPPORT,
+ features, &mcp_resp, &mcp_param);
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index af03b36..c7ec239 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -53,15 +53,25 @@ struct qed_mcp_link_pause_params {
bool forced_tx;
};
+enum qed_mcp_eee_mode {
+ QED_MCP_EEE_DISABLED,
+ QED_MCP_EEE_ENABLED,
+ QED_MCP_EEE_UNSUPPORTED
+};
+
struct qed_mcp_link_params {
- struct qed_mcp_link_speed_params speed;
- struct qed_mcp_link_pause_params pause;
- u32 loopback_mode;
+ struct qed_mcp_link_speed_params speed;
+ struct qed_mcp_link_pause_params pause;
+ u32 loopback_mode;
+ struct qed_link_eee_params eee;
};
struct qed_mcp_link_capabilities {
u32 speed_capabilities;
bool default_speed_autoneg;
+ enum qed_mcp_eee_mode default_eee;
+ u32 eee_lpi_timer;
+ u8 eee_speed_caps;
};
struct qed_mcp_link_state {
@@ -102,6 +112,9 @@ struct qed_mcp_link_state {
u8 partner_adv_pause;
bool sfp_tx_fault;
+ bool eee_active;
+ u8 eee_adv_caps;
+ u8 eee_lp_adv_caps;
};
struct qed_mcp_function_info {
@@ -546,6 +559,9 @@ struct qed_mcp_info {
u8 *mfw_mb_shadow;
u16 mfw_mb_length;
u32 mcp_hist;
+
+ /* Capabilties negotiated with the MFW */
+ u32 capabilities;
};
struct qed_mcp_mb_params {
@@ -925,5 +941,20 @@ void qed_mcp_resc_lock_default_init(struct qed_resc_lock_params *p_lock,
struct qed_resc_unlock_params *p_unlock,
enum qed_resc_lock
resource, bool b_is_permanent);
+/**
+ * @brief Learn of supported MFW features; To be done during early init
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ */
+int qed_mcp_get_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
+/**
+ * @brief Inform MFW of set of features supported by driver. Should be done
+ * inside the content of the LOAD_REQ.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ */
+int qed_mcp_set_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
#endif
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index ef39c7f..9f32762 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -161,6 +161,18 @@ enum qed_nvm_images {
QED_NVM_IMAGE_FCOE_CFG,
};
+struct qed_link_eee_params {
+ u32 tx_lpi_timer;
+#define QED_EEE_1G_ADV BIT(0)
+#define QED_EEE_10G_ADV BIT(1)
+
+ /* Capabilities are represented using QED_EEE_*_ADV values */
+ u8 adv_caps;
+ u8 lp_adv_caps;
+ bool enable;
+ bool tx_lpi_enable;
+};
+
enum qed_led_mode {
QED_LED_MODE_OFF,
QED_LED_MODE_ON,
@@ -408,6 +420,7 @@ struct qed_link_params {
#define QED_LINK_OVERRIDE_SPEED_FORCED_SPEED BIT(2)
#define QED_LINK_OVERRIDE_PAUSE_CONFIG BIT(3)
#define QED_LINK_OVERRIDE_LOOPBACK_MODE BIT(4)
+#define QED_LINK_OVERRIDE_EEE_CONFIG BIT(5)
u32 override_flags;
bool autoneg;
u32 adv_speeds;
@@ -422,6 +435,7 @@ struct qed_link_params {
#define QED_LINK_LOOPBACK_EXT BIT(3)
#define QED_LINK_LOOPBACK_MAC BIT(4)
u32 loopback_mode;
+ struct qed_link_eee_params eee;
};
struct qed_link_output {
@@ -437,6 +451,12 @@ struct qed_link_output {
u8 port; /* In PORT defs */
bool autoneg;
u32 pause_config;
+
+ /* EEE - capability & param */
+ bool eee_supported;
+ bool eee_active;
+ u8 sup_caps;
+ struct qed_link_eee_params eee;
};
struct qed_probe_params {
--
1.7.1
^ permalink raw reply related
* [PATCH v2 net-next 2/7] qed/qede: Add setter APIs support for RX flow classification
From: Manish Chopra @ 2017-07-26 13:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Yuval.Mintz, rahul.verma, sudarsana.kalluru
In-Reply-To: <20170726130715.12976-1-manish.chopra@cavium.com>
This patch adds support for adding and deleting rx flow
classification rules. Using this user can classify RX flow
constituting of TCP/UDP 4-tuples [src_ip/dst_ip and src_port/dst_port]
to be steered on a given RX queue
Signed-off-by: Manish Chopra <manish.chopra@cavium.com>
Signed-off-by: Yuval Mintz <yuval.mintz@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_main.c | 8 -
drivers/net/ethernet/qlogic/qede/qede.h | 11 +-
drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 14 +-
drivers/net/ethernet/qlogic/qede/qede_filter.c | 365 ++++++++++++++++++++---
drivers/net/ethernet/qlogic/qede/qede_main.c | 9 +-
5 files changed, 347 insertions(+), 60 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index b113996..1bddf93 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -954,9 +954,7 @@ static int qed_slowpath_start(struct qed_dev *cdev,
struct qed_tunnel_info tunn_info;
const u8 *data = NULL;
struct qed_hwfn *hwfn;
-#ifdef CONFIG_RFS_ACCEL
struct qed_ptt *p_ptt;
-#endif
int rc = -EINVAL;
if (qed_iov_wq_start(cdev))
@@ -972,7 +970,6 @@ static int qed_slowpath_start(struct qed_dev *cdev,
goto err;
}
-#ifdef CONFIG_RFS_ACCEL
if (cdev->num_hwfns == 1) {
p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev));
if (p_ptt) {
@@ -983,7 +980,6 @@ static int qed_slowpath_start(struct qed_dev *cdev,
goto err;
}
}
-#endif
}
cdev->rx_coalesce_usecs = QED_DEFAULT_RX_USECS;
@@ -1091,12 +1087,10 @@ static int qed_slowpath_start(struct qed_dev *cdev,
if (IS_PF(cdev))
release_firmware(cdev->firmware);
-#ifdef CONFIG_RFS_ACCEL
if (IS_PF(cdev) && (cdev->num_hwfns == 1) &&
QED_LEADING_HWFN(cdev)->p_arfs_ptt)
qed_ptt_release(QED_LEADING_HWFN(cdev),
QED_LEADING_HWFN(cdev)->p_arfs_ptt);
-#endif
qed_iov_wq_stop(cdev, false);
@@ -1111,11 +1105,9 @@ static int qed_slowpath_stop(struct qed_dev *cdev)
qed_ll2_dealloc_if(cdev);
if (IS_PF(cdev)) {
-#ifdef CONFIG_RFS_ACCEL
if (cdev->num_hwfns == 1)
qed_ptt_release(QED_LEADING_HWFN(cdev),
QED_LEADING_HWFN(cdev)->p_arfs_ptt);
-#endif
qed_free_stream_mem(cdev);
if (IS_QED_ETH_IF(cdev))
qed_sriov_disable(cdev, true);
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index 0a2475b..adb7005 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -447,16 +447,17 @@ struct qede_fastpath {
#ifdef CONFIG_RFS_ACCEL
int qede_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
u16 rxq_index, u32 flow_id);
+#define QEDE_SP_ARFS_CONFIG 4
+#define QEDE_SP_TASK_POLL_DELAY (5 * HZ)
+#endif
+
void qede_process_arfs_filters(struct qede_dev *edev, bool free_fltr);
void qede_poll_for_freeing_arfs_filters(struct qede_dev *edev);
void qede_arfs_filter_op(void *dev, void *filter, u8 fw_rc);
void qede_free_arfs(struct qede_dev *edev);
int qede_alloc_arfs(struct qede_dev *edev);
-
-#define QEDE_SP_ARFS_CONFIG 4
-#define QEDE_SP_TASK_POLL_DELAY (5 * HZ)
-#endif
-
+int qede_add_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info);
+int qede_del_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info);
int qede_get_cls_rule_entry(struct qede_dev *edev, struct ethtool_rxnfc *cmd);
int qede_get_cls_rule_all(struct qede_dev *edev, struct ethtool_rxnfc *info,
u32 *rule_locs);
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index dd39dec..e31266d 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -1182,14 +1182,24 @@ static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
{
struct qede_dev *edev = netdev_priv(dev);
+ int rc;
switch (info->cmd) {
case ETHTOOL_SRXFH:
- return qede_set_rss_flags(edev, info);
+ rc = qede_set_rss_flags(edev, info);
+ break;
+ case ETHTOOL_SRXCLSRLINS:
+ rc = qede_add_cls_rule(edev, info);
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ rc = qede_del_cls_rule(edev, info);
+ break;
default:
DP_INFO(edev, "Command parameters not supported\n");
- return -EOPNOTSUPP;
+ rc = -EOPNOTSUPP;
}
+
+ return rc;
}
static u32 qede_get_rxfh_indir_size(struct net_device *dev)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index a5e5d32..f79e36e 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -75,6 +75,7 @@ struct qede_arfs_fltr_node {
u16 next_rxq_id;
bool filter_op;
bool used;
+ u8 fw_rc;
struct hlist_node node;
};
@@ -92,7 +93,6 @@ struct qede_arfs {
bool enable;
};
-#ifdef CONFIG_RFS_ACCEL
static void qede_configure_arfs_fltr(struct qede_dev *edev,
struct qede_arfs_fltr_node *n,
u16 rxq_id, bool add_fltr)
@@ -122,11 +122,56 @@ static void qede_configure_arfs_fltr(struct qede_dev *edev,
kfree(fltr);
}
+static int
+qede_enqueue_fltr_and_config_searcher(struct qede_dev *edev,
+ struct qede_arfs_fltr_node *fltr,
+ u16 bucket_idx)
+{
+ fltr->mapping = dma_map_single(&edev->pdev->dev, fltr->data,
+ fltr->buf_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(&edev->pdev->dev, fltr->mapping)) {
+ DP_NOTICE(edev, "Failed to map DMA memory for rule\n");
+ qede_free_arfs_filter(edev, fltr);
+ return -ENOMEM;
+ }
+
+ INIT_HLIST_NODE(&fltr->node);
+ hlist_add_head(&fltr->node,
+ QEDE_ARFS_BUCKET_HEAD(edev, bucket_idx));
+ edev->arfs->filter_count++;
+
+ if (edev->arfs->filter_count == 1 && !edev->arfs->enable) {
+ edev->ops->configure_arfs_searcher(edev->cdev, true);
+ edev->arfs->enable = true;
+ }
+
+ return 0;
+}
+
+static void
+qede_dequeue_fltr_and_config_searcher(struct qede_dev *edev,
+ struct qede_arfs_fltr_node *fltr)
+{
+ hlist_del(&fltr->node);
+ dma_unmap_single(&edev->pdev->dev, fltr->mapping,
+ fltr->buf_len, DMA_TO_DEVICE);
+
+ qede_free_arfs_filter(edev, fltr);
+ edev->arfs->filter_count--;
+
+ if (!edev->arfs->filter_count && edev->arfs->enable) {
+ edev->arfs->enable = false;
+ edev->ops->configure_arfs_searcher(edev->cdev, false);
+ }
+}
+
void qede_arfs_filter_op(void *dev, void *filter, u8 fw_rc)
{
struct qede_arfs_fltr_node *fltr = filter;
struct qede_dev *edev = dev;
+ fltr->fw_rc = fw_rc;
+
if (fw_rc) {
DP_NOTICE(edev,
"Failed arfs filter configuration fw_rc=%d, flow_id=%d, sw_id=%d, src_port=%d, dst_port=%d, rxq=%d\n",
@@ -186,18 +231,17 @@ void qede_process_arfs_filters(struct qede_dev *edev, bool free_fltr)
if ((!test_bit(QEDE_FLTR_VALID, &fltr->state) &&
!fltr->used) || free_fltr) {
- hlist_del(&fltr->node);
- dma_unmap_single(&edev->pdev->dev,
- fltr->mapping,
- fltr->buf_len, DMA_TO_DEVICE);
- qede_free_arfs_filter(edev, fltr);
- edev->arfs->filter_count--;
+ qede_dequeue_fltr_and_config_searcher(edev,
+ fltr);
} else {
- if ((rps_may_expire_flow(edev->ndev,
- fltr->rxq_id,
- fltr->flow_id,
- fltr->sw_id) || del) &&
- !free_fltr)
+ bool flow_exp = false;
+#ifdef CONFIG_RFS_ACCEL
+ flow_exp = rps_may_expire_flow(edev->ndev,
+ fltr->rxq_id,
+ fltr->flow_id,
+ fltr->sw_id);
+#endif
+ if ((flow_exp || del) && !free_fltr)
qede_configure_arfs_fltr(edev, fltr,
fltr->rxq_id,
false);
@@ -214,10 +258,12 @@ void qede_process_arfs_filters(struct qede_dev *edev, bool free_fltr)
edev->arfs->enable = false;
edev->ops->configure_arfs_searcher(edev->cdev, false);
}
+#ifdef CONFIG_RFS_ACCEL
} else {
set_bit(QEDE_SP_ARFS_CONFIG, &edev->sp_flags);
schedule_delayed_work(&edev->sp_task,
QEDE_SP_TASK_POLL_DELAY);
+#endif
}
spin_unlock_bh(&edev->arfs->arfs_list_lock);
@@ -259,25 +305,26 @@ int qede_alloc_arfs(struct qede_dev *edev)
spin_lock_init(&edev->arfs->arfs_list_lock);
for (i = 0; i <= QEDE_RFS_FLW_MASK; i++)
- INIT_HLIST_HEAD(&edev->arfs->arfs_hl_head[i]);
+ INIT_HLIST_HEAD(QEDE_ARFS_BUCKET_HEAD(edev, i));
- edev->ndev->rx_cpu_rmap = alloc_irq_cpu_rmap(QEDE_RSS_COUNT(edev));
- if (!edev->ndev->rx_cpu_rmap) {
+ edev->arfs->arfs_fltr_bmap = vzalloc(BITS_TO_LONGS(QEDE_RFS_MAX_FLTR) *
+ sizeof(long));
+ if (!edev->arfs->arfs_fltr_bmap) {
vfree(edev->arfs);
edev->arfs = NULL;
return -ENOMEM;
}
- edev->arfs->arfs_fltr_bmap = vzalloc(BITS_TO_LONGS(QEDE_RFS_MAX_FLTR) *
- sizeof(long));
- if (!edev->arfs->arfs_fltr_bmap) {
- free_irq_cpu_rmap(edev->ndev->rx_cpu_rmap);
- edev->ndev->rx_cpu_rmap = NULL;
+#ifdef CONFIG_RFS_ACCEL
+ edev->ndev->rx_cpu_rmap = alloc_irq_cpu_rmap(QEDE_RSS_COUNT(edev));
+ if (!edev->ndev->rx_cpu_rmap) {
+ vfree(edev->arfs->arfs_fltr_bmap);
+ edev->arfs->arfs_fltr_bmap = NULL;
vfree(edev->arfs);
edev->arfs = NULL;
return -ENOMEM;
}
-
+#endif
return 0;
}
@@ -286,16 +333,19 @@ void qede_free_arfs(struct qede_dev *edev)
if (!edev->arfs)
return;
+#ifdef CONFIG_RFS_ACCEL
if (edev->ndev->rx_cpu_rmap)
free_irq_cpu_rmap(edev->ndev->rx_cpu_rmap);
edev->ndev->rx_cpu_rmap = NULL;
+#endif
vfree(edev->arfs->arfs_fltr_bmap);
edev->arfs->arfs_fltr_bmap = NULL;
vfree(edev->arfs);
edev->arfs = NULL;
}
+#ifdef CONFIG_RFS_ACCEL
static bool qede_compare_ip_addr(struct qede_arfs_fltr_node *tpos,
const struct sk_buff *skb)
{
@@ -395,9 +445,8 @@ int qede_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
spin_lock_bh(&edev->arfs->arfs_list_lock);
- n = qede_arfs_htbl_key_search(&edev->arfs->arfs_hl_head[tbl_idx],
+ n = qede_arfs_htbl_key_search(QEDE_ARFS_BUCKET_HEAD(edev, tbl_idx),
skb, ports[0], ports[1], ip_proto);
-
if (n) {
/* Filter match */
n->next_rxq_id = rxq_index;
@@ -449,23 +498,9 @@ int qede_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
n->tuple.ip_proto = ip_proto;
memcpy(n->data + ETH_HLEN, skb->data, skb_headlen(skb));
- n->mapping = dma_map_single(&edev->pdev->dev, n->data,
- n->buf_len, DMA_TO_DEVICE);
- if (dma_mapping_error(&edev->pdev->dev, n->mapping)) {
- DP_NOTICE(edev, "Failed to map DMA memory for arfs\n");
- qede_free_arfs_filter(edev, n);
- rc = -ENOMEM;
+ rc = qede_enqueue_fltr_and_config_searcher(edev, n, tbl_idx);
+ if (rc)
goto ret_unlock;
- }
-
- INIT_HLIST_NODE(&n->node);
- hlist_add_head(&n->node, &edev->arfs->arfs_hl_head[tbl_idx]);
- edev->arfs->filter_count++;
-
- if (edev->arfs->filter_count == 1 && !edev->arfs->enable) {
- edev->ops->configure_arfs_searcher(edev->cdev, true);
- edev->arfs->enable = true;
- }
qede_configure_arfs_fltr(edev, n, n->rxq_id, true);
@@ -473,6 +508,7 @@ int qede_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
set_bit(QEDE_SP_ARFS_CONFIG, &edev->sp_flags);
schedule_delayed_work(&edev->sp_task, 0);
+
return n->sw_id;
ret_unlock:
@@ -1277,6 +1313,38 @@ void qede_config_rx_mode(struct net_device *ndev)
return NULL;
}
+static bool
+qede_compare_user_flow_ips(struct qede_arfs_fltr_node *tpos,
+ struct ethtool_rx_flow_spec *fsp,
+ __be16 proto)
+{
+ if (proto == htons(ETH_P_IP)) {
+ struct ethtool_tcpip4_spec *ip;
+
+ ip = &fsp->h_u.tcp_ip4_spec;
+
+ if (tpos->tuple.src_ipv4 == ip->ip4src &&
+ tpos->tuple.dst_ipv4 == ip->ip4dst)
+ return true;
+ else
+ return false;
+ } else {
+ struct ethtool_tcpip6_spec *ip6;
+ struct in6_addr *src;
+
+ ip6 = &fsp->h_u.tcp_ip6_spec;
+ src = &tpos->tuple.src_ipv6;
+
+ if (!memcmp(src, &ip6->ip6src, sizeof(struct in6_addr)) &&
+ !memcmp(&tpos->tuple.dst_ipv6, &ip6->ip6dst,
+ sizeof(struct in6_addr)))
+ return true;
+ else
+ return false;
+ }
+ return false;
+}
+
int qede_get_cls_rule_all(struct qede_dev *edev, struct ethtool_rxnfc *info,
u32 *rule_locs)
{
@@ -1366,6 +1434,225 @@ int qede_get_cls_rule_entry(struct qede_dev *edev, struct ethtool_rxnfc *cmd)
return rc;
}
+static int
+qede_validate_and_check_flow_exist(struct qede_dev *edev,
+ struct ethtool_rx_flow_spec *fsp,
+ int *min_hlen)
+{
+ __be16 src_port = 0x0, dst_port = 0x0;
+ struct qede_arfs_fltr_node *fltr;
+ struct hlist_node *temp;
+ struct hlist_head *head;
+ __be16 eth_proto;
+ u8 ip_proto;
+
+ if (fsp->location >= QEDE_RFS_MAX_FLTR ||
+ fsp->ring_cookie >= QEDE_RSS_COUNT(edev))
+ return -EINVAL;
+
+ if (fsp->flow_type == TCP_V4_FLOW) {
+ *min_hlen += sizeof(struct iphdr) +
+ sizeof(struct tcphdr);
+ eth_proto = htons(ETH_P_IP);
+ ip_proto = IPPROTO_TCP;
+ } else if (fsp->flow_type == UDP_V4_FLOW) {
+ *min_hlen += sizeof(struct iphdr) +
+ sizeof(struct udphdr);
+ eth_proto = htons(ETH_P_IP);
+ ip_proto = IPPROTO_UDP;
+ } else if (fsp->flow_type == TCP_V6_FLOW) {
+ *min_hlen += sizeof(struct ipv6hdr) +
+ sizeof(struct tcphdr);
+ eth_proto = htons(ETH_P_IPV6);
+ ip_proto = IPPROTO_TCP;
+ } else if (fsp->flow_type == UDP_V6_FLOW) {
+ *min_hlen += sizeof(struct ipv6hdr) +
+ sizeof(struct udphdr);
+ eth_proto = htons(ETH_P_IPV6);
+ ip_proto = IPPROTO_UDP;
+ } else {
+ DP_NOTICE(edev, "Unsupported flow type = 0x%x\n",
+ fsp->flow_type);
+ return -EPROTONOSUPPORT;
+ }
+
+ if (eth_proto == htons(ETH_P_IP)) {
+ src_port = fsp->h_u.tcp_ip4_spec.psrc;
+ dst_port = fsp->h_u.tcp_ip4_spec.pdst;
+ } else {
+ src_port = fsp->h_u.tcp_ip6_spec.psrc;
+ dst_port = fsp->h_u.tcp_ip6_spec.pdst;
+ }
+
+ head = QEDE_ARFS_BUCKET_HEAD(edev, 0);
+ hlist_for_each_entry_safe(fltr, temp, head, node) {
+ if ((fltr->tuple.ip_proto == ip_proto &&
+ fltr->tuple.eth_proto == eth_proto &&
+ qede_compare_user_flow_ips(fltr, fsp, eth_proto) &&
+ fltr->tuple.src_port == src_port &&
+ fltr->tuple.dst_port == dst_port) ||
+ fltr->sw_id == fsp->location)
+ return -EEXIST;
+ }
+
+ return 0;
+}
+
+static int
+qede_poll_arfs_filter_config(struct qede_dev *edev,
+ struct qede_arfs_fltr_node *fltr)
+{
+ int count = QEDE_ARFS_POLL_COUNT;
+
+ while (fltr->used && count) {
+ msleep(20);
+ count--;
+ }
+
+ if (count == 0 || fltr->fw_rc) {
+ qede_dequeue_fltr_and_config_searcher(edev, fltr);
+ return -EIO;
+ }
+
+ return fltr->fw_rc;
+}
+
+int qede_add_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info)
+{
+ struct ethtool_rx_flow_spec *fsp = &info->fs;
+ struct qede_arfs_fltr_node *n;
+ int min_hlen = ETH_HLEN, rc;
+ struct ethhdr *eth;
+ struct iphdr *ip;
+ __be16 *ports;
+
+ __qede_lock(edev);
+
+ if (!edev->arfs) {
+ rc = -EPERM;
+ goto unlock;
+ }
+
+ rc = qede_validate_and_check_flow_exist(edev, fsp, &min_hlen);
+ if (rc)
+ goto unlock;
+
+ n = kzalloc(sizeof(*n), GFP_KERNEL);
+ if (!n) {
+ rc = -ENOMEM;
+ goto unlock;
+ }
+
+ n->data = kzalloc(min_hlen, GFP_KERNEL);
+ if (!n->data) {
+ kfree(n);
+ rc = -ENOMEM;
+ goto unlock;
+ }
+
+ n->sw_id = fsp->location;
+ set_bit(n->sw_id, edev->arfs->arfs_fltr_bmap);
+ n->buf_len = min_hlen;
+ n->rxq_id = fsp->ring_cookie;
+ n->next_rxq_id = n->rxq_id;
+ eth = (struct ethhdr *)n->data;
+
+ if (info->fs.flow_type == TCP_V4_FLOW ||
+ info->fs.flow_type == UDP_V4_FLOW) {
+ ports = (__be16 *)(n->data + ETH_HLEN +
+ sizeof(struct iphdr));
+ eth->h_proto = htons(ETH_P_IP);
+ n->tuple.eth_proto = htons(ETH_P_IP);
+ n->tuple.src_ipv4 = info->fs.h_u.tcp_ip4_spec.ip4src;
+ n->tuple.dst_ipv4 = info->fs.h_u.tcp_ip4_spec.ip4dst;
+ n->tuple.src_port = info->fs.h_u.tcp_ip4_spec.psrc;
+ n->tuple.dst_port = info->fs.h_u.tcp_ip4_spec.pdst;
+ ports[0] = n->tuple.src_port;
+ ports[1] = n->tuple.dst_port;
+ ip = (struct iphdr *)(n->data + ETH_HLEN);
+ ip->saddr = info->fs.h_u.tcp_ip4_spec.ip4src;
+ ip->daddr = info->fs.h_u.tcp_ip4_spec.ip4dst;
+ ip->version = 0x4;
+ ip->ihl = 0x5;
+
+ if (info->fs.flow_type == TCP_V4_FLOW) {
+ n->tuple.ip_proto = IPPROTO_TCP;
+ ip->protocol = IPPROTO_TCP;
+ } else {
+ n->tuple.ip_proto = IPPROTO_UDP;
+ ip->protocol = IPPROTO_UDP;
+ }
+ ip->tot_len = cpu_to_be16(min_hlen - ETH_HLEN);
+ } else {
+ struct ipv6hdr *ip6;
+
+ ip6 = (struct ipv6hdr *)(n->data + ETH_HLEN);
+ ports = (__be16 *)(n->data + ETH_HLEN +
+ sizeof(struct ipv6hdr));
+ eth->h_proto = htons(ETH_P_IPV6);
+ n->tuple.eth_proto = htons(ETH_P_IPV6);
+ memcpy(&n->tuple.src_ipv6, &info->fs.h_u.tcp_ip6_spec.ip6src,
+ sizeof(struct in6_addr));
+ memcpy(&n->tuple.dst_ipv6, &info->fs.h_u.tcp_ip6_spec.ip6dst,
+ sizeof(struct in6_addr));
+ n->tuple.src_port = info->fs.h_u.tcp_ip6_spec.psrc;
+ n->tuple.dst_port = info->fs.h_u.tcp_ip6_spec.pdst;
+ ports[0] = n->tuple.src_port;
+ ports[1] = n->tuple.dst_port;
+ memcpy(&ip6->saddr, &n->tuple.src_ipv6,
+ sizeof(struct in6_addr));
+ memcpy(&ip6->daddr, &n->tuple.dst_ipv6,
+ sizeof(struct in6_addr));
+ ip6->version = 0x6;
+
+ if (info->fs.flow_type == TCP_V6_FLOW) {
+ n->tuple.ip_proto = IPPROTO_TCP;
+ ip6->nexthdr = NEXTHDR_TCP;
+ ip6->payload_len = cpu_to_be16(sizeof(struct tcphdr));
+ } else {
+ n->tuple.ip_proto = IPPROTO_UDP;
+ ip6->nexthdr = NEXTHDR_UDP;
+ ip6->payload_len = cpu_to_be16(sizeof(struct udphdr));
+ }
+ }
+
+ rc = qede_enqueue_fltr_and_config_searcher(edev, n, 0);
+ if (rc)
+ goto unlock;
+
+ qede_configure_arfs_fltr(edev, n, n->rxq_id, true);
+ rc = qede_poll_arfs_filter_config(edev, n);
+unlock:
+ __qede_unlock(edev);
+ return rc;
+}
+
+int qede_del_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info)
+{
+ struct ethtool_rx_flow_spec *fsp = &info->fs;
+ struct qede_arfs_fltr_node *fltr = NULL;
+ int rc = -EPERM;
+
+ __qede_lock(edev);
+ if (!edev->arfs)
+ goto unlock;
+
+ fltr = qede_get_arfs_fltr_by_loc(QEDE_ARFS_BUCKET_HEAD(edev, 0),
+ fsp->location);
+ if (!fltr)
+ goto unlock;
+
+ qede_configure_arfs_fltr(edev, fltr, fltr->rxq_id, false);
+
+ rc = qede_poll_arfs_filter_config(edev, fltr);
+ if (rc == 0)
+ qede_dequeue_fltr_and_config_searcher(edev, fltr);
+
+unlock:
+ __qede_unlock(edev);
+ return rc;
+}
+
int qede_get_arfs_filter_count(struct qede_dev *edev)
{
int count = 0;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 06ca13d..e5ee9f2 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -873,9 +873,7 @@ static void qede_update_pf_params(struct qed_dev *cdev)
*/
pf_params.eth_pf_params.num_vf_cons = 48;
-#ifdef CONFIG_RFS_ACCEL
pf_params.eth_pf_params.num_arfs_filters = QEDE_RFS_MAX_FLTR;
-#endif
qed_ops->common->update_pf_params(cdev, &pf_params);
}
@@ -1984,12 +1982,12 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode,
qede_vlan_mark_nonconfigured(edev);
edev->ops->fastpath_stop(edev->cdev);
-#ifdef CONFIG_RFS_ACCEL
+
if (!IS_VF(edev) && edev->dev_info.common.num_hwfns == 1) {
qede_poll_for_freeing_arfs_filters(edev);
qede_free_arfs(edev);
}
-#endif
+
/* Release the interrupts */
qede_sync_free_irqs(edev);
edev->ops->common->set_fp_int(edev->cdev, 0);
@@ -2041,13 +2039,12 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode,
if (rc)
goto err2;
-#ifdef CONFIG_RFS_ACCEL
if (!IS_VF(edev) && edev->dev_info.common.num_hwfns == 1) {
rc = qede_alloc_arfs(edev);
if (rc)
DP_NOTICE(edev, "aRFS memory allocation failed\n");
}
-#endif
+
qede_napi_add_enable(edev);
DP_INFO(edev, "Napi added and enabled\n");
--
1.7.1
^ permalink raw reply related
* [PATCH v2 net-next 1/7] qede: Add getter APIs support for RX flow classification
From: Manish Chopra @ 2017-07-26 13:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Yuval.Mintz, rahul.verma, sudarsana.kalluru
In-Reply-To: <20170726130715.12976-1-manish.chopra@cavium.com>
This patch adds support for ethtool getter APIs to query
RX flow classification rules.
Signed-off-by: Manish Chopra <manish.chopra@cavium.com>
Signed-off-by: Yuval Mintz <yuval.mintz@cavium.com>
---
drivers/net/ethernet/qlogic/qede/qede.h | 10 ++-
drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 22 ++++-
drivers/net/ethernet/qlogic/qede/qede_filter.c | 120 ++++++++++++++++++++++-
3 files changed, 144 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index 4dfb238..0a2475b 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -160,6 +160,8 @@ struct qede_rdma_dev {
struct qede_ptp;
+#define QEDE_RFS_MAX_FLTR 256
+
struct qede_dev {
struct qed_dev *cdev;
struct net_device *ndev;
@@ -241,9 +243,7 @@ struct qede_dev {
u16 vxlan_dst_port;
u16 geneve_dst_port;
-#ifdef CONFIG_RFS_ACCEL
struct qede_arfs *arfs;
-#endif
bool wol_enabled;
struct qede_rdma_dev rdma_info;
@@ -455,9 +455,13 @@ int qede_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
#define QEDE_SP_ARFS_CONFIG 4
#define QEDE_SP_TASK_POLL_DELAY (5 * HZ)
-#define QEDE_RFS_MAX_FLTR 256
#endif
+int qede_get_cls_rule_entry(struct qede_dev *edev, struct ethtool_rxnfc *cmd);
+int qede_get_cls_rule_all(struct qede_dev *edev, struct ethtool_rxnfc *info,
+ u32 *rule_locs);
+int qede_get_arfs_filter_count(struct qede_dev *edev);
+
struct qede_reload_args {
void (*func)(struct qede_dev *edev, struct qede_reload_args *args);
union {
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 6a03d3e..dd39dec 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -1045,20 +1045,34 @@ static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
}
static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
- u32 *rules __always_unused)
+ u32 *rule_locs)
{
struct qede_dev *edev = netdev_priv(dev);
+ int rc = 0;
switch (info->cmd) {
case ETHTOOL_GRXRINGS:
info->data = QEDE_RSS_COUNT(edev);
- return 0;
+ break;
case ETHTOOL_GRXFH:
- return qede_get_rss_flags(edev, info);
+ rc = qede_get_rss_flags(edev, info);
+ break;
+ case ETHTOOL_GRXCLSRLCNT:
+ info->rule_cnt = qede_get_arfs_filter_count(edev);
+ info->data = QEDE_RFS_MAX_FLTR;
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ rc = qede_get_cls_rule_entry(edev, info);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ rc = qede_get_cls_rule_all(edev, info, rule_locs);
+ break;
default:
DP_ERR(edev, "Command parameters not supported\n");
- return -EOPNOTSUPP;
+ rc = -EOPNOTSUPP;
}
+
+ return rc;
}
static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index f939db5..a5e5d32 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -38,7 +38,6 @@
#include <linux/qed/qed_if.h>
#include "qede.h"
-#ifdef CONFIG_RFS_ACCEL
struct qede_arfs_tuple {
union {
__be32 src_ipv4;
@@ -80,6 +79,7 @@ struct qede_arfs_fltr_node {
};
struct qede_arfs {
+#define QEDE_ARFS_BUCKET_HEAD(edev, idx) (&(edev)->arfs->arfs_hl_head[idx])
#define QEDE_ARFS_POLL_COUNT 100
#define QEDE_RFS_FLW_BITSHIFT (4)
#define QEDE_RFS_FLW_MASK ((1 << QEDE_RFS_FLW_BITSHIFT) - 1)
@@ -92,6 +92,7 @@ struct qede_arfs {
bool enable;
};
+#ifdef CONFIG_RFS_ACCEL
static void qede_configure_arfs_fltr(struct qede_dev *edev,
struct qede_arfs_fltr_node *n,
u16 rxq_id, bool add_fltr)
@@ -1263,3 +1264,120 @@ void qede_config_rx_mode(struct net_device *ndev)
out:
kfree(uc_macs);
}
+
+static struct qede_arfs_fltr_node *
+qede_get_arfs_fltr_by_loc(struct hlist_head *head, u32 location)
+{
+ struct qede_arfs_fltr_node *fltr;
+
+ hlist_for_each_entry(fltr, head, node)
+ if (location == fltr->sw_id)
+ return fltr;
+
+ return NULL;
+}
+
+int qede_get_cls_rule_all(struct qede_dev *edev, struct ethtool_rxnfc *info,
+ u32 *rule_locs)
+{
+ struct qede_arfs_fltr_node *fltr;
+ struct hlist_head *head;
+ int cnt = 0, rc = 0;
+
+ info->data = QEDE_RFS_MAX_FLTR;
+
+ __qede_lock(edev);
+
+ if (!edev->arfs) {
+ rc = -EPERM;
+ goto unlock;
+ }
+
+ head = QEDE_ARFS_BUCKET_HEAD(edev, 0);
+
+ hlist_for_each_entry(fltr, head, node) {
+ if (cnt == info->rule_cnt) {
+ rc = -EMSGSIZE;
+ goto unlock;
+ }
+
+ rule_locs[cnt] = fltr->sw_id;
+ cnt++;
+ }
+
+ info->rule_cnt = cnt;
+
+unlock:
+ __qede_unlock(edev);
+ return rc;
+}
+
+int qede_get_cls_rule_entry(struct qede_dev *edev, struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fsp = &cmd->fs;
+ struct qede_arfs_fltr_node *fltr = NULL;
+ int rc = 0;
+
+ cmd->data = QEDE_RFS_MAX_FLTR;
+
+ __qede_lock(edev);
+
+ if (!edev->arfs) {
+ rc = -EPERM;
+ goto unlock;
+ }
+
+ fltr = qede_get_arfs_fltr_by_loc(QEDE_ARFS_BUCKET_HEAD(edev, 0),
+ fsp->location);
+ if (!fltr) {
+ DP_NOTICE(edev, "Rule not found - location=0x%x\n",
+ fsp->location);
+ rc = -EINVAL;
+ goto unlock;
+ }
+
+ if (fltr->tuple.eth_proto == htons(ETH_P_IP)) {
+ if (fltr->tuple.ip_proto == IPPROTO_TCP)
+ fsp->flow_type = TCP_V4_FLOW;
+ else
+ fsp->flow_type = UDP_V4_FLOW;
+
+ fsp->h_u.tcp_ip4_spec.psrc = fltr->tuple.src_port;
+ fsp->h_u.tcp_ip4_spec.pdst = fltr->tuple.dst_port;
+ fsp->h_u.tcp_ip4_spec.ip4src = fltr->tuple.src_ipv4;
+ fsp->h_u.tcp_ip4_spec.ip4dst = fltr->tuple.dst_ipv4;
+ } else {
+ if (fltr->tuple.ip_proto == IPPROTO_TCP)
+ fsp->flow_type = TCP_V6_FLOW;
+ else
+ fsp->flow_type = UDP_V6_FLOW;
+ fsp->h_u.tcp_ip6_spec.psrc = fltr->tuple.src_port;
+ fsp->h_u.tcp_ip6_spec.pdst = fltr->tuple.dst_port;
+ memcpy(&fsp->h_u.tcp_ip6_spec.ip6src,
+ &fltr->tuple.src_ipv6, sizeof(struct in6_addr));
+ memcpy(&fsp->h_u.tcp_ip6_spec.ip6dst,
+ &fltr->tuple.dst_ipv6, sizeof(struct in6_addr));
+ }
+
+ fsp->ring_cookie = fltr->rxq_id;
+
+unlock:
+ __qede_unlock(edev);
+ return rc;
+}
+
+int qede_get_arfs_filter_count(struct qede_dev *edev)
+{
+ int count = 0;
+
+ __qede_lock(edev);
+
+ if (!edev->arfs)
+ goto unlock;
+
+ count = edev->arfs->filter_count;
+
+unlock:
+ __qede_unlock(edev);
+ return count;
+}
--
1.7.1
^ permalink raw reply related
* [PATCH v2 net-next 0/7] qed/qede: Enhancements
From: Manish Chopra @ 2017-07-26 13:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Yuval.Mintz, rahul.verma, sudarsana.kalluru
Hi David,
This patch series adds these below features support in qed/qede
1) Ntuple filter configuration [via ethtool -n/N]
2) EEE (energy efficient ethernet) support [ethtool --set-eee/show-eee]
3) Coalescing configuration support for VFs [via ethtool -c/C]
Please consider applying this to "net-next"
V1->V2:
* Fixes below Kbuild test robot warning.
drivers/net//ethernet/qlogic/qed/qed_l2.c:
In function 'qed_get_queue_coalesce':
drivers/net//ethernet/qlogic/qed/qed_l2.c:2137:8: error:
implicit declaration of function 'qed_vf_pf_get_coalesce'
[-Werror=implicit-function-declaration]
Thanks,
Manish
Manish Chopra (2):
qede: Add getter APIs support for RX flow classification
qed/qede: Add setter APIs support for RX flow classification
Rahul Verma (3):
qed: Add support for vf coalesce configuration.
qed: Read per queue coalesce from hardware
qed: enhanced per queue max coalesce value.
Sudarsana Reddy Kalluru (2):
qed: Add support for Energy efficient ethernet.
qede: Add ethtool support for Energy efficient ethernet.
drivers/net/ethernet/qlogic/qed/qed_dev.c | 145 ++++++--
drivers/net/ethernet/qlogic/qed/qed_dev_api.h | 43 +--
drivers/net/ethernet/qlogic/qed/qed_hsi.h | 49 +++
drivers/net/ethernet/qlogic/qed/qed_l2.c | 115 ++++++
drivers/net/ethernet/qlogic/qed/qed_l2.h | 18 +-
drivers/net/ethernet/qlogic/qed/qed_main.c | 58 +--
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 66 +++
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 37 ++-
drivers/net/ethernet/qlogic/qed/qed_sriov.c | 157 ++++++++
drivers/net/ethernet/qlogic/qed/qed_sriov.h | 3 +
drivers/net/ethernet/qlogic/qed/qed_vf.c | 75 ++++
drivers/net/ethernet/qlogic/qed/qed_vf.h | 53 +++-
drivers/net/ethernet/qlogic/qede/qede.h | 19 +-
drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 205 +++++++++-
drivers/net/ethernet/qlogic/qede/qede_filter.c | 483 +++++++++++++++++++++--
drivers/net/ethernet/qlogic/qede/qede_main.c | 9 +-
include/linux/qed/qed_eth_if.h | 1 +
include/linux/qed/qed_if.h | 37 ++-
18 files changed, 1393 insertions(+), 180 deletions(-)
^ permalink raw reply
* Re: [PATCH net] Revert "vhost: cache used event for better performance"
From: Michael S. Tsirkin @ 2017-07-26 12:57 UTC (permalink / raw)
To: Jason Wang; +Cc: netdev, linux-kernel, kvm, virtualization
In-Reply-To: <1501056197-3368-1-git-send-email-jasowang@redhat.com>
On Wed, Jul 26, 2017 at 04:03:17PM +0800, Jason Wang wrote:
> This reverts commit 809ecb9bca6a9424ccd392d67e368160f8b76c92. Since it
> was reported to break vhost_net. We want to cache used event and use
> it to check for notification. We try to valid cached used event by
> checking whether or not it was ahead of new, but this is not correct
> all the time, it could be stale and there's no way to know about this.
>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
Could you supply a bit more data here please? How does it get stale?
What does guest need to do to make it stale? This will be helpful if
anyone wants to bring it back, or if we want to extend the protocol.
> ---
> drivers/vhost/vhost.c | 28 ++++++----------------------
> drivers/vhost/vhost.h | 3 ---
> 2 files changed, 6 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index e4613a3..9cb3f72 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -308,7 +308,6 @@ static void vhost_vq_reset(struct vhost_dev *dev,
> vq->avail = NULL;
> vq->used = NULL;
> vq->last_avail_idx = 0;
> - vq->last_used_event = 0;
> vq->avail_idx = 0;
> vq->last_used_idx = 0;
> vq->signalled_used = 0;
> @@ -1402,7 +1401,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)
> r = -EINVAL;
> break;
> }
> - vq->last_avail_idx = vq->last_used_event = s.num;
> + vq->last_avail_idx = s.num;
> /* Forget the cached index value. */
> vq->avail_idx = vq->last_avail_idx;
> break;
> @@ -2241,6 +2240,10 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
> __u16 old, new;
> __virtio16 event;
> bool v;
> + /* Flush out used index updates. This is paired
> + * with the barrier that the Guest executes when enabling
> + * interrupts. */
> + smp_mb();
>
> if (vhost_has_feature(vq, VIRTIO_F_NOTIFY_ON_EMPTY) &&
> unlikely(vq->avail_idx == vq->last_avail_idx))
> @@ -2248,10 +2251,6 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
>
> if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) {
> __virtio16 flags;
> - /* Flush out used index updates. This is paired
> - * with the barrier that the Guest executes when enabling
> - * interrupts. */
> - smp_mb();
> if (vhost_get_avail(vq, flags, &vq->avail->flags)) {
> vq_err(vq, "Failed to get flags");
> return true;
> @@ -2266,26 +2265,11 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
> if (unlikely(!v))
> return true;
>
> - /* We're sure if the following conditions are met, there's no
> - * need to notify guest:
> - * 1) cached used event is ahead of new
> - * 2) old to new updating does not cross cached used event. */
> - if (vring_need_event(vq->last_used_event, new + vq->num, new) &&
> - !vring_need_event(vq->last_used_event, new, old))
> - return false;
> -
> - /* Flush out used index updates. This is paired
> - * with the barrier that the Guest executes when enabling
> - * interrupts. */
> - smp_mb();
> -
> if (vhost_get_avail(vq, event, vhost_used_event(vq))) {
> vq_err(vq, "Failed to get used event idx");
> return true;
> }
> - vq->last_used_event = vhost16_to_cpu(vq, event);
> -
> - return vring_need_event(vq->last_used_event, new, old);
> + return vring_need_event(vhost16_to_cpu(vq, event), new, old);
> }
>
> /* This actually signals the guest, using eventfd. */
> diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
> index f720958..bb7c29b 100644
> --- a/drivers/vhost/vhost.h
> +++ b/drivers/vhost/vhost.h
> @@ -115,9 +115,6 @@ struct vhost_virtqueue {
> /* Last index we used. */
> u16 last_used_idx;
>
> - /* Last used evet we've seen */
> - u16 last_used_event;
> -
> /* Used flags */
> u16 used_flags;
>
> --
> 2.7.4
^ permalink raw reply
* (unknown),
From: momofr @ 2017-07-26 12:48 UTC (permalink / raw)
To: netdev
[-- Attachment #1: EMAIL_632952_netdev.zip --]
[-- Type: application/zip, Size: 5704 bytes --]
^ permalink raw reply
* Re: [PATCH V2 net-next 01/21] net-next/hinic: Initialize hw interface
From: Aviad Krawczyk @ 2017-07-26 12:48 UTC (permalink / raw)
To: Francois Romieu
Cc: davem, linux-kernel, netdev, bc.y, victor.gissin, zhaochen6,
tony.qu
In-Reply-To: <20170725200205.GA984@electric-eye.fr.zoreil.com>
OK, we will use module_pci_driver although it is not very common in the same segment.
On 7/25/2017 11:02 PM, Francois Romieu wrote:
> Aviad Krawczyk <aviad.krawczyk@huawei.com> :
> [...]
>> module_pci_driver - is not used in other drivers in the same segments, it
>> is necessary ?
>
> /me checks... Ok, there seems to be some overenthusiastic copy'paste.
>
> See drivers/net/ethernet/intel/ixgb/ixgb_main.c:
> [...]
> /**
> * ixgb_init_module - Driver Registration Routine
> *
> * ixgb_init_module is the first routine called when the driver is
> * loaded. All it does is register with the PCI subsystem.
> **/
>
> static int __init
> ixgb_init_module(void)
> {
> pr_info("%s - version %s\n", ixgb_driver_string, ixgb_driver_version);
> pr_info("%s\n", ixgb_copyright);
>
> return pci_register_driver(&ixgb_driver);
> }
>
> module_init(ixgb_init_module);
>
> /**
> * ixgb_exit_module - Driver Exit Cleanup Routine
> *
> * ixgb_exit_module is called just before the driver is removed
> * from memory.
> **/
>
> static void __exit
> ixgb_exit_module(void)
> {
> pci_unregister_driver(&ixgb_driver);
> }
>
> module_exit(ixgb_exit_module);
>
> Driver version ought to be fed through ethtool, if ever. Copyright message
> mildly contributes to a better world. So the whole stuff above could be:
>
> module_pci_driver(ixgb_driver);
>
^ permalink raw reply
* Re: TCP fast retransmit issues
From: Klavs Klavsen @ 2017-07-26 12:18 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1501069756.12695.11.camel@edumazet-glaptop3.roam.corp.google.com>
the 192.168.32.44 is a Centos 7 box.
Could you help me by elaborating on how to see why the "dup ack" (sack
blocks) are bogus?
Thank you very much. I'll try to capture the same scp done on mac - and
see if it also gets DUP ACK's - and how they look in comparison (since
it works on Mac clients).
Eric Dumazet skrev den 2017-07-26 13:49:
> On Wed, 2017-07-26 at 13:07 +0200, Klavs Klavsen wrote:
>> Hi guys,
>>
>> Me and my colleagues have an annoying issue with our Linux desktops
>> and
>> the company's Junos VPN.
>>
>> We connect with openconnect (some use the official Pulse client) -
>> which
>> then opens up a tun0 device - and traffic runs through that.
>>
>> If we try to scp a file of ~100MB (f.ex. linux-4.12.3.tar.xz :) - it
>> stalls after sending 20-30% typicly.. then starts again after some
>> time,
>> and typicly dies before finishing. I've captured it with tcpdump (its
>> a
>> large 77Mb file - thats how far it got before it died :) -
>> http://blog.klavsen.info/fast-retransmit-problem-junos-linux
>>
>> I've attached an image of wireshark - where the (AFAIK) interesting
>> part
>> starts.. Where my client starts getting DUP ACK's.. but my Linux
>> client
>> does nothing :(
>> I've tried to upgrade to latest Ubuntu-mainline kernel build (4.12.3)
>> and it changed nothing.
>>
>> The problem goes away, if I do:
>> sysctl -w net.ipv4.tcp_sack=0
>>
>> I've tried specificly enabling net.ipv4.tcp_fack=1 - but that did not
>> help.
>>
>> This is not an issue on Mac OSX or Windows clients.
>>
>> None of the Linux users here figured, that could be a Linux kernel
>> issue
>> - but the evidence seems to suggest it - and all my googleing and
>> reading does not lead me to any other conclusion.
>>
>> It may ofcourse be that Junos has implemented the standard
>> badly/wrongly
>> - and Windows/Mac has done a workaround for that?
>>
>> I hope you can help me figure out whats going wrong.
>>
>
> sack blocks returned by the remote peer are completely bogus.
>
> Maybe a firewall is messing with them ?
>
> I suspect ACK packets might be simply dropped because of invalid SACK
> information.
--
Regards,
Klavs Klavsen, GSEC - kl@vsen.dk - http://blog.klavsen.info - Tlf.
61281200
"Those who do not understand Unix are condemned to reinvent it, poorly."
--Henry Spencer
^ permalink raw reply
* Re: [PATCH net-next v2 01/10] net: dsa: lan9303: Fixed MDIO interface
From: Egil Hjelmeland @ 2017-07-26 12:18 UTC (permalink / raw)
To: Vivien Didelot, corbet, andrew, f.fainelli, davem, kernel,
linux-doc, linux-kernel, netdev
In-Reply-To: <878tjc49bl.fsf@weeman.i-did-not-set--mail-host-address--so-tickle-me>
On 25. juli 2017 21:15, Vivien Didelot wrote:
> Hi Egil,
>
> Egil Hjelmeland <privat@egil-hjelmeland.no> writes:
>
>> Fixes after testing on actual HW:
>>
>> - lan9303_mdio_write()/_read() must multiply register number
>> by 4 to get offset
>>
>> - Indirect access (PMI) to phy register only work in I2C mode. In
>> MDIO mode phy registers must be accessed directly. Introduced
>> struct lan9303_phy_ops to handle the two modes. Renamed functions
>> to clarify.
>>
>> - lan9303_detect_phy_setup() : Failed MDIO read return 0xffff.
>> Handle that.
>
> Small patch series when possible are better. Bullet points in commit
> messages are likely to describe how a patch or series may be split up
> ;-)
>
> This patch seems to be the unique patch of the series resolving what is
> described in the cover letter as "Make the MDIO interface work".
>
> I'd suggest you to split up this one commit in several *atomic* and easy
> to review patches and send them separately as on thread named "net: dsa:
> lan9303: fix MDIO interface" (also note that imperative is prefered for
> subject lines, see: https://chris.beams.io/posts/git-commit/#imperative)
>
> <...>
>
>> -static int lan9303_port_phy_reg_wait_for_completion(struct lan9303 *chip)
>> +static int lan9303_indirect_phy_wait_for_completion(struct lan9303 *chip)
>
> For instance you can have a first commit only renaming the functions.
> The reason for it is to separate the functional changes from cosmetic
> changes, which makes it easier for review.
>
> <...>
Thank you for reviewing.
I can split the first patch.
I can also split the patch series to more digestible series. But
since most of the patches touches the same file, I assume that each
series must be completed and applied before starting on a new one.
So I really want to group the patches into only a few series in order
to not spend months on the process.
>> + if ((reg != 0) && (reg != 0xffff))
>
> if (reg && reg != 0xffff) should be enough.
Of course.
>> +struct lan9303_phy_ops {
>> + /* PHY 1 &2 access*/
>
> The spacing is weird in the comment. "/* PHY 1 & 2 access */" maybe?
>
Yes.
>> +int lan9303_mdio_phy_write(struct lan9303 *chip, int phy, int regnum, u16 val)
>> +{
>> + struct lan9303_mdio *sw_dev = dev_get_drvdata(chip->dev);
>> + struct mdio_device *mdio = sw_dev->device;
>> +
>> + mutex_lock(&mdio->bus->mdio_lock);
>> + mdio->bus->write(mdio->bus, phy, regnum, val);
>> + mutex_unlock(&mdio->bus->mdio_lock);
>
> This is exactly what mdiobus_write(mdio->bus, phy, regnum, val) is
> doing. There are very few valid reasons to go play in the mii_bus
> structure, using generic APIs are strongly prefered. Plus you have
> checks and traces for free!
>
Lack of oversight was the only reason. I just adapted stuff from
lan9303_mdio_phy_write above. Will switch to mdiobus_write of course.
> Same here, mdiobus_read().
>
Ditto.
>
> Thanks,
>
> Vivien
>
Appreciated,
Egil
^ permalink raw reply
* Re: [PATCH net] Revert "vhost: cache used event for better performance"
From: Jason Wang @ 2017-07-26 11:56 UTC (permalink / raw)
To: Christian Borntraeger, mst; +Cc: netdev, linux-kernel, kvm, virtualization
In-Reply-To: <da300d74-ca7a-a636-0ed6-6aa78e6a5510@de.ibm.com>
On 2017年07月26日 18:53, Christian Borntraeger wrote:
> On 07/26/2017 10:03 AM, Jason Wang wrote:
>> This reverts commit 809ecb9bca6a9424ccd392d67e368160f8b76c92. Since it
>> was reported to break vhost_net. We want to cache used event and use
>> it to check for notification. We try to valid cached used event by
>> checking whether or not it was ahead of new, but this is not correct
>> all the time, it could be stale and there's no way to know about this.
>>
>> Signed-off-by: Jason Wang <jasowang@redhat.com>
> This would then qualify for stable ?
>
Yes it is.
Thanks
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: TCP fast retransmit issues
From: Eric Dumazet @ 2017-07-26 11:49 UTC (permalink / raw)
To: Klavs Klavsen; +Cc: netdev
In-Reply-To: <200d9a12e9f2f5791d4c5ce2d47a1239@vsen.dk>
On Wed, 2017-07-26 at 13:07 +0200, Klavs Klavsen wrote:
> Hi guys,
>
> Me and my colleagues have an annoying issue with our Linux desktops and
> the company's Junos VPN.
>
> We connect with openconnect (some use the official Pulse client) - which
> then opens up a tun0 device - and traffic runs through that.
>
> If we try to scp a file of ~100MB (f.ex. linux-4.12.3.tar.xz :) - it
> stalls after sending 20-30% typicly.. then starts again after some time,
> and typicly dies before finishing. I've captured it with tcpdump (its a
> large 77Mb file - thats how far it got before it died :) -
> http://blog.klavsen.info/fast-retransmit-problem-junos-linux
>
> I've attached an image of wireshark - where the (AFAIK) interesting part
> starts.. Where my client starts getting DUP ACK's.. but my Linux client
> does nothing :(
> I've tried to upgrade to latest Ubuntu-mainline kernel build (4.12.3)
> and it changed nothing.
>
> The problem goes away, if I do:
> sysctl -w net.ipv4.tcp_sack=0
>
> I've tried specificly enabling net.ipv4.tcp_fack=1 - but that did not
> help.
>
> This is not an issue on Mac OSX or Windows clients.
>
> None of the Linux users here figured, that could be a Linux kernel issue
> - but the evidence seems to suggest it - and all my googleing and
> reading does not lead me to any other conclusion.
>
> It may ofcourse be that Junos has implemented the standard badly/wrongly
> - and Windows/Mac has done a workaround for that?
>
> I hope you can help me figure out whats going wrong.
>
sack blocks returned by the remote peer are completely bogus.
Maybe a firewall is messing with them ?
I suspect ACK packets might be simply dropped because of invalid SACK
information.
^ permalink raw reply
* Re: mlx5 still has lots of warnings
From: Saeed Mahameed @ 2017-07-26 11:27 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Linux Netdev List
In-Reply-To: <20170724095144.57f994ad@xeon-e3>
On Mon, Jul 24, 2017 at 7:51 PM, Stephen Hemminger
<stephen@networkplumber.org> wrote:
> I sent patches for this, and you said you were going to solve this (back in April).
> Still see lots of warnings from MLX5.
>
Hi Stephen,
You are right, we were planning to do some code refactoring to this
area and the priority of this task got reduced.
I will handle this myself, I will take your original patch if required.
Thanks for the reminder.
> CC [M] drivers/net/ethernet/mellanox/mlx5/core/en_rep.o
> drivers/net/ethernet/mellanox/mlx5/core/en_rep.c:767:35: warning: ‘mlx5e_rep_switchdev_ops’ defined but not used [-Wunused-const-variable=]
> static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
> ^~~~~~~~~~~~~~~~~~~~~~~
> In file included from drivers/net/ethernet/mellanox/mlx5/core/en_rep.c:41:0:
> drivers/net/ethernet/mellanox/mlx5/core/en.h:188:19: warning: ‘mlx5e_priv_flags’ defined but not used [-Wunused-const-variable=]
> static const char mlx5e_priv_flags[][ETH_GSTRING_LEN] = {
> ^~~~~~~~~~~~~~~~
> In file included from drivers/net/ethernet/mellanox/mlx5/core/en.h:51:0,
> from drivers/net/ethernet/mellanox/mlx5/core/en_rep.c:41:
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:427:34: warning: ‘mlx5e_pme_error_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc mlx5e_pme_error_desc[] = {
> ^~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:423:34: warning: ‘mlx5e_pme_status_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc mlx5e_pme_status_desc[] = {
> ^~~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:372:34: warning: ‘sq_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc sq_stats_desc[] = {
> ^~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:331:34: warning: ‘rq_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc rq_stats_desc[] = {
> ^~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:303:34: warning: ‘pcie_perf_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc pcie_perf_stats_desc[] = {
> ^~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:284:34: warning: ‘pport_per_prio_pfc_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc pport_per_prio_pfc_stats_desc[] = {
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:277:34: warning: ‘pport_per_prio_traffic_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc pport_per_prio_traffic_stats_desc[] = {
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:272:34: warning: ‘pport_phy_statistical_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc pport_phy_statistical_stats_desc[] = {
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:256:34: warning: ‘pport_2819_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc pport_2819_stats_desc[] = {
> ^~~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:250:34: warning: ‘pport_2863_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc pport_2863_stats_desc[] = {
> ^~~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:229:34: warning: ‘pport_802_3_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc pport_802_3_stats_desc[] = {
> ^~~~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:145:34: warning: ‘vport_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc vport_stats_desc[] = {
> ^~~~~~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:133:34: warning: ‘q_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc q_stats_desc[] = {
> ^~~~~~~~~~~~
> drivers/net/ethernet/mellanox/mlx5/core/en_stats.h:92:34: warning: ‘sw_stats_desc’ defined but not used [-Wunused-const-variable=]
> static const struct counter_desc sw_stats_desc[] = {
> ^~~~~~~~~~~~~
> LD [M] drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.o
^ permalink raw reply
* TCP fast retransmit issues
From: Klavs Klavsen @ 2017-07-26 11:07 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 1591 bytes --]
Hi guys,
Me and my colleagues have an annoying issue with our Linux desktops and
the company's Junos VPN.
We connect with openconnect (some use the official Pulse client) - which
then opens up a tun0 device - and traffic runs through that.
If we try to scp a file of ~100MB (f.ex. linux-4.12.3.tar.xz :) - it
stalls after sending 20-30% typicly.. then starts again after some time,
and typicly dies before finishing. I've captured it with tcpdump (its a
large 77Mb file - thats how far it got before it died :) -
http://blog.klavsen.info/fast-retransmit-problem-junos-linux
I've attached an image of wireshark - where the (AFAIK) interesting part
starts.. Where my client starts getting DUP ACK's.. but my Linux client
does nothing :(
I've tried to upgrade to latest Ubuntu-mainline kernel build (4.12.3)
and it changed nothing.
The problem goes away, if I do:
sysctl -w net.ipv4.tcp_sack=0
I've tried specificly enabling net.ipv4.tcp_fack=1 - but that did not
help.
This is not an issue on Mac OSX or Windows clients.
None of the Linux users here figured, that could be a Linux kernel issue
- but the evidence seems to suggest it - and all my googleing and
reading does not lead me to any other conclusion.
It may ofcourse be that Junos has implemented the standard badly/wrongly
- and Windows/Mac has done a workaround for that?
I hope you can help me figure out whats going wrong.
--
Regards,
Klavs Klavsen, GSEC - kl@vsen.dk - http://blog.klavsen.info - Tlf.
61281200
"Those who do not understand Unix are condemned to reinvent it, poorly."
--Henry Spencer
[-- Attachment #2: fast-retransmit-not-happening.png --]
[-- Type: image/png, Size: 323591 bytes --]
^ permalink raw reply
* Re: [PATCH net-next 2/2] bnxt_en: define sriov_lock unconditionally
From: Sathya Perla @ 2017-07-26 10:54 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Michael Chan, David S. Miller, Somnath Kotur, Deepak Khungar,
Netdev, open list
In-Reply-To: <CAK8P3a3UBfg6=GJ5UKEENnN-qoFuxaO4yo2Lqy65gN0zP4Nw-w@mail.gmail.com>
On Wed, Jul 26, 2017 at 2:35 PM, Arnd Bergmann <arnd@arndb.de> wrote:
[...]
>> Sathya already sent 3 patches to fix some of these issues. But I need
>> to rework one of his patch and resend.
>
> Ok, thanks. I just ran into one more issue, and don't know if that's included
> as well. If not, please also add the patch below (or fold it into the one
> that adds the switchdev dependency to the ethernet driver):
>
> 8<----------
> Subject: [PATCH] RDMA/bnxt_re: add NET_SWITCHDEV dependency
>
> The rdma side of BNXT enables the ethernet driver and has a list
> of its dependencies. However, the ethernet driver now also depends
> on NET_SWITCHDEV, so we have to add that dependency for both:
Arnd, after the patch "bnxt_en: use SWITCHDEV_SET_OPS() for setting
vf_rep_switchdev_ops" the bnxt_en driver doesn't need an explicit
NET_SWITCHDEV dependency. So, the bnxt_re driver shouldn't need one
either. Are you still seeing the bnxt_re issue even after pulling the
above patch??
^ permalink raw reply
* Re: [PATCH net] Revert "vhost: cache used event for better performance"
From: Christian Borntraeger @ 2017-07-26 10:53 UTC (permalink / raw)
To: Jason Wang, mst; +Cc: virtualization, kvm, netdev, linux-kernel
In-Reply-To: <1501056197-3368-1-git-send-email-jasowang@redhat.com>
On 07/26/2017 10:03 AM, Jason Wang wrote:
> This reverts commit 809ecb9bca6a9424ccd392d67e368160f8b76c92. Since it
> was reported to break vhost_net. We want to cache used event and use
> it to check for notification. We try to valid cached used event by
> checking whether or not it was ahead of new, but this is not correct
> all the time, it could be stale and there's no way to know about this.
>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
This would then qualify for stable ?
^ permalink raw reply
* Re: linux-next: Tree for Jul 26
From: Sergey Senozhatsky @ 2017-07-26 10:48 UTC (permalink / raw)
To: Paolo Abeni, Stephen Rothwell
Cc: Linux-Next Mailing List, Linux Kernel Mailing List, Paul Moore,
David S. Miller, netdev
In-Reply-To: <20170726161203.1dfbcff9@canb.auug.org.au>
Hello,
On (07/26/17 16:12), Stephen Rothwell wrote:
> Hi all,
>
> Changes since 20170725:
>
> Non-merge commits (relative to Linus' tree): 2358
> 2466 files changed, 86994 insertions(+), 44655 deletions(-)
dce4551cb2adb1ac ("udp: preserve head state for IP_CMSG_PASSSEC")
causes a build error
net/ipv4/udp.c: In function ‘__udp_queue_rcv_skb’:
net/ipv4/udp.c:1789:49: error: ‘struct sk_buff’ has no member named ‘sp’; did you mean ‘sk’?
if (likely(IPCB(skb)->opt.optlen == 0 && !skb->sp))
^
-ss
^ permalink raw reply
* [net-next 14/14] i40e: handle setting administratively set MAC address back to zero
From: Jeff Kirsher @ 2017-07-26 10:31 UTC (permalink / raw)
To: davem; +Cc: Stefan Assmann, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20170726103123.76743-1-jeffrey.t.kirsher@intel.com>
From: Stefan Assmann <sassmann@kpanic.de>
When an administratively set MAC was previously set and should now be
switched back to 00:00:00:00:00:00 the pf_set_mac flag did not get
toggled back to false.
As a result VFs were still treated as if an administratively set MAC was
present.
Signed-off-by: Stefan Assmann <sassmann@kpanic.de>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 12 ++++++++++--
1 file changed, 10 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 2e261bb59d10..979110d59f67 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -2762,7 +2762,6 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
spin_unlock_bh(&vsi->mac_filter_hash_lock);
- dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf_id);
/* program mac filter */
if (i40e_sync_vsi_filters(vsi)) {
dev_err(&pf->pdev->dev, "Unable to program ucast filters\n");
@@ -2770,7 +2769,16 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
goto error_param;
}
ether_addr_copy(vf->default_lan_addr.addr, mac);
- vf->pf_set_mac = true;
+
+ if (is_zero_ether_addr(mac)) {
+ vf->pf_set_mac = false;
+ dev_info(&pf->pdev->dev, "Removing MAC on VF %d\n", vf_id);
+ } else {
+ vf->pf_set_mac = true;
+ dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n",
+ mac, vf_id);
+ }
+
/* Force the VF driver stop so it has to reload with new MAC address */
i40e_vc_disable_vf(pf, vf);
dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n");
--
2.13.3
^ permalink raw reply related
* [net-next 13/14] i40evf: remove unnecessary __packed
From: Jeff Kirsher @ 2017-07-26 10:31 UTC (permalink / raw)
To: davem; +Cc: Tushar Dave, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20170726103123.76743-1-jeffrey.t.kirsher@intel.com>
From: Tushar Dave <tushar.n.dave@oracle.com>
This is similar to 'commit 9588397d24eec ("i40e: remove unnecessary
__packed")' to avoid unaligned access.
Signed-off-by: Tushar Dave <tushar.n.dave@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40evf/i40e_osdep.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_osdep.h b/drivers/net/ethernet/intel/i40evf/i40e_osdep.h
index 5e314fd3c016..a90737786c34 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_osdep.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_osdep.h
@@ -54,7 +54,7 @@ struct i40e_dma_mem {
void *va;
dma_addr_t pa;
u32 size;
-} __packed;
+};
#define i40e_allocate_dma_mem(h, m, unused, s, a) \
i40evf_allocate_dma_mem_d(h, m, s, a)
@@ -63,7 +63,7 @@ struct i40e_dma_mem {
struct i40e_virt_mem {
void *va;
u32 size;
-} __packed;
+};
#define i40e_allocate_virt_mem(h, m, s) i40evf_allocate_virt_mem_d(h, m, s)
#define i40e_free_virt_mem(h, m) i40evf_free_virt_mem_d(h, m)
--
2.13.3
^ permalink raw reply related
* [net-next 12/14] i40evf: Use le32_to_cpu before evaluating HW desc fields
From: Jeff Kirsher @ 2017-07-26 10:31 UTC (permalink / raw)
To: davem; +Cc: Tushar Dave, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20170726103123.76743-1-jeffrey.t.kirsher@intel.com>
From: Tushar Dave <tushar.n.dave@oracle.com>
i40e hardware descriptor fields are in little-endian format. Driver
must use le32_to_cpu while evaluating these fields otherwise on
big-endian arch we end up evaluating incorrect values, cause errors
like:
i40evf 0000:03:0a.0: Expected response 24 from PF, received 402653184
i40evf 0000:03:0a.1: Expected response 7 from PF, received 117440512
Signed-off-by: Tushar Dave <tushar.n.dave@oracle.com>
Reviewed-by: Shannon Nelson <shannon.nelson@oracle.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 7c213a347909..93536b9fc629 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -1957,8 +1957,8 @@ static void i40evf_adminq_task(struct work_struct *work)
container_of(work, struct i40evf_adapter, adminq_task);
struct i40e_hw *hw = &adapter->hw;
struct i40e_arq_event_info event;
- struct virtchnl_msg *v_msg;
- i40e_status ret;
+ enum virtchnl_ops v_op;
+ i40e_status ret, v_ret;
u32 val, oldval;
u16 pending;
@@ -1970,15 +1970,15 @@ static void i40evf_adminq_task(struct work_struct *work)
if (!event.msg_buf)
goto out;
- v_msg = (struct virtchnl_msg *)&event.desc;
do {
ret = i40evf_clean_arq_element(hw, &event, &pending);
- if (ret || !v_msg->v_opcode)
+ v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
+ v_ret = (i40e_status)le32_to_cpu(event.desc.cookie_low);
+
+ if (ret || !v_op)
break; /* No event to process or error cleaning ARQ */
- i40evf_virtchnl_completion(adapter, v_msg->v_opcode,
- (i40e_status)v_msg->v_retval,
- event.msg_buf,
+ i40evf_virtchnl_completion(adapter, v_op, v_ret, event.msg_buf,
event.msg_len);
if (pending != 0)
memset(event.msg_buf, 0, I40EVF_MAX_AQ_BUF_SIZE);
--
2.13.3
^ permalink raw reply related
* [net-next 11/14] i40e: report BPF prog id during XDP_QUERY_PROG
From: Jeff Kirsher @ 2017-07-26 10:31 UTC (permalink / raw)
To: davem; +Cc: Daniel Borkmann, netdev, nhorman, sassmann, jogreene,
Jeff Kirsher
In-Reply-To: <20170726103123.76743-1-jeffrey.t.kirsher@intel.com>
From: Daniel Borkmann <daniel@iogearbox.net>
Fill the XDP prog_id with the id just like we do in other XDP enabled
drivers such as ixgbe. This is needed so that on dump we can retrieve
the attached program based on the id, and dump BPF insns, opcodes, etc
back to user space. Only XDP driver missing this is currently i40e.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 2b115b0c5296..4104944ea367 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -9601,6 +9601,7 @@ static int i40e_xdp(struct net_device *dev,
return i40e_xdp_setup(vsi, xdp->prog);
case XDP_QUERY_PROG:
xdp->prog_attached = i40e_enabled_xdp_vsi(vsi);
+ xdp->prog_id = vsi->xdp_prog ? vsi->xdp_prog->aux->id : 0;
return 0;
default:
return -EINVAL;
--
2.13.3
^ permalink raw reply related
* [net-next 10/14] i40evf: add some missing includes
From: Jeff Kirsher @ 2017-07-26 10:31 UTC (permalink / raw)
To: davem; +Cc: Jesse Brandeburg, netdev, nhorman, sassmann, jogreene,
Jeff Kirsher
In-Reply-To: <20170726103123.76743-1-jeffrey.t.kirsher@intel.com>
From: Jesse Brandeburg <jesse.brandeburg@intel.com>
These includes were all being used in the driver, but weren't
being directly included.
Since the current advised method is to directly include anything
that you need, this implements that.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40evf/i40evf.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h
index 6cc92089fecb..7901cc85cbe5 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf.h
+++ b/drivers/net/ethernet/intel/i40evf/i40evf.h
@@ -39,6 +39,17 @@
#include <linux/tcp.h>
#include <linux/sctp.h>
#include <linux/ipv6.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/socket.h>
+#include <linux/jiffies.h>
#include <net/ip6_checksum.h>
#include <net/udp.h>
--
2.13.3
^ permalink raw reply related
* [net-next 09/14] i40e: display correct UDP tunnel type name
From: Jeff Kirsher @ 2017-07-26 10:31 UTC (permalink / raw)
To: davem; +Cc: Jacob Keller, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20170726103123.76743-1-jeffrey.t.kirsher@intel.com>
From: Jacob Keller <jacob.e.keller@intel.com>
The i40e driver attempts to display the UDP tunnel name by doing a check
against the type, where for non-zero types we use "vxlan" and for zero
type we use "geneve". This is not future proof, because if new tunnel
types get added, we'll incorrectly label them. It also depends on the
value of UDP_TUNNEL_TYPE_GENEVE == 0, which is brittle.
Instead, replace this with a function that can return a constant string
depending on the type. For now we'll use "unknown" for types we don't
know about, and we can expand this in the future if new types get added.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index a2d665161def..2b115b0c5296 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -7520,6 +7520,18 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
i40e_flush(hw);
}
+static const char *i40e_tunnel_name(struct i40e_udp_port_config *port)
+{
+ switch (port->type) {
+ case UDP_TUNNEL_TYPE_VXLAN:
+ return "vxlan";
+ case UDP_TUNNEL_TYPE_GENEVE:
+ return "geneve";
+ default:
+ return "unknown";
+ }
+}
+
/**
* i40e_sync_udp_filters - Trigger a sync event for existing UDP filters
* @pf: board private structure
@@ -7565,14 +7577,14 @@ static void i40e_sync_udp_filters_subtask(struct i40e_pf *pf)
ret = i40e_aq_del_udp_tunnel(hw, i, NULL);
if (ret) {
- dev_dbg(&pf->pdev->dev,
- "%s %s port %d, index %d failed, err %s aq_err %s\n",
- pf->udp_ports[i].type ? "vxlan" : "geneve",
- port ? "add" : "delete",
- port, i,
- i40e_stat_str(&pf->hw, ret),
- i40e_aq_str(&pf->hw,
- pf->hw.aq.asq_last_status));
+ dev_info(&pf->pdev->dev,
+ "%s %s port %d, index %d failed, err %s aq_err %s\n",
+ i40e_tunnel_name(&pf->udp_ports[i]),
+ port ? "add" : "delete",
+ port, i,
+ i40e_stat_str(&pf->hw, ret),
+ i40e_aq_str(&pf->hw,
+ pf->hw.aq.asq_last_status));
pf->udp_ports[i].port = 0;
}
}
--
2.13.3
^ permalink raw reply related
* [net-next 08/14] i40e/i40evf: remove mismatched type warnings
From: Jeff Kirsher @ 2017-07-26 10:31 UTC (permalink / raw)
To: davem; +Cc: Jesse Brandeburg, netdev, nhorman, sassmann, jogreene,
Jeff Kirsher
In-Reply-To: <20170726103123.76743-1-jeffrey.t.kirsher@intel.com>
From: Jesse Brandeburg <jesse.brandeburg@intel.com>
Compiler reported several places where driver compared
signed and unsigned types. Cast or change the types to remove
the warnings.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 6 +++---
drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +-
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 6 +++---
drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 6 +++---
drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 4 ++--
5 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 9692a5294fa3..1d29152256fe 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -1091,7 +1091,7 @@ static void i40e_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
struct i40e_pf *pf = np->vsi->back;
struct i40e_hw *hw = &pf->hw;
u32 *reg_buf = p;
- int i, j, ri;
+ unsigned int i, j, ri;
u32 reg;
/* Tell ethtool which driver-version-specific regs output we have.
@@ -1550,9 +1550,9 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
struct i40e_ring *tx_ring, *rx_ring;
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
+ unsigned int j;
int i = 0;
char *p;
- int j;
struct rtnl_link_stats64 *net_stats = i40e_get_vsi_stats_struct(vsi);
unsigned int start;
@@ -1637,7 +1637,7 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
char *p = (char *)data;
- int i;
+ unsigned int i;
switch (stringset) {
case ETH_SS_TEST:
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 22e60841cb22..a2d665161def 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -4773,7 +4773,7 @@ static void i40e_detect_recover_hung(struct i40e_pf *pf)
{
struct net_device *netdev;
struct i40e_vsi *vsi;
- int i;
+ unsigned int i;
/* Only for LAN VSI */
vsi = pf->vsi[pf->lan_vsi];
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index c9a149678926..d464fceb300f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -860,7 +860,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
netdev_tx_completed_queue(txring_txq(tx_ring),
total_packets, total_bytes);
-#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
+#define TX_WAKE_THRESHOLD ((s16)(DESC_NEEDED * 2))
if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) &&
(I40E_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
/* Make sure that anybody stopping the queue after this
@@ -2063,7 +2063,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
bool failure = false, xdp_xmit = false;
- while (likely(total_rx_packets < budget)) {
+ while (likely(total_rx_packets < (unsigned int)budget)) {
struct i40e_rx_buffer *rx_buffer;
union i40e_rx_desc *rx_desc;
struct xdp_buff xdp;
@@ -2196,7 +2196,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
rx_ring->q_vector->rx.total_bytes += total_rx_bytes;
/* guarantee a trip back through this routine if there was a failure */
- return failure ? budget : total_rx_packets;
+ return failure ? budget : (int)total_rx_packets;
}
static u32 i40e_buildreg_itr(const int type, const u16 itr)
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index 12b02e530503..d91676ccf125 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -275,7 +275,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
netdev_tx_completed_queue(txring_txq(tx_ring),
total_packets, total_bytes);
-#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
+#define TX_WAKE_THRESHOLD ((s16)(DESC_NEEDED * 2))
if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) &&
(I40E_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
/* Make sure that anybody stopping the queue after this
@@ -1299,7 +1299,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
bool failure = false;
- while (likely(total_rx_packets < budget)) {
+ while (likely(total_rx_packets < (unsigned int)budget)) {
struct i40e_rx_buffer *rx_buffer;
union i40e_rx_desc *rx_desc;
unsigned int size;
@@ -1406,7 +1406,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
rx_ring->q_vector->rx.total_bytes += total_rx_bytes;
/* guarantee a trip back through this routine if there was a failure */
- return failure ? budget : total_rx_packets;
+ return failure ? budget : (int)total_rx_packets;
}
static u32 i40e_buildreg_itr(const int type, const u16 itr)
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index 9bb2cc7dd4e4..76fd89c1dbb2 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -165,7 +165,7 @@ static void i40evf_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
- int i, j;
+ unsigned int i, j;
char *p;
for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
@@ -197,7 +197,7 @@ static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
int i;
if (sset == ETH_SS_STATS) {
- for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
+ for (i = 0; i < (int)I40EVF_GLOBAL_STATS_LEN; i++) {
memcpy(p, i40evf_gstrings_stats[i].stat_string,
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
--
2.13.3
^ permalink raw reply related
* [net-next 07/14] i40e/i40evf: make IPv6 ATR code clearer
From: Jeff Kirsher @ 2017-07-26 10:31 UTC (permalink / raw)
To: davem; +Cc: Jesse Brandeburg, netdev, nhorman, sassmann, jogreene,
Jeff Kirsher
In-Reply-To: <20170726103123.76743-1-jeffrey.t.kirsher@intel.com>
From: Jesse Brandeburg <jesse.brandeburg@intel.com>
This just reorders some local vars and makes the code flow
clearer.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index b936febc315a..c9a149678926 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -2451,9 +2451,15 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
hlen = (hdr.network[0] & 0x0F) << 2;
l4_proto = hdr.ipv4->protocol;
} else {
- hlen = hdr.network - skb->data;
- l4_proto = ipv6_find_hdr(skb, &hlen, IPPROTO_TCP, NULL, NULL);
- hlen -= hdr.network - skb->data;
+ /* find the start of the innermost ipv6 header */
+ unsigned int inner_hlen = hdr.network - skb->data;
+ unsigned int h_offset = inner_hlen;
+
+ /* this function updates h_offset to the end of the header */
+ l4_proto =
+ ipv6_find_hdr(skb, &h_offset, IPPROTO_TCP, NULL, NULL);
+ /* hlen will contain our best estimate of the tcp header */
+ hlen = h_offset - inner_hlen;
}
if (l4_proto != IPPROTO_TCP)
--
2.13.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox