1cf9d2890SYu Zhang /*
2cf9d2890SYu Zhang * Copyright(c) 2011-2015 Intel Corporation. All rights reserved.
3cf9d2890SYu Zhang *
4cf9d2890SYu Zhang * Permission is hereby granted, free of charge, to any person obtaining a
5cf9d2890SYu Zhang * copy of this software and associated documentation files (the "Software"),
6cf9d2890SYu Zhang * to deal in the Software without restriction, including without limitation
7cf9d2890SYu Zhang * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8cf9d2890SYu Zhang * and/or sell copies of the Software, and to permit persons to whom the
9cf9d2890SYu Zhang * Software is furnished to do so, subject to the following conditions:
10cf9d2890SYu Zhang *
11cf9d2890SYu Zhang * The above copyright notice and this permission notice (including the next
12cf9d2890SYu Zhang * paragraph) shall be included in all copies or substantial portions of the
13cf9d2890SYu Zhang * Software.
14cf9d2890SYu Zhang *
15cf9d2890SYu Zhang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16cf9d2890SYu Zhang * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17cf9d2890SYu Zhang * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18cf9d2890SYu Zhang * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19cf9d2890SYu Zhang * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20cf9d2890SYu Zhang * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21cf9d2890SYu Zhang * SOFTWARE.
22cf9d2890SYu Zhang */
23cf9d2890SYu Zhang
249e859eb9SJani Nikula #include "i915_drv.h"
259e859eb9SJani Nikula #include "i915_pvinfo.h"
26cf9d2890SYu Zhang #include "i915_vgpu.h"
27cf9d2890SYu Zhang
28cf9d2890SYu Zhang /**
29cf9d2890SYu Zhang * DOC: Intel GVT-g guest support
30cf9d2890SYu Zhang *
31cf9d2890SYu Zhang * Intel GVT-g is a graphics virtualization technology which shares the
32cf9d2890SYu Zhang * GPU among multiple virtual machines on a time-sharing basis. Each
33cf9d2890SYu Zhang * virtual machine is presented a virtual GPU (vGPU), which has equivalent
34cf9d2890SYu Zhang * features as the underlying physical GPU (pGPU), so i915 driver can run
35cf9d2890SYu Zhang * seamlessly in a virtual machine. This file provides vGPU specific
36cf9d2890SYu Zhang * optimizations when running in a virtual machine, to reduce the complexity
37cf9d2890SYu Zhang * of vGPU emulation and to improve the overall performance.
38cf9d2890SYu Zhang *
39cf9d2890SYu Zhang * A primary function introduced here is so-called "address space ballooning"
40cf9d2890SYu Zhang * technique. Intel GVT-g partitions global graphics memory among multiple VMs,
41cf9d2890SYu Zhang * so each VM can directly access a portion of the memory without hypervisor's
42cf9d2890SYu Zhang * intervention, e.g. filling textures or queuing commands. However with the
43cf9d2890SYu Zhang * partitioning an unmodified i915 driver would assume a smaller graphics
44cf9d2890SYu Zhang * memory starting from address ZERO, then requires vGPU emulation module to
45cf9d2890SYu Zhang * translate the graphics address between 'guest view' and 'host view', for
46cf9d2890SYu Zhang * all registers and command opcodes which contain a graphics memory address.
47cf9d2890SYu Zhang * To reduce the complexity, Intel GVT-g introduces "address space ballooning",
48cf9d2890SYu Zhang * by telling the exact partitioning knowledge to each guest i915 driver, which
49cf9d2890SYu Zhang * then reserves and prevents non-allocated portions from allocation. Thus vGPU
50cf9d2890SYu Zhang * emulation module only needs to scan and validate graphics addresses without
51cf9d2890SYu Zhang * complexity of address translation.
52cf9d2890SYu Zhang *
53cf9d2890SYu Zhang */
54cf9d2890SYu Zhang
55cf9d2890SYu Zhang /**
569e859eb9SJani Nikula * intel_vgpu_detect - detect virtual GPU
5714bb2c11STvrtko Ursulin * @dev_priv: i915 device private
58cf9d2890SYu Zhang *
59cf9d2890SYu Zhang * This function is called at the initialization stage, to detect whether
60cf9d2890SYu Zhang * running on a vGPU.
61cf9d2890SYu Zhang */
intel_vgpu_detect(struct drm_i915_private * dev_priv)629e859eb9SJani Nikula void intel_vgpu_detect(struct drm_i915_private *dev_priv)
63cf9d2890SYu Zhang {
648ff5446aSThomas Zimmermann struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
650c8792d0SZhenyu Wang u64 magic;
660c8792d0SZhenyu Wang u16 version_major;
679e138ea1SDaniele Ceraolo Spurio void __iomem *shared_area;
68cf9d2890SYu Zhang
69cf9d2890SYu Zhang BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
70cf9d2890SYu Zhang
719e138ea1SDaniele Ceraolo Spurio /*
729e138ea1SDaniele Ceraolo Spurio * This is called before we setup the main MMIO BAR mappings used via
739e138ea1SDaniele Ceraolo Spurio * the uncore structure, so we need to access the BAR directly. Since
749e138ea1SDaniele Ceraolo Spurio * we do not support VGT on older gens, return early so we don't have
759e138ea1SDaniele Ceraolo Spurio * to consider differently numbered or sized MMIO bars
769e138ea1SDaniele Ceraolo Spurio */
77651e7d48SLucas De Marchi if (GRAPHICS_VER(dev_priv) < 6)
78cf9d2890SYu Zhang return;
79cf9d2890SYu Zhang
809e138ea1SDaniele Ceraolo Spurio shared_area = pci_iomap_range(pdev, 0, VGT_PVINFO_PAGE, VGT_PVINFO_SIZE);
819e138ea1SDaniele Ceraolo Spurio if (!shared_area) {
82aee2eeebSWambui Karuga drm_err(&dev_priv->drm,
83aee2eeebSWambui Karuga "failed to map MMIO bar to check for VGT\n");
84cf9d2890SYu Zhang return;
85cf9d2890SYu Zhang }
86cf9d2890SYu Zhang
879e138ea1SDaniele Ceraolo Spurio magic = readq(shared_area + vgtif_offset(magic));
889e138ea1SDaniele Ceraolo Spurio if (magic != VGT_MAGIC)
899e138ea1SDaniele Ceraolo Spurio goto out;
909e138ea1SDaniele Ceraolo Spurio
919e138ea1SDaniele Ceraolo Spurio version_major = readw(shared_area + vgtif_offset(version_major));
929e138ea1SDaniele Ceraolo Spurio if (version_major < VGT_VERSION_MAJOR) {
93aee2eeebSWambui Karuga drm_info(&dev_priv->drm, "VGT interface version mismatch!\n");
949e138ea1SDaniele Ceraolo Spurio goto out;
959e138ea1SDaniele Ceraolo Spurio }
969e138ea1SDaniele Ceraolo Spurio
979e138ea1SDaniele Ceraolo Spurio dev_priv->vgpu.caps = readl(shared_area + vgtif_offset(vgt_caps));
988a4ab66fSTina Zhang
99cf9d2890SYu Zhang dev_priv->vgpu.active = true;
10052988009SXiaolin Zhang mutex_init(&dev_priv->vgpu.lock);
101aee2eeebSWambui Karuga drm_info(&dev_priv->drm, "Virtual GPU for Intel GVT-g detected.\n");
1029e138ea1SDaniele Ceraolo Spurio
1039e138ea1SDaniele Ceraolo Spurio out:
1049e138ea1SDaniele Ceraolo Spurio pci_iounmap(pdev, shared_area);
105cf9d2890SYu Zhang }
1065dda8fa3SYu Zhang
intel_vgpu_register(struct drm_i915_private * i915)1079e859eb9SJani Nikula void intel_vgpu_register(struct drm_i915_private *i915)
1089e859eb9SJani Nikula {
1099e859eb9SJani Nikula /*
1109e859eb9SJani Nikula * Notify a valid surface after modesetting, when running inside a VM.
1119e859eb9SJani Nikula */
1129e859eb9SJani Nikula if (intel_vgpu_active(i915))
1139e859eb9SJani Nikula intel_uncore_write(&i915->uncore, vgtif_reg(display_ready),
1149e859eb9SJani Nikula VGT_DRV_DISPLAY_READY);
1159e859eb9SJani Nikula }
1169e859eb9SJani Nikula
intel_vgpu_active(struct drm_i915_private * dev_priv)1179e859eb9SJani Nikula bool intel_vgpu_active(struct drm_i915_private *dev_priv)
1189e859eb9SJani Nikula {
1199e859eb9SJani Nikula return dev_priv->vgpu.active;
1209e859eb9SJani Nikula }
1219e859eb9SJani Nikula
intel_vgpu_has_full_ppgtt(struct drm_i915_private * dev_priv)122ca6ac684SChris Wilson bool intel_vgpu_has_full_ppgtt(struct drm_i915_private *dev_priv)
1238a4ab66fSTina Zhang {
124ca6ac684SChris Wilson return dev_priv->vgpu.caps & VGT_CAPS_FULL_PPGTT;
1258a4ab66fSTina Zhang }
1268a4ab66fSTina Zhang
intel_vgpu_has_hwsp_emulation(struct drm_i915_private * dev_priv)1279e859eb9SJani Nikula bool intel_vgpu_has_hwsp_emulation(struct drm_i915_private *dev_priv)
1289e859eb9SJani Nikula {
1299e859eb9SJani Nikula return dev_priv->vgpu.caps & VGT_CAPS_HWSP_EMULATION;
1309e859eb9SJani Nikula }
1319e859eb9SJani Nikula
intel_vgpu_has_huge_gtt(struct drm_i915_private * dev_priv)1329e859eb9SJani Nikula bool intel_vgpu_has_huge_gtt(struct drm_i915_private *dev_priv)
1339e859eb9SJani Nikula {
1349e859eb9SJani Nikula return dev_priv->vgpu.caps & VGT_CAPS_HUGE_GTT;
1359e859eb9SJani Nikula }
1369e859eb9SJani Nikula
1375dda8fa3SYu Zhang struct _balloon_info_ {
1385dda8fa3SYu Zhang /*
1395dda8fa3SYu Zhang * There are up to 2 regions per mappable/unmappable graphic
1405dda8fa3SYu Zhang * memory that might be ballooned. Here, index 0/1 is for mappable
1415dda8fa3SYu Zhang * graphic memory, 2/3 for unmappable graphic memory.
1425dda8fa3SYu Zhang */
1435dda8fa3SYu Zhang struct drm_mm_node space[4];
1445dda8fa3SYu Zhang };
1455dda8fa3SYu Zhang
1465dda8fa3SYu Zhang static struct _balloon_info_ bl_info;
1475dda8fa3SYu Zhang
vgt_deballoon_space(struct i915_ggtt * ggtt,struct drm_mm_node * node)148ff8f7975SWeinan Li static void vgt_deballoon_space(struct i915_ggtt *ggtt,
149ff8f7975SWeinan Li struct drm_mm_node *node)
150ff8f7975SWeinan Li {
151aee2eeebSWambui Karuga struct drm_i915_private *dev_priv = ggtt->vm.i915;
1524776f352SXiong Zhang if (!drm_mm_node_allocated(node))
1534776f352SXiong Zhang return;
1544776f352SXiong Zhang
155aee2eeebSWambui Karuga drm_dbg(&dev_priv->drm,
156aee2eeebSWambui Karuga "deballoon space: range [0x%llx - 0x%llx] %llu KiB.\n",
157ff8f7975SWeinan Li node->start,
158ff8f7975SWeinan Li node->start + node->size,
159ff8f7975SWeinan Li node->size / 1024);
160ff8f7975SWeinan Li
16182ad6443SChris Wilson ggtt->vm.reserved -= node->size;
162ff8f7975SWeinan Li drm_mm_remove_node(node);
163ff8f7975SWeinan Li }
164ff8f7975SWeinan Li
1655dda8fa3SYu Zhang /**
1665dda8fa3SYu Zhang * intel_vgt_deballoon - deballoon reserved graphics address trunks
16780fc1c19SChris Wilson * @ggtt: the global GGTT from which we reserved earlier
1685dda8fa3SYu Zhang *
1695dda8fa3SYu Zhang * This function is called to deallocate the ballooned-out graphic memory, when
1705dda8fa3SYu Zhang * driver is unloaded or when ballooning fails.
1715dda8fa3SYu Zhang */
intel_vgt_deballoon(struct i915_ggtt * ggtt)1723cb4ce00STvrtko Ursulin void intel_vgt_deballoon(struct i915_ggtt *ggtt)
1735dda8fa3SYu Zhang {
174aee2eeebSWambui Karuga struct drm_i915_private *dev_priv = ggtt->vm.i915;
1755dda8fa3SYu Zhang int i;
1765dda8fa3SYu Zhang
1773cb4ce00STvrtko Ursulin if (!intel_vgpu_active(ggtt->vm.i915))
178b02d22a3SZhi Wang return;
179b02d22a3SZhi Wang
180aee2eeebSWambui Karuga drm_dbg(&dev_priv->drm, "VGT deballoon.\n");
1815dda8fa3SYu Zhang
182ff8f7975SWeinan Li for (i = 0; i < 4; i++)
1833cb4ce00STvrtko Ursulin vgt_deballoon_space(ggtt, &bl_info.space[i]);
1845dda8fa3SYu Zhang }
1855dda8fa3SYu Zhang
vgt_balloon_space(struct i915_ggtt * ggtt,struct drm_mm_node * node,unsigned long start,unsigned long end)186625d988aSChris Wilson static int vgt_balloon_space(struct i915_ggtt *ggtt,
1875dda8fa3SYu Zhang struct drm_mm_node *node,
1885dda8fa3SYu Zhang unsigned long start, unsigned long end)
1895dda8fa3SYu Zhang {
190aee2eeebSWambui Karuga struct drm_i915_private *dev_priv = ggtt->vm.i915;
1915dda8fa3SYu Zhang unsigned long size = end - start;
192ff8f7975SWeinan Li int ret;
1935dda8fa3SYu Zhang
194b368f533SZhenyu Wang if (start >= end)
1955dda8fa3SYu Zhang return -EINVAL;
1965dda8fa3SYu Zhang
197aee2eeebSWambui Karuga drm_info(&dev_priv->drm,
198aee2eeebSWambui Karuga "balloon space: range [ 0x%lx - 0x%lx ] %lu KiB.\n",
1995dda8fa3SYu Zhang start, end, size / 1024);
200*7e00897bSMaarten Lankhorst ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, node,
201625d988aSChris Wilson size, start, I915_COLOR_UNEVICTABLE,
202625d988aSChris Wilson 0);
203ff8f7975SWeinan Li if (!ret)
20482ad6443SChris Wilson ggtt->vm.reserved += size;
205ff8f7975SWeinan Li
206ff8f7975SWeinan Li return ret;
2075dda8fa3SYu Zhang }
2085dda8fa3SYu Zhang
2095dda8fa3SYu Zhang /**
2105dda8fa3SYu Zhang * intel_vgt_balloon - balloon out reserved graphics address trunks
21180fc1c19SChris Wilson * @ggtt: the global GGTT from which to reserve
2125dda8fa3SYu Zhang *
2135dda8fa3SYu Zhang * This function is called at the initialization stage, to balloon out the
2145dda8fa3SYu Zhang * graphic address space allocated to other vGPUs, by marking these spaces as
2155dda8fa3SYu Zhang * reserved. The ballooning related knowledge(starting address and size of
2165dda8fa3SYu Zhang * the mappable/unmappable graphic memory) is described in the vgt_if structure
2175dda8fa3SYu Zhang * in a reserved mmio range.
2185dda8fa3SYu Zhang *
2195dda8fa3SYu Zhang * To give an example, the drawing below depicts one typical scenario after
2205dda8fa3SYu Zhang * ballooning. Here the vGPU1 has 2 pieces of graphic address spaces ballooned
2215dda8fa3SYu Zhang * out each for the mappable and the non-mappable part. From the vGPU1 point of
2225dda8fa3SYu Zhang * view, the total size is the same as the physical one, with the start address
2235dda8fa3SYu Zhang * of its graphic space being zero. Yet there are some portions ballooned out(
2245dda8fa3SYu Zhang * the shadow part, which are marked as reserved by drm allocator). From the
2255dda8fa3SYu Zhang * host point of view, the graphic address space is partitioned by multiple
226da5335b8SDaniel Vetter * vGPUs in different VMs. ::
2275dda8fa3SYu Zhang *
2285dda8fa3SYu Zhang * vGPU1 view Host view
2295dda8fa3SYu Zhang * 0 ------> +-----------+ +-----------+
230da5335b8SDaniel Vetter * ^ |###########| | vGPU3 |
231da5335b8SDaniel Vetter * | |###########| +-----------+
232da5335b8SDaniel Vetter * | |###########| | vGPU2 |
2335dda8fa3SYu Zhang * | +-----------+ +-----------+
2345dda8fa3SYu Zhang * mappable GM | available | ==> | vGPU1 |
2355dda8fa3SYu Zhang * | +-----------+ +-----------+
236da5335b8SDaniel Vetter * | |###########| | |
237da5335b8SDaniel Vetter * v |###########| | Host |
2385dda8fa3SYu Zhang * +=======+===========+ +===========+
239da5335b8SDaniel Vetter * ^ |###########| | vGPU3 |
240da5335b8SDaniel Vetter * | |###########| +-----------+
241da5335b8SDaniel Vetter * | |###########| | vGPU2 |
2425dda8fa3SYu Zhang * | +-----------+ +-----------+
2435dda8fa3SYu Zhang * unmappable GM | available | ==> | vGPU1 |
2445dda8fa3SYu Zhang * | +-----------+ +-----------+
245da5335b8SDaniel Vetter * | |###########| | |
246da5335b8SDaniel Vetter * | |###########| | Host |
247da5335b8SDaniel Vetter * v |###########| | |
2485dda8fa3SYu Zhang * total GM size ------> +-----------+ +-----------+
2495dda8fa3SYu Zhang *
2505dda8fa3SYu Zhang * Returns:
2515dda8fa3SYu Zhang * zero on success, non-zero if configuration invalid or ballooning failed
2525dda8fa3SYu Zhang */
intel_vgt_balloon(struct i915_ggtt * ggtt)2533cb4ce00STvrtko Ursulin int intel_vgt_balloon(struct i915_ggtt *ggtt)
2545dda8fa3SYu Zhang {
255aee2eeebSWambui Karuga struct drm_i915_private *dev_priv = ggtt->vm.i915;
256aee2eeebSWambui Karuga struct intel_uncore *uncore = &dev_priv->uncore;
25782ad6443SChris Wilson unsigned long ggtt_end = ggtt->vm.total;
2585dda8fa3SYu Zhang
2595dda8fa3SYu Zhang unsigned long mappable_base, mappable_size, mappable_end;
2605dda8fa3SYu Zhang unsigned long unmappable_base, unmappable_size, unmappable_end;
2615dda8fa3SYu Zhang int ret;
2625dda8fa3SYu Zhang
2633cb4ce00STvrtko Ursulin if (!intel_vgpu_active(ggtt->vm.i915))
264b02d22a3SZhi Wang return 0;
265b02d22a3SZhi Wang
2663cb4ce00STvrtko Ursulin mappable_base =
2673cb4ce00STvrtko Ursulin intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.base));
2683cb4ce00STvrtko Ursulin mappable_size =
2693cb4ce00STvrtko Ursulin intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.size));
2703cb4ce00STvrtko Ursulin unmappable_base =
2713cb4ce00STvrtko Ursulin intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.base));
2723cb4ce00STvrtko Ursulin unmappable_size =
2733cb4ce00STvrtko Ursulin intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.size));
2745dda8fa3SYu Zhang
2755dda8fa3SYu Zhang mappable_end = mappable_base + mappable_size;
2765dda8fa3SYu Zhang unmappable_end = unmappable_base + unmappable_size;
2775dda8fa3SYu Zhang
278aee2eeebSWambui Karuga drm_info(&dev_priv->drm, "VGT ballooning configuration:\n");
279aee2eeebSWambui Karuga drm_info(&dev_priv->drm,
280aee2eeebSWambui Karuga "Mappable graphic memory: base 0x%lx size %ldKiB\n",
2815dda8fa3SYu Zhang mappable_base, mappable_size / 1024);
282aee2eeebSWambui Karuga drm_info(&dev_priv->drm,
283aee2eeebSWambui Karuga "Unmappable graphic memory: base 0x%lx size %ldKiB\n",
2845dda8fa3SYu Zhang unmappable_base, unmappable_size / 1024);
2855dda8fa3SYu Zhang
286381b943bSChris Wilson if (mappable_end > ggtt->mappable_end ||
28772e96d64SJoonas Lahtinen unmappable_base < ggtt->mappable_end ||
28872e96d64SJoonas Lahtinen unmappable_end > ggtt_end) {
289aee2eeebSWambui Karuga drm_err(&dev_priv->drm, "Invalid ballooning configuration!\n");
2905dda8fa3SYu Zhang return -EINVAL;
2915dda8fa3SYu Zhang }
2925dda8fa3SYu Zhang
2935dda8fa3SYu Zhang /* Unmappable graphic memory ballooning */
29472e96d64SJoonas Lahtinen if (unmappable_base > ggtt->mappable_end) {
295625d988aSChris Wilson ret = vgt_balloon_space(ggtt, &bl_info.space[2],
296625d988aSChris Wilson ggtt->mappable_end, unmappable_base);
2975dda8fa3SYu Zhang
2985dda8fa3SYu Zhang if (ret)
2995dda8fa3SYu Zhang goto err;
3005dda8fa3SYu Zhang }
3015dda8fa3SYu Zhang
302fa7e8b55SZhenyu Wang if (unmappable_end < ggtt_end) {
303625d988aSChris Wilson ret = vgt_balloon_space(ggtt, &bl_info.space[3],
304fa7e8b55SZhenyu Wang unmappable_end, ggtt_end);
3055dda8fa3SYu Zhang if (ret)
306ff8f7975SWeinan Li goto err_upon_mappable;
3075dda8fa3SYu Zhang }
3085dda8fa3SYu Zhang
3095dda8fa3SYu Zhang /* Mappable graphic memory ballooning */
310381b943bSChris Wilson if (mappable_base) {
311625d988aSChris Wilson ret = vgt_balloon_space(ggtt, &bl_info.space[0],
312381b943bSChris Wilson 0, mappable_base);
3135dda8fa3SYu Zhang
3145dda8fa3SYu Zhang if (ret)
315ff8f7975SWeinan Li goto err_upon_unmappable;
3165dda8fa3SYu Zhang }
3175dda8fa3SYu Zhang
31872e96d64SJoonas Lahtinen if (mappable_end < ggtt->mappable_end) {
319625d988aSChris Wilson ret = vgt_balloon_space(ggtt, &bl_info.space[1],
320625d988aSChris Wilson mappable_end, ggtt->mappable_end);
3215dda8fa3SYu Zhang
3225dda8fa3SYu Zhang if (ret)
323ff8f7975SWeinan Li goto err_below_mappable;
3245dda8fa3SYu Zhang }
3255dda8fa3SYu Zhang
326aee2eeebSWambui Karuga drm_info(&dev_priv->drm, "VGT balloon successfully\n");
3275dda8fa3SYu Zhang return 0;
3285dda8fa3SYu Zhang
329ff8f7975SWeinan Li err_below_mappable:
330ff8f7975SWeinan Li vgt_deballoon_space(ggtt, &bl_info.space[0]);
331ff8f7975SWeinan Li err_upon_unmappable:
332ff8f7975SWeinan Li vgt_deballoon_space(ggtt, &bl_info.space[3]);
333ff8f7975SWeinan Li err_upon_mappable:
334ff8f7975SWeinan Li vgt_deballoon_space(ggtt, &bl_info.space[2]);
3355dda8fa3SYu Zhang err:
336aee2eeebSWambui Karuga drm_err(&dev_priv->drm, "VGT balloon fail\n");
3375dda8fa3SYu Zhang return ret;
3385dda8fa3SYu Zhang }
339