diff options
Diffstat (limited to 'net/smc')
| -rw-r--r-- | net/smc/af_smc.c | 11 | ||||
| -rw-r--r-- | net/smc/smc_cdc.c | 21 | ||||
| -rw-r--r-- | net/smc/smc_cdc.h | 34 | ||||
| -rw-r--r-- | net/smc/smc_clc.c | 2 | ||||
| -rw-r--r-- | net/smc/smc_close.c | 9 | ||||
| -rw-r--r-- | net/smc/smc_core.c | 6 | ||||
| -rw-r--r-- | net/smc/smc_core.h | 20 | ||||
| -rw-r--r-- | net/smc/smc_ib.c | 6 | ||||
| -rw-r--r-- | net/smc/smc_llc.c | 3 | ||||
| -rw-r--r-- | net/smc/smc_pnet.c | 2 | ||||
| -rw-r--r-- | net/smc/smc_tx.c | 64 | ||||
| -rw-r--r-- | net/smc/smc_wr.c | 46 | ||||
| -rw-r--r-- | net/smc/smc_wr.h | 1 |
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 | ||
| 24 | struct 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 */ |
| 32 | static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd, | 25 | static 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 | ||
| 62 | int smc_cdc_get_free_slot(struct smc_connection *conn, | 55 | int 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 | ||
| 131 | int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn) | 130 | int 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 | */ | ||
| 164 | static inline int smc_curs_diff(unsigned int size, | 166 | static 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 | */ | ||
| 193 | static 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 | |||
| 188 | static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer, | 212 | static 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 | ||
| 273 | struct smc_cdc_tx_pend; | 297 | struct 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 | ||
| 275 | int smc_cdc_get_free_slot(struct smc_connection *conn, | 304 | int 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); |
| 278 | void smc_cdc_tx_dismiss_slots(struct smc_connection *conn); | 308 | void smc_cdc_tx_dismiss_slots(struct smc_connection *conn); |
| 279 | int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf, | 309 | int 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 | ||
| 55 | struct 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 | |||
| 63 | struct smc_rdma_sges { /* sges per message send */ | ||
| 64 | struct smc_rdma_sge tx_rdma_sge[SMC_MAX_RDMA_WRITES]; | ||
| 65 | }; | ||
| 66 | |||
| 67 | struct smc_rdma_wr { /* work requests per message | ||
| 68 | * send | ||
| 69 | */ | ||
| 70 | struct ib_rdma_wr wr_tx_rdma[SMC_MAX_RDMA_WRITES]; | ||
| 71 | }; | ||
| 72 | |||
| 55 | struct smc_link { | 73 | struct 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 | ||
| 290 | static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv) | 290 | static 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 @@ | |||
| 27 | static struct nla_policy smc_pnet_policy[SMC_PNETID_MAX + 1] = { | 27 | static 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 */ |
| 269 | static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset, | 268 | static 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() */ |
| 315 | static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len, | 310 | static 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 | */ |
| 406 | static int smc_tx_rdma_writes(struct smc_connection *conn) | 403 | static 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) | |||
| 485 | static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn) | 483 | static 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) | |||
| 167 | int smc_wr_tx_get_free_slot(struct smc_link *link, | 168 | int 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); |
| 580 | no_mem_wr_tx_sges: | 612 | no_mem_wr_tx_sges: |
| 581 | kfree(link->wr_tx_sges); | 613 | kfree(link->wr_tx_sges); |
| 614 | no_mem_wr_tx_rdma_sges: | ||
| 615 | kfree(link->wr_tx_rdma_sges); | ||
| 616 | no_mem_wr_tx_rdmas: | ||
| 617 | kfree(link->wr_tx_rdmas); | ||
| 582 | no_mem_wr_rx_ibs: | 618 | no_mem_wr_rx_ibs: |
| 583 | kfree(link->wr_rx_ibs); | 619 | kfree(link->wr_rx_ibs); |
| 584 | no_mem_wr_tx_ibs: | 620 | no_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 | ||
| 86 | int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler, | 86 | int 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); |
| 89 | int smc_wr_tx_put_slot(struct smc_link *link, | 90 | int 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); |
