Commit fbed3b37 authored by Karsten Graul's avatar Karsten Graul Committed by David S. Miller

net/smc: extend smc_llc_send_add_link() and smc_llc_send_delete_link()

All LLC sends are done from worker context only, so remove the prep
functions which were used to build the message before it was sent, and
add the function content into the respective send function
smc_llc_send_add_link() and smc_llc_send_delete_link().
Extend smc_llc_send_add_link() to include the qp_mtu value in the LLC
message, which is needed to establish a link after the initial link was
created. Extend smc_llc_send_delete_link() to contain a link_id and a
reason code for the link deletion in the LLC message, which is needed
when a specific link should be deleted.
And add the list of existing DELETE_LINK reason codes.
Signed-off-by: default avatarKarsten Graul <kgraul@linux.ibm.com>
Reviewed-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fb33d277
......@@ -199,7 +199,8 @@ void smc_lgr_cleanup_early(struct smc_connection *conn)
static int smcr_link_send_delete(struct smc_link *lnk, bool orderly)
{
if (lnk->state == SMC_LNK_ACTIVE &&
!smc_llc_send_delete_link(lnk, SMC_LLC_REQ, orderly)) {
!smc_llc_send_delete_link(lnk, 0, SMC_LLC_REQ, orderly,
SMC_LLC_DEL_PROG_INIT_TERM)) {
return 0;
}
return -ENOTCONN;
......
......@@ -58,7 +58,13 @@ struct smc_llc_msg_add_link { /* type 0x02 */
u8 sender_gid[SMC_GID_SIZE];
u8 sender_qp_num[3];
u8 link_num;
u8 flags2; /* QP mtu */
#if defined(__BIG_ENDIAN_BITFIELD)
u8 reserved3 : 4,
qp_mtu : 4;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
u8 qp_mtu : 4,
reserved3 : 4;
#endif
u8 initial_psn[3];
u8 reserved[8];
};
......@@ -427,26 +433,9 @@ static int smc_llc_send_delete_rkey(struct smc_link *link,
return rc;
}
/* prepare an add link message */
static void smc_llc_prep_add_link(struct smc_llc_msg_add_link *addllc,
struct smc_link *link, u8 mac[], u8 gid[],
enum smc_llc_reqresp reqresp)
{
memset(addllc, 0, sizeof(*addllc));
addllc->hd.common.type = SMC_LLC_ADD_LINK;
addllc->hd.length = sizeof(struct smc_llc_msg_add_link);
if (reqresp == SMC_LLC_RESP) {
addllc->hd.flags |= SMC_LLC_FLAG_RESP;
/* always reject more links for now */
addllc->hd.flags |= SMC_LLC_FLAG_ADD_LNK_REJ;
addllc->hd.add_link_rej_rsn = SMC_LLC_REJ_RSN_NO_ALT_PATH;
}
memcpy(addllc->sender_mac, mac, ETH_ALEN);
memcpy(addllc->sender_gid, gid, SMC_GID_SIZE);
}
/* send ADD LINK request or response */
int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
struct smc_link *link_new,
enum smc_llc_reqresp reqresp)
{
struct smc_llc_msg_add_link *addllc;
......@@ -458,32 +447,33 @@ int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
if (rc)
return rc;
addllc = (struct smc_llc_msg_add_link *)wr_buf;
smc_llc_prep_add_link(addllc, link, mac, gid, reqresp);
memset(addllc, 0, sizeof(*addllc));
addllc->hd.common.type = SMC_LLC_ADD_LINK;
addllc->hd.length = sizeof(struct smc_llc_msg_add_link);
if (reqresp == SMC_LLC_RESP)
addllc->hd.flags |= SMC_LLC_FLAG_RESP;
memcpy(addllc->sender_mac, mac, ETH_ALEN);
memcpy(addllc->sender_gid, gid, SMC_GID_SIZE);
if (link_new) {
addllc->link_num = link_new->link_id;
hton24(addllc->sender_qp_num, link_new->roce_qp->qp_num);
hton24(addllc->initial_psn, link_new->psn_initial);
if (reqresp == SMC_LLC_REQ)
addllc->qp_mtu = link_new->path_mtu;
else
addllc->qp_mtu = min(link_new->path_mtu,
link_new->peer_mtu);
}
/* send llc message */
rc = smc_wr_tx_send(link, pend);
return rc;
}
/* 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, bool orderly)
{
memset(delllc, 0, sizeof(*delllc));
delllc->hd.common.type = SMC_LLC_DELETE_LINK;
delllc->hd.length = sizeof(struct smc_llc_msg_add_link);
if (reqresp == SMC_LLC_RESP)
delllc->hd.flags |= SMC_LLC_FLAG_RESP;
/* DEL_LINK_ALL because only 1 link supported */
delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ALL;
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, bool orderly)
int smc_llc_send_delete_link(struct smc_link *link, u8 link_del_id,
enum smc_llc_reqresp reqresp, bool orderly,
u32 reason)
{
struct smc_llc_msg_del_link *delllc;
struct smc_wr_tx_pend_priv *pend;
......@@ -494,7 +484,19 @@ 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, orderly);
memset(delllc, 0, sizeof(*delllc));
delllc->hd.common.type = SMC_LLC_DELETE_LINK;
delllc->hd.length = sizeof(struct smc_llc_msg_del_link);
if (reqresp == SMC_LLC_RESP)
delllc->hd.flags |= SMC_LLC_FLAG_RESP;
if (orderly)
delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
if (link_del_id)
delllc->link_num = link_del_id;
else
delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ALL;
delllc->reason = htonl(reason);
/* send llc message */
rc = smc_wr_tx_send(link, pend);
return rc;
......@@ -547,12 +549,13 @@ static void smc_llc_rx_delete_link(struct smc_link *link,
smc_lgr_forget(lgr);
if (lgr->role == SMC_SERV) {
/* client asks to delete this link, send request */
smc_llc_prep_delete_link(llc, link, SMC_LLC_REQ, true);
smc_llc_send_delete_link(link, 0, SMC_LLC_REQ, true,
SMC_LLC_DEL_PROG_INIT_TERM);
} else {
/* server requests to delete this link, send response */
smc_llc_prep_delete_link(llc, link, SMC_LLC_RESP, true);
smc_llc_send_delete_link(link, 0, SMC_LLC_RESP, true,
SMC_LLC_DEL_PROG_INIT_TERM);
}
smc_llc_send_message(link, llc);
smc_lgr_terminate_sched(lgr);
}
......
......@@ -35,6 +35,16 @@ enum smc_llc_msg_type {
SMC_LLC_DELETE_RKEY = 0x09,
};
/* LLC DELETE LINK Request Reason Codes */
#define SMC_LLC_DEL_LOST_PATH 0x00010000
#define SMC_LLC_DEL_OP_INIT_TERM 0x00020000
#define SMC_LLC_DEL_PROG_INIT_TERM 0x00030000
#define SMC_LLC_DEL_PROT_VIOL 0x00040000
#define SMC_LLC_DEL_NO_ASYM_NEEDED 0x00050000
/* LLC DELETE LINK Response Reason Codes */
#define SMC_LLC_DEL_NOLNK 0x00100000 /* Unknown Link ID (no link) */
#define SMC_LLC_DEL_NOLGR 0x00200000 /* Unknown Link Group */
/* returns a usable link of the link group, or NULL */
static inline struct smc_link *smc_llc_usable_link(struct smc_link_group *lgr)
{
......@@ -50,9 +60,11 @@ static inline struct smc_link *smc_llc_usable_link(struct smc_link_group *lgr)
int smc_llc_send_confirm_link(struct smc_link *lnk,
enum smc_llc_reqresp reqresp);
int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
struct smc_link *link_new,
enum smc_llc_reqresp reqresp);
int smc_llc_send_delete_link(struct smc_link *link,
enum smc_llc_reqresp reqresp, bool orderly);
int smc_llc_send_delete_link(struct smc_link *link, u8 link_del_id,
enum smc_llc_reqresp reqresp, bool orderly,
u32 reason);
void smc_llc_lgr_init(struct smc_link_group *lgr, struct smc_sock *smc);
void smc_llc_lgr_clear(struct smc_link_group *lgr);
int smc_llc_link_init(struct smc_link *link);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment