.. | .. |
---|
31 | 31 | */ |
---|
32 | 32 | |
---|
33 | 33 | #include <linux/types.h> |
---|
34 | | -#include <xen/xen.h> |
---|
35 | 34 | #include <linux/kthread.h> |
---|
36 | 35 | |
---|
37 | 36 | #include "i915_drv.h" |
---|
| 37 | +#include "intel_gvt.h" |
---|
38 | 38 | #include "gvt.h" |
---|
39 | 39 | #include <linux/vfio.h> |
---|
40 | 40 | #include <linux/mdev.h> |
---|
.. | .. |
---|
49 | 49 | static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt, |
---|
50 | 50 | const char *name) |
---|
51 | 51 | { |
---|
| 52 | + const char *driver_name = |
---|
| 53 | + dev_driver_string(&gvt->gt->i915->drm.pdev->dev); |
---|
52 | 54 | int i; |
---|
53 | | - struct intel_vgpu_type *t; |
---|
54 | | - const char *driver_name = dev_driver_string( |
---|
55 | | - &gvt->dev_priv->drm.pdev->dev); |
---|
56 | 55 | |
---|
| 56 | + name += strlen(driver_name) + 1; |
---|
57 | 57 | for (i = 0; i < gvt->num_types; i++) { |
---|
58 | | - t = &gvt->types[i]; |
---|
59 | | - if (!strncmp(t->name, name + strlen(driver_name) + 1, |
---|
60 | | - sizeof(t->name))) |
---|
| 58 | + struct intel_vgpu_type *t = &gvt->types[i]; |
---|
| 59 | + |
---|
| 60 | + if (!strncmp(t->name, name, sizeof(t->name))) |
---|
61 | 61 | return t; |
---|
62 | 62 | } |
---|
63 | 63 | |
---|
.. | .. |
---|
120 | 120 | [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL, |
---|
121 | 121 | }; |
---|
122 | 122 | |
---|
123 | | -static bool intel_get_gvt_attrs(struct attribute ***type_attrs, |
---|
124 | | - struct attribute_group ***intel_vgpu_type_groups) |
---|
| 123 | +static bool intel_get_gvt_attrs(struct attribute_group ***intel_vgpu_type_groups) |
---|
125 | 124 | { |
---|
126 | | - *type_attrs = gvt_type_attrs; |
---|
127 | 125 | *intel_vgpu_type_groups = gvt_vgpu_type_groups; |
---|
128 | 126 | return true; |
---|
129 | 127 | } |
---|
.. | .. |
---|
185 | 183 | .vgpu_query_plane = intel_vgpu_query_plane, |
---|
186 | 184 | .vgpu_get_dmabuf = intel_vgpu_get_dmabuf, |
---|
187 | 185 | .write_protect_handler = intel_vgpu_page_track_handler, |
---|
| 186 | + .emulate_hotplug = intel_vgpu_emulate_hotplug, |
---|
188 | 187 | }; |
---|
189 | | - |
---|
190 | | -/** |
---|
191 | | - * intel_gvt_init_host - Load MPT modules and detect if we're running in host |
---|
192 | | - * @gvt: intel gvt device |
---|
193 | | - * |
---|
194 | | - * This function is called at the driver loading stage. If failed to find a |
---|
195 | | - * loadable MPT module or detect currently we're running in a VM, then GVT-g |
---|
196 | | - * will be disabled |
---|
197 | | - * |
---|
198 | | - * Returns: |
---|
199 | | - * Zero on success, negative error code if failed. |
---|
200 | | - * |
---|
201 | | - */ |
---|
202 | | -int intel_gvt_init_host(void) |
---|
203 | | -{ |
---|
204 | | - if (intel_gvt_host.initialized) |
---|
205 | | - return 0; |
---|
206 | | - |
---|
207 | | - /* Xen DOM U */ |
---|
208 | | - if (xen_domain() && !xen_initial_domain()) |
---|
209 | | - return -ENODEV; |
---|
210 | | - |
---|
211 | | - /* Try to load MPT modules for hypervisors */ |
---|
212 | | - if (xen_initial_domain()) { |
---|
213 | | - /* In Xen dom0 */ |
---|
214 | | - intel_gvt_host.mpt = try_then_request_module( |
---|
215 | | - symbol_get(xengt_mpt), "xengt"); |
---|
216 | | - intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_XEN; |
---|
217 | | - } else { |
---|
218 | | -#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT) |
---|
219 | | - /* not in Xen. Try KVMGT */ |
---|
220 | | - intel_gvt_host.mpt = try_then_request_module( |
---|
221 | | - symbol_get(kvmgt_mpt), "kvmgt"); |
---|
222 | | - intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_KVM; |
---|
223 | | -#endif |
---|
224 | | - } |
---|
225 | | - |
---|
226 | | - /* Fail to load MPT modules - bail out */ |
---|
227 | | - if (!intel_gvt_host.mpt) |
---|
228 | | - return -EINVAL; |
---|
229 | | - |
---|
230 | | - gvt_dbg_core("Running with hypervisor %s in host mode\n", |
---|
231 | | - supported_hypervisors[intel_gvt_host.hypervisor_type]); |
---|
232 | | - |
---|
233 | | - intel_gvt_host.initialized = true; |
---|
234 | | - return 0; |
---|
235 | | -} |
---|
236 | 188 | |
---|
237 | 189 | static void init_device_info(struct intel_gvt *gvt) |
---|
238 | 190 | { |
---|
239 | 191 | struct intel_gvt_device_info *info = &gvt->device_info; |
---|
240 | | - struct pci_dev *pdev = gvt->dev_priv->drm.pdev; |
---|
| 192 | + struct pci_dev *pdev = gvt->gt->i915->drm.pdev; |
---|
241 | 193 | |
---|
242 | 194 | info->max_support_vgpus = 8; |
---|
243 | 195 | info->cfg_space_size = PCI_CFG_SPACE_EXP_SIZE; |
---|
.. | .. |
---|
303 | 255 | |
---|
304 | 256 | /** |
---|
305 | 257 | * intel_gvt_clean_device - clean a GVT device |
---|
306 | | - * @gvt: intel gvt device |
---|
| 258 | + * @i915: i915 private |
---|
307 | 259 | * |
---|
308 | 260 | * This function is called at the driver unloading stage, to free the |
---|
309 | 261 | * resources owned by a GVT device. |
---|
310 | 262 | * |
---|
311 | 263 | */ |
---|
312 | | -void intel_gvt_clean_device(struct drm_i915_private *dev_priv) |
---|
| 264 | +void intel_gvt_clean_device(struct drm_i915_private *i915) |
---|
313 | 265 | { |
---|
314 | | - struct intel_gvt *gvt = to_gvt(dev_priv); |
---|
| 266 | + struct intel_gvt *gvt = fetch_and_zero(&i915->gvt); |
---|
315 | 267 | |
---|
316 | | - if (WARN_ON(!gvt)) |
---|
| 268 | + if (drm_WARN_ON(&i915->drm, !gvt)) |
---|
317 | 269 | return; |
---|
318 | 270 | |
---|
319 | 271 | intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu); |
---|
320 | | - intel_gvt_hypervisor_host_exit(&dev_priv->drm.pdev->dev, gvt); |
---|
321 | 272 | intel_gvt_cleanup_vgpu_type_groups(gvt); |
---|
322 | 273 | intel_gvt_clean_vgpu_types(gvt); |
---|
323 | 274 | |
---|
.. | .. |
---|
332 | 283 | intel_gvt_clean_mmio_info(gvt); |
---|
333 | 284 | idr_destroy(&gvt->vgpu_idr); |
---|
334 | 285 | |
---|
335 | | - kfree(dev_priv->gvt); |
---|
336 | | - dev_priv->gvt = NULL; |
---|
| 286 | + kfree(i915->gvt); |
---|
337 | 287 | } |
---|
338 | 288 | |
---|
339 | 289 | /** |
---|
340 | 290 | * intel_gvt_init_device - initialize a GVT device |
---|
341 | | - * @dev_priv: drm i915 private data |
---|
| 291 | + * @i915: drm i915 private data |
---|
342 | 292 | * |
---|
343 | 293 | * This function is called at the initialization stage, to initialize |
---|
344 | 294 | * necessary GVT components. |
---|
.. | .. |
---|
347 | 297 | * Zero on success, negative error code if failed. |
---|
348 | 298 | * |
---|
349 | 299 | */ |
---|
350 | | -int intel_gvt_init_device(struct drm_i915_private *dev_priv) |
---|
| 300 | +int intel_gvt_init_device(struct drm_i915_private *i915) |
---|
351 | 301 | { |
---|
352 | 302 | struct intel_gvt *gvt; |
---|
353 | 303 | struct intel_vgpu *vgpu; |
---|
354 | 304 | int ret; |
---|
355 | 305 | |
---|
356 | | - /* |
---|
357 | | - * Cannot initialize GVT device without intel_gvt_host gets |
---|
358 | | - * initialized first. |
---|
359 | | - */ |
---|
360 | | - if (WARN_ON(!intel_gvt_host.initialized)) |
---|
361 | | - return -EINVAL; |
---|
362 | | - |
---|
363 | | - if (WARN_ON(dev_priv->gvt)) |
---|
| 306 | + if (drm_WARN_ON(&i915->drm, i915->gvt)) |
---|
364 | 307 | return -EEXIST; |
---|
365 | 308 | |
---|
366 | 309 | gvt = kzalloc(sizeof(struct intel_gvt), GFP_KERNEL); |
---|
.. | .. |
---|
373 | 316 | spin_lock_init(&gvt->scheduler.mmio_context_lock); |
---|
374 | 317 | mutex_init(&gvt->lock); |
---|
375 | 318 | mutex_init(&gvt->sched_lock); |
---|
376 | | - gvt->dev_priv = dev_priv; |
---|
| 319 | + gvt->gt = &i915->gt; |
---|
| 320 | + i915->gvt = gvt; |
---|
377 | 321 | |
---|
378 | 322 | init_device_info(gvt); |
---|
379 | 323 | |
---|
.. | .. |
---|
421 | 365 | goto out_clean_types; |
---|
422 | 366 | } |
---|
423 | 367 | |
---|
424 | | - ret = intel_gvt_hypervisor_host_init(&dev_priv->drm.pdev->dev, gvt, |
---|
425 | | - &intel_gvt_ops); |
---|
426 | | - if (ret) { |
---|
427 | | - gvt_err("failed to register gvt-g host device: %d\n", ret); |
---|
428 | | - goto out_clean_types; |
---|
429 | | - } |
---|
430 | | - |
---|
431 | 368 | vgpu = intel_gvt_create_idle_vgpu(gvt); |
---|
432 | 369 | if (IS_ERR(vgpu)) { |
---|
433 | 370 | ret = PTR_ERR(vgpu); |
---|
.. | .. |
---|
436 | 373 | } |
---|
437 | 374 | gvt->idle_vgpu = vgpu; |
---|
438 | 375 | |
---|
439 | | - ret = intel_gvt_debugfs_init(gvt); |
---|
440 | | - if (ret) |
---|
441 | | - gvt_err("debugfs registeration failed, go on.\n"); |
---|
| 376 | + intel_gvt_debugfs_init(gvt); |
---|
442 | 377 | |
---|
443 | 378 | gvt_dbg_core("gvt device initialization is done\n"); |
---|
444 | | - dev_priv->gvt = gvt; |
---|
| 379 | + intel_gvt_host.dev = &i915->drm.pdev->dev; |
---|
| 380 | + intel_gvt_host.initialized = true; |
---|
445 | 381 | return 0; |
---|
446 | 382 | |
---|
447 | 383 | out_clean_types: |
---|
.. | .. |
---|
465 | 401 | out_clean_idr: |
---|
466 | 402 | idr_destroy(&gvt->vgpu_idr); |
---|
467 | 403 | kfree(gvt); |
---|
| 404 | + i915->gvt = NULL; |
---|
468 | 405 | return ret; |
---|
469 | 406 | } |
---|
470 | 407 | |
---|
471 | | -#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT) |
---|
472 | | -MODULE_SOFTDEP("pre: kvmgt"); |
---|
473 | | -#endif |
---|
| 408 | +int |
---|
| 409 | +intel_gvt_pm_resume(struct intel_gvt *gvt) |
---|
| 410 | +{ |
---|
| 411 | + intel_gvt_restore_fence(gvt); |
---|
| 412 | + intel_gvt_restore_mmio(gvt); |
---|
| 413 | + intel_gvt_restore_ggtt(gvt); |
---|
| 414 | + return 0; |
---|
| 415 | +} |
---|
| 416 | + |
---|
| 417 | +int |
---|
| 418 | +intel_gvt_register_hypervisor(struct intel_gvt_mpt *m) |
---|
| 419 | +{ |
---|
| 420 | + int ret; |
---|
| 421 | + void *gvt; |
---|
| 422 | + |
---|
| 423 | + if (!intel_gvt_host.initialized) |
---|
| 424 | + return -ENODEV; |
---|
| 425 | + |
---|
| 426 | + if (m->type != INTEL_GVT_HYPERVISOR_KVM && |
---|
| 427 | + m->type != INTEL_GVT_HYPERVISOR_XEN) |
---|
| 428 | + return -EINVAL; |
---|
| 429 | + |
---|
| 430 | + /* Get a reference for device model module */ |
---|
| 431 | + if (!try_module_get(THIS_MODULE)) |
---|
| 432 | + return -ENODEV; |
---|
| 433 | + |
---|
| 434 | + intel_gvt_host.mpt = m; |
---|
| 435 | + intel_gvt_host.hypervisor_type = m->type; |
---|
| 436 | + gvt = (void *)kdev_to_i915(intel_gvt_host.dev)->gvt; |
---|
| 437 | + |
---|
| 438 | + ret = intel_gvt_hypervisor_host_init(intel_gvt_host.dev, gvt, |
---|
| 439 | + &intel_gvt_ops); |
---|
| 440 | + if (ret < 0) { |
---|
| 441 | + gvt_err("Failed to init %s hypervisor module\n", |
---|
| 442 | + supported_hypervisors[intel_gvt_host.hypervisor_type]); |
---|
| 443 | + module_put(THIS_MODULE); |
---|
| 444 | + return -ENODEV; |
---|
| 445 | + } |
---|
| 446 | + gvt_dbg_core("Running with hypervisor %s in host mode\n", |
---|
| 447 | + supported_hypervisors[intel_gvt_host.hypervisor_type]); |
---|
| 448 | + return 0; |
---|
| 449 | +} |
---|
| 450 | +EXPORT_SYMBOL_GPL(intel_gvt_register_hypervisor); |
---|
| 451 | + |
---|
| 452 | +void |
---|
| 453 | +intel_gvt_unregister_hypervisor(void) |
---|
| 454 | +{ |
---|
| 455 | + intel_gvt_hypervisor_host_exit(intel_gvt_host.dev); |
---|
| 456 | + module_put(THIS_MODULE); |
---|
| 457 | +} |
---|
| 458 | +EXPORT_SYMBOL_GPL(intel_gvt_unregister_hypervisor); |
---|