|
@@ -51,6 +51,7 @@ atomic_t qps_created;
|
|
|
atomic_t sw_qps_destroyed;
|
|
|
|
|
|
static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev);
|
|
|
+static int nes_dereg_mr(struct ib_mr *ib_mr);
|
|
|
|
|
|
/**
|
|
|
* nes_alloc_mw
|
|
@@ -443,9 +444,46 @@ static struct ib_mr *nes_alloc_mr(struct ib_pd *ibpd,
|
|
|
} else {
|
|
|
kfree(nesmr);
|
|
|
nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
|
|
|
- ibmr = ERR_PTR(-ENOMEM);
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
}
|
|
|
+
|
|
|
+ nesmr->pages = pci_alloc_consistent(nesdev->pcidev,
|
|
|
+ max_num_sg * sizeof(u64),
|
|
|
+ &nesmr->paddr);
|
|
|
+ if (!nesmr->paddr)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ nesmr->max_pages = max_num_sg;
|
|
|
+
|
|
|
return ibmr;
|
|
|
+
|
|
|
+err:
|
|
|
+ nes_dereg_mr(ibmr);
|
|
|
+
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+}
|
|
|
+
|
|
|
+static int nes_set_page(struct ib_mr *ibmr, u64 addr)
|
|
|
+{
|
|
|
+ struct nes_mr *nesmr = to_nesmr(ibmr);
|
|
|
+
|
|
|
+ if (unlikely(nesmr->npages == nesmr->max_pages))
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ nesmr->pages[nesmr->npages++] = cpu_to_le64(addr);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int nes_map_mr_sg(struct ib_mr *ibmr,
|
|
|
+ struct scatterlist *sg,
|
|
|
+ int sg_nents)
|
|
|
+{
|
|
|
+ struct nes_mr *nesmr = to_nesmr(ibmr);
|
|
|
+
|
|
|
+ nesmr->npages = 0;
|
|
|
+
|
|
|
+ return ib_sg_to_pages(ibmr, sg, sg_nents, nes_set_page);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -2683,6 +2721,13 @@ static int nes_dereg_mr(struct ib_mr *ib_mr)
|
|
|
u16 major_code;
|
|
|
u16 minor_code;
|
|
|
|
|
|
+
|
|
|
+ if (nesmr->pages)
|
|
|
+ pci_free_consistent(nesdev->pcidev,
|
|
|
+ nesmr->max_pages * sizeof(u64),
|
|
|
+ nesmr->pages,
|
|
|
+ nesmr->paddr);
|
|
|
+
|
|
|
if (nesmr->region) {
|
|
|
ib_umem_release(nesmr->region);
|
|
|
}
|
|
@@ -3513,6 +3558,75 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
|
|
|
wqe_misc);
|
|
|
break;
|
|
|
}
|
|
|
+ case IB_WR_REG_MR:
|
|
|
+ {
|
|
|
+ struct nes_mr *mr = to_nesmr(reg_wr(ib_wr)->mr);
|
|
|
+ int page_shift = ilog2(reg_wr(ib_wr)->mr->page_size);
|
|
|
+ int flags = reg_wr(ib_wr)->access;
|
|
|
+
|
|
|
+ if (mr->npages > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64))) {
|
|
|
+ nes_debug(NES_DBG_IW_TX, "SQ_FMR: bad page_list_len\n");
|
|
|
+ err = -EINVAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ wqe_misc = NES_IWARP_SQ_OP_FAST_REG;
|
|
|
+ set_wqe_64bit_value(wqe->wqe_words,
|
|
|
+ NES_IWARP_SQ_FMR_WQE_VA_FBO_LOW_IDX,
|
|
|
+ mr->ibmr.iova);
|
|
|
+ set_wqe_32bit_value(wqe->wqe_words,
|
|
|
+ NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,
|
|
|
+ mr->ibmr.length);
|
|
|
+ set_wqe_32bit_value(wqe->wqe_words,
|
|
|
+ NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0);
|
|
|
+ set_wqe_32bit_value(wqe->wqe_words,
|
|
|
+ NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,
|
|
|
+ reg_wr(ib_wr)->key);
|
|
|
+
|
|
|
+ if (page_shift == 12) {
|
|
|
+ wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_4K;
|
|
|
+ } else if (page_shift == 21) {
|
|
|
+ wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_2M;
|
|
|
+ } else {
|
|
|
+ nes_debug(NES_DBG_IW_TX, "Invalid page shift,"
|
|
|
+ " ib_wr=%u, max=1\n", ib_wr->num_sge);
|
|
|
+ err = -EINVAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Set access_flags */
|
|
|
+ wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_READ;
|
|
|
+ if (flags & IB_ACCESS_LOCAL_WRITE)
|
|
|
+ wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_WRITE;
|
|
|
+
|
|
|
+ if (flags & IB_ACCESS_REMOTE_WRITE)
|
|
|
+ wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_REMOTE_WRITE;
|
|
|
+
|
|
|
+ if (flags & IB_ACCESS_REMOTE_READ)
|
|
|
+ wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_REMOTE_READ;
|
|
|
+
|
|
|
+ if (flags & IB_ACCESS_MW_BIND)
|
|
|
+ wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_WINDOW_BIND;
|
|
|
+
|
|
|
+ /* Fill in PBL info: */
|
|
|
+ set_wqe_64bit_value(wqe->wqe_words,
|
|
|
+ NES_IWARP_SQ_FMR_WQE_PBL_ADDR_LOW_IDX,
|
|
|
+ mr->paddr);
|
|
|
+
|
|
|
+ set_wqe_32bit_value(wqe->wqe_words,
|
|
|
+ NES_IWARP_SQ_FMR_WQE_PBL_LENGTH_IDX,
|
|
|
+ mr->npages * 8);
|
|
|
+
|
|
|
+ nes_debug(NES_DBG_IW_TX, "SQ_REG_MR: iova_start: %llx, "
|
|
|
+ "length: %d, rkey: %0x, pgl_paddr: %llx, "
|
|
|
+ "page_list_len: %u, wqe_misc: %x\n",
|
|
|
+ (unsigned long long) mr->ibmr.iova,
|
|
|
+ mr->ibmr.length,
|
|
|
+ reg_wr(ib_wr)->key,
|
|
|
+ (unsigned long long) mr->paddr,
|
|
|
+ mr->npages,
|
|
|
+ wqe_misc);
|
|
|
+ break;
|
|
|
+ }
|
|
|
default:
|
|
|
/* error */
|
|
|
err = -EINVAL;
|
|
@@ -3940,6 +4054,7 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
|
|
|
nesibdev->ibdev.bind_mw = nes_bind_mw;
|
|
|
|
|
|
nesibdev->ibdev.alloc_mr = nes_alloc_mr;
|
|
|
+ nesibdev->ibdev.map_mr_sg = nes_map_mr_sg;
|
|
|
nesibdev->ibdev.alloc_fast_reg_page_list = nes_alloc_fast_reg_page_list;
|
|
|
nesibdev->ibdev.free_fast_reg_page_list = nes_free_fast_reg_page_list;
|
|
|
|