@@ -42,6 +42,19 @@ static struct smc_lgr_list smc_lgr_list = { /* established link groups */
4242static void smc_buf_free (struct smc_link_group * lgr , bool is_rmb ,
4343 struct smc_buf_desc * buf_desc );
4444
45+ /* return head of link group list and its lock for a given link group */
46+ static inline struct list_head * smc_lgr_list_head (struct smc_link_group * lgr ,
47+ spinlock_t * * lgr_lock )
48+ {
49+ if (lgr -> is_smcd ) {
50+ * lgr_lock = & lgr -> smcd -> lgr_lock ;
51+ return & lgr -> smcd -> lgr_list ;
52+ }
53+
54+ * lgr_lock = & smc_lgr_list .lock ;
55+ return & smc_lgr_list .list ;
56+ }
57+
4558static void smc_lgr_schedule_free_work (struct smc_link_group * lgr )
4659{
4760 /* client link group creation always follows the server link group
@@ -157,19 +170,21 @@ static void smc_lgr_free_work(struct work_struct *work)
157170 struct smc_link_group * lgr = container_of (to_delayed_work (work ),
158171 struct smc_link_group ,
159172 free_work );
173+ spinlock_t * lgr_lock ;
160174 bool conns ;
161175
162- spin_lock_bh (& smc_lgr_list .lock );
176+ smc_lgr_list_head (lgr , & lgr_lock );
177+ spin_lock_bh (lgr_lock );
163178 read_lock_bh (& lgr -> conns_lock );
164179 conns = RB_EMPTY_ROOT (& lgr -> conns_all );
165180 read_unlock_bh (& lgr -> conns_lock );
166181 if (!conns ) { /* number of lgr connections is no longer zero */
167- spin_unlock_bh (& smc_lgr_list . lock );
182+ spin_unlock_bh (lgr_lock );
168183 return ;
169184 }
170185 if (!list_empty (& lgr -> list ))
171186 list_del_init (& lgr -> list ); /* remove from smc_lgr_list */
172- spin_unlock_bh (& smc_lgr_list . lock );
187+ spin_unlock_bh (lgr_lock );
173188
174189 if (!lgr -> is_smcd && !lgr -> terminating ) {
175190 struct smc_link * lnk = & lgr -> lnk [SMC_SINGLE_LINK ];
@@ -200,6 +215,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
200215 struct smc_link_group * lgr ;
201216 struct list_head * lgr_list ;
202217 struct smc_link * lnk ;
218+ spinlock_t * lgr_lock ;
203219 u8 rndvec [3 ];
204220 int rc = 0 ;
205221 int i ;
@@ -235,6 +251,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
235251 lgr -> peer_gid = ini -> ism_gid ;
236252 lgr -> smcd = ini -> ism_dev ;
237253 lgr_list = & ini -> ism_dev -> lgr_list ;
254+ lgr_lock = & lgr -> smcd -> lgr_lock ;
238255 } else {
239256 /* SMC-R specific settings */
240257 lgr -> role = smc -> listen_smc ? SMC_SERV : SMC_CLNT ;
@@ -248,6 +265,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
248265 lnk -> smcibdev = ini -> ib_dev ;
249266 lnk -> ibport = ini -> ib_port ;
250267 lgr_list = & smc_lgr_list .list ;
268+ lgr_lock = & smc_lgr_list .lock ;
251269 lnk -> path_mtu =
252270 ini -> ib_dev -> pattr [ini -> ib_port - 1 ].active_mtu ;
253271 if (!ini -> ib_dev -> initialized )
@@ -277,9 +295,9 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
277295 goto destroy_qp ;
278296 }
279297 smc -> conn .lgr = lgr ;
280- spin_lock_bh (& smc_lgr_list . lock );
298+ spin_lock_bh (lgr_lock );
281299 list_add (& lgr -> list , lgr_list );
282- spin_unlock_bh (& smc_lgr_list . lock );
300+ spin_unlock_bh (lgr_lock );
283301 return 0 ;
284302
285303destroy_qp :
@@ -442,11 +460,15 @@ static void smc_lgr_free(struct smc_link_group *lgr)
442460
443461void smc_lgr_forget (struct smc_link_group * lgr )
444462{
445- spin_lock_bh (& smc_lgr_list .lock );
463+ struct list_head * lgr_list ;
464+ spinlock_t * lgr_lock ;
465+
466+ lgr_list = smc_lgr_list_head (lgr , & lgr_lock );
467+ spin_lock_bh (lgr_lock );
446468 /* do not use this link group for new connections */
447- if (!list_empty (& lgr -> list ))
448- list_del_init (& lgr -> list );
449- spin_unlock_bh (& smc_lgr_list . lock );
469+ if (!list_empty (lgr_list ))
470+ list_del_init (lgr_list );
471+ spin_unlock_bh (lgr_lock );
450472}
451473
452474/* terminate linkgroup abnormally */
@@ -487,9 +509,12 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr)
487509
488510void smc_lgr_terminate (struct smc_link_group * lgr )
489511{
490- spin_lock_bh (& smc_lgr_list .lock );
512+ spinlock_t * lgr_lock ;
513+
514+ smc_lgr_list_head (lgr , & lgr_lock );
515+ spin_lock_bh (lgr_lock );
491516 __smc_lgr_terminate (lgr );
492- spin_unlock_bh (& smc_lgr_list . lock );
517+ spin_unlock_bh (lgr_lock );
493518}
494519
495520/* Called when IB port is terminated */
@@ -514,15 +539,15 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
514539 LIST_HEAD (lgr_free_list );
515540
516541 /* run common cleanup function and build free list */
517- spin_lock_bh (& smc_lgr_list . lock );
542+ spin_lock_bh (& dev -> lgr_lock );
518543 list_for_each_entry_safe (lgr , l , & dev -> lgr_list , list ) {
519544 if ((!peer_gid || lgr -> peer_gid == peer_gid ) &&
520545 (vlan == VLAN_VID_MASK || lgr -> vlan_id == vlan )) {
521546 __smc_lgr_terminate (lgr );
522547 list_move (& lgr -> list , & lgr_free_list );
523548 }
524549 }
525- spin_unlock_bh (& smc_lgr_list . lock );
550+ spin_unlock_bh (& dev -> lgr_lock );
526551
527552 /* cancel the regular free workers and actually free lgrs */
528553 list_for_each_entry_safe (lgr , l , & lgr_free_list , list ) {
@@ -609,17 +634,19 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
609634 struct list_head * lgr_list ;
610635 struct smc_link_group * lgr ;
611636 enum smc_lgr_role role ;
637+ spinlock_t * lgr_lock ;
612638 int rc = 0 ;
613639
614640 lgr_list = ini -> is_smcd ? & ini -> ism_dev -> lgr_list : & smc_lgr_list .list ;
641+ lgr_lock = ini -> is_smcd ? & ini -> ism_dev -> lgr_lock : & smc_lgr_list .lock ;
615642 ini -> cln_first_contact = SMC_FIRST_CONTACT ;
616643 role = smc -> listen_smc ? SMC_SERV : SMC_CLNT ;
617644 if (role == SMC_CLNT && ini -> srv_first_contact )
618645 /* create new link group as well */
619646 goto create ;
620647
621648 /* determine if an existing link group can be reused */
622- spin_lock_bh (& smc_lgr_list . lock );
649+ spin_lock_bh (lgr_lock );
623650 list_for_each_entry (lgr , lgr_list , list ) {
624651 write_lock_bh (& lgr -> conns_lock );
625652 if ((ini -> is_smcd ?
@@ -640,7 +667,7 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
640667 }
641668 write_unlock_bh (& lgr -> conns_lock );
642669 }
643- spin_unlock_bh (& smc_lgr_list . lock );
670+ spin_unlock_bh (lgr_lock );
644671
645672 if (role == SMC_CLNT && !ini -> srv_first_contact &&
646673 ini -> cln_first_contact == SMC_FIRST_CONTACT ) {
0 commit comments