forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
....@@ -63,66 +63,193 @@
6363 [MLX5E_50GBASE_KR2] = 50000,
6464 };
6565
66
-u32 mlx5e_port_ptys2speed(u32 eth_proto_oper)
66
+static const u32 mlx5e_ext_link_speed[MLX5E_EXT_LINK_MODES_NUMBER] = {
67
+ [MLX5E_SGMII_100M] = 100,
68
+ [MLX5E_1000BASE_X_SGMII] = 1000,
69
+ [MLX5E_5GBASE_R] = 5000,
70
+ [MLX5E_10GBASE_XFI_XAUI_1] = 10000,
71
+ [MLX5E_40GBASE_XLAUI_4_XLPPI_4] = 40000,
72
+ [MLX5E_25GAUI_1_25GBASE_CR_KR] = 25000,
73
+ [MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2] = 50000,
74
+ [MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR] = 50000,
75
+ [MLX5E_CAUI_4_100GBASE_CR4_KR4] = 100000,
76
+ [MLX5E_100GAUI_2_100GBASE_CR2_KR2] = 100000,
77
+ [MLX5E_200GAUI_4_200GBASE_CR4_KR4] = 200000,
78
+ [MLX5E_400GAUI_8] = 400000,
79
+ [MLX5E_100GAUI_1_100GBASE_CR_KR] = 100000,
80
+ [MLX5E_200GAUI_2_200GBASE_CR2_KR2] = 200000,
81
+ [MLX5E_400GAUI_4_400GBASE_CR4_KR4] = 400000,
82
+};
83
+
84
+bool mlx5e_ptys_ext_supported(struct mlx5_core_dev *mdev)
85
+{
86
+ struct mlx5e_port_eth_proto eproto;
87
+ int err;
88
+
89
+ if (MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet))
90
+ return true;
91
+
92
+ err = mlx5_port_query_eth_proto(mdev, 1, true, &eproto);
93
+ if (err)
94
+ return false;
95
+
96
+ return !!eproto.cap;
97
+}
98
+
99
+static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
100
+ const u32 **arr, u32 *size,
101
+ bool force_legacy)
102
+{
103
+ bool ext = force_legacy ? false : mlx5e_ptys_ext_supported(mdev);
104
+
105
+ *size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
106
+ ARRAY_SIZE(mlx5e_link_speed);
107
+ *arr = ext ? mlx5e_ext_link_speed : mlx5e_link_speed;
108
+}
109
+
110
+int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
111
+ struct mlx5e_port_eth_proto *eproto)
112
+{
113
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
114
+ int err;
115
+
116
+ if (!eproto)
117
+ return -EINVAL;
118
+
119
+ err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
120
+ if (err)
121
+ return err;
122
+
123
+ eproto->cap = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
124
+ eth_proto_capability);
125
+ eproto->admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_admin);
126
+ eproto->oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper);
127
+ return 0;
128
+}
129
+
130
+void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status,
131
+ u8 *an_disable_cap, u8 *an_disable_admin)
132
+{
133
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
134
+
135
+ *an_status = 0;
136
+ *an_disable_cap = 0;
137
+ *an_disable_admin = 0;
138
+
139
+ if (mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, 1))
140
+ return;
141
+
142
+ *an_status = MLX5_GET(ptys_reg, out, an_status);
143
+ *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
144
+ *an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
145
+}
146
+
147
+int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
148
+ u32 proto_admin, bool ext)
149
+{
150
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
151
+ u32 in[MLX5_ST_SZ_DW(ptys_reg)];
152
+ u8 an_disable_admin;
153
+ u8 an_disable_cap;
154
+ u8 an_status;
155
+
156
+ mlx5_port_query_eth_autoneg(dev, &an_status, &an_disable_cap,
157
+ &an_disable_admin);
158
+ if (!an_disable_cap && an_disable)
159
+ return -EPERM;
160
+
161
+ memset(in, 0, sizeof(in));
162
+
163
+ MLX5_SET(ptys_reg, in, local_port, 1);
164
+ MLX5_SET(ptys_reg, in, an_disable_admin, an_disable);
165
+ MLX5_SET(ptys_reg, in, proto_mask, MLX5_PTYS_EN);
166
+ if (ext)
167
+ MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin);
168
+ else
169
+ MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
170
+
171
+ return mlx5_core_access_reg(dev, in, sizeof(in), out,
172
+ sizeof(out), MLX5_REG_PTYS, 0, 1);
173
+}
174
+
175
+u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper,
176
+ bool force_legacy)
67177 {
68178 unsigned long temp = eth_proto_oper;
179
+ const u32 *table;
69180 u32 speed = 0;
181
+ u32 max_size;
70182 int i;
71183
72
- i = find_first_bit(&temp, MLX5E_LINK_MODES_NUMBER);
73
- if (i < MLX5E_LINK_MODES_NUMBER)
74
- speed = mlx5e_link_speed[i];
75
-
184
+ mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy);
185
+ i = find_first_bit(&temp, max_size);
186
+ if (i < max_size)
187
+ speed = table[i];
76188 return speed;
77189 }
78190
79191 int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
80192 {
81
- u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {};
82
- u32 eth_proto_oper;
193
+ struct mlx5e_port_eth_proto eproto;
194
+ bool force_legacy = false;
195
+ bool ext;
83196 int err;
84197
85
- err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1);
198
+ ext = mlx5e_ptys_ext_supported(mdev);
199
+ err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
86200 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);
201
+ goto out;
202
+ if (ext && !eproto.admin) {
203
+ force_legacy = true;
204
+ err = mlx5_port_query_eth_proto(mdev, 1, false, &eproto);
205
+ if (err)
206
+ goto out;
207
+ }
208
+ *speed = mlx5e_port_ptys2speed(mdev, eproto.oper, force_legacy);
91209 if (!(*speed))
92210 err = -EINVAL;
93211
212
+out:
94213 return err;
95214 }
96215
97216 int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
98217 {
218
+ struct mlx5e_port_eth_proto eproto;
99219 u32 max_speed = 0;
100
- u32 proto_cap;
220
+ const u32 *table;
221
+ u32 max_size;
222
+ bool ext;
101223 int err;
102224 int i;
103225
104
- err = mlx5_query_port_proto_cap(mdev, &proto_cap, MLX5_PTYS_EN);
226
+ ext = mlx5e_ptys_ext_supported(mdev);
227
+ err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
105228 if (err)
106229 return err;
107230
108
- for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i)
109
- if (proto_cap & MLX5E_PROT_MASK(i))
110
- max_speed = max(max_speed, mlx5e_link_speed[i]);
231
+ mlx5e_port_get_speed_arr(mdev, &table, &max_size, false);
232
+ for (i = 0; i < max_size; ++i)
233
+ if (eproto.cap & MLX5E_PROT_MASK(i))
234
+ max_speed = max(max_speed, table[i]);
111235
112236 *speed = max_speed;
113237 return 0;
114238 }
115239
116
-u32 mlx5e_port_speed2linkmodes(u32 speed)
240
+u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
241
+ bool force_legacy)
117242 {
118243 u32 link_modes = 0;
244
+ const u32 *table;
245
+ u32 max_size;
119246 int i;
120247
121
- for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
122
- if (mlx5e_link_speed[i] == speed)
248
+ mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy);
249
+ for (i = 0; i < max_size; ++i) {
250
+ if (table[i] == speed)
123251 link_modes |= MLX5E_PROT_MASK(i);
124252 }
125
-
126253 return link_modes;
127254 }
128255
....@@ -233,3 +360,235 @@
233360 kfree(out);
234361 return err;
235362 }
363
+
364
+enum mlx5e_fec_supported_link_mode {
365
+ MLX5E_FEC_SUPPORTED_LINK_MODES_10G_40G,
366
+ MLX5E_FEC_SUPPORTED_LINK_MODES_25G,
367
+ MLX5E_FEC_SUPPORTED_LINK_MODES_50G,
368
+ MLX5E_FEC_SUPPORTED_LINK_MODES_56G,
369
+ MLX5E_FEC_SUPPORTED_LINK_MODES_100G,
370
+ MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X,
371
+ MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X,
372
+ MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X,
373
+ MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X,
374
+ MLX5E_MAX_FEC_SUPPORTED_LINK_MODE,
375
+};
376
+
377
+#define MLX5E_FEC_FIRST_50G_PER_LANE_MODE MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X
378
+
379
+#define MLX5E_FEC_OVERRIDE_ADMIN_POLICY(buf, policy, write, link) \
380
+ do { \
381
+ u16 *_policy = &(policy); \
382
+ u32 *_buf = buf; \
383
+ \
384
+ if (write) \
385
+ MLX5_SET(pplm_reg, _buf, fec_override_admin_##link, *_policy); \
386
+ else \
387
+ *_policy = MLX5_GET(pplm_reg, _buf, fec_override_admin_##link); \
388
+ } while (0)
389
+
390
+/* get/set FEC admin field for a given speed */
391
+static int mlx5e_fec_admin_field(u32 *pplm, u16 *fec_policy, bool write,
392
+ enum mlx5e_fec_supported_link_mode link_mode)
393
+{
394
+ switch (link_mode) {
395
+ case MLX5E_FEC_SUPPORTED_LINK_MODES_10G_40G:
396
+ MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 10g_40g);
397
+ break;
398
+ case MLX5E_FEC_SUPPORTED_LINK_MODES_25G:
399
+ MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 25g);
400
+ break;
401
+ case MLX5E_FEC_SUPPORTED_LINK_MODES_50G:
402
+ MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 50g);
403
+ break;
404
+ case MLX5E_FEC_SUPPORTED_LINK_MODES_56G:
405
+ MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 56g);
406
+ break;
407
+ case MLX5E_FEC_SUPPORTED_LINK_MODES_100G:
408
+ MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 100g);
409
+ break;
410
+ case MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X:
411
+ MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 50g_1x);
412
+ break;
413
+ case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X:
414
+ MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 100g_2x);
415
+ break;
416
+ case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X:
417
+ MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 200g_4x);
418
+ break;
419
+ case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X:
420
+ MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 400g_8x);
421
+ break;
422
+ default:
423
+ return -EINVAL;
424
+ }
425
+ return 0;
426
+}
427
+
428
+#define MLX5E_GET_FEC_OVERRIDE_CAP(buf, link) \
429
+ MLX5_GET(pplm_reg, buf, fec_override_cap_##link)
430
+
431
+/* returns FEC capabilities for a given speed */
432
+static int mlx5e_get_fec_cap_field(u32 *pplm, u16 *fec_cap,
433
+ enum mlx5e_fec_supported_link_mode link_mode)
434
+{
435
+ switch (link_mode) {
436
+ case MLX5E_FEC_SUPPORTED_LINK_MODES_10G_40G:
437
+ *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 10g_40g);
438
+ break;
439
+ case MLX5E_FEC_SUPPORTED_LINK_MODES_25G:
440
+ *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 25g);
441
+ break;
442
+ case MLX5E_FEC_SUPPORTED_LINK_MODES_50G:
443
+ *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 50g);
444
+ break;
445
+ case MLX5E_FEC_SUPPORTED_LINK_MODES_56G:
446
+ *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 56g);
447
+ break;
448
+ case MLX5E_FEC_SUPPORTED_LINK_MODES_100G:
449
+ *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 100g);
450
+ break;
451
+ case MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X:
452
+ *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 50g_1x);
453
+ break;
454
+ case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X:
455
+ *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 100g_2x);
456
+ break;
457
+ case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X:
458
+ *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 200g_4x);
459
+ break;
460
+ case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X:
461
+ *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 400g_8x);
462
+ break;
463
+ default:
464
+ return -EINVAL;
465
+ }
466
+ return 0;
467
+}
468
+
469
+bool mlx5e_fec_in_caps(struct mlx5_core_dev *dev, int fec_policy)
470
+{
471
+ bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm);
472
+ u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
473
+ u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
474
+ int sz = MLX5_ST_SZ_BYTES(pplm_reg);
475
+ int err;
476
+ int i;
477
+
478
+ if (!MLX5_CAP_GEN(dev, pcam_reg) || !MLX5_CAP_PCAM_REG(dev, pplm))
479
+ return false;
480
+
481
+ MLX5_SET(pplm_reg, in, local_port, 1);
482
+ err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
483
+ if (err)
484
+ return false;
485
+
486
+ for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) {
487
+ u16 fec_caps;
488
+
489
+ if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane)
490
+ break;
491
+
492
+ mlx5e_get_fec_cap_field(out, &fec_caps, i);
493
+ if (fec_caps & fec_policy)
494
+ return true;
495
+ }
496
+ return false;
497
+}
498
+
499
+int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active,
500
+ u16 *fec_configured_mode)
501
+{
502
+ bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm);
503
+ u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
504
+ u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
505
+ int sz = MLX5_ST_SZ_BYTES(pplm_reg);
506
+ int err;
507
+ int i;
508
+
509
+ if (!MLX5_CAP_GEN(dev, pcam_reg))
510
+ return -EOPNOTSUPP;
511
+
512
+ if (!MLX5_CAP_PCAM_REG(dev, pplm))
513
+ return -EOPNOTSUPP;
514
+
515
+ MLX5_SET(pplm_reg, in, local_port, 1);
516
+ err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
517
+ if (err)
518
+ return err;
519
+
520
+ *fec_mode_active = MLX5_GET(pplm_reg, out, fec_mode_active);
521
+
522
+ if (!fec_configured_mode)
523
+ goto out;
524
+
525
+ *fec_configured_mode = 0;
526
+ for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) {
527
+ if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane)
528
+ break;
529
+
530
+ mlx5e_fec_admin_field(out, fec_configured_mode, 0, i);
531
+ if (*fec_configured_mode != 0)
532
+ goto out;
533
+ }
534
+out:
535
+ return 0;
536
+}
537
+
538
+int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
539
+{
540
+ bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm);
541
+ u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
542
+ u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
543
+ int sz = MLX5_ST_SZ_BYTES(pplm_reg);
544
+ u16 fec_policy_auto = 0;
545
+ int err;
546
+ int i;
547
+
548
+ if (!MLX5_CAP_GEN(dev, pcam_reg))
549
+ return -EOPNOTSUPP;
550
+
551
+ if (!MLX5_CAP_PCAM_REG(dev, pplm))
552
+ return -EOPNOTSUPP;
553
+
554
+ if (fec_policy >= (1 << MLX5E_FEC_LLRS_272_257_1) && !fec_50g_per_lane)
555
+ return -EOPNOTSUPP;
556
+
557
+ if (fec_policy && !mlx5e_fec_in_caps(dev, fec_policy))
558
+ return -EOPNOTSUPP;
559
+
560
+ MLX5_SET(pplm_reg, in, local_port, 1);
561
+ err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
562
+ if (err)
563
+ return err;
564
+
565
+ MLX5_SET(pplm_reg, out, local_port, 1);
566
+
567
+ for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) {
568
+ u16 conf_fec = fec_policy;
569
+ u16 fec_caps = 0;
570
+
571
+ if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane)
572
+ break;
573
+
574
+ /* RS fec in ethtool is mapped to MLX5E_FEC_RS_528_514
575
+ * to link modes up to 25G per lane and to
576
+ * MLX5E_FEC_RS_544_514 in the new link modes based on
577
+ * 50 G per lane
578
+ */
579
+ if (conf_fec == (1 << MLX5E_FEC_RS_528_514) &&
580
+ i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE)
581
+ conf_fec = (1 << MLX5E_FEC_RS_544_514);
582
+
583
+ mlx5e_get_fec_cap_field(out, &fec_caps, i);
584
+
585
+ /* policy supported for link speed */
586
+ if (fec_caps & conf_fec)
587
+ mlx5e_fec_admin_field(out, &conf_fec, 1, i);
588
+ else
589
+ /* set FEC to auto*/
590
+ mlx5e_fec_admin_field(out, &fec_policy_auto, 1, i);
591
+ }
592
+
593
+ return mlx5_core_access_reg(dev, out, sz, out, sz, MLX5_REG_PPLM, 0, 1);
594
+}