/** * ixgbe_dcb_config_pfc_82599 - Configure priority flow control * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Priority Flow Control (PFC) for each traffic class. */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { u32 i, reg; /* If PFC is disabled globally then fall back to LFC. */ if (!dcb_config->pfc_mode_enable) { for (i = 0; i < MAX_TRAFFIC_CLASS; i++) hw->mac.ops.setup_fc(hw, i); goto out; } /* Configure PFC Tx thresholds per TC */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { /* Config and remember Tx */ if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full || dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx) { reg = hw->fc.high_water | IXGBE_FCRTH_FCEN; IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); reg = hw->fc.low_water | IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); } else { IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), 0); IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); } } /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time | (hw->fc.pause_time << 16); for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); /* Enable Transmit PFC */ reg = IXGBE_FCCFG_TFCE_PRIORITY; IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg); /* * Enable Receive PFC * We will always honor XOFF frames we receive when * we are in PFC mode. */ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg &= ~IXGBE_MFLCN_RFCE; reg |= IXGBE_MFLCN_RPFCE; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); out: return 0; }
/** * ixgbe_dcb_config_pfc_82599 - Configure priority flow control * @hw: pointer to hardware structure * @pfc_en: enabled pfc bitmask * * Configure Priority Flow Control (PFC) for each traffic class. */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en) { u32 i, reg, rx_pba_size; /* Configure PFC Tx thresholds per TC */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { int enabled = pfc_en & (1 << i); rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)); rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT; reg = (rx_pba_size - hw->fc.low_water) << 10; if (enabled) reg |= IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); reg = (rx_pba_size - hw->fc.high_water) << 10; if (enabled) reg |= IXGBE_FCRTH_FCEN; IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); } if (pfc_en) { /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time | (hw->fc.pause_time << 16); for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); reg = IXGBE_FCCFG_TFCE_PRIORITY; IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg); /* * Enable Receive PFC * 82599 will always honor XOFF frames we receive when * we are in PFC mode however X540 only honors enabled * traffic classes. */ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg &= ~IXGBE_MFLCN_RFCE; reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF; if (hw->mac.type == ixgbe_mac_X540) reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); } else { for (i = 0; i < MAX_TRAFFIC_CLASS; i++) hw->mac.ops.fc_enable(hw, i); } return 0; }
/** * ixgbe_dcb_config_pfc_82599 - Configure priority flow control * @hw: pointer to hardware structure * @pfc_en: enabled pfc bitmask * @prio_tc: priority to tc assignments indexed by priority * * Configure Priority Flow Control (PFC) for each traffic class. */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc) { u32 i, j, reg; u8 max_tc = 0; for (i = 0; i < MAX_USER_PRIORITY; i++) if (prio_tc[i] > max_tc) max_tc = prio_tc[i]; /* Configure PFC Tx thresholds per TC */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { int enabled = 0; if (i > max_tc) { reg = 0; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); continue; } for (j = 0; j < MAX_USER_PRIORITY; j++) { if ((prio_tc[j] == i) && (pfc_en & (1 << j))) { enabled = 1; break; } } reg = hw->fc.low_water << 10; if (enabled) reg |= IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); reg = hw->fc.high_water[i] << 10; if (enabled) reg |= IXGBE_FCRTH_FCEN; IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); } if (pfc_en) { /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time | (hw->fc.pause_time << 16); for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); reg = IXGBE_FCCFG_TFCE_PRIORITY; IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg); /* * Enable Receive PFC * 82599 will always honor XOFF frames we receive when * we are in PFC mode however X540 only honors enabled * traffic classes. */ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg &= ~IXGBE_MFLCN_RFCE; reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF; if (hw->mac.type == ixgbe_mac_X540) { reg &= ~IXGBE_MFLCN_RPFCE_MASK; reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT; } IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); } else { /* X540 devices have a RX bit that should be cleared * if PFC is disabled on all TCs but PFC features is * enabled. */ if (hw->mac.type == ixgbe_mac_X540) { reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg &= ~IXGBE_MFLCN_RPFCE_MASK; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); } for (i = 0; i < MAX_TRAFFIC_CLASS; i++) hw->mac.ops.fc_enable(hw, i); } return 0; }
/** * ixgbe_dcb_config_pfc_82599 - Configure priority flow control * @hw: pointer to hardware structure * @pfc_en: enabled pfc bitmask * @map: priority to tc assignments indexed by priority * * Configure Priority Flow Control (PFC) for each traffic class. */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *map) { u32 i, j, fcrtl, reg; u8 max_tc = 0; /* Enable Transmit Priority Flow Control */ IXGBE_WRITE_REG(hw, IXGBE_FCCFG, IXGBE_FCCFG_TFCE_PRIORITY); /* Enable Receive Priority Flow Control */ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg |= IXGBE_MFLCN_DPF; /* * X540 supports per TC Rx priority flow control. So * clear all TCs and only enable those that should be * enabled. */ reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); if (hw->mac.type == ixgbe_mac_X540) reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT; if (pfc_en) reg |= IXGBE_MFLCN_RPFCE; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) { if (map[i] > max_tc) max_tc = map[i]; } /* Configure PFC Tx thresholds per TC */ for (i = 0; i <= max_tc; i++) { int enabled = 0; for (j = 0; j < IXGBE_DCB_MAX_USER_PRIORITY; j++) { if ((map[j] == i) && (pfc_en & (1 << j))) { enabled = 1; break; } } if (enabled) { reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); } else { reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); } IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); } for (; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), 0); } /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time | (hw->fc.pause_time << 16); for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); return 0; }
/** * ixgbe_dcb_config_pfc_82599 - Configure priority flow control * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Priority Flow Control (PFC) for each traffic class. */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { u32 i, reg, rx_pba_size; u8 pfc_en = 0; /* If PFC is disabled globally then fall back to LFC. */ if (!dcb_config->pfc_mode_enable) { for (i = 0; i < MAX_TRAFFIC_CLASS; i++) hw->mac.ops.fc_enable(hw, i); goto out; } /* Configure PFC Tx thresholds per TC */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)); rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT; reg = (rx_pba_size - hw->fc.low_water) << 10; if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full || dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx) reg |= IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); reg = (rx_pba_size - hw->fc.high_water) << 10; if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full || dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx) reg |= IXGBE_FCRTH_FCEN; IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); } /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time | (hw->fc.pause_time << 16); for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); /* Enable Transmit PFC */ reg = IXGBE_FCCFG_TFCE_PRIORITY; IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg); /* * Enable Receive PFC * 82599 will always honor XOFF frames we receive when * we are in PFC mode however X540 only honors enabled * traffic classes. */ /* ripped from upstream ixgbe_dcb_unpack_pfc */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) pfc_en |= (dcb_config->tc_config[i].dcb_pfc & 0xF) << i; reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg &= ~IXGBE_MFLCN_RFCE; reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF; if (hw->mac.type == ixgbe_mac_X540) reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); out: return 0; }
/** * ixgbe_dcb_config_pfc_82599 - Configure priority flow control * @hw: pointer to hardware structure * @pfc_en: enabled pfc bitmask * @map: priority to tc assignments indexed by priority * * Configure Priority Flow Control (PFC) for each traffic class. */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *map) { u32 i, j, fcrtl, reg; u8 max_tc = 0; /* Enable Transmit Priority Flow Control */ IXGBE_WRITE_REG(hw, IXGBE_FCCFG, IXGBE_FCCFG_TFCE_PRIORITY); /* Enable Receive Priority Flow Control */ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg |= IXGBE_MFLCN_DPF; /* * X540 supports per TC Rx priority flow control. So * clear all TCs and only enable those that should be * enabled. */ reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); if (hw->mac.type >= ixgbe_mac_X540) reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT; if (pfc_en) reg |= IXGBE_MFLCN_RPFCE; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) { if (map[i] > max_tc) max_tc = map[i]; } /* Configure PFC Tx thresholds per TC */ for (i = 0; i <= max_tc; i++) { int enabled = 0; for (j = 0; j < IXGBE_DCB_MAX_USER_PRIORITY; j++) { if ((map[j] == i) && (pfc_en & (1 << j))) { enabled = 1; break; } } if (enabled) { reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); } else { /* * In order to prevent Tx hangs when the internal Tx * switch is enabled we must set the high water mark * to the Rx packet buffer size - 24KB. This allows * the Tx switch to function even under heavy Rx * workloads. */ reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); } IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); } for (; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), 0); } /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time | (hw->fc.pause_time << 16); for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); return IXGBE_SUCCESS; }
/** * ixgbe_dcb_config_pfc_82599 - Configure priority flow control * @hw: pointer to hardware structure * @pfc_en: enabled pfc bitmask * @map: priority to tc assignments indexed by priority * * Configure Priority Flow Control (PFC) for each traffic class. */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *map) { u32 i, j, reg; u8 max_tc = 0; for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if (map[i] > max_tc) max_tc = map[i]; } #ifdef CONFIG_DCB /* Block LFC now that we're configuring PFC */ hw->fc.requested_mode = ixgbe_fc_pfc; #endif /* CONFIG_DCB */ /* Configure PFC Tx thresholds per TC */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { int enabled = 0; if (i > max_tc) { reg = 0; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); continue; } for (j = 0; j < IXGBE_DCB_MAX_USER_PRIORITY; j++) { if ((map[j] == i) && (pfc_en & (1 << j))) { enabled = 1; break; } } reg = hw->fc.low_water << 10; if (enabled) reg |= IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); reg = hw->fc.high_water[i] << 10; if (enabled) reg |= IXGBE_FCRTH_FCEN; IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); } if (pfc_en) { /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time | (hw->fc.pause_time << 16); for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); /* Enable Transmit PFC */ reg = IXGBE_FCCFG_TFCE_PRIORITY; IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg); /* * Enable Receive PFC * We will always honor XOFF frames we receive when * we are in PFC mode. */ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE_MASK); reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF; if (hw->mac.type == ixgbe_mac_X540) reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); } else { for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) hw->mac.ops.fc_enable(hw, i); } return 0; }