}
 
        smc_conn_save_peer_info(smc, aclc);
+
+       if (smc_ism_support_dmb_nocopy(smc->conn.lgr->smcd)) {
+               rc = smcd_buf_attach(smc);
+               if (rc) {
+                       rc = SMC_CLC_DECL_MEM;  /* try to fallback */
+                       goto connect_abort;
+               }
+       }
        smc_close_init(smc);
        smc_rx_init(smc);
        smc_tx_init(smc);
                mutex_unlock(&smc_server_lgr_pending);
        }
        smc_conn_save_peer_info(new_smc, cclc);
+
+       if (ini->is_smcd &&
+           smc_ism_support_dmb_nocopy(new_smc->conn.lgr->smcd)) {
+               rc = smcd_buf_attach(new_smc);
+               if (rc)
+                       goto out_decl;
+       }
+
        smc_listen_out_connected(new_smc);
        SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk), ini);
        goto out_free;
 
        }
 }
 
+static void smcd_buf_detach(struct smc_connection *conn)
+{
+       struct smcd_dev *smcd = conn->lgr->smcd;
+       u64 peer_token = conn->peer_token;
+
+       if (!conn->sndbuf_desc)
+               return;
+
+       smc_ism_detach_dmb(smcd, peer_token);
+
+       kfree(conn->sndbuf_desc);
+       conn->sndbuf_desc = NULL;
+}
+
 static void smc_buf_unuse(struct smc_connection *conn,
                          struct smc_link_group *lgr)
 {
        if (lgr->is_smcd) {
                if (!list_empty(&lgr->list))
                        smc_ism_unset_conn(conn);
+               if (smc_ism_support_dmb_nocopy(lgr->smcd))
+                       smcd_buf_detach(conn);
                tasklet_kill(&conn->rx_tsklet);
        } else {
                smc_cdc_wait_pend_tx_wr(conn);
        smc_sk_wake_ups(smc);
        if (conn->lgr->is_smcd) {
                smc_ism_unset_conn(conn);
+               if (smc_ism_support_dmb_nocopy(conn->lgr->smcd))
+                       smcd_buf_detach(conn);
                if (soft)
                        tasklet_kill(&conn->rx_tsklet);
                else
        int rc;
 
        /* create send buffer */
+       if (is_smcd &&
+           smc_ism_support_dmb_nocopy(smc->conn.lgr->smcd))
+               goto create_rmb;
+
        rc = __smc_buf_create(smc, is_smcd, false);
        if (rc)
                return rc;
+
+create_rmb:
        /* create rmb */
        rc = __smc_buf_create(smc, is_smcd, true);
-       if (rc) {
+       if (rc && smc->conn.sndbuf_desc) {
                down_write(&smc->conn.lgr->sndbufs_lock);
                list_del(&smc->conn.sndbuf_desc->list);
                up_write(&smc->conn.lgr->sndbufs_lock);
        return rc;
 }
 
+int smcd_buf_attach(struct smc_sock *smc)
+{
+       struct smc_connection *conn = &smc->conn;
+       struct smcd_dev *smcd = conn->lgr->smcd;
+       u64 peer_token = conn->peer_token;
+       struct smc_buf_desc *buf_desc;
+       int rc;
+
+       buf_desc = kzalloc(sizeof(*buf_desc), GFP_KERNEL);
+       if (!buf_desc)
+               return -ENOMEM;
+
+       /* The ghost sndbuf_desc describes the same memory region as
+        * peer RMB. Its lifecycle is consistent with the connection's
+        * and it will be freed with the connections instead of the
+        * link group.
+        */
+       rc = smc_ism_attach_dmb(smcd, peer_token, buf_desc);
+       if (rc)
+               goto free;
+
+       smc->sk.sk_sndbuf = buf_desc->len;
+       buf_desc->cpu_addr =
+               (u8 *)buf_desc->cpu_addr + sizeof(struct smcd_cdc_msg);
+       buf_desc->len -= sizeof(struct smcd_cdc_msg);
+       conn->sndbuf_desc = buf_desc;
+       conn->sndbuf_desc->used = 1;
+       atomic_set(&conn->sndbuf_space, conn->sndbuf_desc->len);
+       return 0;
+
+free:
+       kfree(buf_desc);
+       return rc;
+}
+
 static inline int smc_rmb_reserve_rtoken_idx(struct smc_link_group *lgr)
 {
        int i;
 
 void smc_smcd_terminate_all(struct smcd_dev *dev);
 void smc_smcr_terminate_all(struct smc_ib_device *smcibdev);
 int smc_buf_create(struct smc_sock *smc, bool is_smcd);
+int smcd_buf_attach(struct smc_sock *smc);
 int smc_uncompress_bufsize(u8 compressed);
 int smc_rmb_rtoken_handling(struct smc_connection *conn, struct smc_link *link,
                            struct smc_clc_msg_accept_confirm *clc);