1251964Sjfv/******************************************************************************
2251964Sjfv
3315333Serj  Copyright (c) 2001-2017, Intel Corporation
4251964Sjfv  All rights reserved.
5315333Serj
6315333Serj  Redistribution and use in source and binary forms, with or without
7251964Sjfv  modification, are permitted provided that the following conditions are met:
8315333Serj
9315333Serj   1. Redistributions of source code must retain the above copyright notice,
10251964Sjfv      this list of conditions and the following disclaimer.
11315333Serj
12315333Serj   2. Redistributions in binary form must reproduce the above copyright
13315333Serj      notice, this list of conditions and the following disclaimer in the
14251964Sjfv      documentation and/or other materials provided with the distribution.
15315333Serj
16315333Serj   3. Neither the name of the Intel Corporation nor the names of its
17315333Serj      contributors may be used to endorse or promote products derived from
18251964Sjfv      this software without specific prior written permission.
19315333Serj
20251964Sjfv  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21315333Serj  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22315333Serj  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23315333Serj  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24315333Serj  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25315333Serj  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26315333Serj  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27315333Serj  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28315333Serj  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29251964Sjfv  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30251964Sjfv  POSSIBILITY OF SUCH DAMAGE.
31251964Sjfv
32251964Sjfv******************************************************************************/
33251964Sjfv/*$FreeBSD: stable/10/sys/dev/ixgbe/ixgbe_dcb.c 315333 2017-03-15 21:20:17Z erj $*/
34251964Sjfv
35251964Sjfv
36251964Sjfv#include "ixgbe_type.h"
37251964Sjfv#include "ixgbe_dcb.h"
38251964Sjfv#include "ixgbe_dcb_82598.h"
39251964Sjfv#include "ixgbe_dcb_82599.h"
40251964Sjfv
41251964Sjfv/**
42251964Sjfv * ixgbe_dcb_calculate_tc_credits - This calculates the ieee traffic class
43251964Sjfv * credits from the configured bandwidth percentages. Credits
44251964Sjfv * are the smallest unit programmable into the underlying
45251964Sjfv * hardware. The IEEE 802.1Qaz specification do not use bandwidth
46251964Sjfv * groups so this is much simplified from the CEE case.
47251964Sjfv */
48251964Sjfvs32 ixgbe_dcb_calculate_tc_credits(u8 *bw, u16 *refill, u16 *max,
49251964Sjfv				   int max_frame_size)
50251964Sjfv{
51251964Sjfv	int min_percent = 100;
52251964Sjfv	int min_credit, multiplier;
53251964Sjfv	int i;
54251964Sjfv
55251964Sjfv	min_credit = ((max_frame_size / 2) + IXGBE_DCB_CREDIT_QUANTUM - 1) /
56251964Sjfv			IXGBE_DCB_CREDIT_QUANTUM;
57251964Sjfv
58251964Sjfv	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
59251964Sjfv		if (bw[i] < min_percent && bw[i])
60251964Sjfv			min_percent = bw[i];
61251964Sjfv	}
62251964Sjfv
63251964Sjfv	multiplier = (min_credit / min_percent) + 1;
64251964Sjfv
65251964Sjfv	/* Find out the hw credits for each TC */
66251964Sjfv	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
67251964Sjfv		int val = min(bw[i] * multiplier, IXGBE_DCB_MAX_CREDIT_REFILL);
68251964Sjfv
69251964Sjfv		if (val < min_credit)
70251964Sjfv			val = min_credit;
71251964Sjfv		refill[i] = (u16)val;
72251964Sjfv
73251964Sjfv		max[i] = bw[i] ? (bw[i]*IXGBE_DCB_MAX_CREDIT)/100 : min_credit;
74251964Sjfv	}
75251964Sjfv
76251964Sjfv	return 0;
77251964Sjfv}
78251964Sjfv
79251964Sjfv/**
80251964Sjfv * ixgbe_dcb_calculate_tc_credits_cee - Calculates traffic class credits
81251964Sjfv * @ixgbe_dcb_config: Struct containing DCB settings.
82251964Sjfv * @direction: Configuring either Tx or Rx.
83251964Sjfv *
84251964Sjfv * This function calculates the credits allocated to each traffic class.
85251964Sjfv * It should be called only after the rules are checked by
86251964Sjfv * ixgbe_dcb_check_config_cee().
87251964Sjfv */
88251964Sjfvs32 ixgbe_dcb_calculate_tc_credits_cee(struct ixgbe_hw *hw,
89251964Sjfv				   struct ixgbe_dcb_config *dcb_config,
90251964Sjfv				   u32 max_frame_size, u8 direction)
91251964Sjfv{
92251964Sjfv	struct ixgbe_dcb_tc_path *p;
93251964Sjfv	u32 min_multiplier	= 0;
94251964Sjfv	u16 min_percent		= 100;
95251964Sjfv	s32 ret_val =		IXGBE_SUCCESS;
96251964Sjfv	/* Initialization values default for Tx settings */
97251964Sjfv	u32 min_credit		= 0;
98251964Sjfv	u32 credit_refill	= 0;
99251964Sjfv	u32 credit_max		= 0;
100251964Sjfv	u16 link_percentage	= 0;
101251964Sjfv	u8  bw_percent		= 0;
102251964Sjfv	u8  i;
103251964Sjfv
104251964Sjfv	if (dcb_config == NULL) {
105251964Sjfv		ret_val = IXGBE_ERR_CONFIG;
106251964Sjfv		goto out;
107251964Sjfv	}
108251964Sjfv
109251964Sjfv	min_credit = ((max_frame_size / 2) + IXGBE_DCB_CREDIT_QUANTUM - 1) /
110251964Sjfv		     IXGBE_DCB_CREDIT_QUANTUM;
111251964Sjfv
112251964Sjfv	/* Find smallest link percentage */
113251964Sjfv	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
114251964Sjfv		p = &dcb_config->tc_config[i].path[direction];
115251964Sjfv		bw_percent = dcb_config->bw_percentage[direction][p->bwg_id];
116251964Sjfv		link_percentage = p->bwg_percent;
117251964Sjfv
118251964Sjfv		link_percentage = (link_percentage * bw_percent) / 100;
119251964Sjfv
120251964Sjfv		if (link_percentage && link_percentage < min_percent)
121251964Sjfv			min_percent = link_percentage;
122251964Sjfv	}
123251964Sjfv
124251964Sjfv	/*
125251964Sjfv	 * The ratio between traffic classes will control the bandwidth
126251964Sjfv	 * percentages seen on the wire. To calculate this ratio we use
127251964Sjfv	 * a multiplier. It is required that the refill credits must be
128251964Sjfv	 * larger than the max frame size so here we find the smallest
129251964Sjfv	 * multiplier that will allow all bandwidth percentages to be
130251964Sjfv	 * greater than the max frame size.
131251964Sjfv	 */
132251964Sjfv	min_multiplier = (min_credit / min_percent) + 1;
133251964Sjfv
134251964Sjfv	/* Find out the link percentage for each TC first */
135251964Sjfv	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
136251964Sjfv		p = &dcb_config->tc_config[i].path[direction];
137251964Sjfv		bw_percent = dcb_config->bw_percentage[direction][p->bwg_id];
138251964Sjfv
139251964Sjfv		link_percentage = p->bwg_percent;
140251964Sjfv		/* Must be careful of integer division for very small nums */
141251964Sjfv		link_percentage = (link_percentage * bw_percent) / 100;
142251964Sjfv		if (p->bwg_percent > 0 && link_percentage == 0)
143251964Sjfv			link_percentage = 1;
144251964Sjfv
145251964Sjfv		/* Save link_percentage for reference */
146251964Sjfv		p->link_percent = (u8)link_percentage;
147251964Sjfv
148251964Sjfv		/* Calculate credit refill ratio using multiplier */
149251964Sjfv		credit_refill = min(link_percentage * min_multiplier,
150251964Sjfv				    (u32)IXGBE_DCB_MAX_CREDIT_REFILL);
151295524Ssbruno
152295524Ssbruno		/* Refill at least minimum credit */
153295524Ssbruno		if (credit_refill < min_credit)
154295524Ssbruno			credit_refill = min_credit;
155295524Ssbruno
156251964Sjfv		p->data_credits_refill = (u16)credit_refill;
157251964Sjfv
158251964Sjfv		/* Calculate maximum credit for the TC */
159251964Sjfv		credit_max = (link_percentage * IXGBE_DCB_MAX_CREDIT) / 100;
160251964Sjfv
161251964Sjfv		/*
162251964Sjfv		 * Adjustment based on rule checking, if the percentage
163251964Sjfv		 * of a TC is too small, the maximum credit may not be
164251964Sjfv		 * enough to send out a jumbo frame in data plane arbitration.
165251964Sjfv		 */
166295524Ssbruno		if (credit_max < min_credit)
167251964Sjfv			credit_max = min_credit;
168251964Sjfv
169251964Sjfv		if (direction == IXGBE_DCB_TX_CONFIG) {
170251964Sjfv			/*
171251964Sjfv			 * Adjustment based on rule checking, if the
172251964Sjfv			 * percentage of a TC is too small, the maximum
173251964Sjfv			 * credit may not be enough to send out a TSO
174251964Sjfv			 * packet in descriptor plane arbitration.
175251964Sjfv			 */
176251964Sjfv			if (credit_max && (credit_max <
177251964Sjfv			    IXGBE_DCB_MIN_TSO_CREDIT)
178251964Sjfv			    && (hw->mac.type == ixgbe_mac_82598EB))
179251964Sjfv				credit_max = IXGBE_DCB_MIN_TSO_CREDIT;
180251964Sjfv
181251964Sjfv			dcb_config->tc_config[i].desc_credits_max =
182251964Sjfv								(u16)credit_max;
183251964Sjfv		}
184251964Sjfv
185251964Sjfv		p->data_credits_max = (u16)credit_max;
186251964Sjfv	}
187251964Sjfv
188251964Sjfvout:
189251964Sjfv	return ret_val;
190251964Sjfv}
191251964Sjfv
192251964Sjfv/**
193251964Sjfv * ixgbe_dcb_unpack_pfc_cee - Unpack dcb_config PFC info
194251964Sjfv * @cfg: dcb configuration to unpack into hardware consumable fields
195251964Sjfv * @map: user priority to traffic class map
196251964Sjfv * @pfc_up: u8 to store user priority PFC bitmask
197251964Sjfv *
198251964Sjfv * This unpacks the dcb configuration PFC info which is stored per
199251964Sjfv * traffic class into a 8bit user priority bitmask that can be
200251964Sjfv * consumed by hardware routines. The priority to tc map must be
201251964Sjfv * updated before calling this routine to use current up-to maps.
202251964Sjfv */
203251964Sjfvvoid ixgbe_dcb_unpack_pfc_cee(struct ixgbe_dcb_config *cfg, u8 *map, u8 *pfc_up)
204251964Sjfv{
205251964Sjfv	struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
206251964Sjfv	int up;
207251964Sjfv
208251964Sjfv	/*
209251964Sjfv	 * If the TC for this user priority has PFC enabled then set the
210251964Sjfv	 * matching bit in 'pfc_up' to reflect that PFC is enabled.
211251964Sjfv	 */
212251964Sjfv	for (*pfc_up = 0, up = 0; up < IXGBE_DCB_MAX_USER_PRIORITY; up++) {
213251964Sjfv		if (tc_config[map[up]].pfc != ixgbe_dcb_pfc_disabled)
214251964Sjfv			*pfc_up |= 1 << up;
215251964Sjfv	}
216251964Sjfv}
217251964Sjfv
218251964Sjfvvoid ixgbe_dcb_unpack_refill_cee(struct ixgbe_dcb_config *cfg, int direction,
219251964Sjfv			     u16 *refill)
220251964Sjfv{
221251964Sjfv	struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
222251964Sjfv	int tc;
223251964Sjfv
224251964Sjfv	for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++)
225251964Sjfv		refill[tc] = tc_config[tc].path[direction].data_credits_refill;
226251964Sjfv}
227251964Sjfv
228251964Sjfvvoid ixgbe_dcb_unpack_max_cee(struct ixgbe_dcb_config *cfg, u16 *max)
229251964Sjfv{
230251964Sjfv	struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
231251964Sjfv	int tc;
232251964Sjfv
233251964Sjfv	for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++)
234251964Sjfv		max[tc] = tc_config[tc].desc_credits_max;
235251964Sjfv}
236251964Sjfv
237251964Sjfvvoid ixgbe_dcb_unpack_bwgid_cee(struct ixgbe_dcb_config *cfg, int direction,
238251964Sjfv			    u8 *bwgid)
239251964Sjfv{
240251964Sjfv	struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
241251964Sjfv	int tc;
242251964Sjfv
243251964Sjfv	for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++)
244251964Sjfv		bwgid[tc] = tc_config[tc].path[direction].bwg_id;
245251964Sjfv}
246251964Sjfv
247251964Sjfvvoid ixgbe_dcb_unpack_tsa_cee(struct ixgbe_dcb_config *cfg, int direction,
248251964Sjfv			   u8 *tsa)
249251964Sjfv{
250251964Sjfv	struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
251251964Sjfv	int tc;
252251964Sjfv
253251964Sjfv	for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++)
254251964Sjfv		tsa[tc] = tc_config[tc].path[direction].tsa;
255251964Sjfv}
256251964Sjfv
257251964Sjfvu8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *cfg, int direction, u8 up)
258251964Sjfv{
259251964Sjfv	struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
260251964Sjfv	u8 prio_mask = 1 << up;
261251964Sjfv	u8 tc = cfg->num_tcs.pg_tcs;
262251964Sjfv
263251964Sjfv	/* If tc is 0 then DCB is likely not enabled or supported */
264251964Sjfv	if (!tc)
265251964Sjfv		goto out;
266251964Sjfv
267251964Sjfv	/*
268251964Sjfv	 * Test from maximum TC to 1 and report the first match we find.  If
269251964Sjfv	 * we find no match we can assume that the TC is 0 since the TC must
270251964Sjfv	 * be set for all user priorities
271251964Sjfv	 */
272251964Sjfv	for (tc--; tc; tc--) {
273251964Sjfv		if (prio_mask & tc_config[tc].path[direction].up_to_tc_bitmap)
274251964Sjfv			break;
275251964Sjfv	}
276251964Sjfvout:
277251964Sjfv	return tc;
278251964Sjfv}
279251964Sjfv
280251964Sjfvvoid ixgbe_dcb_unpack_map_cee(struct ixgbe_dcb_config *cfg, int direction,
281251964Sjfv			      u8 *map)
282251964Sjfv{
283251964Sjfv	u8 up;
284251964Sjfv
285251964Sjfv	for (up = 0; up < IXGBE_DCB_MAX_USER_PRIORITY; up++)
286251964Sjfv		map[up] = ixgbe_dcb_get_tc_from_up(cfg, direction, up);
287251964Sjfv}
288251964Sjfv
289251964Sjfv/**
290251964Sjfv * ixgbe_dcb_config - Struct containing DCB settings.
291251964Sjfv * @dcb_config: Pointer to DCB config structure
292251964Sjfv *
293251964Sjfv * This function checks DCB rules for DCB settings.
294251964Sjfv * The following rules are checked:
295251964Sjfv * 1. The sum of bandwidth percentages of all Bandwidth Groups must total 100%.
296251964Sjfv * 2. The sum of bandwidth percentages of all Traffic Classes within a Bandwidth
297251964Sjfv *    Group must total 100.
298251964Sjfv * 3. A Traffic Class should not be set to both Link Strict Priority
299251964Sjfv *    and Group Strict Priority.
300251964Sjfv * 4. Link strict Bandwidth Groups can only have link strict traffic classes
301251964Sjfv *    with zero bandwidth.
302251964Sjfv */
303251964Sjfvs32 ixgbe_dcb_check_config_cee(struct ixgbe_dcb_config *dcb_config)
304251964Sjfv{
305251964Sjfv	struct ixgbe_dcb_tc_path *p;
306251964Sjfv	s32 ret_val = IXGBE_SUCCESS;
307251964Sjfv	u8 i, j, bw = 0, bw_id;
308251964Sjfv	u8 bw_sum[2][IXGBE_DCB_MAX_BW_GROUP];
309251964Sjfv	bool link_strict[2][IXGBE_DCB_MAX_BW_GROUP];
310251964Sjfv
311251964Sjfv	memset(bw_sum, 0, sizeof(bw_sum));
312251964Sjfv	memset(link_strict, 0, sizeof(link_strict));
313251964Sjfv
314251964Sjfv	/* First Tx, then Rx */
315251964Sjfv	for (i = 0; i < 2; i++) {
316251964Sjfv		/* Check each traffic class for rule violation */
317251964Sjfv		for (j = 0; j < IXGBE_DCB_MAX_TRAFFIC_CLASS; j++) {
318251964Sjfv			p = &dcb_config->tc_config[j].path[i];
319251964Sjfv
320251964Sjfv			bw = p->bwg_percent;
321251964Sjfv			bw_id = p->bwg_id;
322251964Sjfv
323251964Sjfv			if (bw_id >= IXGBE_DCB_MAX_BW_GROUP) {
324251964Sjfv				ret_val = IXGBE_ERR_CONFIG;
325251964Sjfv				goto err_config;
326251964Sjfv			}
327251964Sjfv			if (p->tsa == ixgbe_dcb_tsa_strict) {
328251964Sjfv				link_strict[i][bw_id] = TRUE;
329251964Sjfv				/* Link strict should have zero bandwidth */
330251964Sjfv				if (bw) {
331251964Sjfv					ret_val = IXGBE_ERR_CONFIG;
332251964Sjfv					goto err_config;
333251964Sjfv				}
334251964Sjfv			} else if (!bw) {
335251964Sjfv				/*
336251964Sjfv				 * Traffic classes without link strict
337251964Sjfv				 * should have non-zero bandwidth.
338251964Sjfv				 */
339251964Sjfv				ret_val = IXGBE_ERR_CONFIG;
340251964Sjfv				goto err_config;
341251964Sjfv			}
342251964Sjfv			bw_sum[i][bw_id] += bw;
343251964Sjfv		}
344251964Sjfv
345251964Sjfv		bw = 0;
346251964Sjfv
347251964Sjfv		/* Check each bandwidth group for rule violation */
348251964Sjfv		for (j = 0; j < IXGBE_DCB_MAX_BW_GROUP; j++) {
349251964Sjfv			bw += dcb_config->bw_percentage[i][j];
350251964Sjfv			/*
351251964Sjfv			 * Sum of bandwidth percentages of all traffic classes
352251964Sjfv			 * within a Bandwidth Group must total 100 except for
353251964Sjfv			 * link strict group (zero bandwidth).
354251964Sjfv			 */
355251964Sjfv			if (link_strict[i][j]) {
356251964Sjfv				if (bw_sum[i][j]) {
357251964Sjfv					/*
358251964Sjfv					 * Link strict group should have zero
359251964Sjfv					 * bandwidth.
360251964Sjfv					 */
361251964Sjfv					ret_val = IXGBE_ERR_CONFIG;
362251964Sjfv					goto err_config;
363251964Sjfv				}
364251964Sjfv			} else if (bw_sum[i][j] != IXGBE_DCB_BW_PERCENT &&
365251964Sjfv				   bw_sum[i][j] != 0) {
366251964Sjfv				ret_val = IXGBE_ERR_CONFIG;
367251964Sjfv				goto err_config;
368251964Sjfv			}
369251964Sjfv		}
370251964Sjfv
371251964Sjfv		if (bw != IXGBE_DCB_BW_PERCENT) {
372251964Sjfv			ret_val = IXGBE_ERR_CONFIG;
373251964Sjfv			goto err_config;
374251964Sjfv		}
375251964Sjfv	}
376251964Sjfv
377251964Sjfverr_config:
378251964Sjfv	DEBUGOUT2("DCB error code %d while checking %s settings.\n",
379251964Sjfv		  ret_val, (i == IXGBE_DCB_TX_CONFIG) ? "Tx" : "Rx");
380251964Sjfv
381251964Sjfv	return ret_val;
382251964Sjfv}
383251964Sjfv
384251964Sjfv/**
385251964Sjfv * ixgbe_dcb_get_tc_stats - Returns status of each traffic class
386251964Sjfv * @hw: pointer to hardware structure
387251964Sjfv * @stats: pointer to statistics structure
388251964Sjfv * @tc_count:  Number of elements in bwg_array.
389251964Sjfv *
390251964Sjfv * This function returns the status data for each of the Traffic Classes in use.
391251964Sjfv */
392251964Sjfvs32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
393251964Sjfv			   u8 tc_count)
394251964Sjfv{
395251964Sjfv	s32 ret = IXGBE_NOT_IMPLEMENTED;
396251964Sjfv	switch (hw->mac.type) {
397251964Sjfv	case ixgbe_mac_82598EB:
398251964Sjfv		ret = ixgbe_dcb_get_tc_stats_82598(hw, stats, tc_count);
399251964Sjfv		break;
400251964Sjfv	case ixgbe_mac_82599EB:
401251964Sjfv	case ixgbe_mac_X540:
402283620Serj	case ixgbe_mac_X550:
403283620Serj	case ixgbe_mac_X550EM_x:
404315333Serj	case ixgbe_mac_X550EM_a:
405251964Sjfv#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
406251964Sjfv		ret = ixgbe_dcb_get_tc_stats_82599(hw, stats, tc_count);
407251964Sjfv		break;
408251964Sjfv#endif
409251964Sjfv	default:
410251964Sjfv		break;
411251964Sjfv	}
412251964Sjfv	return ret;
413251964Sjfv}
414251964Sjfv
415251964Sjfv/**
416251964Sjfv * ixgbe_dcb_get_pfc_stats - Returns CBFC status of each traffic class
417251964Sjfv * @hw: pointer to hardware structure
418251964Sjfv * @stats: pointer to statistics structure
419251964Sjfv * @tc_count:  Number of elements in bwg_array.
420251964Sjfv *
421251964Sjfv * This function returns the CBFC status data for each of the Traffic Classes.
422251964Sjfv */
423251964Sjfvs32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
424251964Sjfv			    u8 tc_count)
425251964Sjfv{
426251964Sjfv	s32 ret = IXGBE_NOT_IMPLEMENTED;
427251964Sjfv	switch (hw->mac.type) {
428251964Sjfv	case ixgbe_mac_82598EB:
429251964Sjfv		ret = ixgbe_dcb_get_pfc_stats_82598(hw, stats, tc_count);
430251964Sjfv		break;
431251964Sjfv	case ixgbe_mac_82599EB:
432251964Sjfv	case ixgbe_mac_X540:
433283620Serj	case ixgbe_mac_X550:
434283620Serj	case ixgbe_mac_X550EM_x:
435315333Serj	case ixgbe_mac_X550EM_a:
436251964Sjfv#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
437251964Sjfv		ret = ixgbe_dcb_get_pfc_stats_82599(hw, stats, tc_count);
438251964Sjfv		break;
439251964Sjfv#endif
440251964Sjfv	default:
441251964Sjfv		break;
442251964Sjfv	}
443251964Sjfv	return ret;
444251964Sjfv}
445251964Sjfv
446251964Sjfv/**
447251964Sjfv * ixgbe_dcb_config_rx_arbiter_cee - Config Rx arbiter
448251964Sjfv * @hw: pointer to hardware structure
449251964Sjfv * @dcb_config: pointer to ixgbe_dcb_config structure
450251964Sjfv *
451251964Sjfv * Configure Rx Data Arbiter and credits for each traffic class.
452251964Sjfv */
453251964Sjfvs32 ixgbe_dcb_config_rx_arbiter_cee(struct ixgbe_hw *hw,
454251964Sjfv				struct ixgbe_dcb_config *dcb_config)
455251964Sjfv{
456251964Sjfv	s32 ret = IXGBE_NOT_IMPLEMENTED;
457251964Sjfv	u8 tsa[IXGBE_DCB_MAX_TRAFFIC_CLASS]	= { 0 };
458251964Sjfv	u8 bwgid[IXGBE_DCB_MAX_TRAFFIC_CLASS]	= { 0 };
459251964Sjfv	u8 map[IXGBE_DCB_MAX_USER_PRIORITY]	= { 0 };
460251964Sjfv	u16 refill[IXGBE_DCB_MAX_TRAFFIC_CLASS]	= { 0 };
461251964Sjfv	u16 max[IXGBE_DCB_MAX_TRAFFIC_CLASS]	= { 0 };
462251964Sjfv
463251964Sjfv	ixgbe_dcb_unpack_refill_cee(dcb_config, IXGBE_DCB_TX_CONFIG, refill);
464251964Sjfv	ixgbe_dcb_unpack_max_cee(dcb_config, max);
465251964Sjfv	ixgbe_dcb_unpack_bwgid_cee(dcb_config, IXGBE_DCB_TX_CONFIG, bwgid);
466251964Sjfv	ixgbe_dcb_unpack_tsa_cee(dcb_config, IXGBE_DCB_TX_CONFIG, tsa);
467251964Sjfv	ixgbe_dcb_unpack_map_cee(dcb_config, IXGBE_DCB_TX_CONFIG, map);
468251964Sjfv
469251964Sjfv	switch (hw->mac.type) {
470251964Sjfv	case ixgbe_mac_82598EB:
471251964Sjfv		ret = ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, tsa);
472251964Sjfv		break;
473251964Sjfv	case ixgbe_mac_82599EB:
474251964Sjfv	case ixgbe_mac_X540:
475283620Serj	case ixgbe_mac_X550:
476283620Serj	case ixgbe_mac_X550EM_x:
477315333Serj	case ixgbe_mac_X550EM_a:
478251964Sjfv#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
479251964Sjfv		ret = ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwgid,
480251964Sjfv							tsa, map);
481251964Sjfv		break;
482251964Sjfv#endif
483251964Sjfv	default:
484251964Sjfv		break;
485251964Sjfv	}
486251964Sjfv	return ret;
487251964Sjfv}
488251964Sjfv
489251964Sjfv/**
490251964Sjfv * ixgbe_dcb_config_tx_desc_arbiter_cee - Config Tx Desc arbiter
491251964Sjfv * @hw: pointer to hardware structure
492251964Sjfv * @dcb_config: pointer to ixgbe_dcb_config structure
493251964Sjfv *
494251964Sjfv * Configure Tx Descriptor Arbiter and credits for each traffic class.
495251964Sjfv */
496251964Sjfvs32 ixgbe_dcb_config_tx_desc_arbiter_cee(struct ixgbe_hw *hw,
497251964Sjfv				     struct ixgbe_dcb_config *dcb_config)
498251964Sjfv{
499251964Sjfv	s32 ret = IXGBE_NOT_IMPLEMENTED;
500251964Sjfv	u8 tsa[IXGBE_DCB_MAX_TRAFFIC_CLASS];
501251964Sjfv	u8 bwgid[IXGBE_DCB_MAX_TRAFFIC_CLASS];
502251964Sjfv	u16 refill[IXGBE_DCB_MAX_TRAFFIC_CLASS];
503251964Sjfv	u16 max[IXGBE_DCB_MAX_TRAFFIC_CLASS];
504251964Sjfv
505251964Sjfv	ixgbe_dcb_unpack_refill_cee(dcb_config, IXGBE_DCB_TX_CONFIG, refill);
506251964Sjfv	ixgbe_dcb_unpack_max_cee(dcb_config, max);
507251964Sjfv	ixgbe_dcb_unpack_bwgid_cee(dcb_config, IXGBE_DCB_TX_CONFIG, bwgid);
508251964Sjfv	ixgbe_dcb_unpack_tsa_cee(dcb_config, IXGBE_DCB_TX_CONFIG, tsa);
509251964Sjfv
510251964Sjfv	switch (hw->mac.type) {
511251964Sjfv	case ixgbe_mac_82598EB:
512251964Sjfv		ret = ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
513251964Sjfv							     bwgid, tsa);
514251964Sjfv		break;
515251964Sjfv	case ixgbe_mac_82599EB:
516251964Sjfv	case ixgbe_mac_X540:
517283620Serj	case ixgbe_mac_X550:
518283620Serj	case ixgbe_mac_X550EM_x:
519315333Serj	case ixgbe_mac_X550EM_a:
520251964Sjfv#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
521251964Sjfv		ret = ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
522251964Sjfv							     bwgid, tsa);
523251964Sjfv		break;
524251964Sjfv#endif
525251964Sjfv	default:
526251964Sjfv		break;
527251964Sjfv	}
528251964Sjfv	return ret;
529251964Sjfv}
530251964Sjfv
531251964Sjfv/**
532251964Sjfv * ixgbe_dcb_config_tx_data_arbiter_cee - Config Tx data arbiter
533251964Sjfv * @hw: pointer to hardware structure
534251964Sjfv * @dcb_config: pointer to ixgbe_dcb_config structure
535251964Sjfv *
536251964Sjfv * Configure Tx Data Arbiter and credits for each traffic class.
537251964Sjfv */
538251964Sjfvs32 ixgbe_dcb_config_tx_data_arbiter_cee(struct ixgbe_hw *hw,
539251964Sjfv				     struct ixgbe_dcb_config *dcb_config)
540251964Sjfv{
541251964Sjfv	s32 ret = IXGBE_NOT_IMPLEMENTED;
542251964Sjfv	u8 tsa[IXGBE_DCB_MAX_TRAFFIC_CLASS];
543251964Sjfv	u8 bwgid[IXGBE_DCB_MAX_TRAFFIC_CLASS];
544251964Sjfv	u8 map[IXGBE_DCB_MAX_USER_PRIORITY] = { 0 };
545251964Sjfv	u16 refill[IXGBE_DCB_MAX_TRAFFIC_CLASS];
546251964Sjfv	u16 max[IXGBE_DCB_MAX_TRAFFIC_CLASS];
547251964Sjfv
548251964Sjfv	ixgbe_dcb_unpack_refill_cee(dcb_config, IXGBE_DCB_TX_CONFIG, refill);
549251964Sjfv	ixgbe_dcb_unpack_max_cee(dcb_config, max);
550251964Sjfv	ixgbe_dcb_unpack_bwgid_cee(dcb_config, IXGBE_DCB_TX_CONFIG, bwgid);
551251964Sjfv	ixgbe_dcb_unpack_tsa_cee(dcb_config, IXGBE_DCB_TX_CONFIG, tsa);
552251964Sjfv	ixgbe_dcb_unpack_map_cee(dcb_config, IXGBE_DCB_TX_CONFIG, map);
553251964Sjfv
554251964Sjfv	switch (hw->mac.type) {
555251964Sjfv	case ixgbe_mac_82598EB:
556251964Sjfv		ret = ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max,
557251964Sjfv							     bwgid, tsa);
558251964Sjfv		break;
559251964Sjfv	case ixgbe_mac_82599EB:
560251964Sjfv	case ixgbe_mac_X540:
561283620Serj	case ixgbe_mac_X550:
562283620Serj	case ixgbe_mac_X550EM_x:
563315333Serj	case ixgbe_mac_X550EM_a:
564251964Sjfv#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
565251964Sjfv		ret = ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max,
566251964Sjfv							     bwgid, tsa,
567251964Sjfv							     map);
568251964Sjfv		break;
569251964Sjfv#endif
570251964Sjfv	default:
571251964Sjfv		break;
572251964Sjfv	}
573251964Sjfv	return ret;
574251964Sjfv}
575251964Sjfv
576251964Sjfv/**
577251964Sjfv * ixgbe_dcb_config_pfc_cee - Config priority flow control
578251964Sjfv * @hw: pointer to hardware structure
579251964Sjfv * @dcb_config: pointer to ixgbe_dcb_config structure
580251964Sjfv *
581251964Sjfv * Configure Priority Flow Control for each traffic class.
582251964Sjfv */
583251964Sjfvs32 ixgbe_dcb_config_pfc_cee(struct ixgbe_hw *hw,
584251964Sjfv			 struct ixgbe_dcb_config *dcb_config)
585251964Sjfv{
586251964Sjfv	s32 ret = IXGBE_NOT_IMPLEMENTED;
587251964Sjfv	u8 pfc_en;
588251964Sjfv	u8 map[IXGBE_DCB_MAX_USER_PRIORITY] = { 0 };
589251964Sjfv
590251964Sjfv	ixgbe_dcb_unpack_map_cee(dcb_config, IXGBE_DCB_TX_CONFIG, map);
591251964Sjfv	ixgbe_dcb_unpack_pfc_cee(dcb_config, map, &pfc_en);
592251964Sjfv
593251964Sjfv	switch (hw->mac.type) {
594251964Sjfv	case ixgbe_mac_82598EB:
595251964Sjfv		ret = ixgbe_dcb_config_pfc_82598(hw, pfc_en);
596251964Sjfv		break;
597251964Sjfv	case ixgbe_mac_82599EB:
598251964Sjfv	case ixgbe_mac_X540:
599283620Serj	case ixgbe_mac_X550:
600283620Serj	case ixgbe_mac_X550EM_x:
601315333Serj	case ixgbe_mac_X550EM_a:
602251964Sjfv#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
603251964Sjfv		ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, map);
604251964Sjfv		break;
605251964Sjfv#endif
606251964Sjfv	default:
607251964Sjfv		break;
608251964Sjfv	}
609251964Sjfv	return ret;
610251964Sjfv}
611251964Sjfv
612251964Sjfv/**
613251964Sjfv * ixgbe_dcb_config_tc_stats - Config traffic class statistics
614251964Sjfv * @hw: pointer to hardware structure
615251964Sjfv *
616251964Sjfv * Configure queue statistics registers, all queues belonging to same traffic
617251964Sjfv * class uses a single set of queue statistics counters.
618251964Sjfv */
619251964Sjfvs32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *hw)
620251964Sjfv{
621251964Sjfv	s32 ret = IXGBE_NOT_IMPLEMENTED;
622251964Sjfv	switch (hw->mac.type) {
623251964Sjfv	case ixgbe_mac_82598EB:
624251964Sjfv		ret = ixgbe_dcb_config_tc_stats_82598(hw);
625251964Sjfv		break;
626251964Sjfv	case ixgbe_mac_82599EB:
627251964Sjfv	case ixgbe_mac_X540:
628283620Serj	case ixgbe_mac_X550:
629283620Serj	case ixgbe_mac_X550EM_x:
630315333Serj	case ixgbe_mac_X550EM_a:
631251964Sjfv#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
632251964Sjfv		ret = ixgbe_dcb_config_tc_stats_82599(hw, NULL);
633251964Sjfv		break;
634251964Sjfv#endif
635251964Sjfv	default:
636251964Sjfv		break;
637251964Sjfv	}
638251964Sjfv	return ret;
639251964Sjfv}
640251964Sjfv
641251964Sjfv/**
642251964Sjfv * ixgbe_dcb_hw_config_cee - Config and enable DCB
643251964Sjfv * @hw: pointer to hardware structure
644251964Sjfv * @dcb_config: pointer to ixgbe_dcb_config structure
645251964Sjfv *
646251964Sjfv * Configure dcb settings and enable dcb mode.
647251964Sjfv */
648251964Sjfvs32 ixgbe_dcb_hw_config_cee(struct ixgbe_hw *hw,
649251964Sjfv			struct ixgbe_dcb_config *dcb_config)
650251964Sjfv{
651251964Sjfv	s32 ret = IXGBE_NOT_IMPLEMENTED;
652251964Sjfv	u8 pfc_en;
653251964Sjfv	u8 tsa[IXGBE_DCB_MAX_TRAFFIC_CLASS];
654251964Sjfv	u8 bwgid[IXGBE_DCB_MAX_TRAFFIC_CLASS];
655251964Sjfv	u8 map[IXGBE_DCB_MAX_USER_PRIORITY] = { 0 };
656251964Sjfv	u16 refill[IXGBE_DCB_MAX_TRAFFIC_CLASS];
657251964Sjfv	u16 max[IXGBE_DCB_MAX_TRAFFIC_CLASS];
658251964Sjfv
659251964Sjfv	/* Unpack CEE standard containers */
660251964Sjfv	ixgbe_dcb_unpack_refill_cee(dcb_config, IXGBE_DCB_TX_CONFIG, refill);
661251964Sjfv	ixgbe_dcb_unpack_max_cee(dcb_config, max);
662251964Sjfv	ixgbe_dcb_unpack_bwgid_cee(dcb_config, IXGBE_DCB_TX_CONFIG, bwgid);
663251964Sjfv	ixgbe_dcb_unpack_tsa_cee(dcb_config, IXGBE_DCB_TX_CONFIG, tsa);
664251964Sjfv	ixgbe_dcb_unpack_map_cee(dcb_config, IXGBE_DCB_TX_CONFIG, map);
665251964Sjfv
666251964Sjfv	hw->mac.ops.setup_rxpba(hw, dcb_config->num_tcs.pg_tcs,
667251964Sjfv				0, dcb_config->rx_pba_cfg);
668251964Sjfv
669251964Sjfv	switch (hw->mac.type) {
670251964Sjfv	case ixgbe_mac_82598EB:
671251964Sjfv		ret = ixgbe_dcb_hw_config_82598(hw, dcb_config->link_speed,
672251964Sjfv						refill, max, bwgid, tsa);
673251964Sjfv		break;
674251964Sjfv	case ixgbe_mac_82599EB:
675251964Sjfv	case ixgbe_mac_X540:
676283620Serj	case ixgbe_mac_X550:
677283620Serj	case ixgbe_mac_X550EM_x:
678315333Serj	case ixgbe_mac_X550EM_a:
679251964Sjfv#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
680251964Sjfv		ixgbe_dcb_config_82599(hw, dcb_config);
681251964Sjfv		ret = ixgbe_dcb_hw_config_82599(hw, dcb_config->link_speed,
682251964Sjfv						refill, max, bwgid,
683251964Sjfv						tsa, map);
684251964Sjfv
685251964Sjfv		ixgbe_dcb_config_tc_stats_82599(hw, dcb_config);
686251964Sjfv		break;
687251964Sjfv#endif
688251964Sjfv	default:
689251964Sjfv		break;
690251964Sjfv	}
691251964Sjfv
692251964Sjfv	if (!ret && dcb_config->pfc_mode_enable) {
693251964Sjfv		ixgbe_dcb_unpack_pfc_cee(dcb_config, map, &pfc_en);
694251964Sjfv		ret = ixgbe_dcb_config_pfc(hw, pfc_en, map);
695251964Sjfv	}
696251964Sjfv
697251964Sjfv	return ret;
698251964Sjfv}
699251964Sjfv
700251964Sjfv/* Helper routines to abstract HW specifics from DCB netlink ops */
701251964Sjfvs32 ixgbe_dcb_config_pfc(struct ixgbe_hw *hw, u8 pfc_en, u8 *map)
702251964Sjfv{
703251964Sjfv	int ret = IXGBE_ERR_PARAM;
704251964Sjfv
705251964Sjfv	switch (hw->mac.type) {
706251964Sjfv	case ixgbe_mac_82598EB:
707251964Sjfv		ret = ixgbe_dcb_config_pfc_82598(hw, pfc_en);
708251964Sjfv		break;
709251964Sjfv	case ixgbe_mac_82599EB:
710251964Sjfv	case ixgbe_mac_X540:
711283620Serj	case ixgbe_mac_X550:
712283620Serj	case ixgbe_mac_X550EM_x:
713315333Serj	case ixgbe_mac_X550EM_a:
714251964Sjfv#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
715251964Sjfv		ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, map);
716251964Sjfv		break;
717251964Sjfv#endif
718251964Sjfv	default:
719251964Sjfv		break;
720251964Sjfv	}
721251964Sjfv	return ret;
722251964Sjfv}
723251964Sjfv
724251964Sjfvs32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw, u16 *refill, u16 *max,
725251964Sjfv			    u8 *bwg_id, u8 *tsa, u8 *map)
726251964Sjfv{
727251964Sjfv	switch (hw->mac.type) {
728251964Sjfv	case ixgbe_mac_82598EB:
729251964Sjfv		ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, tsa);
730251964Sjfv		ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max, bwg_id,
731251964Sjfv						       tsa);
732251964Sjfv		ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max, bwg_id,
733251964Sjfv						       tsa);
734251964Sjfv		break;
735251964Sjfv	case ixgbe_mac_82599EB:
736251964Sjfv	case ixgbe_mac_X540:
737283620Serj	case ixgbe_mac_X550:
738283620Serj	case ixgbe_mac_X550EM_x:
739315333Serj	case ixgbe_mac_X550EM_a:
740251964Sjfv#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
741251964Sjfv		ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id,
742251964Sjfv						  tsa, map);
743251964Sjfv		ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max, bwg_id,
744251964Sjfv						       tsa);
745251964Sjfv		ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max, bwg_id,
746251964Sjfv						       tsa, map);
747251964Sjfv		break;
748251964Sjfv#endif
749251964Sjfv	default:
750251964Sjfv		break;
751251964Sjfv	}
752251964Sjfv	return 0;
753251964Sjfv}
754