@ -3172,6 +3172,34 @@ static int mlx4_check_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap
return 0 ;
}
static int mlx4_pci_enable_device ( struct mlx4_dev * dev )
{
struct pci_dev * pdev = dev - > persist - > pdev ;
int err = 0 ;
mutex_lock ( & dev - > persist - > pci_status_mutex ) ;
if ( dev - > persist - > pci_status = = MLX4_PCI_STATUS_DISABLED ) {
err = pci_enable_device ( pdev ) ;
if ( ! err )
dev - > persist - > pci_status = MLX4_PCI_STATUS_ENABLED ;
}
mutex_unlock ( & dev - > persist - > pci_status_mutex ) ;
return err ;
}
static void mlx4_pci_disable_device ( struct mlx4_dev * dev )
{
struct pci_dev * pdev = dev - > persist - > pdev ;
mutex_lock ( & dev - > persist - > pci_status_mutex ) ;
if ( dev - > persist - > pci_status = = MLX4_PCI_STATUS_ENABLED ) {
pci_disable_device ( pdev ) ;
dev - > persist - > pci_status = MLX4_PCI_STATUS_DISABLED ;
}
mutex_unlock ( & dev - > persist - > pci_status_mutex ) ;
}
static int mlx4_load_one ( struct pci_dev * pdev , int pci_dev_data ,
int total_vfs , int * nvfs , struct mlx4_priv * priv ,
int reset_flow )
@ -3582,7 +3610,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data,
pr_info ( DRV_NAME " : Initializing %s \n " , pci_name ( pdev ) ) ;
err = pci_enable_device ( pdev ) ;
err = mlx4_ pci_enable_device( & priv - > dev ) ;
if ( err ) {
dev_err ( & pdev - > dev , " Cannot enable PCI device, aborting \n " ) ;
return err ;
@ -3715,7 +3743,7 @@ err_release_regions:
pci_release_regions ( pdev ) ;
err_disable_pdev :
pci_disable_device ( pdev ) ;
mlx4_ pci_disable_device( & priv - > dev ) ;
pci_set_drvdata ( pdev , NULL ) ;
return err ;
}
@ -3775,6 +3803,7 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
priv - > pci_dev_data = id - > driver_data ;
mutex_init ( & dev - > persist - > device_state_mutex ) ;
mutex_init ( & dev - > persist - > interface_state_mutex ) ;
mutex_init ( & dev - > persist - > pci_status_mutex ) ;
ret = devlink_register ( devlink , & pdev - > dev ) ;
if ( ret )
@ -3923,7 +3952,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
}
pci_release_regions ( pdev ) ;
pci_disable_device ( p dev) ;
mlx4_ pci_disable_device( dev ) ;
devlink_unregister ( devlink ) ;
kfree ( dev - > persist ) ;
devlink_free ( devlink ) ;
@ -4042,7 +4071,7 @@ static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
if ( state = = pci_channel_io_perm_failure )
return PCI_ERS_RESULT_DISCONNECT ;
pci_disable_device ( pdev ) ;
mlx4_ pci_disable_device( persist - > dev ) ;
return PCI_ERS_RESULT_NEED_RESET ;
}
@ -4050,45 +4079,53 @@ static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev)
{
struct mlx4_dev_persistent * persist = pci_get_drvdata ( pdev ) ;
struct mlx4_dev * dev = persist - > dev ;
struct mlx4_priv * priv = mlx4_priv ( dev ) ;
int ret ;
int nvfs [ MLX4_MAX_PORTS + 1 ] = { 0 , 0 , 0 } ;
int total_vfs ;
int err ;
mlx4_err ( dev , " mlx4_pci_slot_reset was called \n " ) ;
ret = pci_enable_device ( p dev) ;
if ( ret ) {
mlx4_err ( dev , " Can not re-enable device, ret =%d \n " , ret ) ;
err = mlx4_pci_enable_device ( dev ) ;
if ( err ) {
mlx4_err ( dev , " Can not re-enable device, err =%d \n " , err ) ;
return PCI_ERS_RESULT_DISCONNECT ;
}
pci_set_master ( pdev ) ;
pci_restore_state ( pdev ) ;
pci_save_state ( pdev ) ;
return PCI_ERS_RESULT_RECOVERED ;
}
static void mlx4_pci_resume ( struct pci_dev * pdev )
{
struct mlx4_dev_persistent * persist = pci_get_drvdata ( pdev ) ;
struct mlx4_dev * dev = persist - > dev ;
struct mlx4_priv * priv = mlx4_priv ( dev ) ;
int nvfs [ MLX4_MAX_PORTS + 1 ] = { 0 , 0 , 0 } ;
int total_vfs ;
int err ;
mlx4_err ( dev , " %s was called \n " , __func__ ) ;
total_vfs = dev - > persist - > num_vfs ;
memcpy ( nvfs , dev - > persist - > nvfs , sizeof ( dev - > persist - > nvfs ) ) ;
mutex_lock ( & persist - > interface_state_mutex ) ;
if ( ! ( persist - > interface_state & MLX4_INTERFACE_STATE_UP ) ) {
ret = mlx4_load_one ( pdev , priv - > pci_dev_data , total_vfs , nvfs ,
err = mlx4_load_one ( pdev , priv - > pci_dev_data , total_vfs , nvfs ,
priv , 1 ) ;
if ( ret ) {
mlx4_err ( dev , " %s: mlx4_load_one failed, ret=%d \n " ,
__func__ , ret ) ;
if ( err ) {
mlx4_err ( dev , " %s: mlx4_load_one failed, err =%d \n " ,
__func__ , err ) ;
goto end ;
}
ret = restore_current_port_types ( dev , dev - > persist - >
err = restore_current_port_types ( dev , dev - > persist - >
curr_port_type , dev - > persist - >
curr_port_poss_type ) ;
if ( ret )
mlx4_err ( dev , " could not restore original port types (%d) \n " , ret ) ;
if ( err )
mlx4_err ( dev , " could not restore original port types (%d) \n " , err ) ;
}
end :
mutex_unlock ( & persist - > interface_state_mutex ) ;
return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED ;
}
static void mlx4_shutdown ( struct pci_dev * pdev )
@ -4105,6 +4142,7 @@ static void mlx4_shutdown(struct pci_dev *pdev)
static const struct pci_error_handlers mlx4_err_handler = {
. error_detected = mlx4_pci_err_detected ,
. slot_reset = mlx4_pci_slot_reset ,
. resume = mlx4_pci_resume ,
} ;
static struct pci_driver mlx4_driver = {