hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/ethernet/mellanox/mlx5/core/fw.c
....@@ -31,32 +31,56 @@
3131 */
3232
3333 #include <linux/mlx5/driver.h>
34
-#include <linux/mlx5/cmd.h>
3534 #include <linux/mlx5/eswitch.h>
3635 #include <linux/module.h>
3736 #include "mlx5_core.h"
3837 #include "../../mlxfw/mlxfw.h"
38
+#include "accel/tls.h"
3939
40
-static int mlx5_cmd_query_adapter(struct mlx5_core_dev *dev, u32 *out,
41
- int outlen)
42
-{
43
- u32 in[MLX5_ST_SZ_DW(query_adapter_in)] = {0};
40
+enum {
41
+ MCQS_IDENTIFIER_BOOT_IMG = 0x1,
42
+ MCQS_IDENTIFIER_OEM_NVCONFIG = 0x4,
43
+ MCQS_IDENTIFIER_MLNX_NVCONFIG = 0x5,
44
+ MCQS_IDENTIFIER_CS_TOKEN = 0x6,
45
+ MCQS_IDENTIFIER_DBG_TOKEN = 0x7,
46
+ MCQS_IDENTIFIER_GEARBOX = 0xA,
47
+};
4448
45
- MLX5_SET(query_adapter_in, in, opcode, MLX5_CMD_OP_QUERY_ADAPTER);
46
- return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
47
-}
49
+enum {
50
+ MCQS_UPDATE_STATE_IDLE,
51
+ MCQS_UPDATE_STATE_IN_PROGRESS,
52
+ MCQS_UPDATE_STATE_APPLIED,
53
+ MCQS_UPDATE_STATE_ACTIVE,
54
+ MCQS_UPDATE_STATE_ACTIVE_PENDING_RESET,
55
+ MCQS_UPDATE_STATE_FAILED,
56
+ MCQS_UPDATE_STATE_CANCELED,
57
+ MCQS_UPDATE_STATE_BUSY,
58
+};
59
+
60
+enum {
61
+ MCQI_INFO_TYPE_CAPABILITIES = 0x0,
62
+ MCQI_INFO_TYPE_VERSION = 0x1,
63
+ MCQI_INFO_TYPE_ACTIVATION_METHOD = 0x5,
64
+};
65
+
66
+enum {
67
+ MCQI_FW_RUNNING_VERSION = 0,
68
+ MCQI_FW_STORED_VERSION = 1,
69
+};
4870
4971 int mlx5_query_board_id(struct mlx5_core_dev *dev)
5072 {
5173 u32 *out;
5274 int outlen = MLX5_ST_SZ_BYTES(query_adapter_out);
75
+ u32 in[MLX5_ST_SZ_DW(query_adapter_in)] = {};
5376 int err;
5477
5578 out = kzalloc(outlen, GFP_KERNEL);
5679 if (!out)
5780 return -ENOMEM;
5881
59
- err = mlx5_cmd_query_adapter(dev, out, outlen);
82
+ MLX5_SET(query_adapter_in, in, opcode, MLX5_CMD_OP_QUERY_ADAPTER);
83
+ err = mlx5_cmd_exec_inout(dev, query_adapter, in, out);
6084 if (err)
6185 goto out;
6286
....@@ -75,13 +99,15 @@
7599 {
76100 u32 *out;
77101 int outlen = MLX5_ST_SZ_BYTES(query_adapter_out);
102
+ u32 in[MLX5_ST_SZ_DW(query_adapter_in)] = {};
78103 int err;
79104
80105 out = kzalloc(outlen, GFP_KERNEL);
81106 if (!out)
82107 return -ENOMEM;
83108
84
- err = mlx5_cmd_query_adapter(mdev, out, outlen);
109
+ MLX5_SET(query_adapter_in, in, opcode, MLX5_CMD_OP_QUERY_ADAPTER);
110
+ err = mlx5_cmd_exec_inout(mdev, query_adapter, in, out);
85111 if (err)
86112 goto out;
87113
....@@ -100,11 +126,11 @@
100126 MLX5_PCAM_REGS_5000_TO_507F);
101127 }
102128
103
-static int mlx5_get_mcam_reg(struct mlx5_core_dev *dev)
129
+static int mlx5_get_mcam_access_reg_group(struct mlx5_core_dev *dev,
130
+ enum mlx5_mcam_reg_groups group)
104131 {
105
- return mlx5_query_mcam_reg(dev, dev->caps.mcam,
106
- MLX5_MCAM_FEATURE_ENHANCED_FEATURES,
107
- MLX5_MCAM_REGS_FIRST_128);
132
+ return mlx5_query_mcam_reg(dev, dev->caps.mcam[group],
133
+ MLX5_MCAM_FEATURE_ENHANCED_FEATURES, group);
108134 }
109135
110136 static int mlx5_get_qcam_reg(struct mlx5_core_dev *dev)
....@@ -190,8 +216,11 @@
190216 if (MLX5_CAP_GEN(dev, pcam_reg))
191217 mlx5_get_pcam_reg(dev);
192218
193
- if (MLX5_CAP_GEN(dev, mcam_reg))
194
- mlx5_get_mcam_reg(dev);
219
+ if (MLX5_CAP_GEN(dev, mcam_reg)) {
220
+ mlx5_get_mcam_access_reg_group(dev, MLX5_MCAM_REGS_FIRST_128);
221
+ mlx5_get_mcam_access_reg_group(dev, MLX5_MCAM_REGS_0x9080_0x90FF);
222
+ mlx5_get_mcam_access_reg_group(dev, MLX5_MCAM_REGS_0x9100_0x917F);
223
+ }
195224
196225 if (MLX5_CAP_GEN(dev, qcam_reg))
197226 mlx5_get_qcam_reg(dev);
....@@ -202,13 +231,37 @@
202231 return err;
203232 }
204233
234
+ if (MLX5_CAP_GEN(dev, event_cap)) {
235
+ err = mlx5_core_get_caps(dev, MLX5_CAP_DEV_EVENT);
236
+ if (err)
237
+ return err;
238
+ }
239
+
240
+ if (mlx5_accel_is_ktls_tx(dev) || mlx5_accel_is_ktls_rx(dev)) {
241
+ err = mlx5_core_get_caps(dev, MLX5_CAP_TLS);
242
+ if (err)
243
+ return err;
244
+ }
245
+
246
+ if (MLX5_CAP_GEN_64(dev, general_obj_types) &
247
+ MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q) {
248
+ err = mlx5_core_get_caps(dev, MLX5_CAP_VDPA_EMULATION);
249
+ if (err)
250
+ return err;
251
+ }
252
+
253
+ if (MLX5_CAP_GEN(dev, ipsec_offload)) {
254
+ err = mlx5_core_get_caps(dev, MLX5_CAP_IPSEC);
255
+ if (err)
256
+ return err;
257
+ }
258
+
205259 return 0;
206260 }
207261
208262 int mlx5_cmd_init_hca(struct mlx5_core_dev *dev, uint32_t *sw_owner_id)
209263 {
210
- u32 out[MLX5_ST_SZ_DW(init_hca_out)] = {0};
211
- u32 in[MLX5_ST_SZ_DW(init_hca_in)] = {0};
264
+ u32 in[MLX5_ST_SZ_DW(init_hca_in)] = {};
212265 int i;
213266
214267 MLX5_SET(init_hca_in, in, opcode, MLX5_CMD_OP_INIT_HCA);
....@@ -219,16 +272,15 @@
219272 sw_owner_id[i]);
220273 }
221274
222
- return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
275
+ return mlx5_cmd_exec_in(dev, init_hca, in);
223276 }
224277
225278 int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev)
226279 {
227
- u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {0};
228
- u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {0};
280
+ u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {};
229281
230282 MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA);
231
- return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
283
+ return mlx5_cmd_exec_in(dev, teardown_hca, in);
232284 }
233285
234286 int mlx5_cmd_force_teardown_hca(struct mlx5_core_dev *dev)
....@@ -250,9 +302,57 @@
250302 if (ret)
251303 return ret;
252304
253
- force_state = MLX5_GET(teardown_hca_out, out, force_state);
305
+ force_state = MLX5_GET(teardown_hca_out, out, state);
254306 if (force_state == MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_FAIL) {
255307 mlx5_core_warn(dev, "teardown with force mode failed, doing normal teardown\n");
308
+ return -EIO;
309
+ }
310
+
311
+ return 0;
312
+}
313
+
314
+#define MLX5_FAST_TEARDOWN_WAIT_MS 3000
315
+int mlx5_cmd_fast_teardown_hca(struct mlx5_core_dev *dev)
316
+{
317
+ unsigned long end, delay_ms = MLX5_FAST_TEARDOWN_WAIT_MS;
318
+ u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {};
319
+ u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {};
320
+ int state;
321
+ int ret;
322
+
323
+ if (!MLX5_CAP_GEN(dev, fast_teardown)) {
324
+ mlx5_core_dbg(dev, "fast teardown is not supported in the firmware\n");
325
+ return -EOPNOTSUPP;
326
+ }
327
+
328
+ MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA);
329
+ MLX5_SET(teardown_hca_in, in, profile,
330
+ MLX5_TEARDOWN_HCA_IN_PROFILE_PREPARE_FAST_TEARDOWN);
331
+
332
+ ret = mlx5_cmd_exec_inout(dev, teardown_hca, in, out);
333
+ if (ret)
334
+ return ret;
335
+
336
+ state = MLX5_GET(teardown_hca_out, out, state);
337
+ if (state == MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_FAIL) {
338
+ mlx5_core_warn(dev, "teardown with fast mode failed\n");
339
+ return -EIO;
340
+ }
341
+
342
+ mlx5_set_nic_state(dev, MLX5_NIC_IFC_DISABLED);
343
+
344
+ /* Loop until device state turns to disable */
345
+ end = jiffies + msecs_to_jiffies(delay_ms);
346
+ do {
347
+ if (mlx5_get_nic_state(dev) == MLX5_NIC_IFC_DISABLED)
348
+ break;
349
+
350
+ cond_resched();
351
+ } while (!time_after(jiffies, end));
352
+
353
+ if (mlx5_get_nic_state(dev) != MLX5_NIC_IFC_DISABLED) {
354
+ dev_err(&dev->pdev->dev, "NIC IFC still %d after %lums.\n",
355
+ mlx5_get_nic_state(dev), delay_ms);
256356 return -EIO;
257357 }
258358
....@@ -344,33 +444,49 @@
344444 }
345445
346446 static int mlx5_reg_mcqi_query(struct mlx5_core_dev *dev,
347
- u16 component_index,
348
- u32 *max_component_size,
349
- u8 *log_mcda_word_size,
350
- u16 *mcda_max_write_size)
447
+ u16 component_index, bool read_pending,
448
+ u8 info_type, u16 data_size, void *mcqi_data)
351449 {
352
- u32 out[MLX5_ST_SZ_DW(mcqi_reg) + MLX5_ST_SZ_DW(mcqi_cap)];
353
- int offset = MLX5_ST_SZ_DW(mcqi_reg);
354
- u32 in[MLX5_ST_SZ_DW(mcqi_reg)];
450
+ u32 out[MLX5_ST_SZ_DW(mcqi_reg) + MLX5_UN_SZ_DW(mcqi_reg_data)] = {};
451
+ u32 in[MLX5_ST_SZ_DW(mcqi_reg)] = {};
452
+ void *data;
355453 int err;
356454
357
- memset(in, 0, sizeof(in));
358
- memset(out, 0, sizeof(out));
359
-
360455 MLX5_SET(mcqi_reg, in, component_index, component_index);
361
- MLX5_SET(mcqi_reg, in, data_size, MLX5_ST_SZ_BYTES(mcqi_cap));
456
+ MLX5_SET(mcqi_reg, in, read_pending_component, read_pending);
457
+ MLX5_SET(mcqi_reg, in, info_type, info_type);
458
+ MLX5_SET(mcqi_reg, in, data_size, data_size);
362459
363460 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
364
- sizeof(out), MLX5_REG_MCQI, 0, 0);
461
+ MLX5_ST_SZ_BYTES(mcqi_reg) + data_size,
462
+ MLX5_REG_MCQI, 0, 0);
365463 if (err)
366
- goto out;
464
+ return err;
367465
368
- *max_component_size = MLX5_GET(mcqi_cap, out + offset, max_component_size);
369
- *log_mcda_word_size = MLX5_GET(mcqi_cap, out + offset, log_mcda_word_size);
370
- *mcda_max_write_size = MLX5_GET(mcqi_cap, out + offset, mcda_max_write_size);
466
+ data = MLX5_ADDR_OF(mcqi_reg, out, data);
467
+ memcpy(mcqi_data, data, data_size);
371468
372
-out:
373
- return err;
469
+ return 0;
470
+}
471
+
472
+static int mlx5_reg_mcqi_caps_query(struct mlx5_core_dev *dev, u16 component_index,
473
+ u32 *max_component_size, u8 *log_mcda_word_size,
474
+ u16 *mcda_max_write_size)
475
+{
476
+ u32 mcqi_reg[MLX5_ST_SZ_DW(mcqi_cap)] = {};
477
+ int err;
478
+
479
+ err = mlx5_reg_mcqi_query(dev, component_index, 0,
480
+ MCQI_INFO_TYPE_CAPABILITIES,
481
+ MLX5_ST_SZ_BYTES(mcqi_cap), mcqi_reg);
482
+ if (err)
483
+ return err;
484
+
485
+ *max_component_size = MLX5_GET(mcqi_cap, mcqi_reg, max_component_size);
486
+ *log_mcda_word_size = MLX5_GET(mcqi_cap, mcqi_reg, log_mcda_word_size);
487
+ *mcda_max_write_size = MLX5_GET(mcqi_cap, mcqi_reg, mcda_max_write_size);
488
+
489
+ return 0;
374490 }
375491
376492 struct mlx5_mlxfw_dev {
....@@ -386,8 +502,13 @@
386502 container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
387503 struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
388504
389
- return mlx5_reg_mcqi_query(dev, component_index, p_max_size,
390
- p_align_bits, p_max_write_size);
505
+ if (!MLX5_CAP_GEN(dev, mcam_reg) || !MLX5_CAP_MCAM_REG(dev, mcqi)) {
506
+ mlx5_core_warn(dev, "caps query isn't supported by running FW\n");
507
+ return -EOPNOTSUPP;
508
+ }
509
+
510
+ return mlx5_reg_mcqi_caps_query(dev, component_index, p_max_size,
511
+ p_align_bits, p_max_write_size);
391512 }
392513
393514 static int mlx5_fsm_lock(struct mlxfw_dev *mlxfw_dev, u32 *fwhandle)
....@@ -491,6 +612,44 @@
491612 fwhandle, 0);
492613 }
493614
615
+#define MLX5_FSM_REACTIVATE_TOUT 5000 /* msecs */
616
+static int mlx5_fsm_reactivate(struct mlxfw_dev *mlxfw_dev, u8 *status)
617
+{
618
+ unsigned long exp_time = jiffies + msecs_to_jiffies(MLX5_FSM_REACTIVATE_TOUT);
619
+ struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
620
+ container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
621
+ struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
622
+ u32 out[MLX5_ST_SZ_DW(mirc_reg)];
623
+ u32 in[MLX5_ST_SZ_DW(mirc_reg)];
624
+ int err;
625
+
626
+ if (!MLX5_CAP_MCAM_REG2(dev, mirc))
627
+ return -EOPNOTSUPP;
628
+
629
+ memset(in, 0, sizeof(in));
630
+
631
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
632
+ sizeof(out), MLX5_REG_MIRC, 0, 1);
633
+ if (err)
634
+ return err;
635
+
636
+ do {
637
+ memset(out, 0, sizeof(out));
638
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
639
+ sizeof(out), MLX5_REG_MIRC, 0, 0);
640
+ if (err)
641
+ return err;
642
+
643
+ *status = MLX5_GET(mirc_reg, out, status_code);
644
+ if (*status != MLXFW_FSM_REACTIVATE_STATUS_BUSY)
645
+ return 0;
646
+
647
+ msleep(20);
648
+ } while (time_before(jiffies, exp_time));
649
+
650
+ return 0;
651
+}
652
+
494653 static const struct mlxfw_dev_ops mlx5_mlxfw_dev_ops = {
495654 .component_query = mlx5_component_query,
496655 .fsm_lock = mlx5_fsm_lock,
....@@ -498,19 +657,22 @@
498657 .fsm_block_download = mlx5_fsm_block_download,
499658 .fsm_component_verify = mlx5_fsm_component_verify,
500659 .fsm_activate = mlx5_fsm_activate,
660
+ .fsm_reactivate = mlx5_fsm_reactivate,
501661 .fsm_query_state = mlx5_fsm_query_state,
502662 .fsm_cancel = mlx5_fsm_cancel,
503663 .fsm_release = mlx5_fsm_release
504664 };
505665
506666 int mlx5_firmware_flash(struct mlx5_core_dev *dev,
507
- const struct firmware *firmware)
667
+ const struct firmware *firmware,
668
+ struct netlink_ext_ack *extack)
508669 {
509670 struct mlx5_mlxfw_dev mlx5_mlxfw_dev = {
510671 .mlxfw_dev = {
511672 .ops = &mlx5_mlxfw_dev_ops,
512673 .psid = dev->board_id,
513674 .psid_size = strlen(dev->board_id),
675
+ .devlink = priv_to_devlink(dev),
514676 },
515677 .mlx5_core_dev = dev
516678 };
....@@ -523,5 +685,133 @@
523685 return -EOPNOTSUPP;
524686 }
525687
526
- return mlxfw_firmware_flash(&mlx5_mlxfw_dev.mlxfw_dev, firmware);
688
+ return mlxfw_firmware_flash(&mlx5_mlxfw_dev.mlxfw_dev,
689
+ firmware, extack);
690
+}
691
+
692
+static int mlx5_reg_mcqi_version_query(struct mlx5_core_dev *dev,
693
+ u16 component_index, bool read_pending,
694
+ u32 *mcqi_version_out)
695
+{
696
+ return mlx5_reg_mcqi_query(dev, component_index, read_pending,
697
+ MCQI_INFO_TYPE_VERSION,
698
+ MLX5_ST_SZ_BYTES(mcqi_version),
699
+ mcqi_version_out);
700
+}
701
+
702
+static int mlx5_reg_mcqs_query(struct mlx5_core_dev *dev, u32 *out,
703
+ u16 component_index)
704
+{
705
+ u8 out_sz = MLX5_ST_SZ_BYTES(mcqs_reg);
706
+ u32 in[MLX5_ST_SZ_DW(mcqs_reg)] = {};
707
+ int err;
708
+
709
+ memset(out, 0, out_sz);
710
+
711
+ MLX5_SET(mcqs_reg, in, component_index, component_index);
712
+
713
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
714
+ out_sz, MLX5_REG_MCQS, 0, 0);
715
+ return err;
716
+}
717
+
718
+/* scans component index sequentially, to find the boot img index */
719
+static int mlx5_get_boot_img_component_index(struct mlx5_core_dev *dev)
720
+{
721
+ u32 out[MLX5_ST_SZ_DW(mcqs_reg)] = {};
722
+ u16 identifier, component_idx = 0;
723
+ bool quit;
724
+ int err;
725
+
726
+ do {
727
+ err = mlx5_reg_mcqs_query(dev, out, component_idx);
728
+ if (err)
729
+ return err;
730
+
731
+ identifier = MLX5_GET(mcqs_reg, out, identifier);
732
+ quit = !!MLX5_GET(mcqs_reg, out, last_index_flag);
733
+ quit |= identifier == MCQS_IDENTIFIER_BOOT_IMG;
734
+ } while (!quit && ++component_idx);
735
+
736
+ if (identifier != MCQS_IDENTIFIER_BOOT_IMG) {
737
+ mlx5_core_warn(dev, "mcqs: can't find boot_img component ix, last scanned idx %d\n",
738
+ component_idx);
739
+ return -EOPNOTSUPP;
740
+ }
741
+
742
+ return component_idx;
743
+}
744
+
745
+static int
746
+mlx5_fw_image_pending(struct mlx5_core_dev *dev,
747
+ int component_index,
748
+ bool *pending_version_exists)
749
+{
750
+ u32 out[MLX5_ST_SZ_DW(mcqs_reg)];
751
+ u8 component_update_state;
752
+ int err;
753
+
754
+ err = mlx5_reg_mcqs_query(dev, out, component_index);
755
+ if (err)
756
+ return err;
757
+
758
+ component_update_state = MLX5_GET(mcqs_reg, out, component_update_state);
759
+
760
+ if (component_update_state == MCQS_UPDATE_STATE_IDLE) {
761
+ *pending_version_exists = false;
762
+ } else if (component_update_state == MCQS_UPDATE_STATE_ACTIVE_PENDING_RESET) {
763
+ *pending_version_exists = true;
764
+ } else {
765
+ mlx5_core_warn(dev,
766
+ "mcqs: can't read pending fw version while fw state is %d\n",
767
+ component_update_state);
768
+ return -ENODATA;
769
+ }
770
+ return 0;
771
+}
772
+
773
+int mlx5_fw_version_query(struct mlx5_core_dev *dev,
774
+ u32 *running_ver, u32 *pending_ver)
775
+{
776
+ u32 reg_mcqi_version[MLX5_ST_SZ_DW(mcqi_version)] = {};
777
+ bool pending_version_exists;
778
+ int component_index;
779
+ int err;
780
+
781
+ if (!MLX5_CAP_GEN(dev, mcam_reg) || !MLX5_CAP_MCAM_REG(dev, mcqi) ||
782
+ !MLX5_CAP_MCAM_REG(dev, mcqs)) {
783
+ mlx5_core_warn(dev, "fw query isn't supported by the FW\n");
784
+ return -EOPNOTSUPP;
785
+ }
786
+
787
+ component_index = mlx5_get_boot_img_component_index(dev);
788
+ if (component_index < 0)
789
+ return component_index;
790
+
791
+ err = mlx5_reg_mcqi_version_query(dev, component_index,
792
+ MCQI_FW_RUNNING_VERSION,
793
+ reg_mcqi_version);
794
+ if (err)
795
+ return err;
796
+
797
+ *running_ver = MLX5_GET(mcqi_version, reg_mcqi_version, version);
798
+
799
+ err = mlx5_fw_image_pending(dev, component_index, &pending_version_exists);
800
+ if (err)
801
+ return err;
802
+
803
+ if (!pending_version_exists) {
804
+ *pending_ver = 0;
805
+ return 0;
806
+ }
807
+
808
+ err = mlx5_reg_mcqi_version_query(dev, component_index,
809
+ MCQI_FW_STORED_VERSION,
810
+ reg_mcqi_version);
811
+ if (err)
812
+ return err;
813
+
814
+ *pending_ver = MLX5_GET(mcqi_version, reg_mcqi_version, version);
815
+
816
+ return 0;
527817 }