hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/ethernet/mellanox/mlx5/core/port.c
....@@ -30,10 +30,7 @@
3030 * SOFTWARE.
3131 */
3232
33
-#include <linux/module.h>
34
-#include <linux/mlx5/driver.h>
3533 #include <linux/mlx5/port.h>
36
-#include <linux/mlx5/cmd.h>
3734 #include "mlx5_core.h"
3835
3936 int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in,
....@@ -157,79 +154,8 @@
157154 sizeof(out), MLX5_REG_MLCR, 0, 1);
158155 }
159156
160
-int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
161
- u32 *proto_cap, int proto_mask)
162
-{
163
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
164
- int err;
165
-
166
- err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
167
- if (err)
168
- return err;
169
-
170
- if (proto_mask == MLX5_PTYS_EN)
171
- *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
172
- else
173
- *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
174
-
175
- return 0;
176
-}
177
-EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
178
-
179
-int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
180
- u32 *proto_admin, int proto_mask)
181
-{
182
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
183
- int err;
184
-
185
- err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
186
- if (err)
187
- return err;
188
-
189
- if (proto_mask == MLX5_PTYS_EN)
190
- *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
191
- else
192
- *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
193
-
194
- return 0;
195
-}
196
-EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
197
-
198
-int mlx5_query_port_link_width_oper(struct mlx5_core_dev *dev,
199
- u8 *link_width_oper, u8 local_port)
200
-{
201
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
202
- int err;
203
-
204
- err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_IB, local_port);
205
- if (err)
206
- return err;
207
-
208
- *link_width_oper = MLX5_GET(ptys_reg, out, ib_link_width_oper);
209
-
210
- return 0;
211
-}
212
-EXPORT_SYMBOL_GPL(mlx5_query_port_link_width_oper);
213
-
214
-int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev,
215
- u32 *proto_oper, u8 local_port)
216
-{
217
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
218
- int err;
219
-
220
- err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN,
221
- local_port);
222
- if (err)
223
- return err;
224
-
225
- *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
226
-
227
- return 0;
228
-}
229
-EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper);
230
-
231
-int mlx5_query_port_ib_proto_oper(struct mlx5_core_dev *dev,
232
- u8 *proto_oper, u8 local_port)
157
+int mlx5_query_ib_port_oper(struct mlx5_core_dev *dev, u16 *link_width_oper,
158
+ u16 *proto_oper, u8 local_port)
233159 {
234160 u32 out[MLX5_ST_SZ_DW(ptys_reg)];
235161 int err;
....@@ -239,40 +165,12 @@
239165 if (err)
240166 return err;
241167
168
+ *link_width_oper = MLX5_GET(ptys_reg, out, ib_link_width_oper);
242169 *proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
243170
244171 return 0;
245172 }
246
-EXPORT_SYMBOL(mlx5_query_port_ib_proto_oper);
247
-
248
-int mlx5_set_port_ptys(struct mlx5_core_dev *dev, bool an_disable,
249
- u32 proto_admin, int proto_mask)
250
-{
251
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
252
- u32 in[MLX5_ST_SZ_DW(ptys_reg)];
253
- u8 an_disable_admin;
254
- u8 an_disable_cap;
255
- u8 an_status;
256
-
257
- mlx5_query_port_autoneg(dev, proto_mask, &an_status,
258
- &an_disable_cap, &an_disable_admin);
259
- if (!an_disable_cap && an_disable)
260
- return -EPERM;
261
-
262
- memset(in, 0, sizeof(in));
263
-
264
- MLX5_SET(ptys_reg, in, local_port, 1);
265
- MLX5_SET(ptys_reg, in, an_disable_admin, an_disable);
266
- MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
267
- if (proto_mask == MLX5_PTYS_EN)
268
- MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
269
- else
270
- MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
271
-
272
- return mlx5_core_access_reg(dev, in, sizeof(in), out,
273
- sizeof(out), MLX5_REG_PTYS, 0, 1);
274
-}
275
-EXPORT_SYMBOL_GPL(mlx5_set_port_ptys);
173
+EXPORT_SYMBOL(mlx5_query_ib_port_oper);
276174
277175 /* This function should be used after setting a port register only */
278176 void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
....@@ -380,35 +278,123 @@
380278 return 0;
381279 }
382280
281
+static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,
282
+ u8 *module_id)
283
+{
284
+ u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
285
+ u32 out[MLX5_ST_SZ_DW(mcia_reg)];
286
+ int err, status;
287
+ u8 *ptr;
288
+
289
+ MLX5_SET(mcia_reg, in, i2c_device_address, MLX5_I2C_ADDR_LOW);
290
+ MLX5_SET(mcia_reg, in, module, module_num);
291
+ MLX5_SET(mcia_reg, in, device_address, 0);
292
+ MLX5_SET(mcia_reg, in, page_number, 0);
293
+ MLX5_SET(mcia_reg, in, size, 1);
294
+ MLX5_SET(mcia_reg, in, l, 0);
295
+
296
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
297
+ sizeof(out), MLX5_REG_MCIA, 0, 0);
298
+ if (err)
299
+ return err;
300
+
301
+ status = MLX5_GET(mcia_reg, out, status);
302
+ if (status) {
303
+ mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n",
304
+ status);
305
+ return -EIO;
306
+ }
307
+ ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
308
+
309
+ *module_id = ptr[0];
310
+
311
+ return 0;
312
+}
313
+
314
+static int mlx5_qsfp_eeprom_page(u16 offset)
315
+{
316
+ if (offset < MLX5_EEPROM_PAGE_LENGTH)
317
+ /* Addresses between 0-255 - page 00 */
318
+ return 0;
319
+
320
+ /* Addresses between 256 - 639 belongs to pages 01, 02 and 03
321
+ * For example, offset = 400 belongs to page 02:
322
+ * 1 + ((400 - 256)/128) = 2
323
+ */
324
+ return 1 + ((offset - MLX5_EEPROM_PAGE_LENGTH) /
325
+ MLX5_EEPROM_HIGH_PAGE_LENGTH);
326
+}
327
+
328
+static int mlx5_qsfp_eeprom_high_page_offset(int page_num)
329
+{
330
+ if (!page_num) /* Page 0 always start from low page */
331
+ return 0;
332
+
333
+ /* High page */
334
+ return page_num * MLX5_EEPROM_HIGH_PAGE_LENGTH;
335
+}
336
+
337
+static void mlx5_qsfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset)
338
+{
339
+ *i2c_addr = MLX5_I2C_ADDR_LOW;
340
+ *page_num = mlx5_qsfp_eeprom_page(*offset);
341
+ *offset -= mlx5_qsfp_eeprom_high_page_offset(*page_num);
342
+}
343
+
344
+static void mlx5_sfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset)
345
+{
346
+ *i2c_addr = MLX5_I2C_ADDR_LOW;
347
+ *page_num = 0;
348
+
349
+ if (*offset < MLX5_EEPROM_PAGE_LENGTH)
350
+ return;
351
+
352
+ *i2c_addr = MLX5_I2C_ADDR_HIGH;
353
+ *offset -= MLX5_EEPROM_PAGE_LENGTH;
354
+}
355
+
383356 int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
384357 u16 offset, u16 size, u8 *data)
385358 {
359
+ int module_num, status, err, page_num = 0;
360
+ u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
386361 u32 out[MLX5_ST_SZ_DW(mcia_reg)];
387
- u32 in[MLX5_ST_SZ_DW(mcia_reg)];
388
- int module_num;
389
- u16 i2c_addr;
390
- int status;
391
- int err;
392
- void *ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
362
+ u16 i2c_addr = 0;
363
+ u8 module_id;
364
+ void *ptr;
393365
394366 err = mlx5_query_module_num(dev, &module_num);
395367 if (err)
396368 return err;
397369
398
- memset(in, 0, sizeof(in));
399
- size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
370
+ err = mlx5_query_module_id(dev, module_num, &module_id);
371
+ if (err)
372
+ return err;
400373
401
- if (offset < MLX5_EEPROM_PAGE_LENGTH &&
402
- offset + size > MLX5_EEPROM_PAGE_LENGTH)
374
+ switch (module_id) {
375
+ case MLX5_MODULE_ID_SFP:
376
+ mlx5_sfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
377
+ break;
378
+ case MLX5_MODULE_ID_QSFP:
379
+ case MLX5_MODULE_ID_QSFP_PLUS:
380
+ case MLX5_MODULE_ID_QSFP28:
381
+ mlx5_qsfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
382
+ break;
383
+ default:
384
+ mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id);
385
+ return -EINVAL;
386
+ }
387
+
388
+ if (offset + size > MLX5_EEPROM_PAGE_LENGTH)
403389 /* Cross pages read, read until offset 256 in low page */
404390 size -= offset + size - MLX5_EEPROM_PAGE_LENGTH;
405391
406
- i2c_addr = MLX5_I2C_ADDR_LOW;
392
+ size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
407393
408394 MLX5_SET(mcia_reg, in, l, 0);
409395 MLX5_SET(mcia_reg, in, module, module_num);
410396 MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
411
- MLX5_SET(mcia_reg, in, page_number, 0);
397
+ MLX5_SET(mcia_reg, in, page_number, page_num);
412398 MLX5_SET(mcia_reg, in, device_address, offset);
413399 MLX5_SET(mcia_reg, in, size, size);
414400
....@@ -424,6 +410,7 @@
424410 return -EIO;
425411 }
426412
413
+ ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
427414 memcpy(data, ptr, size);
428415
429416 return size;
....@@ -601,25 +588,6 @@
601588 return 0;
602589 }
603590 EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
604
-
605
-void mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask,
606
- u8 *an_status,
607
- u8 *an_disable_cap, u8 *an_disable_admin)
608
-{
609
- u32 out[MLX5_ST_SZ_DW(ptys_reg)];
610
-
611
- *an_status = 0;
612
- *an_disable_cap = 0;
613
- *an_disable_admin = 0;
614
-
615
- if (mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1))
616
- return;
617
-
618
- *an_status = MLX5_GET(ptys_reg, out, an_status);
619
- *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
620
- *an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
621
-}
622
-EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
623591
624592 int mlx5_max_tc(struct mlx5_core_dev *mdev)
625593 {
....@@ -841,24 +809,23 @@
841809
842810 int mlx5_set_port_wol(struct mlx5_core_dev *mdev, u8 wol_mode)
843811 {
844
- u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {0};
845
- u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)] = {0};
812
+ u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {};
846813
847814 MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
848815 MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
849816 MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
850
- return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
817
+ return mlx5_cmd_exec_in(mdev, set_wol_rol, in);
851818 }
852819 EXPORT_SYMBOL_GPL(mlx5_set_port_wol);
853820
854821 int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode)
855822 {
856
- u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {0};
857
- u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {0};
823
+ u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {};
824
+ u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {};
858825 int err;
859826
860827 MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
861
- err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
828
+ err = mlx5_cmd_exec_inout(mdev, query_wol_rol, in, out);
862829 if (!err)
863830 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
864831
....@@ -866,8 +833,7 @@
866833 }
867834 EXPORT_SYMBOL_GPL(mlx5_query_port_wol);
868835
869
-static int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out,
870
- int outlen)
836
+int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out, int outlen)
871837 {
872838 u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0};
873839
....@@ -876,7 +842,7 @@
876842 outlen, MLX5_REG_PCMR, 0, 0);
877843 }
878844
879
-static int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen)
845
+int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen)
880846 {
881847 u32 out[MLX5_ST_SZ_DW(pcmr_reg)];
882848
....@@ -887,7 +853,11 @@
887853 int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable)
888854 {
889855 u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0};
856
+ int err;
890857
858
+ err = mlx5_query_ports_check(mdev, in, sizeof(in));
859
+ if (err)
860
+ return err;
891861 MLX5_SET(pcmr_reg, in, local_port, 1);
892862 MLX5_SET(pcmr_reg, in, fcs_chk, enable);
893863 return mlx5_set_ports_check(mdev, in, sizeof(in));
....@@ -909,63 +879,6 @@
909879
910880 *supported = !!(MLX5_GET(pcmr_reg, out, fcs_cap));
911881 *enabled = !!(MLX5_GET(pcmr_reg, out, fcs_chk));
912
-}
913
-
914
-static const char *mlx5_pme_status[MLX5_MODULE_STATUS_NUM] = {
915
- "Cable plugged", /* MLX5_MODULE_STATUS_PLUGGED = 0x1 */
916
- "Cable unplugged", /* MLX5_MODULE_STATUS_UNPLUGGED = 0x2 */
917
- "Cable error", /* MLX5_MODULE_STATUS_ERROR = 0x3 */
918
-};
919
-
920
-static const char *mlx5_pme_error[MLX5_MODULE_EVENT_ERROR_NUM] = {
921
- "Power budget exceeded",
922
- "Long Range for non MLNX cable",
923
- "Bus stuck(I2C or data shorted)",
924
- "No EEPROM/retry timeout",
925
- "Enforce part number list",
926
- "Unknown identifier",
927
- "High Temperature",
928
- "Bad or shorted cable/module",
929
- "Unknown status",
930
-};
931
-
932
-void mlx5_port_module_event(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe)
933
-{
934
- enum port_module_event_status_type module_status;
935
- enum port_module_event_error_type error_type;
936
- struct mlx5_eqe_port_module *module_event_eqe;
937
- struct mlx5_priv *priv = &dev->priv;
938
- u8 module_num;
939
-
940
- module_event_eqe = &eqe->data.port_module;
941
- module_num = module_event_eqe->module;
942
- module_status = module_event_eqe->module_status &
943
- PORT_MODULE_EVENT_MODULE_STATUS_MASK;
944
- error_type = module_event_eqe->error_type &
945
- PORT_MODULE_EVENT_ERROR_TYPE_MASK;
946
-
947
- if (module_status < MLX5_MODULE_STATUS_ERROR) {
948
- priv->pme_stats.status_counters[module_status - 1]++;
949
- } else if (module_status == MLX5_MODULE_STATUS_ERROR) {
950
- if (error_type >= MLX5_MODULE_EVENT_ERROR_UNKNOWN)
951
- /* Unknown error type */
952
- error_type = MLX5_MODULE_EVENT_ERROR_UNKNOWN;
953
- priv->pme_stats.error_counters[error_type]++;
954
- }
955
-
956
- if (!printk_ratelimit())
957
- return;
958
-
959
- if (module_status < MLX5_MODULE_STATUS_ERROR)
960
- mlx5_core_info(dev,
961
- "Port module event: module %u, %s\n",
962
- module_num, mlx5_pme_status[module_status - 1]);
963
-
964
- else if (module_status == MLX5_MODULE_STATUS_ERROR)
965
- mlx5_core_info(dev,
966
- "Port module event[error]: module %u, %s, %s\n",
967
- module_num, mlx5_pme_status[module_status - 1],
968
- mlx5_pme_error[error_type]);
969882 }
970883
971884 int mlx5_query_mtpps(struct mlx5_core_dev *mdev, u32 *mtpps, u32 mtpps_size)