Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mlx5e-updates-2018-05-19' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5e-updates-2018-05-19

This series contains updates for mlx5e netdevice driver with one subject,
DSCP to priority mapping, in the first patch Huy adds the needed API in
dcbnl, the second patch adds the needed mlx5 core capability bits for the
feature, and all other patches are mlx5e (netdev) only changes to add
support for the feature.

From: Huy Nguyen

Dscp to priority mapping for Ethernet packet:

These patches enable differentiated services code point (dscp) to
priority mapping for Ethernet packet. Once this feature is
enabled, the packet is routed to the corresponding priority based on its
dscp. User can combine this feature with priority flow control (pfc)
feature to have priority flow control based on the dscp.

Firmware interface:
Mellanox firmware provides two control knobs for this feature:
QPTS register allow changing the trust state between dscp and
pcp mode. The default is pcp mode. Once in dscp mode, firmware will
route the packet based on its dscp value if the dscp field exists.

QPDPM register allow mapping a specific dscp (0 to 63) to a
specific priority (0 to 7). By default, all the dscps are mapped to
priority zero.

Software interface:
This feature is controlled via application priority TLV. IEEE
specification P802.1Qcd/D2.1 defines priority selector id 5 for
application priority TLV. This APP TLV selector defines DSCP to priority
map. This APP TLV can be sent by the switch or can be set locally using
software such as lldptool. In mlx5 drivers, we add the support for net
dcb's getapp and setapp call back. Mlx5 driver only handles the selector
id 5 application entry (dscp application priority application entry).
If user sends multiple dscp to priority APP TLV entries on the same
dscp, the last sent one will take effect. All the previous sent will be
deleted.

This attribute combined with pfc attribute allows advanced user to
fine tune the qos setting for specific priority queue. For example,
user can give dedicated buffer for one or more priorities or user
can give large buffer to certain priorities.

The dcb buffer configuration will be controlled by lldptool.
>> lldptool -T -i eth2 -V BUFFER prio 0,2,5,7,1,2,3,6
maps priorities 0,1,2,3,4,5,6,7 to receive buffer 0,2,5,7,1,2,3,6
>> lldptool -T -i eth2 -V BUFFER size 87296,87296,0,87296,0,0,0,0
sets receive buffer size for buffer 0,1,2,3,4,5,6,7 respectively

After discussion on mailing list with Jakub, Jiri, Ido and John, we agreed to
choose dcbnl over devlink interface since this feature is intended to set
port attributes which are governed by the netdev instance of that port, where
devlink API is more suitable for global ASIC configurations.

The firmware trust state (in QPTS register) is changed based on the
number of dscp to priority application entries. When the first dscp to
priority application entry is added by the user, the trust state is
changed to dscp. When the last dscp to priority application entry is
deleted by the user, the trust state is changed to pcp.

When the port is in DSCP trust state, the transmit queue is selected
based on the dscp of the skb.

