|
@@ -278,7 +278,7 @@ int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
|
|
|
/* prepare a delete link message */
|
|
|
static void smc_llc_prep_delete_link(struct smc_llc_msg_del_link *delllc,
|
|
|
struct smc_link *link,
|
|
|
- enum smc_llc_reqresp reqresp)
|
|
|
+ enum smc_llc_reqresp reqresp, bool orderly)
|
|
|
{
|
|
|
memset(delllc, 0, sizeof(*delllc));
|
|
|
delllc->hd.common.type = SMC_LLC_DELETE_LINK;
|
|
@@ -287,13 +287,14 @@ static void smc_llc_prep_delete_link(struct smc_llc_msg_del_link *delllc,
|
|
|
delllc->hd.flags |= SMC_LLC_FLAG_RESP;
|
|
|
/* DEL_LINK_ALL because only 1 link supported */
|
|
|
delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ALL;
|
|
|
- delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
|
|
|
+ if (orderly)
|
|
|
+ delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
|
|
|
delllc->link_num = link->link_id;
|
|
|
}
|
|
|
|
|
|
/* send DELETE LINK request or response */
|
|
|
int smc_llc_send_delete_link(struct smc_link *link,
|
|
|
- enum smc_llc_reqresp reqresp)
|
|
|
+ enum smc_llc_reqresp reqresp, bool orderly)
|
|
|
{
|
|
|
struct smc_llc_msg_del_link *delllc;
|
|
|
struct smc_wr_tx_pend_priv *pend;
|
|
@@ -304,7 +305,7 @@ int smc_llc_send_delete_link(struct smc_link *link,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
delllc = (struct smc_llc_msg_del_link *)wr_buf;
|
|
|
- smc_llc_prep_delete_link(delllc, link, reqresp);
|
|
|
+ smc_llc_prep_delete_link(delllc, link, reqresp, orderly);
|
|
|
/* send llc message */
|
|
|
rc = smc_wr_tx_send(link, pend);
|
|
|
return rc;
|
|
@@ -438,17 +439,19 @@ static void smc_llc_rx_delete_link(struct smc_link *link,
|
|
|
|
|
|
if (llc->hd.flags & SMC_LLC_FLAG_RESP) {
|
|
|
if (lgr->role == SMC_SERV)
|
|
|
- smc_lgr_terminate(lgr);
|
|
|
+ smc_lgr_schedule_free_work_fast(lgr);
|
|
|
} else {
|
|
|
+ smc_lgr_forget(lgr);
|
|
|
+ smc_llc_link_deleting(link);
|
|
|
if (lgr->role == SMC_SERV) {
|
|
|
- smc_lgr_forget(lgr);
|
|
|
- smc_llc_prep_delete_link(llc, link, SMC_LLC_REQ);
|
|
|
- smc_llc_send_message(link, llc, sizeof(*llc));
|
|
|
+ /* client asks to delete this link, send request */
|
|
|
+ smc_llc_prep_delete_link(llc, link, SMC_LLC_REQ, true);
|
|
|
} else {
|
|
|
- smc_llc_prep_delete_link(llc, link, SMC_LLC_RESP);
|
|
|
- smc_llc_send_message(link, llc, sizeof(*llc));
|
|
|
- smc_lgr_terminate(lgr);
|
|
|
+ /* server requests to delete this link, send response */
|
|
|
+ smc_llc_prep_delete_link(llc, link, SMC_LLC_RESP, true);
|
|
|
}
|
|
|
+ smc_llc_send_message(link, llc, sizeof(*llc));
|
|
|
+ smc_lgr_schedule_free_work_fast(lgr);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -622,6 +625,11 @@ void smc_llc_link_active(struct smc_link *link, int testlink_time)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void smc_llc_link_deleting(struct smc_link *link)
|
|
|
+{
|
|
|
+ link->state = SMC_LNK_DELETING;
|
|
|
+}
|
|
|
+
|
|
|
/* called in tasklet context */
|
|
|
void smc_llc_link_inactive(struct smc_link *link)
|
|
|
{
|