summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;