diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 3f83a12785db224df9d032cc8c6e7facdd72d50f..d291d1cbe041f615e18bb33c44946eb880ff0b6b 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -252,6 +252,7 @@ struct ixgbe_adapter { struct ixgbe_dcb_config dcb_cfg; struct ixgbe_dcb_config temp_dcb_cfg; u8 dcb_set_bitmap; + enum ixgbe_fc_mode last_lfc_mode; /* Interrupt Throttle Rate */ u32 itr_setting; diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 55186dc7dd78275c3743e77ba2f8569aafb404c8..afc9fe3f1eda8274090828095e6ad394e336e9d5 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -363,7 +363,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) } /* Configure pause time (2 TCs per register) */ - reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num)); + reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2)); if ((packetbuf_num & 1) == 0) reg = (reg & 0xFFFF0000) | hw->fc.pause_time; else diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 530da909dc7a01002764193de7b278b636f7b58d..0cc3c47cb45308a02a807d66d4dd2dc6c33a3d9b 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1661,9 +1661,10 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num) reg = IXGBE_READ_REG(hw, IXGBE_MTQC); /* Thresholds are different for link flow control when in DCB mode */ if (reg & IXGBE_MTQC_RT_ENA) { - rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)); - /* Always disable XON for LFC when in DCB mode */ + IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), 0); + + rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)); reg = (rx_pba_size >> 2) & 0xFFE0; if (hw->fc.current_mode & ixgbe_fc_tx_pause) reg |= IXGBE_FCRTH_FCEN; diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c index 62206273d88806921669f38f4ca3a911f4df5d31..f30263898ebca85cc9613d32a311e916ce33a6f8 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c @@ -294,6 +294,9 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u32 reg, rx_pba_size; u8 i; + if (!dcb_config->pfc_mode_enable) + goto out; + /* Enable Transmit Priority Flow Control */ reg = IXGBE_READ_REG(hw, IXGBE_RMCS); reg &= ~IXGBE_RMCS_TFCE_802_3X; @@ -341,6 +344,7 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400); +out: return 0; } diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 5d5d390f84bf8b58ad6e9468279a2bc94797e5d1..6cbff96cc0ff55744f9e624f9bdd85b2df8d5413 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -126,7 +126,10 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) netdev->netdev_ops->ndo_stop(netdev); ixgbe_clear_interrupt_scheme(adapter); - adapter->hw.fc.requested_mode = ixgbe_fc_pfc; + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + adapter->last_lfc_mode = adapter->hw.fc.current_mode; + adapter->hw.fc.requested_mode = ixgbe_fc_none; + } adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; adapter->flags |= IXGBE_FLAG_DCB_ENABLED; ixgbe_init_interrupt_scheme(adapter); @@ -135,11 +138,13 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) } else { /* Turn off DCB */ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - adapter->hw.fc.requested_mode = ixgbe_fc_default; if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); ixgbe_clear_interrupt_scheme(adapter); + adapter->hw.fc.requested_mode = adapter->last_lfc_mode; + adapter->temp_dcb_cfg.pfc_mode_enable = false; + adapter->dcb_cfg.pfc_mode_enable = false; adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; ixgbe_init_interrupt_scheme(adapter); @@ -329,9 +334,24 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) return ret; } + if (adapter->dcb_cfg.pfc_mode_enable) { + if ((adapter->hw.mac.type != ixgbe_mac_82598EB) && + (adapter->hw.fc.current_mode != ixgbe_fc_pfc)) + adapter->last_lfc_mode = adapter->hw.fc.current_mode; + adapter->hw.fc.requested_mode = ixgbe_fc_pfc; + } else { + if (adapter->hw.mac.type != ixgbe_mac_82598EB) + adapter->hw.fc.requested_mode = adapter->last_lfc_mode; + else + adapter->hw.fc.requested_mode = ixgbe_fc_none; + } + if (netif_running(netdev)) ixgbe_up(adapter); + if (adapter->dcb_cfg.pfc_mode_enable) + adapter->hw.fc.current_mode = ixgbe_fc_pfc; + adapter->dcb_set_bitmap = 0x00; clear_bit(__IXGBE_RESETTING, &adapter->state); return ret; @@ -409,11 +429,17 @@ static u8 ixgbe_dcbnl_getpfcstate(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED); + return adapter->dcb_cfg.pfc_mode_enable; } static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state) { + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + 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; return; } diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 39fb98faffd0c93076e68ab5cd87d605ef6b175e..6c7324339ec8bad68d4cddd23d16c376d870202a 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -270,6 +270,13 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; +#ifdef CONFIG_DCB + if (adapter->dcb_cfg.pfc_mode_enable || + ((hw->mac.type == ixgbe_mac_82598EB) && + (adapter->flags & IXGBE_FLAG_DCB_ENABLED))) + return -EINVAL; + +#endif if (pause->autoneg != AUTONEG_ENABLE) hw->fc.disable_fc_autoneg = true; else @@ -286,6 +293,9 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, else return -EINVAL; +#ifdef CONFIG_DCB + adapter->last_lfc_mode = hw->fc.requested_mode; +#endif hw->mac.ops.setup_fc(hw, 0); return 0; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 1b4af3f541b76d37e323d9d9a06d43ea84f5692e..b53f265011730e5b7e480448732c4440567c2cd1 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3554,6 +3554,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100; adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100; adapter->dcb_cfg.rx_pba_cfg = pba_equal; + adapter->dcb_cfg.pfc_mode_enable = false; adapter->dcb_cfg.round_robin_enable = false; adapter->dcb_set_bitmap = 0x00; ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg, @@ -3564,6 +3565,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) /* default flow control settings */ hw->fc.requested_mode = ixgbe_fc_full; hw->fc.current_mode = ixgbe_fc_full; /* init for ethtool output */ +#ifdef CONFIG_DCB + adapter->last_lfc_mode = hw->fc.current_mode; +#endif hw->fc.high_water = IXGBE_DEFAULT_FCRTH; hw->fc.low_water = IXGBE_DEFAULT_FCRTL; hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE; @@ -4319,11 +4323,24 @@ static void ixgbe_watchdog_task(struct work_struct *work) if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) { hw->mac.ops.check_link(hw, &link_speed, &link_up, false); + if (link_up) { +#ifdef CONFIG_DCB + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) + hw->mac.ops.setup_fc(hw, i); + } else { + hw->mac.ops.setup_fc(hw, 0); + } +#else + hw->mac.ops.setup_fc(hw, 0); +#endif + } + if (link_up || time_after(jiffies, (adapter->link_check_timeout + IXGBE_TRY_LINK_TIMEOUT))) { - IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC); adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; + IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC); } adapter->link_up = link_up; adapter->link_speed = link_speed;