aboutsummaryrefslogtreecommitdiffstats
path: root/net/smc
diff options
context:
space:
mode:
Diffstat (limited to 'net/smc')
-rw-r--r--net/smc/af_smc.c11
-rw-r--r--net/smc/smc_cdc.c21
-rw-r--r--net/smc/smc_cdc.h34
-rw-r--r--net/smc/smc_clc.c2
-rw-r--r--net/smc/smc_close.c9
-rw-r--r--net/smc/smc_core.c6
-rw-r--r--net/smc/smc_core.h20
-rw-r--r--net/smc/smc_ib.c6
-rw-r--r--net/smc/smc_llc.c3
-rw-r--r--net/smc/smc_pnet.c2
-rw-r--r--net/smc/smc_tx.c64
-rw-r--r--net/smc/smc_wr.c46
-rw-r--r--net/smc/smc_wr.h1
13 files changed, 158 insertions, 67 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index c4e56602e0c6..b04a813fc865 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1505,6 +1505,11 @@ static int smc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
1505 1505
1506 smc = smc_sk(sk); 1506 smc = smc_sk(sk);
1507 lock_sock(sk); 1507 lock_sock(sk);
1508 if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) {
1509 /* socket was connected before, no more data to read */
1510 rc = 0;
1511 goto out;
1512 }
1508 if ((sk->sk_state == SMC_INIT) || 1513 if ((sk->sk_state == SMC_INIT) ||
1509 (sk->sk_state == SMC_LISTEN) || 1514 (sk->sk_state == SMC_LISTEN) ||
1510 (sk->sk_state == SMC_CLOSED)) 1515 (sk->sk_state == SMC_CLOSED))
@@ -1840,7 +1845,11 @@ static ssize_t smc_splice_read(struct socket *sock, loff_t *ppos,
1840 1845
1841 smc = smc_sk(sk); 1846 smc = smc_sk(sk);
1842 lock_sock(sk); 1847 lock_sock(sk);
1843 1848 if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) {
1849 /* socket was connected before, no more data to read */
1850 rc = 0;
1851 goto out;
1852 }
1844 if (sk->sk_state == SMC_INIT || 1853 if (sk->sk_state == SMC_INIT ||
1845 sk->sk_state == SMC_LISTEN || 1854 sk->sk_state == SMC_LISTEN ||
1846 sk->sk_state == SMC_CLOSED) 1855 sk->sk_state == SMC_CLOSED)
diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c
index db83332ac1c8..a712c9f8699b 100644
--- a/net/smc/smc_cdc.c
+++ b/net/smc/smc_cdc.c
@@ -21,13 +21,6 @@
21 21
22/********************************** send *************************************/ 22/********************************** send *************************************/
23 23
24struct smc_cdc_tx_pend {
25 struct smc_connection *conn; /* socket connection */
26 union smc_host_cursor cursor; /* tx sndbuf cursor sent */
27 union smc_host_cursor p_cursor; /* rx RMBE cursor produced */
28 u16 ctrl_seq; /* conn. tx sequence # */
29};
30
31/* handler for send/transmission completion of a CDC msg */ 24/* handler for send/transmission completion of a CDC msg */
32static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd, 25static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
33 struct smc_link *link, 26 struct smc_link *link,
@@ -61,12 +54,14 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
61 54
62int smc_cdc_get_free_slot(struct smc_connection *conn, 55int smc_cdc_get_free_slot(struct smc_connection *conn,
63 struct smc_wr_buf **wr_buf, 56 struct smc_wr_buf **wr_buf,
57 struct smc_rdma_wr **wr_rdma_buf,
64 struct smc_cdc_tx_pend **pend) 58 struct smc_cdc_tx_pend **pend)
65{ 59{
66 struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK]; 60 struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK];
67 int rc; 61 int rc;
68 62
69 rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf, 63 rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf,
64 wr_rdma_buf,
70 (struct smc_wr_tx_pend_priv **)pend); 65 (struct smc_wr_tx_pend_priv **)pend);
71 if (!conn->alert_token_local) 66 if (!conn->alert_token_local)
72 /* abnormal termination */ 67 /* abnormal termination */
@@ -96,6 +91,7 @@ int smc_cdc_msg_send(struct smc_connection *conn,
96 struct smc_wr_buf *wr_buf, 91 struct smc_wr_buf *wr_buf,
97 struct smc_cdc_tx_pend *pend) 92 struct smc_cdc_tx_pend *pend)
98{ 93{
94 union smc_host_cursor cfed;
99 struct smc_link *link; 95 struct smc_link *link;
100 int rc; 96 int rc;
101 97
@@ -107,10 +103,10 @@ int smc_cdc_msg_send(struct smc_connection *conn,
107 conn->local_tx_ctrl.seqno = conn->tx_cdc_seq; 103 conn->local_tx_ctrl.seqno = conn->tx_cdc_seq;
108 smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf, 104 smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf,
109 &conn->local_tx_ctrl, conn); 105 &conn->local_tx_ctrl, conn);
106 smc_curs_copy(&cfed, &((struct smc_host_cdc_msg *)wr_buf)->cons, conn);
110 rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend); 107 rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend);
111 if (!rc) 108 if (!rc)
112 smc_curs_copy(&conn->rx_curs_confirmed, 109 smc_curs_copy(&conn->rx_curs_confirmed, &cfed, conn);
113 &conn->local_tx_ctrl.cons, conn);
114 110
115 return rc; 111 return rc;
116} 112}
@@ -121,11 +117,14 @@ static int smcr_cdc_get_slot_and_msg_send(struct smc_connection *conn)
121 struct smc_wr_buf *wr_buf; 117 struct smc_wr_buf *wr_buf;
122 int rc; 118 int rc;
123 119
124 rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend); 120 rc = smc_cdc_get_free_slot(conn, &wr_buf, NULL, &pend);
125 if (rc) 121 if (rc)
126 return rc; 122 return rc;
127 123
128 return smc_cdc_msg_send(conn, wr_buf, pend); 124 spin_lock_bh(&conn->send_lock);
125 rc = smc_cdc_msg_send(conn, wr_buf, pend);
126 spin_unlock_bh(&conn->send_lock);
127 return rc;
129} 128}
130 129
131int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn) 130int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn)
diff --git a/net/smc/smc_cdc.h b/net/smc/smc_cdc.h
index b5bfe38c7f9b..271e2524dc8f 100644
--- a/net/smc/smc_cdc.h
+++ b/net/smc/smc_cdc.h
@@ -160,7 +160,9 @@ static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt,
160#endif 160#endif
161} 161}
162 162
163/* calculate cursor difference between old and new, where old <= new */ 163/* calculate cursor difference between old and new, where old <= new and
164 * difference cannot exceed size
165 */
164static inline int smc_curs_diff(unsigned int size, 166static inline int smc_curs_diff(unsigned int size,
165 union smc_host_cursor *old, 167 union smc_host_cursor *old,
166 union smc_host_cursor *new) 168 union smc_host_cursor *new)
@@ -185,6 +187,28 @@ static inline int smc_curs_comp(unsigned int size,
185 return smc_curs_diff(size, old, new); 187 return smc_curs_diff(size, old, new);
186} 188}
187 189
190/* calculate cursor difference between old and new, where old <= new and
191 * difference may exceed size
192 */
193static inline int smc_curs_diff_large(unsigned int size,
194 union smc_host_cursor *old,
195 union smc_host_cursor *new)
196{
197 if (old->wrap < new->wrap)
198 return min_t(int,
199 (size - old->count) + new->count +
200 (new->wrap - old->wrap - 1) * size,
201 size);
202
203 if (old->wrap > new->wrap) /* wrap has switched from 0xffff to 0x0000 */
204 return min_t(int,
205 (size - old->count) + new->count +
206 (new->wrap + 0xffff - old->wrap) * size,
207 size);
208
209 return max_t(int, 0, (new->count - old->count));
210}
211
188static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer, 212static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer,
189 union smc_host_cursor *local, 213 union smc_host_cursor *local,
190 struct smc_connection *conn) 214 struct smc_connection *conn)
@@ -270,10 +294,16 @@ static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local,
270 smcr_cdc_msg_to_host(local, peer, conn); 294 smcr_cdc_msg_to_host(local, peer, conn);
271} 295}
272 296
273struct smc_cdc_tx_pend; 297struct smc_cdc_tx_pend {
298 struct smc_connection *conn; /* socket connection */
299 union smc_host_cursor cursor; /* tx sndbuf cursor sent */
300 union smc_host_cursor p_cursor; /* rx RMBE cursor produced */
301 u16 ctrl_seq; /* conn. tx sequence # */
302};
274 303
275int smc_cdc_get_free_slot(struct smc_connection *conn, 304int smc_cdc_get_free_slot(struct smc_connection *conn,
276 struct smc_wr_buf **wr_buf, 305 struct smc_wr_buf **wr_buf,
306 struct smc_rdma_wr **wr_rdma_buf,
277 struct smc_cdc_tx_pend **pend); 307 struct smc_cdc_tx_pend **pend);
278void smc_cdc_tx_dismiss_slots(struct smc_connection *conn); 308void smc_cdc_tx_dismiss_slots(struct smc_connection *conn);
279int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf, 309int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf,
diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
index 776e9dfc915d..d53fd588d1f5 100644
--- a/net/smc/smc_clc.c
+++ b/net/smc/smc_clc.c
@@ -378,7 +378,7 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
378 vec.iov_len = sizeof(struct smc_clc_msg_decline); 378 vec.iov_len = sizeof(struct smc_clc_msg_decline);
379 len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, 379 len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
380 sizeof(struct smc_clc_msg_decline)); 380 sizeof(struct smc_clc_msg_decline));
381 if (len < sizeof(struct smc_clc_msg_decline)) 381 if (len < 0 || len < sizeof(struct smc_clc_msg_decline))
382 len = -EPROTO; 382 len = -EPROTO;
383 return len > 0 ? 0 : len; 383 return len > 0 ? 0 : len;
384} 384}
diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c
index ea2b87f29469..e39cadda1bf5 100644
--- a/net/smc/smc_close.c
+++ b/net/smc/smc_close.c
@@ -345,14 +345,7 @@ static void smc_close_passive_work(struct work_struct *work)
345 345
346 switch (sk->sk_state) { 346 switch (sk->sk_state) {
347 case SMC_INIT: 347 case SMC_INIT:
348 if (atomic_read(&conn->bytes_to_rcv) || 348 sk->sk_state = SMC_APPCLOSEWAIT1;
349 (rxflags->peer_done_writing &&
350 !smc_cdc_rxed_any_close(conn))) {
351 sk->sk_state = SMC_APPCLOSEWAIT1;
352 } else {
353 sk->sk_state = SMC_CLOSED;
354 sock_put(sk); /* passive closing */
355 }
356 break; 349 break;
357 case SMC_ACTIVE: 350 case SMC_ACTIVE:
358 sk->sk_state = SMC_APPCLOSEWAIT1; 351 sk->sk_state = SMC_APPCLOSEWAIT1;
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index 35c1cdc93e1c..aa1c551cee81 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -128,6 +128,8 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn)
128{ 128{
129 struct smc_link_group *lgr = conn->lgr; 129 struct smc_link_group *lgr = conn->lgr;
130 130
131 if (!lgr)
132 return;
131 write_lock_bh(&lgr->conns_lock); 133 write_lock_bh(&lgr->conns_lock);
132 if (conn->alert_token_local) { 134 if (conn->alert_token_local) {
133 __smc_lgr_unregister_conn(conn); 135 __smc_lgr_unregister_conn(conn);
@@ -300,13 +302,13 @@ static void smc_buf_unuse(struct smc_connection *conn,
300 conn->sndbuf_desc->used = 0; 302 conn->sndbuf_desc->used = 0;
301 if (conn->rmb_desc) { 303 if (conn->rmb_desc) {
302 if (!conn->rmb_desc->regerr) { 304 if (!conn->rmb_desc->regerr) {
303 conn->rmb_desc->used = 0;
304 if (!lgr->is_smcd) { 305 if (!lgr->is_smcd) {
305 /* unregister rmb with peer */ 306 /* unregister rmb with peer */
306 smc_llc_do_delete_rkey( 307 smc_llc_do_delete_rkey(
307 &lgr->lnk[SMC_SINGLE_LINK], 308 &lgr->lnk[SMC_SINGLE_LINK],
308 conn->rmb_desc); 309 conn->rmb_desc);
309 } 310 }
311 conn->rmb_desc->used = 0;
310 } else { 312 } else {
311 /* buf registration failed, reuse not possible */ 313 /* buf registration failed, reuse not possible */
312 write_lock_bh(&lgr->rmbs_lock); 314 write_lock_bh(&lgr->rmbs_lock);
@@ -628,6 +630,8 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
628 local_contact = SMC_REUSE_CONTACT; 630 local_contact = SMC_REUSE_CONTACT;
629 conn->lgr = lgr; 631 conn->lgr = lgr;
630 smc_lgr_register_conn(conn); /* add smc conn to lgr */ 632 smc_lgr_register_conn(conn); /* add smc conn to lgr */
633 if (delayed_work_pending(&lgr->free_work))
634 cancel_delayed_work(&lgr->free_work);
631 write_unlock_bh(&lgr->conns_lock); 635 write_unlock_bh(&lgr->conns_lock);
632 break; 636 break;
633 } 637 }
diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h
index b00287989a3d..8806d2afa6ed 100644
--- a/net/smc/smc_core.h
+++ b/net/smc/smc_core.h
@@ -52,6 +52,24 @@ enum smc_wr_reg_state {
52 FAILED /* ib_wr_reg_mr response: failure */ 52 FAILED /* ib_wr_reg_mr response: failure */
53}; 53};
54 54
55struct smc_rdma_sge { /* sges for RDMA writes */
56 struct ib_sge wr_tx_rdma_sge[SMC_IB_MAX_SEND_SGE];
57};
58
59#define SMC_MAX_RDMA_WRITES 2 /* max. # of RDMA writes per
60 * message send
61 */
62
63struct smc_rdma_sges { /* sges per message send */
64 struct smc_rdma_sge tx_rdma_sge[SMC_MAX_RDMA_WRITES];
65};
66
67struct smc_rdma_wr { /* work requests per message
68 * send
69 */
70 struct ib_rdma_wr wr_tx_rdma[SMC_MAX_RDMA_WRITES];
71};
72
55struct smc_link { 73struct smc_link {
56 struct smc_ib_device *smcibdev; /* ib-device */ 74 struct smc_ib_device *smcibdev; /* ib-device */
57 u8 ibport; /* port - values 1 | 2 */ 75 u8 ibport; /* port - values 1 | 2 */
@@ -64,6 +82,8 @@ struct smc_link {
64 struct smc_wr_buf *wr_tx_bufs; /* WR send payload buffers */ 82 struct smc_wr_buf *wr_tx_bufs; /* WR send payload buffers */
65 struct ib_send_wr *wr_tx_ibs; /* WR send meta data */ 83 struct ib_send_wr *wr_tx_ibs; /* WR send meta data */
66 struct ib_sge *wr_tx_sges; /* WR send gather meta data */ 84 struct ib_sge *wr_tx_sges; /* WR send gather meta data */
85 struct smc_rdma_sges *wr_tx_rdma_sges;/*RDMA WRITE gather meta data*/
86 struct smc_rdma_wr *wr_tx_rdmas; /* WR RDMA WRITE */
67 struct smc_wr_tx_pend *wr_tx_pends; /* WR send waiting for CQE */ 87 struct smc_wr_tx_pend *wr_tx_pends; /* WR send waiting for CQE */
68 /* above four vectors have wr_tx_cnt elements and use the same index */ 88 /* above four vectors have wr_tx_cnt elements and use the same index */
69 dma_addr_t wr_tx_dma_addr; /* DMA address of wr_tx_bufs */ 89 dma_addr_t wr_tx_dma_addr; /* DMA address of wr_tx_bufs */
diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c
index e519ef29c0ff..76487a16934e 100644
--- a/net/smc/smc_ib.c
+++ b/net/smc/smc_ib.c
@@ -289,8 +289,8 @@ int smc_ib_create_protection_domain(struct smc_link *lnk)
289 289
290static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv) 290static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
291{ 291{
292 struct smc_ib_device *smcibdev = 292 struct smc_link *lnk = (struct smc_link *)priv;
293 (struct smc_ib_device *)ibevent->device; 293 struct smc_ib_device *smcibdev = lnk->smcibdev;
294 u8 port_idx; 294 u8 port_idx;
295 295
296 switch (ibevent->event) { 296 switch (ibevent->event) {
@@ -298,7 +298,7 @@ static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
298 case IB_EVENT_GID_CHANGE: 298 case IB_EVENT_GID_CHANGE:
299 case IB_EVENT_PORT_ERR: 299 case IB_EVENT_PORT_ERR:
300 case IB_EVENT_QP_ACCESS_ERR: 300 case IB_EVENT_QP_ACCESS_ERR:
301 port_idx = ibevent->element.port_num - 1; 301 port_idx = ibevent->element.qp->port - 1;
302 set_bit(port_idx, &smcibdev->port_event_mask); 302 set_bit(port_idx, &smcibdev->port_event_mask);
303 schedule_work(&smcibdev->port_event_work); 303 schedule_work(&smcibdev->port_event_work);
304 break; 304 break;
diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c
index a6d3623d06f4..4fd60c522802 100644
--- a/net/smc/smc_llc.c
+++ b/net/smc/smc_llc.c
@@ -166,7 +166,8 @@ static int smc_llc_add_pending_send(struct smc_link *link,
166{ 166{
167 int rc; 167 int rc;
168 168
169 rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, pend); 169 rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, NULL,
170 pend);
170 if (rc < 0) 171 if (rc < 0)
171 return rc; 172 return rc;
172 BUILD_BUG_ON_MSG( 173 BUILD_BUG_ON_MSG(
diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
index 7cb3e4f07c10..632c3109dee5 100644
--- a/net/smc/smc_pnet.c
+++ b/net/smc/smc_pnet.c
@@ -27,7 +27,7 @@
27static struct nla_policy smc_pnet_policy[SMC_PNETID_MAX + 1] = { 27static struct nla_policy smc_pnet_policy[SMC_PNETID_MAX + 1] = {
28 [SMC_PNETID_NAME] = { 28 [SMC_PNETID_NAME] = {
29 .type = NLA_NUL_STRING, 29 .type = NLA_NUL_STRING,
30 .len = SMC_MAX_PNETID_LEN - 1 30 .len = SMC_MAX_PNETID_LEN
31 }, 31 },
32 [SMC_PNETID_ETHNAME] = { 32 [SMC_PNETID_ETHNAME] = {
33 .type = NLA_NUL_STRING, 33 .type = NLA_NUL_STRING,
diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c
index d8366ed51757..f93f3580c100 100644
--- a/net/smc/smc_tx.c
+++ b/net/smc/smc_tx.c
@@ -165,12 +165,11 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len)
165 conn->local_tx_ctrl.prod_flags.urg_data_pending = 1; 165 conn->local_tx_ctrl.prod_flags.urg_data_pending = 1;
166 166
167 if (!atomic_read(&conn->sndbuf_space) || conn->urg_tx_pend) { 167 if (!atomic_read(&conn->sndbuf_space) || conn->urg_tx_pend) {
168 if (send_done)
169 return send_done;
168 rc = smc_tx_wait(smc, msg->msg_flags); 170 rc = smc_tx_wait(smc, msg->msg_flags);
169 if (rc) { 171 if (rc)
170 if (send_done)
171 return send_done;
172 goto out_err; 172 goto out_err;
173 }
174 continue; 173 continue;
175 } 174 }
176 175
@@ -267,27 +266,23 @@ int smcd_tx_ism_write(struct smc_connection *conn, void *data, size_t len,
267 266
268/* sndbuf consumer: actual data transfer of one target chunk with RDMA write */ 267/* sndbuf consumer: actual data transfer of one target chunk with RDMA write */
269static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset, 268static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset,
270 int num_sges, struct ib_sge sges[]) 269 int num_sges, struct ib_rdma_wr *rdma_wr)
271{ 270{
272 struct smc_link_group *lgr = conn->lgr; 271 struct smc_link_group *lgr = conn->lgr;
273 struct ib_rdma_wr rdma_wr;
274 struct smc_link *link; 272 struct smc_link *link;
275 int rc; 273 int rc;
276 274
277 memset(&rdma_wr, 0, sizeof(rdma_wr));
278 link = &lgr->lnk[SMC_SINGLE_LINK]; 275 link = &lgr->lnk[SMC_SINGLE_LINK];
279 rdma_wr.wr.wr_id = smc_wr_tx_get_next_wr_id(link); 276 rdma_wr->wr.wr_id = smc_wr_tx_get_next_wr_id(link);
280 rdma_wr.wr.sg_list = sges; 277 rdma_wr->wr.num_sge = num_sges;
281 rdma_wr.wr.num_sge = num_sges; 278 rdma_wr->remote_addr =
282 rdma_wr.wr.opcode = IB_WR_RDMA_WRITE;
283 rdma_wr.remote_addr =
284 lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].dma_addr + 279 lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].dma_addr +
285 /* RMBE within RMB */ 280 /* RMBE within RMB */
286 conn->tx_off + 281 conn->tx_off +
287 /* offset within RMBE */ 282 /* offset within RMBE */
288 peer_rmbe_offset; 283 peer_rmbe_offset;
289 rdma_wr.rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey; 284 rdma_wr->rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
290 rc = ib_post_send(link->roce_qp, &rdma_wr.wr, NULL); 285 rc = ib_post_send(link->roce_qp, &rdma_wr->wr, NULL);
291 if (rc) { 286 if (rc) {
292 conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; 287 conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
293 smc_lgr_terminate(lgr); 288 smc_lgr_terminate(lgr);
@@ -314,24 +309,25 @@ static inline void smc_tx_advance_cursors(struct smc_connection *conn,
314/* SMC-R helper for smc_tx_rdma_writes() */ 309/* SMC-R helper for smc_tx_rdma_writes() */
315static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len, 310static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
316 size_t src_off, size_t src_len, 311 size_t src_off, size_t src_len,
317 size_t dst_off, size_t dst_len) 312 size_t dst_off, size_t dst_len,
313 struct smc_rdma_wr *wr_rdma_buf)
318{ 314{
319 dma_addr_t dma_addr = 315 dma_addr_t dma_addr =
320 sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl); 316 sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl);
321 struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK];
322 int src_len_sum = src_len, dst_len_sum = dst_len; 317 int src_len_sum = src_len, dst_len_sum = dst_len;
323 struct ib_sge sges[SMC_IB_MAX_SEND_SGE];
324 int sent_count = src_off; 318 int sent_count = src_off;
325 int srcchunk, dstchunk; 319 int srcchunk, dstchunk;
326 int num_sges; 320 int num_sges;
327 int rc; 321 int rc;
328 322
329 for (dstchunk = 0; dstchunk < 2; dstchunk++) { 323 for (dstchunk = 0; dstchunk < 2; dstchunk++) {
324 struct ib_sge *sge =
325 wr_rdma_buf->wr_tx_rdma[dstchunk].wr.sg_list;
326
330 num_sges = 0; 327 num_sges = 0;
331 for (srcchunk = 0; srcchunk < 2; srcchunk++) { 328 for (srcchunk = 0; srcchunk < 2; srcchunk++) {
332 sges[srcchunk].addr = dma_addr + src_off; 329 sge[srcchunk].addr = dma_addr + src_off;
333 sges[srcchunk].length = src_len; 330 sge[srcchunk].length = src_len;
334 sges[srcchunk].lkey = link->roce_pd->local_dma_lkey;
335 num_sges++; 331 num_sges++;
336 332
337 src_off += src_len; 333 src_off += src_len;
@@ -344,7 +340,8 @@ static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
344 src_len = dst_len - src_len; /* remainder */ 340 src_len = dst_len - src_len; /* remainder */
345 src_len_sum += src_len; 341 src_len_sum += src_len;
346 } 342 }
347 rc = smc_tx_rdma_write(conn, dst_off, num_sges, sges); 343 rc = smc_tx_rdma_write(conn, dst_off, num_sges,
344 &wr_rdma_buf->wr_tx_rdma[dstchunk]);
348 if (rc) 345 if (rc)
349 return rc; 346 return rc;
350 if (dst_len_sum == len) 347 if (dst_len_sum == len)
@@ -403,7 +400,8 @@ static int smcd_tx_rdma_writes(struct smc_connection *conn, size_t len,
403/* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit; 400/* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit;
404 * usable snd_wnd as max transmit 401 * usable snd_wnd as max transmit
405 */ 402 */
406static int smc_tx_rdma_writes(struct smc_connection *conn) 403static int smc_tx_rdma_writes(struct smc_connection *conn,
404 struct smc_rdma_wr *wr_rdma_buf)
407{ 405{
408 size_t len, src_len, dst_off, dst_len; /* current chunk values */ 406 size_t len, src_len, dst_off, dst_len; /* current chunk values */
409 union smc_host_cursor sent, prep, prod, cons; 407 union smc_host_cursor sent, prep, prod, cons;
@@ -464,7 +462,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn)
464 dst_off, dst_len); 462 dst_off, dst_len);
465 else 463 else
466 rc = smcr_tx_rdma_writes(conn, len, sent.count, src_len, 464 rc = smcr_tx_rdma_writes(conn, len, sent.count, src_len,
467 dst_off, dst_len); 465 dst_off, dst_len, wr_rdma_buf);
468 if (rc) 466 if (rc)
469 return rc; 467 return rc;
470 468
@@ -485,31 +483,30 @@ static int smc_tx_rdma_writes(struct smc_connection *conn)
485static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn) 483static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
486{ 484{
487 struct smc_cdc_producer_flags *pflags; 485 struct smc_cdc_producer_flags *pflags;
486 struct smc_rdma_wr *wr_rdma_buf;
488 struct smc_cdc_tx_pend *pend; 487 struct smc_cdc_tx_pend *pend;
489 struct smc_wr_buf *wr_buf; 488 struct smc_wr_buf *wr_buf;
490 int rc; 489 int rc;
491 490
492 spin_lock_bh(&conn->send_lock); 491 rc = smc_cdc_get_free_slot(conn, &wr_buf, &wr_rdma_buf, &pend);
493 rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend);
494 if (rc < 0) { 492 if (rc < 0) {
495 if (rc == -EBUSY) { 493 if (rc == -EBUSY) {
496 struct smc_sock *smc = 494 struct smc_sock *smc =
497 container_of(conn, struct smc_sock, conn); 495 container_of(conn, struct smc_sock, conn);
498 496
499 if (smc->sk.sk_err == ECONNABORTED) { 497 if (smc->sk.sk_err == ECONNABORTED)
500 rc = sock_error(&smc->sk); 498 return sock_error(&smc->sk);
501 goto out_unlock;
502 }
503 rc = 0; 499 rc = 0;
504 if (conn->alert_token_local) /* connection healthy */ 500 if (conn->alert_token_local) /* connection healthy */
505 mod_delayed_work(system_wq, &conn->tx_work, 501 mod_delayed_work(system_wq, &conn->tx_work,
506 SMC_TX_WORK_DELAY); 502 SMC_TX_WORK_DELAY);
507 } 503 }
508 goto out_unlock; 504 return rc;
509 } 505 }
510 506
507 spin_lock_bh(&conn->send_lock);
511 if (!conn->local_tx_ctrl.prod_flags.urg_data_present) { 508 if (!conn->local_tx_ctrl.prod_flags.urg_data_present) {
512 rc = smc_tx_rdma_writes(conn); 509 rc = smc_tx_rdma_writes(conn, wr_rdma_buf);
513 if (rc) { 510 if (rc) {
514 smc_wr_tx_put_slot(&conn->lgr->lnk[SMC_SINGLE_LINK], 511 smc_wr_tx_put_slot(&conn->lgr->lnk[SMC_SINGLE_LINK],
515 (struct smc_wr_tx_pend_priv *)pend); 512 (struct smc_wr_tx_pend_priv *)pend);
@@ -536,7 +533,7 @@ static int smcd_tx_sndbuf_nonempty(struct smc_connection *conn)
536 533
537 spin_lock_bh(&conn->send_lock); 534 spin_lock_bh(&conn->send_lock);
538 if (!pflags->urg_data_present) 535 if (!pflags->urg_data_present)
539 rc = smc_tx_rdma_writes(conn); 536 rc = smc_tx_rdma_writes(conn, NULL);
540 if (!rc) 537 if (!rc)
541 rc = smcd_cdc_msg_send(conn); 538 rc = smcd_cdc_msg_send(conn);
542 539
@@ -598,7 +595,8 @@ void smc_tx_consumer_update(struct smc_connection *conn, bool force)
598 if (to_confirm > conn->rmbe_update_limit) { 595 if (to_confirm > conn->rmbe_update_limit) {
599 smc_curs_copy(&prod, &conn->local_rx_ctrl.prod, conn); 596 smc_curs_copy(&prod, &conn->local_rx_ctrl.prod, conn);
600 sender_free = conn->rmb_desc->len - 597 sender_free = conn->rmb_desc->len -
601 smc_curs_diff(conn->rmb_desc->len, &prod, &cfed); 598 smc_curs_diff_large(conn->rmb_desc->len,
599 &cfed, &prod);
602 } 600 }
603 601
604 if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req || 602 if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req ||
diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c
index c2694750a6a8..253aa75dc2b6 100644
--- a/net/smc/smc_wr.c
+++ b/net/smc/smc_wr.c
@@ -160,6 +160,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
160 * @link: Pointer to smc_link used to later send the message. 160 * @link: Pointer to smc_link used to later send the message.
161 * @handler: Send completion handler function pointer. 161 * @handler: Send completion handler function pointer.
162 * @wr_buf: Out value returns pointer to message buffer. 162 * @wr_buf: Out value returns pointer to message buffer.
163 * @wr_rdma_buf: Out value returns pointer to rdma work request.
163 * @wr_pend_priv: Out value returns pointer serving as handler context. 164 * @wr_pend_priv: Out value returns pointer serving as handler context.
164 * 165 *
165 * Return: 0 on success, or -errno on error. 166 * 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)
167int smc_wr_tx_get_free_slot(struct smc_link *link, 168int smc_wr_tx_get_free_slot(struct smc_link *link,
168 smc_wr_tx_handler handler, 169 smc_wr_tx_handler handler,
169 struct smc_wr_buf **wr_buf, 170 struct smc_wr_buf **wr_buf,
171 struct smc_rdma_wr **wr_rdma_buf,
170 struct smc_wr_tx_pend_priv **wr_pend_priv) 172 struct smc_wr_tx_pend_priv **wr_pend_priv)
171{ 173{
172 struct smc_wr_tx_pend *wr_pend; 174 struct smc_wr_tx_pend *wr_pend;
@@ -204,6 +206,8 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
204 wr_ib = &link->wr_tx_ibs[idx]; 206 wr_ib = &link->wr_tx_ibs[idx];
205 wr_ib->wr_id = wr_id; 207 wr_ib->wr_id = wr_id;
206 *wr_buf = &link->wr_tx_bufs[idx]; 208 *wr_buf = &link->wr_tx_bufs[idx];
209 if (wr_rdma_buf)
210 *wr_rdma_buf = &link->wr_tx_rdmas[idx];
207 *wr_pend_priv = &wr_pend->priv; 211 *wr_pend_priv = &wr_pend->priv;
208 return 0; 212 return 0;
209} 213}
@@ -218,10 +222,10 @@ int smc_wr_tx_put_slot(struct smc_link *link,
218 u32 idx = pend->idx; 222 u32 idx = pend->idx;
219 223
220 /* clear the full struct smc_wr_tx_pend including .priv */ 224 /* clear the full struct smc_wr_tx_pend including .priv */
221 memset(&link->wr_tx_pends[pend->idx], 0, 225 memset(&link->wr_tx_pends[idx], 0,
222 sizeof(link->wr_tx_pends[pend->idx])); 226 sizeof(link->wr_tx_pends[idx]));
223 memset(&link->wr_tx_bufs[pend->idx], 0, 227 memset(&link->wr_tx_bufs[idx], 0,
224 sizeof(link->wr_tx_bufs[pend->idx])); 228 sizeof(link->wr_tx_bufs[idx]));
225 test_and_clear_bit(idx, link->wr_tx_mask); 229 test_and_clear_bit(idx, link->wr_tx_mask);
226 return 1; 230 return 1;
227 } 231 }
@@ -465,12 +469,26 @@ static void smc_wr_init_sge(struct smc_link *lnk)
465 lnk->wr_tx_dma_addr + i * SMC_WR_BUF_SIZE; 469 lnk->wr_tx_dma_addr + i * SMC_WR_BUF_SIZE;
466 lnk->wr_tx_sges[i].length = SMC_WR_TX_SIZE; 470 lnk->wr_tx_sges[i].length = SMC_WR_TX_SIZE;
467 lnk->wr_tx_sges[i].lkey = lnk->roce_pd->local_dma_lkey; 471 lnk->wr_tx_sges[i].lkey = lnk->roce_pd->local_dma_lkey;
472 lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[0].lkey =
473 lnk->roce_pd->local_dma_lkey;
474 lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[1].lkey =
475 lnk->roce_pd->local_dma_lkey;
476 lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[0].lkey =
477 lnk->roce_pd->local_dma_lkey;
478 lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[1].lkey =
479 lnk->roce_pd->local_dma_lkey;
468 lnk->wr_tx_ibs[i].next = NULL; 480 lnk->wr_tx_ibs[i].next = NULL;
469 lnk->wr_tx_ibs[i].sg_list = &lnk->wr_tx_sges[i]; 481 lnk->wr_tx_ibs[i].sg_list = &lnk->wr_tx_sges[i];
470 lnk->wr_tx_ibs[i].num_sge = 1; 482 lnk->wr_tx_ibs[i].num_sge = 1;
471 lnk->wr_tx_ibs[i].opcode = IB_WR_SEND; 483 lnk->wr_tx_ibs[i].opcode = IB_WR_SEND;
472 lnk->wr_tx_ibs[i].send_flags = 484 lnk->wr_tx_ibs[i].send_flags =
473 IB_SEND_SIGNALED | IB_SEND_SOLICITED; 485 IB_SEND_SIGNALED | IB_SEND_SOLICITED;
486 lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.opcode = IB_WR_RDMA_WRITE;
487 lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.opcode = IB_WR_RDMA_WRITE;
488 lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.sg_list =
489 lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge;
490 lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.sg_list =
491 lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge;
474 } 492 }
475 for (i = 0; i < lnk->wr_rx_cnt; i++) { 493 for (i = 0; i < lnk->wr_rx_cnt; i++) {
476 lnk->wr_rx_sges[i].addr = 494 lnk->wr_rx_sges[i].addr =
@@ -521,8 +539,12 @@ void smc_wr_free_link_mem(struct smc_link *lnk)
521 lnk->wr_tx_mask = NULL; 539 lnk->wr_tx_mask = NULL;
522 kfree(lnk->wr_tx_sges); 540 kfree(lnk->wr_tx_sges);
523 lnk->wr_tx_sges = NULL; 541 lnk->wr_tx_sges = NULL;
542 kfree(lnk->wr_tx_rdma_sges);
543 lnk->wr_tx_rdma_sges = NULL;
524 kfree(lnk->wr_rx_sges); 544 kfree(lnk->wr_rx_sges);
525 lnk->wr_rx_sges = NULL; 545 lnk->wr_rx_sges = NULL;
546 kfree(lnk->wr_tx_rdmas);
547 lnk->wr_tx_rdmas = NULL;
526 kfree(lnk->wr_rx_ibs); 548 kfree(lnk->wr_rx_ibs);
527 lnk->wr_rx_ibs = NULL; 549 lnk->wr_rx_ibs = NULL;
528 kfree(lnk->wr_tx_ibs); 550 kfree(lnk->wr_tx_ibs);
@@ -552,10 +574,20 @@ int smc_wr_alloc_link_mem(struct smc_link *link)
552 GFP_KERNEL); 574 GFP_KERNEL);
553 if (!link->wr_rx_ibs) 575 if (!link->wr_rx_ibs)
554 goto no_mem_wr_tx_ibs; 576 goto no_mem_wr_tx_ibs;
577 link->wr_tx_rdmas = kcalloc(SMC_WR_BUF_CNT,
578 sizeof(link->wr_tx_rdmas[0]),
579 GFP_KERNEL);
580 if (!link->wr_tx_rdmas)
581 goto no_mem_wr_rx_ibs;
582 link->wr_tx_rdma_sges = kcalloc(SMC_WR_BUF_CNT,
583 sizeof(link->wr_tx_rdma_sges[0]),
584 GFP_KERNEL);
585 if (!link->wr_tx_rdma_sges)
586 goto no_mem_wr_tx_rdmas;
555 link->wr_tx_sges = kcalloc(SMC_WR_BUF_CNT, sizeof(link->wr_tx_sges[0]), 587 link->wr_tx_sges = kcalloc(SMC_WR_BUF_CNT, sizeof(link->wr_tx_sges[0]),
556 GFP_KERNEL); 588 GFP_KERNEL);
557 if (!link->wr_tx_sges) 589 if (!link->wr_tx_sges)
558 goto no_mem_wr_rx_ibs; 590 goto no_mem_wr_tx_rdma_sges;
559 link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3, 591 link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3,
560 sizeof(link->wr_rx_sges[0]), 592 sizeof(link->wr_rx_sges[0]),
561 GFP_KERNEL); 593 GFP_KERNEL);
@@ -579,6 +611,10 @@ no_mem_wr_rx_sges:
579 kfree(link->wr_rx_sges); 611 kfree(link->wr_rx_sges);
580no_mem_wr_tx_sges: 612no_mem_wr_tx_sges:
581 kfree(link->wr_tx_sges); 613 kfree(link->wr_tx_sges);
614no_mem_wr_tx_rdma_sges:
615 kfree(link->wr_tx_rdma_sges);
616no_mem_wr_tx_rdmas:
617 kfree(link->wr_tx_rdmas);
582no_mem_wr_rx_ibs: 618no_mem_wr_rx_ibs:
583 kfree(link->wr_rx_ibs); 619 kfree(link->wr_rx_ibs);
584no_mem_wr_tx_ibs: 620no_mem_wr_tx_ibs:
diff --git a/net/smc/smc_wr.h b/net/smc/smc_wr.h
index 1d85bb14fd6f..09bf32fd3959 100644
--- a/net/smc/smc_wr.h
+++ b/net/smc/smc_wr.h
@@ -85,6 +85,7 @@ void smc_wr_add_dev(struct smc_ib_device *smcibdev);
85 85
86int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler, 86int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler,
87 struct smc_wr_buf **wr_buf, 87 struct smc_wr_buf **wr_buf,
88 struct smc_rdma_wr **wrs,
88 struct smc_wr_tx_pend_priv **wr_pend_priv); 89 struct smc_wr_tx_pend_priv **wr_pend_priv);
89int smc_wr_tx_put_slot(struct smc_link *link, 90int smc_wr_tx_put_slot(struct smc_link *link,
90 struct smc_wr_tx_pend_priv *wr_pend_priv); 91 struct smc_wr_tx_pend_priv *wr_pend_priv);