@@ -81,6 +81,7 @@ struct mlx5_device_context {
81
81
struct list_head list ;
82
82
struct mlx5_interface * intf ;
83
83
void * context ;
84
+ unsigned long state ;
84
85
};
85
86
86
87
enum {
@@ -778,6 +779,11 @@ static int mlx5_core_set_issi(struct mlx5_core_dev *dev)
778
779
return - ENOTSUPP ;
779
780
}
780
781
782
+ enum {
783
+ MLX5_INTERFACE_ADDED ,
784
+ MLX5_INTERFACE_ATTACHED ,
785
+ };
786
+
781
787
static void mlx5_add_device (struct mlx5_interface * intf , struct mlx5_priv * priv )
782
788
{
783
789
struct mlx5_device_context * dev_ctx ;
@@ -786,12 +792,15 @@ static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
786
792
if (!mlx5_lag_intf_add (intf , priv ))
787
793
return ;
788
794
789
- dev_ctx = kmalloc (sizeof (* dev_ctx ), GFP_KERNEL );
795
+ dev_ctx = kzalloc (sizeof (* dev_ctx ), GFP_KERNEL );
790
796
if (!dev_ctx )
791
797
return ;
792
798
793
- dev_ctx -> intf = intf ;
799
+ dev_ctx -> intf = intf ;
794
800
dev_ctx -> context = intf -> add (dev );
801
+ set_bit (MLX5_INTERFACE_ADDED , & dev_ctx -> state );
802
+ if (intf -> attach )
803
+ set_bit (MLX5_INTERFACE_ATTACHED , & dev_ctx -> state );
795
804
796
805
if (dev_ctx -> context ) {
797
806
spin_lock_irq (& priv -> ctx_lock );
@@ -802,21 +811,114 @@ static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
802
811
}
803
812
}
804
813
814
+ static struct mlx5_device_context * mlx5_get_device (struct mlx5_interface * intf ,
815
+ struct mlx5_priv * priv )
816
+ {
817
+ struct mlx5_device_context * dev_ctx ;
818
+
819
+ list_for_each_entry (dev_ctx , & priv -> ctx_list , list )
820
+ if (dev_ctx -> intf == intf )
821
+ return dev_ctx ;
822
+ return NULL ;
823
+ }
824
+
805
825
static void mlx5_remove_device (struct mlx5_interface * intf , struct mlx5_priv * priv )
806
826
{
807
827
struct mlx5_device_context * dev_ctx ;
808
828
struct mlx5_core_dev * dev = container_of (priv , struct mlx5_core_dev , priv );
809
829
810
- list_for_each_entry (dev_ctx , & priv -> ctx_list , list )
811
- if (dev_ctx -> intf == intf ) {
812
- spin_lock_irq (& priv -> ctx_lock );
813
- list_del (& dev_ctx -> list );
814
- spin_unlock_irq (& priv -> ctx_lock );
830
+ dev_ctx = mlx5_get_device (intf , priv );
831
+ if (!dev_ctx )
832
+ return ;
833
+
834
+ spin_lock_irq (& priv -> ctx_lock );
835
+ list_del (& dev_ctx -> list );
836
+ spin_unlock_irq (& priv -> ctx_lock );
837
+
838
+ if (test_bit (MLX5_INTERFACE_ADDED , & dev_ctx -> state ))
839
+ intf -> remove (dev , dev_ctx -> context );
815
840
816
- intf -> remove (dev , dev_ctx -> context );
817
- kfree (dev_ctx );
841
+ kfree (dev_ctx );
842
+ }
843
+
844
+ static void mlx5_attach_interface (struct mlx5_interface * intf , struct mlx5_priv * priv )
845
+ {
846
+ struct mlx5_device_context * dev_ctx ;
847
+ struct mlx5_core_dev * dev = container_of (priv , struct mlx5_core_dev , priv );
848
+
849
+ dev_ctx = mlx5_get_device (intf , priv );
850
+ if (!dev_ctx )
851
+ return ;
852
+
853
+ if (intf -> attach ) {
854
+ if (test_bit (MLX5_INTERFACE_ATTACHED , & dev_ctx -> state ))
818
855
return ;
819
- }
856
+ intf -> attach (dev , dev_ctx -> context );
857
+ set_bit (MLX5_INTERFACE_ATTACHED , & dev_ctx -> state );
858
+ } else {
859
+ if (test_bit (MLX5_INTERFACE_ADDED , & dev_ctx -> state ))
860
+ return ;
861
+ dev_ctx -> context = intf -> add (dev );
862
+ set_bit (MLX5_INTERFACE_ADDED , & dev_ctx -> state );
863
+ }
864
+ }
865
+
866
+ static void mlx5_attach_device (struct mlx5_core_dev * dev )
867
+ {
868
+ struct mlx5_priv * priv = & dev -> priv ;
869
+ struct mlx5_interface * intf ;
870
+
871
+ mutex_lock (& mlx5_intf_mutex );
872
+ list_for_each_entry (intf , & intf_list , list )
873
+ mlx5_attach_interface (intf , priv );
874
+ mutex_unlock (& mlx5_intf_mutex );
875
+ }
876
+
877
+ static void mlx5_detach_interface (struct mlx5_interface * intf , struct mlx5_priv * priv )
878
+ {
879
+ struct mlx5_device_context * dev_ctx ;
880
+ struct mlx5_core_dev * dev = container_of (priv , struct mlx5_core_dev , priv );
881
+
882
+ dev_ctx = mlx5_get_device (intf , priv );
883
+ if (!dev_ctx )
884
+ return ;
885
+
886
+ if (intf -> detach ) {
887
+ if (!test_bit (MLX5_INTERFACE_ATTACHED , & dev_ctx -> state ))
888
+ return ;
889
+ intf -> detach (dev , dev_ctx -> context );
890
+ clear_bit (MLX5_INTERFACE_ATTACHED , & dev_ctx -> state );
891
+ } else {
892
+ if (!test_bit (MLX5_INTERFACE_ADDED , & dev_ctx -> state ))
893
+ return ;
894
+ intf -> remove (dev , dev_ctx -> context );
895
+ clear_bit (MLX5_INTERFACE_ADDED , & dev_ctx -> state );
896
+ }
897
+ }
898
+
899
+ static void mlx5_detach_device (struct mlx5_core_dev * dev )
900
+ {
901
+ struct mlx5_priv * priv = & dev -> priv ;
902
+ struct mlx5_interface * intf ;
903
+
904
+ mutex_lock (& mlx5_intf_mutex );
905
+ list_for_each_entry (intf , & intf_list , list )
906
+ mlx5_detach_interface (intf , priv );
907
+ mutex_unlock (& mlx5_intf_mutex );
908
+ }
909
+
910
+ static bool mlx5_device_registered (struct mlx5_core_dev * dev )
911
+ {
912
+ struct mlx5_priv * priv ;
913
+ bool found = false;
914
+
915
+ mutex_lock (& mlx5_intf_mutex );
916
+ list_for_each_entry (priv , & mlx5_dev_list , dev_list )
917
+ if (priv == & dev -> priv )
918
+ found = true;
919
+ mutex_unlock (& mlx5_intf_mutex );
920
+
921
+ return found ;
820
922
}
821
923
822
924
static int mlx5_register_device (struct mlx5_core_dev * dev )
@@ -1162,16 +1264,16 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
1162
1264
goto err_sriov ;
1163
1265
}
1164
1266
1165
- err = mlx5_register_device (dev );
1166
- if (err ) {
1167
- dev_err (& pdev -> dev , "mlx5_register_device failed %d\n" , err );
1168
- goto err_reg_dev ;
1267
+ if (mlx5_device_registered (dev )) {
1268
+ mlx5_attach_device (dev );
1269
+ } else {
1270
+ err = mlx5_register_device (dev );
1271
+ if (err ) {
1272
+ dev_err (& pdev -> dev , "mlx5_register_device failed %d\n" , err );
1273
+ goto err_reg_dev ;
1274
+ }
1169
1275
}
1170
1276
1171
- err = request_module_nowait (MLX5_IB_MOD );
1172
- if (err )
1173
- pr_info ("failed request module on %s\n" , MLX5_IB_MOD );
1174
-
1175
1277
clear_bit (MLX5_INTERFACE_STATE_DOWN , & dev -> intf_state );
1176
1278
set_bit (MLX5_INTERFACE_STATE_UP , & dev -> intf_state );
1177
1279
out :
@@ -1247,12 +1349,13 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
1247
1349
goto out ;
1248
1350
}
1249
1351
1352
+ if (mlx5_device_registered (dev ))
1353
+ mlx5_detach_device (dev );
1354
+
1250
1355
mlx5_sriov_cleanup (dev );
1251
- mlx5_unregister_device (dev );
1252
1356
#ifdef CONFIG_MLX5_CORE_EN
1253
1357
mlx5_eswitch_cleanup (dev -> priv .eswitch );
1254
1358
#endif
1255
-
1256
1359
mlx5_cleanup_rl_table (dev );
1257
1360
mlx5_cleanup_fs (dev );
1258
1361
mlx5_cleanup_mkey_table (dev );
@@ -1364,6 +1467,9 @@ static int init_one(struct pci_dev *pdev,
1364
1467
dev_err (& pdev -> dev , "mlx5_load_one failed with error code %d\n" , err );
1365
1468
goto clean_health ;
1366
1469
}
1470
+ err = request_module_nowait (MLX5_IB_MOD );
1471
+ if (err )
1472
+ pr_info ("failed request module on %s\n" , MLX5_IB_MOD );
1367
1473
1368
1474
err = devlink_register (devlink , & pdev -> dev );
1369
1475
if (err )
@@ -1391,11 +1497,14 @@ static void remove_one(struct pci_dev *pdev)
1391
1497
struct mlx5_priv * priv = & dev -> priv ;
1392
1498
1393
1499
devlink_unregister (devlink );
1500
+ mlx5_unregister_device (dev );
1501
+
1394
1502
if (mlx5_unload_one (dev , priv )) {
1395
1503
dev_err (& dev -> pdev -> dev , "mlx5_unload_one failed\n" );
1396
1504
mlx5_health_cleanup (dev );
1397
1505
return ;
1398
1506
}
1507
+
1399
1508
mlx5_health_cleanup (dev );
1400
1509
mlx5_pci_close (dev , priv );
1401
1510
pci_set_drvdata (pdev , NULL );
0 commit comments