162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright(c) 2011-2015 Intel Corporation. All rights reserved.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the next
1262306a36Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
1362306a36Sopenharmony_ci * Software.
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1862306a36Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1962306a36Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2062306a36Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2162306a36Sopenharmony_ci * SOFTWARE.
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include "i915_drv.h"
2562306a36Sopenharmony_ci#include "i915_pvinfo.h"
2662306a36Sopenharmony_ci#include "i915_vgpu.h"
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/**
2962306a36Sopenharmony_ci * DOC: Intel GVT-g guest support
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * Intel GVT-g is a graphics virtualization technology which shares the
3262306a36Sopenharmony_ci * GPU among multiple virtual machines on a time-sharing basis. Each
3362306a36Sopenharmony_ci * virtual machine is presented a virtual GPU (vGPU), which has equivalent
3462306a36Sopenharmony_ci * features as the underlying physical GPU (pGPU), so i915 driver can run
3562306a36Sopenharmony_ci * seamlessly in a virtual machine. This file provides vGPU specific
3662306a36Sopenharmony_ci * optimizations when running in a virtual machine, to reduce the complexity
3762306a36Sopenharmony_ci * of vGPU emulation and to improve the overall performance.
3862306a36Sopenharmony_ci *
3962306a36Sopenharmony_ci * A primary function introduced here is so-called "address space ballooning"
4062306a36Sopenharmony_ci * technique. Intel GVT-g partitions global graphics memory among multiple VMs,
4162306a36Sopenharmony_ci * so each VM can directly access a portion of the memory without hypervisor's
4262306a36Sopenharmony_ci * intervention, e.g. filling textures or queuing commands. However with the
4362306a36Sopenharmony_ci * partitioning an unmodified i915 driver would assume a smaller graphics
4462306a36Sopenharmony_ci * memory starting from address ZERO, then requires vGPU emulation module to
4562306a36Sopenharmony_ci * translate the graphics address between 'guest view' and 'host view', for
4662306a36Sopenharmony_ci * all registers and command opcodes which contain a graphics memory address.
4762306a36Sopenharmony_ci * To reduce the complexity, Intel GVT-g introduces "address space ballooning",
4862306a36Sopenharmony_ci * by telling the exact partitioning knowledge to each guest i915 driver, which
4962306a36Sopenharmony_ci * then reserves and prevents non-allocated portions from allocation. Thus vGPU
5062306a36Sopenharmony_ci * emulation module only needs to scan and validate graphics addresses without
5162306a36Sopenharmony_ci * complexity of address translation.
5262306a36Sopenharmony_ci *
5362306a36Sopenharmony_ci */
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/**
5662306a36Sopenharmony_ci * intel_vgpu_detect - detect virtual GPU
5762306a36Sopenharmony_ci * @dev_priv: i915 device private
5862306a36Sopenharmony_ci *
5962306a36Sopenharmony_ci * This function is called at the initialization stage, to detect whether
6062306a36Sopenharmony_ci * running on a vGPU.
6162306a36Sopenharmony_ci */
6262306a36Sopenharmony_civoid intel_vgpu_detect(struct drm_i915_private *dev_priv)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
6562306a36Sopenharmony_ci	u64 magic;
6662306a36Sopenharmony_ci	u16 version_major;
6762306a36Sopenharmony_ci	void __iomem *shared_area;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	/*
7262306a36Sopenharmony_ci	 * This is called before we setup the main MMIO BAR mappings used via
7362306a36Sopenharmony_ci	 * the uncore structure, so we need to access the BAR directly. Since
7462306a36Sopenharmony_ci	 * we do not support VGT on older gens, return early so we don't have
7562306a36Sopenharmony_ci	 * to consider differently numbered or sized MMIO bars
7662306a36Sopenharmony_ci	 */
7762306a36Sopenharmony_ci	if (GRAPHICS_VER(dev_priv) < 6)
7862306a36Sopenharmony_ci		return;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	shared_area = pci_iomap_range(pdev, 0, VGT_PVINFO_PAGE, VGT_PVINFO_SIZE);
8162306a36Sopenharmony_ci	if (!shared_area) {
8262306a36Sopenharmony_ci		drm_err(&dev_priv->drm,
8362306a36Sopenharmony_ci			"failed to map MMIO bar to check for VGT\n");
8462306a36Sopenharmony_ci		return;
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	magic = readq(shared_area + vgtif_offset(magic));
8862306a36Sopenharmony_ci	if (magic != VGT_MAGIC)
8962306a36Sopenharmony_ci		goto out;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	version_major = readw(shared_area + vgtif_offset(version_major));
9262306a36Sopenharmony_ci	if (version_major < VGT_VERSION_MAJOR) {
9362306a36Sopenharmony_ci		drm_info(&dev_priv->drm, "VGT interface version mismatch!\n");
9462306a36Sopenharmony_ci		goto out;
9562306a36Sopenharmony_ci	}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	dev_priv->vgpu.caps = readl(shared_area + vgtif_offset(vgt_caps));
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	dev_priv->vgpu.active = true;
10062306a36Sopenharmony_ci	mutex_init(&dev_priv->vgpu.lock);
10162306a36Sopenharmony_ci	drm_info(&dev_priv->drm, "Virtual GPU for Intel GVT-g detected.\n");
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ciout:
10462306a36Sopenharmony_ci	pci_iounmap(pdev, shared_area);
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_civoid intel_vgpu_register(struct drm_i915_private *i915)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	/*
11062306a36Sopenharmony_ci	 * Notify a valid surface after modesetting, when running inside a VM.
11162306a36Sopenharmony_ci	 */
11262306a36Sopenharmony_ci	if (intel_vgpu_active(i915))
11362306a36Sopenharmony_ci		intel_uncore_write(&i915->uncore, vgtif_reg(display_ready),
11462306a36Sopenharmony_ci				   VGT_DRV_DISPLAY_READY);
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cibool intel_vgpu_active(struct drm_i915_private *dev_priv)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	return dev_priv->vgpu.active;
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cibool intel_vgpu_has_full_ppgtt(struct drm_i915_private *dev_priv)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	return dev_priv->vgpu.caps & VGT_CAPS_FULL_PPGTT;
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cibool intel_vgpu_has_hwsp_emulation(struct drm_i915_private *dev_priv)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	return dev_priv->vgpu.caps & VGT_CAPS_HWSP_EMULATION;
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cibool intel_vgpu_has_huge_gtt(struct drm_i915_private *dev_priv)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	return dev_priv->vgpu.caps & VGT_CAPS_HUGE_GTT;
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistruct _balloon_info_ {
13862306a36Sopenharmony_ci	/*
13962306a36Sopenharmony_ci	 * There are up to 2 regions per mappable/unmappable graphic
14062306a36Sopenharmony_ci	 * memory that might be ballooned. Here, index 0/1 is for mappable
14162306a36Sopenharmony_ci	 * graphic memory, 2/3 for unmappable graphic memory.
14262306a36Sopenharmony_ci	 */
14362306a36Sopenharmony_ci	struct drm_mm_node space[4];
14462306a36Sopenharmony_ci};
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic struct _balloon_info_ bl_info;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic void vgt_deballoon_space(struct i915_ggtt *ggtt,
14962306a36Sopenharmony_ci				struct drm_mm_node *node)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = ggtt->vm.i915;
15262306a36Sopenharmony_ci	if (!drm_mm_node_allocated(node))
15362306a36Sopenharmony_ci		return;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	drm_dbg(&dev_priv->drm,
15662306a36Sopenharmony_ci		"deballoon space: range [0x%llx - 0x%llx] %llu KiB.\n",
15762306a36Sopenharmony_ci		node->start,
15862306a36Sopenharmony_ci		node->start + node->size,
15962306a36Sopenharmony_ci		node->size / 1024);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	ggtt->vm.reserved -= node->size;
16262306a36Sopenharmony_ci	drm_mm_remove_node(node);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/**
16662306a36Sopenharmony_ci * intel_vgt_deballoon - deballoon reserved graphics address trunks
16762306a36Sopenharmony_ci * @ggtt: the global GGTT from which we reserved earlier
16862306a36Sopenharmony_ci *
16962306a36Sopenharmony_ci * This function is called to deallocate the ballooned-out graphic memory, when
17062306a36Sopenharmony_ci * driver is unloaded or when ballooning fails.
17162306a36Sopenharmony_ci */
17262306a36Sopenharmony_civoid intel_vgt_deballoon(struct i915_ggtt *ggtt)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = ggtt->vm.i915;
17562306a36Sopenharmony_ci	int i;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	if (!intel_vgpu_active(ggtt->vm.i915))
17862306a36Sopenharmony_ci		return;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	drm_dbg(&dev_priv->drm, "VGT deballoon.\n");
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	for (i = 0; i < 4; i++)
18362306a36Sopenharmony_ci		vgt_deballoon_space(ggtt, &bl_info.space[i]);
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic int vgt_balloon_space(struct i915_ggtt *ggtt,
18762306a36Sopenharmony_ci			     struct drm_mm_node *node,
18862306a36Sopenharmony_ci			     unsigned long start, unsigned long end)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = ggtt->vm.i915;
19162306a36Sopenharmony_ci	unsigned long size = end - start;
19262306a36Sopenharmony_ci	int ret;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	if (start >= end)
19562306a36Sopenharmony_ci		return -EINVAL;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	drm_info(&dev_priv->drm,
19862306a36Sopenharmony_ci		 "balloon space: range [ 0x%lx - 0x%lx ] %lu KiB.\n",
19962306a36Sopenharmony_ci		 start, end, size / 1024);
20062306a36Sopenharmony_ci	ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, node,
20162306a36Sopenharmony_ci				   size, start, I915_COLOR_UNEVICTABLE,
20262306a36Sopenharmony_ci				   0);
20362306a36Sopenharmony_ci	if (!ret)
20462306a36Sopenharmony_ci		ggtt->vm.reserved += size;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	return ret;
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci/**
21062306a36Sopenharmony_ci * intel_vgt_balloon - balloon out reserved graphics address trunks
21162306a36Sopenharmony_ci * @ggtt: the global GGTT from which to reserve
21262306a36Sopenharmony_ci *
21362306a36Sopenharmony_ci * This function is called at the initialization stage, to balloon out the
21462306a36Sopenharmony_ci * graphic address space allocated to other vGPUs, by marking these spaces as
21562306a36Sopenharmony_ci * reserved. The ballooning related knowledge(starting address and size of
21662306a36Sopenharmony_ci * the mappable/unmappable graphic memory) is described in the vgt_if structure
21762306a36Sopenharmony_ci * in a reserved mmio range.
21862306a36Sopenharmony_ci *
21962306a36Sopenharmony_ci * To give an example, the drawing below depicts one typical scenario after
22062306a36Sopenharmony_ci * ballooning. Here the vGPU1 has 2 pieces of graphic address spaces ballooned
22162306a36Sopenharmony_ci * out each for the mappable and the non-mappable part. From the vGPU1 point of
22262306a36Sopenharmony_ci * view, the total size is the same as the physical one, with the start address
22362306a36Sopenharmony_ci * of its graphic space being zero. Yet there are some portions ballooned out(
22462306a36Sopenharmony_ci * the shadow part, which are marked as reserved by drm allocator). From the
22562306a36Sopenharmony_ci * host point of view, the graphic address space is partitioned by multiple
22662306a36Sopenharmony_ci * vGPUs in different VMs. ::
22762306a36Sopenharmony_ci *
22862306a36Sopenharmony_ci *                         vGPU1 view         Host view
22962306a36Sopenharmony_ci *              0 ------> +-----------+     +-----------+
23062306a36Sopenharmony_ci *                ^       |###########|     |   vGPU3   |
23162306a36Sopenharmony_ci *                |       |###########|     +-----------+
23262306a36Sopenharmony_ci *                |       |###########|     |   vGPU2   |
23362306a36Sopenharmony_ci *                |       +-----------+     +-----------+
23462306a36Sopenharmony_ci *         mappable GM    | available | ==> |   vGPU1   |
23562306a36Sopenharmony_ci *                |       +-----------+     +-----------+
23662306a36Sopenharmony_ci *                |       |###########|     |           |
23762306a36Sopenharmony_ci *                v       |###########|     |   Host    |
23862306a36Sopenharmony_ci *                +=======+===========+     +===========+
23962306a36Sopenharmony_ci *                ^       |###########|     |   vGPU3   |
24062306a36Sopenharmony_ci *                |       |###########|     +-----------+
24162306a36Sopenharmony_ci *                |       |###########|     |   vGPU2   |
24262306a36Sopenharmony_ci *                |       +-----------+     +-----------+
24362306a36Sopenharmony_ci *       unmappable GM    | available | ==> |   vGPU1   |
24462306a36Sopenharmony_ci *                |       +-----------+     +-----------+
24562306a36Sopenharmony_ci *                |       |###########|     |           |
24662306a36Sopenharmony_ci *                |       |###########|     |   Host    |
24762306a36Sopenharmony_ci *                v       |###########|     |           |
24862306a36Sopenharmony_ci *  total GM size ------> +-----------+     +-----------+
24962306a36Sopenharmony_ci *
25062306a36Sopenharmony_ci * Returns:
25162306a36Sopenharmony_ci * zero on success, non-zero if configuration invalid or ballooning failed
25262306a36Sopenharmony_ci */
25362306a36Sopenharmony_ciint intel_vgt_balloon(struct i915_ggtt *ggtt)
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = ggtt->vm.i915;
25662306a36Sopenharmony_ci	struct intel_uncore *uncore = &dev_priv->uncore;
25762306a36Sopenharmony_ci	unsigned long ggtt_end = ggtt->vm.total;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	unsigned long mappable_base, mappable_size, mappable_end;
26062306a36Sopenharmony_ci	unsigned long unmappable_base, unmappable_size, unmappable_end;
26162306a36Sopenharmony_ci	int ret;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	if (!intel_vgpu_active(ggtt->vm.i915))
26462306a36Sopenharmony_ci		return 0;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	mappable_base =
26762306a36Sopenharmony_ci	  intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.base));
26862306a36Sopenharmony_ci	mappable_size =
26962306a36Sopenharmony_ci	  intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.size));
27062306a36Sopenharmony_ci	unmappable_base =
27162306a36Sopenharmony_ci	  intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.base));
27262306a36Sopenharmony_ci	unmappable_size =
27362306a36Sopenharmony_ci	  intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.size));
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	mappable_end = mappable_base + mappable_size;
27662306a36Sopenharmony_ci	unmappable_end = unmappable_base + unmappable_size;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	drm_info(&dev_priv->drm, "VGT ballooning configuration:\n");
27962306a36Sopenharmony_ci	drm_info(&dev_priv->drm,
28062306a36Sopenharmony_ci		 "Mappable graphic memory: base 0x%lx size %ldKiB\n",
28162306a36Sopenharmony_ci		 mappable_base, mappable_size / 1024);
28262306a36Sopenharmony_ci	drm_info(&dev_priv->drm,
28362306a36Sopenharmony_ci		 "Unmappable graphic memory: base 0x%lx size %ldKiB\n",
28462306a36Sopenharmony_ci		 unmappable_base, unmappable_size / 1024);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	if (mappable_end > ggtt->mappable_end ||
28762306a36Sopenharmony_ci	    unmappable_base < ggtt->mappable_end ||
28862306a36Sopenharmony_ci	    unmappable_end > ggtt_end) {
28962306a36Sopenharmony_ci		drm_err(&dev_priv->drm, "Invalid ballooning configuration!\n");
29062306a36Sopenharmony_ci		return -EINVAL;
29162306a36Sopenharmony_ci	}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	/* Unmappable graphic memory ballooning */
29462306a36Sopenharmony_ci	if (unmappable_base > ggtt->mappable_end) {
29562306a36Sopenharmony_ci		ret = vgt_balloon_space(ggtt, &bl_info.space[2],
29662306a36Sopenharmony_ci					ggtt->mappable_end, unmappable_base);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci		if (ret)
29962306a36Sopenharmony_ci			goto err;
30062306a36Sopenharmony_ci	}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	if (unmappable_end < ggtt_end) {
30362306a36Sopenharmony_ci		ret = vgt_balloon_space(ggtt, &bl_info.space[3],
30462306a36Sopenharmony_ci					unmappable_end, ggtt_end);
30562306a36Sopenharmony_ci		if (ret)
30662306a36Sopenharmony_ci			goto err_upon_mappable;
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	/* Mappable graphic memory ballooning */
31062306a36Sopenharmony_ci	if (mappable_base) {
31162306a36Sopenharmony_ci		ret = vgt_balloon_space(ggtt, &bl_info.space[0],
31262306a36Sopenharmony_ci					0, mappable_base);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci		if (ret)
31562306a36Sopenharmony_ci			goto err_upon_unmappable;
31662306a36Sopenharmony_ci	}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	if (mappable_end < ggtt->mappable_end) {
31962306a36Sopenharmony_ci		ret = vgt_balloon_space(ggtt, &bl_info.space[1],
32062306a36Sopenharmony_ci					mappable_end, ggtt->mappable_end);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci		if (ret)
32362306a36Sopenharmony_ci			goto err_below_mappable;
32462306a36Sopenharmony_ci	}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	drm_info(&dev_priv->drm, "VGT balloon successfully\n");
32762306a36Sopenharmony_ci	return 0;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_cierr_below_mappable:
33062306a36Sopenharmony_ci	vgt_deballoon_space(ggtt, &bl_info.space[0]);
33162306a36Sopenharmony_cierr_upon_unmappable:
33262306a36Sopenharmony_ci	vgt_deballoon_space(ggtt, &bl_info.space[3]);
33362306a36Sopenharmony_cierr_upon_mappable:
33462306a36Sopenharmony_ci	vgt_deballoon_space(ggtt, &bl_info.space[2]);
33562306a36Sopenharmony_cierr:
33662306a36Sopenharmony_ci	drm_err(&dev_priv->drm, "VGT balloon fail\n");
33762306a36Sopenharmony_ci	return ret;
33862306a36Sopenharmony_ci}
339