} ____cacheline_aligned_in_smp;
        struct completion       tx_ref_comp;
 
-       struct smc_wr_buf       *wr_rx_bufs;    /* WR recv payload buffers */
+       u8                      *wr_rx_bufs;    /* WR recv payload buffers */
        struct ib_recv_wr       *wr_rx_ibs;     /* WR recv meta data */
        struct ib_sge           *wr_rx_sges;    /* WR recv scatter meta data */
        /* above three vectors have wr_rx_cnt elements and use the same index */
+       int                     wr_rx_sge_cnt; /* rx sge, V1 is 1, V2 is either 2 or 1 */
+       int                     wr_rx_buflen;   /* buffer len for the first sge, len for the
+                                                * second sge is lgr shared if rx sge is 2.
+                                                */
        dma_addr_t              wr_rx_dma_addr; /* DMA address of wr_rx_bufs */
        dma_addr_t              wr_rx_v2_dma_addr; /* DMA address of v2 rx buf*/
        u64                     wr_rx_id;       /* seq # of last recv WR */
        return lnk->state == SMC_LNK_ACTIVE;
 }
 
+static inline bool smc_link_shared_v2_rxbuf(struct smc_link *lnk)
+{
+       return lnk->wr_rx_sge_cnt > 1;
+}
+
 static inline void smc_gid_be16_convert(__u8 *buf, u8 *gid_raw)
 {
        sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
 
 }
 
 static void smc_llc_save_add_link_rkeys(struct smc_link *link,
-                                       struct smc_link *link_new)
+                                       struct smc_link *link_new,
+                                       u8 *llc_msg)
 {
        struct smc_llc_msg_add_link_v2_ext *ext;
        struct smc_link_group *lgr = link->lgr;
        int max, i;
 
-       ext = (struct smc_llc_msg_add_link_v2_ext *)((u8 *)lgr->wr_rx_buf_v2 +
+       ext = (struct smc_llc_msg_add_link_v2_ext *)(llc_msg +
                                                     SMC_WR_TX_SIZE);
        max = min_t(u8, ext->num_rkeys, SMC_LLC_RKEYS_PER_MSG_V2);
        down_write(&lgr->rmbs_lock);
        if (rc)
                goto out_clear_lnk;
        if (lgr->smc_version == SMC_V2) {
-               smc_llc_save_add_link_rkeys(link, lnk_new);
+               u8 *llc_msg = smc_link_shared_v2_rxbuf(link) ?
+                       (u8 *)lgr->wr_rx_buf_v2 : (u8 *)llc;
+               smc_llc_save_add_link_rkeys(link, lnk_new, llc_msg);
        } else {
                rc = smc_llc_cli_rkey_exchange(link, lnk_new);
                if (rc) {
        if (rc)
                goto out_err;
        if (lgr->smc_version == SMC_V2) {
-               smc_llc_save_add_link_rkeys(link, link_new);
+               u8 *llc_msg = smc_link_shared_v2_rxbuf(link) ?
+                       (u8 *)lgr->wr_rx_buf_v2 : (u8 *)add_llc;
+               smc_llc_save_add_link_rkeys(link, link_new, llc_msg);
        } else {
                rc = smc_llc_srv_rkey_exchange(link, link_new);
                if (rc)
        if (lgr->smc_version == SMC_V2) {
                struct smc_llc_msg_delete_rkey_v2 *llcv2;
 
-               memcpy(lgr->wr_rx_buf_v2, llc, sizeof(*llc));
-               llcv2 = (struct smc_llc_msg_delete_rkey_v2 *)lgr->wr_rx_buf_v2;
+               if (smc_link_shared_v2_rxbuf(link)) {
+                       memcpy(lgr->wr_rx_buf_v2, llc, sizeof(*llc));
+                       llcv2 = (struct smc_llc_msg_delete_rkey_v2 *)lgr->wr_rx_buf_v2;
+               } else {
+                       llcv2 = (struct smc_llc_msg_delete_rkey_v2 *)llc;
+               }
                llcv2->num_inval_rkeys = 0;
 
                max = min_t(u8, llcv2->num_rkeys, SMC_LLC_RKEYS_PER_MSG_V2);
 
                return; /* short message */
        temp_wr_id = wc->wr_id;
        index = do_div(temp_wr_id, link->wr_rx_cnt);
-       wr_rx = (struct smc_wr_rx_hdr *)&link->wr_rx_bufs[index];
+       wr_rx = (struct smc_wr_rx_hdr *)(link->wr_rx_bufs + index * link->wr_rx_buflen);
        hash_for_each_possible(smc_wr_rx_hash, handler, list, wr_rx->type) {
                if (handler->type == wr_rx->type)
                        handler->handler(wc, wr_rx);
 
 static void smc_wr_init_sge(struct smc_link *lnk)
 {
-       int sges_per_buf = (lnk->lgr->smc_version == SMC_V2) ? 2 : 1;
        bool send_inline = (lnk->qp_attr.cap.max_inline_data > SMC_WR_TX_SIZE);
        u32 i;
 
         * the larger spillover buffer, allowing easy data mapping.
         */
        for (i = 0; i < lnk->wr_rx_cnt; i++) {
-               int x = i * sges_per_buf;
+               int x = i * lnk->wr_rx_sge_cnt;
 
                lnk->wr_rx_sges[x].addr =
-                       lnk->wr_rx_dma_addr + i * SMC_WR_BUF_SIZE;
-               lnk->wr_rx_sges[x].length = SMC_WR_TX_SIZE;
+                       lnk->wr_rx_dma_addr + i * lnk->wr_rx_buflen;
+               lnk->wr_rx_sges[x].length = smc_link_shared_v2_rxbuf(lnk) ?
+                       SMC_WR_TX_SIZE : lnk->wr_rx_buflen;
                lnk->wr_rx_sges[x].lkey = lnk->roce_pd->local_dma_lkey;
-               if (lnk->lgr->smc_version == SMC_V2) {
+               if (lnk->lgr->smc_version == SMC_V2 && smc_link_shared_v2_rxbuf(lnk)) {
                        lnk->wr_rx_sges[x + 1].addr =
                                        lnk->wr_rx_v2_dma_addr + SMC_WR_TX_SIZE;
                        lnk->wr_rx_sges[x + 1].length =
                }
                lnk->wr_rx_ibs[i].next = NULL;
                lnk->wr_rx_ibs[i].sg_list = &lnk->wr_rx_sges[x];
-               lnk->wr_rx_ibs[i].num_sge = sges_per_buf;
+               lnk->wr_rx_ibs[i].num_sge = lnk->wr_rx_sge_cnt;
        }
        lnk->wr_reg.wr.next = NULL;
        lnk->wr_reg.wr.num_sge = 0;
 
        if (lnk->wr_rx_dma_addr) {
                ib_dma_unmap_single(ibdev, lnk->wr_rx_dma_addr,
-                                   SMC_WR_BUF_SIZE * lnk->wr_rx_cnt,
+                                   lnk->wr_rx_buflen * lnk->wr_rx_cnt,
                                    DMA_FROM_DEVICE);
                lnk->wr_rx_dma_addr = 0;
        }
 
 int smc_wr_alloc_link_mem(struct smc_link *link)
 {
-       int sges_per_buf = link->lgr->smc_version == SMC_V2 ? 2 : 1;
-
        /* allocate link related memory */
        link->wr_tx_bufs = kcalloc(SMC_WR_BUF_CNT, SMC_WR_BUF_SIZE, GFP_KERNEL);
        if (!link->wr_tx_bufs)
                goto no_mem;
-       link->wr_rx_bufs = kcalloc(SMC_WR_BUF_CNT * 3, SMC_WR_BUF_SIZE,
+       link->wr_rx_bufs = kcalloc(SMC_WR_BUF_CNT * 3, link->wr_rx_buflen,
                                   GFP_KERNEL);
        if (!link->wr_rx_bufs)
                goto no_mem_wr_tx_bufs;
        if (!link->wr_tx_sges)
                goto no_mem_wr_tx_rdma_sges;
        link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3,
-                                  sizeof(link->wr_rx_sges[0]) * sges_per_buf,
+                                  sizeof(link->wr_rx_sges[0]) * link->wr_rx_sge_cnt,
                                   GFP_KERNEL);
        if (!link->wr_rx_sges)
                goto no_mem_wr_tx_sges;
        smc_wr_tx_set_wr_id(&lnk->wr_tx_id, 0);
        lnk->wr_rx_id = 0;
        lnk->wr_rx_dma_addr = ib_dma_map_single(
-               ibdev, lnk->wr_rx_bufs, SMC_WR_BUF_SIZE * lnk->wr_rx_cnt,
+               ibdev, lnk->wr_rx_bufs, lnk->wr_rx_buflen * lnk->wr_rx_cnt,
                DMA_FROM_DEVICE);
        if (ib_dma_mapping_error(ibdev, lnk->wr_rx_dma_addr)) {
                lnk->wr_rx_dma_addr = 0;
                goto out;
        }
        if (lnk->lgr->smc_version == SMC_V2) {
-               lnk->wr_rx_v2_dma_addr = ib_dma_map_single(ibdev,
-                       lnk->lgr->wr_rx_buf_v2, SMC_WR_BUF_V2_SIZE,
-                       DMA_FROM_DEVICE);
-               if (ib_dma_mapping_error(ibdev, lnk->wr_rx_v2_dma_addr)) {
-                       lnk->wr_rx_v2_dma_addr = 0;
-                       rc = -EIO;
-                       goto dma_unmap;
+               if (smc_link_shared_v2_rxbuf(lnk)) {
+                       lnk->wr_rx_v2_dma_addr =
+                               ib_dma_map_single(ibdev, lnk->lgr->wr_rx_buf_v2,
+                                                 SMC_WR_BUF_V2_SIZE, DMA_FROM_DEVICE);
+                       if (ib_dma_mapping_error(ibdev, lnk->wr_rx_v2_dma_addr)) {
+                               lnk->wr_rx_v2_dma_addr = 0;
+                               rc = -EIO;
+                               goto dma_unmap;
+                       }
                }
                lnk->wr_tx_v2_dma_addr = ib_dma_map_single(ibdev,
                        lnk->lgr->wr_tx_buf_v2, SMC_WR_BUF_V2_SIZE,
                lnk->wr_tx_v2_dma_addr = 0;
        }
        ib_dma_unmap_single(ibdev, lnk->wr_rx_dma_addr,
-                           SMC_WR_BUF_SIZE * lnk->wr_rx_cnt,
+                           lnk->wr_rx_buflen * lnk->wr_rx_cnt,
                            DMA_FROM_DEVICE);
        lnk->wr_rx_dma_addr = 0;
 out: