aboutsummaryrefslogtreecommitdiffstats
path: root/net/smc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-02-08 14:21:54 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2019-02-08 14:21:54 -0500
commit27b4ad621e887ce8e5eb508a0103f13d30f6b38a (patch)
treee1fda67c6c119c2f6a00a22fe8ae9b7a2494e799 /net/smc
parent680905431b9de8c7224b15b76b1826a1481cfeaf (diff)
parent39841cc1cbb69344539c98a1fa9d858ed124c7ba (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: "This pull request is dedicated to the upcoming snowpocalypse parts 2 and 3 in the Pacific Northwest: 1) Drop profiles are broken because some drivers use dev_kfree_skb* instead of dev_consume_skb*, from Yang Wei. 2) Fix IWLWIFI kconfig deps, from Luca Coelho. 3) Fix percpu maps updating in bpftool, from Paolo Abeni. 4) Missing station release in batman-adv, from Felix Fietkau. 5) Fix some networking compat ioctl bugs, from Johannes Berg. 6) ucc_geth must reset the BQL queue state when stopping the device, from Mathias Thore. 7) Several XDP bug fixes in virtio_net from Toshiaki Makita. 8) TSO packets must be sent always on queue 0 in stmmac, from Jose Abreu. 9) Fix socket refcounting bug in RDS, from Eric Dumazet. 10) Handle sparse cpu allocations in bpf selftests, from Martynas Pumputis. 11) Make sure mgmt frames have enough tailroom in mac80211, from Felix Feitkau. 12) Use safe list walking in sctp_sendmsg() asoc list traversal, from Greg Kroah-Hartman. 13) Make DCCP's ccid_hc_[rt]x_parse_options always check for NULL ccid, from Eric Dumazet. 14) Need to reload WoL password into bcmsysport device after deep sleeps, from Florian Fainelli. 15) Remove filter from mask before freeing in cls_flower, from Petr Machata. 16) Missing release and use after free in error paths of s390 qeth code, from Julian Wiedmann. 17) Fix lockdep false positive in dsa code, from Marc Zyngier. 18) Fix counting of ATU violations in mv88e6xxx, from Andrew Lunn. 19) Fix EQ firmware assert in qed driver, from Manish Chopra. 20) Don't default Caivum PTP to Y in kconfig, from Bjorn Helgaas" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (116 commits) net: dsa: b53: Fix for failure when irq is not defined in dt sit: check if IPv6 enabled before calling ip6_err_gen_icmpv6_unreach() geneve: should not call rt6_lookup() when ipv6 was disabled net: Don't default Cavium PTP driver to 'y' net: broadcom: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles net: via-velocity: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles net: tehuti: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles net: sun: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles net: fsl_ucc_hdlc: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles net: fec_mpc52xx: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles net: smsc: epic100: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles net: dscc4: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles net: tulip: de2104x: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles net: defxx: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles net/mlx5e: Don't overwrite pedit action when multiple pedit used net/mlx5e: Update hw flows when encap source mac changed qed*: Advance drivers version to 8.37.0.20 qed: Change verbosity for coalescing message. qede: Fix system crash on configuring channels. qed: Consider TX tcs while deriving the max num_queues for PF. ...
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);