* [PATCH net-next 5/5] qed: Prevent link getting down in case of autoneg-off.
From: Rahul Verma @ 2018-10-16 10:59 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, Dept-EngEverestLinuxL2, Rahul Verma
In-Reply-To: <20181016105922.25562-1-rahul.verma@cavium.com>
From: Rahul Verma <Rahul.Verma@cavium.com>
Newly added link modes are required to be added
during setting link modes. If the new link mode
is not available during qed_set_link, it may cause
link getting down due to empty supported capability,
being passed to MFW, after setting autoneg off/on
with current/supported speed.
Signed-off-by: Rahul Verma <Rahul.Verma@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_main.c | 40 ++++++++++++++++++++++++------
1 file changed, 33 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index e762881..35fd0db 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -1305,6 +1305,7 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
struct qed_hwfn *hwfn;
struct qed_mcp_link_params *link_params;
struct qed_ptt *ptt;
+ u32 sup_caps;
int rc;
if (!cdev)
@@ -1331,25 +1332,50 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
link_params->speed.autoneg = params->autoneg;
if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) {
link_params->speed.advertised_speeds = 0;
- if (params->adv_speeds & QED_LM_1000baseT_Full_BIT)
+ sup_caps = QED_LM_1000baseT_Full_BIT |
+ QED_LM_1000baseKX_Full_BIT |
+ QED_LM_1000baseX_Full_BIT;
+ if (params->adv_speeds & sup_caps)
link_params->speed.advertised_speeds |=
NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
- if (params->adv_speeds & QED_LM_10000baseKR_Full_BIT)
+ sup_caps = QED_LM_10000baseT_Full_BIT |
+ QED_LM_10000baseKR_Full_BIT |
+ QED_LM_10000baseKX4_Full_BIT |
+ QED_LM_10000baseR_FEC_BIT |
+ QED_LM_10000baseCR_Full_BIT |
+ QED_LM_10000baseSR_Full_BIT |
+ QED_LM_10000baseLR_Full_BIT |
+ QED_LM_10000baseLRM_Full_BIT;
+ if (params->adv_speeds & sup_caps)
link_params->speed.advertised_speeds |=
NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
if (params->adv_speeds & QED_LM_20000baseKR2_Full_BIT)
link_params->speed.advertised_speeds |=
NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G;
- if (params->adv_speeds & QED_LM_25000baseKR_Full_BIT)
+ sup_caps = QED_LM_25000baseKR_Full_BIT |
+ QED_LM_25000baseCR_Full_BIT |
+ QED_LM_25000baseSR_Full_BIT;
+ if (params->adv_speeds & sup_caps)
link_params->speed.advertised_speeds |=
NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
- if (params->adv_speeds & QED_LM_40000baseLR4_Full_BIT)
+ sup_caps = QED_LM_40000baseLR4_Full_BIT |
+ QED_LM_40000baseKR4_Full_BIT |
+ QED_LM_40000baseCR4_Full_BIT |
+ QED_LM_40000baseSR4_Full_BIT;
+ if (params->adv_speeds & sup_caps)
link_params->speed.advertised_speeds |=
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
- if (params->adv_speeds & QED_LM_50000baseKR2_Full_BIT)
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
+ sup_caps = QED_LM_50000baseKR2_Full_BIT |
+ QED_LM_50000baseCR2_Full_BIT |
+ QED_LM_50000baseSR2_Full_BIT;
+ if (params->adv_speeds & sup_caps)
link_params->speed.advertised_speeds |=
NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G;
- if (params->adv_speeds & QED_LM_100000baseKR4_Full_BIT)
+ sup_caps = QED_LM_100000baseKR4_Full_BIT |
+ QED_LM_100000baseSR4_Full_BIT |
+ QED_LM_100000baseCR4_Full_BIT |
+ QED_LM_100000baseLR4_ER4_Full_BIT;
+ if (params->adv_speeds & sup_caps)
link_params->speed.advertised_speeds |=
NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next 3/5] qed: Add supported link and advertise link to display in ethtool.
From: Rahul Verma @ 2018-10-16 10:59 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, Dept-EngEverestLinuxL2, Rahul Verma
In-Reply-To: <20181016105922.25562-1-rahul.verma@cavium.com>
From: Rahul Verma <Rahul.Verma@cavium.com>
Added transceiver type, speed capability and board types
in HSI, are utilizing to display the accurate link
information in ethtool.
Signed-off-by: Rahul Verma <Rahul.Verma@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_main.c | 199 ++++++++++++++++++------
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 182 ++++++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 46 ++++++
drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 31 +++-
include/linux/qed/qed_if.h | 26 +++-
5 files changed, 426 insertions(+), 58 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 8c7cbbd..e762881 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -58,6 +58,7 @@
#include "qed_iscsi.h"
#include "qed_mcp.h"
+#include "qed_reg_addr.h"
#include "qed_hw.h"
#include "qed_selftest.h"
#include "qed_debug.h"
@@ -1330,8 +1331,7 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
link_params->speed.autoneg = params->autoneg;
if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) {
link_params->speed.advertised_speeds = 0;
- if ((params->adv_speeds & QED_LM_1000baseT_Half_BIT) ||
- (params->adv_speeds & QED_LM_1000baseT_Full_BIT))
+ if (params->adv_speeds & QED_LM_1000baseT_Full_BIT)
link_params->speed.advertised_speeds |=
NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
if (params->adv_speeds & QED_LM_10000baseKR_Full_BIT)
@@ -1462,13 +1462,149 @@ static int qed_get_link_data(struct qed_hwfn *hwfn,
return 0;
}
+static void qed_fill_link_capability(struct qed_hwfn *hwfn,
+ struct qed_ptt *ptt, u32 capability,
+ u32 *if_capability)
+{
+ u32 media_type, tcvr_state, tcvr_type;
+ u32 speed_mask, board_cfg;
+
+ if (qed_mcp_get_media_type(hwfn, ptt, &media_type))
+ media_type = MEDIA_UNSPECIFIED;
+
+ if (qed_mcp_get_transceiver_data(hwfn, ptt, &tcvr_state, &tcvr_type))
+ tcvr_type = ETH_TRANSCEIVER_STATE_UNPLUGGED;
+
+ if (qed_mcp_trans_speed_mask(hwfn, ptt, &speed_mask))
+ speed_mask = 0xFFFFFFFF;
+
+ if (qed_mcp_get_board_config(hwfn, ptt, &board_cfg))
+ board_cfg = NVM_CFG1_PORT_PORT_TYPE_UNDEFINED;
+
+ DP_VERBOSE(hwfn->cdev, NETIF_MSG_DRV,
+ "Media_type = 0x%x tcvr_state = 0x%x tcvr_type = 0x%x speed_mask = 0x%x board_cfg = 0x%x\n",
+ media_type, tcvr_state, tcvr_type, speed_mask, board_cfg);
+
+ switch (media_type) {
+ case MEDIA_DA_TWINAX:
+ if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
+ *if_capability |= QED_LM_20000baseKR2_Full_BIT;
+ /* For DAC media multiple speed capabilities are supported*/
+ capability = capability & speed_mask;
+ if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
+ *if_capability |= QED_LM_1000baseKX_Full_BIT;
+ if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
+ *if_capability |= QED_LM_10000baseCR_Full_BIT;
+ if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
+ *if_capability |= QED_LM_40000baseCR4_Full_BIT;
+ if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
+ *if_capability |= QED_LM_25000baseCR_Full_BIT;
+ if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
+ *if_capability |= QED_LM_50000baseCR2_Full_BIT;
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
+ *if_capability |= QED_LM_100000baseCR4_Full_BIT;
+ break;
+ case MEDIA_BASE_T:
+ if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_EXT_PHY) {
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) {
+ *if_capability |= QED_LM_1000baseT_Full_BIT;
+ }
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) {
+ *if_capability |= QED_LM_10000baseT_Full_BIT;
+ }
+ }
+ if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_MODULE) {
+ if (tcvr_type == ETH_TRANSCEIVER_TYPE_1000BASET)
+ *if_capability |= QED_LM_1000baseT_Full_BIT;
+ if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_BASET)
+ *if_capability |= QED_LM_10000baseT_Full_BIT;
+ }
+ break;
+ case MEDIA_SFP_1G_FIBER:
+ case MEDIA_SFPP_10G_FIBER:
+ case MEDIA_XFP_FIBER:
+ case MEDIA_MODULE_FIBER:
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) {
+ if ((tcvr_type == ETH_TRANSCEIVER_TYPE_1G_LX) ||
+ (tcvr_type == ETH_TRANSCEIVER_TYPE_1G_SX))
+ *if_capability |= QED_LM_1000baseKX_Full_BIT;
+ }
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) {
+ if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_SR)
+ *if_capability |= QED_LM_10000baseSR_Full_BIT;
+ if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_LR)
+ *if_capability |= QED_LM_10000baseLR_Full_BIT;
+ if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_LRM)
+ *if_capability |= QED_LM_10000baseLRM_Full_BIT;
+ if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_ER)
+ *if_capability |= QED_LM_10000baseR_FEC_BIT;
+ }
+ if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
+ *if_capability |= QED_LM_20000baseKR2_Full_BIT;
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) {
+ if (tcvr_type == ETH_TRANSCEIVER_TYPE_25G_SR)
+ *if_capability |= QED_LM_25000baseSR_Full_BIT;
+ }
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) {
+ if (tcvr_type == ETH_TRANSCEIVER_TYPE_40G_LR4)
+ *if_capability |= QED_LM_40000baseLR4_Full_BIT;
+ if (tcvr_type == ETH_TRANSCEIVER_TYPE_40G_SR4)
+ *if_capability |= QED_LM_40000baseSR4_Full_BIT;
+ }
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
+ *if_capability |= QED_LM_50000baseKR2_Full_BIT;
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) {
+ if (tcvr_type == ETH_TRANSCEIVER_TYPE_100G_SR4)
+ *if_capability |= QED_LM_100000baseSR4_Full_BIT;
+ }
+
+ break;
+ case MEDIA_KR:
+ if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
+ *if_capability |= QED_LM_20000baseKR2_Full_BIT;
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
+ *if_capability |= QED_LM_1000baseKX_Full_BIT;
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
+ *if_capability |= QED_LM_10000baseKR_Full_BIT;
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
+ *if_capability |= QED_LM_25000baseKR_Full_BIT;
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
+ *if_capability |= QED_LM_40000baseKR4_Full_BIT;
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
+ *if_capability |= QED_LM_50000baseKR2_Full_BIT;
+ if (capability &
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
+ *if_capability |= QED_LM_100000baseKR4_Full_BIT;
+ break;
+ case MEDIA_UNSPECIFIED:
+ case MEDIA_NOT_PRESENT:
+ DP_VERBOSE(hwfn->cdev, QED_MSG_DEBUG,
+ "Unknown media and transceiver type;\n");
+ break;
+ }
+}
+
static void qed_fill_link(struct qed_hwfn *hwfn,
struct qed_ptt *ptt,
struct qed_link_output *if_link)
{
+ struct qed_mcp_link_capabilities link_caps;
struct qed_mcp_link_params params;
struct qed_mcp_link_state link;
- struct qed_mcp_link_capabilities link_caps;
u32 media_type;
memset(if_link, 0, sizeof(*if_link));
@@ -1499,51 +1635,13 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
if_link->advertised_caps |= QED_LM_Autoneg_BIT;
else
if_link->advertised_caps &= ~QED_LM_Autoneg_BIT;
- if (params.speed.advertised_speeds &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
- if_link->advertised_caps |= QED_LM_1000baseT_Half_BIT |
- QED_LM_1000baseT_Full_BIT;
- if (params.speed.advertised_speeds &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
- if_link->advertised_caps |= QED_LM_10000baseKR_Full_BIT;
- if (params.speed.advertised_speeds &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
- if_link->advertised_caps |= QED_LM_20000baseKR2_Full_BIT;
- if (params.speed.advertised_speeds &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
- if_link->advertised_caps |= QED_LM_25000baseKR_Full_BIT;
- if (params.speed.advertised_speeds &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
- if_link->advertised_caps |= QED_LM_40000baseLR4_Full_BIT;
- if (params.speed.advertised_speeds &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
- if_link->advertised_caps |= QED_LM_50000baseKR2_Full_BIT;
- if (params.speed.advertised_speeds &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
- if_link->advertised_caps |= QED_LM_100000baseKR4_Full_BIT;
-
- if (link_caps.speed_capabilities &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
- if_link->supported_caps |= QED_LM_1000baseT_Half_BIT |
- QED_LM_1000baseT_Full_BIT;
- if (link_caps.speed_capabilities &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
- if_link->supported_caps |= QED_LM_10000baseKR_Full_BIT;
- if (link_caps.speed_capabilities &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
- if_link->supported_caps |= QED_LM_20000baseKR2_Full_BIT;
- if (link_caps.speed_capabilities &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
- if_link->supported_caps |= QED_LM_25000baseKR_Full_BIT;
- if (link_caps.speed_capabilities &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
- if_link->supported_caps |= QED_LM_40000baseLR4_Full_BIT;
- if (link_caps.speed_capabilities &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
- if_link->supported_caps |= QED_LM_50000baseKR2_Full_BIT;
- if (link_caps.speed_capabilities &
- NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
- if_link->supported_caps |= QED_LM_100000baseKR4_Full_BIT;
+
+ /* Fill link advertised capability*/
+ qed_fill_link_capability(hwfn, ptt, params.speed.advertised_speeds,
+ &if_link->advertised_caps);
+ /* Fill link supported capability*/
+ qed_fill_link_capability(hwfn, ptt, link_caps.speed_capabilities,
+ &if_link->supported_caps);
if (link.link_up)
if_link->speed = link.speed;
@@ -1563,9 +1661,8 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE;
/* Link partner capabilities */
- if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_HD)
- if_link->lp_caps |= QED_LM_1000baseT_Half_BIT;
- if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_FD)
+ if (link.partner_adv_speed &
+ QED_LINK_PARTNER_SPEED_1G_FD)
if_link->lp_caps |= QED_LM_1000baseT_Full_BIT;
if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_10G)
if_link->lp_caps |= QED_LM_10000baseKR_Full_BIT;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 92c5950..554d57a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1870,6 +1870,8 @@ int qed_mcp_get_mbi_ver(struct qed_hwfn *p_hwfn,
int qed_mcp_get_media_type(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u32 *p_media_type)
{
+ *p_media_type = MEDIA_UNSPECIFIED;
+
if (IS_VF(p_hwfn->cdev))
return -EINVAL;
@@ -1891,6 +1893,186 @@ int qed_mcp_get_media_type(struct qed_hwfn *p_hwfn,
return 0;
}
+int qed_mcp_get_transceiver_data(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 *p_transceiver_state,
+ u32 *p_transceiver_type)
+{
+ u32 transceiver_info;
+
+ if (IS_VF(p_hwfn->cdev))
+ return -EINVAL;
+
+ if (!qed_mcp_is_init(p_hwfn)) {
+ DP_NOTICE(p_hwfn, "MFW is not initialized!\n");
+ return -EBUSY;
+ }
+
+ *p_transceiver_type = ETH_TRANSCEIVER_TYPE_NONE;
+ *p_transceiver_state = ETH_TRANSCEIVER_STATE_UPDATING;
+
+ transceiver_info = qed_rd(p_hwfn, p_ptt,
+ p_hwfn->mcp_info->port_addr +
+ offsetof(struct public_port,
+ transceiver_data));
+
+ *p_transceiver_state = (transceiver_info &
+ ETH_TRANSCEIVER_STATE_MASK) >>
+ ETH_TRANSCEIVER_STATE_OFFSET;
+
+ if (*p_transceiver_state == ETH_TRANSCEIVER_STATE_PRESENT)
+ *p_transceiver_type = (transceiver_info &
+ ETH_TRANSCEIVER_TYPE_MASK) >>
+ ETH_TRANSCEIVER_TYPE_OFFSET;
+ else
+ *p_transceiver_type = ETH_TRANSCEIVER_TYPE_UNKNOWN;
+
+ return 0;
+}
+static bool qed_is_transceiver_ready(u32 transceiver_state,
+ u32 transceiver_type)
+{
+ if ((transceiver_state & ETH_TRANSCEIVER_STATE_PRESENT) &&
+ ((transceiver_state & ETH_TRANSCEIVER_STATE_UPDATING) == 0x0) &&
+ (transceiver_type != ETH_TRANSCEIVER_TYPE_NONE))
+ return true;
+
+ return false;
+}
+
+int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, u32 *p_speed_mask)
+{
+ u32 transceiver_type, transceiver_state;
+
+ qed_mcp_get_transceiver_data(p_hwfn, p_ptt, &transceiver_state,
+ &transceiver_type);
+
+ if (qed_is_transceiver_ready(transceiver_state, transceiver_type) ==
+ false)
+ return -EINVAL;
+
+ switch (transceiver_type) {
+ case ETH_TRANSCEIVER_TYPE_1G_LX:
+ case ETH_TRANSCEIVER_TYPE_1G_SX:
+ case ETH_TRANSCEIVER_TYPE_1G_PCC:
+ case ETH_TRANSCEIVER_TYPE_1G_ACC:
+ case ETH_TRANSCEIVER_TYPE_1000BASET:
+ *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+ break;
+ case ETH_TRANSCEIVER_TYPE_10G_SR:
+ case ETH_TRANSCEIVER_TYPE_10G_LR:
+ case ETH_TRANSCEIVER_TYPE_10G_LRM:
+ case ETH_TRANSCEIVER_TYPE_10G_ER:
+ case ETH_TRANSCEIVER_TYPE_10G_PCC:
+ case ETH_TRANSCEIVER_TYPE_10G_ACC:
+ case ETH_TRANSCEIVER_TYPE_4x10G:
+ *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
+ break;
+ case ETH_TRANSCEIVER_TYPE_40G_LR4:
+ case ETH_TRANSCEIVER_TYPE_40G_SR4:
+ case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR:
+ case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR:
+ *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
+ break;
+ case ETH_TRANSCEIVER_TYPE_100G_AOC:
+ case ETH_TRANSCEIVER_TYPE_100G_SR4:
+ case ETH_TRANSCEIVER_TYPE_100G_LR4:
+ case ETH_TRANSCEIVER_TYPE_100G_ER4:
+ case ETH_TRANSCEIVER_TYPE_100G_ACC:
+ *p_speed_mask =
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
+ break;
+ case ETH_TRANSCEIVER_TYPE_25G_SR:
+ case ETH_TRANSCEIVER_TYPE_25G_LR:
+ case ETH_TRANSCEIVER_TYPE_25G_AOC:
+ case ETH_TRANSCEIVER_TYPE_25G_ACC_S:
+ case ETH_TRANSCEIVER_TYPE_25G_ACC_M:
+ case ETH_TRANSCEIVER_TYPE_25G_ACC_L:
+ *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
+ break;
+ case ETH_TRANSCEIVER_TYPE_25G_CA_N:
+ case ETH_TRANSCEIVER_TYPE_25G_CA_S:
+ case ETH_TRANSCEIVER_TYPE_25G_CA_L:
+ case ETH_TRANSCEIVER_TYPE_4x25G_CR:
+ *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+ break;
+ case ETH_TRANSCEIVER_TYPE_40G_CR4:
+ case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR:
+ *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+ break;
+ case ETH_TRANSCEIVER_TYPE_100G_CR4:
+ case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR:
+ *p_speed_mask =
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+ break;
+ case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR:
+ case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR:
+ case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC:
+ *p_speed_mask =
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
+ break;
+ case ETH_TRANSCEIVER_TYPE_XLPPI:
+ *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
+ break;
+ case ETH_TRANSCEIVER_TYPE_10G_BASET:
+ *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
+ NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+ break;
+ default:
+ DP_INFO(p_hwfn, "Unknown transcevier type 0x%x\n",
+ transceiver_type);
+ *p_speed_mask = 0xff;
+ break;
+ }
+
+ return 0;
+}
+
+int qed_mcp_get_board_config(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, u32 *p_board_config)
+{
+ u32 nvm_cfg_addr, nvm_cfg1_offset, port_cfg_addr;
+
+ if (IS_VF(p_hwfn->cdev))
+ return -EINVAL;
+
+ if (!qed_mcp_is_init(p_hwfn)) {
+ DP_NOTICE(p_hwfn, "MFW is not initialized!\n");
+ return -EBUSY;
+ }
+ if (!p_ptt) {
+ *p_board_config = NVM_CFG1_PORT_PORT_TYPE_UNDEFINED;
+ return -EINVAL;
+ }
+
+ nvm_cfg_addr = qed_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0);
+ nvm_cfg1_offset = qed_rd(p_hwfn, p_ptt, nvm_cfg_addr + 4);
+ port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
+ offsetof(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]);
+ *p_board_config = qed_rd(p_hwfn, p_ptt,
+ port_cfg_addr +
+ offsetof(struct nvm_cfg1_port,
+ board_cfg));
+
+ return 0;
+}
+
/* Old MFW has a global configuration for all PFs regarding RDMA support */
static void
qed_mcp_get_shmem_proto_legacy(struct qed_hwfn *p_hwfn,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index 80a6b5d..1adfe52 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -333,6 +333,52 @@ int qed_mcp_get_media_type(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u32 *media_type);
/**
+ * @brief Get transceiver data of the port.
+ *
+ * @param cdev - qed dev pointer
+ * @param p_ptt
+ * @param p_transceiver_state - transceiver state.
+ * @param p_transceiver_type - media type value
+ *
+ * @return int -
+ * 0 - Operation was successful.
+ * -EBUSY - Operation failed
+ */
+int qed_mcp_get_transceiver_data(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 *p_transceiver_state,
+ u32 *p_tranceiver_type);
+
+/**
+ * @brief Get transceiver supported speed mask.
+ *
+ * @param cdev - qed dev pointer
+ * @param p_ptt
+ * @param p_speed_mask - Bit mask of all supported speeds.
+ *
+ * @return int -
+ * 0 - Operation was successful.
+ * -EBUSY - Operation failed
+ */
+
+int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, u32 *p_speed_mask);
+
+/**
+ * @brief Get board configuration.
+ *
+ * @param cdev - qed dev pointer
+ * @param p_ptt
+ * @param p_board_config - Board config.
+ *
+ * @return int -
+ * 0 - Operation was successful.
+ * -EBUSY - Operation failed
+ */
+int qed_mcp_get_board_config(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, u32 *p_board_config);
+
+/**
* @brief General function for sending commands to the MCP
* mailbox. It acquire mutex lock for the entire
* operation, from sending the request until the MCP
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 7ff50b4..df3ad59 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -413,19 +413,42 @@ struct qede_link_mode_mapping {
};
static const struct qede_link_mode_mapping qed_lm_map[] = {
- {QED_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT},
{QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT},
{QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT},
{QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT},
- {QED_LM_1000baseT_Half_BIT, ETHTOOL_LINK_MODE_1000baseT_Half_BIT},
{QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
+ {QED_LM_10000baseT_Full_BIT, ETHTOOL_LINK_MODE_10000baseT_Full_BIT},
+ {QED_LM_2500baseX_Full_BIT, ETHTOOL_LINK_MODE_2500baseX_Full_BIT},
+ {QED_LM_Backplane_BIT, ETHTOOL_LINK_MODE_Backplane_BIT},
+ {QED_LM_1000baseKX_Full_BIT, ETHTOOL_LINK_MODE_1000baseKX_Full_BIT},
+ {QED_LM_10000baseKX4_Full_BIT, ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT},
{QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT},
+ {QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT},
+ {QED_LM_10000baseR_FEC_BIT, ETHTOOL_LINK_MODE_10000baseR_FEC_BIT},
{QED_LM_20000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT},
- {QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT},
+ {QED_LM_40000baseKR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT},
+ {QED_LM_40000baseCR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT},
+ {QED_LM_40000baseSR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT},
{QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT},
+ {QED_LM_25000baseCR_Full_BIT, ETHTOOL_LINK_MODE_25000baseCR_Full_BIT},
+ {QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT},
+ {QED_LM_25000baseSR_Full_BIT, ETHTOOL_LINK_MODE_25000baseSR_Full_BIT},
+ {QED_LM_50000baseCR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT},
{QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT},
{QED_LM_100000baseKR4_Full_BIT,
- ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT},
+ ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT},
+ {QED_LM_100000baseSR4_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT},
+ {QED_LM_100000baseCR4_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT},
+ {QED_LM_100000baseLR4_ER4_Full_BIT,
+ ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT},
+ {QED_LM_50000baseSR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT},
+ {QED_LM_1000baseX_Full_BIT, ETHTOOL_LINK_MODE_1000baseX_Full_BIT},
+ {QED_LM_10000baseCR_Full_BIT, ETHTOOL_LINK_MODE_10000baseCR_Full_BIT},
+ {QED_LM_10000baseSR_Full_BIT, ETHTOOL_LINK_MODE_10000baseSR_Full_BIT},
+ {QED_LM_10000baseLR_Full_BIT, ETHTOOL_LINK_MODE_10000baseLR_Full_BIT},
+ {QED_LM_10000baseLRM_Full_BIT, ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT},
};
#define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name) \
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index dee3c9c..a47321a 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -667,15 +667,35 @@ enum qed_link_mode_bits {
QED_LM_Autoneg_BIT = BIT(1),
QED_LM_Asym_Pause_BIT = BIT(2),
QED_LM_Pause_BIT = BIT(3),
- QED_LM_1000baseT_Half_BIT = BIT(4),
- QED_LM_1000baseT_Full_BIT = BIT(5),
+ QED_LM_1000baseT_Full_BIT = BIT(4),
+ QED_LM_10000baseT_Full_BIT = BIT(5),
QED_LM_10000baseKR_Full_BIT = BIT(6),
QED_LM_20000baseKR2_Full_BIT = BIT(7),
QED_LM_25000baseKR_Full_BIT = BIT(8),
QED_LM_40000baseLR4_Full_BIT = BIT(9),
QED_LM_50000baseKR2_Full_BIT = BIT(10),
QED_LM_100000baseKR4_Full_BIT = BIT(11),
- QED_LM_COUNT = 11
+ QED_LM_2500baseX_Full_BIT = BIT(12),
+ QED_LM_Backplane_BIT = BIT(13),
+ QED_LM_1000baseKX_Full_BIT = BIT(14),
+ QED_LM_10000baseKX4_Full_BIT = BIT(15),
+ QED_LM_10000baseR_FEC_BIT = BIT(16),
+ QED_LM_40000baseKR4_Full_BIT = BIT(17),
+ QED_LM_40000baseCR4_Full_BIT = BIT(18),
+ QED_LM_40000baseSR4_Full_BIT = BIT(19),
+ QED_LM_25000baseCR_Full_BIT = BIT(20),
+ QED_LM_25000baseSR_Full_BIT = BIT(21),
+ QED_LM_50000baseCR2_Full_BIT = BIT(22),
+ QED_LM_100000baseSR4_Full_BIT = BIT(23),
+ QED_LM_100000baseCR4_Full_BIT = BIT(24),
+ QED_LM_100000baseLR4_ER4_Full_BIT = BIT(25),
+ QED_LM_50000baseSR2_Full_BIT = BIT(26),
+ QED_LM_1000baseX_Full_BIT = BIT(27),
+ QED_LM_10000baseCR_Full_BIT = BIT(28),
+ QED_LM_10000baseSR_Full_BIT = BIT(29),
+ QED_LM_10000baseLR_Full_BIT = BIT(30),
+ QED_LM_10000baseLRM_Full_BIT = BIT(31),
+ QED_LM_COUNT = 32
};
struct qed_link_params {
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next 2/5] qed: Added supported transceiver modes, speed capability and board config to HSI.
From: Rahul Verma @ 2018-10-16 10:59 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, Dept-EngEverestLinuxL2, Rahul Verma
In-Reply-To: <20181016105922.25562-1-rahul.verma@cavium.com>
From: Rahul Verma <Rahul.Verma@cavium.com>
Added transceiver modes with different speed and media type,
speed capability and supported board types in HSI, which
will be utilizing to display correct specification of link
modes and speed type.
Signed-off-by: Rahul Verma <Rahul.Verma@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_hsi.h | 54 ++++++++++++++++++++++++++++++-
1 file changed, 53 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index f2dfc7a..5c221eb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -12207,11 +12207,56 @@ struct public_port {
u32 transceiver_data;
#define ETH_TRANSCEIVER_STATE_MASK 0x000000FF
#define ETH_TRANSCEIVER_STATE_SHIFT 0x00000000
+#define ETH_TRANSCEIVER_STATE_OFFSET 0x00000000
#define ETH_TRANSCEIVER_STATE_UNPLUGGED 0x00000000
#define ETH_TRANSCEIVER_STATE_PRESENT 0x00000001
#define ETH_TRANSCEIVER_STATE_VALID 0x00000003
#define ETH_TRANSCEIVER_STATE_UPDATING 0x00000008
-
+#define ETH_TRANSCEIVER_TYPE_MASK 0x0000FF00
+#define ETH_TRANSCEIVER_TYPE_OFFSET 0x8
+#define ETH_TRANSCEIVER_TYPE_NONE 0x00
+#define ETH_TRANSCEIVER_TYPE_UNKNOWN 0xFF
+#define ETH_TRANSCEIVER_TYPE_1G_PCC 0x01
+#define ETH_TRANSCEIVER_TYPE_1G_ACC 0x02
+#define ETH_TRANSCEIVER_TYPE_1G_LX 0x03
+#define ETH_TRANSCEIVER_TYPE_1G_SX 0x04
+#define ETH_TRANSCEIVER_TYPE_10G_SR 0x05
+#define ETH_TRANSCEIVER_TYPE_10G_LR 0x06
+#define ETH_TRANSCEIVER_TYPE_10G_LRM 0x07
+#define ETH_TRANSCEIVER_TYPE_10G_ER 0x08
+#define ETH_TRANSCEIVER_TYPE_10G_PCC 0x09
+#define ETH_TRANSCEIVER_TYPE_10G_ACC 0x0a
+#define ETH_TRANSCEIVER_TYPE_XLPPI 0x0b
+#define ETH_TRANSCEIVER_TYPE_40G_LR4 0x0c
+#define ETH_TRANSCEIVER_TYPE_40G_SR4 0x0d
+#define ETH_TRANSCEIVER_TYPE_40G_CR4 0x0e
+#define ETH_TRANSCEIVER_TYPE_100G_AOC 0x0f
+#define ETH_TRANSCEIVER_TYPE_100G_SR4 0x10
+#define ETH_TRANSCEIVER_TYPE_100G_LR4 0x11
+#define ETH_TRANSCEIVER_TYPE_100G_ER4 0x12
+#define ETH_TRANSCEIVER_TYPE_100G_ACC 0x13
+#define ETH_TRANSCEIVER_TYPE_100G_CR4 0x14
+#define ETH_TRANSCEIVER_TYPE_4x10G_SR 0x15
+#define ETH_TRANSCEIVER_TYPE_25G_CA_N 0x16
+#define ETH_TRANSCEIVER_TYPE_25G_ACC_S 0x17
+#define ETH_TRANSCEIVER_TYPE_25G_CA_S 0x18
+#define ETH_TRANSCEIVER_TYPE_25G_ACC_M 0x19
+#define ETH_TRANSCEIVER_TYPE_25G_CA_L 0x1a
+#define ETH_TRANSCEIVER_TYPE_25G_ACC_L 0x1b
+#define ETH_TRANSCEIVER_TYPE_25G_SR 0x1c
+#define ETH_TRANSCEIVER_TYPE_25G_LR 0x1d
+#define ETH_TRANSCEIVER_TYPE_25G_AOC 0x1e
+#define ETH_TRANSCEIVER_TYPE_4x10G 0x1f
+#define ETH_TRANSCEIVER_TYPE_4x25G_CR 0x20
+#define ETH_TRANSCEIVER_TYPE_1000BASET 0x21
+#define ETH_TRANSCEIVER_TYPE_10G_BASET 0x22
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR 0x30
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR 0x31
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR 0x32
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR 0x33
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR 0x34
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR 0x35
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC 0x36
u32 wol_info;
u32 wol_pkt_len;
u32 wol_pkt_details;
@@ -13199,6 +13244,13 @@ struct nvm_cfg1_port {
u32 transceiver_00;
u32 device_ids;
u32 board_cfg;
+#define NVM_CFG1_PORT_PORT_TYPE_MASK 0x000000FF
+#define NVM_CFG1_PORT_PORT_TYPE_OFFSET 0
+#define NVM_CFG1_PORT_PORT_TYPE_UNDEFINED 0x0
+#define NVM_CFG1_PORT_PORT_TYPE_MODULE 0x1
+#define NVM_CFG1_PORT_PORT_TYPE_BACKPLANE 0x2
+#define NVM_CFG1_PORT_PORT_TYPE_EXT_PHY 0x3
+#define NVM_CFG1_PORT_PORT_TYPE_MODULE_SLAVE 0x4
u32 mnm_10g_cap;
u32 mnm_10g_ctrl;
u32 mnm_10g_misc;
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next 1/5] qed: Align local and global PTT to propagate through the APIs.
From: Rahul Verma @ 2018-10-16 10:59 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, Dept-EngEverestLinuxL2, Rahul Verma
In-Reply-To: <20181016105922.25562-1-rahul.verma@cavium.com>
From: Rahul Verma <Rahul.Verma@cavium.com>
Align the use of local PTT to propagate through the qed_mcp* API's.
Global ptt should not be used.
Register access should be done through layers. Register address is
mapped into a PTT, PF translation table. Several interface functions
require a PTT to direct read/write into register. There is a pool of
PTT maintained, and several PTT are used simultaneously to access
device registers in different flows. Same PTT should not be used in
flows that can run concurrently.
To avoid running out of PTT resources, too many PTT should not be
acquired without releasing them. Every PF has a global PTT, which is
used throughout the life of PF, in most important flows for register
access. Generic functions acquire the PTT locally and release after
the use. This patch aligns the use of Global PTT and Local PTT
accordingly.
Signed-off-by: Rahul Verma <rahul.verma@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed.h | 2 +-
drivers/net/ethernet/qlogic/qed/qed_main.c | 22 ++++++++++++++++++----
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 27 ++++++++++++---------------
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 5 +++--
drivers/net/ethernet/qlogic/qed/qed_vf.c | 2 +-
5 files changed, 35 insertions(+), 23 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index 5f0962d..d9a03ab 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -915,7 +915,7 @@ void qed_set_fw_mac_addr(__le16 *fw_msb,
/* Prototypes */
int qed_fill_dev_info(struct qed_dev *cdev,
struct qed_dev_info *dev_info);
-void qed_link_update(struct qed_hwfn *hwfn);
+void qed_link_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt);
u32 qed_unzip_data(struct qed_hwfn *p_hwfn,
u32 input_len, u8 *input_buf,
u32 max_size, u8 *unzip_buf);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 75d217a..8c7cbbd 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -1463,6 +1463,7 @@ static int qed_get_link_data(struct qed_hwfn *hwfn,
}
static void qed_fill_link(struct qed_hwfn *hwfn,
+ struct qed_ptt *ptt,
struct qed_link_output *if_link)
{
struct qed_mcp_link_params params;
@@ -1549,7 +1550,7 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
/* TODO - fill duplex properly */
if_link->duplex = DUPLEX_FULL;
- qed_mcp_get_media_type(hwfn->cdev, &media_type);
+ qed_mcp_get_media_type(hwfn, ptt, &media_type);
if_link->port = qed_get_port_type(media_type);
if_link->autoneg = params.speed.autoneg;
@@ -1607,21 +1608,34 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
static void qed_get_current_link(struct qed_dev *cdev,
struct qed_link_output *if_link)
{
+ struct qed_hwfn *hwfn;
+ struct qed_ptt *ptt;
int i;
- qed_fill_link(&cdev->hwfns[0], if_link);
+ hwfn = &cdev->hwfns[0];
+ if (IS_PF(cdev)) {
+ ptt = qed_ptt_acquire(hwfn);
+ if (ptt) {
+ qed_fill_link(hwfn, ptt, if_link);
+ qed_ptt_release(hwfn, ptt);
+ } else {
+ DP_NOTICE(hwfn, "Failed to fill link; No PTT\n");
+ }
+ } else {
+ qed_fill_link(hwfn, NULL, if_link);
+ }
for_each_hwfn(cdev, i)
qed_inform_vf_link_state(&cdev->hwfns[i]);
}
-void qed_link_update(struct qed_hwfn *hwfn)
+void qed_link_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt)
{
void *cookie = hwfn->cdev->ops_cookie;
struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common;
struct qed_link_output if_link;
- qed_fill_link(hwfn, &if_link);
+ qed_fill_link(hwfn, ptt, &if_link);
qed_inform_vf_link_state(hwfn);
if (IS_LEAD_HWFN(hwfn) && cookie)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index b06e4cb..92c5950 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1447,7 +1447,7 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn,
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);
+ qed_link_update(p_hwfn, p_ptt);
out:
spin_unlock_bh(&p_hwfn->mcp_info->link_lock);
}
@@ -1867,12 +1867,10 @@ int qed_mcp_get_mbi_ver(struct qed_hwfn *p_hwfn,
return 0;
}
-int qed_mcp_get_media_type(struct qed_dev *cdev, u32 *p_media_type)
+int qed_mcp_get_media_type(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, u32 *p_media_type)
{
- struct qed_hwfn *p_hwfn = &cdev->hwfns[0];
- struct qed_ptt *p_ptt;
-
- if (IS_VF(cdev))
+ if (IS_VF(p_hwfn->cdev))
return -EINVAL;
if (!qed_mcp_is_init(p_hwfn)) {
@@ -1880,16 +1878,15 @@ int qed_mcp_get_media_type(struct qed_dev *cdev, u32 *p_media_type)
return -EBUSY;
}
- *p_media_type = MEDIA_UNSPECIFIED;
-
- p_ptt = qed_ptt_acquire(p_hwfn);
- if (!p_ptt)
- return -EBUSY;
-
- *p_media_type = qed_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
- offsetof(struct public_port, media_type));
+ if (!p_ptt) {
+ *p_media_type = MEDIA_UNSPECIFIED;
+ return -EINVAL;
+ }
- qed_ptt_release(p_hwfn, p_ptt);
+ *p_media_type = qed_rd(p_hwfn, p_ptt,
+ p_hwfn->mcp_info->port_addr +
+ offsetof(struct public_port,
+ media_type));
return 0;
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index 85e6b39..80a6b5d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -322,14 +322,15 @@ int qed_mcp_get_mbi_ver(struct qed_hwfn *p_hwfn,
* @brief Get media type value of the port.
*
* @param cdev - qed dev pointer
+ * @param p_ptt
* @param mfw_ver - media type value
*
* @return int -
* 0 - Operation was successul.
* -EBUSY - Operation failed
*/
-int qed_mcp_get_media_type(struct qed_dev *cdev,
- u32 *media_type);
+int qed_mcp_get_media_type(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt, u32 *media_type);
/**
* @brief General function for sending commands to the MCP
diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c
index be118d0..b6cccf4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_vf.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c
@@ -1688,7 +1688,7 @@ static void qed_handle_bulletin_change(struct qed_hwfn *hwfn)
ops->ports_update(cookie, vxlan_port, geneve_port);
/* Always update link configuration according to bulletin */
- qed_link_update(hwfn);
+ qed_link_update(hwfn, NULL);
}
void qed_iov_vf_task(struct work_struct *work)
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next 0/5] Align PTT and add various link modes.
From: Rahul Verma @ 2018-10-16 10:59 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, Dept-EngEverestLinuxL2, Rahul Verma
From: Rahul Verma <Rahul.Verma@cavium.com>
This series aligns the ptt propagation as local ptt or global ptt.
Adds new transceiver modes, speed capabilities and board config,
which is utilized to display the enhanced link modes, media types
and speed. Enhances the link with detailed information.
Rahul Verma (5):
qed: Align local and global PTT to propagate through the APIs.
qed: Added supported transceiver modes, speed capability and board
config to HSI.
qed: Add supported link and advertise link to display in ethtool.
qede: Check available link modes before link set from ethtool.
qed: Prevent link getting down in case of autoneg-off.
drivers/net/ethernet/qlogic/qed/qed.h | 2 +-
drivers/net/ethernet/qlogic/qed/qed_hsi.h | 54 ++++-
drivers/net/ethernet/qlogic/qed/qed_main.c | 259 ++++++++++++++++++------
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 201 +++++++++++++++++-
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 51 ++++-
drivers/net/ethernet/qlogic/qed/qed_vf.c | 2 +-
drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 95 ++++++---
include/linux/qed/qed_if.h | 26 ++-
8 files changed, 587 insertions(+), 103 deletions(-)
--
1.8.3.1
^ permalink raw reply
* [PATCH 1/2] arm64: dts: clearfog-gt-8k: fix USB regulator gpio polarity
From: Baruch Siach @ 2018-10-16 10:50 UTC (permalink / raw)
To: Jason Cooper, Andrew Lunn, Gregory Clement, Sebastian Hesselbarth
Cc: linux-arm-kernel, Russell King, Ori Shemtov, Florian Fainelli,
netdev, Linus Walleij, Baruch Siach
The fixed regulator driver ignores the gpio flags, so this change has
no practical effect in the current implementation. Fix it anyway to
correct the hardware description.
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
---
arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
index aea9c220ae6a..af1310c53bc8 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
@@ -42,7 +42,7 @@
v_5v0_usb3_hst_vbus: regulator-usb3-vbus0 {
compatible = "regulator-fixed";
- gpio = <&cp0_gpio2 15 GPIO_ACTIVE_HIGH>;
+ gpio = <&cp0_gpio2 15 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&cp0_xhci_vbus_pins>;
regulator-name = "v_5v0_usb3_hst_vbus";
--
2.19.1
^ permalink raw reply related
* [PATCH 2/2] arm64: dts: clearfog-gt-8k: 1G eth PHY reset signal
From: Baruch Siach @ 2018-10-16 10:50 UTC (permalink / raw)
To: Jason Cooper, Andrew Lunn, Gregory Clement, Sebastian Hesselbarth
Cc: linux-arm-kernel, Russell King, Ori Shemtov, Florian Fainelli,
netdev, Linus Walleij, Baruch Siach
In-Reply-To: <d02745d924c2ad65cbd1194fc35d12796613722d.1539687053.git.baruch@tkos.co.il>
This reset signal controls the Marvell 1512 1G PHY.
Note that current implementation queries the PHY over the MDIO bus
(get_phy_device() call from of_mdiobus_register_phy()) before reset
signal deassert. If the PHY reset signal is asserted at boot time, PHY
registration fails. So current code relies on the bootloader to deassert
the reset signal.
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
---
arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
index af1310c53bc8..73df0ef5e0c4 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
@@ -337,6 +337,10 @@
*/
marvell,reg-init = <3 16 0 0x1017>;
reg = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_copper_eth_phy_reset>;
+ reset-gpios = <&cp1_gpio1 11 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <10000>;
};
switch0: switch0@4 {
--
2.19.1
^ permalink raw reply related
* Re: [RFC] virtio_net: add local_bh_disable() around u64_stats_update_begin
From: Sebastian Andrzej Siewior @ 2018-10-16 18:21 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Michael S. Tsirkin, netdev, virtualization, tglx, David S. Miller
In-Reply-To: <20181016105930.55e8fe5d@xeon-e3>
On 2018-10-16 10:59:30 [-0700], Stephen Hemminger wrote:
> Since there already is u64_stats_update_begin_irqsave inline, why not introduce
> u64_stats_update_begin_bh which encapsulates the local_bh_disable
CPU0 CPU1
refill_work() virtnet_receive()
try_fill_recv() try_fill_recv()
u64_stats_update_begin_bh() u64_stats_update_begin_bh()
both CPUs may operate on the `rq'.
Sebastian
^ permalink raw reply
* [RFC PATCH net-next 2/4] net: 8021q: vlan_core: allow use list of vlans for real device
From: Ivan Khoronzhuk @ 2018-10-16 18:20 UTC (permalink / raw)
To: grygorii.strashko, davem
Cc: linux-omap, netdev, linux-kernel, alexander.h.duyck,
Ivan Khoronzhuk
In-Reply-To: <20181016182035.18234-1-ivan.khoronzhuk@linaro.org>
It's redundancy for the drivers to hold the list of vlans when
absolutely the same list exists in vlan core. In most cases it's
needed only to traverse the vlan devices, their vids and sync some
settings with h/w, so add API to simplify this.
At least some of these drivers also can benefit:
grep "for_each.*vid" -r drivers/net/ethernet/
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c:
drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c:
drivers/net/ethernet/qlogic/qlge/qlge_main.c:
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c:
drivers/net/ethernet/via/via-rhine.c:
drivers/net/ethernet/via/via-velocity.c:
drivers/net/ethernet/intel/igb/igb_main.c:
drivers/net/ethernet/intel/ice/ice_main.c:
drivers/net/ethernet/intel/e1000/e1000_main.c:
drivers/net/ethernet/intel/i40e/i40e_main.c:
drivers/net/ethernet/intel/e1000e/netdev.c:
drivers/net/ethernet/intel/igbvf/netdev.c:
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:
drivers/net/ethernet/intel/ixgb/ixgb_main.c:
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:
drivers/net/ethernet/amd/xgbe/xgbe-dev.c:
drivers/net/ethernet/emulex/benet/be_main.c:
drivers/net/ethernet/neterion/vxge/vxge-main.c:
drivers/net/ethernet/adaptec/starfire.c:
drivers/net/ethernet/brocade/bna/bnad.c:
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
---
include/linux/if_vlan.h | 10 ++++++++++
net/8021q/vlan_core.c | 27 +++++++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 83ea4df6ab81..4ae3993f7166 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -133,6 +133,9 @@ struct vlan_pcpu_stats {
extern struct net_device *__vlan_find_dev_deep_rcu(struct net_device *real_dev,
__be16 vlan_proto, u16 vlan_id);
+extern int vlan_for_each(struct net_device *dev,
+ int (*action)(struct net_device *dev, int vid,
+ void *arg), void *arg);
extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
extern u16 vlan_dev_vlan_id(const struct net_device *dev);
extern __be16 vlan_dev_vlan_proto(const struct net_device *dev);
@@ -236,6 +239,13 @@ __vlan_find_dev_deep_rcu(struct net_device *real_dev,
return NULL;
}
+static inline int
+vlan_for_each(struct net_device *dev,
+ int (*action)(struct net_device *dev, int vid, void *arg),
+ void *arg)
+{
+}
+
static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev)
{
BUG();
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 4f60e86f4b8d..6308b5427a66 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -223,6 +223,33 @@ static int vlan_kill_rx_filter_info(struct net_device *dev, __be16 proto, u16 vi
return -ENODEV;
}
+int vlan_for_each(struct net_device *dev,
+ int (*action)(struct net_device *dev, int vid, void *arg),
+ void *arg)
+{
+ struct vlan_vid_info *vid_info;
+ struct vlan_info *vlan_info;
+ struct net_device *vdev;
+ int ret;
+
+ ASSERT_RTNL();
+
+ vlan_info = rtnl_dereference(dev->vlan_info);
+ if (!vlan_info)
+ return 0;
+
+ list_for_each_entry(vid_info, &vlan_info->vid_list, list) {
+ vdev = vlan_group_get_device(&vlan_info->grp, vid_info->proto,
+ vid_info->vid);
+ ret = action(vdev, vid_info->vid, arg);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(vlan_for_each);
+
int vlan_filter_push_vids(struct vlan_info *vlan_info, __be16 proto)
{
struct net_device *real_dev = vlan_info->real_dev;
--
2.17.1
^ permalink raw reply related
* [RFC PATCH net-next 1/4] net: core: dev_addr_lists: add auxiliary func to handle reference address updates
From: Ivan Khoronzhuk @ 2018-10-16 18:20 UTC (permalink / raw)
To: grygorii.strashko, davem
Cc: linux-omap, netdev, linux-kernel, alexander.h.duyck,
Ivan Khoronzhuk
In-Reply-To: <20181016182035.18234-1-ivan.khoronzhuk@linaro.org>
In order to avoid all table update, and only remove or add new
address, the auxiliary function exists, named __hw_addr_sync_dev().
It allows end driver do nothing when nothing changed and add/rm when
concrete address is firstly added or lastly removed. But it doesn't
include cases when an address of real device or vlan was reused by
other vlans or vlan/macval devices.
For handaling events when address was reused/unreused the patch adds
new auxiliary routine - __hw_addr_ref_sync_dev(). It allows to do
nothing when nothing was changed and do updates only for an address
being added/reused/deleted/unreused. Thus, clone address changes for
vlans can be mirrored in the table. The function is exclusive with
__hw_addr_sync_dev(). It's responsibility of the end driver to
identify address vlan device, if it needs so.
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
---
include/linux/netdevice.h | 10 ++++
net/core/dev_addr_lists.c | 97 +++++++++++++++++++++++++++++++++++++++
2 files changed, 107 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index dc1d9ed33b31..de95f96a6352 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4048,6 +4048,16 @@ int __hw_addr_sync_dev(struct netdev_hw_addr_list *list,
int (*sync)(struct net_device *, const unsigned char *),
int (*unsync)(struct net_device *,
const unsigned char *));
+int __hw_addr_ref_sync_dev(struct netdev_hw_addr_list *list,
+ struct net_device *dev,
+ int (*sync)(struct net_device *,
+ const unsigned char *, int),
+ int (*unsync)(struct net_device *,
+ const unsigned char *, int));
+void __hw_addr_ref_unsync_dev(struct netdev_hw_addr_list *list,
+ struct net_device *dev,
+ int (*unsync)(struct net_device *,
+ const unsigned char *, int));
void __hw_addr_unsync_dev(struct netdev_hw_addr_list *list,
struct net_device *dev,
int (*unsync)(struct net_device *,
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index d884d8f5f0e5..1385d75fe5ea 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -277,6 +277,103 @@ int __hw_addr_sync_dev(struct netdev_hw_addr_list *list,
}
EXPORT_SYMBOL(__hw_addr_sync_dev);
+/**
+ * __hw_addr_ref_sync_dev - Synchronize device's multicast address list taking
+ * into account references
+ * @list: address list to synchronize
+ * @dev: device to sync
+ * @sync: function to call if address or reference on it should be added
+ * @unsync: function to call if address or some reference on it should removed
+ *
+ * This function is intended to be called from the ndo_set_rx_mode
+ * function of devices that require explicit address or references on it
+ * add/remove notifications. The unsync function may be NULL in which case
+ * the addresses or references on it requiring removal will simply be
+ * removed without any notification to the device. That is responsibility of
+ * the driver to identify and distribute address or references on it between
+ * internal address tables.
+ **/
+int __hw_addr_ref_sync_dev(struct netdev_hw_addr_list *list,
+ struct net_device *dev,
+ int (*sync)(struct net_device *,
+ const unsigned char *, int),
+ int (*unsync)(struct net_device *,
+ const unsigned char *, int))
+{
+ struct netdev_hw_addr *ha, *tmp;
+ int err, keep_sync;
+
+ /* first go through and flush out any unsynced/stale entries */
+ list_for_each_entry_safe(ha, tmp, &list->list, list) {
+ /* sync if address is not used */
+ if ((ha->sync_cnt << 1) <= ha->refcount)
+ continue;
+
+ /* if fails defer unsyncing address */
+ keep_sync = ha->refcount - ha->sync_cnt;
+ if (unsync && unsync(dev, ha->addr, keep_sync))
+ continue;
+
+ ha->refcount = (keep_sync << 1) + 1;
+ ha->sync_cnt = keep_sync;
+ __hw_addr_del_entry(list, ha, false, false);
+ }
+
+ /* go through and sync updated/new entries to the list */
+ list_for_each_entry_safe(ha, tmp, &list->list, list) {
+ /* sync if address added or reused */
+ if ((ha->sync_cnt << 1) >= ha->refcount)
+ continue;
+
+ keep_sync = ha->refcount - ha->sync_cnt;
+ err = sync(dev, ha->addr, keep_sync);
+ if (err)
+ return err;
+
+ ha->refcount = keep_sync << 1;
+ ha->sync_cnt = keep_sync;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(__hw_addr_ref_sync_dev);
+
+/**
+ * __hw_addr_ref_unsync_dev - Remove synchronized addresses and references on
+ * it from device
+ * @list: address list to remove synchronized addresses (references on it) from
+ * @dev: device to sync
+ * @unsync: function to call if address and references on it should be removed
+ *
+ * Remove all addresses that were added to the device by
+ * __hw_addr_ref_sync_dev(). This function is intended to be called from the
+ * ndo_stop or ndo_open functions on devices that require explicit address (or
+ * references on it) add/remove notifications. If the unsync function pointer
+ * is NULL then this function can be used to just reset the sync_cnt for the
+ * addresses in the list.
+ **/
+void __hw_addr_ref_unsync_dev(struct netdev_hw_addr_list *list,
+ struct net_device *dev,
+ int (*unsync)(struct net_device *,
+ const unsigned char *, int))
+{
+ struct netdev_hw_addr *ha, *tmp;
+
+ list_for_each_entry_safe(ha, tmp, &list->list, list) {
+ if (!ha->sync_cnt)
+ continue;
+
+ /* if fails defer unsyncing address */
+ if (unsync && unsync(dev, ha->addr, ha->sync_cnt))
+ continue;
+
+ ha->refcount -= ha->sync_cnt - 1;
+ ha->sync_cnt = 0;
+ __hw_addr_del_entry(list, ha, false, false);
+ }
+}
+EXPORT_SYMBOL(__hw_addr_ref_unsync_dev);
+
/**
* __hw_addr_unsync_dev - Remove synchronized addresses from device
* @list: address list to remove synchronized addresses from
--
2.17.1
^ permalink raw reply related
* Re: [PATCH] virtio_net: enable tx after resuming from suspend
From: ake @ 2018-10-16 10:15 UTC (permalink / raw)
To: Jason Wang
Cc: Michael S. Tsirkin, David S. Miller, virtualization, netdev,
linux-kernel
In-Reply-To: <024619cc-9b1b-dac2-18cc-5d757a76b1e3@redhat.com>
On 2018年10月16日 17:53, Jason Wang wrote:
>
> On 2018/10/15 下午6:08, ake wrote:
>>
>> On 2018年10月12日 18:18, ake wrote:
>>>
>>> On 2018年10月12日 17:23, Jason Wang wrote:
>>>>
>>>> On 2018年10月12日 12:30, ake wrote:
>>>>> On 2018年10月11日 22:06, Jason Wang wrote:
>>>>>> On 2018年10月11日 18:22, ake wrote:
>>>>>>> On 2018年10月11日 18:44, Jason Wang wrote:
>>>>>>>> On 2018年10月11日 15:51, Ake Koomsin wrote:
>>>>>>>>> commit 713a98d90c5e ("virtio-net: serialize tx routine during
>>>>>>>>> reset")
>>>>>>>>> disabled the virtio tx before going to suspend to avoid a use
>>>>>>>>> after
>>>>>>>>> free.
>>>>>>>>> However, after resuming, it causes the virtio_net device to
>>>>>>>>> lose its
>>>>>>>>> network connectivity.
>>>>>>>>>
>>>>>>>>> To solve the issue, we need to enable tx after resuming.
>>>>>>>>>
>>>>>>>>> Fixes commit 713a98d90c5e ("virtio-net: serialize tx routine
>>>>>>>>> during
>>>>>>>>> reset")
>>>>>>>>> Signed-off-by: Ake Koomsin <ake@igel.co.jp>
>>>>>>>>> ---
>>>>>>>>> drivers/net/virtio_net.c | 1 +
>>>>>>>>> 1 file changed, 1 insertion(+)
>>>>>>>>>
>>>>>>>>> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
>>>>>>>>> index dab504ec5e50..3453d80f5f81 100644
>>>>>>>>> --- a/drivers/net/virtio_net.c
>>>>>>>>> +++ b/drivers/net/virtio_net.c
>>>>>>>>> @@ -2256,6 +2256,7 @@ static int virtnet_restore_up(struct
>>>>>>>>> virtio_device *vdev)
>>>>>>>>> }
>>>>>>>>> netif_device_attach(vi->dev);
>>>>>>>>> + netif_start_queue(vi->dev);
>>>>>>>> I believe this is duplicated with netif_tx_wake_all_queues() in
>>>>>>>> netif_device_attach() above?
>>>>>>> Thank you for your review.
>>>>>>>
>>>>>>> If both netif_tx_wake_all_queues() and netif_start_queue() result in
>>>>>>> clearing __QUEUE_STATE_DRV_XOFF, then is it possible that some
>>>>>>> conditions in netif_device_attach() is not satisfied?
>>>>>> Yes, maybe. One case I can see now is when the device is down, in
>>>>>> this
>>>>>> case netif_device_attach() won't try to wakeup the queue.
>>>>>>
>>>>>>> Without
>>>>>>> netif_start_queue(), the virtio_net device does not resume properly
>>>>>>> after waking up.
>>>>>> How do you trigger the issue? Just do suspend/resume?
>>>>> Yes, simply suspend and resume.
>>>>>
>>>>> Here is how I trigger the issue:
>>>>>
>>>>> 1) Start the Virtual Machine Manager GUI program.
>>>>> 2) Create a guest Linux OS. Make sure that the guest OS kernel is
>>>>> >= 4.12. Make sure that it uses virtio_net as its network device.
>>>>> In addition, make sure that the video adapter is VGA. Otherwise,
>>>>> waking up with the virtual power button does not work.
>>>>> 3) After installing the guest OS, log in, and test the network
>>>>> connectivity by ping the host machine.
>>>>> 4) Suspend. After this, the screen is blank.
>>>>> 5) Resume by hitting the virtual power button. The login screen
>>>>> appears again.
>>>>> 6) Log in again. The guest loses its network connection.
>>>>>
>>>>> In my test:
>>>>> Guest: Ubuntu 16.04/18.04 with kernel 4.15.0-36-generic
>>>>> Host: Ubuntu 16.04 with kernel 4.15.0-36-generic/4.4.0-137-generic
>>>> I can not reproduce this issue if virtio-net interface is up in guest
>>>> before the suspend. I'm using net-next.git and qemu master. But I do
>>>> reproduce when virtio-net interface is down in guest before suspend,
>>>> after resume, even if I make it up, the network is still lost.
>>>>
>>>> I think the interface is up in your case, but please confirm this.
>>> If you mean the interface state before I hit the suspend button,
>>> the answer is yes. The interface is up before I suspend the guest
>>> machine.
>>>
>>> Note that my current QEMU version is QEMU emulator version 2.5.0
>>> (Debian 1:2.5+dfsg-5ubuntu10.32).
>>>
>>> I will try with net-next.git and qemu master later and see if I can
>>> reproduce the issue.
>> Update. I tried with net-next and qemu master. Interestingly, the result
>> is different from yours. The network is lost even if the virtio_net
>> interface is up before suspending.
>>
>> Host: Ubuntu 16.04 with net-next kernel (default configuration)
>> Guest: Ubuntu 18.04 with net-next kernel (default configuration)
>> Qemu: master
>> Qemu command:
>> qemu-system-x86_64 -cpu host -m 2048 -enable-kvm \
>> -bios /usr/share/OVMF/OVMF_CODE.fd \
>> -drive file=/var/lib/libvirt/images/virtio_test.qcow2,if=virtio \
>> -netdev user,id=hostnet0 \
>> -device virtio-net-pci,netdev=hostnet0 \
>> -device VGA,id=video0,vgamem_mb=16 \
>> -global PIIX4_PM.disable_s3=1 \
>> -global PIIX4_PM.disable_s4=1 -monitor stdio
>
>
> Interesting, just notice you're using userspace network. To isolate the
> issue, can you retry with e.g tap or e1000 to make sure it's not a fault
> of slirp or virito-net?
I will try.
> Thanks
>
There is another thing that I want to discuss. I notice that
netif_device_detach() should result in setting __QUEUE_STATE_DRV_XOFF if
the network interface is running. By calling netif_tx_disable() after
netif_device_detach(), isn't it redundant in case of the network
interface is running? If the goal is to serialize tx routine, would
netif_tx_lock() and net_tx_unlock() are more appropriate? Like this:
netif_tx_lock(vi->dev);
netif_device_detach(vi->dev);
netif_tx_unlock(vi->dev);
Currently, netif_tx_disable() seems to disturb the symmetry of
netif_device_detach() and netif_device_attach(). That is the reason
why you can reproduce the problem when the interface is down before
suspending.
^ permalink raw reply
* [PATCH] brcmfmac: fix spelling mistake "Retreiving" -> "Retrieving"
From: Colin King @ 2018-10-16 17:43 UTC (permalink / raw)
To: Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
Wright Feng, Kalle Valo, David S . Miller, Pieter-Paul Giesberts,
linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
netdev
Cc: kernel-janitors, linux-kernel
From: Colin Ian King <colin.king@canonical.com>
Trivial fix to spelling mistake in brcmf_err error message.
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index 94044a7a6021..9f6938f8b1ca 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -214,7 +214,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
sizeof(ifp->mac_addr));
if (err < 0) {
- brcmf_err("Retreiving cur_etheraddr failed, %d\n", err);
+ brcmf_err("Retrieving cur_etheraddr failed, %d\n", err);
goto done;
}
memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN);
@@ -269,7 +269,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
strcpy(buf, "ver");
err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
if (err < 0) {
- brcmf_err("Retreiving version information failed, %d\n",
+ brcmf_err("Retrieving version information failed, %d\n",
err);
goto done;
}
--
2.19.1
^ permalink raw reply related
* Re: [PATCH v4] Wait for running BPF programs when updating map-in-map
From: Joel Fernandes @ 2018-10-16 17:39 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Daniel Colascione, Joel Fernandes, LKML, Tim Murray, netdev,
Lorenzo Colitti, Chenbo Feng, Mathieu Desnoyers,
Alexei Starovoitov, Daniel Borkmann, stable
In-Reply-To: <20181013023138.m445q6itdmyxdtoc@ast-mbp.dhcp.thefacebook.com>
On Fri, Oct 12, 2018 at 7:31 PM, Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
> On Fri, Oct 12, 2018 at 03:54:27AM -0700, Daniel Colascione wrote:
>> The map-in-map frequently serves as a mechanism for atomic
>> snapshotting of state that a BPF program might record. The current
>> implementation is dangerous to use in this way, however, since
>> userspace has no way of knowing when all programs that might have
>> retrieved the "old" value of the map may have completed.
>>
>> This change ensures that map update operations on map-in-map map types
>> always wait for all references to the old map to drop before returning
>> to userspace.
>>
>> Signed-off-by: Daniel Colascione <dancol@google.com>
>> ---
>> kernel/bpf/syscall.c | 14 ++++++++++++++
>> 1 file changed, 14 insertions(+)
>>
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index 8339d81cba1d..d7c16ae1e85a 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
>> @@ -741,6 +741,18 @@ static int map_lookup_elem(union bpf_attr *attr)
>> return err;
>> }
>>
>> +static void maybe_wait_bpf_programs(struct bpf_map *map)
>> +{
>> + /* Wait for any running BPF programs to complete so that
>> + * userspace, when we return to it, knows that all programs
>> + * that could be running use the new map value.
>> + */
>> + if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS ||
>> + map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS) {
>> + synchronize_rcu();
>> + }
>
> extra {} were not necessary. I removed them while applying to bpf-next.
> Please run checkpatch.pl next time.
> Thanks
Thanks Alexei for taking it. Me and Lorenzo were discussing that not
having this causes incorrect behavior for apps using map-in-map for
this. So I CC'd stable as well.
-Joel
^ permalink raw reply
* Re: crash in xt_policy due to skb_dst_drop() in nf_ct_frag6_gather()
From: Maciej Żenczykowski @ 2018-10-16 9:49 UTC (permalink / raw)
To: Florian Westphal; +Cc: Lorenzo Colitti, Eric Dumazet, Linux NetDev
In-Reply-To: <CAHo-Oowvd8aD4t=hQmH=xUGUdx0gScaQwFKq7hBs2ngsbFsv5A@mail.gmail.com>
4.19-rc8 - pass
4.14.76 - pass
4.9.133 - fail
4.9.133 + revert of ad8b1ffc3efae2f65080bdb11145c87d299b8f9a - pass
On Tue, Oct 16, 2018 at 2:41 AM Maciej Żenczykowski
<zenczykowski@gmail.com> wrote:
>
> (and v4.9.133 latest 4.9 LTS fails the same way, but curiously 4.19-rc8 doesn't)
^ permalink raw reply
* [PATCH net-next v3 2/2] net: phy: mscc: fix memory leak in vsc8574_config_pre_init
From: Gustavo A. R. Silva @ 2018-10-16 17:37 UTC (permalink / raw)
To: linux-kernel
Cc: Andrew Lunn, Florian Fainelli, David S. Miller, Quentin Schulz,
netdev, Gustavo A. R. Silva
In-Reply-To: <cover.1539710647.git.gustavo@embeddedor.com>
In case memory resources for *fw* were successfully allocated,
release them before return.
Addresses-Coverity-ID: 1473968 ("Resource leak")
Fixes: 00d70d8e0e78 ("net: phy: mscc: add support for VSC8574 PHY")
Reviewed-by: Quentin Schulz <quentin.schulz@bootlin.com>
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
---
Changes in v3:
- Add Quentin's Reviewed-by to the commit log.
- Post patch to netdev.
Changes in v2:
- Jump to out label so all functions in the driver exit with the PHY
set to access the standard page. Thanks to Quentin Schulz for
pointing this out.
drivers/net/phy/mscc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index bff56c3..a2e59f4 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -1292,7 +1292,7 @@ static int vsc8574_config_pre_init(struct phy_device *phydev)
dev_err(dev,
"%s: failed to assert reset of micro\n",
__func__);
- return ret;
+ goto out;
}
}
} else {
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v3 1/2] net: phy: mscc: fix signedness bug in vsc85xx_downshift_get
From: Gustavo A. R. Silva @ 2018-10-16 17:35 UTC (permalink / raw)
To: linux-kernel
Cc: Andrew Lunn, Florian Fainelli, David S. Miller, Quentin Schulz,
netdev, Gustavo A. R. Silva
In-Reply-To: <cover.1539710647.git.gustavo@embeddedor.com>
Currently, the error handling for the call to function
phy_read_paged() doesn't work because *reg_val* is of
type u16 (16 bits, unsigned), which makes it impossible
for it to hold a value less than 0.
Fix this by changing the type of variable *reg_val* to int.
Addresses-Coverity-ID: 1473970 ("Unsigned compared against 0")
Fixes: 6a0bfbbe20b0 ("net: phy: mscc: migrate to phy_select/restore_page functions")
Reviewed-by: Quentin Schulz <quentin.schulz@bootlin.com>
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
---
Changes in v3:
- Post patch to netdev.
Changes in v2:
- Add Quentin's Reviewed-by to the commit log.
drivers/net/phy/mscc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index bffe077..bff56c3 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -522,7 +522,7 @@ static int vsc85xx_mdix_set(struct phy_device *phydev, u8 mdix)
static int vsc85xx_downshift_get(struct phy_device *phydev, u8 *count)
{
- u16 reg_val;
+ int reg_val;
reg_val = phy_read_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
MSCC_PHY_ACTIPHY_CNTL);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v3 0/2] fix signedness bug and memory leak in mscc driver
From: Gustavo A. R. Silva @ 2018-10-16 17:33 UTC (permalink / raw)
To: linux-kernel
Cc: Andrew Lunn, Florian Fainelli, David S. Miller, Quentin Schulz,
netdev, Gustavo A. R. Silva
This patchset aims to fix a signedness bug in function
vsc85xx_downshift_get() and a memory leak in function
vsc8574_config_pre_init().
Changes in v3:
- Add Quentin's Reviewed-by to commit log in patch 2/2.
- Post the series to netdev.
Changes in v2:
- Add Quentin's Reviewed-by to commit log in patch 1/2.
- Jump to out label so all functions in the driver exit with the PHY
set to access the standard page. Thanks to Quentin Schulz for
pointing this out.
Thanks
Gustavo A. R. Silva (2):
net: phy: mscc: fix signedness bug in vsc85xx_downshift_get
net: phy: mscc: fix memory leak in vsc8574_config_pre_init
drivers/net/phy/mscc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--
2.7.4
^ permalink raw reply
* Re: crash in xt_policy due to skb_dst_drop() in nf_ct_frag6_gather()
From: Maciej Żenczykowski @ 2018-10-16 9:41 UTC (permalink / raw)
To: Florian Westphal; +Cc: Lorenzo Colitti, Eric Dumazet, Linux NetDev
In-Reply-To: <CAHo-OoynzgQG_fwmU6kupbK6vBy2HQ50Knznv=tjZ+WDNHf8Dw@mail.gmail.com>
(and v4.9.133 latest 4.9 LTS fails the same way, but curiously 4.19-rc8 doesn't)
^ permalink raw reply
* Re: crash in xt_policy due to skb_dst_drop() in nf_ct_frag6_gather()
From: Maciej Żenczykowski @ 2018-10-16 9:40 UTC (permalink / raw)
To: Florian Westphal; +Cc: Lorenzo Colitti, Eric Dumazet, Linux NetDev
In-Reply-To: <20181016081120.umbe3kz2vi4jfgks@breakpoint.cc>
> That is not supposed to happen.
# uname -a
Linux (none) 4.9.119 #3 Tue Oct 16 02:34:36 PDT 2018 x86_64 GNU/Linux
root@(none)# ip6tables -A OUTPUT -m policy --dir out --pol ipsec
root@(none)# python -c "import os, socket;
ip='00000000000000000000000000000001';
x='6001234504d82c40'+ip+ip+'3a000001a1224d20' + 'ff'*(1280-40-8);
y='6001234500092c40'+ip+ip+'3a0004d0a1224d20' + 'ff';
s=socket.socket(socket.AF_INET6,socket.SOCK_RAW,socket.IPPROTO_RAW);
s.sendto(x.decode('hex'),('::1',0,0,1));
s.sendto(y.decode('hex'),('::1',0,0,1));"
Modules linked in:
Pid: 297, comm: python Not tainted 4.9.119
RIP: 0033:[<0000000060272eca>]
RSP: 00000000802afa10 EFLAGS: 00010246
RAX: 0000000060492fa8 RBX: 0000000060272c6f RCX: 00000000803a12a8
RDX: 00000000803a1288 RSI: 00000000802afa98 RDI: 0000000080314d00
RBP: 00000000802afa40 R08: 0000000000000001 R09: 0100000000000000
R10: 0000000000000000 R11: 00000000803a12a8 R12: 0000000000010002
R13: 000000000000000a R14: 0000000000000000 R15: 0000000000000000
Kernel panic - not syncing: Kernel mode fault at addr 0x48, ip 0x60272eca
CPU: 0 PID: 297 Comm: python Not tainted 4.9.119 #3
Stack:
800d5000 803a11e0 80314d00 803a1000
00000000 00000000 802afb00 6031afe1
00000000 803a1288 803a100c 100000003
Call Trace:
[<6031afe1>] ip6t_do_table+0x2a3/0x3d4
[<6026d440>] ? netfilter_net_init+0xbe/0x14f
[<6026d4d1>] ? nf_iterate+0x0/0x5c
[<6031cca5>] ip6table_filter_hook+0x21/0x23
[<6026d509>] nf_iterate+0x38/0x5c
[<6026d561>] nf_hook_slow+0x34/0xa2
[<6003166c>] ? set_signals+0x0/0x3f
[<6003165d>] ? get_signals+0x0/0xf
[<603048b0>] rawv6_sendmsg+0x842/0xc4b
[<60033d15>] ? wait_stub_done+0x40/0x10a
[<60021176>] ? copy_chunk_from_user+0x23/0x2e
[<60021153>] ? copy_chunk_from_user+0x0/0x2e
[<6030307f>] ? dst_output+0x0/0x11
[<602b0926>] inet_sendmsg+0x1e/0x5c
[<600fe15f>] ? __fdget+0x15/0x17
[<602264b9>] sock_sendmsg+0xf/0x62
[<602279aa>] SyS_sendto+0x108/0x140
[<600389c2>] ? arch_switch_to+0x2b/0x2e
[<60367ff4>] ? __schedule+0x428/0x44f
[<60367bcc>] ? __schedule+0x0/0x44f
[<60021125>] handle_syscall+0x79/0xa7
[<6003445c>] userspace+0x3bb/0x453
[<6001dd92>] ? interrupt_end+0x0/0x94
[<6001dc42>] fork_handler+0x85/0x87
^ permalink raw reply
* [PATCH] iwlwifi: mvm: fix spelling mistake "Recieved" -> "Received"
From: Colin King @ 2018-10-16 17:22 UTC (permalink / raw)
To: Johannes Berg, Emmanuel Grumbach, Luca Coelho,
Intel Linux Wireless, Kalle Valo, David S . Miller,
linux-wireless, netdev
Cc: kernel-janitors, linux-kernel
From: Colin Ian King <colin.king@canonical.com>
Trivial fix to spelling mistake in IWL_DEBUG_TE message text.
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 505b0385d800..271db16cf0c8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -3351,7 +3351,7 @@ static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait,
resp = (void *)pkt->data;
IWL_DEBUG_TE(mvm,
- "Aux ROC: Recieved response from ucode: status=%d uid=%d\n",
+ "Aux ROC: Received response from ucode: status=%d uid=%d\n",
resp->status, resp->event_unique_id);
te_data->uid = le32_to_cpu(resp->event_unique_id);
--
2.19.1
^ permalink raw reply related
* Re: patch "staging: MAINTAINERS: remove obsolete IPX staging directory" added to staging-testing
From: Joe Perches @ 2018-10-16 17:11 UTC (permalink / raw)
To: Greg KH; +Cc: LKML, netdev
In-Reply-To: <20181016115137.GA28641@kroah.com>
On Tue, 2018-10-16 at 13:51 +0200, Greg KH wrote:
> On Tue, Oct 16, 2018 at 04:43:30AM -0700, Joe Perches wrote:
> > On Tue, 2018-10-16 at 12:46 +0200, gregkh@linuxfoundation.org wrote:
> > > This is a note to let you know that I've just added the patch titled
> > >
> > > staging: MAINTAINERS: remove obsolete IPX staging directoryts
> > []
> > > From dd71c89b2c1ae049d2018107e9d7a41261db3f7b Mon Sep 17 00:00:00 2001
> > > From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > > Date: Tue, 16 Oct 2018 12:45:13 +0200
> > > Subject: staging: MAINTAINERS: remove obsolete IPX staging directory
> > >
> > > The IPX code was removed from staging back in November 2017, but the
> > > MAINTAINERS entry stuck around. Remove the invalid directory from the
> > > file as it does not actually point to anything anymore.
> >
> > As the uapi ipx file still exists but the functionality
> > has been removed, perhaps some compiler message like
> >
> > #pragma message "IPX functionality removed as of linux kernel v4.18"
> >
> > should be added to the uapi file.
>
> Eventually those files should be removed by the networking developers.
> It will take a bit of work for them to do it, it's not a straight
> "delete the file" work.
I understand that, but it's not the point.
#pragma message might still be useful because,
in the meantime, anyone
actually including the
uapi file would get some heads-up notification
that IPX doesn't work here anymore.
^ permalink raw reply
* Re: [PATCH net-next 0/5] Some cleanup and bugfix for desc filling
From: David Miller @ 2018-10-16 17:10 UTC (permalink / raw)
To: linyunsheng
Cc: huangdaode, xuwei5, liguozhu, Yisen.Zhuang, john.garry, linuxarm,
salil.mehta, lipeng321, netdev, linux-kernel
In-Reply-To: <1539691132-158455-1-git-send-email-linyunsheng@huawei.com>
From: Yunsheng Lin <linyunsheng@huawei.com>
Date: Tue, 16 Oct 2018 19:58:47 +0800
> When retransmiting packets, skb_cow_head which is called in
> hns3_set_tso may clone a new header. And driver will clear the
> checksum of the header after doing DMA map, so HW will read the
> old header whose L3 checksum is not cleared and calculate a
> wrong L3 checksum.
>
> Also When sending a big fragment using multiple buffer descriptor,
> hns3 does one maping, but do multiple unmapping when tx is done,
> which may cause unmapping problem.
>
> This patchset does some cleanup before fixing the above problem.
Series applied.
^ permalink raw reply
* [PATCH 4.9 71/71] ipv4: frags: precedence bug in ip_expire()
From: Greg Kroah-Hartman @ 2018-10-16 17:10 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: Greg Kroah-Hartman, stable, Dan Carpenter, David S. Miller
In-Reply-To: <20181016170539.315587743@linuxfoundation.org>
4.9-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <dan.carpenter@oracle.com>
(commit 70837ffe3085c9a91488b52ca13ac84424da1042 upstream)
We accidentally removed the parentheses here, but they are required
because '!' has higher precedence than '&'.
Fixes: fa0f527358bd ("ip: use rb trees for IP frag queue.")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv4/ip_fragment.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -203,7 +203,7 @@ static void ip_expire(unsigned long arg)
__IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS);
__IP_INC_STATS(net, IPSTATS_MIB_REASMTIMEOUT);
- if (!qp->q.flags & INET_FRAG_FIRST_IN)
+ if (!(qp->q.flags & INET_FRAG_FIRST_IN))
goto out;
/* sk_buff::dev and sk_buff::rbnode are unionized. So we
^ permalink raw reply
* [PATCH 4.9 70/71] ip: frags: fix crash in ip_do_fragment()
From: Greg Kroah-Hartman @ 2018-10-16 17:10 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: Greg Kroah-Hartman, stable, Eric Dumazet, Taehee Yoo,
David S. Miller
In-Reply-To: <20181016170539.315587743@linuxfoundation.org>
4.9-stable review patch. If anyone has any objections, please let me know.
------------------
From: Taehee Yoo <ap420073@gmail.com>
commit 5d407b071dc369c26a38398326ee2be53651cfe4 upstream
A kernel crash occurrs when defragmented packet is fragmented
in ip_do_fragment().
In defragment routine, skb_orphan() is called and
skb->ip_defrag_offset is set. but skb->sk and
skb->ip_defrag_offset are same union member. so that
frag->sk is not NULL.
Hence crash occurrs in skb->sk check routine in ip_do_fragment() when
defragmented packet is fragmented.
test commands:
%iptables -t nat -I POSTROUTING -j MASQUERADE
%hping3 192.168.4.2 -s 1000 -p 2000 -d 60000
splat looks like:
[ 261.069429] kernel BUG at net/ipv4/ip_output.c:636!
[ 261.075753] invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI
[ 261.083854] CPU: 1 PID: 1349 Comm: hping3 Not tainted 4.19.0-rc2+ #3
[ 261.100977] RIP: 0010:ip_do_fragment+0x1613/0x2600
[ 261.106945] Code: e8 e2 38 e3 fe 4c 8b 44 24 18 48 8b 74 24 08 e9 92 f6 ff ff 80 3c 02 00 0f 85 da 07 00 00 48 8b b5 d0 00 00 00 e9 25 f6 ff ff <0f> 0b 0f 0b 44 8b 54 24 58 4c 8b 4c 24 18 4c 8b 5c 24 60 4c 8b 6c
[ 261.127015] RSP: 0018:ffff8801031cf2c0 EFLAGS: 00010202
[ 261.134156] RAX: 1ffff1002297537b RBX: ffffed0020639e6e RCX: 0000000000000004
[ 261.142156] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff880114ba9bd8
[ 261.150157] RBP: ffff880114ba8a40 R08: ffffed0022975395 R09: ffffed0022975395
[ 261.158157] R10: 0000000000000001 R11: ffffed0022975394 R12: ffff880114ba9ca4
[ 261.166159] R13: 0000000000000010 R14: ffff880114ba9bc0 R15: dffffc0000000000
[ 261.174169] FS: 00007fbae2199700(0000) GS:ffff88011b400000(0000) knlGS:0000000000000000
[ 261.183012] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 261.189013] CR2: 00005579244fe000 CR3: 0000000119bf4000 CR4: 00000000001006e0
[ 261.198158] Call Trace:
[ 261.199018] ? dst_output+0x180/0x180
[ 261.205011] ? save_trace+0x300/0x300
[ 261.209018] ? ip_copy_metadata+0xb00/0xb00
[ 261.213034] ? sched_clock_local+0xd4/0x140
[ 261.218158] ? kill_l4proto+0x120/0x120 [nf_conntrack]
[ 261.223014] ? rt_cpu_seq_stop+0x10/0x10
[ 261.227014] ? find_held_lock+0x39/0x1c0
[ 261.233008] ip_finish_output+0x51d/0xb50
[ 261.237006] ? ip_fragment.constprop.56+0x220/0x220
[ 261.243011] ? nf_ct_l4proto_register_one+0x5b0/0x5b0 [nf_conntrack]
[ 261.250152] ? rcu_is_watching+0x77/0x120
[ 261.255010] ? nf_nat_ipv4_out+0x1e/0x2b0 [nf_nat_ipv4]
[ 261.261033] ? nf_hook_slow+0xb1/0x160
[ 261.265007] ip_output+0x1c7/0x710
[ 261.269005] ? ip_mc_output+0x13f0/0x13f0
[ 261.273002] ? __local_bh_enable_ip+0xe9/0x1b0
[ 261.278152] ? ip_fragment.constprop.56+0x220/0x220
[ 261.282996] ? nf_hook_slow+0xb1/0x160
[ 261.287007] raw_sendmsg+0x21f9/0x4420
[ 261.291008] ? dst_output+0x180/0x180
[ 261.297003] ? sched_clock_cpu+0x126/0x170
[ 261.301003] ? find_held_lock+0x39/0x1c0
[ 261.306155] ? stop_critical_timings+0x420/0x420
[ 261.311004] ? check_flags.part.36+0x450/0x450
[ 261.315005] ? _raw_spin_unlock_irq+0x29/0x40
[ 261.320995] ? _raw_spin_unlock_irq+0x29/0x40
[ 261.326142] ? cyc2ns_read_end+0x10/0x10
[ 261.330139] ? raw_bind+0x280/0x280
[ 261.334138] ? sched_clock_cpu+0x126/0x170
[ 261.338995] ? check_flags.part.36+0x450/0x450
[ 261.342991] ? __lock_acquire+0x4500/0x4500
[ 261.348994] ? inet_sendmsg+0x11c/0x500
[ 261.352989] ? dst_output+0x180/0x180
[ 261.357012] inet_sendmsg+0x11c/0x500
[ ... ]
v2:
- clear skb->sk at reassembly routine.(Eric Dumarzet)
Fixes: fa0f527358bd ("ip: use rb trees for IP frag queue.")
Suggested-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv4/ip_fragment.c | 1 +
net/ipv6/netfilter/nf_conntrack_reasm.c | 1 +
2 files changed, 2 insertions(+)
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -597,6 +597,7 @@ static int ip_frag_reasm(struct ipq *qp,
nextp = &fp->next;
fp->prev = NULL;
memset(&fp->rbnode, 0, sizeof(fp->rbnode));
+ fp->sk = NULL;
head->data_len += fp->len;
head->len += fp->len;
if (head->ip_summed != fp->ip_summed)
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -452,6 +452,7 @@ nf_ct_frag6_reasm(struct frag_queue *fq,
else if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_add(head->csum, fp->csum);
head->truesize += fp->truesize;
+ fp->sk = NULL;
}
sub_frag_mem_limit(fq->q.net, head->truesize);
^ permalink raw reply
* [PATCH 4.9 69/71] ip: process in-order fragments efficiently
From: Greg Kroah-Hartman @ 2018-10-16 17:10 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: Greg Kroah-Hartman, stable, Willem de Bruijn, Peter Oskolkov,
Eric Dumazet, Florian Westphal, David S. Miller
In-Reply-To: <20181016170539.315587743@linuxfoundation.org>
4.9-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Oskolkov <posk@google.com>
This patch changes the runtime behavior of IP defrag queue:
incoming in-order fragments are added to the end of the current
list/"run" of in-order fragments at the tail.
On some workloads, UDP stream performance is substantially improved:
RX: ./udp_stream -F 10 -T 2 -l 60
TX: ./udp_stream -c -H <host> -F 10 -T 5 -l 60
with this patchset applied on a 10Gbps receiver:
throughput=9524.18
throughput_units=Mbit/s
upstream (net-next):
throughput=4608.93
throughput_units=Mbit/s
Reported-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit a4fd284a1f8fd4b6c59aa59db2185b1e17c5c11c)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv4/inet_fragment.c | 2
net/ipv4/ip_fragment.c | 110 +++++++++++++++++++++++++++++------------------
2 files changed, 70 insertions(+), 42 deletions(-)
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -145,7 +145,7 @@ void inet_frag_destroy(struct inet_frag_
fp = xp;
} while (fp);
} else {
- sum_truesize = skb_rbtree_purge(&q->rb_fragments);
+ sum_truesize = inet_frag_rbtree_purge(&q->rb_fragments);
}
sum = sum_truesize + f->qsize;
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -125,8 +125,8 @@ static u8 ip4_frag_ecn(u8 tos)
static struct inet_frags ip4_frags;
-static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
- struct net_device *dev);
+static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
+ struct sk_buff *prev_tail, struct net_device *dev);
static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
@@ -217,7 +217,12 @@ static void ip_expire(unsigned long arg)
head = skb_rb_first(&qp->q.rb_fragments);
if (!head)
goto out;
- rb_erase(&head->rbnode, &qp->q.rb_fragments);
+ if (FRAG_CB(head)->next_frag)
+ rb_replace_node(&head->rbnode,
+ &FRAG_CB(head)->next_frag->rbnode,
+ &qp->q.rb_fragments);
+ else
+ rb_erase(&head->rbnode, &qp->q.rb_fragments);
memset(&head->rbnode, 0, sizeof(head->rbnode));
barrier();
}
@@ -318,7 +323,7 @@ static int ip_frag_reinit(struct ipq *qp
return -ETIMEDOUT;
}
- sum_truesize = skb_rbtree_purge(&qp->q.rb_fragments);
+ sum_truesize = inet_frag_rbtree_purge(&qp->q.rb_fragments);
sub_frag_mem_limit(qp->q.net, sum_truesize);
qp->q.flags = 0;
@@ -327,6 +332,7 @@ static int ip_frag_reinit(struct ipq *qp
qp->q.fragments = NULL;
qp->q.rb_fragments = RB_ROOT;
qp->q.fragments_tail = NULL;
+ qp->q.last_run_head = NULL;
qp->iif = 0;
qp->ecn = 0;
@@ -338,7 +344,7 @@ static int ip_frag_queue(struct ipq *qp,
{
struct net *net = container_of(qp->q.net, struct net, ipv4.frags);
struct rb_node **rbn, *parent;
- struct sk_buff *skb1;
+ struct sk_buff *skb1, *prev_tail;
struct net_device *dev;
unsigned int fragsize;
int flags, offset;
@@ -416,38 +422,41 @@ static int ip_frag_queue(struct ipq *qp,
*/
/* Find out where to put this fragment. */
- skb1 = qp->q.fragments_tail;
- if (!skb1) {
- /* This is the first fragment we've received. */
- rb_link_node(&skb->rbnode, NULL, &qp->q.rb_fragments.rb_node);
- qp->q.fragments_tail = skb;
- } else if ((skb1->ip_defrag_offset + skb1->len) < end) {
- /* This is the common/special case: skb goes to the end. */
+ prev_tail = qp->q.fragments_tail;
+ if (!prev_tail)
+ ip4_frag_create_run(&qp->q, skb); /* First fragment. */
+ else if (prev_tail->ip_defrag_offset + prev_tail->len < end) {
+ /* This is the common case: skb goes to the end. */
/* Detect and discard overlaps. */
- if (offset < (skb1->ip_defrag_offset + skb1->len))
+ if (offset < prev_tail->ip_defrag_offset + prev_tail->len)
goto discard_qp;
- /* Insert after skb1. */
- rb_link_node(&skb->rbnode, &skb1->rbnode, &skb1->rbnode.rb_right);
- qp->q.fragments_tail = skb;
+ if (offset == prev_tail->ip_defrag_offset + prev_tail->len)
+ ip4_frag_append_to_last_run(&qp->q, skb);
+ else
+ ip4_frag_create_run(&qp->q, skb);
} else {
- /* Binary search. Note that skb can become the first fragment, but
- * not the last (covered above). */
+ /* Binary search. Note that skb can become the first fragment,
+ * but not the last (covered above).
+ */
rbn = &qp->q.rb_fragments.rb_node;
do {
parent = *rbn;
skb1 = rb_to_skb(parent);
if (end <= skb1->ip_defrag_offset)
rbn = &parent->rb_left;
- else if (offset >= skb1->ip_defrag_offset + skb1->len)
+ else if (offset >= skb1->ip_defrag_offset +
+ FRAG_CB(skb1)->frag_run_len)
rbn = &parent->rb_right;
else /* Found an overlap with skb1. */
goto discard_qp;
} while (*rbn);
/* Here we have parent properly set, and rbn pointing to
- * one of its NULL left/right children. Insert skb. */
+ * one of its NULL left/right children. Insert skb.
+ */
+ ip4_frag_init_run(skb);
rb_link_node(&skb->rbnode, parent, rbn);
+ rb_insert_color(&skb->rbnode, &qp->q.rb_fragments);
}
- rb_insert_color(&skb->rbnode, &qp->q.rb_fragments);
if (dev)
qp->iif = dev->ifindex;
@@ -474,7 +483,7 @@ static int ip_frag_queue(struct ipq *qp,
unsigned long orefdst = skb->_skb_refdst;
skb->_skb_refdst = 0UL;
- err = ip_frag_reasm(qp, skb, dev);
+ err = ip_frag_reasm(qp, skb, prev_tail, dev);
skb->_skb_refdst = orefdst;
return err;
}
@@ -493,7 +502,7 @@ err:
/* Build a new IP datagram from all its fragments. */
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
- struct net_device *dev)
+ struct sk_buff *prev_tail, struct net_device *dev)
{
struct net *net = container_of(qp->q.net, struct net, ipv4.frags);
struct iphdr *iph;
@@ -517,10 +526,16 @@ static int ip_frag_reasm(struct ipq *qp,
fp = skb_clone(skb, GFP_ATOMIC);
if (!fp)
goto out_nomem;
- rb_replace_node(&skb->rbnode, &fp->rbnode, &qp->q.rb_fragments);
+ FRAG_CB(fp)->next_frag = FRAG_CB(skb)->next_frag;
+ if (RB_EMPTY_NODE(&skb->rbnode))
+ FRAG_CB(prev_tail)->next_frag = fp;
+ else
+ rb_replace_node(&skb->rbnode, &fp->rbnode,
+ &qp->q.rb_fragments);
if (qp->q.fragments_tail == skb)
qp->q.fragments_tail = fp;
skb_morph(skb, head);
+ FRAG_CB(skb)->next_frag = FRAG_CB(head)->next_frag;
rb_replace_node(&head->rbnode, &skb->rbnode,
&qp->q.rb_fragments);
consume_skb(head);
@@ -556,7 +571,7 @@ static int ip_frag_reasm(struct ipq *qp,
for (i = 0; i < skb_shinfo(head)->nr_frags; i++)
plen += skb_frag_size(&skb_shinfo(head)->frags[i]);
clone->len = clone->data_len = head->data_len - plen;
- skb->truesize += clone->truesize;
+ head->truesize += clone->truesize;
clone->csum = 0;
clone->ip_summed = head->ip_summed;
add_frag_mem_limit(qp->q.net, clone->truesize);
@@ -569,24 +584,36 @@ static int ip_frag_reasm(struct ipq *qp,
skb_push(head, head->data - skb_network_header(head));
/* Traverse the tree in order, to build frag_list. */
+ fp = FRAG_CB(head)->next_frag;
rbn = rb_next(&head->rbnode);
rb_erase(&head->rbnode, &qp->q.rb_fragments);
- while (rbn) {
- struct rb_node *rbnext = rb_next(rbn);
- fp = rb_to_skb(rbn);
- rb_erase(rbn, &qp->q.rb_fragments);
- rbn = rbnext;
- *nextp = fp;
- nextp = &fp->next;
- fp->prev = NULL;
- memset(&fp->rbnode, 0, sizeof(fp->rbnode));
- head->data_len += fp->len;
- head->len += fp->len;
- if (head->ip_summed != fp->ip_summed)
- head->ip_summed = CHECKSUM_NONE;
- else if (head->ip_summed == CHECKSUM_COMPLETE)
- head->csum = csum_add(head->csum, fp->csum);
- head->truesize += fp->truesize;
+ while (rbn || fp) {
+ /* fp points to the next sk_buff in the current run;
+ * rbn points to the next run.
+ */
+ /* Go through the current run. */
+ while (fp) {
+ *nextp = fp;
+ nextp = &fp->next;
+ fp->prev = NULL;
+ memset(&fp->rbnode, 0, sizeof(fp->rbnode));
+ head->data_len += fp->len;
+ head->len += fp->len;
+ if (head->ip_summed != fp->ip_summed)
+ head->ip_summed = CHECKSUM_NONE;
+ else if (head->ip_summed == CHECKSUM_COMPLETE)
+ head->csum = csum_add(head->csum, fp->csum);
+ head->truesize += fp->truesize;
+ fp = FRAG_CB(fp)->next_frag;
+ }
+ /* Move to the next run. */
+ if (rbn) {
+ struct rb_node *rbnext = rb_next(rbn);
+
+ fp = rb_to_skb(rbn);
+ rb_erase(rbn, &qp->q.rb_fragments);
+ rbn = rbnext;
+ }
}
sub_frag_mem_limit(qp->q.net, head->truesize);
@@ -622,6 +649,7 @@ static int ip_frag_reasm(struct ipq *qp,
qp->q.fragments = NULL;
qp->q.rb_fragments = RB_ROOT;
qp->q.fragments_tail = NULL;
+ qp->q.last_run_head = NULL;
return 0;
out_nomem:
^ permalink raw reply
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