RDMA/nes: Support the new memory registration API

Support the new memory registration API by allocating a
private page list array in nes_mr and populate it when
nes_map_mr_sg is invoked. Also, support IB_WR_REG_MR
by duplicating IB_WR_FAST_REG_MR handling and take the
needed information from different places:
- page_size, iova, length (ib_mr)
- page array (nes_mr)
- key, access flags (ib_reg_wr)

The IB_WR_FAST_REG_MR handlers will be removed later when
all the ULPs will be converted.

Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
Sagi Grimberg 2015-10-13 19:11:32 +03:00 committed by Doug Ledford
parent 38071a461f
commit 0ba24dd39a
2 changed files with 120 additions and 1 deletions

View File

@ -51,6 +51,7 @@ atomic_t qps_created;
atomic_t sw_qps_destroyed; atomic_t sw_qps_destroyed;
static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev); static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev);
static int nes_dereg_mr(struct ib_mr *ib_mr);
/** /**
* nes_alloc_mw * nes_alloc_mw
@ -443,9 +444,46 @@ static struct ib_mr *nes_alloc_mr(struct ib_pd *ibpd,
} else { } else {
kfree(nesmr); kfree(nesmr);
nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); 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; 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 major_code;
u16 minor_code; u16 minor_code;
if (nesmr->pages)
pci_free_consistent(nesdev->pcidev,
nesmr->max_pages * sizeof(u64),
nesmr->pages,
nesmr->paddr);
if (nesmr->region) { if (nesmr->region) {
ib_umem_release(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); wqe_misc);
break; 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: default:
/* error */ /* error */
err = -EINVAL; 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.bind_mw = nes_bind_mw;
nesibdev->ibdev.alloc_mr = nes_alloc_mr; 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.alloc_fast_reg_page_list = nes_alloc_fast_reg_page_list;
nesibdev->ibdev.free_fast_reg_page_list = nes_free_fast_reg_page_list; nesibdev->ibdev.free_fast_reg_page_list = nes_free_fast_reg_page_list;

View File

@ -79,6 +79,10 @@ struct nes_mr {
u16 pbls_used; u16 pbls_used;
u8 mode; u8 mode;
u8 pbl_4k; u8 pbl_4k;
__le64 *pages;
dma_addr_t paddr;
u32 max_pages;
u32 npages;
}; };
struct nes_hw_pb { struct nes_hw_pb {