diff options
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/Makefile | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en.h | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en/port.c | 237 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en/port.h | 48 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c | 327 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h | 75 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 132 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 102 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 3 | ||||
-rw-r--r-- | include/linux/mlx5/device.h | 3 | ||||
-rw-r--r-- | include/linux/mlx5/driver.h | 2 | ||||
-rw-r--r-- | include/linux/mlx5/mlx5_ifc.h | 47 | ||||
-rw-r--r-- | include/net/dcbnl.h | 4 | ||||
-rw-r--r-- | include/uapi/linux/dcbnl.h | 11 | ||||
-rw-r--r-- | net/dcb/dcbnl.c | 20 |
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 | ||
16 | mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \ | 16 | mlx5_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 | ||
20 | mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o | 20 | mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o |
21 | 21 | ||
22 | mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o en_rep.o en_tc.o | 22 | mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o en_rep.o en_tc.o |
23 | 23 | ||
24 | mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o | 24 | mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o |
25 | 25 | ||
26 | mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o ipoib/ipoib_vlan.o | 26 | mlx5_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 | ||
280 | struct mlx5e_dcbx_dp { | 286 | struct mlx5e_dcbx_dp { |
@@ -932,8 +938,6 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv); | |||
932 | 938 | ||
933 | void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len, | 939 | void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len, |
934 | int num_channels); | 940 | int num_channels); |
935 | int mlx5e_get_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); | ||
936 | |||
937 | void mlx5e_set_tx_cq_mode_params(struct mlx5e_params *params, | 941 | void mlx5e_set_tx_cq_mode_params(struct mlx5e_params *params, |
938 | u8 cq_period_mode); | 942 | u8 cq_period_mode); |
939 | void mlx5e_set_rx_cq_mode_params(struct mlx5e_params *params, | 943 | void 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 */ | ||
36 | static const u32 mlx5e_link_speed[MLX5E_LINK_MODES_NUMBER] = { | ||
37 | [MLX5E_1000BASE_CX_SGMII] = 1000, | ||
38 | [MLX5E_1000BASE_KX] = 1000, | ||
39 | [MLX5E_10GBASE_CX4] = 10000, | ||
40 | [MLX5E_10GBASE_KX4] = 10000, | ||
41 | [MLX5E_10GBASE_KR] = 10000, | ||
42 | [MLX5E_20GBASE_KR2] = 20000, | ||
43 | [MLX5E_40GBASE_CR4] = 40000, | ||
44 | [MLX5E_40GBASE_KR4] = 40000, | ||
45 | [MLX5E_56GBASE_R4] = 56000, | ||
46 | [MLX5E_10GBASE_CR] = 10000, | ||
47 | [MLX5E_10GBASE_SR] = 10000, | ||
48 | [MLX5E_10GBASE_ER] = 10000, | ||
49 | [MLX5E_40GBASE_SR4] = 40000, | ||
50 | [MLX5E_40GBASE_LR4] = 40000, | ||
51 | [MLX5E_50GBASE_SR2] = 50000, | ||
52 | [MLX5E_100GBASE_CR4] = 100000, | ||
53 | [MLX5E_100GBASE_SR4] = 100000, | ||
54 | [MLX5E_100GBASE_KR4] = 100000, | ||
55 | [MLX5E_100GBASE_LR4] = 100000, | ||
56 | [MLX5E_100BASE_TX] = 100, | ||
57 | [MLX5E_1000BASE_T] = 1000, | ||
58 | [MLX5E_10GBASE_T] = 10000, | ||
59 | [MLX5E_25GBASE_CR] = 25000, | ||
60 | [MLX5E_25GBASE_KR] = 25000, | ||
61 | [MLX5E_25GBASE_SR] = 25000, | ||
62 | [MLX5E_50GBASE_CR2] = 50000, | ||
63 | [MLX5E_50GBASE_KR2] = 50000, | ||
64 | }; | ||
65 | |||
66 | u32 mlx5e_port_ptys2speed(u32 eth_proto_oper) | ||
67 | { | ||
68 | unsigned long temp = eth_proto_oper; | ||
69 | u32 speed = 0; | ||
70 | int i; | ||
71 | |||
72 | i = find_first_bit(&temp, MLX5E_LINK_MODES_NUMBER); | ||
73 | if (i < MLX5E_LINK_MODES_NUMBER) | ||
74 | speed = mlx5e_link_speed[i]; | ||
75 | |||
76 | return speed; | ||
77 | } | ||
78 | |||
79 | int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) | ||
80 | { | ||
81 | u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {}; | ||
82 | u32 eth_proto_oper; | ||
83 | int err; | ||
84 | |||
85 | err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1); | ||
86 | if (err) | ||
87 | return err; | ||
88 | |||
89 | eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); | ||
90 | *speed = mlx5e_port_ptys2speed(eth_proto_oper); | ||
91 | if (!(*speed)) { | ||
92 | mlx5_core_warn(mdev, "cannot get port speed\n"); | ||
93 | err = -EINVAL; | ||
94 | } | ||
95 | |||
96 | return err; | ||
97 | } | ||
98 | |||
99 | int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) | ||
100 | { | ||
101 | u32 max_speed = 0; | ||
102 | u32 proto_cap; | ||
103 | int err; | ||
104 | int i; | ||
105 | |||
106 | err = mlx5_query_port_proto_cap(mdev, &proto_cap, MLX5_PTYS_EN); | ||
107 | if (err) | ||
108 | return err; | ||
109 | |||
110 | for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) | ||
111 | if (proto_cap & MLX5E_PROT_MASK(i)) | ||
112 | max_speed = max(max_speed, mlx5e_link_speed[i]); | ||
113 | |||
114 | *speed = max_speed; | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | u32 mlx5e_port_speed2linkmodes(u32 speed) | ||
119 | { | ||
120 | u32 link_modes = 0; | ||
121 | int i; | ||
122 | |||
123 | for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { | ||
124 | if (mlx5e_link_speed[i] == speed) | ||
125 | link_modes |= MLX5E_PROT_MASK(i); | ||
126 | } | ||
127 | |||
128 | return link_modes; | ||
129 | } | ||
130 | |||
131 | int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out) | ||
132 | { | ||
133 | int sz = MLX5_ST_SZ_BYTES(pbmc_reg); | ||
134 | void *in; | ||
135 | int err; | ||
136 | |||
137 | in = kzalloc(sz, GFP_KERNEL); | ||
138 | if (!in) | ||
139 | return -ENOMEM; | ||
140 | |||
141 | MLX5_SET(pbmc_reg, in, local_port, 1); | ||
142 | err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 0); | ||
143 | |||
144 | kfree(in); | ||
145 | return err; | ||
146 | } | ||
147 | |||
148 | int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in) | ||
149 | { | ||
150 | int sz = MLX5_ST_SZ_BYTES(pbmc_reg); | ||
151 | void *out; | ||
152 | int err; | ||
153 | |||
154 | out = kzalloc(sz, GFP_KERNEL); | ||
155 | if (!out) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | MLX5_SET(pbmc_reg, in, local_port, 1); | ||
159 | err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 1); | ||
160 | |||
161 | kfree(out); | ||
162 | return err; | ||
163 | } | ||
164 | |||
165 | /* buffer[i]: buffer that priority i mapped to */ | ||
166 | int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer) | ||
167 | { | ||
168 | int sz = MLX5_ST_SZ_BYTES(pptb_reg); | ||
169 | u32 prio_x_buff; | ||
170 | void *out; | ||
171 | void *in; | ||
172 | int prio; | ||
173 | int err; | ||
174 | |||
175 | in = kzalloc(sz, GFP_KERNEL); | ||
176 | out = kzalloc(sz, GFP_KERNEL); | ||
177 | if (!in || !out) { | ||
178 | err = -ENOMEM; | ||
179 | goto out; | ||
180 | } | ||
181 | |||
182 | MLX5_SET(pptb_reg, in, local_port, 1); | ||
183 | err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0); | ||
184 | if (err) | ||
185 | goto out; | ||
186 | |||
187 | prio_x_buff = MLX5_GET(pptb_reg, out, prio_x_buff); | ||
188 | for (prio = 0; prio < 8; prio++) { | ||
189 | buffer[prio] = (u8)(prio_x_buff >> (4 * prio)) & 0xF; | ||
190 | mlx5_core_dbg(mdev, "prio %d, buffer %d\n", prio, buffer[prio]); | ||
191 | } | ||
192 | out: | ||
193 | kfree(in); | ||
194 | kfree(out); | ||
195 | return err; | ||
196 | } | ||
197 | |||
198 | int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer) | ||
199 | { | ||
200 | int sz = MLX5_ST_SZ_BYTES(pptb_reg); | ||
201 | u32 prio_x_buff; | ||
202 | void *out; | ||
203 | void *in; | ||
204 | int prio; | ||
205 | int err; | ||
206 | |||
207 | in = kzalloc(sz, GFP_KERNEL); | ||
208 | out = kzalloc(sz, GFP_KERNEL); | ||
209 | if (!in || !out) { | ||
210 | err = -ENOMEM; | ||
211 | goto out; | ||
212 | } | ||
213 | |||
214 | /* First query the pptb register */ | ||
215 | MLX5_SET(pptb_reg, in, local_port, 1); | ||
216 | err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0); | ||
217 | if (err) | ||
218 | goto out; | ||
219 | |||
220 | memcpy(in, out, sz); | ||
221 | MLX5_SET(pptb_reg, in, local_port, 1); | ||
222 | |||
223 | /* Update the pm and prio_x_buff */ | ||
224 | MLX5_SET(pptb_reg, in, pm, 0xFF); | ||
225 | |||
226 | prio_x_buff = 0; | ||
227 | for (prio = 0; prio < 8; prio++) | ||
228 | prio_x_buff |= (buffer[prio] << (4 * prio)); | ||
229 | MLX5_SET(pptb_reg, in, prio_x_buff, prio_x_buff); | ||
230 | |||
231 | err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1); | ||
232 | |||
233 | out: | ||
234 | kfree(in); | ||
235 | kfree(out); | ||
236 | return err; | ||
237 | } | ||
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 | |||
39 | u32 mlx5e_port_ptys2speed(u32 eth_proto_oper); | ||
40 | int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); | ||
41 | int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); | ||
42 | u32 mlx5e_port_speed2linkmodes(u32 speed); | ||
43 | |||
44 | int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out); | ||
45 | int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in); | ||
46 | int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer); | ||
47 | int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer); | ||
48 | #endif | ||
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 | |||
34 | int mlx5e_port_query_buffer(struct mlx5e_priv *priv, | ||
35 | struct mlx5e_port_buffer *port_buffer) | ||
36 | { | ||
37 | struct mlx5_core_dev *mdev = priv->mdev; | ||
38 | int sz = MLX5_ST_SZ_BYTES(pbmc_reg); | ||
39 | u32 total_used = 0; | ||
40 | void *buffer; | ||
41 | void *out; | ||
42 | int err; | ||
43 | int i; | ||
44 | |||
45 | out = kzalloc(sz, GFP_KERNEL); | ||
46 | if (!out) | ||
47 | return -ENOMEM; | ||
48 | |||
49 | err = mlx5e_port_query_pbmc(mdev, out); | ||
50 | if (err) | ||
51 | goto out; | ||
52 | |||
53 | for (i = 0; i < MLX5E_MAX_BUFFER; i++) { | ||
54 | buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]); | ||
55 | port_buffer->buffer[i].lossy = | ||
56 | MLX5_GET(bufferx_reg, buffer, lossy); | ||
57 | port_buffer->buffer[i].epsb = | ||
58 | MLX5_GET(bufferx_reg, buffer, epsb); | ||
59 | port_buffer->buffer[i].size = | ||
60 | MLX5_GET(bufferx_reg, buffer, size) << MLX5E_BUFFER_CELL_SHIFT; | ||
61 | port_buffer->buffer[i].xon = | ||
62 | MLX5_GET(bufferx_reg, buffer, xon_threshold) << MLX5E_BUFFER_CELL_SHIFT; | ||
63 | port_buffer->buffer[i].xoff = | ||
64 | MLX5_GET(bufferx_reg, buffer, xoff_threshold) << MLX5E_BUFFER_CELL_SHIFT; | ||
65 | total_used += port_buffer->buffer[i].size; | ||
66 | |||
67 | mlx5e_dbg(HW, priv, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", i, | ||
68 | port_buffer->buffer[i].size, | ||
69 | port_buffer->buffer[i].xon, | ||
70 | port_buffer->buffer[i].xoff, | ||
71 | port_buffer->buffer[i].epsb, | ||
72 | port_buffer->buffer[i].lossy); | ||
73 | } | ||
74 | |||
75 | port_buffer->port_buffer_size = | ||
76 | MLX5_GET(pbmc_reg, out, port_buffer_size) << MLX5E_BUFFER_CELL_SHIFT; | ||
77 | port_buffer->spare_buffer_size = | ||
78 | port_buffer->port_buffer_size - total_used; | ||
79 | |||
80 | mlx5e_dbg(HW, priv, "total buffer size=%d, spare buffer size=%d\n", | ||
81 | port_buffer->port_buffer_size, | ||
82 | port_buffer->spare_buffer_size); | ||
83 | out: | ||
84 | kfree(out); | ||
85 | return err; | ||
86 | } | ||
87 | |||
88 | static int port_set_buffer(struct mlx5e_priv *priv, | ||
89 | struct mlx5e_port_buffer *port_buffer) | ||
90 | { | ||
91 | struct mlx5_core_dev *mdev = priv->mdev; | ||
92 | int sz = MLX5_ST_SZ_BYTES(pbmc_reg); | ||
93 | void *buffer; | ||
94 | void *in; | ||
95 | int err; | ||
96 | int i; | ||
97 | |||
98 | in = kzalloc(sz, GFP_KERNEL); | ||
99 | if (!in) | ||
100 | return -ENOMEM; | ||
101 | |||
102 | err = mlx5e_port_query_pbmc(mdev, in); | ||
103 | if (err) | ||
104 | goto out; | ||
105 | |||
106 | for (i = 0; i < MLX5E_MAX_BUFFER; i++) { | ||
107 | buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]); | ||
108 | |||
109 | MLX5_SET(bufferx_reg, buffer, size, | ||
110 | port_buffer->buffer[i].size >> MLX5E_BUFFER_CELL_SHIFT); | ||
111 | MLX5_SET(bufferx_reg, buffer, lossy, | ||
112 | port_buffer->buffer[i].lossy); | ||
113 | MLX5_SET(bufferx_reg, buffer, xoff_threshold, | ||
114 | port_buffer->buffer[i].xoff >> MLX5E_BUFFER_CELL_SHIFT); | ||
115 | MLX5_SET(bufferx_reg, buffer, xon_threshold, | ||
116 | port_buffer->buffer[i].xon >> MLX5E_BUFFER_CELL_SHIFT); | ||
117 | } | ||
118 | |||
119 | err = mlx5e_port_set_pbmc(mdev, in); | ||
120 | out: | ||
121 | kfree(in); | ||
122 | return err; | ||
123 | } | ||
124 | |||
125 | /* xoff = ((301+2.16 * len [m]) * speed [Gbps] + 2.72 MTU [B]) */ | ||
126 | static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu) | ||
127 | { | ||
128 | u32 speed; | ||
129 | u32 xoff; | ||
130 | int err; | ||
131 | |||
132 | err = mlx5e_port_linkspeed(priv->mdev, &speed); | ||
133 | if (err) | ||
134 | return 0; | ||
135 | |||
136 | xoff = (301 + 216 * priv->dcbx.cable_len / 100) * speed / 1000 + 272 * mtu / 100; | ||
137 | |||
138 | mlx5e_dbg(HW, priv, "%s: xoff=%d\n", __func__, xoff); | ||
139 | return xoff; | ||
140 | } | ||
141 | |||
142 | static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer, | ||
143 | u32 xoff, unsigned int mtu) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | for (i = 0; i < MLX5E_MAX_BUFFER; i++) { | ||
148 | if (port_buffer->buffer[i].lossy) { | ||
149 | port_buffer->buffer[i].xoff = 0; | ||
150 | port_buffer->buffer[i].xon = 0; | ||
151 | continue; | ||
152 | } | ||
153 | |||
154 | if (port_buffer->buffer[i].size < | ||
155 | (xoff + mtu + (1 << MLX5E_BUFFER_CELL_SHIFT))) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | port_buffer->buffer[i].xoff = port_buffer->buffer[i].size - xoff; | ||
159 | port_buffer->buffer[i].xon = port_buffer->buffer[i].xoff - mtu; | ||
160 | } | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * update_buffer_lossy() | ||
167 | * mtu: device's MTU | ||
168 | * pfc_en: <input> current pfc configuration | ||
169 | * buffer: <input> current prio to buffer mapping | ||
170 | * xoff: <input> xoff value | ||
171 | * port_buffer: <output> port receive buffer configuration | ||
172 | * change: <output> | ||
173 | * | ||
174 | * Update buffer configuration based on pfc configuraiton and priority | ||
175 | * to buffer mapping. | ||
176 | * Buffer's lossy bit is changed to: | ||
177 | * lossless if there is at least one PFC enabled priority mapped to this buffer | ||
178 | * lossy if all priorities mapped to this buffer are PFC disabled | ||
179 | * | ||
180 | * Return: | ||
181 | * Return 0 if no error. | ||
182 | * Set change to true if buffer configuration is modified. | ||
183 | */ | ||
184 | static int update_buffer_lossy(unsigned int mtu, | ||
185 | u8 pfc_en, u8 *buffer, u32 xoff, | ||
186 | struct mlx5e_port_buffer *port_buffer, | ||
187 | bool *change) | ||
188 | { | ||
189 | bool changed = false; | ||
190 | u8 lossy_count; | ||
191 | u8 prio_count; | ||
192 | u8 lossy; | ||
193 | int prio; | ||
194 | int err; | ||
195 | int i; | ||
196 | |||
197 | for (i = 0; i < MLX5E_MAX_BUFFER; i++) { | ||
198 | prio_count = 0; | ||
199 | lossy_count = 0; | ||
200 | |||
201 | for (prio = 0; prio < MLX5E_MAX_PRIORITY; prio++) { | ||
202 | if (buffer[prio] != i) | ||
203 | continue; | ||
204 | |||
205 | prio_count++; | ||
206 | lossy_count += !(pfc_en & (1 << prio)); | ||
207 | } | ||
208 | |||
209 | if (lossy_count == prio_count) | ||
210 | lossy = 1; | ||
211 | else /* lossy_count < prio_count */ | ||
212 | lossy = 0; | ||
213 | |||
214 | if (lossy != port_buffer->buffer[i].lossy) { | ||
215 | port_buffer->buffer[i].lossy = lossy; | ||
216 | changed = true; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | if (changed) { | ||
221 | err = update_xoff_threshold(port_buffer, xoff, mtu); | ||
222 | if (err) | ||
223 | return err; | ||
224 | |||
225 | *change = true; | ||
226 | } | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, | ||
232 | u32 change, unsigned int mtu, | ||
233 | struct ieee_pfc *pfc, | ||
234 | u32 *buffer_size, | ||
235 | u8 *prio2buffer) | ||
236 | { | ||
237 | struct mlx5e_port_buffer port_buffer; | ||
238 | u32 xoff = calculate_xoff(priv, mtu); | ||
239 | bool update_prio2buffer = false; | ||
240 | u8 buffer[MLX5E_MAX_PRIORITY]; | ||
241 | bool update_buffer = false; | ||
242 | u32 total_used = 0; | ||
243 | u8 curr_pfc_en; | ||
244 | int err; | ||
245 | int i; | ||
246 | |||
247 | mlx5e_dbg(HW, priv, "%s: change=%x\n", __func__, change); | ||
248 | |||
249 | err = mlx5e_port_query_buffer(priv, &port_buffer); | ||
250 | if (err) | ||
251 | return err; | ||
252 | |||
253 | if (change & MLX5E_PORT_BUFFER_CABLE_LEN) { | ||
254 | update_buffer = true; | ||
255 | err = update_xoff_threshold(&port_buffer, xoff, mtu); | ||
256 | if (err) | ||
257 | return err; | ||
258 | } | ||
259 | |||
260 | if (change & MLX5E_PORT_BUFFER_PFC) { | ||
261 | err = mlx5e_port_query_priority2buffer(priv->mdev, buffer); | ||
262 | if (err) | ||
263 | return err; | ||
264 | |||
265 | err = update_buffer_lossy(mtu, pfc->pfc_en, buffer, xoff, | ||
266 | &port_buffer, &update_buffer); | ||
267 | if (err) | ||
268 | return err; | ||
269 | } | ||
270 | |||
271 | if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) { | ||
272 | update_prio2buffer = true; | ||
273 | err = mlx5_query_port_pfc(priv->mdev, &curr_pfc_en, NULL); | ||
274 | if (err) | ||
275 | return err; | ||
276 | |||
277 | err = update_buffer_lossy(mtu, curr_pfc_en, prio2buffer, xoff, | ||
278 | &port_buffer, &update_buffer); | ||
279 | if (err) | ||
280 | return err; | ||
281 | } | ||
282 | |||
283 | if (change & MLX5E_PORT_BUFFER_SIZE) { | ||
284 | for (i = 0; i < MLX5E_MAX_BUFFER; i++) { | ||
285 | mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]); | ||
286 | if (!port_buffer.buffer[i].lossy && !buffer_size[i]) { | ||
287 | mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n", | ||
288 | __func__, i); | ||
289 | return -EINVAL; | ||
290 | } | ||
291 | |||
292 | port_buffer.buffer[i].size = buffer_size[i]; | ||
293 | total_used += buffer_size[i]; | ||
294 | } | ||
295 | |||
296 | mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used); | ||
297 | |||
298 | if (total_used > port_buffer.port_buffer_size) | ||
299 | return -EINVAL; | ||
300 | |||
301 | update_buffer = true; | ||
302 | err = update_xoff_threshold(&port_buffer, xoff, mtu); | ||
303 | if (err) | ||
304 | return err; | ||
305 | } | ||
306 | |||
307 | /* Need to update buffer configuration if xoff value is changed */ | ||
308 | if (!update_buffer && xoff != priv->dcbx.xoff) { | ||
309 | update_buffer = true; | ||
310 | err = update_xoff_threshold(&port_buffer, xoff, mtu); | ||
311 | if (err) | ||
312 | return err; | ||
313 | } | ||
314 | priv->dcbx.xoff = xoff; | ||
315 | |||
316 | /* Apply the settings */ | ||
317 | if (update_buffer) { | ||
318 | err = port_set_buffer(priv, &port_buffer); | ||
319 | if (err) | ||
320 | return err; | ||
321 | } | ||
322 | |||
323 | if (update_prio2buffer) | ||
324 | err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); | ||
325 | |||
326 | return err; | ||
327 | } | ||
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 | |||
46 | enum { | ||
47 | MLX5E_PORT_BUFFER_CABLE_LEN = BIT(0), | ||
48 | MLX5E_PORT_BUFFER_PFC = BIT(1), | ||
49 | MLX5E_PORT_BUFFER_PRIO2BUFFER = BIT(2), | ||
50 | MLX5E_PORT_BUFFER_SIZE = BIT(3), | ||
51 | }; | ||
52 | |||
53 | struct mlx5e_bufferx_reg { | ||
54 | u8 lossy; | ||
55 | u8 epsb; | ||
56 | u32 size; | ||
57 | u32 xoff; | ||
58 | u32 xon; | ||
59 | }; | ||
60 | |||
61 | struct mlx5e_port_buffer { | ||
62 | u32 port_buffer_size; | ||
63 | u32 spare_buffer_size; | ||
64 | struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER]; | ||
65 | }; | ||
66 | |||
67 | int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, | ||
68 | u32 change, unsigned int mtu, | ||
69 | struct ieee_pfc *pfc, | ||
70 | u32 *buffer_size, | ||
71 | u8 *prio2buffer); | ||
72 | |||
73 | int mlx5e_port_query_buffer(struct mlx5e_priv *priv, | ||
74 | struct mlx5e_port_buffer *port_buffer); | ||
75 | #endif | ||
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 | |||
44 | enum { | 47 | enum { |
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 | ||
905 | static 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 | |||
935 | static 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 | |||
876 | const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = { | 989 | const 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 | ||
35 | void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv, | 36 | void 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, | |||
59 | struct ptys2ethtool_config { | 60 | struct 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 | ||
65 | static struct ptys2ethtool_config ptys2ethtool_table[MLX5E_LINK_MODES_NUMBER]; | 65 | static 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 | ||
84 | void mlx5e_build_ptys2ethtool_map(void) | 83 | void 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 | ||
620 | int 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 | |||
639 | static void get_speed_duplex(struct net_device *netdev, | 619 | static 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 | |||
657 | out: | 637 | out: |
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 | ||
814 | static 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 | |||
826 | static int mlx5e_set_link_ksettings(struct net_device *netdev, | 794 | static 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, ð_proto_cap, MLX5_PTYS_EN); | 815 | err = mlx5_query_port_proto_cap(mdev, ð_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 | ||
50 | struct mlx5e_rq_param { | 51 | struct 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 | ||
56 | struct mlx5_nic_flow_attr { | 57 | struct 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 | ||
8006 | struct mlx5_ifc_pcam_regs_5000_to_507f_bits { | ||
8007 | u8 port_access_reg_cap_mask_127_to_96[0x20]; | ||
8008 | u8 port_access_reg_cap_mask_95_to_64[0x20]; | ||
8009 | u8 port_access_reg_cap_mask_63_to_32[0x20]; | ||
8010 | |||
8011 | u8 port_access_reg_cap_mask_31_to_13[0x13]; | ||
8012 | u8 pbmc[0x1]; | ||
8013 | u8 pptb[0x1]; | ||
8014 | u8 port_access_reg_cap_mask_10_to_0[0xb]; | ||
8015 | }; | ||
8016 | |||
8006 | struct mlx5_ifc_pcam_reg_bits { | 8017 | struct 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 | ||
8791 | struct 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 | |||
8809 | struct 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 | |||
8779 | struct mlx5_ifc_qtct_reg_bits { | 8826 | struct 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 | ||
168 | struct dcbnl_buffer { | ||
169 | /* priority to buffer mapping */ | ||
170 | __u8 prio2buffer[IEEE_8021Q_MAX_PRIORITIES]; | ||
171 | /* buffer size in Bytes */ | ||
172 | __u32 buffer_size[DCBX_MAX_BUFFERS]; | ||
173 | __u32 total_size; | ||
174 | }; | ||
175 | |||
166 | /* 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; |