root/drivers/gpu/drm/i915/gvt/aperture_gm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. alloc_gm
  2. alloc_vgpu_gm
  3. free_vgpu_gm
  4. intel_vgpu_write_fence
  5. _clear_vgpu_fence
  6. free_vgpu_fence
  7. alloc_vgpu_fence
  8. free_resource
  9. alloc_resource
  10. intel_vgpu_free_resource
  11. intel_vgpu_reset_resource
  12. intel_vgpu_alloc_resource

   1 /*
   2  * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice (including the next
  12  * paragraph) shall be included in all copies or substantial portions of the
  13  * Software.
  14  *
  15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21  * SOFTWARE.
  22  *
  23  * Authors:
  24  *    Kevin Tian <kevin.tian@intel.com>
  25  *    Dexuan Cui
  26  *
  27  * Contributors:
  28  *    Pei Zhang <pei.zhang@intel.com>
  29  *    Min He <min.he@intel.com>
  30  *    Niu Bing <bing.niu@intel.com>
  31  *    Yulei Zhang <yulei.zhang@intel.com>
  32  *    Zhenyu Wang <zhenyuw@linux.intel.com>
  33  *    Zhi Wang <zhi.a.wang@intel.com>
  34  *
  35  */
  36 
  37 #include "i915_drv.h"
  38 #include "i915_gem_fence_reg.h"
  39 #include "gvt.h"
  40 
  41 static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
  42 {
  43         struct intel_gvt *gvt = vgpu->gvt;
  44         struct drm_i915_private *dev_priv = gvt->dev_priv;
  45         unsigned int flags;
  46         u64 start, end, size;
  47         struct drm_mm_node *node;
  48         int ret;
  49 
  50         if (high_gm) {
  51                 node = &vgpu->gm.high_gm_node;
  52                 size = vgpu_hidden_sz(vgpu);
  53                 start = ALIGN(gvt_hidden_gmadr_base(gvt), I915_GTT_PAGE_SIZE);
  54                 end = ALIGN(gvt_hidden_gmadr_end(gvt), I915_GTT_PAGE_SIZE);
  55                 flags = PIN_HIGH;
  56         } else {
  57                 node = &vgpu->gm.low_gm_node;
  58                 size = vgpu_aperture_sz(vgpu);
  59                 start = ALIGN(gvt_aperture_gmadr_base(gvt), I915_GTT_PAGE_SIZE);
  60                 end = ALIGN(gvt_aperture_gmadr_end(gvt), I915_GTT_PAGE_SIZE);
  61                 flags = PIN_MAPPABLE;
  62         }
  63 
  64         mutex_lock(&dev_priv->drm.struct_mutex);
  65         mmio_hw_access_pre(dev_priv);
  66         ret = i915_gem_gtt_insert(&dev_priv->ggtt.vm, node,
  67                                   size, I915_GTT_PAGE_SIZE,
  68                                   I915_COLOR_UNEVICTABLE,
  69                                   start, end, flags);
  70         mmio_hw_access_post(dev_priv);
  71         mutex_unlock(&dev_priv->drm.struct_mutex);
  72         if (ret)
  73                 gvt_err("fail to alloc %s gm space from host\n",
  74                         high_gm ? "high" : "low");
  75 
  76         return ret;
  77 }
  78 
  79 static int alloc_vgpu_gm(struct intel_vgpu *vgpu)
  80 {
  81         struct intel_gvt *gvt = vgpu->gvt;
  82         struct drm_i915_private *dev_priv = gvt->dev_priv;
  83         int ret;
  84 
  85         ret = alloc_gm(vgpu, false);
  86         if (ret)
  87                 return ret;
  88 
  89         ret = alloc_gm(vgpu, true);
  90         if (ret)
  91                 goto out_free_aperture;
  92 
  93         gvt_dbg_core("vgpu%d: alloc low GM start %llx size %llx\n", vgpu->id,
  94                      vgpu_aperture_offset(vgpu), vgpu_aperture_sz(vgpu));
  95 
  96         gvt_dbg_core("vgpu%d: alloc high GM start %llx size %llx\n", vgpu->id,
  97                      vgpu_hidden_offset(vgpu), vgpu_hidden_sz(vgpu));
  98 
  99         return 0;
 100 out_free_aperture:
 101         mutex_lock(&dev_priv->drm.struct_mutex);
 102         drm_mm_remove_node(&vgpu->gm.low_gm_node);
 103         mutex_unlock(&dev_priv->drm.struct_mutex);
 104         return ret;
 105 }
 106 
 107 static void free_vgpu_gm(struct intel_vgpu *vgpu)
 108 {
 109         struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
 110 
 111         mutex_lock(&dev_priv->drm.struct_mutex);
 112         drm_mm_remove_node(&vgpu->gm.low_gm_node);
 113         drm_mm_remove_node(&vgpu->gm.high_gm_node);
 114         mutex_unlock(&dev_priv->drm.struct_mutex);
 115 }
 116 
 117 /**
 118  * intel_vgpu_write_fence - write fence registers owned by a vGPU
 119  * @vgpu: vGPU instance
 120  * @fence: vGPU fence register number
 121  * @value: Fence register value to be written
 122  *
 123  * This function is used to write fence registers owned by a vGPU. The vGPU
 124  * fence register number will be translated into HW fence register number.
 125  *
 126  */
 127 void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
 128                 u32 fence, u64 value)
 129 {
 130         struct intel_gvt *gvt = vgpu->gvt;
 131         struct drm_i915_private *dev_priv = gvt->dev_priv;
 132         struct i915_fence_reg *reg;
 133         i915_reg_t fence_reg_lo, fence_reg_hi;
 134 
 135         assert_rpm_wakelock_held(&dev_priv->runtime_pm);
 136 
 137         if (WARN_ON(fence >= vgpu_fence_sz(vgpu)))
 138                 return;
 139 
 140         reg = vgpu->fence.regs[fence];
 141         if (WARN_ON(!reg))
 142                 return;
 143 
 144         fence_reg_lo = FENCE_REG_GEN6_LO(reg->id);
 145         fence_reg_hi = FENCE_REG_GEN6_HI(reg->id);
 146 
 147         I915_WRITE(fence_reg_lo, 0);
 148         POSTING_READ(fence_reg_lo);
 149 
 150         I915_WRITE(fence_reg_hi, upper_32_bits(value));
 151         I915_WRITE(fence_reg_lo, lower_32_bits(value));
 152         POSTING_READ(fence_reg_lo);
 153 }
 154 
 155 static void _clear_vgpu_fence(struct intel_vgpu *vgpu)
 156 {
 157         int i;
 158 
 159         for (i = 0; i < vgpu_fence_sz(vgpu); i++)
 160                 intel_vgpu_write_fence(vgpu, i, 0);
 161 }
 162 
 163 static void free_vgpu_fence(struct intel_vgpu *vgpu)
 164 {
 165         struct intel_gvt *gvt = vgpu->gvt;
 166         struct drm_i915_private *dev_priv = gvt->dev_priv;
 167         struct i915_fence_reg *reg;
 168         u32 i;
 169 
 170         if (WARN_ON(!vgpu_fence_sz(vgpu)))
 171                 return;
 172 
 173         intel_runtime_pm_get(&dev_priv->runtime_pm);
 174 
 175         mutex_lock(&dev_priv->ggtt.vm.mutex);
 176         _clear_vgpu_fence(vgpu);
 177         for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
 178                 reg = vgpu->fence.regs[i];
 179                 i915_unreserve_fence(reg);
 180                 vgpu->fence.regs[i] = NULL;
 181         }
 182         mutex_unlock(&dev_priv->ggtt.vm.mutex);
 183 
 184         intel_runtime_pm_put_unchecked(&dev_priv->runtime_pm);
 185 }
 186 
 187 static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
 188 {
 189         struct intel_gvt *gvt = vgpu->gvt;
 190         struct drm_i915_private *dev_priv = gvt->dev_priv;
 191         struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
 192         struct i915_fence_reg *reg;
 193         int i;
 194 
 195         intel_runtime_pm_get(rpm);
 196 
 197         /* Request fences from host */
 198         mutex_lock(&dev_priv->ggtt.vm.mutex);
 199 
 200         for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
 201                 reg = i915_reserve_fence(dev_priv);
 202                 if (IS_ERR(reg))
 203                         goto out_free_fence;
 204 
 205                 vgpu->fence.regs[i] = reg;
 206         }
 207 
 208         _clear_vgpu_fence(vgpu);
 209 
 210         mutex_unlock(&dev_priv->ggtt.vm.mutex);
 211         intel_runtime_pm_put_unchecked(rpm);
 212         return 0;
 213 out_free_fence:
 214         gvt_vgpu_err("Failed to alloc fences\n");
 215         /* Return fences to host, if fail */
 216         for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
 217                 reg = vgpu->fence.regs[i];
 218                 if (!reg)
 219                         continue;
 220                 i915_unreserve_fence(reg);
 221                 vgpu->fence.regs[i] = NULL;
 222         }
 223         mutex_unlock(&dev_priv->ggtt.vm.mutex);
 224         intel_runtime_pm_put_unchecked(rpm);
 225         return -ENOSPC;
 226 }
 227 
 228 static void free_resource(struct intel_vgpu *vgpu)
 229 {
 230         struct intel_gvt *gvt = vgpu->gvt;
 231 
 232         gvt->gm.vgpu_allocated_low_gm_size -= vgpu_aperture_sz(vgpu);
 233         gvt->gm.vgpu_allocated_high_gm_size -= vgpu_hidden_sz(vgpu);
 234         gvt->fence.vgpu_allocated_fence_num -= vgpu_fence_sz(vgpu);
 235 }
 236 
 237 static int alloc_resource(struct intel_vgpu *vgpu,
 238                 struct intel_vgpu_creation_params *param)
 239 {
 240         struct intel_gvt *gvt = vgpu->gvt;
 241         unsigned long request, avail, max, taken;
 242         const char *item;
 243 
 244         if (!param->low_gm_sz || !param->high_gm_sz || !param->fence_sz) {
 245                 gvt_vgpu_err("Invalid vGPU creation params\n");
 246                 return -EINVAL;
 247         }
 248 
 249         item = "low GM space";
 250         max = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE;
 251         taken = gvt->gm.vgpu_allocated_low_gm_size;
 252         avail = max - taken;
 253         request = MB_TO_BYTES(param->low_gm_sz);
 254 
 255         if (request > avail)
 256                 goto no_enough_resource;
 257 
 258         vgpu_aperture_sz(vgpu) = ALIGN(request, I915_GTT_PAGE_SIZE);
 259 
 260         item = "high GM space";
 261         max = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE;
 262         taken = gvt->gm.vgpu_allocated_high_gm_size;
 263         avail = max - taken;
 264         request = MB_TO_BYTES(param->high_gm_sz);
 265 
 266         if (request > avail)
 267                 goto no_enough_resource;
 268 
 269         vgpu_hidden_sz(vgpu) = ALIGN(request, I915_GTT_PAGE_SIZE);
 270 
 271         item = "fence";
 272         max = gvt_fence_sz(gvt) - HOST_FENCE;
 273         taken = gvt->fence.vgpu_allocated_fence_num;
 274         avail = max - taken;
 275         request = param->fence_sz;
 276 
 277         if (request > avail)
 278                 goto no_enough_resource;
 279 
 280         vgpu_fence_sz(vgpu) = request;
 281 
 282         gvt->gm.vgpu_allocated_low_gm_size += MB_TO_BYTES(param->low_gm_sz);
 283         gvt->gm.vgpu_allocated_high_gm_size += MB_TO_BYTES(param->high_gm_sz);
 284         gvt->fence.vgpu_allocated_fence_num += param->fence_sz;
 285         return 0;
 286 
 287 no_enough_resource:
 288         gvt_err("fail to allocate resource %s\n", item);
 289         gvt_err("request %luMB avail %luMB max %luMB taken %luMB\n",
 290                 BYTES_TO_MB(request), BYTES_TO_MB(avail),
 291                 BYTES_TO_MB(max), BYTES_TO_MB(taken));
 292         return -ENOSPC;
 293 }
 294 
 295 /**
 296  * inte_gvt_free_vgpu_resource - free HW resource owned by a vGPU
 297  * @vgpu: a vGPU
 298  *
 299  * This function is used to free the HW resource owned by a vGPU.
 300  *
 301  */
 302 void intel_vgpu_free_resource(struct intel_vgpu *vgpu)
 303 {
 304         free_vgpu_gm(vgpu);
 305         free_vgpu_fence(vgpu);
 306         free_resource(vgpu);
 307 }
 308 
 309 /**
 310  * intel_vgpu_reset_resource - reset resource state owned by a vGPU
 311  * @vgpu: a vGPU
 312  *
 313  * This function is used to reset resource state owned by a vGPU.
 314  *
 315  */
 316 void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
 317 {
 318         struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
 319 
 320         intel_runtime_pm_get(&dev_priv->runtime_pm);
 321         _clear_vgpu_fence(vgpu);
 322         intel_runtime_pm_put_unchecked(&dev_priv->runtime_pm);
 323 }
 324 
 325 /**
 326  * intel_alloc_vgpu_resource - allocate HW resource for a vGPU
 327  * @vgpu: vGPU
 328  * @param: vGPU creation params
 329  *
 330  * This function is used to allocate HW resource for a vGPU. User specifies
 331  * the resource configuration through the creation params.
 332  *
 333  * Returns:
 334  * zero on success, negative error code if failed.
 335  *
 336  */
 337 int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu,
 338                 struct intel_vgpu_creation_params *param)
 339 {
 340         int ret;
 341 
 342         ret = alloc_resource(vgpu, param);
 343         if (ret)
 344                 return ret;
 345 
 346         ret = alloc_vgpu_gm(vgpu);
 347         if (ret)
 348                 goto out_free_resource;
 349 
 350         ret = alloc_vgpu_fence(vgpu);
 351         if (ret)
 352                 goto out_free_vgpu_gm;
 353 
 354         return 0;
 355 
 356 out_free_vgpu_gm:
 357         free_vgpu_gm(vgpu);
 358 out_free_resource:
 359         free_resource(vgpu);
 360         return ret;
 361 }

/* [<][>][^][v][top][bottom][index][help] */