RDMA/qedr: Use the common mmap API
Remove all functions related to mmap from qedr and use the common API. Link: https://lore.kernel.org/r/20191030094417.16866-7-michal.kalderon@marvell.com Signed-off-by: Ariel Elior <ariel.elior@marvell.com> Signed-off-by: Michal Kalderon <michal.kalderon@marvell.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
parent
11f1a75567
commit
4c6bb02d59
@ -212,6 +212,7 @@ static const struct ib_device_ops qedr_dev_ops = {
|
|||||||
.get_link_layer = qedr_link_layer,
|
.get_link_layer = qedr_link_layer,
|
||||||
.map_mr_sg = qedr_map_mr_sg,
|
.map_mr_sg = qedr_map_mr_sg,
|
||||||
.mmap = qedr_mmap,
|
.mmap = qedr_mmap,
|
||||||
|
.mmap_free = qedr_mmap_free,
|
||||||
.modify_port = qedr_modify_port,
|
.modify_port = qedr_modify_port,
|
||||||
.modify_qp = qedr_modify_qp,
|
.modify_qp = qedr_modify_qp,
|
||||||
.modify_srq = qedr_modify_srq,
|
.modify_srq = qedr_modify_srq,
|
||||||
|
@ -231,14 +231,10 @@ struct qedr_ucontext {
|
|||||||
struct qedr_dev *dev;
|
struct qedr_dev *dev;
|
||||||
struct qedr_pd *pd;
|
struct qedr_pd *pd;
|
||||||
void __iomem *dpi_addr;
|
void __iomem *dpi_addr;
|
||||||
|
struct rdma_user_mmap_entry *db_mmap_entry;
|
||||||
u64 dpi_phys_addr;
|
u64 dpi_phys_addr;
|
||||||
u32 dpi_size;
|
u32 dpi_size;
|
||||||
u16 dpi;
|
u16 dpi;
|
||||||
|
|
||||||
struct list_head mm_head;
|
|
||||||
|
|
||||||
/* Lock to protect mm list */
|
|
||||||
struct mutex mm_list_lock;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
union db_prod64 {
|
union db_prod64 {
|
||||||
@ -301,14 +297,6 @@ struct qedr_pd {
|
|||||||
struct qedr_ucontext *uctx;
|
struct qedr_ucontext *uctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qedr_mm {
|
|
||||||
struct {
|
|
||||||
u64 phy_addr;
|
|
||||||
unsigned long len;
|
|
||||||
} key;
|
|
||||||
struct list_head entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
union db_prod32 {
|
union db_prod32 {
|
||||||
struct rdma_pwm_val16_data data;
|
struct rdma_pwm_val16_data data;
|
||||||
u32 raw;
|
u32 raw;
|
||||||
@ -491,6 +479,15 @@ struct qedr_mr {
|
|||||||
u32 npages;
|
u32 npages;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct qedr_user_mmap_entry {
|
||||||
|
struct rdma_user_mmap_entry rdma_entry;
|
||||||
|
struct qedr_dev *dev;
|
||||||
|
u64 io_address;
|
||||||
|
size_t length;
|
||||||
|
u16 dpi;
|
||||||
|
u8 mmap_flag;
|
||||||
|
};
|
||||||
|
|
||||||
#define SET_FIELD2(value, name, flag) ((value) |= ((flag) << (name ## _SHIFT)))
|
#define SET_FIELD2(value, name, flag) ((value) |= ((flag) << (name ## _SHIFT)))
|
||||||
|
|
||||||
#define QEDR_RESP_IMM (RDMA_CQE_RESPONDER_IMM_FLG_MASK << \
|
#define QEDR_RESP_IMM (RDMA_CQE_RESPONDER_IMM_FLG_MASK << \
|
||||||
@ -589,4 +586,11 @@ static inline struct qedr_srq *get_qedr_srq(struct ib_srq *ibsrq)
|
|||||||
{
|
{
|
||||||
return container_of(ibsrq, struct qedr_srq, ibsrq);
|
return container_of(ibsrq, struct qedr_srq, ibsrq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct qedr_user_mmap_entry *
|
||||||
|
get_qedr_mmap_entry(struct rdma_user_mmap_entry *rdma_entry)
|
||||||
|
{
|
||||||
|
return container_of(rdma_entry, struct qedr_user_mmap_entry,
|
||||||
|
rdma_entry);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,6 +59,10 @@
|
|||||||
|
|
||||||
#define DB_ADDR_SHIFT(addr) ((addr) << DB_PWM_ADDR_OFFSET_SHIFT)
|
#define DB_ADDR_SHIFT(addr) ((addr) << DB_PWM_ADDR_OFFSET_SHIFT)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
QEDR_USER_MMAP_IO_WC = 0,
|
||||||
|
};
|
||||||
|
|
||||||
static inline int qedr_ib_copy_to_udata(struct ib_udata *udata, void *src,
|
static inline int qedr_ib_copy_to_udata(struct ib_udata *udata, void *src,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
@ -257,60 +261,6 @@ int qedr_modify_port(struct ib_device *ibdev, u8 port, int mask,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qedr_add_mmap(struct qedr_ucontext *uctx, u64 phy_addr,
|
|
||||||
unsigned long len)
|
|
||||||
{
|
|
||||||
struct qedr_mm *mm;
|
|
||||||
|
|
||||||
mm = kzalloc(sizeof(*mm), GFP_KERNEL);
|
|
||||||
if (!mm)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
mm->key.phy_addr = phy_addr;
|
|
||||||
/* This function might be called with a length which is not a multiple
|
|
||||||
* of PAGE_SIZE, while the mapping is PAGE_SIZE grained and the kernel
|
|
||||||
* forces this granularity by increasing the requested size if needed.
|
|
||||||
* When qedr_mmap is called, it will search the list with the updated
|
|
||||||
* length as a key. To prevent search failures, the length is rounded up
|
|
||||||
* in advance to PAGE_SIZE.
|
|
||||||
*/
|
|
||||||
mm->key.len = roundup(len, PAGE_SIZE);
|
|
||||||
INIT_LIST_HEAD(&mm->entry);
|
|
||||||
|
|
||||||
mutex_lock(&uctx->mm_list_lock);
|
|
||||||
list_add(&mm->entry, &uctx->mm_head);
|
|
||||||
mutex_unlock(&uctx->mm_list_lock);
|
|
||||||
|
|
||||||
DP_DEBUG(uctx->dev, QEDR_MSG_MISC,
|
|
||||||
"added (addr=0x%llx,len=0x%lx) for ctx=%p\n",
|
|
||||||
(unsigned long long)mm->key.phy_addr,
|
|
||||||
(unsigned long)mm->key.len, uctx);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool qedr_search_mmap(struct qedr_ucontext *uctx, u64 phy_addr,
|
|
||||||
unsigned long len)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
struct qedr_mm *mm;
|
|
||||||
|
|
||||||
mutex_lock(&uctx->mm_list_lock);
|
|
||||||
list_for_each_entry(mm, &uctx->mm_head, entry) {
|
|
||||||
if (len != mm->key.len || phy_addr != mm->key.phy_addr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mutex_unlock(&uctx->mm_list_lock);
|
|
||||||
DP_DEBUG(uctx->dev, QEDR_MSG_MISC,
|
|
||||||
"searched for (addr=0x%llx,len=0x%lx) for ctx=%p, result=%d\n",
|
|
||||||
mm->key.phy_addr, mm->key.len, uctx, found);
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
|
int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
|
||||||
{
|
{
|
||||||
struct ib_device *ibdev = uctx->device;
|
struct ib_device *ibdev = uctx->device;
|
||||||
@ -319,6 +269,7 @@ int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
|
|||||||
struct qedr_alloc_ucontext_resp uresp = {};
|
struct qedr_alloc_ucontext_resp uresp = {};
|
||||||
struct qedr_dev *dev = get_qedr_dev(ibdev);
|
struct qedr_dev *dev = get_qedr_dev(ibdev);
|
||||||
struct qed_rdma_add_user_out_params oparams;
|
struct qed_rdma_add_user_out_params oparams;
|
||||||
|
struct qedr_user_mmap_entry *entry;
|
||||||
|
|
||||||
if (!udata)
|
if (!udata)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@ -335,13 +286,29 @@ int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
|
|||||||
ctx->dpi_addr = oparams.dpi_addr;
|
ctx->dpi_addr = oparams.dpi_addr;
|
||||||
ctx->dpi_phys_addr = oparams.dpi_phys_addr;
|
ctx->dpi_phys_addr = oparams.dpi_phys_addr;
|
||||||
ctx->dpi_size = oparams.dpi_size;
|
ctx->dpi_size = oparams.dpi_size;
|
||||||
INIT_LIST_HEAD(&ctx->mm_head);
|
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
||||||
mutex_init(&ctx->mm_list_lock);
|
if (!entry) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->io_address = ctx->dpi_phys_addr;
|
||||||
|
entry->length = ctx->dpi_size;
|
||||||
|
entry->mmap_flag = QEDR_USER_MMAP_IO_WC;
|
||||||
|
entry->dpi = ctx->dpi;
|
||||||
|
entry->dev = dev;
|
||||||
|
rc = rdma_user_mmap_entry_insert(uctx, &entry->rdma_entry,
|
||||||
|
ctx->dpi_size);
|
||||||
|
if (rc) {
|
||||||
|
kfree(entry);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
ctx->db_mmap_entry = &entry->rdma_entry;
|
||||||
|
|
||||||
uresp.dpm_enabled = dev->user_dpm_enabled;
|
uresp.dpm_enabled = dev->user_dpm_enabled;
|
||||||
uresp.wids_enabled = 1;
|
uresp.wids_enabled = 1;
|
||||||
uresp.wid_count = oparams.wid_count;
|
uresp.wid_count = oparams.wid_count;
|
||||||
uresp.db_pa = ctx->dpi_phys_addr;
|
uresp.db_pa = rdma_user_mmap_get_offset(ctx->db_mmap_entry);
|
||||||
uresp.db_size = ctx->dpi_size;
|
uresp.db_size = ctx->dpi_size;
|
||||||
uresp.max_send_wr = dev->attr.max_sqe;
|
uresp.max_send_wr = dev->attr.max_sqe;
|
||||||
uresp.max_recv_wr = dev->attr.max_rqe;
|
uresp.max_recv_wr = dev->attr.max_rqe;
|
||||||
@ -353,82 +320,86 @@ int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
|
|||||||
|
|
||||||
rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp));
|
rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp));
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
goto err;
|
||||||
|
|
||||||
ctx->dev = dev;
|
ctx->dev = dev;
|
||||||
|
|
||||||
rc = qedr_add_mmap(ctx, ctx->dpi_phys_addr, ctx->dpi_size);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
DP_DEBUG(dev, QEDR_MSG_INIT, "Allocating user context %p\n",
|
DP_DEBUG(dev, QEDR_MSG_INIT, "Allocating user context %p\n",
|
||||||
&ctx->ibucontext);
|
&ctx->ibucontext);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (!ctx->db_mmap_entry)
|
||||||
|
dev->ops->rdma_remove_user(dev->rdma_ctx, ctx->dpi);
|
||||||
|
else
|
||||||
|
rdma_user_mmap_entry_remove(ctx->db_mmap_entry);
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qedr_dealloc_ucontext(struct ib_ucontext *ibctx)
|
void qedr_dealloc_ucontext(struct ib_ucontext *ibctx)
|
||||||
{
|
{
|
||||||
struct qedr_ucontext *uctx = get_qedr_ucontext(ibctx);
|
struct qedr_ucontext *uctx = get_qedr_ucontext(ibctx);
|
||||||
struct qedr_mm *mm, *tmp;
|
|
||||||
|
|
||||||
DP_DEBUG(uctx->dev, QEDR_MSG_INIT, "Deallocating user context %p\n",
|
DP_DEBUG(uctx->dev, QEDR_MSG_INIT, "Deallocating user context %p\n",
|
||||||
uctx);
|
uctx);
|
||||||
uctx->dev->ops->rdma_remove_user(uctx->dev->rdma_ctx, uctx->dpi);
|
|
||||||
|
|
||||||
list_for_each_entry_safe(mm, tmp, &uctx->mm_head, entry) {
|
rdma_user_mmap_entry_remove(uctx->db_mmap_entry);
|
||||||
DP_DEBUG(uctx->dev, QEDR_MSG_MISC,
|
|
||||||
"deleted (addr=0x%llx,len=0x%lx) for ctx=%p\n",
|
|
||||||
mm->key.phy_addr, mm->key.len, uctx);
|
|
||||||
list_del(&mm->entry);
|
|
||||||
kfree(mm);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int qedr_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
|
void qedr_mmap_free(struct rdma_user_mmap_entry *rdma_entry)
|
||||||
{
|
{
|
||||||
struct qedr_ucontext *ucontext = get_qedr_ucontext(context);
|
struct qedr_user_mmap_entry *entry = get_qedr_mmap_entry(rdma_entry);
|
||||||
struct qedr_dev *dev = get_qedr_dev(context->device);
|
struct qedr_dev *dev = entry->dev;
|
||||||
unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT;
|
|
||||||
unsigned long len = (vma->vm_end - vma->vm_start);
|
|
||||||
unsigned long dpi_start;
|
|
||||||
|
|
||||||
dpi_start = dev->db_phys_addr + (ucontext->dpi * ucontext->dpi_size);
|
if (entry->mmap_flag == QEDR_USER_MMAP_IO_WC)
|
||||||
|
dev->ops->rdma_remove_user(dev->rdma_ctx, entry->dpi);
|
||||||
|
|
||||||
DP_DEBUG(dev, QEDR_MSG_INIT,
|
kfree(entry);
|
||||||
"mmap invoked with vm_start=0x%pK, vm_end=0x%pK,vm_pgoff=0x%pK; dpi_start=0x%pK dpi_size=0x%x\n",
|
}
|
||||||
(void *)vma->vm_start, (void *)vma->vm_end,
|
|
||||||
(void *)vma->vm_pgoff, (void *)dpi_start, ucontext->dpi_size);
|
|
||||||
|
|
||||||
if ((vma->vm_start & (PAGE_SIZE - 1)) || (len & (PAGE_SIZE - 1))) {
|
int qedr_mmap(struct ib_ucontext *ucontext, struct vm_area_struct *vma)
|
||||||
DP_ERR(dev,
|
{
|
||||||
"failed mmap, addresses must be page aligned: start=0x%pK, end=0x%pK\n",
|
struct ib_device *dev = ucontext->device;
|
||||||
(void *)vma->vm_start, (void *)vma->vm_end);
|
size_t length = vma->vm_end - vma->vm_start;
|
||||||
|
struct rdma_user_mmap_entry *rdma_entry;
|
||||||
|
struct qedr_user_mmap_entry *entry;
|
||||||
|
int rc = 0;
|
||||||
|
u64 pfn;
|
||||||
|
|
||||||
|
ibdev_dbg(dev,
|
||||||
|
"start %#lx, end %#lx, length = %#zx, pgoff = %#lx\n",
|
||||||
|
vma->vm_start, vma->vm_end, length, vma->vm_pgoff);
|
||||||
|
|
||||||
|
rdma_entry = rdma_user_mmap_entry_get(ucontext, vma);
|
||||||
|
if (!rdma_entry) {
|
||||||
|
ibdev_dbg(dev, "pgoff[%#lx] does not have valid entry\n",
|
||||||
|
vma->vm_pgoff);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
entry = get_qedr_mmap_entry(rdma_entry);
|
||||||
|
ibdev_dbg(dev,
|
||||||
|
"Mapping address[%#llx], length[%#zx], mmap_flag[%d]\n",
|
||||||
|
entry->io_address, length, entry->mmap_flag);
|
||||||
|
|
||||||
if (!qedr_search_mmap(ucontext, phys_addr, len)) {
|
switch (entry->mmap_flag) {
|
||||||
DP_ERR(dev, "failed mmap, vm_pgoff=0x%lx is not authorized\n",
|
case QEDR_USER_MMAP_IO_WC:
|
||||||
vma->vm_pgoff);
|
pfn = entry->io_address >> PAGE_SHIFT;
|
||||||
return -EINVAL;
|
rc = rdma_user_mmap_io(ucontext, vma, pfn, length,
|
||||||
|
pgprot_writecombine(vma->vm_page_prot),
|
||||||
|
rdma_entry);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phys_addr < dpi_start ||
|
if (rc)
|
||||||
((phys_addr + len) > (dpi_start + ucontext->dpi_size))) {
|
ibdev_dbg(dev,
|
||||||
DP_ERR(dev,
|
"Couldn't mmap address[%#llx] length[%#zx] mmap_flag[%d] err[%d]\n",
|
||||||
"failed mmap, pages are outside of dpi; page address=0x%pK, dpi_start=0x%pK, dpi_size=0x%x\n",
|
entry->io_address, length, entry->mmap_flag, rc);
|
||||||
(void *)phys_addr, (void *)dpi_start,
|
|
||||||
ucontext->dpi_size);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vma->vm_flags & VM_READ) {
|
rdma_user_mmap_entry_put(rdma_entry);
|
||||||
DP_ERR(dev, "failed mmap, cannot map doorbell bar for read\n");
|
return rc;
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
|
||||||
return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, len,
|
|
||||||
vma->vm_page_prot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int qedr_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
|
int qedr_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
|
||||||
|
@ -46,7 +46,8 @@ int qedr_query_pkey(struct ib_device *, u8 port, u16 index, u16 *pkey);
|
|||||||
int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata);
|
int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata);
|
||||||
void qedr_dealloc_ucontext(struct ib_ucontext *uctx);
|
void qedr_dealloc_ucontext(struct ib_ucontext *uctx);
|
||||||
|
|
||||||
int qedr_mmap(struct ib_ucontext *, struct vm_area_struct *vma);
|
int qedr_mmap(struct ib_ucontext *ucontext, struct vm_area_struct *vma);
|
||||||
|
void qedr_mmap_free(struct rdma_user_mmap_entry *rdma_entry);
|
||||||
int qedr_alloc_pd(struct ib_pd *pd, struct ib_udata *udata);
|
int qedr_alloc_pd(struct ib_pd *pd, struct ib_udata *udata);
|
||||||
void qedr_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata);
|
void qedr_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user