162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2022, Microsoft Corporation. All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include "mana_ib.h"
762306a36Sopenharmony_ci
862306a36Sopenharmony_cistruct ib_wq *mana_ib_create_wq(struct ib_pd *pd,
962306a36Sopenharmony_ci				struct ib_wq_init_attr *init_attr,
1062306a36Sopenharmony_ci				struct ib_udata *udata)
1162306a36Sopenharmony_ci{
1262306a36Sopenharmony_ci	struct mana_ib_dev *mdev =
1362306a36Sopenharmony_ci		container_of(pd->device, struct mana_ib_dev, ib_dev);
1462306a36Sopenharmony_ci	struct mana_ib_create_wq ucmd = {};
1562306a36Sopenharmony_ci	struct mana_ib_wq *wq;
1662306a36Sopenharmony_ci	struct ib_umem *umem;
1762306a36Sopenharmony_ci	int err;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	if (udata->inlen < sizeof(ucmd))
2062306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	err = ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen));
2362306a36Sopenharmony_ci	if (err) {
2462306a36Sopenharmony_ci		ibdev_dbg(&mdev->ib_dev,
2562306a36Sopenharmony_ci			  "Failed to copy from udata for create wq, %d\n", err);
2662306a36Sopenharmony_ci		return ERR_PTR(err);
2762306a36Sopenharmony_ci	}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	wq = kzalloc(sizeof(*wq), GFP_KERNEL);
3062306a36Sopenharmony_ci	if (!wq)
3162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	ibdev_dbg(&mdev->ib_dev, "ucmd wq_buf_addr 0x%llx\n", ucmd.wq_buf_addr);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	umem = ib_umem_get(pd->device, ucmd.wq_buf_addr, ucmd.wq_buf_size,
3662306a36Sopenharmony_ci			   IB_ACCESS_LOCAL_WRITE);
3762306a36Sopenharmony_ci	if (IS_ERR(umem)) {
3862306a36Sopenharmony_ci		err = PTR_ERR(umem);
3962306a36Sopenharmony_ci		ibdev_dbg(&mdev->ib_dev,
4062306a36Sopenharmony_ci			  "Failed to get umem for create wq, err %d\n", err);
4162306a36Sopenharmony_ci		goto err_free_wq;
4262306a36Sopenharmony_ci	}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	wq->umem = umem;
4562306a36Sopenharmony_ci	wq->wqe = init_attr->max_wr;
4662306a36Sopenharmony_ci	wq->wq_buf_size = ucmd.wq_buf_size;
4762306a36Sopenharmony_ci	wq->rx_object = INVALID_MANA_HANDLE;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	err = mana_ib_gd_create_dma_region(mdev, wq->umem, &wq->gdma_region);
5062306a36Sopenharmony_ci	if (err) {
5162306a36Sopenharmony_ci		ibdev_dbg(&mdev->ib_dev,
5262306a36Sopenharmony_ci			  "Failed to create dma region for create wq, %d\n",
5362306a36Sopenharmony_ci			  err);
5462306a36Sopenharmony_ci		goto err_release_umem;
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	ibdev_dbg(&mdev->ib_dev,
5862306a36Sopenharmony_ci		  "mana_ib_gd_create_dma_region ret %d gdma_region 0x%llx\n",
5962306a36Sopenharmony_ci		  err, wq->gdma_region);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	/* WQ ID is returned at wq_create time, doesn't know the value yet */
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	return &wq->ibwq;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cierr_release_umem:
6662306a36Sopenharmony_ci	ib_umem_release(umem);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cierr_free_wq:
6962306a36Sopenharmony_ci	kfree(wq);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	return ERR_PTR(err);
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ciint mana_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
7562306a36Sopenharmony_ci		      u32 wq_attr_mask, struct ib_udata *udata)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	/* modify_wq is not supported by this version of the driver */
7862306a36Sopenharmony_ci	return -EOPNOTSUPP;
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ciint mana_ib_destroy_wq(struct ib_wq *ibwq, struct ib_udata *udata)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	struct mana_ib_wq *wq = container_of(ibwq, struct mana_ib_wq, ibwq);
8462306a36Sopenharmony_ci	struct ib_device *ib_dev = ibwq->device;
8562306a36Sopenharmony_ci	struct mana_ib_dev *mdev;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	mdev = container_of(ib_dev, struct mana_ib_dev, ib_dev);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	mana_ib_gd_destroy_dma_region(mdev, wq->gdma_region);
9062306a36Sopenharmony_ci	ib_umem_release(wq->umem);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	kfree(wq);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	return 0;
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciint mana_ib_create_rwq_ind_table(struct ib_rwq_ind_table *ib_rwq_ind_table,
9862306a36Sopenharmony_ci				 struct ib_rwq_ind_table_init_attr *init_attr,
9962306a36Sopenharmony_ci				 struct ib_udata *udata)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	/*
10262306a36Sopenharmony_ci	 * There is no additional data in ind_table to be maintained by this
10362306a36Sopenharmony_ci	 * driver, do nothing
10462306a36Sopenharmony_ci	 */
10562306a36Sopenharmony_ci	return 0;
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ciint mana_ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *ib_rwq_ind_tbl)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	/*
11162306a36Sopenharmony_ci	 * There is no additional data in ind_table to be maintained by this
11262306a36Sopenharmony_ci	 * driver, do nothing
11362306a36Sopenharmony_ci	 */
11462306a36Sopenharmony_ci	return 0;
11562306a36Sopenharmony_ci}
116