18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next
128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
138c2ecf20Sopenharmony_ci * Software.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
208c2ecf20Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
218c2ecf20Sopenharmony_ci * SOFTWARE.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * Authors:
248c2ecf20Sopenharmony_ci *    Kevin Tian <kevin.tian@intel.com>
258c2ecf20Sopenharmony_ci *    Dexuan Cui
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * Contributors:
288c2ecf20Sopenharmony_ci *    Pei Zhang <pei.zhang@intel.com>
298c2ecf20Sopenharmony_ci *    Min He <min.he@intel.com>
308c2ecf20Sopenharmony_ci *    Niu Bing <bing.niu@intel.com>
318c2ecf20Sopenharmony_ci *    Yulei Zhang <yulei.zhang@intel.com>
328c2ecf20Sopenharmony_ci *    Zhenyu Wang <zhenyuw@linux.intel.com>
338c2ecf20Sopenharmony_ci *    Zhi Wang <zhi.a.wang@intel.com>
348c2ecf20Sopenharmony_ci *
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#include "i915_drv.h"
388c2ecf20Sopenharmony_ci#include "gt/intel_ggtt_fencing.h"
398c2ecf20Sopenharmony_ci#include "gvt.h"
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	struct intel_gvt *gvt = vgpu->gvt;
448c2ecf20Sopenharmony_ci	struct intel_gt *gt = gvt->gt;
458c2ecf20Sopenharmony_ci	unsigned int flags;
468c2ecf20Sopenharmony_ci	u64 start, end, size;
478c2ecf20Sopenharmony_ci	struct drm_mm_node *node;
488c2ecf20Sopenharmony_ci	int ret;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	if (high_gm) {
518c2ecf20Sopenharmony_ci		node = &vgpu->gm.high_gm_node;
528c2ecf20Sopenharmony_ci		size = vgpu_hidden_sz(vgpu);
538c2ecf20Sopenharmony_ci		start = ALIGN(gvt_hidden_gmadr_base(gvt), I915_GTT_PAGE_SIZE);
548c2ecf20Sopenharmony_ci		end = ALIGN(gvt_hidden_gmadr_end(gvt), I915_GTT_PAGE_SIZE);
558c2ecf20Sopenharmony_ci		flags = PIN_HIGH;
568c2ecf20Sopenharmony_ci	} else {
578c2ecf20Sopenharmony_ci		node = &vgpu->gm.low_gm_node;
588c2ecf20Sopenharmony_ci		size = vgpu_aperture_sz(vgpu);
598c2ecf20Sopenharmony_ci		start = ALIGN(gvt_aperture_gmadr_base(gvt), I915_GTT_PAGE_SIZE);
608c2ecf20Sopenharmony_ci		end = ALIGN(gvt_aperture_gmadr_end(gvt), I915_GTT_PAGE_SIZE);
618c2ecf20Sopenharmony_ci		flags = PIN_MAPPABLE;
628c2ecf20Sopenharmony_ci	}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	mutex_lock(&gt->ggtt->vm.mutex);
658c2ecf20Sopenharmony_ci	mmio_hw_access_pre(gt);
668c2ecf20Sopenharmony_ci	ret = i915_gem_gtt_insert(&gt->ggtt->vm, node,
678c2ecf20Sopenharmony_ci				  size, I915_GTT_PAGE_SIZE,
688c2ecf20Sopenharmony_ci				  I915_COLOR_UNEVICTABLE,
698c2ecf20Sopenharmony_ci				  start, end, flags);
708c2ecf20Sopenharmony_ci	mmio_hw_access_post(gt);
718c2ecf20Sopenharmony_ci	mutex_unlock(&gt->ggtt->vm.mutex);
728c2ecf20Sopenharmony_ci	if (ret)
738c2ecf20Sopenharmony_ci		gvt_err("fail to alloc %s gm space from host\n",
748c2ecf20Sopenharmony_ci			high_gm ? "high" : "low");
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	return ret;
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic int alloc_vgpu_gm(struct intel_vgpu *vgpu)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	struct intel_gvt *gvt = vgpu->gvt;
828c2ecf20Sopenharmony_ci	struct intel_gt *gt = gvt->gt;
838c2ecf20Sopenharmony_ci	int ret;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	ret = alloc_gm(vgpu, false);
868c2ecf20Sopenharmony_ci	if (ret)
878c2ecf20Sopenharmony_ci		return ret;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	ret = alloc_gm(vgpu, true);
908c2ecf20Sopenharmony_ci	if (ret)
918c2ecf20Sopenharmony_ci		goto out_free_aperture;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	gvt_dbg_core("vgpu%d: alloc low GM start %llx size %llx\n", vgpu->id,
948c2ecf20Sopenharmony_ci		     vgpu_aperture_offset(vgpu), vgpu_aperture_sz(vgpu));
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	gvt_dbg_core("vgpu%d: alloc high GM start %llx size %llx\n", vgpu->id,
978c2ecf20Sopenharmony_ci		     vgpu_hidden_offset(vgpu), vgpu_hidden_sz(vgpu));
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	return 0;
1008c2ecf20Sopenharmony_ciout_free_aperture:
1018c2ecf20Sopenharmony_ci	mutex_lock(&gt->ggtt->vm.mutex);
1028c2ecf20Sopenharmony_ci	drm_mm_remove_node(&vgpu->gm.low_gm_node);
1038c2ecf20Sopenharmony_ci	mutex_unlock(&gt->ggtt->vm.mutex);
1048c2ecf20Sopenharmony_ci	return ret;
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic void free_vgpu_gm(struct intel_vgpu *vgpu)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	struct intel_gvt *gvt = vgpu->gvt;
1108c2ecf20Sopenharmony_ci	struct intel_gt *gt = gvt->gt;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	mutex_lock(&gt->ggtt->vm.mutex);
1138c2ecf20Sopenharmony_ci	drm_mm_remove_node(&vgpu->gm.low_gm_node);
1148c2ecf20Sopenharmony_ci	drm_mm_remove_node(&vgpu->gm.high_gm_node);
1158c2ecf20Sopenharmony_ci	mutex_unlock(&gt->ggtt->vm.mutex);
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci/**
1198c2ecf20Sopenharmony_ci * intel_vgpu_write_fence - write fence registers owned by a vGPU
1208c2ecf20Sopenharmony_ci * @vgpu: vGPU instance
1218c2ecf20Sopenharmony_ci * @fence: vGPU fence register number
1228c2ecf20Sopenharmony_ci * @value: Fence register value to be written
1238c2ecf20Sopenharmony_ci *
1248c2ecf20Sopenharmony_ci * This function is used to write fence registers owned by a vGPU. The vGPU
1258c2ecf20Sopenharmony_ci * fence register number will be translated into HW fence register number.
1268c2ecf20Sopenharmony_ci *
1278c2ecf20Sopenharmony_ci */
1288c2ecf20Sopenharmony_civoid intel_vgpu_write_fence(struct intel_vgpu *vgpu,
1298c2ecf20Sopenharmony_ci		u32 fence, u64 value)
1308c2ecf20Sopenharmony_ci{
1318c2ecf20Sopenharmony_ci	struct intel_gvt *gvt = vgpu->gvt;
1328c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = gvt->gt->i915;
1338c2ecf20Sopenharmony_ci	struct intel_uncore *uncore = gvt->gt->uncore;
1348c2ecf20Sopenharmony_ci	struct i915_fence_reg *reg;
1358c2ecf20Sopenharmony_ci	i915_reg_t fence_reg_lo, fence_reg_hi;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	assert_rpm_wakelock_held(uncore->rpm);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	if (drm_WARN_ON(&i915->drm, fence >= vgpu_fence_sz(vgpu)))
1408c2ecf20Sopenharmony_ci		return;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	reg = vgpu->fence.regs[fence];
1438c2ecf20Sopenharmony_ci	if (drm_WARN_ON(&i915->drm, !reg))
1448c2ecf20Sopenharmony_ci		return;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	fence_reg_lo = FENCE_REG_GEN6_LO(reg->id);
1478c2ecf20Sopenharmony_ci	fence_reg_hi = FENCE_REG_GEN6_HI(reg->id);
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	intel_uncore_write(uncore, fence_reg_lo, 0);
1508c2ecf20Sopenharmony_ci	intel_uncore_posting_read(uncore, fence_reg_lo);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	intel_uncore_write(uncore, fence_reg_hi, upper_32_bits(value));
1538c2ecf20Sopenharmony_ci	intel_uncore_write(uncore, fence_reg_lo, lower_32_bits(value));
1548c2ecf20Sopenharmony_ci	intel_uncore_posting_read(uncore, fence_reg_lo);
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistatic void _clear_vgpu_fence(struct intel_vgpu *vgpu)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	int i;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	for (i = 0; i < vgpu_fence_sz(vgpu); i++)
1628c2ecf20Sopenharmony_ci		intel_vgpu_write_fence(vgpu, i, 0);
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic void free_vgpu_fence(struct intel_vgpu *vgpu)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	struct intel_gvt *gvt = vgpu->gvt;
1688c2ecf20Sopenharmony_ci	struct intel_uncore *uncore = gvt->gt->uncore;
1698c2ecf20Sopenharmony_ci	struct i915_fence_reg *reg;
1708c2ecf20Sopenharmony_ci	intel_wakeref_t wakeref;
1718c2ecf20Sopenharmony_ci	u32 i;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	if (drm_WARN_ON(&gvt->gt->i915->drm, !vgpu_fence_sz(vgpu)))
1748c2ecf20Sopenharmony_ci		return;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	wakeref = intel_runtime_pm_get(uncore->rpm);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	mutex_lock(&gvt->gt->ggtt->vm.mutex);
1798c2ecf20Sopenharmony_ci	_clear_vgpu_fence(vgpu);
1808c2ecf20Sopenharmony_ci	for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
1818c2ecf20Sopenharmony_ci		reg = vgpu->fence.regs[i];
1828c2ecf20Sopenharmony_ci		i915_unreserve_fence(reg);
1838c2ecf20Sopenharmony_ci		vgpu->fence.regs[i] = NULL;
1848c2ecf20Sopenharmony_ci	}
1858c2ecf20Sopenharmony_ci	mutex_unlock(&gvt->gt->ggtt->vm.mutex);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	intel_runtime_pm_put(uncore->rpm, wakeref);
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic int alloc_vgpu_fence(struct intel_vgpu *vgpu)
1918c2ecf20Sopenharmony_ci{
1928c2ecf20Sopenharmony_ci	struct intel_gvt *gvt = vgpu->gvt;
1938c2ecf20Sopenharmony_ci	struct intel_uncore *uncore = gvt->gt->uncore;
1948c2ecf20Sopenharmony_ci	struct i915_fence_reg *reg;
1958c2ecf20Sopenharmony_ci	intel_wakeref_t wakeref;
1968c2ecf20Sopenharmony_ci	int i;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	wakeref = intel_runtime_pm_get(uncore->rpm);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	/* Request fences from host */
2018c2ecf20Sopenharmony_ci	mutex_lock(&gvt->gt->ggtt->vm.mutex);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
2048c2ecf20Sopenharmony_ci		reg = i915_reserve_fence(gvt->gt->ggtt);
2058c2ecf20Sopenharmony_ci		if (IS_ERR(reg))
2068c2ecf20Sopenharmony_ci			goto out_free_fence;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci		vgpu->fence.regs[i] = reg;
2098c2ecf20Sopenharmony_ci	}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	_clear_vgpu_fence(vgpu);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	mutex_unlock(&gvt->gt->ggtt->vm.mutex);
2148c2ecf20Sopenharmony_ci	intel_runtime_pm_put(uncore->rpm, wakeref);
2158c2ecf20Sopenharmony_ci	return 0;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ciout_free_fence:
2188c2ecf20Sopenharmony_ci	gvt_vgpu_err("Failed to alloc fences\n");
2198c2ecf20Sopenharmony_ci	/* Return fences to host, if fail */
2208c2ecf20Sopenharmony_ci	for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
2218c2ecf20Sopenharmony_ci		reg = vgpu->fence.regs[i];
2228c2ecf20Sopenharmony_ci		if (!reg)
2238c2ecf20Sopenharmony_ci			continue;
2248c2ecf20Sopenharmony_ci		i915_unreserve_fence(reg);
2258c2ecf20Sopenharmony_ci		vgpu->fence.regs[i] = NULL;
2268c2ecf20Sopenharmony_ci	}
2278c2ecf20Sopenharmony_ci	mutex_unlock(&gvt->gt->ggtt->vm.mutex);
2288c2ecf20Sopenharmony_ci	intel_runtime_pm_put_unchecked(uncore->rpm);
2298c2ecf20Sopenharmony_ci	return -ENOSPC;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic void free_resource(struct intel_vgpu *vgpu)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	struct intel_gvt *gvt = vgpu->gvt;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	gvt->gm.vgpu_allocated_low_gm_size -= vgpu_aperture_sz(vgpu);
2378c2ecf20Sopenharmony_ci	gvt->gm.vgpu_allocated_high_gm_size -= vgpu_hidden_sz(vgpu);
2388c2ecf20Sopenharmony_ci	gvt->fence.vgpu_allocated_fence_num -= vgpu_fence_sz(vgpu);
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_cistatic int alloc_resource(struct intel_vgpu *vgpu,
2428c2ecf20Sopenharmony_ci		struct intel_vgpu_creation_params *param)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	struct intel_gvt *gvt = vgpu->gvt;
2458c2ecf20Sopenharmony_ci	unsigned long request, avail, max, taken;
2468c2ecf20Sopenharmony_ci	const char *item;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	if (!param->low_gm_sz || !param->high_gm_sz || !param->fence_sz) {
2498c2ecf20Sopenharmony_ci		gvt_vgpu_err("Invalid vGPU creation params\n");
2508c2ecf20Sopenharmony_ci		return -EINVAL;
2518c2ecf20Sopenharmony_ci	}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	item = "low GM space";
2548c2ecf20Sopenharmony_ci	max = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE;
2558c2ecf20Sopenharmony_ci	taken = gvt->gm.vgpu_allocated_low_gm_size;
2568c2ecf20Sopenharmony_ci	avail = max - taken;
2578c2ecf20Sopenharmony_ci	request = MB_TO_BYTES(param->low_gm_sz);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	if (request > avail)
2608c2ecf20Sopenharmony_ci		goto no_enough_resource;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	vgpu_aperture_sz(vgpu) = ALIGN(request, I915_GTT_PAGE_SIZE);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	item = "high GM space";
2658c2ecf20Sopenharmony_ci	max = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE;
2668c2ecf20Sopenharmony_ci	taken = gvt->gm.vgpu_allocated_high_gm_size;
2678c2ecf20Sopenharmony_ci	avail = max - taken;
2688c2ecf20Sopenharmony_ci	request = MB_TO_BYTES(param->high_gm_sz);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	if (request > avail)
2718c2ecf20Sopenharmony_ci		goto no_enough_resource;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	vgpu_hidden_sz(vgpu) = ALIGN(request, I915_GTT_PAGE_SIZE);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	item = "fence";
2768c2ecf20Sopenharmony_ci	max = gvt_fence_sz(gvt) - HOST_FENCE;
2778c2ecf20Sopenharmony_ci	taken = gvt->fence.vgpu_allocated_fence_num;
2788c2ecf20Sopenharmony_ci	avail = max - taken;
2798c2ecf20Sopenharmony_ci	request = param->fence_sz;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	if (request > avail)
2828c2ecf20Sopenharmony_ci		goto no_enough_resource;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	vgpu_fence_sz(vgpu) = request;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	gvt->gm.vgpu_allocated_low_gm_size += MB_TO_BYTES(param->low_gm_sz);
2878c2ecf20Sopenharmony_ci	gvt->gm.vgpu_allocated_high_gm_size += MB_TO_BYTES(param->high_gm_sz);
2888c2ecf20Sopenharmony_ci	gvt->fence.vgpu_allocated_fence_num += param->fence_sz;
2898c2ecf20Sopenharmony_ci	return 0;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cino_enough_resource:
2928c2ecf20Sopenharmony_ci	gvt_err("fail to allocate resource %s\n", item);
2938c2ecf20Sopenharmony_ci	gvt_err("request %luMB avail %luMB max %luMB taken %luMB\n",
2948c2ecf20Sopenharmony_ci		BYTES_TO_MB(request), BYTES_TO_MB(avail),
2958c2ecf20Sopenharmony_ci		BYTES_TO_MB(max), BYTES_TO_MB(taken));
2968c2ecf20Sopenharmony_ci	return -ENOSPC;
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci/**
3008c2ecf20Sopenharmony_ci * inte_gvt_free_vgpu_resource - free HW resource owned by a vGPU
3018c2ecf20Sopenharmony_ci * @vgpu: a vGPU
3028c2ecf20Sopenharmony_ci *
3038c2ecf20Sopenharmony_ci * This function is used to free the HW resource owned by a vGPU.
3048c2ecf20Sopenharmony_ci *
3058c2ecf20Sopenharmony_ci */
3068c2ecf20Sopenharmony_civoid intel_vgpu_free_resource(struct intel_vgpu *vgpu)
3078c2ecf20Sopenharmony_ci{
3088c2ecf20Sopenharmony_ci	free_vgpu_gm(vgpu);
3098c2ecf20Sopenharmony_ci	free_vgpu_fence(vgpu);
3108c2ecf20Sopenharmony_ci	free_resource(vgpu);
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci/**
3148c2ecf20Sopenharmony_ci * intel_vgpu_reset_resource - reset resource state owned by a vGPU
3158c2ecf20Sopenharmony_ci * @vgpu: a vGPU
3168c2ecf20Sopenharmony_ci *
3178c2ecf20Sopenharmony_ci * This function is used to reset resource state owned by a vGPU.
3188c2ecf20Sopenharmony_ci *
3198c2ecf20Sopenharmony_ci */
3208c2ecf20Sopenharmony_civoid intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	struct intel_gvt *gvt = vgpu->gvt;
3238c2ecf20Sopenharmony_ci	intel_wakeref_t wakeref;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	with_intel_runtime_pm(gvt->gt->uncore->rpm, wakeref)
3268c2ecf20Sopenharmony_ci		_clear_vgpu_fence(vgpu);
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci/**
3308c2ecf20Sopenharmony_ci * intel_alloc_vgpu_resource - allocate HW resource for a vGPU
3318c2ecf20Sopenharmony_ci * @vgpu: vGPU
3328c2ecf20Sopenharmony_ci * @param: vGPU creation params
3338c2ecf20Sopenharmony_ci *
3348c2ecf20Sopenharmony_ci * This function is used to allocate HW resource for a vGPU. User specifies
3358c2ecf20Sopenharmony_ci * the resource configuration through the creation params.
3368c2ecf20Sopenharmony_ci *
3378c2ecf20Sopenharmony_ci * Returns:
3388c2ecf20Sopenharmony_ci * zero on success, negative error code if failed.
3398c2ecf20Sopenharmony_ci *
3408c2ecf20Sopenharmony_ci */
3418c2ecf20Sopenharmony_ciint intel_vgpu_alloc_resource(struct intel_vgpu *vgpu,
3428c2ecf20Sopenharmony_ci		struct intel_vgpu_creation_params *param)
3438c2ecf20Sopenharmony_ci{
3448c2ecf20Sopenharmony_ci	int ret;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	ret = alloc_resource(vgpu, param);
3478c2ecf20Sopenharmony_ci	if (ret)
3488c2ecf20Sopenharmony_ci		return ret;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	ret = alloc_vgpu_gm(vgpu);
3518c2ecf20Sopenharmony_ci	if (ret)
3528c2ecf20Sopenharmony_ci		goto out_free_resource;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	ret = alloc_vgpu_fence(vgpu);
3558c2ecf20Sopenharmony_ci	if (ret)
3568c2ecf20Sopenharmony_ci		goto out_free_vgpu_gm;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	return 0;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ciout_free_vgpu_gm:
3618c2ecf20Sopenharmony_ci	free_vgpu_gm(vgpu);
3628c2ecf20Sopenharmony_ciout_free_resource:
3638c2ecf20Sopenharmony_ci	free_resource(vgpu);
3648c2ecf20Sopenharmony_ci	return ret;
3658c2ecf20Sopenharmony_ci}
366