aboutsummaryrefslogtreecommitdiffstats
path: root/net/smc
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@mellanox.com>2018-08-16 15:08:18 -0400
committerJason Gunthorpe <jgg@mellanox.com>2018-08-16 15:12:00 -0400
commit89982f7ccee2fcd8fea7936b81eec6defbf0f131 (patch)
treefc553c8d008d24595ad7de0ea0f3b56f656da27c /net/smc
parenta1ceeca679dccc492235f0f629d9e9f7b3d51ca8 (diff)
parent94710cac0ef4ee177a63b5227664b38c95bbf703 (diff)
Merge tag 'v4.18' into rdma.git for-next
Resolve merge conflicts from the -rc cycle against the rdma.git tree: Conflicts: drivers/infiniband/core/uverbs_cmd.c - New ifs added to ib_uverbs_ex_create_flow in -rc and for-next - Merge removal of file->ucontext in for-next with new code in -rc drivers/infiniband/core/uverbs_main.c - for-next removed code from ib_uverbs_write() that was modified in for-rc Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Diffstat (limited to 'net/smc')
-rw-r--r--net/smc/af_smc.c151
-rw-r--r--net/smc/smc.h8
-rw-r--r--net/smc/smc_cdc.c3
-rw-r--r--net/smc/smc_clc.c3
-rw-r--r--net/smc/smc_close.c2
-rw-r--r--net/smc/smc_tx.c12
6 files changed, 129 insertions, 50 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index da7f02edcd37..e7de5f282722 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -45,6 +45,7 @@ static DEFINE_MUTEX(smc_create_lgr_pending); /* serialize link group
45 */ 45 */
46 46
47static void smc_tcp_listen_work(struct work_struct *); 47static void smc_tcp_listen_work(struct work_struct *);
48static void smc_connect_work(struct work_struct *);
48 49
49static void smc_set_keepalive(struct sock *sk, int val) 50static void smc_set_keepalive(struct sock *sk, int val)
50{ 51{
@@ -122,6 +123,12 @@ static int smc_release(struct socket *sock)
122 goto out; 123 goto out;
123 124
124 smc = smc_sk(sk); 125 smc = smc_sk(sk);
126
127 /* cleanup for a dangling non-blocking connect */
128 flush_work(&smc->connect_work);
129 kfree(smc->connect_info);
130 smc->connect_info = NULL;
131
125 if (sk->sk_state == SMC_LISTEN) 132 if (sk->sk_state == SMC_LISTEN)
126 /* smc_close_non_accepted() is called and acquires 133 /* smc_close_non_accepted() is called and acquires
127 * sock lock for child sockets again 134 * sock lock for child sockets again
@@ -140,7 +147,8 @@ static int smc_release(struct socket *sock)
140 smc->clcsock = NULL; 147 smc->clcsock = NULL;
141 } 148 }
142 if (smc->use_fallback) { 149 if (smc->use_fallback) {
143 sock_put(sk); /* passive closing */ 150 if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT)
151 sock_put(sk); /* passive closing */
144 sk->sk_state = SMC_CLOSED; 152 sk->sk_state = SMC_CLOSED;
145 sk->sk_state_change(sk); 153 sk->sk_state_change(sk);
146 } 154 }
@@ -186,6 +194,7 @@ static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
186 sk->sk_protocol = protocol; 194 sk->sk_protocol = protocol;
187 smc = smc_sk(sk); 195 smc = smc_sk(sk);
188 INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work); 196 INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work);
197 INIT_WORK(&smc->connect_work, smc_connect_work);
189 INIT_DELAYED_WORK(&smc->conn.tx_work, smc_tx_work); 198 INIT_DELAYED_WORK(&smc->conn.tx_work, smc_tx_work);
190 INIT_LIST_HEAD(&smc->accept_q); 199 INIT_LIST_HEAD(&smc->accept_q);
191 spin_lock_init(&smc->accept_q_lock); 200 spin_lock_init(&smc->accept_q_lock);
@@ -409,12 +418,18 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code)
409{ 418{
410 int rc; 419 int rc;
411 420
412 if (reason_code < 0) /* error, fallback is not possible */ 421 if (reason_code < 0) { /* error, fallback is not possible */
422 if (smc->sk.sk_state == SMC_INIT)
423 sock_put(&smc->sk); /* passive closing */
413 return reason_code; 424 return reason_code;
425 }
414 if (reason_code != SMC_CLC_DECL_REPLY) { 426 if (reason_code != SMC_CLC_DECL_REPLY) {
415 rc = smc_clc_send_decline(smc, reason_code); 427 rc = smc_clc_send_decline(smc, reason_code);
416 if (rc < 0) 428 if (rc < 0) {
429 if (smc->sk.sk_state == SMC_INIT)
430 sock_put(&smc->sk); /* passive closing */
417 return rc; 431 return rc;
432 }
418 } 433 }
419 return smc_connect_fallback(smc); 434 return smc_connect_fallback(smc);
420} 435}
@@ -427,8 +442,6 @@ static int smc_connect_abort(struct smc_sock *smc, int reason_code,
427 smc_lgr_forget(smc->conn.lgr); 442 smc_lgr_forget(smc->conn.lgr);
428 mutex_unlock(&smc_create_lgr_pending); 443 mutex_unlock(&smc_create_lgr_pending);
429 smc_conn_free(&smc->conn); 444 smc_conn_free(&smc->conn);
430 if (reason_code < 0 && smc->sk.sk_state == SMC_INIT)
431 sock_put(&smc->sk); /* passive closing */
432 return reason_code; 445 return reason_code;
433} 446}
434 447
@@ -576,6 +589,35 @@ static int __smc_connect(struct smc_sock *smc)
576 return 0; 589 return 0;
577} 590}
578 591
592static void smc_connect_work(struct work_struct *work)
593{
594 struct smc_sock *smc = container_of(work, struct smc_sock,
595 connect_work);
596 int rc;
597
598 lock_sock(&smc->sk);
599 rc = kernel_connect(smc->clcsock, &smc->connect_info->addr,
600 smc->connect_info->alen, smc->connect_info->flags);
601 if (smc->clcsock->sk->sk_err) {
602 smc->sk.sk_err = smc->clcsock->sk->sk_err;
603 goto out;
604 }
605 if (rc < 0) {
606 smc->sk.sk_err = -rc;
607 goto out;
608 }
609
610 rc = __smc_connect(smc);
611 if (rc < 0)
612 smc->sk.sk_err = -rc;
613
614out:
615 smc->sk.sk_state_change(&smc->sk);
616 kfree(smc->connect_info);
617 smc->connect_info = NULL;
618 release_sock(&smc->sk);
619}
620
579static int smc_connect(struct socket *sock, struct sockaddr *addr, 621static int smc_connect(struct socket *sock, struct sockaddr *addr,
580 int alen, int flags) 622 int alen, int flags)
581{ 623{
@@ -605,15 +647,32 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
605 647
606 smc_copy_sock_settings_to_clc(smc); 648 smc_copy_sock_settings_to_clc(smc);
607 tcp_sk(smc->clcsock->sk)->syn_smc = 1; 649 tcp_sk(smc->clcsock->sk)->syn_smc = 1;
608 rc = kernel_connect(smc->clcsock, addr, alen, flags); 650 if (flags & O_NONBLOCK) {
609 if (rc) 651 if (smc->connect_info) {
610 goto out; 652 rc = -EALREADY;
653 goto out;
654 }
655 smc->connect_info = kzalloc(alen + 2 * sizeof(int), GFP_KERNEL);
656 if (!smc->connect_info) {
657 rc = -ENOMEM;
658 goto out;
659 }
660 smc->connect_info->alen = alen;
661 smc->connect_info->flags = flags ^ O_NONBLOCK;
662 memcpy(&smc->connect_info->addr, addr, alen);
663 schedule_work(&smc->connect_work);
664 rc = -EINPROGRESS;
665 } else {
666 rc = kernel_connect(smc->clcsock, addr, alen, flags);
667 if (rc)
668 goto out;
611 669
612 rc = __smc_connect(smc); 670 rc = __smc_connect(smc);
613 if (rc < 0) 671 if (rc < 0)
614 goto out; 672 goto out;
615 else 673 else
616 rc = 0; /* success cases including fallback */ 674 rc = 0; /* success cases including fallback */
675 }
617 676
618out: 677out:
619 release_sock(sk); 678 release_sock(sk);
@@ -1063,6 +1122,8 @@ static void smc_tcp_listen_work(struct work_struct *work)
1063 sock_hold(lsk); /* sock_put in smc_listen_work */ 1122 sock_hold(lsk); /* sock_put in smc_listen_work */
1064 INIT_WORK(&new_smc->smc_listen_work, smc_listen_work); 1123 INIT_WORK(&new_smc->smc_listen_work, smc_listen_work);
1065 smc_copy_sock_settings_to_smc(new_smc); 1124 smc_copy_sock_settings_to_smc(new_smc);
1125 new_smc->sk.sk_sndbuf = lsmc->sk.sk_sndbuf;
1126 new_smc->sk.sk_rcvbuf = lsmc->sk.sk_rcvbuf;
1066 sock_hold(&new_smc->sk); /* sock_put in passive closing */ 1127 sock_hold(&new_smc->sk); /* sock_put in passive closing */
1067 if (!schedule_work(&new_smc->smc_listen_work)) 1128 if (!schedule_work(&new_smc->smc_listen_work))
1068 sock_put(&new_smc->sk); 1129 sock_put(&new_smc->sk);
@@ -1273,40 +1334,26 @@ static __poll_t smc_accept_poll(struct sock *parent)
1273 return mask; 1334 return mask;
1274} 1335}
1275 1336
1276static __poll_t smc_poll_mask(struct socket *sock, __poll_t events) 1337static __poll_t smc_poll(struct file *file, struct socket *sock,
1338 poll_table *wait)
1277{ 1339{
1278 struct sock *sk = sock->sk; 1340 struct sock *sk = sock->sk;
1279 __poll_t mask = 0; 1341 __poll_t mask = 0;
1280 struct smc_sock *smc; 1342 struct smc_sock *smc;
1281 int rc;
1282 1343
1283 if (!sk) 1344 if (!sk)
1284 return EPOLLNVAL; 1345 return EPOLLNVAL;
1285 1346
1286 smc = smc_sk(sock->sk); 1347 smc = smc_sk(sock->sk);
1287 sock_hold(sk);
1288 lock_sock(sk);
1289 if ((sk->sk_state == SMC_INIT) || smc->use_fallback) { 1348 if ((sk->sk_state == SMC_INIT) || smc->use_fallback) {
1290 /* delegate to CLC child sock */ 1349 /* delegate to CLC child sock */
1291 release_sock(sk); 1350 mask = smc->clcsock->ops->poll(file, smc->clcsock, wait);
1292 mask = smc->clcsock->ops->poll_mask(smc->clcsock, events);
1293 lock_sock(sk);
1294 sk->sk_err = smc->clcsock->sk->sk_err; 1351 sk->sk_err = smc->clcsock->sk->sk_err;
1295 if (sk->sk_err) { 1352 if (sk->sk_err)
1296 mask |= EPOLLERR; 1353 mask |= EPOLLERR;
1297 } else {
1298 /* if non-blocking connect finished ... */
1299 if (sk->sk_state == SMC_INIT &&
1300 mask & EPOLLOUT &&
1301 smc->clcsock->sk->sk_state != TCP_CLOSE) {
1302 rc = __smc_connect(smc);
1303 if (rc < 0)
1304 mask |= EPOLLERR;
1305 /* success cases including fallback */
1306 mask |= EPOLLOUT | EPOLLWRNORM;
1307 }
1308 }
1309 } else { 1354 } else {
1355 if (sk->sk_state != SMC_CLOSED)
1356 sock_poll_wait(file, sk_sleep(sk), wait);
1310 if (sk->sk_err) 1357 if (sk->sk_err)
1311 mask |= EPOLLERR; 1358 mask |= EPOLLERR;
1312 if ((sk->sk_shutdown == SHUTDOWN_MASK) || 1359 if ((sk->sk_shutdown == SHUTDOWN_MASK) ||
@@ -1332,10 +1379,7 @@ static __poll_t smc_poll_mask(struct socket *sock, __poll_t events)
1332 } 1379 }
1333 if (smc->conn.urg_state == SMC_URG_VALID) 1380 if (smc->conn.urg_state == SMC_URG_VALID)
1334 mask |= EPOLLPRI; 1381 mask |= EPOLLPRI;
1335
1336 } 1382 }
1337 release_sock(sk);
1338 sock_put(sk);
1339 1383
1340 return mask; 1384 return mask;
1341} 1385}
@@ -1355,8 +1399,7 @@ static int smc_shutdown(struct socket *sock, int how)
1355 lock_sock(sk); 1399 lock_sock(sk);
1356 1400
1357 rc = -ENOTCONN; 1401 rc = -ENOTCONN;
1358 if ((sk->sk_state != SMC_LISTEN) && 1402 if ((sk->sk_state != SMC_ACTIVE) &&
1359 (sk->sk_state != SMC_ACTIVE) &&
1360 (sk->sk_state != SMC_PEERCLOSEWAIT1) && 1403 (sk->sk_state != SMC_PEERCLOSEWAIT1) &&
1361 (sk->sk_state != SMC_PEERCLOSEWAIT2) && 1404 (sk->sk_state != SMC_PEERCLOSEWAIT2) &&
1362 (sk->sk_state != SMC_APPCLOSEWAIT1) && 1405 (sk->sk_state != SMC_APPCLOSEWAIT1) &&
@@ -1415,7 +1458,8 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
1415 1458
1416 if (optlen < sizeof(int)) 1459 if (optlen < sizeof(int))
1417 return -EINVAL; 1460 return -EINVAL;
1418 get_user(val, (int __user *)optval); 1461 if (get_user(val, (int __user *)optval))
1462 return -EFAULT;
1419 1463
1420 lock_sock(sk); 1464 lock_sock(sk);
1421 switch (optname) { 1465 switch (optname) {
@@ -1478,15 +1522,22 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
1478 1522
1479 smc = smc_sk(sock->sk); 1523 smc = smc_sk(sock->sk);
1480 conn = &smc->conn; 1524 conn = &smc->conn;
1525 lock_sock(&smc->sk);
1481 if (smc->use_fallback) { 1526 if (smc->use_fallback) {
1482 if (!smc->clcsock) 1527 if (!smc->clcsock) {
1528 release_sock(&smc->sk);
1483 return -EBADF; 1529 return -EBADF;
1484 return smc->clcsock->ops->ioctl(smc->clcsock, cmd, arg); 1530 }
1531 answ = smc->clcsock->ops->ioctl(smc->clcsock, cmd, arg);
1532 release_sock(&smc->sk);
1533 return answ;
1485 } 1534 }
1486 switch (cmd) { 1535 switch (cmd) {
1487 case SIOCINQ: /* same as FIONREAD */ 1536 case SIOCINQ: /* same as FIONREAD */
1488 if (smc->sk.sk_state == SMC_LISTEN) 1537 if (smc->sk.sk_state == SMC_LISTEN) {
1538 release_sock(&smc->sk);
1489 return -EINVAL; 1539 return -EINVAL;
1540 }
1490 if (smc->sk.sk_state == SMC_INIT || 1541 if (smc->sk.sk_state == SMC_INIT ||
1491 smc->sk.sk_state == SMC_CLOSED) 1542 smc->sk.sk_state == SMC_CLOSED)
1492 answ = 0; 1543 answ = 0;
@@ -1495,8 +1546,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
1495 break; 1546 break;
1496 case SIOCOUTQ: 1547 case SIOCOUTQ:
1497 /* output queue size (not send + not acked) */ 1548 /* output queue size (not send + not acked) */
1498 if (smc->sk.sk_state == SMC_LISTEN) 1549 if (smc->sk.sk_state == SMC_LISTEN) {
1550 release_sock(&smc->sk);
1499 return -EINVAL; 1551 return -EINVAL;
1552 }
1500 if (smc->sk.sk_state == SMC_INIT || 1553 if (smc->sk.sk_state == SMC_INIT ||
1501 smc->sk.sk_state == SMC_CLOSED) 1554 smc->sk.sk_state == SMC_CLOSED)
1502 answ = 0; 1555 answ = 0;
@@ -1506,8 +1559,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
1506 break; 1559 break;
1507 case SIOCOUTQNSD: 1560 case SIOCOUTQNSD:
1508 /* output queue size (not send only) */ 1561 /* output queue size (not send only) */
1509 if (smc->sk.sk_state == SMC_LISTEN) 1562 if (smc->sk.sk_state == SMC_LISTEN) {
1563 release_sock(&smc->sk);
1510 return -EINVAL; 1564 return -EINVAL;
1565 }
1511 if (smc->sk.sk_state == SMC_INIT || 1566 if (smc->sk.sk_state == SMC_INIT ||
1512 smc->sk.sk_state == SMC_CLOSED) 1567 smc->sk.sk_state == SMC_CLOSED)
1513 answ = 0; 1568 answ = 0;
@@ -1515,8 +1570,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
1515 answ = smc_tx_prepared_sends(&smc->conn); 1570 answ = smc_tx_prepared_sends(&smc->conn);
1516 break; 1571 break;
1517 case SIOCATMARK: 1572 case SIOCATMARK:
1518 if (smc->sk.sk_state == SMC_LISTEN) 1573 if (smc->sk.sk_state == SMC_LISTEN) {
1574 release_sock(&smc->sk);
1519 return -EINVAL; 1575 return -EINVAL;
1576 }
1520 if (smc->sk.sk_state == SMC_INIT || 1577 if (smc->sk.sk_state == SMC_INIT ||
1521 smc->sk.sk_state == SMC_CLOSED) { 1578 smc->sk.sk_state == SMC_CLOSED) {
1522 answ = 0; 1579 answ = 0;
@@ -1532,8 +1589,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
1532 } 1589 }
1533 break; 1590 break;
1534 default: 1591 default:
1592 release_sock(&smc->sk);
1535 return -ENOIOCTLCMD; 1593 return -ENOIOCTLCMD;
1536 } 1594 }
1595 release_sock(&smc->sk);
1537 1596
1538 return put_user(answ, (int __user *)arg); 1597 return put_user(answ, (int __user *)arg);
1539} 1598}
@@ -1619,7 +1678,7 @@ static const struct proto_ops smc_sock_ops = {
1619 .socketpair = sock_no_socketpair, 1678 .socketpair = sock_no_socketpair,
1620 .accept = smc_accept, 1679 .accept = smc_accept,
1621 .getname = smc_getname, 1680 .getname = smc_getname,
1622 .poll_mask = smc_poll_mask, 1681 .poll = smc_poll,
1623 .ioctl = smc_ioctl, 1682 .ioctl = smc_ioctl,
1624 .listen = smc_listen, 1683 .listen = smc_listen,
1625 .shutdown = smc_shutdown, 1684 .shutdown = smc_shutdown,
diff --git a/net/smc/smc.h b/net/smc/smc.h
index 51ae1f10d81a..d7ca26570482 100644
--- a/net/smc/smc.h
+++ b/net/smc/smc.h
@@ -187,11 +187,19 @@ struct smc_connection {
187 struct work_struct close_work; /* peer sent some closing */ 187 struct work_struct close_work; /* peer sent some closing */
188}; 188};
189 189
190struct smc_connect_info {
191 int flags;
192 int alen;
193 struct sockaddr addr;
194};
195
190struct smc_sock { /* smc sock container */ 196struct smc_sock { /* smc sock container */
191 struct sock sk; 197 struct sock sk;
192 struct socket *clcsock; /* internal tcp socket */ 198 struct socket *clcsock; /* internal tcp socket */
193 struct smc_connection conn; /* smc connection */ 199 struct smc_connection conn; /* smc connection */
194 struct smc_sock *listen_smc; /* listen parent */ 200 struct smc_sock *listen_smc; /* listen parent */
201 struct smc_connect_info *connect_info; /* connect address & flags */
202 struct work_struct connect_work; /* handle non-blocking connect*/
195 struct work_struct tcp_listen_work;/* handle tcp socket accepts */ 203 struct work_struct tcp_listen_work;/* handle tcp socket accepts */
196 struct work_struct smc_listen_work;/* prepare new accept socket */ 204 struct work_struct smc_listen_work;/* prepare new accept socket */
197 struct list_head accept_q; /* sockets to be accepted */ 205 struct list_head accept_q; /* sockets to be accepted */
diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c
index a7e8d63fc8ae..9bde1e4ca288 100644
--- a/net/smc/smc_cdc.c
+++ b/net/smc/smc_cdc.c
@@ -233,7 +233,8 @@ static void smc_cdc_msg_recv_action(struct smc_sock *smc,
233 /* force immediate tx of current consumer cursor, but 233 /* force immediate tx of current consumer cursor, but
234 * under send_lock to guarantee arrival in seqno-order 234 * under send_lock to guarantee arrival in seqno-order
235 */ 235 */
236 smc_tx_sndbuf_nonempty(conn); 236 if (smc->sk.sk_state != SMC_INIT)
237 smc_tx_sndbuf_nonempty(conn);
237 } 238 }
238 } 239 }
239 240
diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
index 717449b1da0b..ae5d168653ce 100644
--- a/net/smc/smc_clc.c
+++ b/net/smc/smc_clc.c
@@ -250,6 +250,7 @@ out:
250int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, 250int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
251 u8 expected_type) 251 u8 expected_type)
252{ 252{
253 long rcvtimeo = smc->clcsock->sk->sk_rcvtimeo;
253 struct sock *clc_sk = smc->clcsock->sk; 254 struct sock *clc_sk = smc->clcsock->sk;
254 struct smc_clc_msg_hdr *clcm = buf; 255 struct smc_clc_msg_hdr *clcm = buf;
255 struct msghdr msg = {NULL, 0}; 256 struct msghdr msg = {NULL, 0};
@@ -306,7 +307,6 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
306 memset(&msg, 0, sizeof(struct msghdr)); 307 memset(&msg, 0, sizeof(struct msghdr));
307 iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &vec, 1, datlen); 308 iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &vec, 1, datlen);
308 krflags = MSG_WAITALL; 309 krflags = MSG_WAITALL;
309 smc->clcsock->sk->sk_rcvtimeo = CLC_WAIT_TIME;
310 len = sock_recvmsg(smc->clcsock, &msg, krflags); 310 len = sock_recvmsg(smc->clcsock, &msg, krflags);
311 if (len < datlen || !smc_clc_msg_hdr_valid(clcm)) { 311 if (len < datlen || !smc_clc_msg_hdr_valid(clcm)) {
312 smc->sk.sk_err = EPROTO; 312 smc->sk.sk_err = EPROTO;
@@ -322,6 +322,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
322 } 322 }
323 323
324out: 324out:
325 smc->clcsock->sk->sk_rcvtimeo = rcvtimeo;
325 return reason_code; 326 return reason_code;
326} 327}
327 328
diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c
index fa41d9881741..ac961dfb1ea1 100644
--- a/net/smc/smc_close.c
+++ b/net/smc/smc_close.c
@@ -107,6 +107,8 @@ static void smc_close_active_abort(struct smc_sock *smc)
107 } 107 }
108 switch (sk->sk_state) { 108 switch (sk->sk_state) {
109 case SMC_INIT: 109 case SMC_INIT:
110 sk->sk_state = SMC_PEERABORTWAIT;
111 break;
110 case SMC_ACTIVE: 112 case SMC_ACTIVE:
111 sk->sk_state = SMC_PEERABORTWAIT; 113 sk->sk_state = SMC_PEERABORTWAIT;
112 release_sock(sk); 114 release_sock(sk);
diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c
index a171c168f98e..72e1a2782fe8 100644
--- a/net/smc/smc_tx.c
+++ b/net/smc/smc_tx.c
@@ -494,7 +494,8 @@ out:
494 494
495void smc_tx_consumer_update(struct smc_connection *conn, bool force) 495void smc_tx_consumer_update(struct smc_connection *conn, bool force)
496{ 496{
497 union smc_host_cursor cfed, cons; 497 union smc_host_cursor cfed, cons, prod;
498 int sender_free = conn->rmb_desc->len;
498 int to_confirm; 499 int to_confirm;
499 500
500 smc_curs_write(&cons, 501 smc_curs_write(&cons,
@@ -504,11 +505,18 @@ void smc_tx_consumer_update(struct smc_connection *conn, bool force)
504 smc_curs_read(&conn->rx_curs_confirmed, conn), 505 smc_curs_read(&conn->rx_curs_confirmed, conn),
505 conn); 506 conn);
506 to_confirm = smc_curs_diff(conn->rmb_desc->len, &cfed, &cons); 507 to_confirm = smc_curs_diff(conn->rmb_desc->len, &cfed, &cons);
508 if (to_confirm > conn->rmbe_update_limit) {
509 smc_curs_write(&prod,
510 smc_curs_read(&conn->local_rx_ctrl.prod, conn),
511 conn);
512 sender_free = conn->rmb_desc->len -
513 smc_curs_diff(conn->rmb_desc->len, &prod, &cfed);
514 }
507 515
508 if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req || 516 if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req ||
509 force || 517 force ||
510 ((to_confirm > conn->rmbe_update_limit) && 518 ((to_confirm > conn->rmbe_update_limit) &&
511 ((to_confirm > (conn->rmb_desc->len / 2)) || 519 ((sender_free <= (conn->rmb_desc->len / 2)) ||
512 conn->local_rx_ctrl.prod_flags.write_blocked))) { 520 conn->local_rx_ctrl.prod_flags.write_blocked))) {
513 if ((smc_cdc_get_slot_and_msg_send(conn) < 0) && 521 if ((smc_cdc_get_slot_and_msg_send(conn) < 0) &&
514 conn->alert_token_local) { /* connection healthy */ 522 conn->alert_token_local) { /* connection healthy */