@@ -26,6 +26,7 @@ struct mlx5_fw_reset {
26
26
struct work_struct reset_now_work ;
27
27
struct work_struct reset_abort_work ;
28
28
unsigned long reset_flags ;
29
+ u8 reset_method ;
29
30
struct timer_list timer ;
30
31
struct completion done ;
31
32
int ret ;
@@ -95,7 +96,7 @@ static int mlx5_reg_mfrl_set(struct mlx5_core_dev *dev, u8 reset_level,
95
96
}
96
97
97
98
static int mlx5_reg_mfrl_query (struct mlx5_core_dev * dev , u8 * reset_level ,
98
- u8 * reset_type , u8 * reset_state )
99
+ u8 * reset_type , u8 * reset_state , u8 * reset_method )
99
100
{
100
101
u32 out [MLX5_ST_SZ_DW (mfrl_reg )] = {};
101
102
u32 in [MLX5_ST_SZ_DW (mfrl_reg )] = {};
@@ -111,21 +112,34 @@ static int mlx5_reg_mfrl_query(struct mlx5_core_dev *dev, u8 *reset_level,
111
112
* reset_type = MLX5_GET (mfrl_reg , out , reset_type );
112
113
if (reset_state )
113
114
* reset_state = MLX5_GET (mfrl_reg , out , reset_state );
115
+ if (reset_method )
116
+ * reset_method = MLX5_GET (mfrl_reg , out , pci_reset_req_method );
114
117
115
118
return 0 ;
116
119
}
117
120
118
121
int mlx5_fw_reset_query (struct mlx5_core_dev * dev , u8 * reset_level , u8 * reset_type )
119
122
{
120
- return mlx5_reg_mfrl_query (dev , reset_level , reset_type , NULL );
123
+ return mlx5_reg_mfrl_query (dev , reset_level , reset_type , NULL , NULL );
124
+ }
125
+
126
+ static int mlx5_fw_reset_get_reset_method (struct mlx5_core_dev * dev ,
127
+ u8 * reset_method )
128
+ {
129
+ if (!MLX5_CAP_GEN (dev , pcie_reset_using_hotreset_method )) {
130
+ * reset_method = MLX5_MFRL_REG_PCI_RESET_METHOD_LINK_TOGGLE ;
131
+ return 0 ;
132
+ }
133
+
134
+ return mlx5_reg_mfrl_query (dev , NULL , NULL , NULL , reset_method );
121
135
}
122
136
123
137
static int mlx5_fw_reset_get_reset_state_err (struct mlx5_core_dev * dev ,
124
138
struct netlink_ext_ack * extack )
125
139
{
126
140
u8 reset_state ;
127
141
128
- if (mlx5_reg_mfrl_query (dev , NULL , NULL , & reset_state ))
142
+ if (mlx5_reg_mfrl_query (dev , NULL , NULL , & reset_state , NULL ))
129
143
goto out ;
130
144
131
145
if (!reset_state )
@@ -427,7 +441,11 @@ static void mlx5_sync_reset_request_event(struct work_struct *work)
427
441
struct mlx5_core_dev * dev = fw_reset -> dev ;
428
442
int err ;
429
443
430
- if (test_bit (MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST , & fw_reset -> reset_flags ) ||
444
+ err = mlx5_fw_reset_get_reset_method (dev , & fw_reset -> reset_method );
445
+ if (err )
446
+ mlx5_core_warn (dev , "Failed reading MFRL, err %d\n" , err );
447
+
448
+ if (err || test_bit (MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST , & fw_reset -> reset_flags ) ||
431
449
!mlx5_is_reset_now_capable (dev )) {
432
450
err = mlx5_fw_reset_set_reset_sync_nack (dev );
433
451
mlx5_core_warn (dev , "PCI Sync FW Update Reset Nack %s" ,
@@ -444,21 +462,15 @@ static void mlx5_sync_reset_request_event(struct work_struct *work)
444
462
mlx5_core_warn (dev , "PCI Sync FW Update Reset Ack. Device reset is expected.\n" );
445
463
}
446
464
447
- static int mlx5_pci_link_toggle (struct mlx5_core_dev * dev )
465
+ static int mlx5_pci_link_toggle (struct mlx5_core_dev * dev , u16 dev_id )
448
466
{
449
467
struct pci_bus * bridge_bus = dev -> pdev -> bus ;
450
468
struct pci_dev * bridge = bridge_bus -> self ;
451
469
unsigned long timeout ;
452
470
struct pci_dev * sdev ;
453
- u16 reg16 , dev_id ;
454
471
int cap , err ;
472
+ u16 reg16 ;
455
473
456
- err = pci_read_config_word (dev -> pdev , PCI_DEVICE_ID , & dev_id );
457
- if (err )
458
- return pcibios_err_to_errno (err );
459
- err = mlx5_check_dev_ids (dev , dev_id );
460
- if (err )
461
- return err ;
462
474
cap = pci_find_capability (bridge , PCI_CAP_ID_EXP );
463
475
if (!cap )
464
476
return - EOPNOTSUPP ;
@@ -528,6 +540,44 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev)
528
540
return err ;
529
541
}
530
542
543
+ static int mlx5_pci_reset_bus (struct mlx5_core_dev * dev )
544
+ {
545
+ if (!MLX5_CAP_GEN (dev , pcie_reset_using_hotreset_method ))
546
+ return - EOPNOTSUPP ;
547
+
548
+ return pci_reset_bus (dev -> pdev );
549
+ }
550
+
551
+ static int mlx5_sync_pci_reset (struct mlx5_core_dev * dev , u8 reset_method )
552
+ {
553
+ u16 dev_id ;
554
+ int err ;
555
+
556
+ err = pci_read_config_word (dev -> pdev , PCI_DEVICE_ID , & dev_id );
557
+ if (err )
558
+ return pcibios_err_to_errno (err );
559
+ err = mlx5_check_dev_ids (dev , dev_id );
560
+ if (err )
561
+ return err ;
562
+
563
+ switch (reset_method ) {
564
+ case MLX5_MFRL_REG_PCI_RESET_METHOD_LINK_TOGGLE :
565
+ err = mlx5_pci_link_toggle (dev , dev_id );
566
+ if (err )
567
+ mlx5_core_warn (dev , "mlx5_pci_link_toggle failed\n" );
568
+ break ;
569
+ case MLX5_MFRL_REG_PCI_RESET_METHOD_HOT_RESET :
570
+ err = mlx5_pci_reset_bus (dev );
571
+ if (err )
572
+ mlx5_core_warn (dev , "mlx5_pci_reset_bus failed\n" );
573
+ break ;
574
+ default :
575
+ return - EOPNOTSUPP ;
576
+ }
577
+
578
+ return err ;
579
+ }
580
+
531
581
static void mlx5_sync_reset_now_event (struct work_struct * work )
532
582
{
533
583
struct mlx5_fw_reset * fw_reset = container_of (work , struct mlx5_fw_reset ,
@@ -546,9 +596,9 @@ static void mlx5_sync_reset_now_event(struct work_struct *work)
546
596
goto done ;
547
597
}
548
598
549
- err = mlx5_pci_link_toggle (dev );
599
+ err = mlx5_sync_pci_reset (dev , fw_reset -> reset_method );
550
600
if (err ) {
551
- mlx5_core_warn (dev , "mlx5_pci_link_toggle failed, no reset done, err %d\n" , err );
601
+ mlx5_core_warn (dev , "mlx5_sync_pci_reset failed, no reset done, err %d\n" , err );
552
602
set_bit (MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED , & fw_reset -> reset_flags );
553
603
}
554
604
@@ -610,9 +660,9 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work)
610
660
611
661
mlx5_core_warn (dev , "Sync Reset, got reset action. rst_state = %u\n" , rst_state );
612
662
if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ ) {
613
- err = mlx5_pci_link_toggle (dev );
663
+ err = mlx5_sync_pci_reset (dev , fw_reset -> reset_method );
614
664
if (err ) {
615
- mlx5_core_warn (dev , "mlx5_pci_link_toggle failed, err %d\n" , err );
665
+ mlx5_core_warn (dev , "mlx5_sync_pci_reset failed, err %d\n" , err );
616
666
fw_reset -> ret = err ;
617
667
}
618
668
}
0 commit comments