Commit 277aa590 authored by David S. Miller's avatar David S. Miller

Merge branch 'smc-fixes'

Ursula Braun says:

====================
net/smc: fixes 2019-02-04

here are more fixes in the smc code for the net tree:
Patch 1 fixes an IB-related problem with SMCR.
Patch 2 fixes a cursor problem for one-way traffic.
Patch 3 fixes a problem with RMB-reusage.
Patch 4 fixes a closing issue.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 53bc8d2a 84b799a2
...@@ -21,13 +21,6 @@ ...@@ -21,13 +21,6 @@
/********************************** send *************************************/ /********************************** send *************************************/
struct smc_cdc_tx_pend {
struct smc_connection *conn; /* socket connection */
union smc_host_cursor cursor; /* tx sndbuf cursor sent */
union smc_host_cursor p_cursor; /* rx RMBE cursor produced */
u16 ctrl_seq; /* conn. tx sequence # */
};
/* handler for send/transmission completion of a CDC msg */ /* handler for send/transmission completion of a CDC msg */
static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd, static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
struct smc_link *link, struct smc_link *link,
...@@ -61,12 +54,14 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd, ...@@ -61,12 +54,14 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
int smc_cdc_get_free_slot(struct smc_connection *conn, int smc_cdc_get_free_slot(struct smc_connection *conn,
struct smc_wr_buf **wr_buf, struct smc_wr_buf **wr_buf,
struct smc_rdma_wr **wr_rdma_buf,
struct smc_cdc_tx_pend **pend) struct smc_cdc_tx_pend **pend)
{ {
struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK]; struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK];
int rc; int rc;
rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf, rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf,
wr_rdma_buf,
(struct smc_wr_tx_pend_priv **)pend); (struct smc_wr_tx_pend_priv **)pend);
if (!conn->alert_token_local) if (!conn->alert_token_local)
/* abnormal termination */ /* abnormal termination */
...@@ -96,6 +91,7 @@ int smc_cdc_msg_send(struct smc_connection *conn, ...@@ -96,6 +91,7 @@ int smc_cdc_msg_send(struct smc_connection *conn,
struct smc_wr_buf *wr_buf, struct smc_wr_buf *wr_buf,
struct smc_cdc_tx_pend *pend) struct smc_cdc_tx_pend *pend)
{ {
union smc_host_cursor cfed;
struct smc_link *link; struct smc_link *link;
int rc; int rc;
...@@ -107,10 +103,10 @@ int smc_cdc_msg_send(struct smc_connection *conn, ...@@ -107,10 +103,10 @@ int smc_cdc_msg_send(struct smc_connection *conn,
conn->local_tx_ctrl.seqno = conn->tx_cdc_seq; conn->local_tx_ctrl.seqno = conn->tx_cdc_seq;
smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf, smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf,
&conn->local_tx_ctrl, conn); &conn->local_tx_ctrl, conn);
smc_curs_copy(&cfed, &((struct smc_host_cdc_msg *)wr_buf)->cons, conn);
rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend); rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend);
if (!rc) if (!rc)
smc_curs_copy(&conn->rx_curs_confirmed, smc_curs_copy(&conn->rx_curs_confirmed, &cfed, conn);
&conn->local_tx_ctrl.cons, conn);
return rc; return rc;
} }
...@@ -121,7 +117,7 @@ static int smcr_cdc_get_slot_and_msg_send(struct smc_connection *conn) ...@@ -121,7 +117,7 @@ static int smcr_cdc_get_slot_and_msg_send(struct smc_connection *conn)
struct smc_wr_buf *wr_buf; struct smc_wr_buf *wr_buf;
int rc; int rc;
rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend); rc = smc_cdc_get_free_slot(conn, &wr_buf, NULL, &pend);
if (rc) if (rc)
return rc; return rc;
......
...@@ -160,7 +160,9 @@ static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt, ...@@ -160,7 +160,9 @@ static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt,
#endif #endif
} }
/* calculate cursor difference between old and new, where old <= new */ /* calculate cursor difference between old and new, where old <= new and
* difference cannot exceed size
*/
static inline int smc_curs_diff(unsigned int size, static inline int smc_curs_diff(unsigned int size,
union smc_host_cursor *old, union smc_host_cursor *old,
union smc_host_cursor *new) union smc_host_cursor *new)
...@@ -185,6 +187,28 @@ static inline int smc_curs_comp(unsigned int size, ...@@ -185,6 +187,28 @@ static inline int smc_curs_comp(unsigned int size,
return smc_curs_diff(size, old, new); return smc_curs_diff(size, old, new);
} }
/* calculate cursor difference between old and new, where old <= new and
* difference may exceed size
*/
static inline int smc_curs_diff_large(unsigned int size,
union smc_host_cursor *old,
union smc_host_cursor *new)
{
if (old->wrap < new->wrap)
return min_t(int,
(size - old->count) + new->count +
(new->wrap - old->wrap - 1) * size,
size);
if (old->wrap > new->wrap) /* wrap has switched from 0xffff to 0x0000 */
return min_t(int,
(size - old->count) + new->count +
(new->wrap + 0xffff - old->wrap) * size,
size);
return max_t(int, 0, (new->count - old->count));
}
static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer, static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer,
union smc_host_cursor *local, union smc_host_cursor *local,
struct smc_connection *conn) struct smc_connection *conn)
...@@ -270,10 +294,16 @@ static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local, ...@@ -270,10 +294,16 @@ static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local,
smcr_cdc_msg_to_host(local, peer, conn); smcr_cdc_msg_to_host(local, peer, conn);
} }
struct smc_cdc_tx_pend; struct smc_cdc_tx_pend {
struct smc_connection *conn; /* socket connection */
union smc_host_cursor cursor; /* tx sndbuf cursor sent */
union smc_host_cursor p_cursor; /* rx RMBE cursor produced */
u16 ctrl_seq; /* conn. tx sequence # */
};
int smc_cdc_get_free_slot(struct smc_connection *conn, int smc_cdc_get_free_slot(struct smc_connection *conn,
struct smc_wr_buf **wr_buf, struct smc_wr_buf **wr_buf,
struct smc_rdma_wr **wr_rdma_buf,
struct smc_cdc_tx_pend **pend); struct smc_cdc_tx_pend **pend);
void smc_cdc_tx_dismiss_slots(struct smc_connection *conn); void smc_cdc_tx_dismiss_slots(struct smc_connection *conn);
int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf, int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf,
......
...@@ -345,14 +345,7 @@ static void smc_close_passive_work(struct work_struct *work) ...@@ -345,14 +345,7 @@ static void smc_close_passive_work(struct work_struct *work)
switch (sk->sk_state) { switch (sk->sk_state) {
case SMC_INIT: case SMC_INIT:
if (atomic_read(&conn->bytes_to_rcv) || sk->sk_state = SMC_APPCLOSEWAIT1;
(rxflags->peer_done_writing &&
!smc_cdc_rxed_any_close(conn))) {
sk->sk_state = SMC_APPCLOSEWAIT1;
} else {
sk->sk_state = SMC_CLOSED;
sock_put(sk); /* passive closing */
}
break; break;
case SMC_ACTIVE: case SMC_ACTIVE:
sk->sk_state = SMC_APPCLOSEWAIT1; sk->sk_state = SMC_APPCLOSEWAIT1;
......
...@@ -302,13 +302,13 @@ static void smc_buf_unuse(struct smc_connection *conn, ...@@ -302,13 +302,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->used = 0;
if (!lgr->is_smcd) { if (!lgr->is_smcd) {
/* unregister rmb with peer */ /* unregister rmb with peer */
smc_llc_do_delete_rkey( smc_llc_do_delete_rkey(
&lgr->lnk[SMC_SINGLE_LINK], &lgr->lnk[SMC_SINGLE_LINK],
conn->rmb_desc); conn->rmb_desc);
} }
conn->rmb_desc->used = 0;
} 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);
......
...@@ -52,6 +52,24 @@ enum smc_wr_reg_state { ...@@ -52,6 +52,24 @@ enum smc_wr_reg_state {
FAILED /* ib_wr_reg_mr response: failure */ FAILED /* ib_wr_reg_mr response: failure */
}; };
struct smc_rdma_sge { /* sges for RDMA writes */
struct ib_sge wr_tx_rdma_sge[SMC_IB_MAX_SEND_SGE];
};
#define SMC_MAX_RDMA_WRITES 2 /* max. # of RDMA writes per
* message send
*/
struct smc_rdma_sges { /* sges per message send */
struct smc_rdma_sge tx_rdma_sge[SMC_MAX_RDMA_WRITES];
};
struct smc_rdma_wr { /* work requests per message
* send
*/
struct ib_rdma_wr wr_tx_rdma[SMC_MAX_RDMA_WRITES];
};
struct smc_link { struct smc_link {
struct smc_ib_device *smcibdev; /* ib-device */ struct smc_ib_device *smcibdev; /* ib-device */
u8 ibport; /* port - values 1 | 2 */ u8 ibport; /* port - values 1 | 2 */
...@@ -64,6 +82,8 @@ struct smc_link { ...@@ -64,6 +82,8 @@ struct smc_link {
struct smc_wr_buf *wr_tx_bufs; /* WR send payload buffers */ struct smc_wr_buf *wr_tx_bufs; /* WR send payload buffers */
struct ib_send_wr *wr_tx_ibs; /* WR send meta data */ struct ib_send_wr *wr_tx_ibs; /* WR send meta data */
struct ib_sge *wr_tx_sges; /* WR send gather meta data */ struct ib_sge *wr_tx_sges; /* WR send gather meta data */
struct smc_rdma_sges *wr_tx_rdma_sges;/*RDMA WRITE gather meta data*/
struct smc_rdma_wr *wr_tx_rdmas; /* WR RDMA WRITE */
struct smc_wr_tx_pend *wr_tx_pends; /* WR send waiting for CQE */ struct smc_wr_tx_pend *wr_tx_pends; /* WR send waiting for CQE */
/* above four vectors have wr_tx_cnt elements and use the same index */ /* above four vectors have wr_tx_cnt elements and use the same index */
dma_addr_t wr_tx_dma_addr; /* DMA address of wr_tx_bufs */ dma_addr_t wr_tx_dma_addr; /* DMA address of wr_tx_bufs */
......
...@@ -166,7 +166,8 @@ static int smc_llc_add_pending_send(struct smc_link *link, ...@@ -166,7 +166,8 @@ static int smc_llc_add_pending_send(struct smc_link *link,
{ {
int rc; int rc;
rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, pend); rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, NULL,
pend);
if (rc < 0) if (rc < 0)
return rc; return rc;
BUILD_BUG_ON_MSG( BUILD_BUG_ON_MSG(
......
...@@ -266,27 +266,23 @@ int smcd_tx_ism_write(struct smc_connection *conn, void *data, size_t len, ...@@ -266,27 +266,23 @@ int smcd_tx_ism_write(struct smc_connection *conn, void *data, size_t len,
/* sndbuf consumer: actual data transfer of one target chunk with RDMA write */ /* sndbuf consumer: actual data transfer of one target chunk with RDMA write */
static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset, static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset,
int num_sges, struct ib_sge sges[]) int num_sges, struct ib_rdma_wr *rdma_wr)
{ {
struct smc_link_group *lgr = conn->lgr; struct smc_link_group *lgr = conn->lgr;
struct ib_rdma_wr rdma_wr;
struct smc_link *link; struct smc_link *link;
int rc; int rc;
memset(&rdma_wr, 0, sizeof(rdma_wr));
link = &lgr->lnk[SMC_SINGLE_LINK]; link = &lgr->lnk[SMC_SINGLE_LINK];
rdma_wr.wr.wr_id = smc_wr_tx_get_next_wr_id(link); rdma_wr->wr.wr_id = smc_wr_tx_get_next_wr_id(link);
rdma_wr.wr.sg_list = sges; rdma_wr->wr.num_sge = num_sges;
rdma_wr.wr.num_sge = num_sges; rdma_wr->remote_addr =
rdma_wr.wr.opcode = IB_WR_RDMA_WRITE;
rdma_wr.remote_addr =
lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].dma_addr + lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].dma_addr +
/* RMBE within RMB */ /* RMBE within RMB */
conn->tx_off + conn->tx_off +
/* offset within RMBE */ /* offset within RMBE */
peer_rmbe_offset; peer_rmbe_offset;
rdma_wr.rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey; rdma_wr->rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
rc = ib_post_send(link->roce_qp, &rdma_wr.wr, NULL); rc = ib_post_send(link->roce_qp, &rdma_wr->wr, NULL);
if (rc) { if (rc) {
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
smc_lgr_terminate(lgr); smc_lgr_terminate(lgr);
...@@ -313,24 +309,25 @@ static inline void smc_tx_advance_cursors(struct smc_connection *conn, ...@@ -313,24 +309,25 @@ static inline void smc_tx_advance_cursors(struct smc_connection *conn,
/* SMC-R helper for smc_tx_rdma_writes() */ /* SMC-R helper for smc_tx_rdma_writes() */
static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len, static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
size_t src_off, size_t src_len, size_t src_off, size_t src_len,
size_t dst_off, size_t dst_len) size_t dst_off, size_t dst_len,
struct smc_rdma_wr *wr_rdma_buf)
{ {
dma_addr_t dma_addr = dma_addr_t dma_addr =
sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl); sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl);
struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK];
int src_len_sum = src_len, dst_len_sum = dst_len; int src_len_sum = src_len, dst_len_sum = dst_len;
struct ib_sge sges[SMC_IB_MAX_SEND_SGE];
int sent_count = src_off; int sent_count = src_off;
int srcchunk, dstchunk; int srcchunk, dstchunk;
int num_sges; int num_sges;
int rc; int rc;
for (dstchunk = 0; dstchunk < 2; dstchunk++) { for (dstchunk = 0; dstchunk < 2; dstchunk++) {
struct ib_sge *sge =
wr_rdma_buf->wr_tx_rdma[dstchunk].wr.sg_list;
num_sges = 0; num_sges = 0;
for (srcchunk = 0; srcchunk < 2; srcchunk++) { for (srcchunk = 0; srcchunk < 2; srcchunk++) {
sges[srcchunk].addr = dma_addr + src_off; sge[srcchunk].addr = dma_addr + src_off;
sges[srcchunk].length = src_len; sge[srcchunk].length = src_len;
sges[srcchunk].lkey = link->roce_pd->local_dma_lkey;
num_sges++; num_sges++;
src_off += src_len; src_off += src_len;
...@@ -343,7 +340,8 @@ static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len, ...@@ -343,7 +340,8 @@ static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
src_len = dst_len - src_len; /* remainder */ src_len = dst_len - src_len; /* remainder */
src_len_sum += src_len; src_len_sum += src_len;
} }
rc = smc_tx_rdma_write(conn, dst_off, num_sges, sges); rc = smc_tx_rdma_write(conn, dst_off, num_sges,
&wr_rdma_buf->wr_tx_rdma[dstchunk]);
if (rc) if (rc)
return rc; return rc;
if (dst_len_sum == len) if (dst_len_sum == len)
...@@ -402,7 +400,8 @@ static int smcd_tx_rdma_writes(struct smc_connection *conn, size_t len, ...@@ -402,7 +400,8 @@ static int smcd_tx_rdma_writes(struct smc_connection *conn, size_t len,
/* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit; /* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit;
* usable snd_wnd as max transmit * usable snd_wnd as max transmit
*/ */
static int smc_tx_rdma_writes(struct smc_connection *conn) static int smc_tx_rdma_writes(struct smc_connection *conn,
struct smc_rdma_wr *wr_rdma_buf)
{ {
size_t len, src_len, dst_off, dst_len; /* current chunk values */ size_t len, src_len, dst_off, dst_len; /* current chunk values */
union smc_host_cursor sent, prep, prod, cons; union smc_host_cursor sent, prep, prod, cons;
...@@ -463,7 +462,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn) ...@@ -463,7 +462,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn)
dst_off, dst_len); dst_off, dst_len);
else else
rc = smcr_tx_rdma_writes(conn, len, sent.count, src_len, rc = smcr_tx_rdma_writes(conn, len, sent.count, src_len,
dst_off, dst_len); dst_off, dst_len, wr_rdma_buf);
if (rc) if (rc)
return rc; return rc;
...@@ -484,11 +483,12 @@ static int smc_tx_rdma_writes(struct smc_connection *conn) ...@@ -484,11 +483,12 @@ static int smc_tx_rdma_writes(struct smc_connection *conn)
static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn) static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
{ {
struct smc_cdc_producer_flags *pflags; struct smc_cdc_producer_flags *pflags;
struct smc_rdma_wr *wr_rdma_buf;
struct smc_cdc_tx_pend *pend; struct smc_cdc_tx_pend *pend;
struct smc_wr_buf *wr_buf; struct smc_wr_buf *wr_buf;
int rc; int rc;
rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend); rc = smc_cdc_get_free_slot(conn, &wr_buf, &wr_rdma_buf, &pend);
if (rc < 0) { if (rc < 0) {
if (rc == -EBUSY) { if (rc == -EBUSY) {
struct smc_sock *smc = struct smc_sock *smc =
...@@ -506,7 +506,7 @@ static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn) ...@@ -506,7 +506,7 @@ static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
spin_lock_bh(&conn->send_lock); spin_lock_bh(&conn->send_lock);
if (!conn->local_tx_ctrl.prod_flags.urg_data_present) { if (!conn->local_tx_ctrl.prod_flags.urg_data_present) {
rc = smc_tx_rdma_writes(conn); rc = smc_tx_rdma_writes(conn, wr_rdma_buf);
if (rc) { if (rc) {
smc_wr_tx_put_slot(&conn->lgr->lnk[SMC_SINGLE_LINK], smc_wr_tx_put_slot(&conn->lgr->lnk[SMC_SINGLE_LINK],
(struct smc_wr_tx_pend_priv *)pend); (struct smc_wr_tx_pend_priv *)pend);
...@@ -533,7 +533,7 @@ static int smcd_tx_sndbuf_nonempty(struct smc_connection *conn) ...@@ -533,7 +533,7 @@ static int smcd_tx_sndbuf_nonempty(struct smc_connection *conn)
spin_lock_bh(&conn->send_lock); spin_lock_bh(&conn->send_lock);
if (!pflags->urg_data_present) if (!pflags->urg_data_present)
rc = smc_tx_rdma_writes(conn); rc = smc_tx_rdma_writes(conn, NULL);
if (!rc) if (!rc)
rc = smcd_cdc_msg_send(conn); rc = smcd_cdc_msg_send(conn);
...@@ -595,7 +595,8 @@ void smc_tx_consumer_update(struct smc_connection *conn, bool force) ...@@ -595,7 +595,8 @@ void smc_tx_consumer_update(struct smc_connection *conn, bool force)
if (to_confirm > conn->rmbe_update_limit) { if (to_confirm > conn->rmbe_update_limit) {
smc_curs_copy(&prod, &conn->local_rx_ctrl.prod, conn); smc_curs_copy(&prod, &conn->local_rx_ctrl.prod, conn);
sender_free = conn->rmb_desc->len - sender_free = conn->rmb_desc->len -
smc_curs_diff(conn->rmb_desc->len, &prod, &cfed); smc_curs_diff_large(conn->rmb_desc->len,
&cfed, &prod);
} }
if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req || if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req ||
......
...@@ -160,6 +160,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx) ...@@ -160,6 +160,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
* @link: Pointer to smc_link used to later send the message. * @link: Pointer to smc_link used to later send the message.
* @handler: Send completion handler function pointer. * @handler: Send completion handler function pointer.
* @wr_buf: Out value returns pointer to message buffer. * @wr_buf: Out value returns pointer to message buffer.
* @wr_rdma_buf: Out value returns pointer to rdma work request.
* @wr_pend_priv: Out value returns pointer serving as handler context. * @wr_pend_priv: Out value returns pointer serving as handler context.
* *
* Return: 0 on success, or -errno on error. * Return: 0 on success, or -errno on error.
...@@ -167,6 +168,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx) ...@@ -167,6 +168,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
int smc_wr_tx_get_free_slot(struct smc_link *link, int smc_wr_tx_get_free_slot(struct smc_link *link,
smc_wr_tx_handler handler, smc_wr_tx_handler handler,
struct smc_wr_buf **wr_buf, struct smc_wr_buf **wr_buf,
struct smc_rdma_wr **wr_rdma_buf,
struct smc_wr_tx_pend_priv **wr_pend_priv) struct smc_wr_tx_pend_priv **wr_pend_priv)
{ {
struct smc_wr_tx_pend *wr_pend; struct smc_wr_tx_pend *wr_pend;
...@@ -204,6 +206,8 @@ int smc_wr_tx_get_free_slot(struct smc_link *link, ...@@ -204,6 +206,8 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
wr_ib = &link->wr_tx_ibs[idx]; wr_ib = &link->wr_tx_ibs[idx];
wr_ib->wr_id = wr_id; wr_ib->wr_id = wr_id;
*wr_buf = &link->wr_tx_bufs[idx]; *wr_buf = &link->wr_tx_bufs[idx];
if (wr_rdma_buf)
*wr_rdma_buf = &link->wr_tx_rdmas[idx];
*wr_pend_priv = &wr_pend->priv; *wr_pend_priv = &wr_pend->priv;
return 0; return 0;
} }
...@@ -465,12 +469,26 @@ static void smc_wr_init_sge(struct smc_link *lnk) ...@@ -465,12 +469,26 @@ static void smc_wr_init_sge(struct smc_link *lnk)
lnk->wr_tx_dma_addr + i * SMC_WR_BUF_SIZE; lnk->wr_tx_dma_addr + i * SMC_WR_BUF_SIZE;
lnk->wr_tx_sges[i].length = SMC_WR_TX_SIZE; lnk->wr_tx_sges[i].length = SMC_WR_TX_SIZE;
lnk->wr_tx_sges[i].lkey = lnk->roce_pd->local_dma_lkey; lnk->wr_tx_sges[i].lkey = lnk->roce_pd->local_dma_lkey;
lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[0].lkey =
lnk->roce_pd->local_dma_lkey;
lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[1].lkey =
lnk->roce_pd->local_dma_lkey;
lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[0].lkey =
lnk->roce_pd->local_dma_lkey;
lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[1].lkey =
lnk->roce_pd->local_dma_lkey;
lnk->wr_tx_ibs[i].next = NULL; lnk->wr_tx_ibs[i].next = NULL;
lnk->wr_tx_ibs[i].sg_list = &lnk->wr_tx_sges[i]; lnk->wr_tx_ibs[i].sg_list = &lnk->wr_tx_sges[i];
lnk->wr_tx_ibs[i].num_sge = 1; lnk->wr_tx_ibs[i].num_sge = 1;
lnk->wr_tx_ibs[i].opcode = IB_WR_SEND; lnk->wr_tx_ibs[i].opcode = IB_WR_SEND;
lnk->wr_tx_ibs[i].send_flags = lnk->wr_tx_ibs[i].send_flags =
IB_SEND_SIGNALED | IB_SEND_SOLICITED; IB_SEND_SIGNALED | IB_SEND_SOLICITED;
lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.opcode = IB_WR_RDMA_WRITE;
lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.opcode = IB_WR_RDMA_WRITE;
lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.sg_list =
lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge;
lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.sg_list =
lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge;
} }
for (i = 0; i < lnk->wr_rx_cnt; i++) { for (i = 0; i < lnk->wr_rx_cnt; i++) {
lnk->wr_rx_sges[i].addr = lnk->wr_rx_sges[i].addr =
...@@ -521,8 +539,12 @@ void smc_wr_free_link_mem(struct smc_link *lnk) ...@@ -521,8 +539,12 @@ void smc_wr_free_link_mem(struct smc_link *lnk)
lnk->wr_tx_mask = NULL; lnk->wr_tx_mask = NULL;
kfree(lnk->wr_tx_sges); kfree(lnk->wr_tx_sges);
lnk->wr_tx_sges = NULL; lnk->wr_tx_sges = NULL;
kfree(lnk->wr_tx_rdma_sges);
lnk->wr_tx_rdma_sges = NULL;
kfree(lnk->wr_rx_sges); kfree(lnk->wr_rx_sges);
lnk->wr_rx_sges = NULL; lnk->wr_rx_sges = NULL;
kfree(lnk->wr_tx_rdmas);
lnk->wr_tx_rdmas = NULL;
kfree(lnk->wr_rx_ibs); kfree(lnk->wr_rx_ibs);
lnk->wr_rx_ibs = NULL; lnk->wr_rx_ibs = NULL;
kfree(lnk->wr_tx_ibs); kfree(lnk->wr_tx_ibs);
...@@ -552,10 +574,20 @@ int smc_wr_alloc_link_mem(struct smc_link *link) ...@@ -552,10 +574,20 @@ int smc_wr_alloc_link_mem(struct smc_link *link)
GFP_KERNEL); GFP_KERNEL);
if (!link->wr_rx_ibs) if (!link->wr_rx_ibs)
goto no_mem_wr_tx_ibs; goto no_mem_wr_tx_ibs;
link->wr_tx_rdmas = kcalloc(SMC_WR_BUF_CNT,
sizeof(link->wr_tx_rdmas[0]),
GFP_KERNEL);
if (!link->wr_tx_rdmas)
goto no_mem_wr_rx_ibs;
link->wr_tx_rdma_sges = kcalloc(SMC_WR_BUF_CNT,
sizeof(link->wr_tx_rdma_sges[0]),
GFP_KERNEL);
if (!link->wr_tx_rdma_sges)
goto no_mem_wr_tx_rdmas;
link->wr_tx_sges = kcalloc(SMC_WR_BUF_CNT, sizeof(link->wr_tx_sges[0]), link->wr_tx_sges = kcalloc(SMC_WR_BUF_CNT, sizeof(link->wr_tx_sges[0]),
GFP_KERNEL); GFP_KERNEL);
if (!link->wr_tx_sges) if (!link->wr_tx_sges)
goto no_mem_wr_rx_ibs; goto no_mem_wr_tx_rdma_sges;
link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3, link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3,
sizeof(link->wr_rx_sges[0]), sizeof(link->wr_rx_sges[0]),
GFP_KERNEL); GFP_KERNEL);
...@@ -579,6 +611,10 @@ int smc_wr_alloc_link_mem(struct smc_link *link) ...@@ -579,6 +611,10 @@ int smc_wr_alloc_link_mem(struct smc_link *link)
kfree(link->wr_rx_sges); kfree(link->wr_rx_sges);
no_mem_wr_tx_sges: no_mem_wr_tx_sges:
kfree(link->wr_tx_sges); kfree(link->wr_tx_sges);
no_mem_wr_tx_rdma_sges:
kfree(link->wr_tx_rdma_sges);
no_mem_wr_tx_rdmas:
kfree(link->wr_tx_rdmas);
no_mem_wr_rx_ibs: no_mem_wr_rx_ibs:
kfree(link->wr_rx_ibs); kfree(link->wr_rx_ibs);
no_mem_wr_tx_ibs: no_mem_wr_tx_ibs:
......
...@@ -85,6 +85,7 @@ void smc_wr_add_dev(struct smc_ib_device *smcibdev); ...@@ -85,6 +85,7 @@ void smc_wr_add_dev(struct smc_ib_device *smcibdev);
int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler, int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler,
struct smc_wr_buf **wr_buf, struct smc_wr_buf **wr_buf,
struct smc_rdma_wr **wrs,
struct smc_wr_tx_pend_priv **wr_pend_priv); struct smc_wr_tx_pend_priv **wr_pend_priv);
int smc_wr_tx_put_slot(struct smc_link *link, int smc_wr_tx_put_slot(struct smc_link *link,
struct smc_wr_tx_pend_priv *wr_pend_priv); struct smc_wr_tx_pend_priv *wr_pend_priv);
......
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