@@ -3120,7 +3120,10 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
3120
3120
if (ret ) {
3121
3121
kfree (dev -> persist );
3122
3122
kfree (priv );
3123
+ } else {
3124
+ pci_save_state (pdev );
3123
3125
}
3126
+
3124
3127
return ret ;
3125
3128
}
3126
3129
@@ -3351,23 +3354,79 @@ MODULE_DEVICE_TABLE(pci, mlx4_pci_table);
3351
3354
static pci_ers_result_t mlx4_pci_err_detected (struct pci_dev * pdev ,
3352
3355
pci_channel_state_t state )
3353
3356
{
3354
- mlx4_unload_one (pdev );
3357
+ struct mlx4_dev_persistent * persist = pci_get_drvdata (pdev );
3358
+
3359
+ mlx4_err (persist -> dev , "mlx4_pci_err_detected was called\n" );
3360
+ mlx4_enter_error_state (persist );
3355
3361
3356
- return state == pci_channel_io_perm_failure ?
3357
- PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET ;
3362
+ mutex_lock (& persist -> interface_state_mutex );
3363
+ if (persist -> interface_state & MLX4_INTERFACE_STATE_UP )
3364
+ mlx4_unload_one (pdev );
3365
+
3366
+ mutex_unlock (& persist -> interface_state_mutex );
3367
+ if (state == pci_channel_io_perm_failure )
3368
+ return PCI_ERS_RESULT_DISCONNECT ;
3369
+
3370
+ pci_disable_device (pdev );
3371
+ return PCI_ERS_RESULT_NEED_RESET ;
3358
3372
}
3359
3373
3360
3374
static pci_ers_result_t mlx4_pci_slot_reset (struct pci_dev * pdev )
3361
3375
{
3362
- struct mlx4_dev * dev = pci_get_drvdata (pdev );
3376
+ struct mlx4_dev_persistent * persist = pci_get_drvdata (pdev );
3377
+ struct mlx4_dev * dev = persist -> dev ;
3363
3378
struct mlx4_priv * priv = mlx4_priv (dev );
3364
3379
int ret ;
3380
+ int nvfs [MLX4_MAX_PORTS + 1 ] = {0 , 0 , 0 };
3381
+ int total_vfs ;
3365
3382
3366
- ret = __mlx4_init_one (pdev , priv -> pci_dev_data , priv );
3383
+ mlx4_err (dev , "mlx4_pci_slot_reset was called\n" );
3384
+ ret = pci_enable_device (pdev );
3385
+ if (ret ) {
3386
+ mlx4_err (dev , "Can not re-enable device, ret=%d\n" , ret );
3387
+ return PCI_ERS_RESULT_DISCONNECT ;
3388
+ }
3389
+
3390
+ pci_set_master (pdev );
3391
+ pci_restore_state (pdev );
3392
+ pci_save_state (pdev );
3393
+
3394
+ total_vfs = dev -> persist -> num_vfs ;
3395
+ memcpy (nvfs , dev -> persist -> nvfs , sizeof (dev -> persist -> nvfs ));
3396
+
3397
+ mutex_lock (& persist -> interface_state_mutex );
3398
+ if (!(persist -> interface_state & MLX4_INTERFACE_STATE_UP )) {
3399
+ ret = mlx4_load_one (pdev , priv -> pci_dev_data , total_vfs , nvfs ,
3400
+ priv );
3401
+ if (ret ) {
3402
+ mlx4_err (dev , "%s: mlx4_load_one failed, ret=%d\n" ,
3403
+ __func__ , ret );
3404
+ goto end ;
3405
+ }
3406
+
3407
+ ret = restore_current_port_types (dev , dev -> persist ->
3408
+ curr_port_type , dev -> persist ->
3409
+ curr_port_poss_type );
3410
+ if (ret )
3411
+ mlx4_err (dev , "could not restore original port types (%d)\n" , ret );
3412
+ }
3413
+ end :
3414
+ mutex_unlock (& persist -> interface_state_mutex );
3367
3415
3368
3416
return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED ;
3369
3417
}
3370
3418
3419
+ static void mlx4_shutdown (struct pci_dev * pdev )
3420
+ {
3421
+ struct mlx4_dev_persistent * persist = pci_get_drvdata (pdev );
3422
+
3423
+ mlx4_info (persist -> dev , "mlx4_shutdown was called\n" );
3424
+ mutex_lock (& persist -> interface_state_mutex );
3425
+ if (persist -> interface_state & MLX4_INTERFACE_STATE_UP )
3426
+ mlx4_unload_one (pdev );
3427
+ mutex_unlock (& persist -> interface_state_mutex );
3428
+ }
3429
+
3371
3430
static const struct pci_error_handlers mlx4_err_handler = {
3372
3431
.error_detected = mlx4_pci_err_detected ,
3373
3432
.slot_reset = mlx4_pci_slot_reset ,
@@ -3377,7 +3436,7 @@ static struct pci_driver mlx4_driver = {
3377
3436
.name = DRV_NAME ,
3378
3437
.id_table = mlx4_pci_table ,
3379
3438
.probe = mlx4_init_one ,
3380
- .shutdown = mlx4_unload_one ,
3439
+ .shutdown = mlx4_shutdown ,
3381
3440
.remove = mlx4_remove_one ,
3382
3441
.err_handler = & mlx4_err_handler ,
3383
3442
};
0 commit comments