Commit aacc1bea authored by Multanen, Eric W's avatar Multanen, Eric W Committed by Jeff Kirsher

ixgbe: driver fix for link flap

Fix up code so that changes in DCB settings
are detected only when ixgbe_dcbnl_set_all is called.
Previously, a series of 'change' commands followed by
a call to ixgbe_dcbnl_set_all() would always be handled
as a HW change - even if the net change was zero.
This patch checks for this case of no actual change and
skips going through the HW set process.

Without this fix, the link could reset and result in
a link flap.

The core change in this patch is to check for changes
in the ixgbe_copy_dcb_cfg() routine - and return
a bitmask of detected changes.  The other
places where changes were detected previously can be removed.
Signed-off-by: default avatarEric Multanen <eric.w.multanen@intel.com>
Tested-by: default avatarRoss Brattain <ross.b.brattain@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 01627d96
...@@ -44,62 +44,94 @@ ...@@ -44,62 +44,94 @@
#define DCB_NO_HW_CHG 1 /* DCB configuration did not change */ #define DCB_NO_HW_CHG 1 /* DCB configuration did not change */
#define DCB_HW_CHG 2 /* DCB configuration changed, no reset */ #define DCB_HW_CHG 2 /* DCB configuration changed, no reset */
int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *scfg,
struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max) struct ixgbe_dcb_config *dcfg, int tc_max)
{ {
struct tc_configuration *src_tc_cfg = NULL; struct tc_configuration *src = NULL;
struct tc_configuration *dst_tc_cfg = NULL; struct tc_configuration *dst = NULL;
int i; int i, j;
int tx = DCB_TX_CONFIG;
int rx = DCB_RX_CONFIG;
int changes = 0;
if (!src_dcb_cfg || !dst_dcb_cfg) if (!scfg || !dcfg)
return -EINVAL; return changes;
for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) { for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) {
src_tc_cfg = &src_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0]; src = &scfg->tc_config[i - DCB_PG_ATTR_TC_0];
dst_tc_cfg = &dst_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0]; dst = &dcfg->tc_config[i - DCB_PG_ATTR_TC_0];
dst_tc_cfg->path[DCB_TX_CONFIG].prio_type = if (dst->path[tx].prio_type != src->path[tx].prio_type) {
src_tc_cfg->path[DCB_TX_CONFIG].prio_type; dst->path[tx].prio_type = src->path[tx].prio_type;
changes |= BIT_PG_TX;
}
dst_tc_cfg->path[DCB_TX_CONFIG].bwg_id = if (dst->path[tx].bwg_id != src->path[tx].bwg_id) {
src_tc_cfg->path[DCB_TX_CONFIG].bwg_id; dst->path[tx].bwg_id = src->path[tx].bwg_id;
changes |= BIT_PG_TX;
}
dst_tc_cfg->path[DCB_TX_CONFIG].bwg_percent = if (dst->path[tx].bwg_percent != src->path[tx].bwg_percent) {
src_tc_cfg->path[DCB_TX_CONFIG].bwg_percent; dst->path[tx].bwg_percent = src->path[tx].bwg_percent;
changes |= BIT_PG_TX;
}
dst_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap = if (dst->path[tx].up_to_tc_bitmap !=
src_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap; src->path[tx].up_to_tc_bitmap) {
dst->path[tx].up_to_tc_bitmap =
src->path[tx].up_to_tc_bitmap;
changes |= (BIT_PG_TX | BIT_PFC | BIT_APP_UPCHG);
}
dst_tc_cfg->path[DCB_RX_CONFIG].prio_type = if (dst->path[rx].prio_type != src->path[rx].prio_type) {
src_tc_cfg->path[DCB_RX_CONFIG].prio_type; dst->path[rx].prio_type = src->path[rx].prio_type;
changes |= BIT_PG_RX;
}
dst_tc_cfg->path[DCB_RX_CONFIG].bwg_id = if (dst->path[rx].bwg_id != src->path[rx].bwg_id) {
src_tc_cfg->path[DCB_RX_CONFIG].bwg_id; dst->path[rx].bwg_id = src->path[rx].bwg_id;
changes |= BIT_PG_RX;
}
dst_tc_cfg->path[DCB_RX_CONFIG].bwg_percent = if (dst->path[rx].bwg_percent != src->path[rx].bwg_percent) {
src_tc_cfg->path[DCB_RX_CONFIG].bwg_percent; dst->path[rx].bwg_percent = src->path[rx].bwg_percent;
changes |= BIT_PG_RX;
}
dst_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap = if (dst->path[rx].up_to_tc_bitmap !=
src_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap; src->path[rx].up_to_tc_bitmap) {
dst->path[rx].up_to_tc_bitmap =
src->path[rx].up_to_tc_bitmap;
changes |= (BIT_PG_RX | BIT_PFC | BIT_APP_UPCHG);
}
} }
for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) { for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) {
dst_dcb_cfg->bw_percentage[DCB_TX_CONFIG] j = i - DCB_PG_ATTR_BW_ID_0;
[i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage if (dcfg->bw_percentage[tx][j] != scfg->bw_percentage[tx][j]) {
[DCB_TX_CONFIG][i-DCB_PG_ATTR_BW_ID_0]; dcfg->bw_percentage[tx][j] = scfg->bw_percentage[tx][j];
dst_dcb_cfg->bw_percentage[DCB_RX_CONFIG] changes |= BIT_PG_TX;
[i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage }
[DCB_RX_CONFIG][i-DCB_PG_ATTR_BW_ID_0]; if (dcfg->bw_percentage[rx][j] != scfg->bw_percentage[rx][j]) {
dcfg->bw_percentage[rx][j] = scfg->bw_percentage[rx][j];
changes |= BIT_PG_RX;
}
} }
for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) { for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) {
dst_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc = j = i - DCB_PFC_UP_ATTR_0;
src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc; if (dcfg->tc_config[j].dcb_pfc != scfg->tc_config[j].dcb_pfc) {
dcfg->tc_config[j].dcb_pfc = scfg->tc_config[j].dcb_pfc;
changes |= BIT_PFC;
}
} }
dst_dcb_cfg->pfc_mode_enable = src_dcb_cfg->pfc_mode_enable; if (dcfg->pfc_mode_enable != scfg->pfc_mode_enable) {
dcfg->pfc_mode_enable = scfg->pfc_mode_enable;
changes |= BIT_PFC;
}
return 0; return changes;
} }
static u8 ixgbe_dcbnl_get_state(struct net_device *netdev) static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
...@@ -179,20 +211,6 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, ...@@ -179,20 +211,6 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
if (up_map != DCB_ATTR_VALUE_UNDEFINED) if (up_map != DCB_ATTR_VALUE_UNDEFINED)
adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap = adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap =
up_map; up_map;
if ((adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type !=
adapter->dcb_cfg.tc_config[tc].path[0].prio_type) ||
(adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id !=
adapter->dcb_cfg.tc_config[tc].path[0].bwg_id) ||
(adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent !=
adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) ||
(adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap))
adapter->dcb_set_bitmap |= BIT_PG_TX;
if (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)
adapter->dcb_set_bitmap |= BIT_PFC | BIT_APP_UPCHG;
} }
static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
...@@ -201,10 +219,6 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, ...@@ -201,10 +219,6 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct; adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] !=
adapter->dcb_cfg.bw_percentage[0][bwg_id])
adapter->dcb_set_bitmap |= BIT_PG_TX;
} }
static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
...@@ -223,20 +237,6 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, ...@@ -223,20 +237,6 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
if (up_map != DCB_ATTR_VALUE_UNDEFINED) if (up_map != DCB_ATTR_VALUE_UNDEFINED)
adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap = adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap =
up_map; up_map;
if ((adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type !=
adapter->dcb_cfg.tc_config[tc].path[1].prio_type) ||
(adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id !=
adapter->dcb_cfg.tc_config[tc].path[1].bwg_id) ||
(adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent !=
adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) ||
(adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap))
adapter->dcb_set_bitmap |= BIT_PG_RX;
if (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)
adapter->dcb_set_bitmap |= BIT_PFC;
} }
static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
...@@ -245,10 +245,6 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, ...@@ -245,10 +245,6 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct; adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] !=
adapter->dcb_cfg.bw_percentage[1][bwg_id])
adapter->dcb_set_bitmap |= BIT_PG_RX;
} }
static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
...@@ -298,10 +294,8 @@ static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority, ...@@ -298,10 +294,8 @@ static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting; adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting;
if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc != if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc !=
adapter->dcb_cfg.tc_config[priority].dcb_pfc) { adapter->dcb_cfg.tc_config[priority].dcb_pfc)
adapter->dcb_set_bitmap |= BIT_PFC;
adapter->temp_dcb_cfg.pfc_mode_enable = true; adapter->temp_dcb_cfg.pfc_mode_enable = true;
}
} }
static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority, static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
...@@ -336,7 +330,8 @@ static void ixgbe_dcbnl_devreset(struct net_device *dev) ...@@ -336,7 +330,8 @@ static void ixgbe_dcbnl_devreset(struct net_device *dev)
static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
int ret, i; int ret = DCB_NO_HW_CHG;
int i;
#ifdef IXGBE_FCOE #ifdef IXGBE_FCOE
struct dcb_app app = { struct dcb_app app = {
.selector = DCB_APP_IDTYPE_ETHTYPE, .selector = DCB_APP_IDTYPE_ETHTYPE,
...@@ -355,12 +350,13 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) ...@@ -355,12 +350,13 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
/* Fail command if not in CEE mode */ /* Fail command if not in CEE mode */
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
return 1; return ret;
ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg,
MAX_TRAFFIC_CLASS); &adapter->dcb_cfg,
if (ret) MAX_TRAFFIC_CLASS);
return DCB_NO_HW_CHG; if (!adapter->dcb_set_bitmap)
return ret;
if (adapter->dcb_cfg.pfc_mode_enable) { if (adapter->dcb_cfg.pfc_mode_enable) {
switch (adapter->hw.mac.type) { switch (adapter->hw.mac.type) {
...@@ -420,6 +416,8 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) ...@@ -420,6 +416,8 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
netdev_set_prio_tc_map(netdev, i, prio_tc[i]); netdev_set_prio_tc_map(netdev, i, prio_tc[i]);
ret = DCB_HW_CHG_RST;
} }
if (adapter->dcb_set_bitmap & BIT_PFC) { if (adapter->dcb_set_bitmap & BIT_PFC) {
...@@ -430,7 +428,8 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) ...@@ -430,7 +428,8 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
DCB_TX_CONFIG, prio_tc); DCB_TX_CONFIG, prio_tc);
ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en); ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en);
ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en, prio_tc); ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en, prio_tc);
ret = DCB_HW_CHG; if (ret != DCB_HW_CHG_RST)
ret = DCB_HW_CHG;
} }
if (adapter->dcb_cfg.pfc_mode_enable) if (adapter->dcb_cfg.pfc_mode_enable)
...@@ -531,9 +530,6 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state) ...@@ -531,9 +530,6 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
adapter->temp_dcb_cfg.pfc_mode_enable = state; adapter->temp_dcb_cfg.pfc_mode_enable = state;
if (adapter->temp_dcb_cfg.pfc_mode_enable !=
adapter->dcb_cfg.pfc_mode_enable)
adapter->dcb_set_bitmap |= BIT_PFC;
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment