@@ -237,6 +237,19 @@ void smc_lgr_cleanup_early(struct smc_connection *conn)
237
237
smc_lgr_schedule_free_work_fast (lgr );
238
238
}
239
239
240
+ static void smcr_lgr_link_deactivate_all (struct smc_link_group * lgr )
241
+ {
242
+ int i ;
243
+
244
+ for (i = 0 ; i < SMC_LINKS_PER_LGR_MAX ; i ++ ) {
245
+ struct smc_link * lnk = & lgr -> lnk [i ];
246
+
247
+ if (smc_link_usable (lnk ))
248
+ lnk -> state = SMC_LNK_INACTIVE ;
249
+ }
250
+ wake_up_interruptible_all (& lgr -> llc_waiter );
251
+ }
252
+
240
253
static void smc_lgr_free (struct smc_link_group * lgr );
241
254
242
255
static void smc_lgr_free_work (struct work_struct * work )
@@ -246,7 +259,6 @@ static void smc_lgr_free_work(struct work_struct *work)
246
259
free_work );
247
260
spinlock_t * lgr_lock ;
248
261
bool conns ;
249
- int i ;
250
262
251
263
smc_lgr_list_head (lgr , & lgr_lock );
252
264
spin_lock_bh (lgr_lock );
@@ -271,15 +283,8 @@ static void smc_lgr_free_work(struct work_struct *work)
271
283
SMC_LLC_DEL_PROG_INIT_TERM );
272
284
if (lgr -> is_smcd && !lgr -> terminating )
273
285
smc_ism_signal_shutdown (lgr );
274
- if (!lgr -> is_smcd ) {
275
- for (i = 0 ; i < SMC_LINKS_PER_LGR_MAX ; i ++ ) {
276
- struct smc_link * lnk = & lgr -> lnk [i ];
277
-
278
- if (smc_link_usable (lnk ))
279
- lnk -> state = SMC_LNK_INACTIVE ;
280
- }
281
- wake_up_interruptible_all (& lgr -> llc_waiter );
282
- }
286
+ if (!lgr -> is_smcd )
287
+ smcr_lgr_link_deactivate_all (lgr );
283
288
smc_lgr_free (lgr );
284
289
}
285
290
@@ -802,6 +807,16 @@ static void smc_lgr_free(struct smc_link_group *lgr)
802
807
{
803
808
int i ;
804
809
810
+ if (!lgr -> is_smcd ) {
811
+ mutex_lock (& lgr -> llc_conf_mutex );
812
+ for (i = 0 ; i < SMC_LINKS_PER_LGR_MAX ; i ++ ) {
813
+ if (lgr -> lnk [i ].state != SMC_LNK_UNUSED )
814
+ smcr_link_clear (& lgr -> lnk [i ]);
815
+ }
816
+ mutex_unlock (& lgr -> llc_conf_mutex );
817
+ smc_llc_lgr_clear (lgr );
818
+ }
819
+
805
820
smc_lgr_free_bufs (lgr );
806
821
if (lgr -> is_smcd ) {
807
822
if (!lgr -> terminating ) {
@@ -811,11 +826,6 @@ static void smc_lgr_free(struct smc_link_group *lgr)
811
826
if (!atomic_dec_return (& lgr -> smcd -> lgr_cnt ))
812
827
wake_up (& lgr -> smcd -> lgrs_deleted );
813
828
} else {
814
- for (i = 0 ; i < SMC_LINKS_PER_LGR_MAX ; i ++ ) {
815
- if (lgr -> lnk [i ].state != SMC_LNK_UNUSED )
816
- smcr_link_clear (& lgr -> lnk [i ]);
817
- }
818
- smc_llc_lgr_clear (lgr );
819
829
if (!atomic_dec_return (& lgr_cnt ))
820
830
wake_up (& lgrs_deleted );
821
831
}
@@ -870,8 +880,6 @@ static void smc_conn_kill(struct smc_connection *conn, bool soft)
870
880
871
881
static void smc_lgr_cleanup (struct smc_link_group * lgr )
872
882
{
873
- int i ;
874
-
875
883
if (lgr -> is_smcd ) {
876
884
smc_ism_signal_shutdown (lgr );
877
885
smcd_unregister_all_dmbs (lgr );
@@ -883,13 +891,7 @@ static void smc_lgr_cleanup(struct smc_link_group *lgr)
883
891
if (!rsn )
884
892
rsn = SMC_LLC_DEL_PROG_INIT_TERM ;
885
893
smc_llc_send_link_delete_all (lgr , false, rsn );
886
- for (i = 0 ; i < SMC_LINKS_PER_LGR_MAX ; i ++ ) {
887
- struct smc_link * lnk = & lgr -> lnk [i ];
888
-
889
- if (smc_link_usable (lnk ))
890
- lnk -> state = SMC_LNK_INACTIVE ;
891
- }
892
- wake_up_interruptible_all (& lgr -> llc_waiter );
894
+ smcr_lgr_link_deactivate_all (lgr );
893
895
}
894
896
}
895
897
@@ -905,8 +907,8 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft)
905
907
906
908
if (lgr -> terminating )
907
909
return ; /* lgr already terminating */
908
- if (! soft )
909
- cancel_delayed_work_sync (& lgr -> free_work );
910
+ /* cancel free_work sync, will terminate when lgr->freeing is set */
911
+ cancel_delayed_work_sync (& lgr -> free_work );
910
912
lgr -> terminating = 1 ;
911
913
912
914
/* kill remaining link group connections */
@@ -926,10 +928,7 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft)
926
928
}
927
929
read_unlock_bh (& lgr -> conns_lock );
928
930
smc_lgr_cleanup (lgr );
929
- if (soft )
930
- smc_lgr_schedule_free_work_fast (lgr );
931
- else
932
- smc_lgr_free (lgr );
931
+ smc_lgr_free (lgr );
933
932
}
934
933
935
934
/* unlink link group and schedule termination */
@@ -944,6 +943,7 @@ void smc_lgr_terminate_sched(struct smc_link_group *lgr)
944
943
return ; /* lgr already terminating */
945
944
}
946
945
list_del_init (& lgr -> list );
946
+ lgr -> freeing = 1 ;
947
947
spin_unlock_bh (lgr_lock );
948
948
schedule_work (& lgr -> terminate_work );
949
949
}
@@ -962,6 +962,7 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
962
962
if (peer_gid ) /* peer triggered termination */
963
963
lgr -> peer_shutdown = 1 ;
964
964
list_move (& lgr -> list , & lgr_free_list );
965
+ lgr -> freeing = 1 ;
965
966
}
966
967
}
967
968
spin_unlock_bh (& dev -> lgr_lock );
0 commit comments