#include "smc_tx.h"
 #include "smc_rx.h"
 #include "smc_close.h"
+#include "smc_ism.h"
 
 /********************************** send *************************************/
 
                return rc;
        smc_curs_copy(&conn->rx_curs_confirmed, &curs, conn);
        conn->local_rx_ctrl.prod_flags.cons_curs_upd_req = 0;
+
+       if (smc_ism_support_dmb_nocopy(conn->lgr->smcd))
+               /* if local sndbuf shares the same memory region with
+                * peer DMB, then don't update the tx_curs_fin
+                * and sndbuf_space until peer has consumed the data.
+                */
+               return 0;
+
        /* Calculate transmitted data and increment free send buffer space */
        diff = smc_curs_diff(conn->sndbuf_desc->len, &conn->tx_curs_fin,
                             &conn->tx_curs_sent);
        smc_curs_copy(&conn->tx_curs_fin, &conn->tx_curs_sent, conn);
 
        smc_tx_sndbuf_nonfull(smc);
-       return rc;
+       return 0;
 }
 
 /********************************* receive ***********************************/
 {
        union smc_host_cursor cons_old, prod_old;
        struct smc_connection *conn = &smc->conn;
-       int diff_cons, diff_prod;
+       int diff_cons, diff_prod, diff_tx;
 
        smc_curs_copy(&prod_old, &conn->local_rx_ctrl.prod, conn);
        smc_curs_copy(&cons_old, &conn->local_rx_ctrl.cons, conn);
                atomic_add(diff_cons, &conn->peer_rmbe_space);
                /* guarantee 0 <= peer_rmbe_space <= peer_rmbe_size */
                smp_mb__after_atomic();
+
+               /* if local sndbuf shares the same memory region with
+                * peer RMB, then update tx_curs_fin and sndbuf_space
+                * here since peer has already consumed the data.
+                */
+               if (conn->lgr->is_smcd &&
+                   smc_ism_support_dmb_nocopy(conn->lgr->smcd)) {
+                       /* Calculate consumed data and
+                        * increment free send buffer space.
+                        */
+                       diff_tx = smc_curs_diff(conn->sndbuf_desc->len,
+                                               &conn->tx_curs_fin,
+                                               &conn->local_rx_ctrl.cons);
+                       /* increase local sndbuf space and fin_curs */
+                       smp_mb__before_atomic();
+                       atomic_add(diff_tx, &conn->sndbuf_space);
+                       /* guarantee 0 <= sndbuf_space <= sndbuf_desc->len */
+                       smp_mb__after_atomic();
+                       smc_curs_copy(&conn->tx_curs_fin,
+                                     &conn->local_rx_ctrl.cons, conn);
+
+                       smc_tx_sndbuf_nonfull(smc);
+               }
        }
 
        diff_prod = smc_curs_diff(conn->rmb_desc->len, &prod_old,