aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-05-25 16:41:23 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-25 16:41:23 -0400
commitd7c52fc8bc45dba13333b21e42bd9dee6cf14a38 (patch)
tree158c54300ec0b4398c88f62963abb68e8272f31c
parenta45675796a0763f5e0ffb75496c3865e961560d3 (diff)
parentecdf2dadee8e8c5015771b802a9851ff332d3fc4 (diff)
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>
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Makefile4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/Makefile1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port.c237
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port.h48
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c327
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h75
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c132
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c102
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c3
-rw-r--r--include/linux/mlx5/device.h3
-rw-r--r--include/linux/mlx5/driver.h2
-rw-r--r--include/linux/mlx5/mlx5_ifc.h47
-rw-r--r--include/net/dcbnl.h4
-rw-r--r--include/uapi/linux/dcbnl.h11
-rw-r--r--net/dcb/dcbnl.c20
17 files changed, 947 insertions, 80 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index a7135f5d5cf6..9efbf193ad5a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -15,13 +15,13 @@ mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o \
15 15
16mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \ 16mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \
17 en_tx.o en_rx.o en_dim.o en_txrx.o en_stats.o vxlan.o \ 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
20mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o 20mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
21 21
22mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o en_rep.o en_tc.o 22mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o en_rep.o en_tc.o
23 23
24mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o 24mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o
25 25
26mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o ipoib/ipoib_vlan.o 26mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o ipoib/ipoib_vlan.o
27 27
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index bc91a7335c93..c5c7a6d687ff 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -65,6 +65,7 @@ struct page_pool;
65#define MLX5E_HW2SW_MTU(params, hwmtu) ((hwmtu) - ((params)->hard_mtu)) 65#define MLX5E_HW2SW_MTU(params, hwmtu) ((hwmtu) - ((params)->hard_mtu))
66#define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu)) 66#define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu))
67 67
68#define MLX5E_MAX_PRIORITY 8
68#define MLX5E_MAX_DSCP 64 69#define MLX5E_MAX_DSCP 64
69#define MLX5E_MAX_NUM_TC 8 70#define MLX5E_MAX_NUM_TC 8
70 71
@@ -275,6 +276,11 @@ struct mlx5e_dcbx {
275 /* The only setting that cannot be read from FW */ 276 /* The only setting that cannot be read from FW */
276 u8 tc_tsa[IEEE_8021QAZ_MAX_TCS]; 277 u8 tc_tsa[IEEE_8021QAZ_MAX_TCS];
277 u8 cap; 278 u8 cap;
279
280 /* Buffer configuration */
281 bool manual_buffer;
282 u32 cable_len;
283 u32 xoff;
278}; 284};
279 285
280struct mlx5e_dcbx_dp { 286struct mlx5e_dcbx_dp {
@@ -932,8 +938,6 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv);
932 938
933void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len, 939void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
934 int num_channels); 940 int num_channels);
935int mlx5e_get_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
936
937void mlx5e_set_tx_cq_mode_params(struct mlx5e_params *params, 941void mlx5e_set_tx_cq_mode_params(struct mlx5e_params *params,
938 u8 cq_period_mode); 942 u8 cq_period_mode);
939void mlx5e_set_rx_cq_mode_params(struct mlx5e_params *params, 943void mlx5e_set_rx_cq_mode_params(struct mlx5e_params *params,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/en/Makefile
new file mode 100644
index 000000000000..d8e17110f25d
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/Makefile
@@ -0,0 +1 @@
subdir-ccflags-y += -I$(src)/..
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
new file mode 100644
index 000000000000..24e3b564964f
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
@@ -0,0 +1,237 @@
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 */
36static 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
66u32 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
79int 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
99int 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
118u32 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
131int 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
148int 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 */
166int 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 }
192out:
193 kfree(in);
194 kfree(out);
195 return err;
196}
197
198int 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
233out:
234 kfree(in);
235 kfree(out);
236 return err;
237}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
new file mode 100644
index 000000000000..f8cbd8194179
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
@@ -0,0 +1,48 @@
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
39u32 mlx5e_port_ptys2speed(u32 eth_proto_oper);
40int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
41int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
42u32 mlx5e_port_speed2linkmodes(u32 speed);
43
44int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
45int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
46int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer);
47int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer);
48#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
new file mode 100644
index 000000000000..c047da8752da
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
@@ -0,0 +1,327 @@
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
34int 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);
83out:
84 kfree(out);
85 return err;
86}
87
88static 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);
120out:
121 kfree(in);
122 return err;
123}
124
125/* xoff = ((301+2.16 * len [m]) * speed [Gbps] + 2.72 MTU [B]) */
126static 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
142static 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 */
184static 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
231int 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}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h
new file mode 100644
index 000000000000..34f55b81a0de
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h
@@ -0,0 +1,75 @@
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
46enum {
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
53struct mlx5e_bufferx_reg {
54 u8 lossy;
55 u8 epsb;
56 u32 size;
57 u32 xoff;
58 u32 xon;
59};
60
61struct mlx5e_port_buffer {
62 u32 port_buffer_size;
63 u32 spare_buffer_size;
64 struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER];
65};
66
67int 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
73int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
74 struct mlx5e_port_buffer *port_buffer);
75#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index c641d5656b2d..0a52f31fef37 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -32,8 +32,8 @@
32#include <linux/device.h> 32#include <linux/device.h>
33#include <linux/netdevice.h> 33#include <linux/netdevice.h>
34#include "en.h" 34#include "en.h"
35 35#include "en/port.h"
36#define MLX5E_MAX_PRIORITY 8 36#include "en/port_buffer.h"
37 37
38#define MLX5E_100MB (100000) 38#define MLX5E_100MB (100000)
39#define MLX5E_1GB (1000000) 39#define MLX5E_1GB (1000000)
@@ -41,6 +41,9 @@
41#define MLX5E_CEE_STATE_UP 1 41#define MLX5E_CEE_STATE_UP 1
42#define MLX5E_CEE_STATE_DOWN 0 42#define MLX5E_CEE_STATE_DOWN 0
43 43
44/* Max supported cable length is 1000 meters */
45#define MLX5E_MAX_CABLE_LENGTH 1000
46
44enum { 47enum {
45 MLX5E_VENDOR_TC_GROUP_NUM = 7, 48 MLX5E_VENDOR_TC_GROUP_NUM = 7,
46 MLX5E_LOWEST_PRIO_GROUP = 0, 49 MLX5E_LOWEST_PRIO_GROUP = 0,
@@ -338,6 +341,9 @@ static int mlx5e_dcbnl_ieee_getpfc(struct net_device *dev,
338 pfc->indications[i] = PPORT_PER_PRIO_GET(pstats, i, rx_pause); 341 pfc->indications[i] = PPORT_PER_PRIO_GET(pstats, i, rx_pause);
339 } 342 }
340 343
344 if (MLX5_BUFFER_SUPPORTED(mdev))
345 pfc->delay = priv->dcbx.cable_len;
346
341 return mlx5_query_port_pfc(mdev, &pfc->pfc_en, NULL); 347 return mlx5_query_port_pfc(mdev, &pfc->pfc_en, NULL);
342} 348}
343 349
@@ -346,16 +352,39 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
346{ 352{
347 struct mlx5e_priv *priv = netdev_priv(dev); 353 struct mlx5e_priv *priv = netdev_priv(dev);
348 struct mlx5_core_dev *mdev = priv->mdev; 354 struct mlx5_core_dev *mdev = priv->mdev;
355 u32 old_cable_len = priv->dcbx.cable_len;
356 struct ieee_pfc pfc_new;
357 u32 changed = 0;
349 u8 curr_pfc_en; 358 u8 curr_pfc_en;
350 int ret; 359 int ret = 0;
351 360
361 /* pfc_en */
352 mlx5_query_port_pfc(mdev, &curr_pfc_en, NULL); 362 mlx5_query_port_pfc(mdev, &curr_pfc_en, NULL);
363 if (pfc->pfc_en != curr_pfc_en) {
364 ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en);
365 if (ret)
366 return ret;
367 mlx5_toggle_port_link(mdev);
368 changed |= MLX5E_PORT_BUFFER_PFC;
369 }
353 370
354 if (pfc->pfc_en == curr_pfc_en) 371 if (pfc->delay &&
355 return 0; 372 pfc->delay < MLX5E_MAX_CABLE_LENGTH &&
373 pfc->delay != priv->dcbx.cable_len) {
374 priv->dcbx.cable_len = pfc->delay;
375 changed |= MLX5E_PORT_BUFFER_CABLE_LEN;
376 }
356 377
357 ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en); 378 if (MLX5_BUFFER_SUPPORTED(mdev)) {
358 mlx5_toggle_port_link(mdev); 379 pfc_new.pfc_en = (changed & MLX5E_PORT_BUFFER_PFC) ? pfc->pfc_en : curr_pfc_en;
380 if (priv->dcbx.manual_buffer)
381 ret = mlx5e_port_manual_buffer_config(priv, changed,
382 dev->mtu, &pfc_new,
383 NULL, NULL);
384
385 if (ret && (changed & MLX5E_PORT_BUFFER_CABLE_LEN))
386 priv->dcbx.cable_len = old_cable_len;
387 }
359 388
360 if (!ret) { 389 if (!ret) {
361 mlx5e_dbg(HW, priv, 390 mlx5e_dbg(HW, priv,
@@ -873,6 +902,90 @@ static void mlx5e_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
873 cee_cfg->pfc_enable = state; 902 cee_cfg->pfc_enable = state;
874} 903}
875 904
905static int mlx5e_dcbnl_getbuffer(struct net_device *dev,
906 struct dcbnl_buffer *dcb_buffer)
907{
908 struct mlx5e_priv *priv = netdev_priv(dev);
909 struct mlx5_core_dev *mdev = priv->mdev;
910 struct mlx5e_port_buffer port_buffer;
911 u8 buffer[MLX5E_MAX_PRIORITY];
912 int i, err;
913
914 if (!MLX5_BUFFER_SUPPORTED(mdev))
915 return -EOPNOTSUPP;
916
917 err = mlx5e_port_query_priority2buffer(mdev, buffer);
918 if (err)
919 return err;
920
921 for (i = 0; i < MLX5E_MAX_PRIORITY; i++)
922 dcb_buffer->prio2buffer[i] = buffer[i];
923
924 err = mlx5e_port_query_buffer(priv, &port_buffer);
925 if (err)
926 return err;
927
928 for (i = 0; i < MLX5E_MAX_BUFFER; i++)
929 dcb_buffer->buffer_size[i] = port_buffer.buffer[i].size;
930 dcb_buffer->total_size = port_buffer.port_buffer_size;
931
932 return 0;
933}
934
935static int mlx5e_dcbnl_setbuffer(struct net_device *dev,
936 struct dcbnl_buffer *dcb_buffer)
937{
938 struct mlx5e_priv *priv = netdev_priv(dev);
939 struct mlx5_core_dev *mdev = priv->mdev;
940 struct mlx5e_port_buffer port_buffer;
941 u8 old_prio2buffer[MLX5E_MAX_PRIORITY];
942 u32 *buffer_size = NULL;
943 u8 *prio2buffer = NULL;
944 u32 changed = 0;
945 int i, err;
946
947 if (!MLX5_BUFFER_SUPPORTED(mdev))
948 return -EOPNOTSUPP;
949
950 for (i = 0; i < DCBX_MAX_BUFFERS; i++)
951 mlx5_core_dbg(mdev, "buffer[%d]=%d\n", i, dcb_buffer->buffer_size[i]);
952
953 for (i = 0; i < MLX5E_MAX_PRIORITY; i++)
954 mlx5_core_dbg(mdev, "priority %d buffer%d\n", i, dcb_buffer->prio2buffer[i]);
955
956 err = mlx5e_port_query_priority2buffer(mdev, old_prio2buffer);
957 if (err)
958 return err;
959
960 for (i = 0; i < MLX5E_MAX_PRIORITY; i++) {
961 if (dcb_buffer->prio2buffer[i] != old_prio2buffer[i]) {
962 changed |= MLX5E_PORT_BUFFER_PRIO2BUFFER;
963 prio2buffer = dcb_buffer->prio2buffer;
964 break;
965 }
966 }
967
968 err = mlx5e_port_query_buffer(priv, &port_buffer);
969 if (err)
970 return err;
971
972 for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
973 if (port_buffer.buffer[i].size != dcb_buffer->buffer_size[i]) {
974 changed |= MLX5E_PORT_BUFFER_SIZE;
975 buffer_size = dcb_buffer->buffer_size;
976 break;
977 }
978 }
979
980 if (!changed)
981 return 0;
982
983 priv->dcbx.manual_buffer = true;
984 err = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, NULL,
985 buffer_size, prio2buffer);
986 return err;
987}
988
876const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = { 989const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
877 .ieee_getets = mlx5e_dcbnl_ieee_getets, 990 .ieee_getets = mlx5e_dcbnl_ieee_getets,
878 .ieee_setets = mlx5e_dcbnl_ieee_setets, 991 .ieee_setets = mlx5e_dcbnl_ieee_setets,
@@ -884,6 +997,8 @@ const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
884 .ieee_delapp = mlx5e_dcbnl_ieee_delapp, 997 .ieee_delapp = mlx5e_dcbnl_ieee_delapp,
885 .getdcbx = mlx5e_dcbnl_getdcbx, 998 .getdcbx = mlx5e_dcbnl_getdcbx,
886 .setdcbx = mlx5e_dcbnl_setdcbx, 999 .setdcbx = mlx5e_dcbnl_setdcbx,
1000 .dcbnl_getbuffer = mlx5e_dcbnl_getbuffer,
1001 .dcbnl_setbuffer = mlx5e_dcbnl_setbuffer,
887 1002
888/* CEE interfaces */ 1003/* CEE interfaces */
889 .setall = mlx5e_dcbnl_setall, 1004 .setall = mlx5e_dcbnl_setall,
@@ -1091,5 +1206,8 @@ void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
1091 if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST) 1206 if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
1092 priv->dcbx.cap |= DCB_CAP_DCBX_HOST; 1207 priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
1093 1208
1209 priv->dcbx.manual_buffer = false;
1210 priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN;
1211
1094 mlx5e_ets_init(priv); 1212 mlx5e_ets_init(priv);
1095} 1213}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 2b786c4d3dab..42bd256e680d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -31,6 +31,7 @@
31 */ 31 */
32 32
33#include "en.h" 33#include "en.h"
34#include "en/port.h"
34 35
35void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv, 36void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv,
36 struct ethtool_drvinfo *drvinfo) 37 struct ethtool_drvinfo *drvinfo)
@@ -59,18 +60,16 @@ static void mlx5e_get_drvinfo(struct net_device *dev,
59struct ptys2ethtool_config { 60struct ptys2ethtool_config {
60 __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); 61 __ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
61 __ETHTOOL_DECLARE_LINK_MODE_MASK(advertised); 62 __ETHTOOL_DECLARE_LINK_MODE_MASK(advertised);
62 u32 speed;
63}; 63};
64 64
65static struct ptys2ethtool_config ptys2ethtool_table[MLX5E_LINK_MODES_NUMBER]; 65static struct ptys2ethtool_config ptys2ethtool_table[MLX5E_LINK_MODES_NUMBER];
66 66
67#define MLX5_BUILD_PTYS2ETHTOOL_CONFIG(reg_, speed_, ...) \ 67#define MLX5_BUILD_PTYS2ETHTOOL_CONFIG(reg_, ...) \
68 ({ \ 68 ({ \
69 struct ptys2ethtool_config *cfg; \ 69 struct ptys2ethtool_config *cfg; \
70 const unsigned int modes[] = { __VA_ARGS__ }; \ 70 const unsigned int modes[] = { __VA_ARGS__ }; \
71 unsigned int i; \ 71 unsigned int i; \
72 cfg = &ptys2ethtool_table[reg_]; \ 72 cfg = &ptys2ethtool_table[reg_]; \
73 cfg->speed = speed_; \
74 bitmap_zero(cfg->supported, \ 73 bitmap_zero(cfg->supported, \
75 __ETHTOOL_LINK_MODE_MASK_NBITS); \ 74 __ETHTOOL_LINK_MODE_MASK_NBITS); \
76 bitmap_zero(cfg->advertised, \ 75 bitmap_zero(cfg->advertised, \
@@ -83,55 +82,55 @@ static struct ptys2ethtool_config ptys2ethtool_table[MLX5E_LINK_MODES_NUMBER];
83 82
84void mlx5e_build_ptys2ethtool_map(void) 83void mlx5e_build_ptys2ethtool_map(void)
85{ 84{
86 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_CX_SGMII, SPEED_1000, 85 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_CX_SGMII,
87 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); 86 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT);
88 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_KX, SPEED_1000, 87 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_KX,
89 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); 88 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT);
90 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CX4, SPEED_10000, 89 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CX4,
91 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT); 90 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT);
92 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KX4, SPEED_10000, 91 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KX4,
93 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT); 92 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT);
94 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KR, SPEED_10000, 93 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KR,
95 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); 94 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
96 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_20GBASE_KR2, SPEED_20000, 95 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_20GBASE_KR2,
97 ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT); 96 ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT);
98 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_CR4, SPEED_40000, 97 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_CR4,
99 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT); 98 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT);
100 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_KR4, SPEED_40000, 99 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_KR4,
101 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT); 100 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT);
102 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_56GBASE_R4, SPEED_56000, 101 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_56GBASE_R4,
103 ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT); 102 ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT);
104 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CR, SPEED_10000, 103 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CR,
105 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); 104 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
106 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_SR, SPEED_10000, 105 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_SR,
107 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); 106 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
108 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_ER, SPEED_10000, 107 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_ER,
109 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); 108 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
110 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_SR4, SPEED_40000, 109 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_SR4,
111 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT); 110 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT);
112 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_LR4, SPEED_40000, 111 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_LR4,
113 ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT); 112 ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT);
114 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_SR2, SPEED_50000, 113 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_SR2,
115 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT); 114 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT);
116 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_CR4, SPEED_100000, 115 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_CR4,
117 ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT); 116 ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT);
118 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_SR4, SPEED_100000, 117 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_SR4,
119 ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT); 118 ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT);
120 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_KR4, SPEED_100000, 119 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_KR4,
121 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT); 120 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT);
122 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4, SPEED_100000, 121 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4,
123 ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT); 122 ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT);
124 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T, SPEED_10000, 123 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T,
125 ETHTOOL_LINK_MODE_10000baseT_Full_BIT); 124 ETHTOOL_LINK_MODE_10000baseT_Full_BIT);
126 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR, SPEED_25000, 125 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR,
127 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT); 126 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT);
128 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_KR, SPEED_25000, 127 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_KR,
129 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT); 128 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT);
130 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_SR, SPEED_25000, 129 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_SR,
131 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT); 130 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT);
132 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_CR2, SPEED_50000, 131 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_CR2,
133 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT); 132 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT);
134 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_KR2, SPEED_50000, 133 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_KR2,
135 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT); 134 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT);
136} 135}
137 136
@@ -617,43 +616,24 @@ static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings
617 } 616 }
618} 617}
619 618
620int mlx5e_get_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
621{
622 u32 max_speed = 0;
623 u32 proto_cap;
624 int err;
625 int i;
626
627 err = mlx5_query_port_proto_cap(mdev, &proto_cap, MLX5_PTYS_EN);
628 if (err)
629 return err;
630
631 for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i)
632 if (proto_cap & MLX5E_PROT_MASK(i))
633 max_speed = max(max_speed, ptys2ethtool_table[i].speed);
634
635 *speed = max_speed;
636 return 0;
637}
638
639static void get_speed_duplex(struct net_device *netdev, 619static void get_speed_duplex(struct net_device *netdev,
640 u32 eth_proto_oper, 620 u32 eth_proto_oper,
641 struct ethtool_link_ksettings *link_ksettings) 621 struct ethtool_link_ksettings *link_ksettings)
642{ 622{
643 int i;
644 u32 speed = SPEED_UNKNOWN; 623 u32 speed = SPEED_UNKNOWN;
645 u8 duplex = DUPLEX_UNKNOWN; 624 u8 duplex = DUPLEX_UNKNOWN;
646 625
647 if (!netif_carrier_ok(netdev)) 626 if (!netif_carrier_ok(netdev))
648 goto out; 627 goto out;
649 628
650 for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { 629 speed = mlx5e_port_ptys2speed(eth_proto_oper);
651 if (eth_proto_oper & MLX5E_PROT_MASK(i)) { 630 if (!speed) {
652 speed = ptys2ethtool_table[i].speed; 631 speed = SPEED_UNKNOWN;
653 duplex = DUPLEX_FULL; 632 goto out;
654 break;
655 }
656 } 633 }
634
635 duplex = DUPLEX_FULL;
636
657out: 637out:
658 link_ksettings->base.speed = speed; 638 link_ksettings->base.speed = speed;
659 link_ksettings->base.duplex = duplex; 639 link_ksettings->base.duplex = duplex;
@@ -811,18 +791,6 @@ static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes)
811 return ptys_modes; 791 return ptys_modes;
812} 792}
813 793
814static u32 mlx5e_ethtool2ptys_speed_link(u32 speed)
815{
816 u32 i, speed_links = 0;
817
818 for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
819 if (ptys2ethtool_table[i].speed == speed)
820 speed_links |= MLX5E_PROT_MASK(i);
821 }
822
823 return speed_links;
824}
825
826static int mlx5e_set_link_ksettings(struct net_device *netdev, 794static int mlx5e_set_link_ksettings(struct net_device *netdev,
827 const struct ethtool_link_ksettings *link_ksettings) 795 const struct ethtool_link_ksettings *link_ksettings)
828{ 796{
@@ -842,7 +810,7 @@ static int mlx5e_set_link_ksettings(struct net_device *netdev,
842 810
843 link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ? 811 link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
844 mlx5e_ethtool2ptys_adver_link(link_ksettings->link_modes.advertising) : 812 mlx5e_ethtool2ptys_adver_link(link_ksettings->link_modes.advertising) :
845 mlx5e_ethtool2ptys_speed_link(speed); 813 mlx5e_port_speed2linkmodes(speed);
846 814
847 err = mlx5_query_port_proto_cap(mdev, &eth_proto_cap, MLX5_PTYS_EN); 815 err = mlx5_query_port_proto_cap(mdev, &eth_proto_cap, MLX5_PTYS_EN);
848 if (err) { 816 if (err) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index b5a7580b12fe..cee44c21766c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -46,6 +46,7 @@
46#include "accel/ipsec.h" 46#include "accel/ipsec.h"
47#include "accel/tls.h" 47#include "accel/tls.h"
48#include "vxlan.h" 48#include "vxlan.h"
49#include "en/port.h"
49 50
50struct mlx5e_rq_param { 51struct mlx5e_rq_param {
51 u32 rqc[MLX5_ST_SZ_DW(rqc)]; 52 u32 rqc[MLX5_ST_SZ_DW(rqc)];
@@ -4082,7 +4083,7 @@ static bool slow_pci_heuristic(struct mlx5_core_dev *mdev)
4082 u32 link_speed = 0; 4083 u32 link_speed = 0;
4083 u32 pci_bw = 0; 4084 u32 pci_bw = 0;
4084 4085
4085 mlx5e_get_max_linkspeed(mdev, &link_speed); 4086 mlx5e_port_max_linkspeed(mdev, &link_speed);
4086 pci_bw = pcie_bandwidth_available(mdev->pdev, NULL, NULL, NULL); 4087 pci_bw = pcie_bandwidth_available(mdev->pdev, NULL, NULL, NULL);
4087 mlx5_core_dbg_once(mdev, "Max link speed = %d, PCI BW = %d\n", 4088 mlx5_core_dbg_once(mdev, "Max link speed = %d, PCI BW = %d\n",
4088 link_speed, pci_bw); 4089 link_speed, pci_bw);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 674f1d7d2737..a9c96fe8e4fe 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -52,6 +52,7 @@
52#include "eswitch.h" 52#include "eswitch.h"
53#include "vxlan.h" 53#include "vxlan.h"
54#include "fs_core.h" 54#include "fs_core.h"
55#include "en/port.h"
55 56
56struct mlx5_nic_flow_attr { 57struct mlx5_nic_flow_attr {
57 u32 action; 58 u32 action;
@@ -613,7 +614,7 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
613 614
614 params.q_counter = priv->q_counter; 615 params.q_counter = priv->q_counter;
615 /* set hairpin pair per each 50Gbs share of the link */ 616 /* set hairpin pair per each 50Gbs share of the link */
616 mlx5e_get_max_linkspeed(priv->mdev, &link_speed); 617 mlx5e_port_max_linkspeed(priv->mdev, &link_speed);
617 link_speed = max_t(u32, link_speed, 50000); 618 link_speed = max_t(u32, link_speed, 50000);
618 link_speed64 = link_speed; 619 link_speed64 = link_speed;
619 do_div(link_speed64, 50000); 620 do_div(link_speed64, 50000);
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index 2bc27f8c5b87..db0332a6d23c 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -1152,6 +1152,9 @@ enum mlx5_qcam_feature_groups {
1152#define MLX5_CAP_PCAM_FEATURE(mdev, fld) \ 1152#define MLX5_CAP_PCAM_FEATURE(mdev, fld) \
1153 MLX5_GET(pcam_reg, (mdev)->caps.pcam, feature_cap_mask.enhanced_features.fld) 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#define MLX5_CAP_MCAM_REG(mdev, reg) \ 1158#define MLX5_CAP_MCAM_REG(mdev, reg) \
1156 MLX5_GET(mcam_reg, (mdev)->caps.mcam, mng_access_reg_cap_mask.access_regs.reg) 1159 MLX5_GET(mcam_reg, (mdev)->caps.mcam, mng_access_reg_cap_mask.access_regs.reg)
1157 1160
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index d703774982ca..92d292454351 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -124,6 +124,8 @@ enum {
124 MLX5_REG_PAOS = 0x5006, 124 MLX5_REG_PAOS = 0x5006,
125 MLX5_REG_PFCC = 0x5007, 125 MLX5_REG_PFCC = 0x5007,
126 MLX5_REG_PPCNT = 0x5008, 126 MLX5_REG_PPCNT = 0x5008,
127 MLX5_REG_PPTB = 0x500b,
128 MLX5_REG_PBMC = 0x500c,
127 MLX5_REG_PMAOS = 0x5012, 129 MLX5_REG_PMAOS = 0x5012,
128 MLX5_REG_PUDE = 0x5009, 130 MLX5_REG_PUDE = 0x5009,
129 MLX5_REG_PMPE = 0x5010, 131 MLX5_REG_PMPE = 0x5010,
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index b4ea8a9914c4..edbddeaacc88 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -8003,6 +8003,17 @@ struct mlx5_ifc_pcam_enhanced_features_bits {
8003 u8 ppcnt_statistical_group[0x1]; 8003 u8 ppcnt_statistical_group[0x1];
8004}; 8004};
8005 8005
8006struct 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
8006struct mlx5_ifc_pcam_reg_bits { 8017struct mlx5_ifc_pcam_reg_bits {
8007 u8 reserved_at_0[0x8]; 8018 u8 reserved_at_0[0x8];
8008 u8 feature_group[0x8]; 8019 u8 feature_group[0x8];
@@ -8012,6 +8023,7 @@ struct mlx5_ifc_pcam_reg_bits {
8012 u8 reserved_at_20[0x20]; 8023 u8 reserved_at_20[0x20];
8013 8024
8014 union { 8025 union {
8026 struct mlx5_ifc_pcam_regs_5000_to_507f_bits regs_5000_to_507f;
8015 u8 reserved_at_0[0x80]; 8027 u8 reserved_at_0[0x80];
8016 } port_access_reg_cap_mask; 8028 } port_access_reg_cap_mask;
8017 8029
@@ -8776,6 +8788,41 @@ struct mlx5_ifc_qpts_reg_bits {
8776 u8 trust_state[0x3]; 8788 u8 trust_state[0x3];
8777}; 8789};
8778 8790
8791struct mlx5_ifc_pptb_reg_bits {
8792 u8 reserved_at_0[0x2];
8793 u8 mm[0x2];
8794 u8 reserved_at_4[0x4];
8795 u8 local_port[0x8];
8796 u8 reserved_at_10[0x6];
8797 u8 cm[0x1];
8798 u8 um[0x1];
8799 u8 pm[0x8];
8800
8801 u8 prio_x_buff[0x20];
8802
8803 u8 pm_msb[0x8];
8804 u8 reserved_at_48[0x10];
8805 u8 ctrl_buff[0x4];
8806 u8 untagged_buff[0x4];
8807};
8808
8809struct mlx5_ifc_pbmc_reg_bits {
8810 u8 reserved_at_0[0x8];
8811 u8 local_port[0x8];
8812 u8 reserved_at_10[0x10];
8813
8814 u8 xoff_timer_value[0x10];
8815 u8 xoff_refresh[0x10];
8816
8817 u8 reserved_at_40[0x9];
8818 u8 fullness_threshold[0x7];
8819 u8 port_buffer_size[0x10];
8820
8821 struct mlx5_ifc_bufferx_reg_bits buffer[10];
8822
8823 u8 reserved_at_2e0[0x40];
8824};
8825
8779struct mlx5_ifc_qtct_reg_bits { 8826struct mlx5_ifc_qtct_reg_bits {
8780 u8 reserved_at_0[0x8]; 8827 u8 reserved_at_0[0x8];
8781 u8 port_number[0x8]; 8828 u8 port_number[0x8];
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h
index 207d9ba1f92c..0e5e91be2d30 100644
--- a/include/net/dcbnl.h
+++ b/include/net/dcbnl.h
@@ -101,6 +101,10 @@ struct dcbnl_rtnl_ops {
101 /* CEE peer */ 101 /* CEE peer */
102 int (*cee_peer_getpg) (struct net_device *, struct cee_pg *); 102 int (*cee_peer_getpg) (struct net_device *, struct cee_pg *);
103 int (*cee_peer_getpfc) (struct net_device *, struct cee_pfc *); 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#endif /* __NET_DCBNL_H__ */ 110#endif /* __NET_DCBNL_H__ */
diff --git a/include/uapi/linux/dcbnl.h b/include/uapi/linux/dcbnl.h
index 2c0c6453c3f4..60aa2e446698 100644
--- a/include/uapi/linux/dcbnl.h
+++ b/include/uapi/linux/dcbnl.h
@@ -163,6 +163,16 @@ struct ieee_pfc {
163 __u64 indications[IEEE_8021QAZ_MAX_TCS]; 163 __u64 indications[IEEE_8021QAZ_MAX_TCS];
164}; 164};
165 165
166#define IEEE_8021Q_MAX_PRIORITIES 8
167#define DCBX_MAX_BUFFERS 8
168struct 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/* CEE DCBX std supported values */ 176/* CEE DCBX std supported values */
167#define CEE_DCBX_MAX_PGS 8 177#define CEE_DCBX_MAX_PGS 8
168#define CEE_DCBX_MAX_PRIO 8 178#define CEE_DCBX_MAX_PRIO 8
@@ -406,6 +416,7 @@ enum ieee_attrs {
406 DCB_ATTR_IEEE_MAXRATE, 416 DCB_ATTR_IEEE_MAXRATE,
407 DCB_ATTR_IEEE_QCN, 417 DCB_ATTR_IEEE_QCN,
408 DCB_ATTR_IEEE_QCN_STATS, 418 DCB_ATTR_IEEE_QCN_STATS,
419 DCB_ATTR_DCB_BUFFER,
409 __DCB_ATTR_IEEE_MAX 420 __DCB_ATTR_IEEE_MAX
410}; 421};
411#define DCB_ATTR_IEEE_MAX (__DCB_ATTR_IEEE_MAX - 1) 422#define DCB_ATTR_IEEE_MAX (__DCB_ATTR_IEEE_MAX - 1)
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index bae7d78aa068..d2f4e0c1faaf 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -176,6 +176,7 @@ static const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = {
176 [DCB_ATTR_IEEE_MAXRATE] = {.len = sizeof(struct ieee_maxrate)}, 176 [DCB_ATTR_IEEE_MAXRATE] = {.len = sizeof(struct ieee_maxrate)},
177 [DCB_ATTR_IEEE_QCN] = {.len = sizeof(struct ieee_qcn)}, 177 [DCB_ATTR_IEEE_QCN] = {.len = sizeof(struct ieee_qcn)},
178 [DCB_ATTR_IEEE_QCN_STATS] = {.len = sizeof(struct ieee_qcn_stats)}, 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/* DCB number of traffic classes nested attributes. */ 182/* DCB number of traffic classes nested attributes. */
@@ -1094,6 +1095,16 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
1094 return -EMSGSIZE; 1095 return -EMSGSIZE;
1095 } 1096 }
1096 1097
1098 if (ops->dcbnl_getbuffer) {
1099 struct dcbnl_buffer buffer;
1100
1101 memset(&buffer, 0, sizeof(buffer));
1102 err = ops->dcbnl_getbuffer(netdev, &buffer);
1103 if (!err &&
1104 nla_put(skb, DCB_ATTR_DCB_BUFFER, sizeof(buffer), &buffer))
1105 return -EMSGSIZE;
1106 }
1107
1097 app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE); 1108 app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
1098 if (!app) 1109 if (!app)
1099 return -EMSGSIZE; 1110 return -EMSGSIZE;
@@ -1453,6 +1464,15 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
1453 goto err; 1464 goto err;
1454 } 1465 }
1455 1466
1467 if (ieee[DCB_ATTR_DCB_BUFFER] && ops->dcbnl_setbuffer) {
1468 struct dcbnl_buffer *buffer =
1469 nla_data(ieee[DCB_ATTR_DCB_BUFFER]);
1470
1471 err = ops->dcbnl_setbuffer(netdev, buffer);
1472 if (err)
1473 goto err;
1474 }
1475
1456 if (ieee[DCB_ATTR_IEEE_APP_TABLE]) { 1476 if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1457 struct nlattr *attr; 1477 struct nlattr *attr;
1458 int rem; 1478 int rem;