| /* | 
 |  * Copyright (c) 2011 Mellanox Technologies. All rights reserved. | 
 |  * | 
 |  * This software is available to you under a choice of one of two | 
 |  * licenses.  You may choose to be licensed under the terms of the GNU | 
 |  * General Public License (GPL) Version 2, available from the file | 
 |  * COPYING in the main directory of this source tree, or the | 
 |  * OpenIB.org BSD license below: | 
 |  * | 
 |  *     Redistribution and use in source and binary forms, with or | 
 |  *     without modification, are permitted provided that the following | 
 |  *     conditions are met: | 
 |  * | 
 |  *      - Redistributions of source code must retain the above | 
 |  *        copyright notice, this list of conditions and the following | 
 |  *        disclaimer. | 
 |  * | 
 |  *      - Redistributions in binary form must reproduce the above | 
 |  *        copyright notice, this list of conditions and the following | 
 |  *        disclaimer in the documentation and/or other materials | 
 |  *        provided with the distribution. | 
 |  * | 
 |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
 |  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
 |  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
 |  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | 
 |  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | 
 |  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 
 |  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
 |  * SOFTWARE. | 
 |  * | 
 |  */ | 
 |  | 
 | #include <linux/dcbnl.h> | 
 | #include <linux/math64.h> | 
 |  | 
 | #include "mlx4_en.h" | 
 | #include "fw_qos.h" | 
 |  | 
 | /* Definitions for QCN | 
 |  */ | 
 |  | 
 | struct mlx4_congestion_control_mb_prio_802_1_qau_params { | 
 | 	__be32 modify_enable_high; | 
 | 	__be32 modify_enable_low; | 
 | 	__be32 reserved1; | 
 | 	__be32 extended_enable; | 
 | 	__be32 rppp_max_rps; | 
 | 	__be32 rpg_time_reset; | 
 | 	__be32 rpg_byte_reset; | 
 | 	__be32 rpg_threshold; | 
 | 	__be32 rpg_max_rate; | 
 | 	__be32 rpg_ai_rate; | 
 | 	__be32 rpg_hai_rate; | 
 | 	__be32 rpg_gd; | 
 | 	__be32 rpg_min_dec_fac; | 
 | 	__be32 rpg_min_rate; | 
 | 	__be32 max_time_rise; | 
 | 	__be32 max_byte_rise; | 
 | 	__be32 max_qdelta; | 
 | 	__be32 min_qoffset; | 
 | 	__be32 gd_coefficient; | 
 | 	__be32 reserved2[5]; | 
 | 	__be32 cp_sample_base; | 
 | 	__be32 reserved3[39]; | 
 | }; | 
 |  | 
 | struct mlx4_congestion_control_mb_prio_802_1_qau_statistics { | 
 | 	__be64 rppp_rp_centiseconds; | 
 | 	__be32 reserved1; | 
 | 	__be32 ignored_cnm; | 
 | 	__be32 rppp_created_rps; | 
 | 	__be32 estimated_total_rate; | 
 | 	__be32 max_active_rate_limiter_index; | 
 | 	__be32 dropped_cnms_busy_fw; | 
 | 	__be32 reserved2; | 
 | 	__be32 cnms_handled_successfully; | 
 | 	__be32 min_total_limiters_rate; | 
 | 	__be32 max_total_limiters_rate; | 
 | 	__be32 reserved3[4]; | 
 | }; | 
 |  | 
 | static int mlx4_en_dcbnl_ieee_getets(struct ether *dev, | 
 | 				     struct ieee_ets *ets) | 
 | { | 
 | 	struct mlx4_en_priv *priv = netdev_priv(dev); | 
 | 	struct ieee_ets *my_ets = &priv->ets; | 
 |  | 
 | 	/* No IEEE PFC settings available */ | 
 | 	if (!my_ets) | 
 | 		return -EINVAL; | 
 |  | 
 | 	ets->ets_cap = IEEE_8021QAZ_MAX_TCS; | 
 | 	ets->cbs = my_ets->cbs; | 
 | 	memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw)); | 
 | 	memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); | 
 | 	memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int mlx4_en_ets_validate(struct mlx4_en_priv *priv, struct ieee_ets *ets) | 
 | { | 
 | 	int i; | 
 | 	int total_ets_bw = 0; | 
 | 	int has_ets_tc = 0; | 
 |  | 
 | 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { | 
 | 		if (ets->prio_tc[i] >= MLX4_EN_NUM_UP) { | 
 | 			en_err(priv, "Bad priority in UP <=> TC mapping. TC: %d, UP: %d\n", | 
 | 					i, ets->prio_tc[i]); | 
 | 			return -EINVAL; | 
 | 		} | 
 |  | 
 | 		switch (ets->tc_tsa[i]) { | 
 | 		case IEEE_8021QAZ_TSA_STRICT: | 
 | 			break; | 
 | 		case IEEE_8021QAZ_TSA_ETS: | 
 | 			has_ets_tc = 1; | 
 | 			total_ets_bw += ets->tc_tx_bw[i]; | 
 | 			break; | 
 | 		default: | 
 | 			en_err(priv, "TC[%d]: Not supported TSA: %d\n", | 
 | 					i, ets->tc_tsa[i]); | 
 | 			return -ENOTSUPP; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	if (has_ets_tc && total_ets_bw != MLX4_EN_BW_MAX) { | 
 | 		en_err(priv, "Bad ETS BW sum: %d. Should be exactly 100%%\n", | 
 | 				total_ets_bw); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int mlx4_en_config_port_scheduler(struct mlx4_en_priv *priv, | 
 | 		struct ieee_ets *ets, uint16_t *ratelimit) | 
 | { | 
 | 	struct mlx4_en_dev *mdev = priv->mdev; | 
 | 	int num_strict = 0; | 
 | 	int i; | 
 | 	__u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS] = { 0 }; | 
 | 	__u8 pg[IEEE_8021QAZ_MAX_TCS] = { 0 }; | 
 |  | 
 | 	ets = ets ?: &priv->ets; | 
 | 	ratelimit = ratelimit ?: priv->maxrate; | 
 |  | 
 | 	/* higher TC means higher priority => lower pg */ | 
 | 	for (i = IEEE_8021QAZ_MAX_TCS - 1; i >= 0; i--) { | 
 | 		switch (ets->tc_tsa[i]) { | 
 | 		case IEEE_8021QAZ_TSA_STRICT: | 
 | 			pg[i] = num_strict++; | 
 | 			tc_tx_bw[i] = MLX4_EN_BW_MAX; | 
 | 			break; | 
 | 		case IEEE_8021QAZ_TSA_ETS: | 
 | 			pg[i] = MLX4_EN_TC_ETS; | 
 | 			tc_tx_bw[i] = ets->tc_tx_bw[i] ?: MLX4_EN_BW_MIN; | 
 | 			break; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return mlx4_SET_PORT_SCHEDULER(mdev->dev, priv->port, tc_tx_bw, pg, | 
 | 			ratelimit); | 
 | } | 
 |  | 
 | static int | 
 | mlx4_en_dcbnl_ieee_setets(struct ether *dev, struct ieee_ets *ets) | 
 | { | 
 | 	struct mlx4_en_priv *priv = netdev_priv(dev); | 
 | 	struct mlx4_en_dev *mdev = priv->mdev; | 
 | 	int err; | 
 |  | 
 | 	err = mlx4_en_ets_validate(priv, ets); | 
 | 	if (err) | 
 | 		return err; | 
 |  | 
 | 	err = mlx4_SET_PORT_PRIO2TC(mdev->dev, priv->port, ets->prio_tc); | 
 | 	if (err) | 
 | 		return err; | 
 |  | 
 | 	err = mlx4_en_config_port_scheduler(priv, ets, NULL); | 
 | 	if (err) | 
 | 		return err; | 
 |  | 
 | 	memcpy(&priv->ets, ets, sizeof(priv->ets)); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int mlx4_en_dcbnl_ieee_getpfc(struct ether *dev, | 
 | 				     struct ieee_pfc *pfc) | 
 | { | 
 | 	struct mlx4_en_priv *priv = netdev_priv(dev); | 
 |  | 
 | 	pfc->pfc_cap = IEEE_8021QAZ_MAX_TCS; | 
 | 	pfc->pfc_en = priv->prof->tx_ppp; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int mlx4_en_dcbnl_ieee_setpfc(struct ether *dev, | 
 | 				     struct ieee_pfc *pfc) | 
 | { | 
 | 	struct mlx4_en_priv *priv = netdev_priv(dev); | 
 | 	struct mlx4_en_port_profile *prof = priv->prof; | 
 | 	struct mlx4_en_dev *mdev = priv->mdev; | 
 | 	int err; | 
 |  | 
 | 	en_dbg(DRV, priv, "cap: 0x%x en: 0x%x mbc: 0x%x delay: %d\n", | 
 | 			pfc->pfc_cap, | 
 | 			pfc->pfc_en, | 
 | 			pfc->mbc, | 
 | 			pfc->delay); | 
 |  | 
 | 	prof->rx_pause = !pfc->pfc_en; | 
 | 	prof->tx_pause = !pfc->pfc_en; | 
 | 	prof->rx_ppp = pfc->pfc_en; | 
 | 	prof->tx_ppp = pfc->pfc_en; | 
 |  | 
 | 	err = mlx4_SET_PORT_general(mdev->dev, priv->port, | 
 | 				    priv->rx_skb_size + ETH_FCS_LEN, | 
 | 				    prof->tx_pause, | 
 | 				    prof->tx_ppp, | 
 | 				    prof->rx_pause, | 
 | 				    prof->rx_ppp); | 
 | 	if (err) | 
 | 		en_err(priv, "Failed setting pause params\n"); | 
 | 	else | 
 | 		mlx4_en_update_pfc_stats_bitmap(mdev->dev, &priv->stats_bitmap, | 
 | 						prof->rx_ppp, prof->rx_pause, | 
 | 						prof->tx_ppp, prof->tx_pause); | 
 |  | 
 | 	return err; | 
 | } | 
 |  | 
 | static uint8_t mlx4_en_dcbnl_getdcbx(struct ether *dev) | 
 | { | 
 | 	return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE; | 
 | } | 
 |  | 
 | static uint8_t mlx4_en_dcbnl_setdcbx(struct ether *dev, uint8_t mode) | 
 | { | 
 | 	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || | 
 | 	    (mode & DCB_CAP_DCBX_VER_CEE) || | 
 | 	    !(mode & DCB_CAP_DCBX_VER_IEEE) || | 
 | 	    !(mode & DCB_CAP_DCBX_HOST)) | 
 | 		return 1; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | #define MLX4_RATELIMIT_UNITS_IN_KB 100000 /* rate-limit HW unit in Kbps */ | 
 | static int mlx4_en_dcbnl_ieee_getmaxrate(struct ether *dev, | 
 | 					 struct ieee_maxrate *maxrate) | 
 | { | 
 | 	struct mlx4_en_priv *priv = netdev_priv(dev); | 
 | 	int i; | 
 |  | 
 | 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) | 
 | 		maxrate->tc_maxrate[i] = | 
 | 			priv->maxrate[i] * MLX4_RATELIMIT_UNITS_IN_KB; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int mlx4_en_dcbnl_ieee_setmaxrate(struct ether *dev, | 
 | 					 struct ieee_maxrate *maxrate) | 
 | { | 
 | 	struct mlx4_en_priv *priv = netdev_priv(dev); | 
 | 	uint16_t tmp[IEEE_8021QAZ_MAX_TCS]; | 
 | 	int i, err; | 
 |  | 
 | 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { | 
 | 		/* Convert from Kbps into HW units, rounding result up. | 
 | 		 * Setting to 0, means unlimited BW. | 
 | 		 */ | 
 | 		tmp[i] = div_u64(maxrate->tc_maxrate[i] + | 
 | 				 MLX4_RATELIMIT_UNITS_IN_KB - 1, | 
 | 				 MLX4_RATELIMIT_UNITS_IN_KB); | 
 | 	} | 
 |  | 
 | 	err = mlx4_en_config_port_scheduler(priv, NULL, tmp); | 
 | 	if (err) | 
 | 		return err; | 
 |  | 
 | 	memcpy(priv->maxrate, tmp, sizeof(priv->maxrate)); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | #define RPG_ENABLE_BIT	31 | 
 | #define CN_TAG_BIT	30 | 
 |  | 
 | static int mlx4_en_dcbnl_ieee_getqcn(struct ether *dev, | 
 | 				     struct ieee_qcn *qcn) | 
 | { | 
 | 	struct mlx4_en_priv *priv = netdev_priv(dev); | 
 | 	struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn; | 
 | 	struct mlx4_cmd_mailbox *mailbox_out = NULL; | 
 | 	uint64_t mailbox_in_dma = 0; | 
 | 	uint32_t inmod = 0; | 
 | 	int i, err; | 
 |  | 
 | 	if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN)) | 
 | 		return -EOPNOTSUPP; | 
 |  | 
 | 	mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev); | 
 | 	if (IS_ERR(mailbox_out)) | 
 | 		return -ENOMEM; | 
 | 	hw_qcn = | 
 | 	(struct mlx4_congestion_control_mb_prio_802_1_qau_params *) | 
 | 	mailbox_out->buf; | 
 |  | 
 | 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { | 
 | 		inmod = priv->port | ((1 << i) << 8) | | 
 | 			 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16); | 
 | 		err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma, | 
 | 				   mailbox_out->dma, | 
 | 				   inmod, MLX4_CONGESTION_CONTROL_GET_PARAMS, | 
 | 				   MLX4_CMD_CONGESTION_CTRL_OPCODE, | 
 | 				   MLX4_CMD_TIME_CLASS_C, | 
 | 				   MLX4_CMD_NATIVE); | 
 | 		if (err) { | 
 | 			mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out); | 
 | 			return err; | 
 | 		} | 
 |  | 
 | 		qcn->rpg_enable[i] = | 
 | 			be32_to_cpu(hw_qcn->extended_enable) >> RPG_ENABLE_BIT; | 
 | 		qcn->rppp_max_rps[i] = | 
 | 			be32_to_cpu(hw_qcn->rppp_max_rps); | 
 | 		qcn->rpg_time_reset[i] = | 
 | 			be32_to_cpu(hw_qcn->rpg_time_reset); | 
 | 		qcn->rpg_byte_reset[i] = | 
 | 			be32_to_cpu(hw_qcn->rpg_byte_reset); | 
 | 		qcn->rpg_threshold[i] = | 
 | 			be32_to_cpu(hw_qcn->rpg_threshold); | 
 | 		qcn->rpg_max_rate[i] = | 
 | 			be32_to_cpu(hw_qcn->rpg_max_rate); | 
 | 		qcn->rpg_ai_rate[i] = | 
 | 			be32_to_cpu(hw_qcn->rpg_ai_rate); | 
 | 		qcn->rpg_hai_rate[i] = | 
 | 			be32_to_cpu(hw_qcn->rpg_hai_rate); | 
 | 		qcn->rpg_gd[i] = | 
 | 			be32_to_cpu(hw_qcn->rpg_gd); | 
 | 		qcn->rpg_min_dec_fac[i] = | 
 | 			be32_to_cpu(hw_qcn->rpg_min_dec_fac); | 
 | 		qcn->rpg_min_rate[i] = | 
 | 			be32_to_cpu(hw_qcn->rpg_min_rate); | 
 | 		qcn->cndd_state_machine[i] = | 
 | 			priv->cndd_state[i]; | 
 | 	} | 
 | 	mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out); | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int mlx4_en_dcbnl_ieee_setqcn(struct ether *dev, | 
 | 				     struct ieee_qcn *qcn) | 
 | { | 
 | 	struct mlx4_en_priv *priv = netdev_priv(dev); | 
 | 	struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn; | 
 | 	struct mlx4_cmd_mailbox *mailbox_in = NULL; | 
 | 	uint64_t mailbox_in_dma = 0; | 
 | 	uint32_t inmod = 0; | 
 | 	int i, err; | 
 | #define MODIFY_ENABLE_HIGH_MASK 0xc0000000 | 
 | #define MODIFY_ENABLE_LOW_MASK 0xffc00000 | 
 |  | 
 | 	if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN)) | 
 | 		return -EOPNOTSUPP; | 
 |  | 
 | 	mailbox_in = mlx4_alloc_cmd_mailbox(priv->mdev->dev); | 
 | 	if (IS_ERR(mailbox_in)) | 
 | 		return -ENOMEM; | 
 |  | 
 | 	mailbox_in_dma = mailbox_in->dma; | 
 | 	hw_qcn = | 
 | 	(struct mlx4_congestion_control_mb_prio_802_1_qau_params *)mailbox_in->buf; | 
 | 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { | 
 | 		inmod = priv->port | ((1 << i) << 8) | | 
 | 			 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16); | 
 |  | 
 | 		/* Before updating QCN parameter, | 
 | 		 * need to set it's modify enable bit to 1 | 
 | 		 */ | 
 |  | 
 | 		hw_qcn->modify_enable_high = cpu_to_be32( | 
 | 						MODIFY_ENABLE_HIGH_MASK); | 
 | 		hw_qcn->modify_enable_low = cpu_to_be32(MODIFY_ENABLE_LOW_MASK); | 
 |  | 
 | 		hw_qcn->extended_enable = cpu_to_be32(qcn->rpg_enable[i] << RPG_ENABLE_BIT); | 
 | 		hw_qcn->rppp_max_rps = cpu_to_be32(qcn->rppp_max_rps[i]); | 
 | 		hw_qcn->rpg_time_reset = cpu_to_be32(qcn->rpg_time_reset[i]); | 
 | 		hw_qcn->rpg_byte_reset = cpu_to_be32(qcn->rpg_byte_reset[i]); | 
 | 		hw_qcn->rpg_threshold = cpu_to_be32(qcn->rpg_threshold[i]); | 
 | 		hw_qcn->rpg_max_rate = cpu_to_be32(qcn->rpg_max_rate[i]); | 
 | 		hw_qcn->rpg_ai_rate = cpu_to_be32(qcn->rpg_ai_rate[i]); | 
 | 		hw_qcn->rpg_hai_rate = cpu_to_be32(qcn->rpg_hai_rate[i]); | 
 | 		hw_qcn->rpg_gd = cpu_to_be32(qcn->rpg_gd[i]); | 
 | 		hw_qcn->rpg_min_dec_fac = cpu_to_be32(qcn->rpg_min_dec_fac[i]); | 
 | 		hw_qcn->rpg_min_rate = cpu_to_be32(qcn->rpg_min_rate[i]); | 
 | 		priv->cndd_state[i] = qcn->cndd_state_machine[i]; | 
 | 		if (qcn->cndd_state_machine[i] == DCB_CNDD_INTERIOR_READY) | 
 | 			hw_qcn->extended_enable |= cpu_to_be32(1 << CN_TAG_BIT); | 
 |  | 
 | 		err = mlx4_cmd(priv->mdev->dev, mailbox_in_dma, inmod, | 
 | 			       MLX4_CONGESTION_CONTROL_SET_PARAMS, | 
 | 			       MLX4_CMD_CONGESTION_CTRL_OPCODE, | 
 | 			       MLX4_CMD_TIME_CLASS_C, | 
 | 			       MLX4_CMD_NATIVE); | 
 | 		if (err) { | 
 | 			mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in); | 
 | 			return err; | 
 | 		} | 
 | 	} | 
 | 	mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in); | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int mlx4_en_dcbnl_ieee_getqcnstats(struct ether *dev, | 
 | 					  struct ieee_qcn_stats *qcn_stats) | 
 | { | 
 | 	struct mlx4_en_priv *priv = netdev_priv(dev); | 
 | 	struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *hw_qcn_stats; | 
 | 	struct mlx4_cmd_mailbox *mailbox_out = NULL; | 
 | 	uint64_t mailbox_in_dma = 0; | 
 | 	uint32_t inmod = 0; | 
 | 	int i, err; | 
 |  | 
 | 	if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN)) | 
 | 		return -EOPNOTSUPP; | 
 |  | 
 | 	mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev); | 
 | 	if (IS_ERR(mailbox_out)) | 
 | 		return -ENOMEM; | 
 |  | 
 | 	hw_qcn_stats = | 
 | 	(struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *) | 
 | 	mailbox_out->buf; | 
 |  | 
 | 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { | 
 | 		inmod = priv->port | ((1 << i) << 8) | | 
 | 			 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16); | 
 | 		err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma, | 
 | 				   mailbox_out->dma, inmod, | 
 | 				   MLX4_CONGESTION_CONTROL_GET_STATISTICS, | 
 | 				   MLX4_CMD_CONGESTION_CTRL_OPCODE, | 
 | 				   MLX4_CMD_TIME_CLASS_C, | 
 | 				   MLX4_CMD_NATIVE); | 
 | 		if (err) { | 
 | 			mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out); | 
 | 			return err; | 
 | 		} | 
 | 		qcn_stats->rppp_rp_centiseconds[i] = | 
 | 			be64_to_cpu(hw_qcn_stats->rppp_rp_centiseconds); | 
 | 		qcn_stats->rppp_created_rps[i] = | 
 | 			be32_to_cpu(hw_qcn_stats->rppp_created_rps); | 
 | 	} | 
 | 	mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out); | 
 | 	return 0; | 
 | } | 
 |  | 
 | const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops = { | 
 | 	.ieee_getets	= mlx4_en_dcbnl_ieee_getets, | 
 | 	.ieee_setets	= mlx4_en_dcbnl_ieee_setets, | 
 | 	.ieee_getmaxrate = mlx4_en_dcbnl_ieee_getmaxrate, | 
 | 	.ieee_setmaxrate = mlx4_en_dcbnl_ieee_setmaxrate, | 
 | 	.ieee_getpfc	= mlx4_en_dcbnl_ieee_getpfc, | 
 | 	.ieee_setpfc	= mlx4_en_dcbnl_ieee_setpfc, | 
 |  | 
 | 	.getdcbx	= mlx4_en_dcbnl_getdcbx, | 
 | 	.setdcbx	= mlx4_en_dcbnl_setdcbx, | 
 | 	.ieee_getqcn	= mlx4_en_dcbnl_ieee_getqcn, | 
 | 	.ieee_setqcn	= mlx4_en_dcbnl_ieee_setqcn, | 
 | 	.ieee_getqcnstats = mlx4_en_dcbnl_ieee_getqcnstats, | 
 | }; | 
 |  | 
 | const struct dcbnl_rtnl_ops mlx4_en_dcbnl_pfc_ops = { | 
 | 	.ieee_getpfc	= mlx4_en_dcbnl_ieee_getpfc, | 
 | 	.ieee_setpfc	= mlx4_en_dcbnl_ieee_setpfc, | 
 |  | 
 | 	.getdcbx	= mlx4_en_dcbnl_getdcbx, | 
 | 	.setdcbx	= mlx4_en_dcbnl_setdcbx, | 
 | }; |