Commit b0c4b041 authored by David S. Miller's avatar David S. Miller

Merge branch 'smc-next'

Ursula Braun says:

====================
net/smc: patches 2018-11-22

here are more patches for SMC:
* patches 1-3 and 7 are cleanups without functional change
* patches 4-6 and 8 are optimizations of existing code
* patches 9 and 10 introduce and exploit LLC message DELETE RKEY
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e4a3e9ff c7674c00
...@@ -299,15 +299,18 @@ static void smc_copy_sock_settings_to_smc(struct smc_sock *smc) ...@@ -299,15 +299,18 @@ static void smc_copy_sock_settings_to_smc(struct smc_sock *smc)
smc_copy_sock_settings(&smc->sk, smc->clcsock->sk, SK_FLAGS_CLC_TO_SMC); smc_copy_sock_settings(&smc->sk, smc->clcsock->sk, SK_FLAGS_CLC_TO_SMC);
} }
/* register a new rmb, optionally send confirm_rkey msg to register with peer */ /* register a new rmb, send confirm_rkey msg to register with peer */
static int smc_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc, static int smc_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc,
bool conf_rkey) bool conf_rkey)
{ {
if (!rmb_desc->wr_reg) {
/* register memory region for new rmb */ /* register memory region for new rmb */
if (smc_wr_reg_send(link, rmb_desc->mr_rx[SMC_SINGLE_LINK])) { if (smc_wr_reg_send(link, rmb_desc->mr_rx[SMC_SINGLE_LINK])) {
rmb_desc->regerr = 1; rmb_desc->regerr = 1;
return -EFAULT; return -EFAULT;
} }
rmb_desc->wr_reg = 1;
}
if (!conf_rkey) if (!conf_rkey)
return 0; return 0;
/* exchange confirm_rkey msg with peer */ /* exchange confirm_rkey msg with peer */
...@@ -335,8 +338,8 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc) ...@@ -335,8 +338,8 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc)
struct smc_clc_msg_decline dclc; struct smc_clc_msg_decline dclc;
rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc), rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
SMC_CLC_DECLINE); SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
return rc; return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc;
} }
if (link->llc_confirm_rc) if (link->llc_confirm_rc)
...@@ -363,8 +366,8 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc) ...@@ -363,8 +366,8 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc)
struct smc_clc_msg_decline dclc; struct smc_clc_msg_decline dclc;
rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc), rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
SMC_CLC_DECLINE); SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
return rc; return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_AL : rc;
} }
/* send add link reject message, only one link supported for now */ /* send add link reject message, only one link supported for now */
...@@ -533,7 +536,8 @@ static int smc_connect_clc(struct smc_sock *smc, int smc_type, ...@@ -533,7 +536,8 @@ static int smc_connect_clc(struct smc_sock *smc, int smc_type,
if (rc) if (rc)
return rc; return rc;
/* receive SMC Accept CLC message */ /* receive SMC Accept CLC message */
return smc_clc_wait_msg(smc, aclc, sizeof(*aclc), SMC_CLC_ACCEPT); return smc_clc_wait_msg(smc, aclc, sizeof(*aclc), SMC_CLC_ACCEPT,
CLC_WAIT_TIME);
} }
/* setup for RDMA connection of client */ /* setup for RDMA connection of client */
...@@ -580,8 +584,7 @@ static int smc_connect_rdma(struct smc_sock *smc, ...@@ -580,8 +584,7 @@ static int smc_connect_rdma(struct smc_sock *smc,
return smc_connect_abort(smc, SMC_CLC_DECL_ERR_RDYLNK, return smc_connect_abort(smc, SMC_CLC_DECL_ERR_RDYLNK,
local_contact); local_contact);
} else { } else {
if (!smc->conn.rmb_desc->reused && if (smc_reg_rmb(link, smc->conn.rmb_desc, true))
smc_reg_rmb(link, smc->conn.rmb_desc, true))
return smc_connect_abort(smc, SMC_CLC_DECL_ERR_REGRMB, return smc_connect_abort(smc, SMC_CLC_DECL_ERR_REGRMB,
local_contact); local_contact);
} }
...@@ -965,8 +968,8 @@ static int smc_serv_conf_first_link(struct smc_sock *smc) ...@@ -965,8 +968,8 @@ static int smc_serv_conf_first_link(struct smc_sock *smc)
struct smc_clc_msg_decline dclc; struct smc_clc_msg_decline dclc;
rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc), rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
SMC_CLC_DECLINE); SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
return rc; return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc;
} }
if (link->llc_confirm_resp_rc) if (link->llc_confirm_resp_rc)
...@@ -986,8 +989,8 @@ static int smc_serv_conf_first_link(struct smc_sock *smc) ...@@ -986,8 +989,8 @@ static int smc_serv_conf_first_link(struct smc_sock *smc)
struct smc_clc_msg_decline dclc; struct smc_clc_msg_decline dclc;
rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc), rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
SMC_CLC_DECLINE); SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
return rc; return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_AL : rc;
} }
smc_llc_link_active(link, net->ipv4.sysctl_tcp_keepalive_time); smc_llc_link_active(link, net->ipv4.sysctl_tcp_keepalive_time);
...@@ -1142,11 +1145,9 @@ static int smc_listen_rdma_reg(struct smc_sock *new_smc, int local_contact) ...@@ -1142,11 +1145,9 @@ static int smc_listen_rdma_reg(struct smc_sock *new_smc, int local_contact)
struct smc_link *link = &new_smc->conn.lgr->lnk[SMC_SINGLE_LINK]; struct smc_link *link = &new_smc->conn.lgr->lnk[SMC_SINGLE_LINK];
if (local_contact != SMC_FIRST_CONTACT) { if (local_contact != SMC_FIRST_CONTACT) {
if (!new_smc->conn.rmb_desc->reused) {
if (smc_reg_rmb(link, new_smc->conn.rmb_desc, true)) if (smc_reg_rmb(link, new_smc->conn.rmb_desc, true))
return SMC_CLC_DECL_ERR_REGRMB; return SMC_CLC_DECL_ERR_REGRMB;
} }
}
smc_rmb_sync_sg_for_device(&new_smc->conn); smc_rmb_sync_sg_for_device(&new_smc->conn);
return 0; return 0;
...@@ -1181,7 +1182,6 @@ static int smc_listen_rdma_finish(struct smc_sock *new_smc, ...@@ -1181,7 +1182,6 @@ static int smc_listen_rdma_finish(struct smc_sock *new_smc,
return 0; return 0;
decline: decline:
mutex_unlock(&smc_create_lgr_pending);
smc_listen_decline(new_smc, reason_code, local_contact); smc_listen_decline(new_smc, reason_code, local_contact);
return reason_code; return reason_code;
} }
...@@ -1222,7 +1222,7 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1222,7 +1222,7 @@ static void smc_listen_work(struct work_struct *work)
*/ */
pclc = (struct smc_clc_msg_proposal *)&buf; pclc = (struct smc_clc_msg_proposal *)&buf;
reason_code = smc_clc_wait_msg(new_smc, pclc, SMC_CLC_MAX_LEN, reason_code = smc_clc_wait_msg(new_smc, pclc, SMC_CLC_MAX_LEN,
SMC_CLC_PROPOSAL); SMC_CLC_PROPOSAL, CLC_WAIT_TIME);
if (reason_code) { if (reason_code) {
smc_listen_decline(new_smc, reason_code, 0); smc_listen_decline(new_smc, reason_code, 0);
return; return;
...@@ -1272,7 +1272,7 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1272,7 +1272,7 @@ static void smc_listen_work(struct work_struct *work)
/* receive SMC Confirm CLC message */ /* receive SMC Confirm CLC message */
reason_code = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc), reason_code = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc),
SMC_CLC_CONFIRM); SMC_CLC_CONFIRM, CLC_WAIT_TIME);
if (reason_code) { if (reason_code) {
mutex_unlock(&smc_create_lgr_pending); mutex_unlock(&smc_create_lgr_pending);
smc_listen_decline(new_smc, reason_code, local_contact); smc_listen_decline(new_smc, reason_code, local_contact);
...@@ -1281,9 +1281,11 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1281,9 +1281,11 @@ static void smc_listen_work(struct work_struct *work)
/* finish worker */ /* finish worker */
if (!ism_supported) { if (!ism_supported) {
if (smc_listen_rdma_finish(new_smc, &cclc, local_contact)) if (smc_listen_rdma_finish(new_smc, &cclc, local_contact)) {
mutex_unlock(&smc_create_lgr_pending);
return; return;
} }
}
smc_conn_save_peer_info(new_smc, &cclc); smc_conn_save_peer_info(new_smc, &cclc);
mutex_unlock(&smc_create_lgr_pending); mutex_unlock(&smc_create_lgr_pending);
smc_listen_out_connected(new_smc); smc_listen_out_connected(new_smc);
...@@ -1354,7 +1356,6 @@ static int smc_listen(struct socket *sock, int backlog) ...@@ -1354,7 +1356,6 @@ static int smc_listen(struct socket *sock, int backlog)
sk->sk_max_ack_backlog = backlog; sk->sk_max_ack_backlog = backlog;
sk->sk_ack_backlog = 0; sk->sk_ack_backlog = 0;
sk->sk_state = SMC_LISTEN; sk->sk_state = SMC_LISTEN;
INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work);
sock_hold(sk); /* sock_hold in tcp_listen_worker */ sock_hold(sk); /* sock_hold in tcp_listen_worker */
if (!schedule_work(&smc->tcp_listen_work)) if (!schedule_work(&smc->tcp_listen_work))
sock_put(sk); sock_put(sk);
......
...@@ -265,7 +265,7 @@ int smc_clc_prfx_match(struct socket *clcsock, ...@@ -265,7 +265,7 @@ int smc_clc_prfx_match(struct socket *clcsock,
* clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise. * clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise.
*/ */
int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
u8 expected_type) u8 expected_type, unsigned long timeout)
{ {
long rcvtimeo = smc->clcsock->sk->sk_rcvtimeo; long rcvtimeo = smc->clcsock->sk->sk_rcvtimeo;
struct sock *clc_sk = smc->clcsock->sk; struct sock *clc_sk = smc->clcsock->sk;
...@@ -285,7 +285,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, ...@@ -285,7 +285,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
* sizeof(struct smc_clc_msg_hdr) * sizeof(struct smc_clc_msg_hdr)
*/ */
krflags = MSG_PEEK | MSG_WAITALL; krflags = MSG_PEEK | MSG_WAITALL;
smc->clcsock->sk->sk_rcvtimeo = CLC_WAIT_TIME; clc_sk->sk_rcvtimeo = timeout;
iov_iter_kvec(&msg.msg_iter, READ, &vec, 1, iov_iter_kvec(&msg.msg_iter, READ, &vec, 1,
sizeof(struct smc_clc_msg_hdr)); sizeof(struct smc_clc_msg_hdr));
len = sock_recvmsg(smc->clcsock, &msg, krflags); len = sock_recvmsg(smc->clcsock, &msg, krflags);
...@@ -297,6 +297,10 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, ...@@ -297,6 +297,10 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
} }
if (clc_sk->sk_err) { if (clc_sk->sk_err) {
reason_code = -clc_sk->sk_err; reason_code = -clc_sk->sk_err;
if (clc_sk->sk_err == EAGAIN &&
expected_type == SMC_CLC_DECLINE)
clc_sk->sk_err = 0; /* reset for fallback usage */
else
smc->sk.sk_err = clc_sk->sk_err; smc->sk.sk_err = clc_sk->sk_err;
goto out; goto out;
} }
...@@ -306,6 +310,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, ...@@ -306,6 +310,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
goto out; goto out;
} }
if (len < 0) { if (len < 0) {
if (len != -EAGAIN || expected_type != SMC_CLC_DECLINE)
smc->sk.sk_err = -len; smc->sk.sk_err = -len;
reason_code = len; reason_code = len;
goto out; goto out;
...@@ -346,7 +351,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, ...@@ -346,7 +351,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
} }
out: out:
smc->clcsock->sk->sk_rcvtimeo = rcvtimeo; clc_sk->sk_rcvtimeo = rcvtimeo;
return reason_code; return reason_code;
} }
...@@ -374,10 +379,8 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info) ...@@ -374,10 +379,8 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
sizeof(struct smc_clc_msg_decline)); sizeof(struct smc_clc_msg_decline));
if (len < sizeof(struct smc_clc_msg_decline)) if (len < sizeof(struct smc_clc_msg_decline))
smc->sk.sk_err = EPROTO; len = -EPROTO;
if (len < 0) return len > 0 ? 0 : len;
smc->sk.sk_err = -len;
return sock_error(&smc->sk);
} }
/* send CLC PROPOSAL message across internal TCP socket */ /* send CLC PROPOSAL message across internal TCP socket */
...@@ -536,7 +539,6 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact) ...@@ -536,7 +539,6 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
struct smc_link *link; struct smc_link *link;
struct msghdr msg; struct msghdr msg;
struct kvec vec; struct kvec vec;
int rc = 0;
int len; int len;
memset(&aclc, 0, sizeof(aclc)); memset(&aclc, 0, sizeof(aclc));
...@@ -589,13 +591,8 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact) ...@@ -589,13 +591,8 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
vec.iov_len = ntohs(aclc.hdr.length); vec.iov_len = ntohs(aclc.hdr.length);
len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1, len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1,
ntohs(aclc.hdr.length)); ntohs(aclc.hdr.length));
if (len < ntohs(aclc.hdr.length)) { if (len < ntohs(aclc.hdr.length))
if (len >= 0) len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err;
new_smc->sk.sk_err = EPROTO;
else
new_smc->sk.sk_err = new_smc->clcsock->sk->sk_err;
rc = sock_error(&new_smc->sk);
}
return rc; return len > 0 ? 0 : len;
} }
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define SMC_TYPE_D 1 /* SMC-D only */ #define SMC_TYPE_D 1 /* SMC-D only */
#define SMC_TYPE_B 3 /* SMC-R and SMC-D */ #define SMC_TYPE_B 3 /* SMC-R and SMC-D */
#define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */ #define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */
#define CLC_WAIT_TIME_SHORT HZ /* short wait time on clcsock */
#define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */ #define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */
#define SMC_CLC_DECL_TIMEOUT_CL 0x02010000 /* timeout w4 QP confirm link */ #define SMC_CLC_DECL_TIMEOUT_CL 0x02010000 /* timeout w4 QP confirm link */
#define SMC_CLC_DECL_TIMEOUT_AL 0x02020000 /* timeout w4 QP add link */ #define SMC_CLC_DECL_TIMEOUT_AL 0x02020000 /* timeout w4 QP add link */
...@@ -182,7 +183,7 @@ struct smcd_dev; ...@@ -182,7 +183,7 @@ struct smcd_dev;
int smc_clc_prfx_match(struct socket *clcsock, int smc_clc_prfx_match(struct socket *clcsock,
struct smc_clc_msg_proposal_prefix *prop); struct smc_clc_msg_proposal_prefix *prop);
int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
u8 expected_type); u8 expected_type, unsigned long timeout);
int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info); int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
int smc_clc_send_proposal(struct smc_sock *smc, int smc_type, int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
struct smc_ib_device *smcibdev, u8 ibport, u8 gid[], struct smc_ib_device *smcibdev, u8 ibport, u8 gid[],
......
...@@ -149,6 +149,8 @@ static int smc_link_send_delete(struct smc_link *lnk) ...@@ -149,6 +149,8 @@ static int smc_link_send_delete(struct smc_link *lnk)
return -ENOTCONN; return -ENOTCONN;
} }
static void smc_lgr_free(struct smc_link_group *lgr);
static void smc_lgr_free_work(struct work_struct *work) static void smc_lgr_free_work(struct work_struct *work)
{ {
struct smc_link_group *lgr = container_of(to_delayed_work(work), struct smc_link_group *lgr = container_of(to_delayed_work(work),
...@@ -171,8 +173,11 @@ static void smc_lgr_free_work(struct work_struct *work) ...@@ -171,8 +173,11 @@ static void smc_lgr_free_work(struct work_struct *work)
spin_unlock_bh(&smc_lgr_list.lock); spin_unlock_bh(&smc_lgr_list.lock);
if (!lgr->is_smcd && !lgr->terminating) { if (!lgr->is_smcd && !lgr->terminating) {
struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
/* try to send del link msg, on error free lgr immediately */ /* try to send del link msg, on error free lgr immediately */
if (!smc_link_send_delete(&lgr->lnk[SMC_SINGLE_LINK])) { if (lnk->state == SMC_LNK_ACTIVE &&
!smc_link_send_delete(lnk)) {
/* reschedule in case we never receive a response */ /* reschedule in case we never receive a response */
smc_lgr_schedule_free_work(lgr); smc_lgr_schedule_free_work(lgr);
return; return;
...@@ -293,8 +298,13 @@ static void smc_buf_unuse(struct smc_connection *conn, ...@@ -293,8 +298,13 @@ static void smc_buf_unuse(struct smc_connection *conn,
conn->sndbuf_desc->used = 0; conn->sndbuf_desc->used = 0;
if (conn->rmb_desc) { if (conn->rmb_desc) {
if (!conn->rmb_desc->regerr) { if (!conn->rmb_desc->regerr) {
conn->rmb_desc->reused = 1;
conn->rmb_desc->used = 0; conn->rmb_desc->used = 0;
if (!lgr->is_smcd) {
/* unregister rmb with peer */
smc_llc_do_delete_rkey(
&lgr->lnk[SMC_SINGLE_LINK],
conn->rmb_desc);
}
} else { } else {
/* buf registration failed, reuse not possible */ /* buf registration failed, reuse not possible */
write_lock_bh(&lgr->rmbs_lock); write_lock_bh(&lgr->rmbs_lock);
...@@ -408,7 +418,7 @@ static void smc_lgr_free_bufs(struct smc_link_group *lgr) ...@@ -408,7 +418,7 @@ static void smc_lgr_free_bufs(struct smc_link_group *lgr)
} }
/* remove a link group */ /* remove a link group */
void smc_lgr_free(struct smc_link_group *lgr) static void smc_lgr_free(struct smc_link_group *lgr)
{ {
smc_lgr_free_bufs(lgr); smc_lgr_free_bufs(lgr);
if (lgr->is_smcd) if (lgr->is_smcd)
......
...@@ -109,6 +109,9 @@ struct smc_link { ...@@ -109,6 +109,9 @@ struct smc_link {
int llc_testlink_time; /* testlink interval */ int llc_testlink_time; /* testlink interval */
struct completion llc_confirm_rkey; /* wait 4 rx of cnf rkey */ struct completion llc_confirm_rkey; /* wait 4 rx of cnf rkey */
int llc_confirm_rkey_rc; /* rc from cnf rkey msg */ int llc_confirm_rkey_rc; /* rc from cnf rkey msg */
struct completion llc_delete_rkey; /* wait 4 rx of del rkey */
int llc_delete_rkey_rc; /* rc from del rkey msg */
struct mutex llc_delete_rkey_mutex; /* serialize usage */
}; };
/* For now we just allow one parallel link per link group. The SMC protocol /* For now we just allow one parallel link per link group. The SMC protocol
...@@ -127,7 +130,7 @@ struct smc_buf_desc { ...@@ -127,7 +130,7 @@ struct smc_buf_desc {
struct page *pages; struct page *pages;
int len; /* length of buffer */ int len; /* length of buffer */
u32 used; /* currently used / unused */ u32 used; /* currently used / unused */
u8 reused : 1; /* new created / reused */ u8 wr_reg : 1; /* mem region registered */
u8 regerr : 1; /* err during registration */ u8 regerr : 1; /* err during registration */
union { union {
struct { /* SMC-R */ struct { /* SMC-R */
...@@ -243,7 +246,6 @@ struct smc_sock; ...@@ -243,7 +246,6 @@ struct smc_sock;
struct smc_clc_msg_accept_confirm; struct smc_clc_msg_accept_confirm;
struct smc_clc_msg_local; struct smc_clc_msg_local;
void smc_lgr_free(struct smc_link_group *lgr);
void smc_lgr_forget(struct smc_link_group *lgr); void smc_lgr_forget(struct smc_link_group *lgr);
void smc_lgr_terminate(struct smc_link_group *lgr); void smc_lgr_terminate(struct smc_link_group *lgr);
void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport); void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport);
......
...@@ -238,6 +238,29 @@ static int smc_llc_send_confirm_rkey(struct smc_link *link, ...@@ -238,6 +238,29 @@ static int smc_llc_send_confirm_rkey(struct smc_link *link,
return rc; return rc;
} }
/* send LLC delete rkey request */
static int smc_llc_send_delete_rkey(struct smc_link *link,
struct smc_buf_desc *rmb_desc)
{
struct smc_llc_msg_delete_rkey *rkeyllc;
struct smc_wr_tx_pend_priv *pend;
struct smc_wr_buf *wr_buf;
int rc;
rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
if (rc)
return rc;
rkeyllc = (struct smc_llc_msg_delete_rkey *)wr_buf;
memset(rkeyllc, 0, sizeof(*rkeyllc));
rkeyllc->hd.common.type = SMC_LLC_DELETE_RKEY;
rkeyllc->hd.length = sizeof(struct smc_llc_msg_delete_rkey);
rkeyllc->num_rkeys = 1;
rkeyllc->rkey[0] = htonl(rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
/* send llc message */
rc = smc_wr_tx_send(link, pend);
return rc;
}
/* prepare an add link message */ /* prepare an add link message */
static void smc_llc_prep_add_link(struct smc_llc_msg_add_link *addllc, static void smc_llc_prep_add_link(struct smc_llc_msg_add_link *addllc,
struct smc_link *link, u8 mac[], u8 gid[], struct smc_link *link, u8 mac[], u8 gid[],
...@@ -509,7 +532,9 @@ static void smc_llc_rx_delete_rkey(struct smc_link *link, ...@@ -509,7 +532,9 @@ static void smc_llc_rx_delete_rkey(struct smc_link *link,
int i, max; int i, max;
if (llc->hd.flags & SMC_LLC_FLAG_RESP) { if (llc->hd.flags & SMC_LLC_FLAG_RESP) {
/* unused as long as we don't send this type of msg */ link->llc_delete_rkey_rc = llc->hd.flags &
SMC_LLC_FLAG_RKEY_NEG;
complete(&link->llc_delete_rkey);
} else { } else {
max = min_t(u8, llc->num_rkeys, SMC_LLC_DEL_RKEY_MAX); max = min_t(u8, llc->num_rkeys, SMC_LLC_DEL_RKEY_MAX);
for (i = 0; i < max; i++) { for (i = 0; i < max; i++) {
...@@ -610,6 +635,8 @@ int smc_llc_link_init(struct smc_link *link) ...@@ -610,6 +635,8 @@ int smc_llc_link_init(struct smc_link *link)
init_completion(&link->llc_add); init_completion(&link->llc_add);
init_completion(&link->llc_add_resp); init_completion(&link->llc_add_resp);
init_completion(&link->llc_confirm_rkey); init_completion(&link->llc_confirm_rkey);
init_completion(&link->llc_delete_rkey);
mutex_init(&link->llc_delete_rkey_mutex);
init_completion(&link->llc_testlink_resp); init_completion(&link->llc_testlink_resp);
INIT_DELAYED_WORK(&link->llc_testlink_wrk, smc_llc_testlink_work); INIT_DELAYED_WORK(&link->llc_testlink_wrk, smc_llc_testlink_work);
return 0; return 0;
...@@ -650,8 +677,11 @@ int smc_llc_do_confirm_rkey(struct smc_link *link, ...@@ -650,8 +677,11 @@ int smc_llc_do_confirm_rkey(struct smc_link *link,
{ {
int rc; int rc;
/* protected by mutex smc_create_lgr_pending */
reinit_completion(&link->llc_confirm_rkey); reinit_completion(&link->llc_confirm_rkey);
smc_llc_send_confirm_rkey(link, rmb_desc); rc = smc_llc_send_confirm_rkey(link, rmb_desc);
if (rc)
return rc;
/* receive CONFIRM RKEY response from server over RoCE fabric */ /* receive CONFIRM RKEY response from server over RoCE fabric */
rc = wait_for_completion_interruptible_timeout(&link->llc_confirm_rkey, rc = wait_for_completion_interruptible_timeout(&link->llc_confirm_rkey,
SMC_LLC_WAIT_TIME); SMC_LLC_WAIT_TIME);
...@@ -660,6 +690,29 @@ int smc_llc_do_confirm_rkey(struct smc_link *link, ...@@ -660,6 +690,29 @@ int smc_llc_do_confirm_rkey(struct smc_link *link,
return 0; return 0;
} }
/* unregister an rtoken at the remote peer */
int smc_llc_do_delete_rkey(struct smc_link *link,
struct smc_buf_desc *rmb_desc)
{
int rc;
mutex_lock(&link->llc_delete_rkey_mutex);
reinit_completion(&link->llc_delete_rkey);
rc = smc_llc_send_delete_rkey(link, rmb_desc);
if (rc)
goto out;
/* receive DELETE RKEY response from server over RoCE fabric */
rc = wait_for_completion_interruptible_timeout(&link->llc_delete_rkey,
SMC_LLC_WAIT_TIME);
if (rc <= 0 || link->llc_delete_rkey_rc)
rc = -EFAULT;
else
rc = 0;
out:
mutex_unlock(&link->llc_delete_rkey_mutex);
return rc;
}
/***************************** init, exit, misc ******************************/ /***************************** init, exit, misc ******************************/
static struct smc_wr_rx_handler smc_llc_rx_handlers[] = { static struct smc_wr_rx_handler smc_llc_rx_handlers[] = {
......
...@@ -49,6 +49,8 @@ void smc_llc_link_inactive(struct smc_link *link); ...@@ -49,6 +49,8 @@ void smc_llc_link_inactive(struct smc_link *link);
void smc_llc_link_clear(struct smc_link *link); void smc_llc_link_clear(struct smc_link *link);
int smc_llc_do_confirm_rkey(struct smc_link *link, int smc_llc_do_confirm_rkey(struct smc_link *link,
struct smc_buf_desc *rmb_desc); struct smc_buf_desc *rmb_desc);
int smc_llc_do_delete_rkey(struct smc_link *link,
struct smc_buf_desc *rmb_desc);
int smc_llc_init(void) __init; int smc_llc_init(void) __init;
#endif /* SMC_LLC_H */ #endif /* SMC_LLC_H */
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