@@ -237,6 +237,19 @@ void smc_lgr_cleanup_early(struct smc_connection *conn)
237237 smc_lgr_schedule_free_work_fast (lgr );
238238}
239239
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+
240253static void smc_lgr_free (struct smc_link_group * lgr );
241254
242255static void smc_lgr_free_work (struct work_struct * work )
@@ -246,7 +259,6 @@ static void smc_lgr_free_work(struct work_struct *work)
246259 free_work );
247260 spinlock_t * lgr_lock ;
248261 bool conns ;
249- int i ;
250262
251263 smc_lgr_list_head (lgr , & lgr_lock );
252264 spin_lock_bh (lgr_lock );
@@ -271,15 +283,8 @@ static void smc_lgr_free_work(struct work_struct *work)
271283 SMC_LLC_DEL_PROG_INIT_TERM );
272284 if (lgr -> is_smcd && !lgr -> terminating )
273285 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 );
283288 smc_lgr_free (lgr );
284289}
285290
@@ -802,6 +807,16 @@ static void smc_lgr_free(struct smc_link_group *lgr)
802807{
803808 int i ;
804809
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+
805820 smc_lgr_free_bufs (lgr );
806821 if (lgr -> is_smcd ) {
807822 if (!lgr -> terminating ) {
@@ -811,11 +826,6 @@ static void smc_lgr_free(struct smc_link_group *lgr)
811826 if (!atomic_dec_return (& lgr -> smcd -> lgr_cnt ))
812827 wake_up (& lgr -> smcd -> lgrs_deleted );
813828 } 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 );
819829 if (!atomic_dec_return (& lgr_cnt ))
820830 wake_up (& lgrs_deleted );
821831 }
@@ -870,8 +880,6 @@ static void smc_conn_kill(struct smc_connection *conn, bool soft)
870880
871881static void smc_lgr_cleanup (struct smc_link_group * lgr )
872882{
873- int i ;
874-
875883 if (lgr -> is_smcd ) {
876884 smc_ism_signal_shutdown (lgr );
877885 smcd_unregister_all_dmbs (lgr );
@@ -883,13 +891,7 @@ static void smc_lgr_cleanup(struct smc_link_group *lgr)
883891 if (!rsn )
884892 rsn = SMC_LLC_DEL_PROG_INIT_TERM ;
885893 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 );
893895 }
894896}
895897
@@ -905,8 +907,8 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft)
905907
906908 if (lgr -> terminating )
907909 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 );
910912 lgr -> terminating = 1 ;
911913
912914 /* kill remaining link group connections */
@@ -926,10 +928,7 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft)
926928 }
927929 read_unlock_bh (& lgr -> conns_lock );
928930 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 );
933932}
934933
935934/* unlink link group and schedule termination */
@@ -944,6 +943,7 @@ void smc_lgr_terminate_sched(struct smc_link_group *lgr)
944943 return ; /* lgr already terminating */
945944 }
946945 list_del_init (& lgr -> list );
946+ lgr -> freeing = 1 ;
947947 spin_unlock_bh (lgr_lock );
948948 schedule_work (& lgr -> terminate_work );
949949}
@@ -962,6 +962,7 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
962962 if (peer_gid ) /* peer triggered termination */
963963 lgr -> peer_shutdown = 1 ;
964964 list_move (& lgr -> list , & lgr_free_list );
965+ lgr -> freeing = 1 ;
965966 }
966967 }
967968 spin_unlock_bh (& dev -> lgr_lock );
0 commit comments