Skip to content

Commit 9c41687

Browse files
karstengrdavem330
authored andcommitted
net/smc: delete link processing as SMC client
Add smc_llc_process_cli_delete_link() to process a DELETE_LINK request as SMC client. When the request is to delete ALL links then terminate the whole link group. If not, find the link to delete by its link_id, send the DELETE_LINK response LLC message and then clear the deleted link. Finally determine and update the link group state. Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Reviewed-by: Ursula Braun <ubraun@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9ec6bf1 commit 9c41687

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

net/smc/smc_llc.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,18 @@ static void smc_llc_process_cli_add_link(struct smc_link_group *lgr)
863863
mutex_unlock(&lgr->llc_conf_mutex);
864864
}
865865

866+
static int smc_llc_active_link_count(struct smc_link_group *lgr)
867+
{
868+
int i, link_count = 0;
869+
870+
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
871+
if (!smc_link_usable(&lgr->lnk[i]))
872+
continue;
873+
link_count++;
874+
}
875+
return link_count;
876+
}
877+
866878
/* find the asymmetric link when 3 links are established */
867879
static struct smc_link *smc_llc_find_asym_link(struct smc_link_group *lgr)
868880
{
@@ -1118,6 +1130,63 @@ static void smc_llc_add_link_work(struct work_struct *work)
11181130
smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
11191131
}
11201132

1133+
static void smc_llc_process_cli_delete_link(struct smc_link_group *lgr)
1134+
{
1135+
struct smc_link *lnk_del = NULL, *lnk_asym, *lnk;
1136+
struct smc_llc_msg_del_link *del_llc;
1137+
struct smc_llc_qentry *qentry;
1138+
int active_links;
1139+
int lnk_idx;
1140+
1141+
qentry = smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl);
1142+
lnk = qentry->link;
1143+
del_llc = &qentry->msg.delete_link;
1144+
1145+
if (del_llc->hd.flags & SMC_LLC_FLAG_DEL_LINK_ALL) {
1146+
smc_lgr_terminate_sched(lgr);
1147+
goto out;
1148+
}
1149+
mutex_lock(&lgr->llc_conf_mutex);
1150+
/* delete single link */
1151+
for (lnk_idx = 0; lnk_idx < SMC_LINKS_PER_LGR_MAX; lnk_idx++) {
1152+
if (lgr->lnk[lnk_idx].link_id != del_llc->link_num)
1153+
continue;
1154+
lnk_del = &lgr->lnk[lnk_idx];
1155+
break;
1156+
}
1157+
del_llc->hd.flags |= SMC_LLC_FLAG_RESP;
1158+
if (!lnk_del) {
1159+
/* link was not found */
1160+
del_llc->reason = htonl(SMC_LLC_DEL_NOLNK);
1161+
smc_llc_send_message(lnk, &qentry->msg);
1162+
goto out_unlock;
1163+
}
1164+
lnk_asym = smc_llc_find_asym_link(lgr);
1165+
1166+
del_llc->reason = 0;
1167+
smc_llc_send_message(lnk, &qentry->msg); /* response */
1168+
1169+
if (smc_link_downing(&lnk_del->state)) {
1170+
/* tbd: call smc_switch_conns(lgr, lnk_del, false); */
1171+
smc_wr_tx_wait_no_pending_sends(lnk_del);
1172+
}
1173+
smcr_link_clear(lnk_del);
1174+
1175+
active_links = smc_llc_active_link_count(lgr);
1176+
if (lnk_del == lnk_asym) {
1177+
/* expected deletion of asym link, don't change lgr state */
1178+
} else if (active_links == 1) {
1179+
lgr->type = SMC_LGR_SINGLE;
1180+
} else if (!active_links) {
1181+
lgr->type = SMC_LGR_NONE;
1182+
smc_lgr_terminate_sched(lgr);
1183+
}
1184+
out_unlock:
1185+
mutex_unlock(&lgr->llc_conf_mutex);
1186+
out:
1187+
kfree(qentry);
1188+
}
1189+
11211190
static void smc_llc_delete_link_work(struct work_struct *work)
11221191
{
11231192
struct smc_link_group *lgr = container_of(work, struct smc_link_group,
@@ -1128,6 +1197,9 @@ static void smc_llc_delete_link_work(struct work_struct *work)
11281197
smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
11291198
goto out;
11301199
}
1200+
1201+
if (lgr->role == SMC_CLNT)
1202+
smc_llc_process_cli_delete_link(lgr);
11311203
out:
11321204
smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
11331205
}

0 commit comments

Comments
 (0)