Blob Blame History Raw
From: Stefan Raspl <raspl@linux.ibm.com>
Subject: smc: no consumer update in tasklet context
Patch-mainline: v4.16-rc1
Git-commit: 6b5771aa3c351b118b1eee7bc98e1483eb0c8ca8
References: FATE#325694, LTC#167874, bsc#1113480

Summary:     net/smc: SMC-R MVP
Description: Add latest upstream patches to push SMC-R to the MVP level

Upstream-Description:

             smc: no consumer update in tasklet context

             The SMC protocol requires to send a separate consumer cursor update,
             if it cannot be piggybacked to updates of the producer cursor.
             When receiving a blocked signal from the sender, this update is sent
             already in tasklet context. In addition consumer cursor updates are
             sent after data receival.
             Sending of cursor updates is controlled by sequence numbers.
             Assuming receiving stray messages the receiver drops updates with older
             sequence numbers than an already received cursor update with a higher
             sequence number.
             Sending consumer cursor updates in tasklet context may result in
             wrong order sends and its corresponding drops at the receiver. Since
             it is sufficient to send consumer cursor updates once the data is
             received, this patch gets rid of the consumer cursor update in tasklet
             context to guarantee in-sequence arrival of cursor updates.

             Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com>
             Signed-off-by: David S. Miller <davem@davemloft.net>

Signed-off-by: Stefan Raspl <raspl@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 net/smc/smc_cdc.c |   12 +++---------
 net/smc/smc_tx.c  |    9 ++-------
 2 files changed, 5 insertions(+), 16 deletions(-)

--- a/net/smc/smc_cdc.c
+++ b/net/smc/smc_cdc.c
@@ -212,6 +212,9 @@ static void smc_cdc_msg_recv_action(stru
 		/* guarantee 0 <= bytes_to_rcv <= rmbe_size */
 		smp_mb__after_atomic();
 		smc->sk.sk_data_ready(&smc->sk);
+	} else if ((conn->local_rx_ctrl.prod_flags.write_blocked) ||
+		   (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req)) {
+		smc->sk.sk_data_ready(&smc->sk);
 	}
 
 	if (conn->local_rx_ctrl.conn_state_flags.peer_conn_abort) {
@@ -233,15 +236,6 @@ static void smc_cdc_msg_recv_action(stru
 		/* trigger socket release if connection closed */
 		smc_close_wake_tx_prepared(smc);
 	}
-
-	/* socket connected but not accepted */
-	if (!smc->sk.sk_socket)
-		return;
-
-	/* data available */
-	if ((conn->local_rx_ctrl.prod_flags.write_blocked) ||
-	    (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req))
-		smc_tx_consumer_update(conn);
 }
 
 /* called under tasklet context */
--- a/net/smc/smc_tx.c
+++ b/net/smc/smc_tx.c
@@ -447,9 +447,7 @@ static void smc_tx_work(struct work_stru
 void smc_tx_consumer_update(struct smc_connection *conn)
 {
 	union smc_host_cursor cfed, cons;
-	struct smc_cdc_tx_pend *pend;
-	struct smc_wr_buf *wr_buf;
-	int to_confirm, rc;
+	int to_confirm;
 
 	smc_curs_write(&cons,
 		       smc_curs_read(&conn->local_tx_ctrl.cons, conn),
@@ -463,10 +461,7 @@ void smc_tx_consumer_update(struct smc_c
 	    ((to_confirm > conn->rmbe_update_limit) &&
 	     ((to_confirm > (conn->rmbe_size / 2)) ||
 	      conn->local_rx_ctrl.prod_flags.write_blocked))) {
-		rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend);
-		if (!rc)
-			rc = smc_cdc_msg_send(conn, wr_buf, pend);
-		if (rc < 0) {
+		if (smc_cdc_get_slot_and_msg_send(conn) < 0) {
 			schedule_delayed_work(&conn->tx_work,
 					      SMC_TX_WORK_DELAY);
 			return;