aboutsummaryrefslogtreecommitdiffstats
path: root/net/smc/smc_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/smc/smc_core.c')
-rw-r--r--net/smc/smc_core.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index 1382ddae591e..35c1cdc93e1c 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -189,6 +189,8 @@ free:
189 189
190 if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE) 190 if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE)
191 smc_llc_link_inactive(lnk); 191 smc_llc_link_inactive(lnk);
192 if (lgr->is_smcd)
193 smc_ism_signal_shutdown(lgr);
192 smc_lgr_free(lgr); 194 smc_lgr_free(lgr);
193 } 195 }
194} 196}
@@ -495,7 +497,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
495} 497}
496 498
497/* Called when SMC-D device is terminated or peer is lost */ 499/* Called when SMC-D device is terminated or peer is lost */
498void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid) 500void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
499{ 501{
500 struct smc_link_group *lgr, *l; 502 struct smc_link_group *lgr, *l;
501 LIST_HEAD(lgr_free_list); 503 LIST_HEAD(lgr_free_list);
@@ -505,7 +507,7 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
505 list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) { 507 list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) {
506 if (lgr->is_smcd && lgr->smcd == dev && 508 if (lgr->is_smcd && lgr->smcd == dev &&
507 (!peer_gid || lgr->peer_gid == peer_gid) && 509 (!peer_gid || lgr->peer_gid == peer_gid) &&
508 !list_empty(&lgr->list)) { 510 (vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
509 __smc_lgr_terminate(lgr); 511 __smc_lgr_terminate(lgr);
510 list_move(&lgr->list, &lgr_free_list); 512 list_move(&lgr->list, &lgr_free_list);
511 } 513 }
@@ -516,6 +518,8 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
516 list_for_each_entry_safe(lgr, l, &lgr_free_list, list) { 518 list_for_each_entry_safe(lgr, l, &lgr_free_list, list) {
517 list_del_init(&lgr->list); 519 list_del_init(&lgr->list);
518 cancel_delayed_work_sync(&lgr->free_work); 520 cancel_delayed_work_sync(&lgr->free_work);
521 if (!peer_gid && vlan == VLAN_VID_MASK) /* dev terminated? */
522 smc_ism_signal_shutdown(lgr);
519 smc_lgr_free(lgr); 523 smc_lgr_free(lgr);
520 } 524 }
521} 525}
@@ -569,7 +573,7 @@ out:
569 573
570static bool smcr_lgr_match(struct smc_link_group *lgr, 574static bool smcr_lgr_match(struct smc_link_group *lgr,
571 struct smc_clc_msg_local *lcl, 575 struct smc_clc_msg_local *lcl,
572 enum smc_lgr_role role) 576 enum smc_lgr_role role, u32 clcqpn)
573{ 577{
574 return !memcmp(lgr->peer_systemid, lcl->id_for_peer, 578 return !memcmp(lgr->peer_systemid, lcl->id_for_peer,
575 SMC_SYSTEMID_LEN) && 579 SMC_SYSTEMID_LEN) &&
@@ -577,7 +581,9 @@ static bool smcr_lgr_match(struct smc_link_group *lgr,
577 SMC_GID_SIZE) && 581 SMC_GID_SIZE) &&
578 !memcmp(lgr->lnk[SMC_SINGLE_LINK].peer_mac, lcl->mac, 582 !memcmp(lgr->lnk[SMC_SINGLE_LINK].peer_mac, lcl->mac,
579 sizeof(lcl->mac)) && 583 sizeof(lcl->mac)) &&
580 lgr->role == role; 584 lgr->role == role &&
585 (lgr->role == SMC_SERV ||
586 lgr->lnk[SMC_SINGLE_LINK].peer_qpn == clcqpn);
581} 587}
582 588
583static bool smcd_lgr_match(struct smc_link_group *lgr, 589static bool smcd_lgr_match(struct smc_link_group *lgr,
@@ -588,7 +594,7 @@ static bool smcd_lgr_match(struct smc_link_group *lgr,
588 594
589/* create a new SMC connection (and a new link group if necessary) */ 595/* create a new SMC connection (and a new link group if necessary) */
590int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact, 596int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
591 struct smc_ib_device *smcibdev, u8 ibport, 597 struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn,
592 struct smc_clc_msg_local *lcl, struct smcd_dev *smcd, 598 struct smc_clc_msg_local *lcl, struct smcd_dev *smcd,
593 u64 peer_gid) 599 u64 peer_gid)
594{ 600{
@@ -613,7 +619,7 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
613 list_for_each_entry(lgr, &smc_lgr_list.list, list) { 619 list_for_each_entry(lgr, &smc_lgr_list.list, list) {
614 write_lock_bh(&lgr->conns_lock); 620 write_lock_bh(&lgr->conns_lock);
615 if ((is_smcd ? smcd_lgr_match(lgr, smcd, peer_gid) : 621 if ((is_smcd ? smcd_lgr_match(lgr, smcd, peer_gid) :
616 smcr_lgr_match(lgr, lcl, role)) && 622 smcr_lgr_match(lgr, lcl, role, clcqpn)) &&
617 !lgr->sync_err && 623 !lgr->sync_err &&
618 lgr->vlan_id == vlan_id && 624 lgr->vlan_id == vlan_id &&
619 (role == SMC_CLNT || 625 (role == SMC_CLNT ||
@@ -1034,6 +1040,8 @@ void smc_core_exit(void)
1034 smc_llc_link_inactive(lnk); 1040 smc_llc_link_inactive(lnk);
1035 } 1041 }
1036 cancel_delayed_work_sync(&lgr->free_work); 1042 cancel_delayed_work_sync(&lgr->free_work);
1043 if (lgr->is_smcd)
1044 smc_ism_signal_shutdown(lgr);
1037 smc_lgr_free(lgr); /* free link group */ 1045 smc_lgr_free(lgr); /* free link group */
1038 } 1046 }
1039} 1047}