aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2012-05-10 01:14:44 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2012-05-10 01:15:40 -0400
commit943561d3e7f82645aafb65839feb9f99e2718bac (patch)
treead98ffc6c1cb0aa2ec3014abc5779997ed783f72
parentdcaccc825b5475266bf343defa086d7b70b599f9 (diff)
ixgbe: Clean up priority based flow control
This change cleans up the logic in the priority based flow control configuration routines. Both the 82599 and 82598 based routines perform similar functions however they are both arranged completely differently. This patch goes over both of them to clean up the code. In addition I am dropping the ixgbe_fc_pfc flow control mode and instead just replacing it with checks for if priority flow control is enabled. This allows us to maintain some of the link flow control information which allows for an easier transition between link and priority flow control. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Ross Brattain <ross.b.brattain@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c69
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c93
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c95
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c30
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c70
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h3
6 files changed, 156 insertions, 204 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
index d3695edfcb8b..87592b458c9c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
@@ -191,53 +191,46 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
191 */ 191 */
192s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en) 192s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en)
193{ 193{
194 u32 reg; 194 u32 fcrtl, reg;
195 u8 i; 195 u8 i;
196 196
197 if (pfc_en) { 197 /* Enable Transmit Priority Flow Control */
198 /* Enable Transmit Priority Flow Control */ 198 reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
199 reg = IXGBE_READ_REG(hw, IXGBE_RMCS); 199 reg &= ~IXGBE_RMCS_TFCE_802_3X;
200 reg &= ~IXGBE_RMCS_TFCE_802_3X; 200 reg |= IXGBE_RMCS_TFCE_PRIORITY;
201 /* correct the reporting of our flow control status */ 201 IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
202 reg |= IXGBE_RMCS_TFCE_PRIORITY;
203 IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
204
205 /* Enable Receive Priority Flow Control */
206 reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
207 reg &= ~IXGBE_FCTRL_RFCE;
208 reg |= IXGBE_FCTRL_RPFCE;
209 IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
210
211 /* Configure pause time */
212 for (i = 0; i < (MAX_TRAFFIC_CLASS >> 1); i++)
213 IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), 0x68006800);
214 202
215 /* Configure flow control refresh threshold value */ 203 /* Enable Receive Priority Flow Control */
216 IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400); 204 reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
217 } 205 reg &= ~(IXGBE_FCTRL_RPFCE | IXGBE_FCTRL_RFCE);
218 206
219 /* 207 if (pfc_en)
220 * Configure flow control thresholds and enable priority flow control 208 reg |= IXGBE_FCTRL_RPFCE;
221 * for each traffic class.
222 */
223 for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
224 int enabled = pfc_en & (1 << i);
225 209
226 reg = hw->fc.low_water << 10; 210 IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
227 211
228 if (enabled == pfc_enabled_tx || 212 fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
229 enabled == pfc_enabled_full) 213 /* Configure PFC Tx thresholds per TC */
230 reg |= IXGBE_FCRTL_XONE; 214 for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
215 if (!(pfc_en & (1 << i))) {
216 IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0);
217 IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0);
218 continue;
219 }
220
221 reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
222 IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
223 IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
224 }
231 225
232 IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), reg); 226 /* Configure pause time */
227 reg = hw->fc.pause_time * 0x00010001;
228 for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
229 IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
233 230
234 reg = hw->fc.high_water[i] << 10; 231 /* Configure flow control refresh threshold value */
235 if (enabled == pfc_enabled_tx || 232 IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
236 enabled == pfc_enabled_full)
237 reg |= IXGBE_FCRTH_FCEN;
238 233
239 IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
240 }
241 234
242 return 0; 235 return 0;
243} 236}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
index 65913c5a616e..4eac80d01857 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
@@ -211,24 +211,42 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
211 */ 211 */
212s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc) 212s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
213{ 213{
214 u32 i, j, reg; 214 u32 i, j, fcrtl, reg;
215 u8 max_tc = 0; 215 u8 max_tc = 0;
216 216
217 for (i = 0; i < MAX_USER_PRIORITY; i++) 217 /* Enable Transmit Priority Flow Control */
218 IXGBE_WRITE_REG(hw, IXGBE_FCCFG, IXGBE_FCCFG_TFCE_PRIORITY);
219
220 /* Enable Receive Priority Flow Control */
221 reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
222 reg |= IXGBE_MFLCN_DPF;
223
224 /*
225 * X540 supports per TC Rx priority flow control. So
226 * clear all TCs and only enable those that should be
227 * enabled.
228 */
229 reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE);
230
231 if (hw->mac.type == ixgbe_mac_X540)
232 reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT;
233
234 if (pfc_en)
235 reg |= IXGBE_MFLCN_RPFCE;
236
237 IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
238
239 for (i = 0; i < MAX_USER_PRIORITY; i++) {
218 if (prio_tc[i] > max_tc) 240 if (prio_tc[i] > max_tc)
219 max_tc = prio_tc[i]; 241 max_tc = prio_tc[i];
242 }
243
244 fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
220 245
221 /* Configure PFC Tx thresholds per TC */ 246 /* Configure PFC Tx thresholds per TC */
222 for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { 247 for (i = 0; i <= max_tc; i++) {
223 int enabled = 0; 248 int enabled = 0;
224 249
225 if (i > max_tc) {
226 reg = 0;
227 IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg);
228 IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg);
229 continue;
230 }
231
232 for (j = 0; j < MAX_USER_PRIORITY; j++) { 250 for (j = 0; j < MAX_USER_PRIORITY; j++) {
233 if ((prio_tc[j] == i) && (pfc_en & (1 << j))) { 251 if ((prio_tc[j] == i) && (pfc_en & (1 << j))) {
234 enabled = 1; 252 enabled = 1;
@@ -236,50 +254,29 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
236 } 254 }
237 } 255 }
238 256
239 reg = hw->fc.low_water << 10; 257 if (enabled) {
240 258 reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
241 if (enabled) 259 IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
242 reg |= IXGBE_FCRTL_XONE; 260 } else {
243 IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); 261 reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
262 IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
263 }
244 264
245 reg = hw->fc.high_water[i] << 10;
246 if (enabled)
247 reg |= IXGBE_FCRTH_FCEN;
248 IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); 265 IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg);
249 } 266 }
250 267
251 if (pfc_en) { 268 for (; i < MAX_TRAFFIC_CLASS; i++) {
252 /* Configure pause time (2 TCs per register) */ 269 IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
253 reg = hw->fc.pause_time | (hw->fc.pause_time << 16); 270 IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), 0);
254 for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++) 271 }
255 IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
256
257 /* Configure flow control refresh threshold value */
258 IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
259
260
261 reg = IXGBE_FCCFG_TFCE_PRIORITY;
262 IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg);
263 /*
264 * Enable Receive PFC
265 * 82599 will always honor XOFF frames we receive when
266 * we are in PFC mode however X540 only honors enabled
267 * traffic classes.
268 */
269 reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
270 reg &= ~IXGBE_MFLCN_RFCE;
271 reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF;
272
273 if (hw->mac.type == ixgbe_mac_X540) {
274 reg &= ~IXGBE_MFLCN_RPFCE_MASK;
275 reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT;
276 }
277 272
278 IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); 273 /* Configure pause time (2 TCs per register) */
274 reg = hw->fc.pause_time * 0x00010001;
275 for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
276 IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
279 277
280 } else { 278 /* Configure flow control refresh threshold value */
281 hw->mac.ops.fc_enable(hw); 279 IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
282 }
283 280
284 return 0; 281 return 0;
285} 282}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
index a09d6b4f0ab0..7f2fa6992775 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
@@ -338,6 +338,8 @@ static void ixgbe_dcbnl_devreset(struct net_device *dev)
338static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) 338static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
339{ 339{
340 struct ixgbe_adapter *adapter = netdev_priv(netdev); 340 struct ixgbe_adapter *adapter = netdev_priv(netdev);
341 struct ixgbe_dcb_config *dcb_cfg = &adapter->dcb_cfg;
342 struct ixgbe_hw *hw = &adapter->hw;
341 int ret = DCB_NO_HW_CHG; 343 int ret = DCB_NO_HW_CHG;
342 int i; 344 int i;
343 345
@@ -350,32 +352,6 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
350 if (!adapter->dcb_set_bitmap) 352 if (!adapter->dcb_set_bitmap)
351 return ret; 353 return ret;
352 354
353 if (adapter->dcb_cfg.pfc_mode_enable) {
354 switch (adapter->hw.mac.type) {
355 case ixgbe_mac_82599EB:
356 case ixgbe_mac_X540:
357 if (adapter->hw.fc.current_mode != ixgbe_fc_pfc)
358 adapter->last_lfc_mode =
359 adapter->hw.fc.current_mode;
360 break;
361 default:
362 break;
363 }
364 adapter->hw.fc.requested_mode = ixgbe_fc_pfc;
365 } else {
366 switch (adapter->hw.mac.type) {
367 case ixgbe_mac_82598EB:
368 adapter->hw.fc.requested_mode = ixgbe_fc_none;
369 break;
370 case ixgbe_mac_82599EB:
371 case ixgbe_mac_X540:
372 adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
373 break;
374 default:
375 break;
376 }
377 }
378
379 if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) { 355 if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) {
380 u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS]; 356 u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS];
381 u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS]; 357 u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS];
@@ -388,23 +364,19 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
388 max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE); 364 max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
389#endif 365#endif
390 366
391 ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg, 367 ixgbe_dcb_calculate_tc_credits(hw, dcb_cfg, max_frame,
392 max_frame, DCB_TX_CONFIG); 368 DCB_TX_CONFIG);
393 ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg, 369 ixgbe_dcb_calculate_tc_credits(hw, dcb_cfg, max_frame,
394 max_frame, DCB_RX_CONFIG); 370 DCB_RX_CONFIG);
395 371
396 ixgbe_dcb_unpack_refill(&adapter->dcb_cfg, 372 ixgbe_dcb_unpack_refill(dcb_cfg, DCB_TX_CONFIG, refill);
397 DCB_TX_CONFIG, refill); 373 ixgbe_dcb_unpack_max(dcb_cfg, max);
398 ixgbe_dcb_unpack_max(&adapter->dcb_cfg, max); 374 ixgbe_dcb_unpack_bwgid(dcb_cfg, DCB_TX_CONFIG, bwg_id);
399 ixgbe_dcb_unpack_bwgid(&adapter->dcb_cfg, 375 ixgbe_dcb_unpack_prio(dcb_cfg, DCB_TX_CONFIG, prio_type);
400 DCB_TX_CONFIG, bwg_id); 376 ixgbe_dcb_unpack_map(dcb_cfg, DCB_TX_CONFIG, prio_tc);
401 ixgbe_dcb_unpack_prio(&adapter->dcb_cfg,
402 DCB_TX_CONFIG, prio_type);
403 ixgbe_dcb_unpack_map(&adapter->dcb_cfg,
404 DCB_TX_CONFIG, prio_tc);
405 377
406 ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max, 378 ixgbe_dcb_hw_ets_config(hw, refill, max, bwg_id,
407 bwg_id, prio_type, prio_tc); 379 prio_type, prio_tc);
408 380
409 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) 381 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
410 netdev_set_prio_tc_map(netdev, i, prio_tc[i]); 382 netdev_set_prio_tc_map(netdev, i, prio_tc[i]);
@@ -413,20 +385,19 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
413 } 385 }
414 386
415 if (adapter->dcb_set_bitmap & BIT_PFC) { 387 if (adapter->dcb_set_bitmap & BIT_PFC) {
416 u8 pfc_en; 388 if (dcb_cfg->pfc_mode_enable) {
417 u8 prio_tc[MAX_USER_PRIORITY]; 389 u8 pfc_en;
418 390 u8 prio_tc[MAX_USER_PRIORITY];
419 ixgbe_dcb_unpack_map(&adapter->dcb_cfg, 391
420 DCB_TX_CONFIG, prio_tc); 392 ixgbe_dcb_unpack_map(dcb_cfg, DCB_TX_CONFIG, prio_tc);
421 ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en); 393 ixgbe_dcb_unpack_pfc(dcb_cfg, &pfc_en);
422 ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en, prio_tc); 394 ixgbe_dcb_hw_pfc_config(hw, pfc_en, prio_tc);
423 if (ret != DCB_HW_CHG_RST) 395 } else {
424 ret = DCB_HW_CHG; 396 hw->mac.ops.fc_enable(hw);
397 }
398 ret = DCB_HW_CHG;
425 } 399 }
426 400
427 if (adapter->dcb_cfg.pfc_mode_enable)
428 adapter->hw.fc.current_mode = ixgbe_fc_pfc;
429
430#ifdef IXGBE_FCOE 401#ifdef IXGBE_FCOE
431 /* Reprogam FCoE hardware offloads when the traffic class 402 /* Reprogam FCoE hardware offloads when the traffic class
432 * FCoE is using changes. This happens if the APP info 403 * FCoE is using changes. This happens if the APP info
@@ -647,7 +618,9 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
647 struct ieee_pfc *pfc) 618 struct ieee_pfc *pfc)
648{ 619{
649 struct ixgbe_adapter *adapter = netdev_priv(dev); 620 struct ixgbe_adapter *adapter = netdev_priv(dev);
621 struct ixgbe_hw *hw = &adapter->hw;
650 u8 *prio_tc; 622 u8 *prio_tc;
623 int err;
651 624
652 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) 625 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
653 return -EINVAL; 626 return -EINVAL;
@@ -659,16 +632,16 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
659 return -ENOMEM; 632 return -ENOMEM;
660 } 633 }
661 634
662 if (pfc->pfc_en) {
663 adapter->last_lfc_mode = adapter->hw.fc.current_mode;
664 adapter->hw.fc.current_mode = ixgbe_fc_pfc;
665 } else {
666 adapter->hw.fc.current_mode = adapter->last_lfc_mode;
667 }
668
669 prio_tc = adapter->ixgbe_ieee_ets->prio_tc; 635 prio_tc = adapter->ixgbe_ieee_ets->prio_tc;
670 memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc)); 636 memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc));
671 return ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en, prio_tc); 637
638 /* Enable link flow control parameters if PFC is disabled */
639 if (pfc->pfc_en)
640 err = ixgbe_dcb_hw_pfc_config(hw, pfc->pfc_en, prio_tc);
641 else
642 err = hw->mac.ops.fc_enable(hw);
643
644 return err;
672} 645}
673 646
674static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev, 647static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index cca3e9c4a08a..082446d44fa8 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -391,11 +391,6 @@ static void ixgbe_get_pauseparam(struct net_device *netdev,
391 } else if (hw->fc.current_mode == ixgbe_fc_full) { 391 } else if (hw->fc.current_mode == ixgbe_fc_full) {
392 pause->rx_pause = 1; 392 pause->rx_pause = 1;
393 pause->tx_pause = 1; 393 pause->tx_pause = 1;
394#ifdef CONFIG_DCB
395 } else if (hw->fc.current_mode == ixgbe_fc_pfc) {
396 pause->rx_pause = 0;
397 pause->tx_pause = 0;
398#endif
399 } 394 }
400} 395}
401 396
@@ -404,21 +399,14 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
404{ 399{
405 struct ixgbe_adapter *adapter = netdev_priv(netdev); 400 struct ixgbe_adapter *adapter = netdev_priv(netdev);
406 struct ixgbe_hw *hw = &adapter->hw; 401 struct ixgbe_hw *hw = &adapter->hw;
407 struct ixgbe_fc_info fc; 402 struct ixgbe_fc_info fc = hw->fc;
408 403
409#ifdef CONFIG_DCB 404 /* 82598 does no support link flow control with DCB enabled */
410 if (adapter->dcb_cfg.pfc_mode_enable || 405 if ((hw->mac.type == ixgbe_mac_82598EB) &&
411 ((hw->mac.type == ixgbe_mac_82598EB) && 406 (adapter->flags & IXGBE_FLAG_DCB_ENABLED))
412 (adapter->flags & IXGBE_FLAG_DCB_ENABLED)))
413 return -EINVAL; 407 return -EINVAL;
414 408
415#endif 409 fc.disable_fc_autoneg = (pause->autoneg != AUTONEG_ENABLE);
416 fc = hw->fc;
417
418 if (pause->autoneg != AUTONEG_ENABLE)
419 fc.disable_fc_autoneg = true;
420 else
421 fc.disable_fc_autoneg = false;
422 410
423 if ((pause->rx_pause && pause->tx_pause) || pause->autoneg) 411 if ((pause->rx_pause && pause->tx_pause) || pause->autoneg)
424 fc.requested_mode = ixgbe_fc_full; 412 fc.requested_mode = ixgbe_fc_full;
@@ -426,14 +414,8 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
426 fc.requested_mode = ixgbe_fc_rx_pause; 414 fc.requested_mode = ixgbe_fc_rx_pause;
427 else if (!pause->rx_pause && pause->tx_pause) 415 else if (!pause->rx_pause && pause->tx_pause)
428 fc.requested_mode = ixgbe_fc_tx_pause; 416 fc.requested_mode = ixgbe_fc_tx_pause;
429 else if (!pause->rx_pause && !pause->tx_pause)
430 fc.requested_mode = ixgbe_fc_none;
431 else 417 else
432 return -EINVAL; 418 fc.requested_mode = ixgbe_fc_none;
433
434#ifdef CONFIG_DCB
435 adapter->last_lfc_mode = fc.requested_mode;
436#endif
437 419
438 /* if the thing changed then we'll update and use new autoneg */ 420 /* if the thing changed then we'll update and use new autoneg */
439 if (memcmp(&fc, &hw->fc, sizeof(struct ixgbe_fc_info))) { 421 if (memcmp(&fc, &hw->fc, sizeof(struct ixgbe_fc_info))) {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index ea3cb710c2dd..0915e77cf375 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -610,39 +610,50 @@ void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *ring,
610 /* tx_buffer must be completely set up in the transmit path */ 610 /* tx_buffer must be completely set up in the transmit path */
611} 611}
612 612
613static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter) 613static void ixgbe_update_xoff_rx_lfc(struct ixgbe_adapter *adapter)
614{ 614{
615 struct ixgbe_hw *hw = &adapter->hw; 615 struct ixgbe_hw *hw = &adapter->hw;
616 struct ixgbe_hw_stats *hwstats = &adapter->stats; 616 struct ixgbe_hw_stats *hwstats = &adapter->stats;
617 u32 data = 0;
618 u32 xoff[8] = {0};
619 int i; 617 int i;
618 u32 data;
620 619
621 if ((hw->fc.current_mode == ixgbe_fc_full) || 620 if ((hw->fc.current_mode != ixgbe_fc_full) &&
622 (hw->fc.current_mode == ixgbe_fc_rx_pause)) { 621 (hw->fc.current_mode != ixgbe_fc_rx_pause))
623 switch (hw->mac.type) { 622 return;
624 case ixgbe_mac_82598EB:
625 data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
626 break;
627 default:
628 data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
629 }
630 hwstats->lxoffrxc += data;
631 623
632 /* refill credits (no tx hang) if we received xoff */ 624 switch (hw->mac.type) {
633 if (!data) 625 case ixgbe_mac_82598EB:
634 return; 626 data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
627 break;
628 default:
629 data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
630 }
631 hwstats->lxoffrxc += data;
635 632
636 for (i = 0; i < adapter->num_tx_queues; i++) 633 /* refill credits (no tx hang) if we received xoff */
637 clear_bit(__IXGBE_HANG_CHECK_ARMED, 634 if (!data)
638 &adapter->tx_ring[i]->state);
639 return; 635 return;
640 } else if (((adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE) && 636
641 !(adapter->dcb_cfg.pfc_mode_enable)) || 637 for (i = 0; i < adapter->num_tx_queues; i++)
642 ((adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) && 638 clear_bit(__IXGBE_HANG_CHECK_ARMED,
643 adapter->ixgbe_ieee_pfc && 639 &adapter->tx_ring[i]->state);
644 !(adapter->ixgbe_ieee_pfc->pfc_en))) 640}
641
642static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
643{
644 struct ixgbe_hw *hw = &adapter->hw;
645 struct ixgbe_hw_stats *hwstats = &adapter->stats;
646 u32 xoff[8] = {0};
647 int i;
648 bool pfc_en = adapter->dcb_cfg.pfc_mode_enable;
649
650 if (adapter->ixgbe_ieee_pfc)
651 pfc_en |= !!(adapter->ixgbe_ieee_pfc->pfc_en);
652
653 if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED) || !pfc_en) {
654 ixgbe_update_xoff_rx_lfc(adapter);
645 return; 655 return;
656 }
646 657
647 /* update stats for each tc, only valid with PFC enabled */ 658 /* update stats for each tc, only valid with PFC enabled */
648 for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) { 659 for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) {
@@ -4403,9 +4414,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
4403 /* default flow control settings */ 4414 /* default flow control settings */
4404 hw->fc.requested_mode = ixgbe_fc_full; 4415 hw->fc.requested_mode = ixgbe_fc_full;
4405 hw->fc.current_mode = ixgbe_fc_full; /* init for ethtool output */ 4416 hw->fc.current_mode = ixgbe_fc_full; /* init for ethtool output */
4406#ifdef CONFIG_DCB
4407 adapter->last_lfc_mode = hw->fc.current_mode;
4408#endif
4409 ixgbe_pbthresh_setup(adapter); 4417 ixgbe_pbthresh_setup(adapter);
4410 hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE; 4418 hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
4411 hw->fc.send_xon = true; 4419 hw->fc.send_xon = true;
@@ -6542,15 +6550,17 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
6542 6550
6543 if (tc) { 6551 if (tc) {
6544 netdev_set_num_tc(dev, tc); 6552 netdev_set_num_tc(dev, tc);
6545 adapter->last_lfc_mode = adapter->hw.fc.current_mode;
6546 adapter->flags |= IXGBE_FLAG_DCB_ENABLED; 6553 adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
6547 adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; 6554 adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
6548 6555
6549 if (adapter->hw.mac.type == ixgbe_mac_82598EB) 6556 if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
6557 adapter->last_lfc_mode = adapter->hw.fc.requested_mode;
6550 adapter->hw.fc.requested_mode = ixgbe_fc_none; 6558 adapter->hw.fc.requested_mode = ixgbe_fc_none;
6559 }
6551 } else { 6560 } else {
6552 netdev_reset_tc(dev); 6561 netdev_reset_tc(dev);
6553 adapter->hw.fc.requested_mode = adapter->last_lfc_mode; 6562 if (adapter->hw.mac.type == ixgbe_mac_82598EB)
6563 adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
6554 6564
6555 adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; 6565 adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
6556 adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; 6566 adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 5e64c77255e9..9559c03ab696 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -2573,9 +2573,6 @@ enum ixgbe_fc_mode {
2573 ixgbe_fc_rx_pause, 2573 ixgbe_fc_rx_pause,
2574 ixgbe_fc_tx_pause, 2574 ixgbe_fc_tx_pause,
2575 ixgbe_fc_full, 2575 ixgbe_fc_full,
2576#ifdef CONFIG_DCB
2577 ixgbe_fc_pfc,
2578#endif
2579 ixgbe_fc_default 2576 ixgbe_fc_default
2580}; 2577};
2581 2578