| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * Copyright (c) 2022, Microsoft Corporation. All rights reserved. |
| */ |
| |
| #include "mana_ib.h" |
| |
| struct ib_wq *mana_ib_create_wq(struct ib_pd *pd, |
| struct ib_wq_init_attr *init_attr, |
| struct ib_udata *udata) |
| { |
| struct mana_ib_dev *mdev = |
| container_of(pd->device, struct mana_ib_dev, ib_dev); |
| struct mana_ib_create_wq ucmd = {}; |
| struct mana_ib_wq *wq; |
| struct ib_umem *umem; |
| int err; |
| |
| if (udata->inlen < sizeof(ucmd)) |
| return ERR_PTR(-EINVAL); |
| |
| err = ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen)); |
| if (err) { |
| ibdev_dbg(&mdev->ib_dev, |
| "Failed to copy from udata for create wq, %d\n", err); |
| return ERR_PTR(err); |
| } |
| |
| wq = kzalloc(sizeof(*wq), GFP_KERNEL); |
| if (!wq) |
| return ERR_PTR(-ENOMEM); |
| |
| ibdev_dbg(&mdev->ib_dev, "ucmd wq_buf_addr 0x%llx\n", ucmd.wq_buf_addr); |
| |
| umem = ib_umem_get(pd->device, ucmd.wq_buf_addr, ucmd.wq_buf_size, |
| IB_ACCESS_LOCAL_WRITE); |
| if (IS_ERR(umem)) { |
| err = PTR_ERR(umem); |
| ibdev_dbg(&mdev->ib_dev, |
| "Failed to get umem for create wq, err %d\n", err); |
| goto err_free_wq; |
| } |
| |
| wq->umem = umem; |
| wq->wqe = init_attr->max_wr; |
| wq->wq_buf_size = ucmd.wq_buf_size; |
| wq->rx_object = INVALID_MANA_HANDLE; |
| |
| err = mana_ib_gd_create_dma_region(mdev, wq->umem, &wq->gdma_region); |
| if (err) { |
| ibdev_dbg(&mdev->ib_dev, |
| "Failed to create dma region for create wq, %d\n", |
| err); |
| goto err_release_umem; |
| } |
| |
| ibdev_dbg(&mdev->ib_dev, |
| "mana_ib_gd_create_dma_region ret %d gdma_region 0x%llx\n", |
| err, wq->gdma_region); |
| |
| /* WQ ID is returned at wq_create time, doesn't know the value yet */ |
| |
| return &wq->ibwq; |
| |
| err_release_umem: |
| ib_umem_release(umem); |
| |
| err_free_wq: |
| kfree(wq); |
| |
| return ERR_PTR(err); |
| } |
| |
| int mana_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr, |
| u32 wq_attr_mask, struct ib_udata *udata) |
| { |
| /* modify_wq is not supported by this version of the driver */ |
| return -EOPNOTSUPP; |
| } |
| |
| int mana_ib_destroy_wq(struct ib_wq *ibwq, struct ib_udata *udata) |
| { |
| struct mana_ib_wq *wq = container_of(ibwq, struct mana_ib_wq, ibwq); |
| struct ib_device *ib_dev = ibwq->device; |
| struct mana_ib_dev *mdev; |
| |
| mdev = container_of(ib_dev, struct mana_ib_dev, ib_dev); |
| |
| mana_ib_gd_destroy_dma_region(mdev, wq->gdma_region); |
| ib_umem_release(wq->umem); |
| |
| kfree(wq); |
| |
| return 0; |
| } |
| |
| int mana_ib_create_rwq_ind_table(struct ib_rwq_ind_table *ib_rwq_ind_table, |
| struct ib_rwq_ind_table_init_attr *init_attr, |
| struct ib_udata *udata) |
| { |
| /* |
| * There is no additional data in ind_table to be maintained by this |
| * driver, do nothing |
| */ |
| return 0; |
| } |
| |
| int mana_ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *ib_rwq_ind_tbl) |
| { |
| /* |
| * There is no additional data in ind_table to be maintained by this |
| * driver, do nothing |
| */ |
| return 0; |
| } |