1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2015-2020
5 #include "txgbe_type.h"
8 #include "txgbe_dcb_hw.h"
11 * txgbe_pfc_enable - Enable flow control
12 * @hw: pointer to hardware structure
13 * @tc_num: traffic class number
14 * Enable flow control according to the current settings.
17 txgbe_dcb_pfc_enable(struct txgbe_hw *hw, uint8_t tc_num)
20 uint32_t mflcn_reg, fccfg_reg;
22 uint32_t fcrtl, fcrth;
26 /* Validate the water mark configuration */
27 if (!hw->fc.pause_time) {
28 ret_val = TXGBE_ERR_INVALID_LINK_SETTINGS;
32 /* Low water mark of zero causes XOFF floods */
33 if (hw->fc.current_mode & txgbe_fc_tx_pause) {
34 /* High/Low water can not be 0 */
35 if (!hw->fc.high_water[tc_num] ||
36 !hw->fc.low_water[tc_num]) {
37 PMD_INIT_LOG(ERR, "Invalid water mark configuration");
38 ret_val = TXGBE_ERR_INVALID_LINK_SETTINGS;
42 if (hw->fc.low_water[tc_num] >= hw->fc.high_water[tc_num]) {
43 PMD_INIT_LOG(ERR, "Invalid water mark configuration");
44 ret_val = TXGBE_ERR_INVALID_LINK_SETTINGS;
48 /* Negotiate the fc mode to use */
51 /* Disable any previous flow control settings */
52 mflcn_reg = rd32(hw, TXGBE_RXFCCFG);
53 mflcn_reg &= ~(TXGBE_RXFCCFG_FC | TXGBE_RXFCCFG_PFC);
55 fccfg_reg = rd32(hw, TXGBE_TXFCCFG);
56 fccfg_reg &= ~(TXGBE_TXFCCFG_FC | TXGBE_TXFCCFG_PFC);
58 switch (hw->fc.current_mode) {
61 * If the count of enabled RX Priority Flow control > 1,
62 * and the TX pause can not be disabled
65 for (i = 0; i < TXGBE_DCB_TC_MAX; i++) {
66 uint32_t reg = rd32(hw, TXGBE_FCWTRHI(i));
67 if (reg & TXGBE_FCWTRHI_XOFF)
71 fccfg_reg |= TXGBE_TXFCCFG_PFC;
73 case txgbe_fc_rx_pause:
75 * Rx Flow control is enabled and Tx Flow control is
76 * disabled by software override. Since there really
77 * isn't a way to advertise that we are capable of RX
78 * Pause ONLY, we will advertise that we support both
79 * symmetric and asymmetric Rx PAUSE. Later, we will
80 * disable the adapter's ability to send PAUSE frames.
82 mflcn_reg |= TXGBE_RXFCCFG_PFC;
84 * If the count of enabled RX Priority Flow control > 1,
85 * and the TX pause can not be disabled
88 for (i = 0; i < TXGBE_DCB_TC_MAX; i++) {
89 uint32_t reg = rd32(hw, TXGBE_FCWTRHI(i));
90 if (reg & TXGBE_FCWTRHI_XOFF)
94 fccfg_reg |= TXGBE_TXFCCFG_PFC;
96 case txgbe_fc_tx_pause:
98 * Tx Flow control is enabled, and Rx Flow control is
99 * disabled by software override.
101 fccfg_reg |= TXGBE_TXFCCFG_PFC;
104 /* Flow control (both Rx and Tx) is enabled by SW override. */
105 mflcn_reg |= TXGBE_RXFCCFG_PFC;
106 fccfg_reg |= TXGBE_TXFCCFG_PFC;
109 PMD_DRV_LOG(DEBUG, "Flow control param set incorrectly");
110 ret_val = TXGBE_ERR_CONFIG;
114 /* Set 802.3x based flow control settings. */
115 wr32(hw, TXGBE_RXFCCFG, mflcn_reg);
116 wr32(hw, TXGBE_TXFCCFG, fccfg_reg);
118 /* Set up and enable Rx high/low water mark thresholds, enable XON. */
119 if ((hw->fc.current_mode & txgbe_fc_tx_pause) &&
120 hw->fc.high_water[tc_num]) {
121 fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[tc_num]) |
123 fcrth = TXGBE_FCWTRHI_TH(hw->fc.high_water[tc_num]) |
127 * In order to prevent Tx hangs when the internal Tx
128 * switch is enabled we must set the high water mark
129 * to the maximum FCRTH value. This allows the Tx
130 * switch to function even under heavy Rx workloads.
133 fcrth = rd32(hw, TXGBE_PBRXSIZE(tc_num)) - 32;
135 wr32(hw, TXGBE_FCWTRLO(tc_num), fcrtl);
136 wr32(hw, TXGBE_FCWTRHI(tc_num), fcrth);
138 /* Configure pause time (2 TCs per register) */
139 pause_time = TXGBE_RXFCFSH_TIME(hw->fc.pause_time);
140 for (i = 0; i < (TXGBE_DCB_TC_MAX / 2); i++)
141 wr32(hw, TXGBE_FCXOFFTM(i), pause_time * 0x00010001);
143 /* Configure flow control refresh threshold value */
144 wr32(hw, TXGBE_RXFCRFSH, pause_time / 2);
151 * txgbe_dcb_calculate_tc_credits_cee - Calculates traffic class credits
152 * @hw: pointer to hardware structure
153 * @dcb_config: Struct containing DCB settings
154 * @max_frame_size: Maximum frame size
155 * @direction: Configuring either Tx or Rx
157 * This function calculates the credits allocated to each traffic class.
158 * It should be called only after the rules are checked by
159 * txgbe_dcb_check_config_cee().
161 s32 txgbe_dcb_calculate_tc_credits_cee(struct txgbe_hw *hw,
162 struct txgbe_dcb_config *dcb_config,
163 u32 max_frame_size, u8 direction)
165 struct txgbe_dcb_tc_path *p;
166 u32 min_multiplier = 0;
167 u16 min_percent = 100;
169 /* Initialization values default for Tx settings */
171 u32 credit_refill = 0;
173 u16 link_percentage = 0;
177 UNREFERENCED_PARAMETER(hw);
179 if (dcb_config == NULL) {
180 ret_val = TXGBE_ERR_CONFIG;
184 min_credit = ((max_frame_size / 2) + TXGBE_DCB_CREDIT_QUANTUM - 1) /
185 TXGBE_DCB_CREDIT_QUANTUM;
187 /* Find smallest link percentage */
188 for (i = 0; i < TXGBE_DCB_TC_MAX; i++) {
189 p = &dcb_config->tc_config[i].path[direction];
190 bw_percent = dcb_config->bw_percentage[p->bwg_id][direction];
191 link_percentage = p->bwg_percent;
193 link_percentage = (link_percentage * bw_percent) / 100;
195 if (link_percentage && link_percentage < min_percent)
196 min_percent = link_percentage;
200 * The ratio between traffic classes will control the bandwidth
201 * percentages seen on the wire. To calculate this ratio we use
202 * a multiplier. It is required that the refill credits must be
203 * larger than the max frame size so here we find the smallest
204 * multiplier that will allow all bandwidth percentages to be
205 * greater than the max frame size.
207 min_multiplier = (min_credit / min_percent) + 1;
209 /* Find out the link percentage for each TC first */
210 for (i = 0; i < TXGBE_DCB_TC_MAX; i++) {
211 p = &dcb_config->tc_config[i].path[direction];
212 bw_percent = dcb_config->bw_percentage[p->bwg_id][direction];
214 link_percentage = p->bwg_percent;
215 /* Must be careful of integer division for very small nums */
216 link_percentage = (link_percentage * bw_percent) / 100;
217 if (p->bwg_percent > 0 && link_percentage == 0)
220 /* Save link_percentage for reference */
221 p->link_percent = (u8)link_percentage;
223 /* Calculate credit refill ratio using multiplier */
224 credit_refill = min(link_percentage * min_multiplier,
225 (u32)TXGBE_DCB_MAX_CREDIT_REFILL);
227 /* Refill at least minimum credit */
228 if (credit_refill < min_credit)
229 credit_refill = min_credit;
231 p->data_credits_refill = (u16)credit_refill;
233 /* Calculate maximum credit for the TC */
234 credit_max = (link_percentage * TXGBE_DCB_MAX_CREDIT) / 100;
237 * Adjustment based on rule checking, if the percentage
238 * of a TC is too small, the maximum credit may not be
239 * enough to send out a jumbo frame in data plane arbitration.
241 if (credit_max < min_credit)
242 credit_max = min_credit;
244 if (direction == TXGBE_DCB_TX_CONFIG) {
245 dcb_config->tc_config[i].desc_credits_max =
249 p->data_credits_max = (u16)credit_max;
257 * txgbe_dcb_unpack_pfc_cee - Unpack dcb_config PFC info
258 * @cfg: dcb configuration to unpack into hardware consumable fields
259 * @map: user priority to traffic class map
260 * @pfc_up: u8 to store user priority PFC bitmask
262 * This unpacks the dcb configuration PFC info which is stored per
263 * traffic class into a 8bit user priority bitmask that can be
264 * consumed by hardware routines. The priority to tc map must be
265 * updated before calling this routine to use current up-to maps.
267 void txgbe_dcb_unpack_pfc_cee(struct txgbe_dcb_config *cfg, u8 *map, u8 *pfc_up)
269 struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
273 * If the TC for this user priority has PFC enabled then set the
274 * matching bit in 'pfc_up' to reflect that PFC is enabled.
276 for (*pfc_up = 0, up = 0; up < TXGBE_DCB_UP_MAX; up++) {
277 if (tc_config[map[up]].pfc != txgbe_dcb_pfc_disabled)
282 void txgbe_dcb_unpack_refill_cee(struct txgbe_dcb_config *cfg, int direction,
285 struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
288 for (tc = 0; tc < TXGBE_DCB_TC_MAX; tc++)
289 refill[tc] = tc_config[tc].path[direction].data_credits_refill;
292 void txgbe_dcb_unpack_max_cee(struct txgbe_dcb_config *cfg, u16 *max)
294 struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
297 for (tc = 0; tc < TXGBE_DCB_TC_MAX; tc++)
298 max[tc] = tc_config[tc].desc_credits_max;
301 void txgbe_dcb_unpack_bwgid_cee(struct txgbe_dcb_config *cfg, int direction,
304 struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
307 for (tc = 0; tc < TXGBE_DCB_TC_MAX; tc++)
308 bwgid[tc] = tc_config[tc].path[direction].bwg_id;
311 void txgbe_dcb_unpack_tsa_cee(struct txgbe_dcb_config *cfg, int direction,
314 struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
317 for (tc = 0; tc < TXGBE_DCB_TC_MAX; tc++)
318 tsa[tc] = tc_config[tc].path[direction].tsa;
321 u8 txgbe_dcb_get_tc_from_up(struct txgbe_dcb_config *cfg, int direction, u8 up)
323 struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
324 u8 prio_mask = 1 << up;
325 u8 tc = cfg->num_tcs.pg_tcs;
327 /* If tc is 0 then DCB is likely not enabled or supported */
332 * Test from maximum TC to 1 and report the first match we find. If
333 * we find no match we can assume that the TC is 0 since the TC must
334 * be set for all user priorities
336 for (tc--; tc; tc--) {
337 if (prio_mask & tc_config[tc].path[direction].up_to_tc_bitmap)
344 void txgbe_dcb_unpack_map_cee(struct txgbe_dcb_config *cfg, int direction,
349 for (up = 0; up < TXGBE_DCB_UP_MAX; up++)
350 map[up] = txgbe_dcb_get_tc_from_up(cfg, direction, up);
353 /* Helper routines to abstract HW specifics from DCB netlink ops */
354 s32 txgbe_dcb_config_pfc(struct txgbe_hw *hw, u8 pfc_en, u8 *map)
356 int ret = TXGBE_ERR_PARAM;
357 ret = txgbe_dcb_config_pfc_raptor(hw, pfc_en, map);