When the port is in DSCP trust state and vport inline mode is not NONE,
firmware requires mlx5 driver to copy the IP header to the
wqe ethernet segment inline header if the skb has it.
This is done by changing the transmit queue sq's min inline mode to L3.
Note that the min inline mode of sqs that belong to other features
such as xdpsq, icosq are not modified.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+947 -80
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/Makefile
··· 15 15 16 16 mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \ 17 17 en_tx.o en_rx.o en_dim.o en_txrx.o en_stats.o vxlan.o \ 18 - en_arfs.o en_fs_ethtool.o en_selftest.o 18 + en_arfs.o en_fs_ethtool.o en_selftest.o en/port.o 19 19 20 20 mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o 21 21 22 22 mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o en_rep.o en_tc.o 23 23 24 - mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o 24 + mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o 25 25 26 26 mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o ipoib/ipoib_vlan.o 27 27
+6 -2
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 65 65 #define MLX5E_HW2SW_MTU(params, hwmtu) ((hwmtu) - ((params)->hard_mtu)) 66 66 #define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu)) 67 67 68 + #define MLX5E_MAX_PRIORITY 8 68 69 #define MLX5E_MAX_DSCP 64 69 70 #define MLX5E_MAX_NUM_TC 8 70 71 ··· 276 275 /* The only setting that cannot be read from FW */ 277 276 u8 tc_tsa[IEEE_8021QAZ_MAX_TCS]; 278 277 u8 cap; 278 + 279 + /* Buffer configuration */ 280 + bool manual_buffer; 281 + u32 cable_len; 282 + u32 xoff; 279 283 }; 280 284 281 285 struct mlx5e_dcbx_dp { ··· 938 932 939 933 void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len, 940 934 int num_channels); 941 - int mlx5e_get_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); 942 - 943 935 void mlx5e_set_tx_cq_mode_params(struct mlx5e_params *params, 944 936 u8 cq_period_mode); 945 937 void mlx5e_set_rx_cq_mode_params(struct mlx5e_params *params,
+1
drivers/net/ethernet/mellanox/mlx5/core/en/Makefile
··· 1 + subdir-ccflags-y += -I$(src)/..
+237
drivers/net/ethernet/mellanox/mlx5/core/en/port.c
··· 1 + /* 2 + * Copyright (c) 2018, Mellanox Technologies. All rights reserved. 3 + * 4 + * This software is available to you under a choice of one of two 5 + * licenses. You may choose to be licensed under the terms of the GNU 6 + * General Public License (GPL) Version 2, available from the file 7 + * COPYING in the main directory of this source tree, or the 8 + * OpenIB.org BSD license below: 9 + * 10 + * Redistribution and use in source and binary forms, with or 11 + * without modification, are permitted provided that the following 12 + * conditions are met: 13 + * 14 + * - Redistributions of source code must retain the above 15 + * copyright notice, this list of conditions and the following 16 + * disclaimer. 17 + * 18 + * - Redistributions in binary form must reproduce the above 19 + * copyright notice, this list of conditions and the following 20 + * disclaimer in the documentation and/or other materials 21 + * provided with the distribution. 22 + * 23 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 + * SOFTWARE. 31 + */ 32 + 33 + #include "port.h" 34 + 35 + /* speed in units of 1Mb */ 36 + static const u32 mlx5e_link_speed[MLX5E_LINK_MODES_NUMBER] = { 37 + [MLX5E_1000BASE_CX_SGMII] = 1000, 38 + [MLX5E_1000BASE_KX] = 1000, 39 + [MLX5E_10GBASE_CX4] = 10000, 40 + [MLX5E_10GBASE_KX4] = 10000, 41 + [MLX5E_10GBASE_KR] = 10000, 42 + [MLX5E_20GBASE_KR2] = 20000, 43 + [MLX5E_40GBASE_CR4] = 40000, 44 + [MLX5E_40GBASE_KR4] = 40000, 45 + [MLX5E_56GBASE_R4] = 56000, 46 + [MLX5E_10GBASE_CR] = 10000, 47 + [MLX5E_10GBASE_SR] = 10000, 48 + [MLX5E_10GBASE_ER] = 10000, 49 + [MLX5E_40GBASE_SR4] = 40000, 50 + [MLX5E_40GBASE_LR4] = 40000, 51 + [MLX5E_50GBASE_SR2] = 50000, 52 + [MLX5E_100GBASE_CR4] = 100000, 53 + [MLX5E_100GBASE_SR4] = 100000, 54 + [MLX5E_100GBASE_KR4] = 100000, 55 + [MLX5E_100GBASE_LR4] = 100000, 56 + [MLX5E_100BASE_TX] = 100, 57 + [MLX5E_1000BASE_T] = 1000, 58 + [MLX5E_10GBASE_T] = 10000, 59 + [MLX5E_25GBASE_CR] = 25000, 60 + [MLX5E_25GBASE_KR] = 25000, 61 + [MLX5E_25GBASE_SR] = 25000, 62 + [MLX5E_50GBASE_CR2] = 50000, 63 + [MLX5E_50GBASE_KR2] = 50000, 64 + }; 65 + 66 + u32 mlx5e_port_ptys2speed(u32 eth_proto_oper) 67 + { 68 + unsigned long temp = eth_proto_oper; 69 + u32 speed = 0; 70 + int i; 71 + 72 + i = find_first_bit(&temp, MLX5E_LINK_MODES_NUMBER); 73 + if (i < MLX5E_LINK_MODES_NUMBER) 74 + speed = mlx5e_link_speed[i]; 75 + 76 + return speed; 77 + } 78 + 79 + int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) 80 + { 81 + u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {}; 82 + u32 eth_proto_oper; 83 + int err; 84 + 85 + err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1); 86 + if (err) 87 + return err; 88 + 89 + eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 90 + *speed = mlx5e_port_ptys2speed(eth_proto_oper); 91 + if (!(*speed)) { 92 + mlx5_core_warn(mdev, "cannot get port speed\n"); 93 + err = -EINVAL; 94 + } 95 + 96 + return err; 97 + } 98 + 99 + int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) 100 + { 101 + u32 max_speed = 0; 102 + u32 proto_cap; 103 + int err; 104 + int i; 105 + 106 + err = mlx5_query_port_proto_cap(mdev, &proto_cap, MLX5_PTYS_EN); 107 + if (err) 108 + return err; 109 + 110 + for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) 111 + if (proto_cap & MLX5E_PROT_MASK(i)) 112 + max_speed = max(max_speed, mlx5e_link_speed[i]); 113 + 114 + *speed = max_speed; 115 + return 0; 116 + } 117 + 118 + u32 mlx5e_port_speed2linkmodes(u32 speed) 119 + { 120 + u32 link_modes = 0; 121 + int i; 122 + 123 + for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { 124 + if (mlx5e_link_speed[i] == speed) 125 + link_modes |= MLX5E_PROT_MASK(i); 126 + } 127 + 128 + return link_modes; 129 + } 130 + 131 + int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out) 132 + { 133 + int sz = MLX5_ST_SZ_BYTES(pbmc_reg); 134 + void *in; 135 + int err; 136 + 137 + in = kzalloc(sz, GFP_KERNEL); 138 + if (!in) 139 + return -ENOMEM; 140 + 141 + MLX5_SET(pbmc_reg, in, local_port, 1); 142 + err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 0); 143 + 144 + kfree(in); 145 + return err; 146 + } 147 + 148 + int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in) 149 + { 150 + int sz = MLX5_ST_SZ_BYTES(pbmc_reg); 151 + void *out; 152 + int err; 153 + 154 + out = kzalloc(sz, GFP_KERNEL); 155 + if (!out) 156 + return -ENOMEM; 157 + 158 + MLX5_SET(pbmc_reg, in, local_port, 1); 159 + err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 1); 160 + 161 + kfree(out); 162 + return err; 163 + } 164 + 165 + /* buffer[i]: buffer that priority i mapped to */ 166 + int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer) 167 + { 168 + int sz = MLX5_ST_SZ_BYTES(pptb_reg); 169 + u32 prio_x_buff; 170 + void *out; 171 + void *in; 172 + int prio; 173 + int err; 174 + 175 + in = kzalloc(sz, GFP_KERNEL); 176 + out = kzalloc(sz, GFP_KERNEL); 177 + if (!in || !out) { 178 + err = -ENOMEM; 179 + goto out; 180 + } 181 + 182 + MLX5_SET(pptb_reg, in, local_port, 1); 183 + err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0); 184 + if (err) 185 + goto out; 186 + 187 + prio_x_buff = MLX5_GET(pptb_reg, out, prio_x_buff); 188 + for (prio = 0; prio < 8; prio++) { 189 + buffer[prio] = (u8)(prio_x_buff >> (4 * prio)) & 0xF; 190 + mlx5_core_dbg(mdev, "prio %d, buffer %d\n", prio, buffer[prio]); 191 + } 192 + out: 193 + kfree(in); 194 + kfree(out); 195 + return err; 196 + } 197 + 198 + int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer) 199 + { 200 + int sz = MLX5_ST_SZ_BYTES(pptb_reg); 201 + u32 prio_x_buff; 202 + void *out; 203 + void *in; 204 + int prio; 205 + int err; 206 + 207 + in = kzalloc(sz, GFP_KERNEL); 208 + out = kzalloc(sz, GFP_KERNEL); 209 + if (!in || !out) { 210 + err = -ENOMEM; 211 + goto out; 212 + } 213 + 214 + /* First query the pptb register */ 215 + MLX5_SET(pptb_reg, in, local_port, 1); 216 + err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0); 217 + if (err) 218 + goto out; 219 + 220 + memcpy(in, out, sz); 221 + MLX5_SET(pptb_reg, in, local_port, 1); 222 + 223 + /* Update the pm and prio_x_buff */ 224 + MLX5_SET(pptb_reg, in, pm, 0xFF); 225 + 226 + prio_x_buff = 0; 227 + for (prio = 0; prio < 8; prio++) 228 + prio_x_buff |= (buffer[prio] << (4 * prio)); 229 + MLX5_SET(pptb_reg, in, prio_x_buff, prio_x_buff); 230 + 231 + err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1); 232 + 233 + out: 234 + kfree(in); 235 + kfree(out); 236 + return err; 237 + }
+48
drivers/net/ethernet/mellanox/mlx5/core/en/port.h
··· 1 + /* 2 + * Copyright (c) 2018, Mellanox Technologies. All rights reserved. 3 + * 4 + * This software is available to you under a choice of one of two 5 + * licenses. You may choose to be licensed under the terms of the GNU 6 + * General Public License (GPL) Version 2, available from the file 7 + * COPYING in the main directory of this source tree, or the 8 + * OpenIB.org BSD license below: 9 + * 10 + * Redistribution and use in source and binary forms, with or 11 + * without modification, are permitted provided that the following 12 + * conditions are met: 13 + * 14 + * - Redistributions of source code must retain the above 15 + * copyright notice, this list of conditions and the following 16 + * disclaimer. 17 + * 18 + * - Redistributions in binary form must reproduce the above 19 + * copyright notice, this list of conditions and the following 20 + * disclaimer in the documentation and/or other materials 21 + * provided with the distribution. 22 + * 23 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 + * SOFTWARE. 31 + */ 32 + 33 + #ifndef __MLX5E_EN_PORT_H 34 + #define __MLX5E_EN_PORT_H 35 + 36 + #include <linux/mlx5/driver.h> 37 + #include "en.h" 38 + 39 + u32 mlx5e_port_ptys2speed(u32 eth_proto_oper); 40 + int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); 41 + int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); 42 + u32 mlx5e_port_speed2linkmodes(u32 speed); 43 + 44 + int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out); 45 + int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in); 46 + int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer); 47 + int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer); 48 + #endif
+327
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
··· 1 + /* 2 + * Copyright (c) 2018, Mellanox Technologies. All rights reserved. 3 + * 4 + * This software is available to you under a choice of one of two 5 + * licenses. You may choose to be licensed under the terms of the GNU 6 + * General Public License (GPL) Version 2, available from the file 7 + * COPYING in the main directory of this source tree, or the 8 + * OpenIB.org BSD license below: 9 + * 10 + * Redistribution and use in source and binary forms, with or 11 + * without modification, are permitted provided that the following 12 + * conditions are met: 13 + * 14 + * - Redistributions of source code must retain the above 15 + * copyright notice, this list of conditions and the following 16 + * disclaimer. 17 + * 18 + * - Redistributions in binary form must reproduce the above 19 + * copyright notice, this list of conditions and the following 20 + * disclaimer in the documentation and/or other materials 21 + * provided with the distribution. 22 + * 23 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 + * SOFTWARE. 31 + */ 32 + #include "port_buffer.h" 33 + 34 + int mlx5e_port_query_buffer(struct mlx5e_priv *priv, 35 + struct mlx5e_port_buffer *port_buffer) 36 + { 37 + struct mlx5_core_dev *mdev = priv->mdev; 38 + int sz = MLX5_ST_SZ_BYTES(pbmc_reg); 39 + u32 total_used = 0; 40 + void *buffer; 41 + void *out; 42 + int err; 43 + int i; 44 + 45 + out = kzalloc(sz, GFP_KERNEL); 46 + if (!out) 47 + return -ENOMEM; 48 + 49 + err = mlx5e_port_query_pbmc(mdev, out); 50 + if (err) 51 + goto out; 52 + 53 + for (i = 0; i < MLX5E_MAX_BUFFER; i++) { 54 + buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]); 55 + port_buffer->buffer[i].lossy = 56 + MLX5_GET(bufferx_reg, buffer, lossy); 57 + port_buffer->buffer[i].epsb = 58 + MLX5_GET(bufferx_reg, buffer, epsb); 59 + port_buffer->buffer[i].size = 60 + MLX5_GET(bufferx_reg, buffer, size) << MLX5E_BUFFER_CELL_SHIFT; 61 + port_buffer->buffer[i].xon = 62 + MLX5_GET(bufferx_reg, buffer, xon_threshold) << MLX5E_BUFFER_CELL_SHIFT; 63 + port_buffer->buffer[i].xoff = 64 + MLX5_GET(bufferx_reg, buffer, xoff_threshold) << MLX5E_BUFFER_CELL_SHIFT; 65 + total_used += port_buffer->buffer[i].size; 66 + 67 + mlx5e_dbg(HW, priv, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", i, 68 + port_buffer->buffer[i].size, 69 + port_buffer->buffer[i].xon, 70 + port_buffer->buffer[i].xoff, 71 + port_buffer->buffer[i].epsb, 72 + port_buffer->buffer[i].lossy); 73 + } 74 + 75 + port_buffer->port_buffer_size = 76 + MLX5_GET(pbmc_reg, out, port_buffer_size) << MLX5E_BUFFER_CELL_SHIFT; 77 + port_buffer->spare_buffer_size = 78 + port_buffer->port_buffer_size - total_used; 79 + 80 + mlx5e_dbg(HW, priv, "total buffer size=%d, spare buffer size=%d\n", 81 + port_buffer->port_buffer_size, 82 + port_buffer->spare_buffer_size); 83 + out: 84 + kfree(out); 85 + return err; 86 + } 87 + 88 + static int port_set_buffer(struct mlx5e_priv *priv, 89 + struct mlx5e_port_buffer *port_buffer) 90 + { 91 + struct mlx5_core_dev *mdev = priv->mdev; 92 + int sz = MLX5_ST_SZ_BYTES(pbmc_reg); 93 + void *buffer; 94 + void *in; 95 + int err; 96 + int i; 97 + 98 + in = kzalloc(sz, GFP_KERNEL); 99 + if (!in) 100 + return -ENOMEM; 101 + 102 + err = mlx5e_port_query_pbmc(mdev, in); 103 + if (err) 104 + goto out; 105 + 106 + for (i = 0; i < MLX5E_MAX_BUFFER; i++) { 107 + buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]); 108 + 109 + MLX5_SET(bufferx_reg, buffer, size, 110 + port_buffer->buffer[i].size >> MLX5E_BUFFER_CELL_SHIFT); 111 + MLX5_SET(bufferx_reg, buffer, lossy, 112 + port_buffer->buffer[i].lossy); 113 + MLX5_SET(bufferx_reg, buffer, xoff_threshold, 114 + port_buffer->buffer[i].xoff >> MLX5E_BUFFER_CELL_SHIFT); 115 + MLX5_SET(bufferx_reg, buffer, xon_threshold, 116 + port_buffer->buffer[i].xon >> MLX5E_BUFFER_CELL_SHIFT); 117 + } 118 + 119 + err = mlx5e_port_set_pbmc(mdev, in); 120 + out: 121 + kfree(in); 122 + return err; 123 + } 124 + 125 + /* xoff = ((301+2.16 * len [m]) * speed [Gbps] + 2.72 MTU [B]) */ 126 + static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu) 127 + { 128 + u32 speed; 129 + u32 xoff; 130 + int err; 131 + 132 + err = mlx5e_port_linkspeed(priv->mdev, &speed); 133 + if (err) 134 + return 0; 135 + 136 + xoff = (301 + 216 * priv->dcbx.cable_len / 100) * speed / 1000 + 272 * mtu / 100; 137 + 138 + mlx5e_dbg(HW, priv, "%s: xoff=%d\n", __func__, xoff); 139 + return xoff; 140 + } 141 + 142 + static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer, 143 + u32 xoff, unsigned int mtu) 144 + { 145 + int i; 146 + 147 + for (i = 0; i < MLX5E_MAX_BUFFER; i++) { 148 + if (port_buffer->buffer[i].lossy) { 149 + port_buffer->buffer[i].xoff = 0; 150 + port_buffer->buffer[i].xon = 0; 151 + continue; 152 + } 153 + 154 + if (port_buffer->buffer[i].size < 155 + (xoff + mtu + (1 << MLX5E_BUFFER_CELL_SHIFT))) 156 + return -ENOMEM; 157 + 158 + port_buffer->buffer[i].xoff = port_buffer->buffer[i].size - xoff; 159 + port_buffer->buffer[i].xon = port_buffer->buffer[i].xoff - mtu; 160 + } 161 + 162 + return 0; 163 + } 164 + 165 + /** 166 + * update_buffer_lossy() 167 + * mtu: device's MTU 168 + * pfc_en: <input> current pfc configuration 169 + * buffer: <input> current prio to buffer mapping 170 + * xoff: <input> xoff value 171 + * port_buffer: <output> port receive buffer configuration 172 + * change: <output> 173 + * 174 + * Update buffer configuration based on pfc configuraiton and priority 175 + * to buffer mapping. 176 + * Buffer's lossy bit is changed to: 177 + * lossless if there is at least one PFC enabled priority mapped to this buffer 178 + * lossy if all priorities mapped to this buffer are PFC disabled 179 + * 180 + * Return: 181 + * Return 0 if no error. 182 + * Set change to true if buffer configuration is modified. 183 + */ 184 + static int update_buffer_lossy(unsigned int mtu, 185 + u8 pfc_en, u8 *buffer, u32 xoff, 186 + struct mlx5e_port_buffer *port_buffer, 187 + bool *change) 188 + { 189 + bool changed = false; 190 + u8 lossy_count; 191 + u8 prio_count; 192 + u8 lossy; 193 + int prio; 194 + int err; 195 + int i; 196 + 197 + for (i = 0; i < MLX5E_MAX_BUFFER; i++) { 198 + prio_count = 0; 199 + lossy_count = 0; 200 + 201 + for (prio = 0; prio < MLX5E_MAX_PRIORITY; prio++) { 202 + if (buffer[prio] != i) 203 + continue; 204 + 205 + prio_count++; 206 + lossy_count += !(pfc_en & (1 << prio)); 207 + } 208 + 209 + if (lossy_count == prio_count) 210 + lossy = 1; 211 + else /* lossy_count < prio_count */ 212 + lossy = 0; 213 + 214 + if (lossy != port_buffer->buffer[i].lossy) { 215 + port_buffer->buffer[i].lossy = lossy; 216 + changed = true; 217 + } 218 + } 219 + 220 + if (changed) { 221 + err = update_xoff_threshold(port_buffer, xoff, mtu); 222 + if (err) 223 + return err; 224 + 225 + *change = true; 226 + } 227 + 228 + return 0; 229 + } 230 + 231 + int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, 232 + u32 change, unsigned int mtu, 233 + struct ieee_pfc *pfc, 234 + u32 *buffer_size, 235 + u8 *prio2buffer) 236 + { 237 + struct mlx5e_port_buffer port_buffer; 238 + u32 xoff = calculate_xoff(priv, mtu); 239 + bool update_prio2buffer = false; 240 + u8 buffer[MLX5E_MAX_PRIORITY]; 241 + bool update_buffer = false; 242 + u32 total_used = 0; 243 + u8 curr_pfc_en; 244 + int err; 245 + int i; 246 + 247 + mlx5e_dbg(HW, priv, "%s: change=%x\n", __func__, change); 248 + 249 + err = mlx5e_port_query_buffer(priv, &port_buffer); 250 + if (err) 251 + return err; 252 + 253 + if (change & MLX5E_PORT_BUFFER_CABLE_LEN) { 254 + update_buffer = true; 255 + err = update_xoff_threshold(&port_buffer, xoff, mtu); 256 + if (err) 257 + return err; 258 + } 259 + 260 + if (change & MLX5E_PORT_BUFFER_PFC) { 261 + err = mlx5e_port_query_priority2buffer(priv->mdev, buffer); 262 + if (err) 263 + return err; 264 + 265 + err = update_buffer_lossy(mtu, pfc->pfc_en, buffer, xoff, 266 + &port_buffer, &update_buffer); 267 + if (err) 268 + return err; 269 + } 270 + 271 + if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) { 272 + update_prio2buffer = true; 273 + err = mlx5_query_port_pfc(priv->mdev, &curr_pfc_en, NULL); 274 + if (err) 275 + return err; 276 + 277 + err = update_buffer_lossy(mtu, curr_pfc_en, prio2buffer, xoff, 278 + &port_buffer, &update_buffer); 279 + if (err) 280 + return err; 281 + } 282 + 283 + if (change & MLX5E_PORT_BUFFER_SIZE) { 284 + for (i = 0; i < MLX5E_MAX_BUFFER; i++) { 285 + mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]); 286 + if (!port_buffer.buffer[i].lossy && !buffer_size[i]) { 287 + mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n", 288 + __func__, i); 289 + return -EINVAL; 290 + } 291 + 292 + port_buffer.buffer[i].size = buffer_size[i]; 293 + total_used += buffer_size[i]; 294 + } 295 + 296 + mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used); 297 + 298 + if (total_used > port_buffer.port_buffer_size) 299 + return -EINVAL; 300 + 301 + update_buffer = true; 302 + err = update_xoff_threshold(&port_buffer, xoff, mtu); 303 + if (err) 304 + return err; 305 + } 306 + 307 + /* Need to update buffer configuration if xoff value is changed */ 308 + if (!update_buffer && xoff != priv->dcbx.xoff) { 309 + update_buffer = true; 310 + err = update_xoff_threshold(&port_buffer, xoff, mtu); 311 + if (err) 312 + return err; 313 + } 314 + priv->dcbx.xoff = xoff; 315 + 316 + /* Apply the settings */ 317 + if (update_buffer) { 318 + err = port_set_buffer(priv, &port_buffer); 319 + if (err) 320 + return err; 321 + } 322 + 323 + if (update_prio2buffer) 324 + err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); 325 + 326 + return err; 327 + }
+75
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h
··· 1 + /* 2 + * Copyright (c) 2018, Mellanox Technologies. All rights reserved. 3 + * 4 + * This software is available to you under a choice of one of two 5 + * licenses. You may choose to be licensed under the terms of the GNU 6 + * General Public License (GPL) Version 2, available from the file 7 + * COPYING in the main directory of this source tree, or the 8 + * OpenIB.org BSD license below: 9 + * 10 + * Redistribution and use in source and binary forms, with or 11 + * without modification, are permitted provided that the following 12 + * conditions are met: 13 + * 14 + * - Redistributions of source code must retain the above 15 + * copyright notice, this list of conditions and the following 16 + * disclaimer. 17 + * 18 + * - Redistributions in binary form must reproduce the above 19 + * copyright notice, this list of conditions and the following 20 + * disclaimer in the documentation and/or other materials 21 + * provided with the distribution. 22 + * 23 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 + * SOFTWARE. 31 + */ 32 + #ifndef __MLX5_EN_PORT_BUFFER_H__ 33 + #define __MLX5_EN_PORT_BUFFER_H__ 34 + 35 + #include "en.h" 36 + #include "port.h" 37 + 38 + #define MLX5E_MAX_BUFFER 8 39 + #define MLX5E_BUFFER_CELL_SHIFT 7 40 + #define MLX5E_DEFAULT_CABLE_LEN 7 /* 7 meters */ 41 + 42 + #define MLX5_BUFFER_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, pcam_reg) && \ 43 + MLX5_CAP_PCAM_REG(mdev, pbmc) && \ 44 + MLX5_CAP_PCAM_REG(mdev, pptb)) 45 + 46 + enum { 47 + MLX5E_PORT_BUFFER_CABLE_LEN = BIT(0), 48 + MLX5E_PORT_BUFFER_PFC = BIT(1), 49 + MLX5E_PORT_BUFFER_PRIO2BUFFER = BIT(2), 50 + MLX5E_PORT_BUFFER_SIZE = BIT(3), 51 + }; 52 + 53 + struct mlx5e_bufferx_reg { 54 + u8 lossy; 55 + u8 epsb; 56 + u32 size; 57 + u32 xoff; 58 + u32 xon; 59 + }; 60 + 61 + struct mlx5e_port_buffer { 62 + u32 port_buffer_size; 63 + u32 spare_buffer_size; 64 + struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER]; 65 + }; 66 + 67 + int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, 68 + u32 change, unsigned int mtu, 69 + struct ieee_pfc *pfc, 70 + u32 *buffer_size, 71 + u8 *prio2buffer); 72 + 73 + int mlx5e_port_query_buffer(struct mlx5e_priv *priv, 74 + struct mlx5e_port_buffer *port_buffer); 75 + #endif
+125 -7
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
··· 32 32 #include <linux/device.h> 33 33 #include <linux/netdevice.h> 34 34 #include "en.h" 35 - 36 - #define MLX5E_MAX_PRIORITY 8 35 + #include "en/port.h" 36 + #include "en/port_buffer.h" 37 37 38 38 #define MLX5E_100MB (100000) 39 39 #define MLX5E_1GB (1000000) 40 40 41 41 #define MLX5E_CEE_STATE_UP 1 42 42 #define MLX5E_CEE_STATE_DOWN 0 43 + 44 + /* Max supported cable length is 1000 meters */ 45 + #define MLX5E_MAX_CABLE_LENGTH 1000 43 46 44 47 enum { 45 48 MLX5E_VENDOR_TC_GROUP_NUM = 7, ··· 341 338 pfc->indications[i] = PPORT_PER_PRIO_GET(pstats, i, rx_pause); 342 339 } 343 340 341 + if (MLX5_BUFFER_SUPPORTED(mdev)) 342 + pfc->delay = priv->dcbx.cable_len; 343 + 344 344 return mlx5_query_port_pfc(mdev, &pfc->pfc_en, NULL); 345 345 } 346 346 ··· 352 346 { 353 347 struct mlx5e_priv *priv = netdev_priv(dev); 354 348 struct mlx5_core_dev *mdev = priv->mdev; 349 + u32 old_cable_len = priv->dcbx.cable_len; 350 + struct ieee_pfc pfc_new; 351 + u32 changed = 0; 355 352 u8 curr_pfc_en; 356 - int ret; 353 + int ret = 0; 357 354 355 + /* pfc_en */ 358 356 mlx5_query_port_pfc(mdev, &curr_pfc_en, NULL); 357 + if (pfc->pfc_en != curr_pfc_en) { 358 + ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en); 359 + if (ret) 360 + return ret; 361 + mlx5_toggle_port_link(mdev); 362 + changed |= MLX5E_PORT_BUFFER_PFC; 363 + } 359 364 360 - if (pfc->pfc_en == curr_pfc_en) 361 - return 0; 365 + if (pfc->delay && 366 + pfc->delay < MLX5E_MAX_CABLE_LENGTH && 367 + pfc->delay != priv->dcbx.cable_len) { 368 + priv->dcbx.cable_len = pfc->delay; 369 + changed |= MLX5E_PORT_BUFFER_CABLE_LEN; 370 + } 362 371 363 - ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en); 364 - mlx5_toggle_port_link(mdev); 372 + if (MLX5_BUFFER_SUPPORTED(mdev)) { 373 + pfc_new.pfc_en = (changed & MLX5E_PORT_BUFFER_PFC) ? pfc->pfc_en : curr_pfc_en; 374 + if (priv->dcbx.manual_buffer) 375 + ret = mlx5e_port_manual_buffer_config(priv, changed, 376 + dev->mtu, &pfc_new, 377 + NULL, NULL); 378 + 379 + if (ret && (changed & MLX5E_PORT_BUFFER_CABLE_LEN)) 380 + priv->dcbx.cable_len = old_cable_len; 381 + } 365 382 366 383 if (!ret) { 367 384 mlx5e_dbg(HW, priv, ··· 902 873 cee_cfg->pfc_enable = state; 903 874 } 904 875 876 + static int mlx5e_dcbnl_getbuffer(struct net_device *dev, 877 + struct dcbnl_buffer *dcb_buffer) 878 + { 879 + struct mlx5e_priv *priv = netdev_priv(dev); 880 + struct mlx5_core_dev *mdev = priv->mdev; 881 + struct mlx5e_port_buffer port_buffer; 882 + u8 buffer[MLX5E_MAX_PRIORITY]; 883 + int i, err; 884 + 885 + if (!MLX5_BUFFER_SUPPORTED(mdev)) 886 + return -EOPNOTSUPP; 887 + 888 + err = mlx5e_port_query_priority2buffer(mdev, buffer); 889 + if (err) 890 + return err; 891 + 892 + for (i = 0; i < MLX5E_MAX_PRIORITY; i++) 893 + dcb_buffer->prio2buffer[i] = buffer[i]; 894 + 895 + err = mlx5e_port_query_buffer(priv, &port_buffer); 896 + if (err) 897 + return err; 898 + 899 + for (i = 0; i < MLX5E_MAX_BUFFER; i++) 900 + dcb_buffer->buffer_size[i] = port_buffer.buffer[i].size; 901 + dcb_buffer->total_size = port_buffer.port_buffer_size; 902 + 903 + return 0; 904 + } 905 + 906 + static int mlx5e_dcbnl_setbuffer(struct net_device *dev, 907 + struct dcbnl_buffer *dcb_buffer) 908 + { 909 + struct mlx5e_priv *priv = netdev_priv(dev); 910 + struct mlx5_core_dev *mdev = priv->mdev; 911 + struct mlx5e_port_buffer port_buffer; 912 + u8 old_prio2buffer[MLX5E_MAX_PRIORITY]; 913 + u32 *buffer_size = NULL; 914 + u8 *prio2buffer = NULL; 915 + u32 changed = 0; 916 + int i, err; 917 + 918 + if (!MLX5_BUFFER_SUPPORTED(mdev)) 919 + return -EOPNOTSUPP; 920 + 921 + for (i = 0; i < DCBX_MAX_BUFFERS; i++) 922 + mlx5_core_dbg(mdev, "buffer[%d]=%d\n", i, dcb_buffer->buffer_size[i]); 923 + 924 + for (i = 0; i < MLX5E_MAX_PRIORITY; i++) 925 + mlx5_core_dbg(mdev, "priority %d buffer%d\n", i, dcb_buffer->prio2buffer[i]); 926 + 927 + err = mlx5e_port_query_priority2buffer(mdev, old_prio2buffer); 928 + if (err) 929 + return err; 930 + 931 + for (i = 0; i < MLX5E_MAX_PRIORITY; i++) { 932 + if (dcb_buffer->prio2buffer[i] != old_prio2buffer[i]) { 933 + changed |= MLX5E_PORT_BUFFER_PRIO2BUFFER; 934 + prio2buffer = dcb_buffer->prio2buffer; 935 + break; 936 + } 937 + } 938 + 939 + err = mlx5e_port_query_buffer(priv, &port_buffer); 940 + if (err) 941 + return err; 942 + 943 + for (i = 0; i < MLX5E_MAX_BUFFER; i++) { 944 + if (port_buffer.buffer[i].size != dcb_buffer->buffer_size[i]) { 945 + changed |= MLX5E_PORT_BUFFER_SIZE; 946 + buffer_size = dcb_buffer->buffer_size; 947 + break; 948 + } 949 + } 950 + 951 + if (!changed) 952 + return 0; 953 + 954 + priv->dcbx.manual_buffer = true; 955 + err = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, NULL, 956 + buffer_size, prio2buffer); 957 + return err; 958 + } 959 + 905 960 const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = { 906 961 .ieee_getets = mlx5e_dcbnl_ieee_getets, 907 962 .ieee_setets = mlx5e_dcbnl_ieee_setets, ··· 997 884 .ieee_delapp = mlx5e_dcbnl_ieee_delapp, 998 885 .getdcbx = mlx5e_dcbnl_getdcbx, 999 886 .setdcbx = mlx5e_dcbnl_setdcbx, 887 + .dcbnl_getbuffer = mlx5e_dcbnl_getbuffer, 888 + .dcbnl_setbuffer = mlx5e_dcbnl_setbuffer, 1000 889 1001 890 /* CEE interfaces */ 1002 891 .setall = mlx5e_dcbnl_setall, ··· 1205 1090 DCB_CAP_DCBX_VER_IEEE; 1206 1091 if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST) 1207 1092 priv->dcbx.cap |= DCB_CAP_DCBX_HOST; 1093 + 1094 + priv->dcbx.manual_buffer = false; 1095 + priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN; 1208 1096 1209 1097 mlx5e_ets_init(priv); 1210 1098 }
+35 -67
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
··· 31 31 */ 32 32 33 33 #include "en.h" 34 + #include "en/port.h" 34 35 35 36 void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv, 36 37 struct ethtool_drvinfo *drvinfo) ··· 60 59 struct ptys2ethtool_config { 61 60 __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); 62 61 __ETHTOOL_DECLARE_LINK_MODE_MASK(advertised); 63 - u32 speed; 64 62 }; 65 63 66 64 static struct ptys2ethtool_config ptys2ethtool_table[MLX5E_LINK_MODES_NUMBER]; 67 65 68 - #define MLX5_BUILD_PTYS2ETHTOOL_CONFIG(reg_, speed_, ...) \ 66 + #define MLX5_BUILD_PTYS2ETHTOOL_CONFIG(reg_, ...) \ 69 67 ({ \ 70 68 struct ptys2ethtool_config *cfg; \ 71 69 const unsigned int modes[] = { __VA_ARGS__ }; \ 72 70 unsigned int i; \ 73 71 cfg = &ptys2ethtool_table[reg_]; \ 74 - cfg->speed = speed_; \ 75 72 bitmap_zero(cfg->supported, \ 76 73 __ETHTOOL_LINK_MODE_MASK_NBITS); \ 77 74 bitmap_zero(cfg->advertised, \ ··· 82 83 83 84 void mlx5e_build_ptys2ethtool_map(void) 84 85 { 85 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_CX_SGMII, SPEED_1000, 86 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_CX_SGMII, 86 87 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); 87 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_KX, SPEED_1000, 88 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_KX, 88 89 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); 89 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CX4, SPEED_10000, 90 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CX4, 90 91 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT); 91 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KX4, SPEED_10000, 92 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KX4, 92 93 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT); 93 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KR, SPEED_10000, 94 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KR, 94 95 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); 95 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_20GBASE_KR2, SPEED_20000, 96 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_20GBASE_KR2, 96 97 ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT); 97 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_CR4, SPEED_40000, 98 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_CR4, 98 99 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT); 99 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_KR4, SPEED_40000, 100 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_KR4, 100 101 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT); 101 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_56GBASE_R4, SPEED_56000, 102 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_56GBASE_R4, 102 103 ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT); 103 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CR, SPEED_10000, 104 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CR, 104 105 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); 105 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_SR, SPEED_10000, 106 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_SR, 106 107 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); 107 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_ER, SPEED_10000, 108 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_ER, 108 109 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); 109 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_SR4, SPEED_40000, 110 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_SR4, 110 111 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT); 111 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_LR4, SPEED_40000, 112 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_LR4, 112 113 ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT); 113 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_SR2, SPEED_50000, 114 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_SR2, 114 115 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT); 115 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_CR4, SPEED_100000, 116 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_CR4, 116 117 ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT); 117 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_SR4, SPEED_100000, 118 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_SR4, 118 119 ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT); 119 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_KR4, SPEED_100000, 120 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_KR4, 120 121 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT); 121 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4, SPEED_100000, 122 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4, 122 123 ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT); 123 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T, SPEED_10000, 124 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T, 124 125 ETHTOOL_LINK_MODE_10000baseT_Full_BIT); 125 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR, SPEED_25000, 126 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR, 126 127 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT); 127 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_KR, SPEED_25000, 128 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_KR, 128 129 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT); 129 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_SR, SPEED_25000, 130 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_SR, 130 131 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT); 131 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_CR2, SPEED_50000, 132 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_CR2, 132 133 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT); 133 - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_KR2, SPEED_50000, 134 + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_KR2, 134 135 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT); 135 136 } 136 137 ··· 616 617 } 617 618 } 618 619 619 - int mlx5e_get_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) 620 - { 621 - u32 max_speed = 0; 622 - u32 proto_cap; 623 - int err; 624 - int i; 625 - 626 - err = mlx5_query_port_proto_cap(mdev, &proto_cap, MLX5_PTYS_EN); 627 - if (err) 628 - return err; 629 - 630 - for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) 631 - if (proto_cap & MLX5E_PROT_MASK(i)) 632 - max_speed = max(max_speed, ptys2ethtool_table[i].speed); 633 - 634 - *speed = max_speed; 635 - return 0; 636 - } 637 - 638 620 static void get_speed_duplex(struct net_device *netdev, 639 621 u32 eth_proto_oper, 640 622 struct ethtool_link_ksettings *link_ksettings) 641 623 { 642 - int i; 643 624 u32 speed = SPEED_UNKNOWN; 644 625 u8 duplex = DUPLEX_UNKNOWN; 645 626 646 627 if (!netif_carrier_ok(netdev)) 647 628 goto out; 648 629 649 - for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { 650 - if (eth_proto_oper & MLX5E_PROT_MASK(i)) { 651 - speed = ptys2ethtool_table[i].speed; 652 - duplex = DUPLEX_FULL; 653 - break; 654 - } 630 + speed = mlx5e_port_ptys2speed(eth_proto_oper); 631 + if (!speed) { 632 + speed = SPEED_UNKNOWN; 633 + goto out; 655 634 } 635 + 636 + duplex = DUPLEX_FULL; 637 + 656 638 out: 657 639 link_ksettings->base.speed = speed; 658 640 link_ksettings->base.duplex = duplex; ··· 791 811 return ptys_modes; 792 812 } 793 813 794 - static u32 mlx5e_ethtool2ptys_speed_link(u32 speed) 795 - { 796 - u32 i, speed_links = 0; 797 - 798 - for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { 799 - if (ptys2ethtool_table[i].speed == speed) 800 - speed_links |= MLX5E_PROT_MASK(i); 801 - } 802 - 803 - return speed_links; 804 - } 805 - 806 814 static int mlx5e_set_link_ksettings(struct net_device *netdev, 807 815 const struct ethtool_link_ksettings *link_ksettings) 808 816 { ··· 810 842 811 843 link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ? 812 844 mlx5e_ethtool2ptys_adver_link(link_ksettings->link_modes.advertising) : 813 - mlx5e_ethtool2ptys_speed_link(speed); 845 + mlx5e_port_speed2linkmodes(speed); 814 846 815 847 err = mlx5_query_port_proto_cap(mdev, &eth_proto_cap, MLX5_PTYS_EN); 816 848 if (err) {
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 46 46 #include "accel/ipsec.h" 47 47 #include "accel/tls.h" 48 48 #include "vxlan.h" 49 + #include "en/port.h" 49 50 50 51 struct mlx5e_rq_param { 51 52 u32 rqc[MLX5_ST_SZ_DW(rqc)]; ··· 4083 4082 u32 link_speed = 0; 4084 4083 u32 pci_bw = 0; 4085 4084 4086 - mlx5e_get_max_linkspeed(mdev, &link_speed); 4085 + mlx5e_port_max_linkspeed(mdev, &link_speed); 4087 4086 pci_bw = pcie_bandwidth_available(mdev->pdev, NULL, NULL, NULL); 4088 4087 mlx5_core_dbg_once(mdev, "Max link speed = %d, PCI BW = %d\n", 4089 4088 link_speed, pci_bw);
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
··· 52 52 #include "eswitch.h" 53 53 #include "vxlan.h" 54 54 #include "fs_core.h" 55 + #include "en/port.h" 55 56 56 57 struct mlx5_nic_flow_attr { 57 58 u32 action; ··· 614 613 615 614 params.q_counter = priv->q_counter; 616 615 /* set hairpin pair per each 50Gbs share of the link */ 617 - mlx5e_get_max_linkspeed(priv->mdev, &link_speed); 616 + mlx5e_port_max_linkspeed(priv->mdev, &link_speed); 618 617 link_speed = max_t(u32, link_speed, 50000); 619 618 link_speed64 = link_speed; 620 619 do_div(link_speed64, 50000);
+3
include/linux/mlx5/device.h
··· 1152 1152 #define MLX5_CAP_PCAM_FEATURE(mdev, fld) \ 1153 1153 MLX5_GET(pcam_reg, (mdev)->caps.pcam, feature_cap_mask.enhanced_features.fld) 1154 1154 1155 + #define MLX5_CAP_PCAM_REG(mdev, reg) \ 1156 + MLX5_GET(pcam_reg, (mdev)->caps.pcam, port_access_reg_cap_mask.regs_5000_to_507f.reg) 1157 + 1155 1158 #define MLX5_CAP_MCAM_REG(mdev, reg) \ 1156 1159 MLX5_GET(mcam_reg, (mdev)->caps.mcam, mng_access_reg_cap_mask.access_regs.reg) 1157 1160
+2
include/linux/mlx5/driver.h
··· 124 124 MLX5_REG_PAOS = 0x5006, 125 125 MLX5_REG_PFCC = 0x5007, 126 126 MLX5_REG_PPCNT = 0x5008, 127 + MLX5_REG_PPTB = 0x500b, 128 + MLX5_REG_PBMC = 0x500c, 127 129 MLX5_REG_PMAOS = 0x5012, 128 130 MLX5_REG_PUDE = 0x5009, 129 131 MLX5_REG_PMPE = 0x5010,
+47
include/linux/mlx5/mlx5_ifc.h
··· 8003 8003 u8 ppcnt_statistical_group[0x1]; 8004 8004 }; 8005 8005 8006 + struct mlx5_ifc_pcam_regs_5000_to_507f_bits { 8007 + u8 port_access_reg_cap_mask_127_to_96[0x20]; 8008 + u8 port_access_reg_cap_mask_95_to_64[0x20]; 8009 + u8 port_access_reg_cap_mask_63_to_32[0x20]; 8010 + 8011 + u8 port_access_reg_cap_mask_31_to_13[0x13]; 8012 + u8 pbmc[0x1]; 8013 + u8 pptb[0x1]; 8014 + u8 port_access_reg_cap_mask_10_to_0[0xb]; 8015 + }; 8016 + 8006 8017 struct mlx5_ifc_pcam_reg_bits { 8007 8018 u8 reserved_at_0[0x8]; 8008 8019 u8 feature_group[0x8]; ··· 8023 8012 u8 reserved_at_20[0x20]; 8024 8013 8025 8014 union { 8015 + struct mlx5_ifc_pcam_regs_5000_to_507f_bits regs_5000_to_507f; 8026 8016 u8 reserved_at_0[0x80]; 8027 8017 } port_access_reg_cap_mask; 8028 8018 ··· 8786 8774 u8 local_port[0x8]; 8787 8775 u8 reserved_at_10[0x2d]; 8788 8776 u8 trust_state[0x3]; 8777 + }; 8778 + 8779 + struct mlx5_ifc_pptb_reg_bits { 8780 + u8 reserved_at_0[0x2]; 8781 + u8 mm[0x2]; 8782 + u8 reserved_at_4[0x4]; 8783 + u8 local_port[0x8]; 8784 + u8 reserved_at_10[0x6]; 8785 + u8 cm[0x1]; 8786 + u8 um[0x1]; 8787 + u8 pm[0x8]; 8788 + 8789 + u8 prio_x_buff[0x20]; 8790 + 8791 + u8 pm_msb[0x8]; 8792 + u8 reserved_at_48[0x10]; 8793 + u8 ctrl_buff[0x4]; 8794 + u8 untagged_buff[0x4]; 8795 + }; 8796 + 8797 + struct mlx5_ifc_pbmc_reg_bits { 8798 + u8 reserved_at_0[0x8]; 8799 + u8 local_port[0x8]; 8800 + u8 reserved_at_10[0x10]; 8801 + 8802 + u8 xoff_timer_value[0x10]; 8803 + u8 xoff_refresh[0x10]; 8804 + 8805 + u8 reserved_at_40[0x9]; 8806 + u8 fullness_threshold[0x7]; 8807 + u8 port_buffer_size[0x10]; 8808 + 8809 + struct mlx5_ifc_bufferx_reg_bits buffer[10]; 8810 + 8811 + u8 reserved_at_2e0[0x40]; 8789 8812 }; 8790 8813 8791 8814 struct mlx5_ifc_qtct_reg_bits {
+4
include/net/dcbnl.h
··· 101 101 /* CEE peer */ 102 102 int (*cee_peer_getpg) (struct net_device *, struct cee_pg *); 103 103 int (*cee_peer_getpfc) (struct net_device *, struct cee_pfc *); 104 + 105 + /* buffer settings */ 106 + int (*dcbnl_getbuffer)(struct net_device *, struct dcbnl_buffer *); 107 + int (*dcbnl_setbuffer)(struct net_device *, struct dcbnl_buffer *); 104 108 }; 105 109 106 110 #endif /* __NET_DCBNL_H__ */
+11
include/uapi/linux/dcbnl.h
··· 163 163 __u64 indications[IEEE_8021QAZ_MAX_TCS]; 164 164 }; 165 165 166 + #define IEEE_8021Q_MAX_PRIORITIES 8 167 + #define DCBX_MAX_BUFFERS 8 168 + struct dcbnl_buffer { 169 + /* priority to buffer mapping */ 170 + __u8 prio2buffer[IEEE_8021Q_MAX_PRIORITIES]; 171 + /* buffer size in Bytes */ 172 + __u32 buffer_size[DCBX_MAX_BUFFERS]; 173 + __u32 total_size; 174 + }; 175 + 166 176 /* CEE DCBX std supported values */ 167 177 #define CEE_DCBX_MAX_PGS 8 168 178 #define CEE_DCBX_MAX_PRIO 8 ··· 416 406 DCB_ATTR_IEEE_MAXRATE, 417 407 DCB_ATTR_IEEE_QCN, 418 408 DCB_ATTR_IEEE_QCN_STATS, 409 + DCB_ATTR_DCB_BUFFER, 419 410 __DCB_ATTR_IEEE_MAX 420 411 }; 421 412 #define DCB_ATTR_IEEE_MAX (__DCB_ATTR_IEEE_MAX - 1)
+20
net/dcb/dcbnl.c
··· 176 176 [DCB_ATTR_IEEE_MAXRATE] = {.len = sizeof(struct ieee_maxrate)}, 177 177 [DCB_ATTR_IEEE_QCN] = {.len = sizeof(struct ieee_qcn)}, 178 178 [DCB_ATTR_IEEE_QCN_STATS] = {.len = sizeof(struct ieee_qcn_stats)}, 179 + [DCB_ATTR_DCB_BUFFER] = {.len = sizeof(struct dcbnl_buffer)}, 179 180 }; 180 181 181 182 /* DCB number of traffic classes nested attributes. */ ··· 1095 1094 return -EMSGSIZE; 1096 1095 } 1097 1096 1097 + if (ops->dcbnl_getbuffer) { 1098 + struct dcbnl_buffer buffer; 1099 + 1100 + memset(&buffer, 0, sizeof(buffer)); 1101 + err = ops->dcbnl_getbuffer(netdev, &buffer); 1102 + if (!err && 1103 + nla_put(skb, DCB_ATTR_DCB_BUFFER, sizeof(buffer), &buffer)) 1104 + return -EMSGSIZE; 1105 + } 1106 + 1098 1107 app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE); 1099 1108 if (!app) 1100 1109 return -EMSGSIZE; ··· 1460 1449 if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) { 1461 1450 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]); 1462 1451 err = ops->ieee_setpfc(netdev, pfc); 1452 + if (err) 1453 + goto err; 1454 + } 1455 + 1456 + if (ieee[DCB_ATTR_DCB_BUFFER] && ops->dcbnl_setbuffer) { 1457 + struct dcbnl_buffer *buffer = 1458 + nla_data(ieee[DCB_ATTR_DCB_BUFFER]); 1459 + 1460 + err = ops->dcbnl_setbuffer(netdev, buffer); 1463 1461 if (err) 1464 1462 goto err; 1465 1463 }