162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright(c) 2016 Intel Corporation.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/slab.h>
762306a36Sopenharmony_ci#include "pd.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/**
1062306a36Sopenharmony_ci * rvt_alloc_pd - allocate a protection domain
1162306a36Sopenharmony_ci * @ibpd: PD
1262306a36Sopenharmony_ci * @udata: optional user data
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * Allocate and keep track of a PD.
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * Return: 0 on success
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ciint rvt_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	struct ib_device *ibdev = ibpd->device;
2162306a36Sopenharmony_ci	struct rvt_dev_info *dev = ib_to_rvt(ibdev);
2262306a36Sopenharmony_ci	struct rvt_pd *pd = ibpd_to_rvtpd(ibpd);
2362306a36Sopenharmony_ci	int ret = 0;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	/*
2662306a36Sopenharmony_ci	 * While we could continue allocating protecetion domains, being
2762306a36Sopenharmony_ci	 * constrained only by system resources. The IBTA spec defines that
2862306a36Sopenharmony_ci	 * there is a max_pd limit that can be set and we need to check for
2962306a36Sopenharmony_ci	 * that.
3062306a36Sopenharmony_ci	 */
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	spin_lock(&dev->n_pds_lock);
3362306a36Sopenharmony_ci	if (dev->n_pds_allocated == dev->dparms.props.max_pd) {
3462306a36Sopenharmony_ci		spin_unlock(&dev->n_pds_lock);
3562306a36Sopenharmony_ci		ret = -ENOMEM;
3662306a36Sopenharmony_ci		goto bail;
3762306a36Sopenharmony_ci	}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	dev->n_pds_allocated++;
4062306a36Sopenharmony_ci	spin_unlock(&dev->n_pds_lock);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	/* ib_alloc_pd() will initialize pd->ibpd. */
4362306a36Sopenharmony_ci	pd->user = !!udata;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cibail:
4662306a36Sopenharmony_ci	return ret;
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/**
5062306a36Sopenharmony_ci * rvt_dealloc_pd - Free PD
5162306a36Sopenharmony_ci * @ibpd: Free up PD
5262306a36Sopenharmony_ci * @udata: Valid user data or NULL for kernel object
5362306a36Sopenharmony_ci *
5462306a36Sopenharmony_ci * Return: always 0
5562306a36Sopenharmony_ci */
5662306a36Sopenharmony_ciint rvt_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	struct rvt_dev_info *dev = ib_to_rvt(ibpd->device);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	spin_lock(&dev->n_pds_lock);
6162306a36Sopenharmony_ci	dev->n_pds_allocated--;
6262306a36Sopenharmony_ci	spin_unlock(&dev->n_pds_lock);
6362306a36Sopenharmony_ci	return 0;
6462306a36Sopenharmony_ci}
65