Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/mthca/mthca_provider.c
Show All 31 Lines | |||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
* SOFTWARE. | * SOFTWARE. | ||||
*/ | */ | ||||
#include <rdma/ib_smi.h> | #include <rdma/ib_smi.h> | ||||
#include <rdma/ib_umem.h> | #include <rdma/ib_umem.h> | ||||
#include <rdma/ib_user_verbs.h> | #include <rdma/ib_user_verbs.h> | ||||
#include <rdma/uverbs_ioctl.h> | |||||
#include <linux/sched.h> | #include <linux/sched.h> | ||||
#include <linux/slab.h> | #include <linux/slab.h> | ||||
#include <linux/mm.h> | #include <linux/mm.h> | ||||
#include <linux/fs.h> | #include <linux/fs.h> | ||||
#include "mthca_dev.h" | #include "mthca_dev.h" | ||||
#include "mthca_cmd.h" | #include "mthca_cmd.h" | ||||
▲ Show 20 Lines • Show All 245 Lines • ▼ Show 20 Lines | static int mthca_query_gid(struct ib_device *ibdev, u8 port, | ||||
memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); | memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); | ||||
out: | out: | ||||
kfree(in_mad); | kfree(in_mad); | ||||
kfree(out_mad); | kfree(out_mad); | ||||
return err; | return err; | ||||
} | } | ||||
static struct ib_ucontext *mthca_alloc_ucontext(struct ib_device *ibdev, | static int mthca_alloc_ucontext(struct ib_ucontext *uctx, | ||||
struct ib_udata *udata) | struct ib_udata *udata) | ||||
{ | { | ||||
struct mthca_alloc_ucontext_resp uresp; | struct ib_device *ibdev = uctx->device; | ||||
struct mthca_ucontext *context; | struct mthca_alloc_ucontext_resp uresp = {}; | ||||
struct mthca_ucontext *context = to_mucontext(uctx); | |||||
int err; | int err; | ||||
if (!(to_mdev(ibdev)->active)) | if (!(to_mdev(ibdev)->active)) | ||||
return ERR_PTR(-EAGAIN); | return -EAGAIN; | ||||
memset(&uresp, 0, sizeof uresp); | |||||
uresp.qp_tab_size = to_mdev(ibdev)->limits.num_qps; | uresp.qp_tab_size = to_mdev(ibdev)->limits.num_qps; | ||||
if (mthca_is_memfree(to_mdev(ibdev))) | if (mthca_is_memfree(to_mdev(ibdev))) | ||||
uresp.uarc_size = to_mdev(ibdev)->uar_table.uarc_size; | uresp.uarc_size = to_mdev(ibdev)->uar_table.uarc_size; | ||||
else | else | ||||
uresp.uarc_size = 0; | uresp.uarc_size = 0; | ||||
context = kmalloc(sizeof *context, GFP_KERNEL); | |||||
if (!context) | |||||
return ERR_PTR(-ENOMEM); | |||||
err = mthca_uar_alloc(to_mdev(ibdev), &context->uar); | err = mthca_uar_alloc(to_mdev(ibdev), &context->uar); | ||||
if (err) { | if (err) | ||||
kfree(context); | return err; | ||||
return ERR_PTR(err); | |||||
} | |||||
context->db_tab = mthca_init_user_db_tab(to_mdev(ibdev)); | context->db_tab = mthca_init_user_db_tab(to_mdev(ibdev)); | ||||
if (IS_ERR(context->db_tab)) { | if (IS_ERR(context->db_tab)) { | ||||
err = PTR_ERR(context->db_tab); | err = PTR_ERR(context->db_tab); | ||||
mthca_uar_free(to_mdev(ibdev), &context->uar); | mthca_uar_free(to_mdev(ibdev), &context->uar); | ||||
kfree(context); | return err; | ||||
return ERR_PTR(err); | |||||
} | } | ||||
if (ib_copy_to_udata(udata, &uresp, sizeof uresp)) { | if (ib_copy_to_udata(udata, &uresp, sizeof(uresp))) { | ||||
mthca_cleanup_user_db_tab(to_mdev(ibdev), &context->uar, context->db_tab); | mthca_cleanup_user_db_tab(to_mdev(ibdev), &context->uar, context->db_tab); | ||||
mthca_uar_free(to_mdev(ibdev), &context->uar); | mthca_uar_free(to_mdev(ibdev), &context->uar); | ||||
kfree(context); | return -EFAULT; | ||||
return ERR_PTR(-EFAULT); | |||||
} | } | ||||
context->reg_mr_warned = 0; | context->reg_mr_warned = 0; | ||||
return &context->ibucontext; | return 0; | ||||
} | } | ||||
static int mthca_dealloc_ucontext(struct ib_ucontext *context) | static void mthca_dealloc_ucontext(struct ib_ucontext *context) | ||||
{ | { | ||||
mthca_cleanup_user_db_tab(to_mdev(context->device), &to_mucontext(context)->uar, | mthca_cleanup_user_db_tab(to_mdev(context->device), &to_mucontext(context)->uar, | ||||
to_mucontext(context)->db_tab); | to_mucontext(context)->db_tab); | ||||
mthca_uar_free(to_mdev(context->device), &to_mucontext(context)->uar); | mthca_uar_free(to_mdev(context->device), &to_mucontext(context)->uar); | ||||
kfree(to_mucontext(context)); | |||||
return 0; | |||||
} | } | ||||
static int mthca_mmap_uar(struct ib_ucontext *context, | static int mthca_mmap_uar(struct ib_ucontext *context, | ||||
struct vm_area_struct *vma) | struct vm_area_struct *vma) | ||||
{ | { | ||||
if (vma->vm_end - vma->vm_start != PAGE_SIZE) | if (vma->vm_end - vma->vm_start != PAGE_SIZE) | ||||
return -EINVAL; | return -EINVAL; | ||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||||
if (io_remap_pfn_range(vma, vma->vm_start, | if (io_remap_pfn_range(vma, vma->vm_start, | ||||
to_mucontext(context)->uar.pfn, | to_mucontext(context)->uar.pfn, | ||||
PAGE_SIZE, vma->vm_page_prot)) | PAGE_SIZE, vma->vm_page_prot)) | ||||
return -EAGAIN; | return -EAGAIN; | ||||
return 0; | return 0; | ||||
} | } | ||||
static struct ib_pd *mthca_alloc_pd(struct ib_device *ibdev, | static int mthca_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) | ||||
struct ib_ucontext *context, | |||||
struct ib_udata *udata) | |||||
{ | { | ||||
struct mthca_pd *pd; | struct ib_device *ibdev = ibpd->device; | ||||
struct mthca_pd *pd = to_mpd(ibpd); | |||||
int err; | int err; | ||||
pd = kmalloc(sizeof *pd, GFP_KERNEL); | err = mthca_pd_alloc(to_mdev(ibdev), !udata, pd); | ||||
if (!pd) | if (err) | ||||
return ERR_PTR(-ENOMEM); | return err; | ||||
err = mthca_pd_alloc(to_mdev(ibdev), !context, pd); | if (udata) { | ||||
if (err) { | |||||
kfree(pd); | |||||
return ERR_PTR(err); | |||||
} | |||||
if (context) { | |||||
if (ib_copy_to_udata(udata, &pd->pd_num, sizeof (__u32))) { | if (ib_copy_to_udata(udata, &pd->pd_num, sizeof (__u32))) { | ||||
mthca_pd_free(to_mdev(ibdev), pd); | mthca_pd_free(to_mdev(ibdev), pd); | ||||
kfree(pd); | return -EFAULT; | ||||
return ERR_PTR(-EFAULT); | |||||
} | } | ||||
} | } | ||||
return &pd->ibpd; | return 0; | ||||
} | } | ||||
static int mthca_dealloc_pd(struct ib_pd *pd) | static void mthca_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata) | ||||
{ | { | ||||
mthca_pd_free(to_mdev(pd->device), to_mpd(pd)); | mthca_pd_free(to_mdev(pd->device), to_mpd(pd)); | ||||
kfree(pd); | |||||
return 0; | |||||
} | } | ||||
static struct ib_ah *mthca_ah_create(struct ib_pd *pd, | static int mthca_ah_create(struct ib_ah *ibah, | ||||
struct ib_ah_attr *ah_attr, | struct ib_ah_attr *init_attr, u32 flags, | ||||
struct ib_udata *udata) | struct ib_udata *udata) | ||||
{ | { | ||||
int err; | struct mthca_ah *ah = to_mah(ibah); | ||||
struct mthca_ah *ah; | |||||
ah = kmalloc(sizeof *ah, GFP_ATOMIC); | return mthca_create_ah(to_mdev(ibah->device), to_mpd(ibah->pd), | ||||
if (!ah) | init_attr, ah); | ||||
return ERR_PTR(-ENOMEM); | |||||
err = mthca_create_ah(to_mdev(pd->device), to_mpd(pd), ah_attr, ah); | |||||
if (err) { | |||||
kfree(ah); | |||||
return ERR_PTR(err); | |||||
} | } | ||||
return &ah->ibah; | static void mthca_ah_destroy(struct ib_ah *ah, u32 flags) | ||||
} | |||||
static int mthca_ah_destroy(struct ib_ah *ah) | |||||
{ | { | ||||
mthca_destroy_ah(to_mdev(ah->device), to_mah(ah)); | mthca_destroy_ah(to_mdev(ah->device), to_mah(ah)); | ||||
kfree(ah); | |||||
return 0; | |||||
} | } | ||||
static struct ib_srq *mthca_create_srq(struct ib_pd *pd, | static int mthca_create_srq(struct ib_srq *ibsrq, | ||||
struct ib_srq_init_attr *init_attr, | struct ib_srq_init_attr *init_attr, | ||||
struct ib_udata *udata) | struct ib_udata *udata) | ||||
{ | { | ||||
struct mthca_create_srq ucmd; | struct mthca_create_srq ucmd; | ||||
struct mthca_ucontext *context = NULL; | struct mthca_ucontext *context = rdma_udata_to_drv_context( | ||||
struct mthca_srq *srq; | udata, struct mthca_ucontext, ibucontext); | ||||
struct mthca_srq *srq = to_msrq(ibsrq); | |||||
int err; | int err; | ||||
if (init_attr->srq_type != IB_SRQT_BASIC) | if (init_attr->srq_type != IB_SRQT_BASIC) | ||||
return ERR_PTR(-ENOSYS); | return -EOPNOTSUPP; | ||||
srq = kmalloc(sizeof *srq, GFP_KERNEL); | if (udata) { | ||||
if (!srq) | if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) | ||||
return ERR_PTR(-ENOMEM); | return -EFAULT; | ||||
if (pd->uobject) { | err = mthca_map_user_db(to_mdev(ibsrq->device), &context->uar, | ||||
context = to_mucontext(pd->uobject->context); | |||||
if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { | |||||
err = -EFAULT; | |||||
goto err_free; | |||||
} | |||||
err = mthca_map_user_db(to_mdev(pd->device), &context->uar, | |||||
context->db_tab, ucmd.db_index, | context->db_tab, ucmd.db_index, | ||||
ucmd.db_page); | ucmd.db_page); | ||||
if (err) | if (err) | ||||
goto err_free; | return err; | ||||
srq->mr.ibmr.lkey = ucmd.lkey; | srq->mr.ibmr.lkey = ucmd.lkey; | ||||
srq->db_index = ucmd.db_index; | srq->db_index = ucmd.db_index; | ||||
} | } | ||||
err = mthca_alloc_srq(to_mdev(pd->device), to_mpd(pd), | err = mthca_alloc_srq(to_mdev(ibsrq->device), to_mpd(ibsrq->pd), | ||||
&init_attr->attr, srq); | &init_attr->attr, srq, udata); | ||||
if (err && pd->uobject) | if (err && udata) | ||||
mthca_unmap_user_db(to_mdev(pd->device), &context->uar, | mthca_unmap_user_db(to_mdev(ibsrq->device), &context->uar, | ||||
context->db_tab, ucmd.db_index); | context->db_tab, ucmd.db_index); | ||||
if (err) | if (err) | ||||
goto err_free; | return err; | ||||
if (context && ib_copy_to_udata(udata, &srq->srqn, sizeof (__u32))) { | if (context && ib_copy_to_udata(udata, &srq->srqn, sizeof(__u32))) { | ||||
mthca_free_srq(to_mdev(pd->device), srq); | mthca_free_srq(to_mdev(ibsrq->device), srq); | ||||
err = -EFAULT; | return -EFAULT; | ||||
goto err_free; | |||||
} | } | ||||
return &srq->ibsrq; | return 0; | ||||
err_free: | |||||
kfree(srq); | |||||
return ERR_PTR(err); | |||||
} | } | ||||
static int mthca_destroy_srq(struct ib_srq *srq) | static void mthca_destroy_srq(struct ib_srq *srq, struct ib_udata *udata) | ||||
{ | { | ||||
struct mthca_ucontext *context; | if (udata) { | ||||
struct mthca_ucontext *context = | |||||
rdma_udata_to_drv_context( | |||||
udata, | |||||
struct mthca_ucontext, | |||||
ibucontext); | |||||
if (srq->uobject) { | |||||
context = to_mucontext(srq->uobject->context); | |||||
mthca_unmap_user_db(to_mdev(srq->device), &context->uar, | mthca_unmap_user_db(to_mdev(srq->device), &context->uar, | ||||
context->db_tab, to_msrq(srq)->db_index); | context->db_tab, to_msrq(srq)->db_index); | ||||
} | } | ||||
mthca_free_srq(to_mdev(srq->device), to_msrq(srq)); | mthca_free_srq(to_mdev(srq->device), to_msrq(srq)); | ||||
kfree(srq); | |||||
return 0; | |||||
} | } | ||||
static struct ib_qp *mthca_create_qp(struct ib_pd *pd, | static struct ib_qp *mthca_create_qp(struct ib_pd *pd, | ||||
struct ib_qp_init_attr *init_attr, | struct ib_qp_init_attr *init_attr, | ||||
struct ib_udata *udata) | struct ib_udata *udata) | ||||
{ | { | ||||
struct mthca_ucontext *context = rdma_udata_to_drv_context( | |||||
udata, struct mthca_ucontext, ibucontext); | |||||
struct mthca_create_qp ucmd; | struct mthca_create_qp ucmd; | ||||
struct mthca_qp *qp; | struct mthca_qp *qp; | ||||
int err; | int err; | ||||
if (init_attr->create_flags) | if (init_attr->create_flags) | ||||
return ERR_PTR(-EINVAL); | return ERR_PTR(-EINVAL); | ||||
switch (init_attr->qp_type) { | switch (init_attr->qp_type) { | ||||
case IB_QPT_RC: | case IB_QPT_RC: | ||||
case IB_QPT_UC: | case IB_QPT_UC: | ||||
case IB_QPT_UD: | case IB_QPT_UD: | ||||
{ | { | ||||
struct mthca_ucontext *context; | qp = kzalloc(sizeof(*qp), GFP_KERNEL); | ||||
qp = kmalloc(sizeof *qp, GFP_KERNEL); | |||||
if (!qp) | if (!qp) | ||||
return ERR_PTR(-ENOMEM); | return ERR_PTR(-ENOMEM); | ||||
if (pd->uobject) { | if (udata) { | ||||
context = to_mucontext(pd->uobject->context); | |||||
if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { | ||||
kfree(qp); | kfree(qp); | ||||
return ERR_PTR(-EFAULT); | return ERR_PTR(-EFAULT); | ||||
} | } | ||||
err = mthca_map_user_db(to_mdev(pd->device), &context->uar, | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, | ||||
context->db_tab, | context->db_tab, | ||||
ucmd.sq_db_index, ucmd.sq_db_page); | ucmd.sq_db_index, ucmd.sq_db_page); | ||||
Show All 18 Lines | if (udata) { | ||||
qp->sq.db_index = ucmd.sq_db_index; | qp->sq.db_index = ucmd.sq_db_index; | ||||
qp->rq.db_index = ucmd.rq_db_index; | qp->rq.db_index = ucmd.rq_db_index; | ||||
} | } | ||||
err = mthca_alloc_qp(to_mdev(pd->device), to_mpd(pd), | err = mthca_alloc_qp(to_mdev(pd->device), to_mpd(pd), | ||||
to_mcq(init_attr->send_cq), | to_mcq(init_attr->send_cq), | ||||
to_mcq(init_attr->recv_cq), | to_mcq(init_attr->recv_cq), | ||||
init_attr->qp_type, init_attr->sq_sig_type, | init_attr->qp_type, init_attr->sq_sig_type, | ||||
&init_attr->cap, qp); | &init_attr->cap, qp, udata); | ||||
if (err && pd->uobject) { | if (err && udata) { | ||||
context = to_mucontext(pd->uobject->context); | |||||
mthca_unmap_user_db(to_mdev(pd->device), | mthca_unmap_user_db(to_mdev(pd->device), | ||||
&context->uar, | &context->uar, | ||||
context->db_tab, | context->db_tab, | ||||
ucmd.sq_db_index); | ucmd.sq_db_index); | ||||
mthca_unmap_user_db(to_mdev(pd->device), | mthca_unmap_user_db(to_mdev(pd->device), | ||||
&context->uar, | &context->uar, | ||||
context->db_tab, | context->db_tab, | ||||
ucmd.rq_db_index); | ucmd.rq_db_index); | ||||
} | } | ||||
qp->ibqp.qp_num = qp->qpn; | qp->ibqp.qp_num = qp->qpn; | ||||
break; | break; | ||||
} | } | ||||
case IB_QPT_SMI: | case IB_QPT_SMI: | ||||
case IB_QPT_GSI: | case IB_QPT_GSI: | ||||
{ | { | ||||
/* Don't allow userspace to create special QPs */ | qp = kzalloc(sizeof(*qp), GFP_KERNEL); | ||||
if (pd->uobject) | |||||
return ERR_PTR(-EINVAL); | |||||
qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL); | |||||
if (!qp) | if (!qp) | ||||
return ERR_PTR(-ENOMEM); | return ERR_PTR(-ENOMEM); | ||||
qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1; | qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1; | ||||
err = mthca_alloc_sqp(to_mdev(pd->device), to_mpd(pd), | err = mthca_alloc_sqp(to_mdev(pd->device), to_mpd(pd), | ||||
to_mcq(init_attr->send_cq), | to_mcq(init_attr->send_cq), | ||||
to_mcq(init_attr->recv_cq), | to_mcq(init_attr->recv_cq), | ||||
init_attr->sq_sig_type, &init_attr->cap, | init_attr->sq_sig_type, &init_attr->cap, | ||||
qp->ibqp.qp_num, init_attr->port_num, | qp->ibqp.qp_num, init_attr->port_num, | ||||
to_msqp(qp)); | to_msqp(qp), udata); | ||||
break; | break; | ||||
} | } | ||||
default: | default: | ||||
/* Don't support raw QPs */ | /* Don't support raw QPs */ | ||||
return ERR_PTR(-ENOSYS); | return ERR_PTR(-ENOSYS); | ||||
} | } | ||||
if (err) { | if (err) { | ||||
kfree(qp); | kfree(qp); | ||||
return ERR_PTR(err); | return ERR_PTR(err); | ||||
} | } | ||||
init_attr->cap.max_send_wr = qp->sq.max; | init_attr->cap.max_send_wr = qp->sq.max; | ||||
init_attr->cap.max_recv_wr = qp->rq.max; | init_attr->cap.max_recv_wr = qp->rq.max; | ||||
init_attr->cap.max_send_sge = qp->sq.max_gs; | init_attr->cap.max_send_sge = qp->sq.max_gs; | ||||
init_attr->cap.max_recv_sge = qp->rq.max_gs; | init_attr->cap.max_recv_sge = qp->rq.max_gs; | ||||
init_attr->cap.max_inline_data = qp->max_inline_data; | init_attr->cap.max_inline_data = qp->max_inline_data; | ||||
return &qp->ibqp; | return &qp->ibqp; | ||||
} | } | ||||
static int mthca_destroy_qp(struct ib_qp *qp) | static int mthca_destroy_qp(struct ib_qp *qp, struct ib_udata *udata) | ||||
{ | { | ||||
if (qp->uobject) { | if (udata) { | ||||
struct mthca_ucontext *context = | |||||
rdma_udata_to_drv_context( | |||||
udata, | |||||
struct mthca_ucontext, | |||||
ibucontext); | |||||
mthca_unmap_user_db(to_mdev(qp->device), | mthca_unmap_user_db(to_mdev(qp->device), | ||||
&to_mucontext(qp->uobject->context)->uar, | &context->uar, | ||||
to_mucontext(qp->uobject->context)->db_tab, | context->db_tab, | ||||
to_mqp(qp)->sq.db_index); | to_mqp(qp)->sq.db_index); | ||||
mthca_unmap_user_db(to_mdev(qp->device), | mthca_unmap_user_db(to_mdev(qp->device), | ||||
&to_mucontext(qp->uobject->context)->uar, | &context->uar, | ||||
to_mucontext(qp->uobject->context)->db_tab, | context->db_tab, | ||||
to_mqp(qp)->rq.db_index); | to_mqp(qp)->rq.db_index); | ||||
} | } | ||||
mthca_free_qp(to_mdev(qp->device), to_mqp(qp)); | mthca_free_qp(to_mdev(qp->device), to_mqp(qp)); | ||||
kfree(qp); | kfree(to_mqp(qp)); | ||||
return 0; | return 0; | ||||
} | } | ||||
static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, | static int mthca_create_cq(struct ib_cq *ibcq, | ||||
const struct ib_cq_init_attr *attr, | const struct ib_cq_init_attr *attr, | ||||
struct ib_ucontext *context, | |||||
struct ib_udata *udata) | struct ib_udata *udata) | ||||
{ | { | ||||
struct ib_device *ibdev = ibcq->device; | |||||
int entries = attr->cqe; | int entries = attr->cqe; | ||||
struct mthca_create_cq ucmd; | struct mthca_create_cq ucmd; | ||||
struct mthca_cq *cq; | struct mthca_cq *cq; | ||||
int nent; | int nent; | ||||
int err; | int err; | ||||
struct mthca_ucontext *context = rdma_udata_to_drv_context( | |||||
udata, struct mthca_ucontext, ibucontext); | |||||
if (attr->flags) | if (attr->flags) | ||||
return ERR_PTR(-EINVAL); | return -EOPNOTSUPP; | ||||
if (entries < 1 || entries > to_mdev(ibdev)->limits.max_cqes) | if (entries < 1 || entries > to_mdev(ibdev)->limits.max_cqes) | ||||
return ERR_PTR(-EINVAL); | return -EINVAL; | ||||
if (context) { | if (udata) { | ||||
if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) | if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) | ||||
return ERR_PTR(-EFAULT); | return -EFAULT; | ||||
err = mthca_map_user_db(to_mdev(ibdev), &to_mucontext(context)->uar, | err = mthca_map_user_db(to_mdev(ibdev), &context->uar, | ||||
to_mucontext(context)->db_tab, | context->db_tab, ucmd.set_db_index, | ||||
ucmd.set_db_index, ucmd.set_db_page); | ucmd.set_db_page); | ||||
if (err) | if (err) | ||||
return ERR_PTR(err); | return err; | ||||
err = mthca_map_user_db(to_mdev(ibdev), &to_mucontext(context)->uar, | err = mthca_map_user_db(to_mdev(ibdev), &context->uar, | ||||
to_mucontext(context)->db_tab, | context->db_tab, ucmd.arm_db_index, | ||||
ucmd.arm_db_index, ucmd.arm_db_page); | ucmd.arm_db_page); | ||||
if (err) | if (err) | ||||
goto err_unmap_set; | goto err_unmap_set; | ||||
} | } | ||||
cq = kmalloc(sizeof *cq, GFP_KERNEL); | cq = to_mcq(ibcq); | ||||
if (!cq) { | |||||
err = -ENOMEM; | |||||
goto err_unmap_arm; | |||||
} | |||||
if (context) { | if (udata) { | ||||
cq->buf.mr.ibmr.lkey = ucmd.lkey; | cq->buf.mr.ibmr.lkey = ucmd.lkey; | ||||
cq->set_ci_db_index = ucmd.set_db_index; | cq->set_ci_db_index = ucmd.set_db_index; | ||||
cq->arm_db_index = ucmd.arm_db_index; | cq->arm_db_index = ucmd.arm_db_index; | ||||
} | } | ||||
for (nent = 1; nent <= entries; nent <<= 1) | for (nent = 1; nent <= entries; nent <<= 1) | ||||
; /* nothing */ | ; /* nothing */ | ||||
err = mthca_init_cq(to_mdev(ibdev), nent, | err = mthca_init_cq(to_mdev(ibdev), nent, context, | ||||
context ? to_mucontext(context) : NULL, | udata ? ucmd.pdn : to_mdev(ibdev)->driver_pd.pd_num, | ||||
context ? ucmd.pdn : to_mdev(ibdev)->driver_pd.pd_num, | |||||
cq); | cq); | ||||
if (err) | if (err) | ||||
goto err_free; | goto err_unmap_arm; | ||||
if (context && ib_copy_to_udata(udata, &cq->cqn, sizeof (__u32))) { | if (udata && ib_copy_to_udata(udata, &cq->cqn, sizeof(__u32))) { | ||||
mthca_free_cq(to_mdev(ibdev), cq); | mthca_free_cq(to_mdev(ibdev), cq); | ||||
err = -EFAULT; | err = -EFAULT; | ||||
goto err_free; | goto err_unmap_arm; | ||||
} | } | ||||
cq->resize_buf = NULL; | cq->resize_buf = NULL; | ||||
return &cq->ibcq; | return 0; | ||||
err_free: | |||||
kfree(cq); | |||||
err_unmap_arm: | err_unmap_arm: | ||||
if (context) | if (udata) | ||||
mthca_unmap_user_db(to_mdev(ibdev), &to_mucontext(context)->uar, | mthca_unmap_user_db(to_mdev(ibdev), &context->uar, | ||||
to_mucontext(context)->db_tab, ucmd.arm_db_index); | context->db_tab, ucmd.arm_db_index); | ||||
err_unmap_set: | err_unmap_set: | ||||
if (context) | if (udata) | ||||
mthca_unmap_user_db(to_mdev(ibdev), &to_mucontext(context)->uar, | mthca_unmap_user_db(to_mdev(ibdev), &context->uar, | ||||
to_mucontext(context)->db_tab, ucmd.set_db_index); | context->db_tab, ucmd.set_db_index); | ||||
return ERR_PTR(err); | return err; | ||||
} | } | ||||
static int mthca_alloc_resize_buf(struct mthca_dev *dev, struct mthca_cq *cq, | static int mthca_alloc_resize_buf(struct mthca_dev *dev, struct mthca_cq *cq, | ||||
int entries) | int entries) | ||||
{ | { | ||||
int ret; | int ret; | ||||
spin_lock_irq(&cq->lock); | spin_lock_irq(&cq->lock); | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | if (cq->is_kernel) { | ||||
ibcq->cqe = entries - 1; | ibcq->cqe = entries - 1; | ||||
out: | out: | ||||
mutex_unlock(&cq->mutex); | mutex_unlock(&cq->mutex); | ||||
return ret; | return ret; | ||||
} | } | ||||
static int mthca_destroy_cq(struct ib_cq *cq) | static void mthca_destroy_cq(struct ib_cq *cq, struct ib_udata *udata) | ||||
{ | { | ||||
if (cq->uobject) { | if (udata) { | ||||
struct mthca_ucontext *context = | |||||
rdma_udata_to_drv_context( | |||||
udata, | |||||
struct mthca_ucontext, | |||||
ibucontext); | |||||
mthca_unmap_user_db(to_mdev(cq->device), | mthca_unmap_user_db(to_mdev(cq->device), | ||||
&to_mucontext(cq->uobject->context)->uar, | &context->uar, | ||||
to_mucontext(cq->uobject->context)->db_tab, | context->db_tab, | ||||
to_mcq(cq)->arm_db_index); | to_mcq(cq)->arm_db_index); | ||||
mthca_unmap_user_db(to_mdev(cq->device), | mthca_unmap_user_db(to_mdev(cq->device), | ||||
&to_mucontext(cq->uobject->context)->uar, | &context->uar, | ||||
to_mucontext(cq->uobject->context)->db_tab, | context->db_tab, | ||||
to_mcq(cq)->set_ci_db_index); | to_mcq(cq)->set_ci_db_index); | ||||
} | } | ||||
mthca_free_cq(to_mdev(cq->device), to_mcq(cq)); | mthca_free_cq(to_mdev(cq->device), to_mcq(cq)); | ||||
kfree(cq); | |||||
return 0; | |||||
} | } | ||||
static inline u32 convert_access(int acc) | static inline u32 convert_access(int acc) | ||||
{ | { | ||||
return (acc & IB_ACCESS_REMOTE_ATOMIC ? MTHCA_MPT_FLAG_ATOMIC : 0) | | return (acc & IB_ACCESS_REMOTE_ATOMIC ? MTHCA_MPT_FLAG_ATOMIC : 0) | | ||||
(acc & IB_ACCESS_REMOTE_WRITE ? MTHCA_MPT_FLAG_REMOTE_WRITE : 0) | | (acc & IB_ACCESS_REMOTE_WRITE ? MTHCA_MPT_FLAG_REMOTE_WRITE : 0) | | ||||
(acc & IB_ACCESS_REMOTE_READ ? MTHCA_MPT_FLAG_REMOTE_READ : 0) | | (acc & IB_ACCESS_REMOTE_READ ? MTHCA_MPT_FLAG_REMOTE_READ : 0) | | ||||
(acc & IB_ACCESS_LOCAL_WRITE ? MTHCA_MPT_FLAG_LOCAL_WRITE : 0) | | (acc & IB_ACCESS_LOCAL_WRITE ? MTHCA_MPT_FLAG_LOCAL_WRITE : 0) | | ||||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | |||||
err_umem: | err_umem: | ||||
ib_umem_release(mr->umem); | ib_umem_release(mr->umem); | ||||
err: | err: | ||||
kfree(mr); | kfree(mr); | ||||
return ERR_PTR(err); | return ERR_PTR(err); | ||||
} | } | ||||
static int mthca_dereg_mr(struct ib_mr *mr) | static int mthca_dereg_mr(struct ib_mr *mr, struct ib_udata *udata) | ||||
{ | { | ||||
struct mthca_mr *mmr = to_mmr(mr); | struct mthca_mr *mmr = to_mmr(mr); | ||||
mthca_free_mr(to_mdev(mr->device), mmr); | mthca_free_mr(to_mdev(mr->device), mmr); | ||||
if (mmr->umem) | |||||
ib_umem_release(mmr->umem); | ib_umem_release(mmr->umem); | ||||
kfree(mmr); | kfree(mmr); | ||||
return 0; | return 0; | ||||
} | } | ||||
static struct ib_fmr *mthca_alloc_fmr(struct ib_pd *pd, int mr_access_flags, | static struct ib_fmr *mthca_alloc_fmr(struct ib_pd *pd, int mr_access_flags, | ||||
struct ib_fmr_attr *fmr_attr) | struct ib_fmr_attr *fmr_attr) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
int ret; | int ret; | ||||
int i; | int i; | ||||
ret = mthca_init_node_data(dev); | ret = mthca_init_node_data(dev); | ||||
if (ret) | if (ret) | ||||
return ret; | return ret; | ||||
#define mthca_ib_ah mthca_ah | |||||
#define mthca_ib_cq mthca_cq | |||||
#define mthca_ib_pd mthca_pd | |||||
#define mthca_ib_qp mthca_qp | |||||
#define mthca_ib_srq mthca_srq | |||||
#define mthca_ib_ucontext mthca_ucontext | |||||
INIT_IB_DEVICE_OPS(&dev->ib_dev.ops, mthca, MTHCA); | |||||
strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX); | strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX); | ||||
dev->ib_dev.owner = THIS_MODULE; | dev->ib_dev.owner = THIS_MODULE; | ||||
dev->ib_dev.uverbs_abi_ver = MTHCA_UVERBS_ABI_VERSION; | dev->ib_dev.uverbs_abi_ver = MTHCA_UVERBS_ABI_VERSION; | ||||
dev->ib_dev.uverbs_cmd_mask = | dev->ib_dev.uverbs_cmd_mask = | ||||
(1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | | (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | | ||||
(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | | (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | | ||||
(1ull << IB_USER_VERBS_CMD_QUERY_PORT) | | (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | | ||||
▲ Show 20 Lines • Show All 113 Lines • Show Last 20 Lines |