Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'drm-intel-next-2017-12-14' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

- Fix documentation build issues (Randy, Markus)
- Fix timestamp frequency calculation for perf on CNL (Lionel)
- New DMC firmware for Skylake (Anusha)
- GTT flush fixes and other GGTT write track and refactors (Chris)
- Taint kernel when GPU reset fails (Chris)
- Display workarounds organization (Lucas)
- GuC and HuC initialization clean-up and fixes (Michal)
- Other fixes around GuC submission (Michal)
- Execlist clean-ups like caching ELSP reg offset and improving log readability (Chri\
s)
- Many other improvements on our logs and dumps (Chris)
- Restore GT performance in headless mode with DMC loaded (Tvrtko)
- Stop updating legacy fb parameters since FBC is not using anymore (Daniel)
- More selftest improvements (Chris)
- Preemption fixes and improvements (Chris)
- x86/early-quirks improvements for Intel graphics stolen memory. (Joonas, Matthew)
- Other improvements on Stolen Memory code to be resource centric. (Matthew)
- Improvements and fixes on fence allocation/release (Chris).

GVT:

- fixes for two coverity scan errors (Colin)
- mmio switch code refine (Changbin)
- more virtual display dmabuf fixes (Tina/Gustavo)
- misc cleanups (Pei)
- VFIO mdev display dmabuf interface and gvt support (Tina)
- VFIO mdev opregion support/fixes (Tina/Xiong/Chris)
- workload scheduling optimization (Changbin)
- preemption fix and temporal workaround (Zhenyu)
- and misc fixes after refactor (Chris)

* tag 'drm-intel-next-2017-12-14' of git://anongit.freedesktop.org/drm/drm-intel: (87 commits)
drm/i915: Update DRIVER_DATE to 20171214
drm/i915: properly init lockdep class
drm/i915: Show engine state when hangcheck detects a stall
drm/i915: make CS frequency read support missing more obvious
drm/i915/guc: Extract doorbell verification into a function
drm/i915/guc: Extract clients allocation to submission_init
drm/i915/guc: Extract doorbell creation from client allocation
drm/i915/guc: Call invalidate after changing the vfunc
drm/i915/guc: Extract guc_init from guc_init_hw
drm/i915/guc: Move GuC workqueue allocations outside of the mutex
drm/i915/guc: Move shared data allocation away from submission path
drm/i915: Unwind i915_gem_init() failure
drm/i915: Ratelimit request allocation under oom
drm/i915: Allow fence allocations to fail
drm/i915: Mark up potential allocation paths within i915_sw_fence as might_sleep
drm/i915: Don't check #active_requests from i915_gem_wait_for_idle()
drm/i915/fence: Use rcu to defer freeing of irq_work
drm/i915: Dump the engine state before declaring wedged from wait_for_engines()
drm/i915: Bump timeout for wait_for_engines()
drm/i915: Downgrade misleading "Memory usable" message
...

+3108 -1314
+1 -4
Documentation/gpu/i915.rst
··· 341 341 GuC-specific firmware loader 342 342 ---------------------------- 343 343 344 - .. kernel-doc:: drivers/gpu/drm/i915/intel_guc_loader.c 345 - :doc: GuC-specific firmware loader 346 - 347 - .. kernel-doc:: drivers/gpu/drm/i915/intel_guc_loader.c 344 + .. kernel-doc:: drivers/gpu/drm/i915/intel_guc_fw.c 348 345 :internal: 349 346 350 347 GuC-based command submission
+47 -39
arch/x86/kernel/early-quirks.c
··· 243 243 #define KB(x) ((x) * 1024UL) 244 244 #define MB(x) (KB (KB (x))) 245 245 246 - static size_t __init i830_tseg_size(void) 246 + static resource_size_t __init i830_tseg_size(void) 247 247 { 248 248 u8 esmramc = read_pci_config_byte(0, 0, 0, I830_ESMRAMC); 249 249 ··· 256 256 return KB(512); 257 257 } 258 258 259 - static size_t __init i845_tseg_size(void) 259 + static resource_size_t __init i845_tseg_size(void) 260 260 { 261 261 u8 esmramc = read_pci_config_byte(0, 0, 0, I845_ESMRAMC); 262 262 u8 tseg_size = esmramc & I845_TSEG_SIZE_MASK; ··· 273 273 return 0; 274 274 } 275 275 276 - static size_t __init i85x_tseg_size(void) 276 + static resource_size_t __init i85x_tseg_size(void) 277 277 { 278 278 u8 esmramc = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC); 279 279 ··· 283 283 return MB(1); 284 284 } 285 285 286 - static size_t __init i830_mem_size(void) 286 + static resource_size_t __init i830_mem_size(void) 287 287 { 288 288 return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32); 289 289 } 290 290 291 - static size_t __init i85x_mem_size(void) 291 + static resource_size_t __init i85x_mem_size(void) 292 292 { 293 293 return read_pci_config_byte(0, 0, 1, I85X_DRB3) * MB(32); 294 294 } ··· 297 297 * On 830/845/85x the stolen memory base isn't available in any 298 298 * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size. 299 299 */ 300 - static phys_addr_t __init i830_stolen_base(int num, int slot, int func, 301 - size_t stolen_size) 300 + static resource_size_t __init i830_stolen_base(int num, int slot, int func, 301 + resource_size_t stolen_size) 302 302 { 303 - return (phys_addr_t)i830_mem_size() - i830_tseg_size() - stolen_size; 303 + return i830_mem_size() - i830_tseg_size() - stolen_size; 304 304 } 305 305 306 - static phys_addr_t __init i845_stolen_base(int num, int slot, int func, 307 - size_t stolen_size) 306 + static resource_size_t __init i845_stolen_base(int num, int slot, int func, 307 + resource_size_t stolen_size) 308 308 { 309 - return (phys_addr_t)i830_mem_size() - i845_tseg_size() - stolen_size; 309 + return i830_mem_size() - i845_tseg_size() - stolen_size; 310 310 } 311 311 312 - static phys_addr_t __init i85x_stolen_base(int num, int slot, int func, 313 - size_t stolen_size) 312 + static resource_size_t __init i85x_stolen_base(int num, int slot, int func, 313 + resource_size_t stolen_size) 314 314 { 315 - return (phys_addr_t)i85x_mem_size() - i85x_tseg_size() - stolen_size; 315 + return i85x_mem_size() - i85x_tseg_size() - stolen_size; 316 316 } 317 317 318 - static phys_addr_t __init i865_stolen_base(int num, int slot, int func, 319 - size_t stolen_size) 318 + static resource_size_t __init i865_stolen_base(int num, int slot, int func, 319 + resource_size_t stolen_size) 320 320 { 321 321 u16 toud = 0; 322 322 323 323 toud = read_pci_config_16(0, 0, 0, I865_TOUD); 324 324 325 - return (phys_addr_t)(toud << 16) + i845_tseg_size(); 325 + return toud * KB(64) + i845_tseg_size(); 326 326 } 327 327 328 - static phys_addr_t __init gen3_stolen_base(int num, int slot, int func, 329 - size_t stolen_size) 328 + static resource_size_t __init gen3_stolen_base(int num, int slot, int func, 329 + resource_size_t stolen_size) 330 330 { 331 331 u32 bsm; 332 332 ··· 337 337 */ 338 338 bsm = read_pci_config(num, slot, func, INTEL_BSM); 339 339 340 - return (phys_addr_t)bsm & INTEL_BSM_MASK; 340 + return bsm & INTEL_BSM_MASK; 341 341 } 342 342 343 - static size_t __init i830_stolen_size(int num, int slot, int func) 343 + static resource_size_t __init i830_stolen_size(int num, int slot, int func) 344 344 { 345 345 u16 gmch_ctrl; 346 346 u16 gms; ··· 361 361 return 0; 362 362 } 363 363 364 - static size_t __init gen3_stolen_size(int num, int slot, int func) 364 + static resource_size_t __init gen3_stolen_size(int num, int slot, int func) 365 365 { 366 366 u16 gmch_ctrl; 367 367 u16 gms; ··· 390 390 return 0; 391 391 } 392 392 393 - static size_t __init gen6_stolen_size(int num, int slot, int func) 393 + static resource_size_t __init gen6_stolen_size(int num, int slot, int func) 394 394 { 395 395 u16 gmch_ctrl; 396 396 u16 gms; ··· 398 398 gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL); 399 399 gms = (gmch_ctrl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK; 400 400 401 - return (size_t)gms * MB(32); 401 + return gms * MB(32); 402 402 } 403 403 404 - static size_t __init gen8_stolen_size(int num, int slot, int func) 404 + static resource_size_t __init gen8_stolen_size(int num, int slot, int func) 405 405 { 406 406 u16 gmch_ctrl; 407 407 u16 gms; ··· 409 409 gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL); 410 410 gms = (gmch_ctrl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK; 411 411 412 - return (size_t)gms * MB(32); 412 + return gms * MB(32); 413 413 } 414 414 415 - static size_t __init chv_stolen_size(int num, int slot, int func) 415 + static resource_size_t __init chv_stolen_size(int num, int slot, int func) 416 416 { 417 417 u16 gmch_ctrl; 418 418 u16 gms; ··· 426 426 * 0x17 to 0x1d: 4MB increments start at 36MB 427 427 */ 428 428 if (gms < 0x11) 429 - return (size_t)gms * MB(32); 429 + return gms * MB(32); 430 430 else if (gms < 0x17) 431 - return (size_t)(gms - 0x11 + 2) * MB(4); 431 + return (gms - 0x11) * MB(4) + MB(8); 432 432 else 433 - return (size_t)(gms - 0x17 + 9) * MB(4); 433 + return (gms - 0x17) * MB(4) + MB(36); 434 434 } 435 435 436 - static size_t __init gen9_stolen_size(int num, int slot, int func) 436 + static resource_size_t __init gen9_stolen_size(int num, int slot, int func) 437 437 { 438 438 u16 gmch_ctrl; 439 439 u16 gms; ··· 444 444 /* 0x0 to 0xef: 32MB increments starting at 0MB */ 445 445 /* 0xf0 to 0xfe: 4MB increments starting at 4MB */ 446 446 if (gms < 0xf0) 447 - return (size_t)gms * MB(32); 447 + return gms * MB(32); 448 448 else 449 - return (size_t)(gms - 0xf0 + 1) * MB(4); 449 + return (gms - 0xf0) * MB(4) + MB(4); 450 450 } 451 451 452 452 struct intel_early_ops { 453 - size_t (*stolen_size)(int num, int slot, int func); 454 - phys_addr_t (*stolen_base)(int num, int slot, int func, size_t size); 453 + resource_size_t (*stolen_size)(int num, int slot, int func); 454 + resource_size_t (*stolen_base)(int num, int slot, int func, 455 + resource_size_t size); 455 456 }; 456 457 457 458 static const struct intel_early_ops i830_early_ops __initconst = { ··· 532 531 INTEL_CNL_IDS(&gen9_early_ops), 533 532 }; 534 533 534 + struct resource intel_graphics_stolen_res __ro_after_init = DEFINE_RES_MEM(0, 0); 535 + EXPORT_SYMBOL(intel_graphics_stolen_res); 536 + 535 537 static void __init 536 538 intel_graphics_stolen(int num, int slot, int func, 537 539 const struct intel_early_ops *early_ops) 538 540 { 539 - phys_addr_t base, end; 540 - size_t size; 541 + resource_size_t base, size; 542 + resource_size_t end; 541 543 542 544 size = early_ops->stolen_size(num, slot, func); 543 545 base = early_ops->stolen_base(num, slot, func, size); ··· 549 545 return; 550 546 551 547 end = base + size - 1; 552 - printk(KERN_INFO "Reserving Intel graphics memory at %pa-%pa\n", 553 - &base, &end); 548 + 549 + intel_graphics_stolen_res.start = base; 550 + intel_graphics_stolen_res.end = end; 551 + 552 + printk(KERN_INFO "Reserving Intel graphics memory at %pR\n", 553 + &intel_graphics_stolen_res); 554 554 555 555 /* Mark this space as reserved */ 556 556 e820__range_add(base, size, E820_TYPE_RESERVED);
+8 -8
drivers/char/agp/intel-gtt.c
··· 80 80 unsigned int needs_dmar : 1; 81 81 phys_addr_t gma_bus_addr; 82 82 /* Size of memory reserved for graphics by the BIOS */ 83 - unsigned int stolen_size; 83 + resource_size_t stolen_size; 84 84 /* Total number of gtt entries. */ 85 85 unsigned int gtt_total_entries; 86 86 /* Part of the gtt that is mappable by the cpu, for those chips where ··· 333 333 writel_relaxed(addr | pte_flags, intel_private.gtt + entry); 334 334 } 335 335 336 - static unsigned int intel_gtt_stolen_size(void) 336 + static resource_size_t intel_gtt_stolen_size(void) 337 337 { 338 338 u16 gmch_ctrl; 339 339 u8 rdct; 340 340 int local = 0; 341 341 static const int ddt[4] = { 0, 16, 32, 64 }; 342 - unsigned int stolen_size = 0; 342 + resource_size_t stolen_size = 0; 343 343 344 344 if (INTEL_GTT_GEN == 1) 345 345 return 0; /* no stolen mem on i81x */ ··· 417 417 } 418 418 419 419 if (stolen_size > 0) { 420 - dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n", 421 - stolen_size / KB(1), local ? "local" : "stolen"); 420 + dev_info(&intel_private.bridge_dev->dev, "detected %lluK %s memory\n", 421 + (u64)stolen_size / KB(1), local ? "local" : "stolen"); 422 422 } else { 423 423 dev_info(&intel_private.bridge_dev->dev, 424 424 "no pre-allocated video memory detected\n"); ··· 872 872 } 873 873 } 874 874 wmb(); 875 + if (intel_private.driver->chipset_flush) 876 + intel_private.driver->chipset_flush(); 875 877 } 876 878 EXPORT_SYMBOL(intel_gtt_insert_sg_entries); 877 879 ··· 1424 1422 EXPORT_SYMBOL(intel_gmch_probe); 1425 1423 1426 1424 void intel_gtt_get(u64 *gtt_total, 1427 - u32 *stolen_size, 1428 1425 phys_addr_t *mappable_base, 1429 - u64 *mappable_end) 1426 + resource_size_t *mappable_end) 1430 1427 { 1431 1428 *gtt_total = intel_private.gtt_total_entries << PAGE_SHIFT; 1432 - *stolen_size = intel_private.stolen_size; 1433 1429 *mappable_base = intel_private.gma_bus_addr; 1434 1430 *mappable_end = intel_private.gtt_mappable_entries << PAGE_SHIFT; 1435 1431 }
+2 -1
drivers/gpu/drm/i915/gvt/Makefile
··· 2 2 GVT_DIR := gvt 3 3 GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ 4 4 interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ 5 - execlist.o scheduler.o sched_policy.o render.o cmd_parser.o debugfs.o 5 + execlist.o scheduler.o sched_policy.o mmio_context.o cmd_parser.o debugfs.o \ 6 + fb_decoder.o dmabuf.o 6 7 7 8 ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) 8 9 i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
+2 -1
drivers/gpu/drm/i915/gvt/cfg_space.c
··· 335 335 case INTEL_GVT_PCI_OPREGION: 336 336 if (WARN_ON(!IS_ALIGNED(offset, 4))) 337 337 return -EINVAL; 338 - ret = intel_vgpu_init_opregion(vgpu, *(u32 *)p_data); 338 + ret = intel_vgpu_opregion_base_write_handler(vgpu, 339 + *(u32 *)p_data); 339 340 if (ret) 340 341 return ret; 341 342
+1 -1
drivers/gpu/drm/i915/gvt/display.c
··· 67 67 return 1; 68 68 } 69 69 70 - static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe) 70 + int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe) 71 71 { 72 72 struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 73 73
+2
drivers/gpu/drm/i915/gvt/display.h
··· 179 179 void intel_vgpu_reset_display(struct intel_vgpu *vgpu); 180 180 void intel_vgpu_clean_display(struct intel_vgpu *vgpu); 181 181 182 + int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe); 183 + 182 184 #endif
+537
drivers/gpu/drm/i915/gvt/dmabuf.c
··· 1 + /* 2 + * Copyright 2017 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 20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 + * DEALINGS IN THE SOFTWARE. 22 + * 23 + * Authors: 24 + * Zhiyuan Lv <zhiyuan.lv@intel.com> 25 + * 26 + * Contributors: 27 + * Xiaoguang Chen 28 + * Tina Zhang <tina.zhang@intel.com> 29 + */ 30 + 31 + #include <linux/dma-buf.h> 32 + #include <drm/drmP.h> 33 + #include <linux/vfio.h> 34 + 35 + #include "i915_drv.h" 36 + #include "gvt.h" 37 + 38 + #define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12)) 39 + 40 + static int vgpu_gem_get_pages( 41 + struct drm_i915_gem_object *obj) 42 + { 43 + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); 44 + struct sg_table *st; 45 + struct scatterlist *sg; 46 + int i, ret; 47 + gen8_pte_t __iomem *gtt_entries; 48 + struct intel_vgpu_fb_info *fb_info; 49 + 50 + fb_info = (struct intel_vgpu_fb_info *)obj->gvt_info; 51 + if (WARN_ON(!fb_info)) 52 + return -ENODEV; 53 + 54 + st = kmalloc(sizeof(*st), GFP_KERNEL); 55 + if (unlikely(!st)) 56 + return -ENOMEM; 57 + 58 + ret = sg_alloc_table(st, fb_info->size, GFP_KERNEL); 59 + if (ret) { 60 + kfree(st); 61 + return ret; 62 + } 63 + gtt_entries = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + 64 + (fb_info->start >> PAGE_SHIFT); 65 + for_each_sg(st->sgl, sg, fb_info->size, i) { 66 + sg->offset = 0; 67 + sg->length = PAGE_SIZE; 68 + sg_dma_address(sg) = 69 + GEN8_DECODE_PTE(readq(&gtt_entries[i])); 70 + sg_dma_len(sg) = PAGE_SIZE; 71 + } 72 + 73 + __i915_gem_object_set_pages(obj, st, PAGE_SIZE); 74 + 75 + return 0; 76 + } 77 + 78 + static void vgpu_gem_put_pages(struct drm_i915_gem_object *obj, 79 + struct sg_table *pages) 80 + { 81 + sg_free_table(pages); 82 + kfree(pages); 83 + } 84 + 85 + static void dmabuf_gem_object_free(struct kref *kref) 86 + { 87 + struct intel_vgpu_dmabuf_obj *obj = 88 + container_of(kref, struct intel_vgpu_dmabuf_obj, kref); 89 + struct intel_vgpu *vgpu = obj->vgpu; 90 + struct list_head *pos; 91 + struct intel_vgpu_dmabuf_obj *dmabuf_obj; 92 + 93 + if (vgpu && vgpu->active && !list_empty(&vgpu->dmabuf_obj_list_head)) { 94 + list_for_each(pos, &vgpu->dmabuf_obj_list_head) { 95 + dmabuf_obj = container_of(pos, 96 + struct intel_vgpu_dmabuf_obj, list); 97 + if (dmabuf_obj == obj) { 98 + intel_gvt_hypervisor_put_vfio_device(vgpu); 99 + idr_remove(&vgpu->object_idr, 100 + dmabuf_obj->dmabuf_id); 101 + kfree(dmabuf_obj->info); 102 + kfree(dmabuf_obj); 103 + list_del(pos); 104 + break; 105 + } 106 + } 107 + } else { 108 + /* Free the orphan dmabuf_objs here */ 109 + kfree(obj->info); 110 + kfree(obj); 111 + } 112 + } 113 + 114 + 115 + static inline void dmabuf_obj_get(struct intel_vgpu_dmabuf_obj *obj) 116 + { 117 + kref_get(&obj->kref); 118 + } 119 + 120 + static inline void dmabuf_obj_put(struct intel_vgpu_dmabuf_obj *obj) 121 + { 122 + kref_put(&obj->kref, dmabuf_gem_object_free); 123 + } 124 + 125 + static void vgpu_gem_release(struct drm_i915_gem_object *gem_obj) 126 + { 127 + 128 + struct intel_vgpu_fb_info *fb_info = gem_obj->gvt_info; 129 + struct intel_vgpu_dmabuf_obj *obj = fb_info->obj; 130 + struct intel_vgpu *vgpu = obj->vgpu; 131 + 132 + if (vgpu) { 133 + mutex_lock(&vgpu->dmabuf_lock); 134 + gem_obj->base.dma_buf = NULL; 135 + dmabuf_obj_put(obj); 136 + mutex_unlock(&vgpu->dmabuf_lock); 137 + } else { 138 + /* vgpu is NULL, as it has been removed already */ 139 + gem_obj->base.dma_buf = NULL; 140 + dmabuf_obj_put(obj); 141 + } 142 + } 143 + 144 + static const struct drm_i915_gem_object_ops intel_vgpu_gem_ops = { 145 + .flags = I915_GEM_OBJECT_IS_PROXY, 146 + .get_pages = vgpu_gem_get_pages, 147 + .put_pages = vgpu_gem_put_pages, 148 + .release = vgpu_gem_release, 149 + }; 150 + 151 + static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev, 152 + struct intel_vgpu_fb_info *info) 153 + { 154 + struct drm_i915_private *dev_priv = to_i915(dev); 155 + struct drm_i915_gem_object *obj; 156 + 157 + obj = i915_gem_object_alloc(dev_priv); 158 + if (obj == NULL) 159 + return NULL; 160 + 161 + drm_gem_private_object_init(dev, &obj->base, 162 + info->size << PAGE_SHIFT); 163 + i915_gem_object_init(obj, &intel_vgpu_gem_ops); 164 + 165 + obj->base.read_domains = I915_GEM_DOMAIN_GTT; 166 + obj->base.write_domain = 0; 167 + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { 168 + unsigned int tiling_mode = 0; 169 + unsigned int stride = 0; 170 + 171 + switch (info->drm_format_mod << 10) { 172 + case PLANE_CTL_TILED_LINEAR: 173 + tiling_mode = I915_TILING_NONE; 174 + break; 175 + case PLANE_CTL_TILED_X: 176 + tiling_mode = I915_TILING_X; 177 + stride = info->stride; 178 + break; 179 + case PLANE_CTL_TILED_Y: 180 + tiling_mode = I915_TILING_Y; 181 + stride = info->stride; 182 + break; 183 + default: 184 + gvt_dbg_core("not supported tiling mode\n"); 185 + } 186 + obj->tiling_and_stride = tiling_mode | stride; 187 + } else { 188 + obj->tiling_and_stride = info->drm_format_mod ? 189 + I915_TILING_X : 0; 190 + } 191 + 192 + return obj; 193 + } 194 + 195 + static int vgpu_get_plane_info(struct drm_device *dev, 196 + struct intel_vgpu *vgpu, 197 + struct intel_vgpu_fb_info *info, 198 + int plane_id) 199 + { 200 + struct drm_i915_private *dev_priv = to_i915(dev); 201 + struct intel_vgpu_primary_plane_format p; 202 + struct intel_vgpu_cursor_plane_format c; 203 + int ret; 204 + 205 + if (plane_id == DRM_PLANE_TYPE_PRIMARY) { 206 + ret = intel_vgpu_decode_primary_plane(vgpu, &p); 207 + if (ret) 208 + return ret; 209 + info->start = p.base; 210 + info->start_gpa = p.base_gpa; 211 + info->width = p.width; 212 + info->height = p.height; 213 + info->stride = p.stride; 214 + info->drm_format = p.drm_format; 215 + info->drm_format_mod = p.tiled; 216 + info->size = (((p.stride * p.height * p.bpp) / 8) + 217 + (PAGE_SIZE - 1)) >> PAGE_SHIFT; 218 + } else if (plane_id == DRM_PLANE_TYPE_CURSOR) { 219 + ret = intel_vgpu_decode_cursor_plane(vgpu, &c); 220 + if (ret) 221 + return ret; 222 + info->start = c.base; 223 + info->start_gpa = c.base_gpa; 224 + info->width = c.width; 225 + info->height = c.height; 226 + info->stride = c.width * (c.bpp / 8); 227 + info->drm_format = c.drm_format; 228 + info->drm_format_mod = 0; 229 + info->x_pos = c.x_pos; 230 + info->y_pos = c.y_pos; 231 + 232 + /* The invalid cursor hotspot value is delivered to host 233 + * until we find a way to get the cursor hotspot info of 234 + * guest OS. 235 + */ 236 + info->x_hot = UINT_MAX; 237 + info->y_hot = UINT_MAX; 238 + info->size = (((info->stride * c.height * c.bpp) / 8) 239 + + (PAGE_SIZE - 1)) >> PAGE_SHIFT; 240 + } else { 241 + gvt_vgpu_err("invalid plane id:%d\n", plane_id); 242 + return -EINVAL; 243 + } 244 + 245 + if (info->size == 0) { 246 + gvt_vgpu_err("fb size is zero\n"); 247 + return -EINVAL; 248 + } 249 + 250 + if (info->start & (PAGE_SIZE - 1)) { 251 + gvt_vgpu_err("Not aligned fb address:0x%llx\n", info->start); 252 + return -EFAULT; 253 + } 254 + if (((info->start >> PAGE_SHIFT) + info->size) > 255 + ggtt_total_entries(&dev_priv->ggtt)) { 256 + gvt_vgpu_err("Invalid GTT offset or size\n"); 257 + return -EFAULT; 258 + } 259 + 260 + if (!intel_gvt_ggtt_validate_range(vgpu, info->start, info->size)) { 261 + gvt_vgpu_err("invalid gma addr\n"); 262 + return -EFAULT; 263 + } 264 + 265 + return 0; 266 + } 267 + 268 + static struct intel_vgpu_dmabuf_obj * 269 + pick_dmabuf_by_info(struct intel_vgpu *vgpu, 270 + struct intel_vgpu_fb_info *latest_info) 271 + { 272 + struct list_head *pos; 273 + struct intel_vgpu_fb_info *fb_info; 274 + struct intel_vgpu_dmabuf_obj *dmabuf_obj = NULL; 275 + struct intel_vgpu_dmabuf_obj *ret = NULL; 276 + 277 + list_for_each(pos, &vgpu->dmabuf_obj_list_head) { 278 + dmabuf_obj = container_of(pos, struct intel_vgpu_dmabuf_obj, 279 + list); 280 + if ((dmabuf_obj == NULL) || 281 + (dmabuf_obj->info == NULL)) 282 + continue; 283 + 284 + fb_info = (struct intel_vgpu_fb_info *)dmabuf_obj->info; 285 + if ((fb_info->start == latest_info->start) && 286 + (fb_info->start_gpa == latest_info->start_gpa) && 287 + (fb_info->size == latest_info->size) && 288 + (fb_info->drm_format_mod == latest_info->drm_format_mod) && 289 + (fb_info->drm_format == latest_info->drm_format) && 290 + (fb_info->width == latest_info->width) && 291 + (fb_info->height == latest_info->height)) { 292 + ret = dmabuf_obj; 293 + break; 294 + } 295 + } 296 + 297 + return ret; 298 + } 299 + 300 + static struct intel_vgpu_dmabuf_obj * 301 + pick_dmabuf_by_num(struct intel_vgpu *vgpu, u32 id) 302 + { 303 + struct list_head *pos; 304 + struct intel_vgpu_dmabuf_obj *dmabuf_obj = NULL; 305 + struct intel_vgpu_dmabuf_obj *ret = NULL; 306 + 307 + list_for_each(pos, &vgpu->dmabuf_obj_list_head) { 308 + dmabuf_obj = container_of(pos, struct intel_vgpu_dmabuf_obj, 309 + list); 310 + if (!dmabuf_obj) 311 + continue; 312 + 313 + if (dmabuf_obj->dmabuf_id == id) { 314 + ret = dmabuf_obj; 315 + break; 316 + } 317 + } 318 + 319 + return ret; 320 + } 321 + 322 + static void update_fb_info(struct vfio_device_gfx_plane_info *gvt_dmabuf, 323 + struct intel_vgpu_fb_info *fb_info) 324 + { 325 + gvt_dmabuf->drm_format = fb_info->drm_format; 326 + gvt_dmabuf->width = fb_info->width; 327 + gvt_dmabuf->height = fb_info->height; 328 + gvt_dmabuf->stride = fb_info->stride; 329 + gvt_dmabuf->size = fb_info->size; 330 + gvt_dmabuf->x_pos = fb_info->x_pos; 331 + gvt_dmabuf->y_pos = fb_info->y_pos; 332 + gvt_dmabuf->x_hot = fb_info->x_hot; 333 + gvt_dmabuf->y_hot = fb_info->y_hot; 334 + } 335 + 336 + int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args) 337 + { 338 + struct drm_device *dev = &vgpu->gvt->dev_priv->drm; 339 + struct vfio_device_gfx_plane_info *gfx_plane_info = args; 340 + struct intel_vgpu_dmabuf_obj *dmabuf_obj; 341 + struct intel_vgpu_fb_info fb_info; 342 + int ret = 0; 343 + 344 + if (gfx_plane_info->flags == (VFIO_GFX_PLANE_TYPE_DMABUF | 345 + VFIO_GFX_PLANE_TYPE_PROBE)) 346 + return ret; 347 + else if ((gfx_plane_info->flags & ~VFIO_GFX_PLANE_TYPE_DMABUF) || 348 + (!gfx_plane_info->flags)) 349 + return -EINVAL; 350 + 351 + ret = vgpu_get_plane_info(dev, vgpu, &fb_info, 352 + gfx_plane_info->drm_plane_type); 353 + if (ret != 0) 354 + goto out; 355 + 356 + mutex_lock(&vgpu->dmabuf_lock); 357 + /* If exists, pick up the exposed dmabuf_obj */ 358 + dmabuf_obj = pick_dmabuf_by_info(vgpu, &fb_info); 359 + if (dmabuf_obj) { 360 + update_fb_info(gfx_plane_info, &fb_info); 361 + gfx_plane_info->dmabuf_id = dmabuf_obj->dmabuf_id; 362 + 363 + /* This buffer may be released between query_plane ioctl and 364 + * get_dmabuf ioctl. Add the refcount to make sure it won't 365 + * be released between the two ioctls. 366 + */ 367 + if (!dmabuf_obj->initref) { 368 + dmabuf_obj->initref = true; 369 + dmabuf_obj_get(dmabuf_obj); 370 + } 371 + ret = 0; 372 + gvt_dbg_dpy("vgpu%d: re-use dmabuf_obj ref %d, id %d\n", 373 + vgpu->id, kref_read(&dmabuf_obj->kref), 374 + gfx_plane_info->dmabuf_id); 375 + mutex_unlock(&vgpu->dmabuf_lock); 376 + goto out; 377 + } 378 + 379 + mutex_unlock(&vgpu->dmabuf_lock); 380 + 381 + /* Need to allocate a new one*/ 382 + dmabuf_obj = kmalloc(sizeof(struct intel_vgpu_dmabuf_obj), GFP_KERNEL); 383 + if (unlikely(!dmabuf_obj)) { 384 + gvt_vgpu_err("alloc dmabuf_obj failed\n"); 385 + ret = -ENOMEM; 386 + goto out; 387 + } 388 + 389 + dmabuf_obj->info = kmalloc(sizeof(struct intel_vgpu_fb_info), 390 + GFP_KERNEL); 391 + if (unlikely(!dmabuf_obj->info)) { 392 + gvt_vgpu_err("allocate intel vgpu fb info failed\n"); 393 + ret = -ENOMEM; 394 + goto out_free_dmabuf; 395 + } 396 + memcpy(dmabuf_obj->info, &fb_info, sizeof(struct intel_vgpu_fb_info)); 397 + 398 + ((struct intel_vgpu_fb_info *)dmabuf_obj->info)->obj = dmabuf_obj; 399 + 400 + dmabuf_obj->vgpu = vgpu; 401 + 402 + ret = idr_alloc(&vgpu->object_idr, dmabuf_obj, 1, 0, GFP_NOWAIT); 403 + if (ret < 0) 404 + goto out_free_info; 405 + gfx_plane_info->dmabuf_id = ret; 406 + dmabuf_obj->dmabuf_id = ret; 407 + 408 + dmabuf_obj->initref = true; 409 + 410 + kref_init(&dmabuf_obj->kref); 411 + 412 + mutex_lock(&vgpu->dmabuf_lock); 413 + if (intel_gvt_hypervisor_get_vfio_device(vgpu)) { 414 + gvt_vgpu_err("get vfio device failed\n"); 415 + mutex_unlock(&vgpu->dmabuf_lock); 416 + goto out_free_info; 417 + } 418 + mutex_unlock(&vgpu->dmabuf_lock); 419 + 420 + update_fb_info(gfx_plane_info, &fb_info); 421 + 422 + INIT_LIST_HEAD(&dmabuf_obj->list); 423 + mutex_lock(&vgpu->dmabuf_lock); 424 + list_add_tail(&dmabuf_obj->list, &vgpu->dmabuf_obj_list_head); 425 + mutex_unlock(&vgpu->dmabuf_lock); 426 + 427 + gvt_dbg_dpy("vgpu%d: %s new dmabuf_obj ref %d, id %d\n", vgpu->id, 428 + __func__, kref_read(&dmabuf_obj->kref), ret); 429 + 430 + return 0; 431 + 432 + out_free_info: 433 + kfree(dmabuf_obj->info); 434 + out_free_dmabuf: 435 + kfree(dmabuf_obj); 436 + out: 437 + /* ENODEV means plane isn't ready, which might be a normal case. */ 438 + return (ret == -ENODEV) ? 0 : ret; 439 + } 440 + 441 + /* To associate an exposed dmabuf with the dmabuf_obj */ 442 + int intel_vgpu_get_dmabuf(struct intel_vgpu *vgpu, unsigned int dmabuf_id) 443 + { 444 + struct drm_device *dev = &vgpu->gvt->dev_priv->drm; 445 + struct intel_vgpu_dmabuf_obj *dmabuf_obj; 446 + struct drm_i915_gem_object *obj; 447 + struct dma_buf *dmabuf; 448 + int dmabuf_fd; 449 + int ret = 0; 450 + 451 + mutex_lock(&vgpu->dmabuf_lock); 452 + 453 + dmabuf_obj = pick_dmabuf_by_num(vgpu, dmabuf_id); 454 + if (dmabuf_obj == NULL) { 455 + gvt_vgpu_err("invalid dmabuf id:%d\n", dmabuf_id); 456 + ret = -EINVAL; 457 + goto out; 458 + } 459 + 460 + obj = vgpu_create_gem(dev, dmabuf_obj->info); 461 + if (obj == NULL) { 462 + gvt_vgpu_err("create gvt gem obj failed:%d\n", vgpu->id); 463 + ret = -ENOMEM; 464 + goto out; 465 + } 466 + 467 + obj->gvt_info = dmabuf_obj->info; 468 + 469 + dmabuf = i915_gem_prime_export(dev, &obj->base, DRM_CLOEXEC | DRM_RDWR); 470 + if (IS_ERR(dmabuf)) { 471 + gvt_vgpu_err("export dma-buf failed\n"); 472 + ret = PTR_ERR(dmabuf); 473 + goto out_free_gem; 474 + } 475 + obj->base.dma_buf = dmabuf; 476 + 477 + i915_gem_object_put(obj); 478 + 479 + ret = dma_buf_fd(dmabuf, DRM_CLOEXEC | DRM_RDWR); 480 + if (ret < 0) { 481 + gvt_vgpu_err("create dma-buf fd failed ret:%d\n", ret); 482 + goto out_free_dmabuf; 483 + } 484 + dmabuf_fd = ret; 485 + 486 + dmabuf_obj_get(dmabuf_obj); 487 + 488 + if (dmabuf_obj->initref) { 489 + dmabuf_obj->initref = false; 490 + dmabuf_obj_put(dmabuf_obj); 491 + } 492 + 493 + mutex_unlock(&vgpu->dmabuf_lock); 494 + 495 + gvt_dbg_dpy("vgpu%d: dmabuf:%d, dmabuf ref %d, fd:%d\n" 496 + " file count: %ld, GEM ref: %d\n", 497 + vgpu->id, dmabuf_obj->dmabuf_id, 498 + kref_read(&dmabuf_obj->kref), 499 + dmabuf_fd, 500 + file_count(dmabuf->file), 501 + kref_read(&obj->base.refcount)); 502 + 503 + return dmabuf_fd; 504 + 505 + out_free_dmabuf: 506 + dma_buf_put(dmabuf); 507 + out_free_gem: 508 + i915_gem_object_put(obj); 509 + out: 510 + mutex_unlock(&vgpu->dmabuf_lock); 511 + return ret; 512 + } 513 + 514 + void intel_vgpu_dmabuf_cleanup(struct intel_vgpu *vgpu) 515 + { 516 + struct list_head *pos, *n; 517 + struct intel_vgpu_dmabuf_obj *dmabuf_obj; 518 + 519 + mutex_lock(&vgpu->dmabuf_lock); 520 + list_for_each_safe(pos, n, &vgpu->dmabuf_obj_list_head) { 521 + dmabuf_obj = container_of(pos, struct intel_vgpu_dmabuf_obj, 522 + list); 523 + dmabuf_obj->vgpu = NULL; 524 + 525 + idr_remove(&vgpu->object_idr, dmabuf_obj->dmabuf_id); 526 + intel_gvt_hypervisor_put_vfio_device(vgpu); 527 + list_del(pos); 528 + 529 + /* dmabuf_obj might be freed in dmabuf_obj_put */ 530 + if (dmabuf_obj->initref) { 531 + dmabuf_obj->initref = false; 532 + dmabuf_obj_put(dmabuf_obj); 533 + } 534 + 535 + } 536 + mutex_unlock(&vgpu->dmabuf_lock); 537 + }
+4 -4
drivers/gpu/drm/i915/gvt/execlist.c
··· 458 458 gvt_dbg_el("workload %p emulate schedule_in %d\n", workload, 459 459 emulate_schedule_in); 460 460 461 - queue_workload(workload); 461 + intel_vgpu_queue_workload(workload); 462 462 return 0; 463 463 } 464 464 ··· 528 528 vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw; 529 529 } 530 530 531 - void clean_execlist(struct intel_vgpu *vgpu) 531 + static void clean_execlist(struct intel_vgpu *vgpu) 532 532 { 533 533 enum intel_engine_id i; 534 534 struct intel_engine_cs *engine; ··· 542 542 } 543 543 } 544 544 545 - void reset_execlist(struct intel_vgpu *vgpu, 545 + static void reset_execlist(struct intel_vgpu *vgpu, 546 546 unsigned long engine_mask) 547 547 { 548 548 struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; ··· 553 553 init_vgpu_execlist(vgpu, engine->id); 554 554 } 555 555 556 - int init_execlist(struct intel_vgpu *vgpu) 556 + static int init_execlist(struct intel_vgpu *vgpu) 557 557 { 558 558 reset_execlist(vgpu, ALL_ENGINES); 559 559 return 0;
+514
drivers/gpu/drm/i915/gvt/fb_decoder.c
··· 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 + * 26 + * Contributors: 27 + * Bing Niu <bing.niu@intel.com> 28 + * Xu Han <xu.han@intel.com> 29 + * Ping Gao <ping.a.gao@intel.com> 30 + * Xiaoguang Chen <xiaoguang.chen@intel.com> 31 + * Yang Liu <yang2.liu@intel.com> 32 + * Tina Zhang <tina.zhang@intel.com> 33 + * 34 + */ 35 + 36 + #include <uapi/drm/drm_fourcc.h> 37 + #include "i915_drv.h" 38 + #include "gvt.h" 39 + 40 + #define PRIMARY_FORMAT_NUM 16 41 + struct pixel_format { 42 + int drm_format; /* Pixel format in DRM definition */ 43 + int bpp; /* Bits per pixel, 0 indicates invalid */ 44 + char *desc; /* The description */ 45 + }; 46 + 47 + static struct pixel_format bdw_pixel_formats[] = { 48 + {DRM_FORMAT_C8, 8, "8-bit Indexed"}, 49 + {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"}, 50 + {DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"}, 51 + {DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"}, 52 + 53 + {DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"}, 54 + {DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"}, 55 + 56 + /* non-supported format has bpp default to 0 */ 57 + {0, 0, NULL}, 58 + }; 59 + 60 + static struct pixel_format skl_pixel_formats[] = { 61 + {DRM_FORMAT_YUYV, 16, "16-bit packed YUYV (8:8:8:8 MSB-V:Y2:U:Y1)"}, 62 + {DRM_FORMAT_UYVY, 16, "16-bit packed UYVY (8:8:8:8 MSB-Y2:V:Y1:U)"}, 63 + {DRM_FORMAT_YVYU, 16, "16-bit packed YVYU (8:8:8:8 MSB-U:Y2:V:Y1)"}, 64 + {DRM_FORMAT_VYUY, 16, "16-bit packed VYUY (8:8:8:8 MSB-Y2:U:Y1:V)"}, 65 + 66 + {DRM_FORMAT_C8, 8, "8-bit Indexed"}, 67 + {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"}, 68 + {DRM_FORMAT_ABGR8888, 32, "32-bit RGBA (8:8:8:8 MSB-A:B:G:R)"}, 69 + {DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"}, 70 + 71 + {DRM_FORMAT_ARGB8888, 32, "32-bit BGRA (8:8:8:8 MSB-A:R:G:B)"}, 72 + {DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"}, 73 + {DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"}, 74 + {DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"}, 75 + 76 + /* non-supported format has bpp default to 0 */ 77 + {0, 0, NULL}, 78 + }; 79 + 80 + static int bdw_format_to_drm(int format) 81 + { 82 + int bdw_pixel_formats_index = 6; 83 + 84 + switch (format) { 85 + case DISPPLANE_8BPP: 86 + bdw_pixel_formats_index = 0; 87 + break; 88 + case DISPPLANE_BGRX565: 89 + bdw_pixel_formats_index = 1; 90 + break; 91 + case DISPPLANE_BGRX888: 92 + bdw_pixel_formats_index = 2; 93 + break; 94 + case DISPPLANE_RGBX101010: 95 + bdw_pixel_formats_index = 3; 96 + break; 97 + case DISPPLANE_BGRX101010: 98 + bdw_pixel_formats_index = 4; 99 + break; 100 + case DISPPLANE_RGBX888: 101 + bdw_pixel_formats_index = 5; 102 + break; 103 + 104 + default: 105 + break; 106 + } 107 + 108 + return bdw_pixel_formats_index; 109 + } 110 + 111 + static int skl_format_to_drm(int format, bool rgb_order, bool alpha, 112 + int yuv_order) 113 + { 114 + int skl_pixel_formats_index = 12; 115 + 116 + switch (format) { 117 + case PLANE_CTL_FORMAT_INDEXED: 118 + skl_pixel_formats_index = 4; 119 + break; 120 + case PLANE_CTL_FORMAT_RGB_565: 121 + skl_pixel_formats_index = 5; 122 + break; 123 + case PLANE_CTL_FORMAT_XRGB_8888: 124 + if (rgb_order) 125 + skl_pixel_formats_index = alpha ? 6 : 7; 126 + else 127 + skl_pixel_formats_index = alpha ? 8 : 9; 128 + break; 129 + case PLANE_CTL_FORMAT_XRGB_2101010: 130 + skl_pixel_formats_index = rgb_order ? 10 : 11; 131 + break; 132 + case PLANE_CTL_FORMAT_YUV422: 133 + skl_pixel_formats_index = yuv_order >> 16; 134 + if (skl_pixel_formats_index > 3) 135 + return -EINVAL; 136 + break; 137 + 138 + default: 139 + break; 140 + } 141 + 142 + return skl_pixel_formats_index; 143 + } 144 + 145 + static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe, 146 + u32 tiled, int stride_mask, int bpp) 147 + { 148 + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 149 + 150 + u32 stride_reg = vgpu_vreg(vgpu, DSPSTRIDE(pipe)) & stride_mask; 151 + u32 stride = stride_reg; 152 + 153 + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { 154 + switch (tiled) { 155 + case PLANE_CTL_TILED_LINEAR: 156 + stride = stride_reg * 64; 157 + break; 158 + case PLANE_CTL_TILED_X: 159 + stride = stride_reg * 512; 160 + break; 161 + case PLANE_CTL_TILED_Y: 162 + stride = stride_reg * 128; 163 + break; 164 + case PLANE_CTL_TILED_YF: 165 + if (bpp == 8) 166 + stride = stride_reg * 64; 167 + else if (bpp == 16 || bpp == 32 || bpp == 64) 168 + stride = stride_reg * 128; 169 + else 170 + gvt_dbg_core("skl: unsupported bpp:%d\n", bpp); 171 + break; 172 + default: 173 + gvt_dbg_core("skl: unsupported tile format:%x\n", 174 + tiled); 175 + } 176 + } 177 + 178 + return stride; 179 + } 180 + 181 + static int get_active_pipe(struct intel_vgpu *vgpu) 182 + { 183 + int i; 184 + 185 + for (i = 0; i < I915_MAX_PIPES; i++) 186 + if (pipe_is_enabled(vgpu, i)) 187 + break; 188 + 189 + return i; 190 + } 191 + 192 + /** 193 + * intel_vgpu_decode_primary_plane - Decode primary plane 194 + * @vgpu: input vgpu 195 + * @plane: primary plane to save decoded info 196 + * This function is called for decoding plane 197 + * 198 + * Returns: 199 + * 0 on success, non-zero if failed. 200 + */ 201 + int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, 202 + struct intel_vgpu_primary_plane_format *plane) 203 + { 204 + u32 val, fmt; 205 + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 206 + int pipe; 207 + 208 + pipe = get_active_pipe(vgpu); 209 + if (pipe >= I915_MAX_PIPES) 210 + return -ENODEV; 211 + 212 + val = vgpu_vreg(vgpu, DSPCNTR(pipe)); 213 + plane->enabled = !!(val & DISPLAY_PLANE_ENABLE); 214 + if (!plane->enabled) 215 + return -ENODEV; 216 + 217 + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { 218 + plane->tiled = (val & PLANE_CTL_TILED_MASK) >> 219 + _PLANE_CTL_TILED_SHIFT; 220 + fmt = skl_format_to_drm( 221 + val & PLANE_CTL_FORMAT_MASK, 222 + val & PLANE_CTL_ORDER_RGBX, 223 + val & PLANE_CTL_ALPHA_MASK, 224 + val & PLANE_CTL_YUV422_ORDER_MASK); 225 + 226 + if (fmt >= ARRAY_SIZE(skl_pixel_formats)) { 227 + gvt_vgpu_err("Out-of-bounds pixel format index\n"); 228 + return -EINVAL; 229 + } 230 + 231 + plane->bpp = skl_pixel_formats[fmt].bpp; 232 + plane->drm_format = skl_pixel_formats[fmt].drm_format; 233 + } else { 234 + plane->tiled = !!(val & DISPPLANE_TILED); 235 + fmt = bdw_format_to_drm(val & DISPPLANE_PIXFORMAT_MASK); 236 + plane->bpp = bdw_pixel_formats[fmt].bpp; 237 + plane->drm_format = bdw_pixel_formats[fmt].drm_format; 238 + } 239 + 240 + if (!plane->bpp) { 241 + gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt); 242 + return -EINVAL; 243 + } 244 + 245 + plane->hw_format = fmt; 246 + 247 + plane->base = vgpu_vreg(vgpu, DSPSURF(pipe)) & I915_GTT_PAGE_MASK; 248 + if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0)) { 249 + gvt_vgpu_err("invalid gma address: %lx\n", 250 + (unsigned long)plane->base); 251 + return -EINVAL; 252 + } 253 + 254 + plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base); 255 + if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) { 256 + gvt_vgpu_err("invalid gma address: %lx\n", 257 + (unsigned long)plane->base); 258 + return -EINVAL; 259 + } 260 + 261 + plane->stride = intel_vgpu_get_stride(vgpu, pipe, (plane->tiled << 10), 262 + (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) ? 263 + (_PRI_PLANE_STRIDE_MASK >> 6) : 264 + _PRI_PLANE_STRIDE_MASK, plane->bpp); 265 + 266 + plane->width = (vgpu_vreg(vgpu, PIPESRC(pipe)) & _PIPE_H_SRCSZ_MASK) >> 267 + _PIPE_H_SRCSZ_SHIFT; 268 + plane->width += 1; 269 + plane->height = (vgpu_vreg(vgpu, PIPESRC(pipe)) & 270 + _PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT; 271 + plane->height += 1; /* raw height is one minus the real value */ 272 + 273 + val = vgpu_vreg(vgpu, DSPTILEOFF(pipe)); 274 + plane->x_offset = (val & _PRI_PLANE_X_OFF_MASK) >> 275 + _PRI_PLANE_X_OFF_SHIFT; 276 + plane->y_offset = (val & _PRI_PLANE_Y_OFF_MASK) >> 277 + _PRI_PLANE_Y_OFF_SHIFT; 278 + 279 + return 0; 280 + } 281 + 282 + #define CURSOR_FORMAT_NUM (1 << 6) 283 + struct cursor_mode_format { 284 + int drm_format; /* Pixel format in DRM definition */ 285 + u8 bpp; /* Bits per pixel; 0 indicates invalid */ 286 + u32 width; /* In pixel */ 287 + u32 height; /* In lines */ 288 + char *desc; /* The description */ 289 + }; 290 + 291 + static struct cursor_mode_format cursor_pixel_formats[] = { 292 + {DRM_FORMAT_ARGB8888, 32, 128, 128, "128x128 32bpp ARGB"}, 293 + {DRM_FORMAT_ARGB8888, 32, 256, 256, "256x256 32bpp ARGB"}, 294 + {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"}, 295 + {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"}, 296 + 297 + /* non-supported format has bpp default to 0 */ 298 + {0, 0, 0, 0, NULL}, 299 + }; 300 + 301 + static int cursor_mode_to_drm(int mode) 302 + { 303 + int cursor_pixel_formats_index = 4; 304 + 305 + switch (mode) { 306 + case CURSOR_MODE_128_ARGB_AX: 307 + cursor_pixel_formats_index = 0; 308 + break; 309 + case CURSOR_MODE_256_ARGB_AX: 310 + cursor_pixel_formats_index = 1; 311 + break; 312 + case CURSOR_MODE_64_ARGB_AX: 313 + cursor_pixel_formats_index = 2; 314 + break; 315 + case CURSOR_MODE_64_32B_AX: 316 + cursor_pixel_formats_index = 3; 317 + break; 318 + 319 + default: 320 + break; 321 + } 322 + 323 + return cursor_pixel_formats_index; 324 + } 325 + 326 + /** 327 + * intel_vgpu_decode_cursor_plane - Decode sprite plane 328 + * @vgpu: input vgpu 329 + * @plane: cursor plane to save decoded info 330 + * This function is called for decoding plane 331 + * 332 + * Returns: 333 + * 0 on success, non-zero if failed. 334 + */ 335 + int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, 336 + struct intel_vgpu_cursor_plane_format *plane) 337 + { 338 + u32 val, mode, index; 339 + u32 alpha_plane, alpha_force; 340 + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 341 + int pipe; 342 + 343 + pipe = get_active_pipe(vgpu); 344 + if (pipe >= I915_MAX_PIPES) 345 + return -ENODEV; 346 + 347 + val = vgpu_vreg(vgpu, CURCNTR(pipe)); 348 + mode = val & CURSOR_MODE; 349 + plane->enabled = (mode != CURSOR_MODE_DISABLE); 350 + if (!plane->enabled) 351 + return -ENODEV; 352 + 353 + index = cursor_mode_to_drm(mode); 354 + 355 + if (!cursor_pixel_formats[index].bpp) { 356 + gvt_vgpu_err("Non-supported cursor mode (0x%x)\n", mode); 357 + return -EINVAL; 358 + } 359 + plane->mode = mode; 360 + plane->bpp = cursor_pixel_formats[index].bpp; 361 + plane->drm_format = cursor_pixel_formats[index].drm_format; 362 + plane->width = cursor_pixel_formats[index].width; 363 + plane->height = cursor_pixel_formats[index].height; 364 + 365 + alpha_plane = (val & _CURSOR_ALPHA_PLANE_MASK) >> 366 + _CURSOR_ALPHA_PLANE_SHIFT; 367 + alpha_force = (val & _CURSOR_ALPHA_FORCE_MASK) >> 368 + _CURSOR_ALPHA_FORCE_SHIFT; 369 + if (alpha_plane || alpha_force) 370 + gvt_dbg_core("alpha_plane=0x%x, alpha_force=0x%x\n", 371 + alpha_plane, alpha_force); 372 + 373 + plane->base = vgpu_vreg(vgpu, CURBASE(pipe)) & I915_GTT_PAGE_MASK; 374 + if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0)) { 375 + gvt_vgpu_err("invalid gma address: %lx\n", 376 + (unsigned long)plane->base); 377 + return -EINVAL; 378 + } 379 + 380 + plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base); 381 + if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) { 382 + gvt_vgpu_err("invalid gma address: %lx\n", 383 + (unsigned long)plane->base); 384 + return -EINVAL; 385 + } 386 + 387 + val = vgpu_vreg(vgpu, CURPOS(pipe)); 388 + plane->x_pos = (val & _CURSOR_POS_X_MASK) >> _CURSOR_POS_X_SHIFT; 389 + plane->x_sign = (val & _CURSOR_SIGN_X_MASK) >> _CURSOR_SIGN_X_SHIFT; 390 + plane->y_pos = (val & _CURSOR_POS_Y_MASK) >> _CURSOR_POS_Y_SHIFT; 391 + plane->y_sign = (val & _CURSOR_SIGN_Y_MASK) >> _CURSOR_SIGN_Y_SHIFT; 392 + 393 + return 0; 394 + } 395 + 396 + #define SPRITE_FORMAT_NUM (1 << 3) 397 + 398 + static struct pixel_format sprite_pixel_formats[SPRITE_FORMAT_NUM] = { 399 + [0x0] = {DRM_FORMAT_YUV422, 16, "YUV 16-bit 4:2:2 packed"}, 400 + [0x1] = {DRM_FORMAT_XRGB2101010, 32, "RGB 32-bit 2:10:10:10"}, 401 + [0x2] = {DRM_FORMAT_XRGB8888, 32, "RGB 32-bit 8:8:8:8"}, 402 + [0x4] = {DRM_FORMAT_AYUV, 32, 403 + "YUV 32-bit 4:4:4 packed (8:8:8:8 MSB-X:Y:U:V)"}, 404 + }; 405 + 406 + /** 407 + * intel_vgpu_decode_sprite_plane - Decode sprite plane 408 + * @vgpu: input vgpu 409 + * @plane: sprite plane to save decoded info 410 + * This function is called for decoding plane 411 + * 412 + * Returns: 413 + * 0 on success, non-zero if failed. 414 + */ 415 + int intel_vgpu_decode_sprite_plane(struct intel_vgpu *vgpu, 416 + struct intel_vgpu_sprite_plane_format *plane) 417 + { 418 + u32 val, fmt; 419 + u32 color_order, yuv_order; 420 + int drm_format; 421 + int pipe; 422 + 423 + pipe = get_active_pipe(vgpu); 424 + if (pipe >= I915_MAX_PIPES) 425 + return -ENODEV; 426 + 427 + val = vgpu_vreg(vgpu, SPRCTL(pipe)); 428 + plane->enabled = !!(val & SPRITE_ENABLE); 429 + if (!plane->enabled) 430 + return -ENODEV; 431 + 432 + plane->tiled = !!(val & SPRITE_TILED); 433 + color_order = !!(val & SPRITE_RGB_ORDER_RGBX); 434 + yuv_order = (val & SPRITE_YUV_BYTE_ORDER_MASK) >> 435 + _SPRITE_YUV_ORDER_SHIFT; 436 + 437 + fmt = (val & SPRITE_PIXFORMAT_MASK) >> _SPRITE_FMT_SHIFT; 438 + if (!sprite_pixel_formats[fmt].bpp) { 439 + gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt); 440 + return -EINVAL; 441 + } 442 + plane->hw_format = fmt; 443 + plane->bpp = sprite_pixel_formats[fmt].bpp; 444 + drm_format = sprite_pixel_formats[fmt].drm_format; 445 + 446 + /* Order of RGB values in an RGBxxx buffer may be ordered RGB or 447 + * BGR depending on the state of the color_order field 448 + */ 449 + if (!color_order) { 450 + if (drm_format == DRM_FORMAT_XRGB2101010) 451 + drm_format = DRM_FORMAT_XBGR2101010; 452 + else if (drm_format == DRM_FORMAT_XRGB8888) 453 + drm_format = DRM_FORMAT_XBGR8888; 454 + } 455 + 456 + if (drm_format == DRM_FORMAT_YUV422) { 457 + switch (yuv_order) { 458 + case 0: 459 + drm_format = DRM_FORMAT_YUYV; 460 + break; 461 + case 1: 462 + drm_format = DRM_FORMAT_UYVY; 463 + break; 464 + case 2: 465 + drm_format = DRM_FORMAT_YVYU; 466 + break; 467 + case 3: 468 + drm_format = DRM_FORMAT_VYUY; 469 + break; 470 + default: 471 + /* yuv_order has only 2 bits */ 472 + break; 473 + } 474 + } 475 + 476 + plane->drm_format = drm_format; 477 + 478 + plane->base = vgpu_vreg(vgpu, SPRSURF(pipe)) & I915_GTT_PAGE_MASK; 479 + if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0)) { 480 + gvt_vgpu_err("invalid gma address: %lx\n", 481 + (unsigned long)plane->base); 482 + return -EINVAL; 483 + } 484 + 485 + plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base); 486 + if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) { 487 + gvt_vgpu_err("invalid gma address: %lx\n", 488 + (unsigned long)plane->base); 489 + return -EINVAL; 490 + } 491 + 492 + plane->stride = vgpu_vreg(vgpu, SPRSTRIDE(pipe)) & 493 + _SPRITE_STRIDE_MASK; 494 + 495 + val = vgpu_vreg(vgpu, SPRSIZE(pipe)); 496 + plane->height = (val & _SPRITE_SIZE_HEIGHT_MASK) >> 497 + _SPRITE_SIZE_HEIGHT_SHIFT; 498 + plane->width = (val & _SPRITE_SIZE_WIDTH_MASK) >> 499 + _SPRITE_SIZE_WIDTH_SHIFT; 500 + plane->height += 1; /* raw height is one minus the real value */ 501 + plane->width += 1; /* raw width is one minus the real value */ 502 + 503 + val = vgpu_vreg(vgpu, SPRPOS(pipe)); 504 + plane->x_pos = (val & _SPRITE_POS_X_MASK) >> _SPRITE_POS_X_SHIFT; 505 + plane->y_pos = (val & _SPRITE_POS_Y_MASK) >> _SPRITE_POS_Y_SHIFT; 506 + 507 + val = vgpu_vreg(vgpu, SPROFFSET(pipe)); 508 + plane->x_offset = (val & _SPRITE_OFFSET_START_X_MASK) >> 509 + _SPRITE_OFFSET_START_X_SHIFT; 510 + plane->y_offset = (val & _SPRITE_OFFSET_START_Y_MASK) >> 511 + _SPRITE_OFFSET_START_Y_SHIFT; 512 + 513 + return 0; 514 + }
+169
drivers/gpu/drm/i915/gvt/fb_decoder.h
··· 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 + * 26 + * Contributors: 27 + * Bing Niu <bing.niu@intel.com> 28 + * Xu Han <xu.han@intel.com> 29 + * Ping Gao <ping.a.gao@intel.com> 30 + * Xiaoguang Chen <xiaoguang.chen@intel.com> 31 + * Yang Liu <yang2.liu@intel.com> 32 + * Tina Zhang <tina.zhang@intel.com> 33 + * 34 + */ 35 + 36 + #ifndef _GVT_FB_DECODER_H_ 37 + #define _GVT_FB_DECODER_H_ 38 + 39 + #define _PLANE_CTL_FORMAT_SHIFT 24 40 + #define _PLANE_CTL_TILED_SHIFT 10 41 + #define _PIPE_V_SRCSZ_SHIFT 0 42 + #define _PIPE_V_SRCSZ_MASK (0xfff << _PIPE_V_SRCSZ_SHIFT) 43 + #define _PIPE_H_SRCSZ_SHIFT 16 44 + #define _PIPE_H_SRCSZ_MASK (0x1fff << _PIPE_H_SRCSZ_SHIFT) 45 + 46 + #define _PRI_PLANE_FMT_SHIFT 26 47 + #define _PRI_PLANE_STRIDE_MASK (0x3ff << 6) 48 + #define _PRI_PLANE_X_OFF_SHIFT 0 49 + #define _PRI_PLANE_X_OFF_MASK (0x1fff << _PRI_PLANE_X_OFF_SHIFT) 50 + #define _PRI_PLANE_Y_OFF_SHIFT 16 51 + #define _PRI_PLANE_Y_OFF_MASK (0xfff << _PRI_PLANE_Y_OFF_SHIFT) 52 + 53 + #define _CURSOR_MODE 0x3f 54 + #define _CURSOR_ALPHA_FORCE_SHIFT 8 55 + #define _CURSOR_ALPHA_FORCE_MASK (0x3 << _CURSOR_ALPHA_FORCE_SHIFT) 56 + #define _CURSOR_ALPHA_PLANE_SHIFT 10 57 + #define _CURSOR_ALPHA_PLANE_MASK (0x3 << _CURSOR_ALPHA_PLANE_SHIFT) 58 + #define _CURSOR_POS_X_SHIFT 0 59 + #define _CURSOR_POS_X_MASK (0x1fff << _CURSOR_POS_X_SHIFT) 60 + #define _CURSOR_SIGN_X_SHIFT 15 61 + #define _CURSOR_SIGN_X_MASK (1 << _CURSOR_SIGN_X_SHIFT) 62 + #define _CURSOR_POS_Y_SHIFT 16 63 + #define _CURSOR_POS_Y_MASK (0xfff << _CURSOR_POS_Y_SHIFT) 64 + #define _CURSOR_SIGN_Y_SHIFT 31 65 + #define _CURSOR_SIGN_Y_MASK (1 << _CURSOR_SIGN_Y_SHIFT) 66 + 67 + #define _SPRITE_FMT_SHIFT 25 68 + #define _SPRITE_COLOR_ORDER_SHIFT 20 69 + #define _SPRITE_YUV_ORDER_SHIFT 16 70 + #define _SPRITE_STRIDE_SHIFT 6 71 + #define _SPRITE_STRIDE_MASK (0x1ff << _SPRITE_STRIDE_SHIFT) 72 + #define _SPRITE_SIZE_WIDTH_SHIFT 0 73 + #define _SPRITE_SIZE_HEIGHT_SHIFT 16 74 + #define _SPRITE_SIZE_WIDTH_MASK (0x1fff << _SPRITE_SIZE_WIDTH_SHIFT) 75 + #define _SPRITE_SIZE_HEIGHT_MASK (0xfff << _SPRITE_SIZE_HEIGHT_SHIFT) 76 + #define _SPRITE_POS_X_SHIFT 0 77 + #define _SPRITE_POS_Y_SHIFT 16 78 + #define _SPRITE_POS_X_MASK (0x1fff << _SPRITE_POS_X_SHIFT) 79 + #define _SPRITE_POS_Y_MASK (0xfff << _SPRITE_POS_Y_SHIFT) 80 + #define _SPRITE_OFFSET_START_X_SHIFT 0 81 + #define _SPRITE_OFFSET_START_Y_SHIFT 16 82 + #define _SPRITE_OFFSET_START_X_MASK (0x1fff << _SPRITE_OFFSET_START_X_SHIFT) 83 + #define _SPRITE_OFFSET_START_Y_MASK (0xfff << _SPRITE_OFFSET_START_Y_SHIFT) 84 + 85 + enum GVT_FB_EVENT { 86 + FB_MODE_SET_START = 1, 87 + FB_MODE_SET_END, 88 + FB_DISPLAY_FLIP, 89 + }; 90 + 91 + enum DDI_PORT { 92 + DDI_PORT_NONE = 0, 93 + DDI_PORT_B = 1, 94 + DDI_PORT_C = 2, 95 + DDI_PORT_D = 3, 96 + DDI_PORT_E = 4 97 + }; 98 + 99 + struct intel_gvt; 100 + 101 + /* color space conversion and gamma correction are not included */ 102 + struct intel_vgpu_primary_plane_format { 103 + u8 enabled; /* plane is enabled */ 104 + u8 tiled; /* X-tiled */ 105 + u8 bpp; /* bits per pixel */ 106 + u32 hw_format; /* format field in the PRI_CTL register */ 107 + u32 drm_format; /* format in DRM definition */ 108 + u32 base; /* framebuffer base in graphics memory */ 109 + u64 base_gpa; 110 + u32 x_offset; /* in pixels */ 111 + u32 y_offset; /* in lines */ 112 + u32 width; /* in pixels */ 113 + u32 height; /* in lines */ 114 + u32 stride; /* in bytes */ 115 + }; 116 + 117 + struct intel_vgpu_sprite_plane_format { 118 + u8 enabled; /* plane is enabled */ 119 + u8 tiled; /* X-tiled */ 120 + u8 bpp; /* bits per pixel */ 121 + u32 hw_format; /* format field in the SPR_CTL register */ 122 + u32 drm_format; /* format in DRM definition */ 123 + u32 base; /* sprite base in graphics memory */ 124 + u64 base_gpa; 125 + u32 x_pos; /* in pixels */ 126 + u32 y_pos; /* in lines */ 127 + u32 x_offset; /* in pixels */ 128 + u32 y_offset; /* in lines */ 129 + u32 width; /* in pixels */ 130 + u32 height; /* in lines */ 131 + u32 stride; /* in bytes */ 132 + }; 133 + 134 + struct intel_vgpu_cursor_plane_format { 135 + u8 enabled; 136 + u8 mode; /* cursor mode select */ 137 + u8 bpp; /* bits per pixel */ 138 + u32 drm_format; /* format in DRM definition */ 139 + u32 base; /* cursor base in graphics memory */ 140 + u64 base_gpa; 141 + u32 x_pos; /* in pixels */ 142 + u32 y_pos; /* in lines */ 143 + u8 x_sign; /* X Position Sign */ 144 + u8 y_sign; /* Y Position Sign */ 145 + u32 width; /* in pixels */ 146 + u32 height; /* in lines */ 147 + u32 x_hot; /* in pixels */ 148 + u32 y_hot; /* in pixels */ 149 + }; 150 + 151 + struct intel_vgpu_pipe_format { 152 + struct intel_vgpu_primary_plane_format primary; 153 + struct intel_vgpu_sprite_plane_format sprite; 154 + struct intel_vgpu_cursor_plane_format cursor; 155 + enum DDI_PORT ddi_port; /* the DDI port that pipe is connected to */ 156 + }; 157 + 158 + struct intel_vgpu_fb_format { 159 + struct intel_vgpu_pipe_format pipes[I915_MAX_PIPES]; 160 + }; 161 + 162 + int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, 163 + struct intel_vgpu_primary_plane_format *plane); 164 + int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, 165 + struct intel_vgpu_cursor_plane_format *plane); 166 + int intel_vgpu_decode_sprite_plane(struct intel_vgpu *vgpu, 167 + struct intel_vgpu_sprite_plane_format *plane); 168 + 169 + #endif
+4
drivers/gpu/drm/i915/gvt/gvt.c
··· 181 181 .vgpu_deactivate = intel_gvt_deactivate_vgpu, 182 182 .gvt_find_vgpu_type = intel_gvt_find_vgpu_type, 183 183 .get_gvt_attrs = intel_get_gvt_attrs, 184 + .vgpu_query_plane = intel_vgpu_query_plane, 185 + .vgpu_get_dmabuf = intel_vgpu_get_dmabuf, 184 186 }; 185 187 186 188 /** ··· 385 383 ret = intel_gvt_setup_mmio_info(gvt); 386 384 if (ret) 387 385 goto out_clean_idr; 386 + 387 + intel_gvt_init_engine_mmio_context(gvt); 388 388 389 389 ret = intel_gvt_load_firmware(gvt); 390 390 if (ret)
+20 -3
drivers/gpu/drm/i915/gvt/gvt.h
··· 44 44 #include "execlist.h" 45 45 #include "scheduler.h" 46 46 #include "sched_policy.h" 47 - #include "render.h" 47 + #include "mmio_context.h" 48 48 #include "cmd_parser.h" 49 + #include "fb_decoder.h" 50 + #include "dmabuf.h" 49 51 50 52 #define GVT_MAX_VGPU 8 51 53 ··· 125 123 }; 126 124 127 125 struct intel_vgpu_opregion { 126 + bool mapped; 128 127 void *va; 128 + void *va_gopregion; 129 129 u32 gfn[INTEL_GVT_OPREGION_PAGES]; 130 130 }; 131 131 ··· 210 206 struct kvm *kvm; 211 207 struct work_struct release_work; 212 208 atomic_t released; 209 + struct vfio_device *vfio_device; 213 210 } vdev; 214 211 #endif 212 + 213 + struct list_head dmabuf_obj_list_head; 214 + struct mutex dmabuf_lock; 215 + struct idr object_idr; 216 + 217 + struct completion vblank_done; 218 + 215 219 }; 216 220 217 221 /* validating GM healthy status*/ ··· 310 298 wait_queue_head_t service_thread_wq; 311 299 unsigned long service_request; 312 300 301 + struct engine_mmio *engine_mmio_list; 302 + 313 303 struct dentry *debugfs_root; 314 304 }; 315 305 ··· 350 336 351 337 /* Aperture/GM space definitions for GVT device */ 352 338 #define gvt_aperture_sz(gvt) (gvt->dev_priv->ggtt.mappable_end) 353 - #define gvt_aperture_pa_base(gvt) (gvt->dev_priv->ggtt.mappable_base) 339 + #define gvt_aperture_pa_base(gvt) (gvt->dev_priv->ggtt.gmadr.start) 354 340 355 341 #define gvt_ggtt_gm_sz(gvt) (gvt->dev_priv->ggtt.base.total) 356 342 #define gvt_ggtt_sz(gvt) \ ··· 519 505 } 520 506 521 507 void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu); 522 - int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa); 508 + int intel_vgpu_init_opregion(struct intel_vgpu *vgpu); 509 + int intel_vgpu_opregion_base_write_handler(struct intel_vgpu *vgpu, u32 gpa); 523 510 524 511 int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci); 525 512 void populate_pvinfo_page(struct intel_vgpu *vgpu); ··· 547 532 const char *name); 548 533 bool (*get_gvt_attrs)(struct attribute ***type_attrs, 549 534 struct attribute_group ***intel_vgpu_type_groups); 535 + int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *); 536 + int (*vgpu_get_dmabuf)(struct intel_vgpu *vgpu, unsigned int); 550 537 }; 551 538 552 539
+4 -2
drivers/gpu/drm/i915/gvt/handlers.c
··· 174 174 break; 175 175 case GVT_FAILSAFE_INSUFFICIENT_RESOURCE: 176 176 pr_err("Graphics resource is not enough for the guest\n"); 177 + break; 177 178 case GVT_FAILSAFE_GUEST_ERR: 178 179 pr_err("GVT Internal error for the guest\n"); 180 + break; 179 181 default: 180 182 break; 181 183 } ··· 1398 1396 * update the VM CSB status correctly. Here listed registers can 1399 1397 * support BDW, SKL or other platforms with same HWSP registers. 1400 1398 */ 1401 - if (unlikely(ring_id < 0 || ring_id > I915_NUM_ENGINES)) { 1399 + if (unlikely(ring_id < 0 || ring_id >= I915_NUM_ENGINES)) { 1402 1400 gvt_vgpu_err("VM(%d) access unknown hardware status page register:0x%x\n", 1403 1401 vgpu->id, offset); 1404 1402 return -EINVAL; ··· 1473 1471 u32 data = *(u32 *)p_data; 1474 1472 int ret = 0; 1475 1473 1476 - if (WARN_ON(ring_id < 0 || ring_id > I915_NUM_ENGINES - 1)) 1474 + if (WARN_ON(ring_id < 0 || ring_id >= I915_NUM_ENGINES)) 1477 1475 return -EINVAL; 1478 1476 1479 1477 execlist = &vgpu->submission.execlist[ring_id];
+3
drivers/gpu/drm/i915/gvt/hypercall.h
··· 55 55 unsigned long mfn, unsigned int nr, bool map); 56 56 int (*set_trap_area)(unsigned long handle, u64 start, u64 end, 57 57 bool map); 58 + int (*set_opregion)(void *vgpu); 59 + int (*get_vfio_device)(void *vgpu); 60 + void (*put_vfio_device)(void *vgpu); 58 61 }; 59 62 60 63 extern struct intel_gvt_mpt xengt_mpt;
+163 -4
drivers/gpu/drm/i915/gvt/kvmgt.c
··· 53 53 #define VFIO_PCI_INDEX_TO_OFFSET(index) ((u64)(index) << VFIO_PCI_OFFSET_SHIFT) 54 54 #define VFIO_PCI_OFFSET_MASK (((u64)(1) << VFIO_PCI_OFFSET_SHIFT) - 1) 55 55 56 + #define OPREGION_SIGNATURE "IntelGraphicsMem" 57 + 58 + struct vfio_region; 59 + struct intel_vgpu_regops { 60 + size_t (*rw)(struct intel_vgpu *vgpu, char *buf, 61 + size_t count, loff_t *ppos, bool iswrite); 62 + void (*release)(struct intel_vgpu *vgpu, 63 + struct vfio_region *region); 64 + }; 65 + 56 66 struct vfio_region { 57 67 u32 type; 58 68 u32 subtype; 59 69 size_t size; 60 70 u32 flags; 71 + const struct intel_vgpu_regops *ops; 72 + void *data; 61 73 }; 62 74 63 75 struct kvmgt_pgfn { ··· 328 316 } 329 317 } 330 318 319 + static size_t intel_vgpu_reg_rw_opregion(struct intel_vgpu *vgpu, char *buf, 320 + size_t count, loff_t *ppos, bool iswrite) 321 + { 322 + unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) - 323 + VFIO_PCI_NUM_REGIONS; 324 + void *base = vgpu->vdev.region[i].data; 325 + loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK; 326 + 327 + if (pos >= vgpu->vdev.region[i].size || iswrite) { 328 + gvt_vgpu_err("invalid op or offset for Intel vgpu OpRegion\n"); 329 + return -EINVAL; 330 + } 331 + count = min(count, (size_t)(vgpu->vdev.region[i].size - pos)); 332 + memcpy(buf, base + pos, count); 333 + 334 + return count; 335 + } 336 + 337 + static void intel_vgpu_reg_release_opregion(struct intel_vgpu *vgpu, 338 + struct vfio_region *region) 339 + { 340 + } 341 + 342 + static const struct intel_vgpu_regops intel_vgpu_regops_opregion = { 343 + .rw = intel_vgpu_reg_rw_opregion, 344 + .release = intel_vgpu_reg_release_opregion, 345 + }; 346 + 347 + static int intel_vgpu_register_reg(struct intel_vgpu *vgpu, 348 + unsigned int type, unsigned int subtype, 349 + const struct intel_vgpu_regops *ops, 350 + size_t size, u32 flags, void *data) 351 + { 352 + struct vfio_region *region; 353 + 354 + region = krealloc(vgpu->vdev.region, 355 + (vgpu->vdev.num_regions + 1) * sizeof(*region), 356 + GFP_KERNEL); 357 + if (!region) 358 + return -ENOMEM; 359 + 360 + vgpu->vdev.region = region; 361 + vgpu->vdev.region[vgpu->vdev.num_regions].type = type; 362 + vgpu->vdev.region[vgpu->vdev.num_regions].subtype = subtype; 363 + vgpu->vdev.region[vgpu->vdev.num_regions].ops = ops; 364 + vgpu->vdev.region[vgpu->vdev.num_regions].size = size; 365 + vgpu->vdev.region[vgpu->vdev.num_regions].flags = flags; 366 + vgpu->vdev.region[vgpu->vdev.num_regions].data = data; 367 + vgpu->vdev.num_regions++; 368 + return 0; 369 + } 370 + 371 + static int kvmgt_get_vfio_device(void *p_vgpu) 372 + { 373 + struct intel_vgpu *vgpu = (struct intel_vgpu *)p_vgpu; 374 + 375 + vgpu->vdev.vfio_device = vfio_device_get_from_dev( 376 + mdev_dev(vgpu->vdev.mdev)); 377 + if (!vgpu->vdev.vfio_device) { 378 + gvt_vgpu_err("failed to get vfio device\n"); 379 + return -ENODEV; 380 + } 381 + return 0; 382 + } 383 + 384 + 385 + static int kvmgt_set_opregion(void *p_vgpu) 386 + { 387 + struct intel_vgpu *vgpu = (struct intel_vgpu *)p_vgpu; 388 + void *base; 389 + int ret; 390 + 391 + /* Each vgpu has its own opregion, although VFIO would create another 392 + * one later. This one is used to expose opregion to VFIO. And the 393 + * other one created by VFIO later, is used by guest actually. 394 + */ 395 + base = vgpu_opregion(vgpu)->va; 396 + if (!base) 397 + return -ENOMEM; 398 + 399 + if (memcmp(base, OPREGION_SIGNATURE, 16)) { 400 + memunmap(base); 401 + return -EINVAL; 402 + } 403 + 404 + ret = intel_vgpu_register_reg(vgpu, 405 + PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE, 406 + VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, 407 + &intel_vgpu_regops_opregion, OPREGION_SIZE, 408 + VFIO_REGION_INFO_FLAG_READ, base); 409 + 410 + return ret; 411 + } 412 + 413 + static void kvmgt_put_vfio_device(void *vgpu) 414 + { 415 + if (WARN_ON(!((struct intel_vgpu *)vgpu)->vdev.vfio_device)) 416 + return; 417 + 418 + vfio_device_put(((struct intel_vgpu *)vgpu)->vdev.vfio_device); 419 + } 420 + 331 421 static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev) 332 422 { 333 423 struct intel_vgpu *vgpu = NULL; ··· 660 546 int ret = -EINVAL; 661 547 662 548 663 - if (index >= VFIO_PCI_NUM_REGIONS) { 549 + if (index >= VFIO_PCI_NUM_REGIONS + vgpu->vdev.num_regions) { 664 550 gvt_vgpu_err("invalid index: %u\n", index); 665 551 return -EINVAL; 666 552 } ··· 688 574 case VFIO_PCI_BAR5_REGION_INDEX: 689 575 case VFIO_PCI_VGA_REGION_INDEX: 690 576 case VFIO_PCI_ROM_REGION_INDEX: 577 + break; 691 578 default: 692 - gvt_vgpu_err("unsupported region: %u\n", index); 579 + if (index >= VFIO_PCI_NUM_REGIONS + vgpu->vdev.num_regions) 580 + return -EINVAL; 581 + 582 + index -= VFIO_PCI_NUM_REGIONS; 583 + return vgpu->vdev.region[index].ops->rw(vgpu, buf, count, 584 + ppos, is_write); 693 585 } 694 586 695 587 return ret == 0 ? count : ret; ··· 958 838 959 839 info.flags = VFIO_DEVICE_FLAGS_PCI; 960 840 info.flags |= VFIO_DEVICE_FLAGS_RESET; 961 - info.num_regions = VFIO_PCI_NUM_REGIONS; 841 + info.num_regions = VFIO_PCI_NUM_REGIONS + 842 + vgpu->vdev.num_regions; 962 843 info.num_irqs = VFIO_PCI_NUM_IRQS; 963 844 964 845 return copy_to_user((void __user *)arg, &info, minsz) ? ··· 1029 908 case VFIO_PCI_BAR3_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX: 1030 909 info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 1031 910 info.size = 0; 1032 - 1033 911 info.flags = 0; 912 + 1034 913 gvt_dbg_core("get region info bar:%d\n", info.index); 1035 914 break; 1036 915 1037 916 case VFIO_PCI_ROM_REGION_INDEX: 1038 917 case VFIO_PCI_VGA_REGION_INDEX: 918 + info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); 919 + info.size = 0; 920 + info.flags = 0; 921 + 1039 922 gvt_dbg_core("get region info index:%d\n", info.index); 1040 923 break; 1041 924 default: ··· 1084 959 } 1085 960 1086 961 if (caps.size) { 962 + info.flags |= VFIO_REGION_INFO_FLAG_CAPS; 1087 963 if (info.argsz < sizeof(info) + caps.size) { 1088 964 info.argsz = sizeof(info) + caps.size; 1089 965 info.cap_offset = 0; ··· 1171 1045 } else if (cmd == VFIO_DEVICE_RESET) { 1172 1046 intel_gvt_ops->vgpu_reset(vgpu); 1173 1047 return 0; 1048 + } else if (cmd == VFIO_DEVICE_QUERY_GFX_PLANE) { 1049 + struct vfio_device_gfx_plane_info dmabuf; 1050 + int ret = 0; 1051 + 1052 + minsz = offsetofend(struct vfio_device_gfx_plane_info, 1053 + dmabuf_id); 1054 + if (copy_from_user(&dmabuf, (void __user *)arg, minsz)) 1055 + return -EFAULT; 1056 + if (dmabuf.argsz < minsz) 1057 + return -EINVAL; 1058 + 1059 + ret = intel_gvt_ops->vgpu_query_plane(vgpu, &dmabuf); 1060 + if (ret != 0) 1061 + return ret; 1062 + 1063 + return copy_to_user((void __user *)arg, &dmabuf, minsz) ? 1064 + -EFAULT : 0; 1065 + } else if (cmd == VFIO_DEVICE_GET_GFX_DMABUF) { 1066 + __u32 dmabuf_id; 1067 + __s32 dmabuf_fd; 1068 + 1069 + if (get_user(dmabuf_id, (__u32 __user *)arg)) 1070 + return -EFAULT; 1071 + 1072 + dmabuf_fd = intel_gvt_ops->vgpu_get_dmabuf(vgpu, dmabuf_id); 1073 + return dmabuf_fd; 1074 + 1174 1075 } 1175 1076 1176 1077 return 0; ··· 1439 1286 kvmgt_protect_table_init(info); 1440 1287 gvt_cache_init(vgpu); 1441 1288 1289 + mutex_init(&vgpu->dmabuf_lock); 1290 + init_completion(&vgpu->vblank_done); 1291 + 1442 1292 info->track_node.track_write = kvmgt_page_track_write; 1443 1293 info->track_node.track_flush_slot = kvmgt_page_track_flush_slot; 1444 1294 kvm_page_track_register_notifier(kvm, &info->track_node); ··· 1582 1426 .read_gpa = kvmgt_read_gpa, 1583 1427 .write_gpa = kvmgt_write_gpa, 1584 1428 .gfn_to_mfn = kvmgt_gfn_to_pfn, 1429 + .set_opregion = kvmgt_set_opregion, 1430 + .get_vfio_device = kvmgt_get_vfio_device, 1431 + .put_vfio_device = kvmgt_put_vfio_device, 1585 1432 }; 1586 1433 EXPORT_SYMBOL_GPL(kvmgt_mpt); 1587 1434
+15 -21
drivers/gpu/drm/i915/gvt/mmio.c
··· 157 157 unsigned int offset = 0; 158 158 int ret = -EINVAL; 159 159 160 - 161 160 if (vgpu->failsafe) { 162 161 failsafe_emulate_mmio_rw(vgpu, pa, p_data, bytes, true); 163 162 return 0; ··· 165 166 166 167 if (vgpu_gpa_is_aperture(vgpu, pa)) { 167 168 ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, true); 168 - mutex_unlock(&gvt->lock); 169 - return ret; 169 + goto out; 170 170 } 171 171 172 172 if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) { ··· 181 183 ret, t->gfn, pa, *(u32 *)p_data, 182 184 bytes); 183 185 } 184 - mutex_unlock(&gvt->lock); 185 - return ret; 186 + goto out; 186 187 } 187 188 } 188 189 ··· 202 205 p_data, bytes); 203 206 if (ret) 204 207 goto err; 205 - mutex_unlock(&gvt->lock); 206 - return ret; 208 + goto out; 207 209 } 208 210 209 211 if (WARN_ON_ONCE(!reg_is_mmio(gvt, offset))) { 210 212 ret = intel_gvt_hypervisor_read_gpa(vgpu, pa, p_data, bytes); 211 - mutex_unlock(&gvt->lock); 212 - return ret; 213 + goto out; 213 214 } 214 215 215 216 if (WARN_ON(!reg_is_mmio(gvt, offset + bytes - 1))) ··· 223 228 goto err; 224 229 225 230 intel_gvt_mmio_set_accessed(gvt, offset); 226 - mutex_unlock(&gvt->lock); 227 - return 0; 231 + ret = 0; 232 + goto out; 233 + 228 234 err: 229 235 gvt_vgpu_err("fail to emulate MMIO read %08x len %d\n", 230 236 offset, bytes); 237 + out: 231 238 mutex_unlock(&gvt->lock); 232 239 return ret; 233 240 } ··· 260 263 261 264 if (vgpu_gpa_is_aperture(vgpu, pa)) { 262 265 ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, false); 263 - mutex_unlock(&gvt->lock); 264 - return ret; 266 + goto out; 265 267 } 266 268 267 269 if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) { ··· 276 280 ret, t->gfn, pa, 277 281 *(u32 *)p_data, bytes); 278 282 } 279 - mutex_unlock(&gvt->lock); 280 - return ret; 283 + goto out; 281 284 } 282 285 } 283 286 ··· 297 302 p_data, bytes); 298 303 if (ret) 299 304 goto err; 300 - mutex_unlock(&gvt->lock); 301 - return ret; 305 + goto out; 302 306 } 303 307 304 308 if (WARN_ON_ONCE(!reg_is_mmio(gvt, offset))) { 305 309 ret = intel_gvt_hypervisor_write_gpa(vgpu, pa, p_data, bytes); 306 - mutex_unlock(&gvt->lock); 307 - return ret; 310 + goto out; 308 311 } 309 312 310 313 ret = intel_vgpu_mmio_reg_rw(vgpu, offset, p_data, bytes, false); ··· 310 317 goto err; 311 318 312 319 intel_gvt_mmio_set_accessed(gvt, offset); 313 - mutex_unlock(&gvt->lock); 314 - return 0; 320 + ret = 0; 321 + goto out; 315 322 err: 316 323 gvt_vgpu_err("fail to emulate MMIO write %08x len %d\n", offset, 317 324 bytes); 325 + out: 318 326 mutex_unlock(&gvt->lock); 319 327 return ret; 320 328 }
+52
drivers/gpu/drm/i915/gvt/mmio_context.h
··· 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 + * Eddie Dong <eddie.dong@intel.com> 25 + * Kevin Tian <kevin.tian@intel.com> 26 + * 27 + * Contributors: 28 + * Zhi Wang <zhi.a.wang@intel.com> 29 + * Changbin Du <changbin.du@intel.com> 30 + * Zhenyu Wang <zhenyuw@linux.intel.com> 31 + * Tina Zhang <tina.zhang@intel.com> 32 + * Bing Niu <bing.niu@intel.com> 33 + * 34 + */ 35 + 36 + #ifndef __GVT_RENDER_H__ 37 + #define __GVT_RENDER_H__ 38 + 39 + struct engine_mmio { 40 + int ring_id; 41 + i915_reg_t reg; 42 + u32 mask; 43 + bool in_context; 44 + u32 value; 45 + }; 46 + 47 + void intel_gvt_switch_mmio(struct intel_vgpu *pre, 48 + struct intel_vgpu *next, int ring_id); 49 + 50 + void intel_gvt_init_engine_mmio_context(struct intel_gvt *gvt); 51 + 52 + #endif
+45
drivers/gpu/drm/i915/gvt/mpt.h
··· 294 294 return intel_gvt_host.mpt->set_trap_area(vgpu->handle, start, end, map); 295 295 } 296 296 297 + /** 298 + * intel_gvt_hypervisor_set_opregion - Set opregion for guest 299 + * @vgpu: a vGPU 300 + * 301 + * Returns: 302 + * Zero on success, negative error code if failed. 303 + */ 304 + static inline int intel_gvt_hypervisor_set_opregion(struct intel_vgpu *vgpu) 305 + { 306 + if (!intel_gvt_host.mpt->set_opregion) 307 + return 0; 308 + 309 + return intel_gvt_host.mpt->set_opregion(vgpu); 310 + } 311 + 312 + /** 313 + * intel_gvt_hypervisor_get_vfio_device - increase vfio device ref count 314 + * @vgpu: a vGPU 315 + * 316 + * Returns: 317 + * Zero on success, negative error code if failed. 318 + */ 319 + static inline int intel_gvt_hypervisor_get_vfio_device(struct intel_vgpu *vgpu) 320 + { 321 + if (!intel_gvt_host.mpt->get_vfio_device) 322 + return 0; 323 + 324 + return intel_gvt_host.mpt->get_vfio_device(vgpu); 325 + } 326 + 327 + /** 328 + * intel_gvt_hypervisor_put_vfio_device - decrease vfio device ref count 329 + * @vgpu: a vGPU 330 + * 331 + * Returns: 332 + * Zero on success, negative error code if failed. 333 + */ 334 + static inline void intel_gvt_hypervisor_put_vfio_device(struct intel_vgpu *vgpu) 335 + { 336 + if (!intel_gvt_host.mpt->put_vfio_device) 337 + return; 338 + 339 + intel_gvt_host.mpt->put_vfio_device(vgpu); 340 + } 341 + 297 342 #endif /* _GVT_MPT_H_ */
+92 -57
drivers/gpu/drm/i915/gvt/opregion.c
··· 213 213 v->driver_features.lvds_config = BDB_DRIVER_FEATURE_NO_LVDS; 214 214 } 215 215 216 - static int alloc_and_init_virt_opregion(struct intel_vgpu *vgpu) 216 + /** 217 + * intel_vgpu_init_opregion - initialize the stuff used to emulate opregion 218 + * @vgpu: a vGPU 219 + * @gpa: guest physical address of opregion 220 + * 221 + * Returns: 222 + * Zero on success, negative error code if failed. 223 + */ 224 + int intel_vgpu_init_opregion(struct intel_vgpu *vgpu) 217 225 { 218 226 u8 *buf; 219 227 struct opregion_header *header; 220 228 struct vbt v; 229 + const char opregion_signature[16] = OPREGION_SIGNATURE; 221 230 222 231 gvt_dbg_core("init vgpu%d opregion\n", vgpu->id); 223 232 vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_KERNEL | ··· 240 231 /* emulated opregion with VBT mailbox only */ 241 232 buf = (u8 *)vgpu_opregion(vgpu)->va; 242 233 header = (struct opregion_header *)buf; 243 - memcpy(header->signature, OPREGION_SIGNATURE, 244 - sizeof(OPREGION_SIGNATURE)); 234 + memcpy(header->signature, opregion_signature, 235 + sizeof(opregion_signature)); 245 236 header->size = 0x8; 246 237 header->opregion_ver = 0x02000000; 247 238 header->mboxes = MBOX_VBT; ··· 255 246 /* emulated vbt from virt vbt generation */ 256 247 virt_vbt_generation(&v); 257 248 memcpy(buf + INTEL_GVT_OPREGION_VBT_OFFSET, &v, sizeof(struct vbt)); 258 - 259 - return 0; 260 - } 261 - 262 - static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa) 263 - { 264 - int i, ret; 265 - 266 - if (WARN((vgpu_opregion(vgpu)->va), 267 - "vgpu%d: opregion has been initialized already.\n", 268 - vgpu->id)) 269 - return -EINVAL; 270 - 271 - ret = alloc_and_init_virt_opregion(vgpu); 272 - if (ret < 0) 273 - return ret; 274 - 275 - for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) 276 - vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i; 277 249 278 250 return 0; 279 251 } ··· 280 290 return ret; 281 291 } 282 292 } 293 + 294 + vgpu_opregion(vgpu)->mapped = map; 295 + 283 296 return 0; 297 + } 298 + 299 + /** 300 + * intel_vgpu_opregion_base_write_handler - Opregion base register write handler 301 + * 302 + * @vgpu: a vGPU 303 + * @gpa: guest physical address of opregion 304 + * 305 + * Returns: 306 + * Zero on success, negative error code if failed. 307 + */ 308 + int intel_vgpu_opregion_base_write_handler(struct intel_vgpu *vgpu, u32 gpa) 309 + { 310 + 311 + int i, ret = 0; 312 + unsigned long pfn; 313 + 314 + gvt_dbg_core("emulate opregion from kernel\n"); 315 + 316 + switch (intel_gvt_host.hypervisor_type) { 317 + case INTEL_GVT_HYPERVISOR_KVM: 318 + pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gpa >> PAGE_SHIFT); 319 + vgpu_opregion(vgpu)->va_gopregion = memremap(pfn << PAGE_SHIFT, 320 + INTEL_GVT_OPREGION_SIZE, 321 + MEMREMAP_WB); 322 + if (!vgpu_opregion(vgpu)->va_gopregion) { 323 + gvt_vgpu_err("failed to map guest opregion\n"); 324 + ret = -EFAULT; 325 + } 326 + vgpu_opregion(vgpu)->mapped = true; 327 + break; 328 + case INTEL_GVT_HYPERVISOR_XEN: 329 + /** 330 + * Wins guest on Xengt will write this register twice: xen 331 + * hvmloader and windows graphic driver. 332 + */ 333 + if (vgpu_opregion(vgpu)->mapped) 334 + map_vgpu_opregion(vgpu, false); 335 + 336 + for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) 337 + vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i; 338 + 339 + ret = map_vgpu_opregion(vgpu, true); 340 + break; 341 + default: 342 + ret = -EINVAL; 343 + gvt_vgpu_err("not supported hypervisor\n"); 344 + } 345 + 346 + return ret; 284 347 } 285 348 286 349 /** ··· 349 306 return; 350 307 351 308 if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) { 352 - map_vgpu_opregion(vgpu, false); 353 - free_pages((unsigned long)vgpu_opregion(vgpu)->va, 354 - get_order(INTEL_GVT_OPREGION_SIZE)); 355 - 356 - vgpu_opregion(vgpu)->va = NULL; 309 + if (vgpu_opregion(vgpu)->mapped) 310 + map_vgpu_opregion(vgpu, false); 311 + } else if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_KVM) { 312 + if (vgpu_opregion(vgpu)->mapped) { 313 + memunmap(vgpu_opregion(vgpu)->va_gopregion); 314 + vgpu_opregion(vgpu)->va_gopregion = NULL; 315 + } 357 316 } 317 + free_pages((unsigned long)vgpu_opregion(vgpu)->va, 318 + get_order(INTEL_GVT_OPREGION_SIZE)); 319 + 320 + vgpu_opregion(vgpu)->va = NULL; 321 + 358 322 } 359 323 360 - /** 361 - * intel_vgpu_init_opregion - initialize the stuff used to emulate opregion 362 - * @vgpu: a vGPU 363 - * @gpa: guest physical address of opregion 364 - * 365 - * Returns: 366 - * Zero on success, negative error code if failed. 367 - */ 368 - int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa) 369 - { 370 - int ret; 371 - 372 - gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id); 373 - 374 - if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) { 375 - gvt_dbg_core("emulate opregion from kernel\n"); 376 - 377 - ret = init_vgpu_opregion(vgpu, gpa); 378 - if (ret) 379 - return ret; 380 - 381 - ret = map_vgpu_opregion(vgpu, true); 382 - if (ret) 383 - return ret; 384 - } 385 - 386 - return 0; 387 - } 388 324 389 325 #define GVT_OPREGION_FUNC(scic) \ 390 326 ({ \ ··· 483 461 u32 *scic, *parm; 484 462 u32 func, subfunc; 485 463 486 - scic = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_SCIC; 487 - parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM; 464 + switch (intel_gvt_host.hypervisor_type) { 465 + case INTEL_GVT_HYPERVISOR_XEN: 466 + scic = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_SCIC; 467 + parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM; 468 + break; 469 + case INTEL_GVT_HYPERVISOR_KVM: 470 + scic = vgpu_opregion(vgpu)->va_gopregion + 471 + INTEL_GVT_OPREGION_SCIC; 472 + parm = vgpu_opregion(vgpu)->va_gopregion + 473 + INTEL_GVT_OPREGION_PARM; 474 + break; 475 + default: 476 + gvt_vgpu_err("not supported hypervisor\n"); 477 + return -EINVAL; 478 + } 488 479 489 480 if (!(swsci & SWSCI_SCI_SELECT)) { 490 481 gvt_vgpu_err("requesting SMI service\n");
+122 -126
drivers/gpu/drm/i915/gvt/render.c drivers/gpu/drm/i915/gvt/mmio_context.c
··· 37 37 #include "gvt.h" 38 38 #include "trace.h" 39 39 40 - struct render_mmio { 41 - int ring_id; 42 - i915_reg_t reg; 43 - u32 mask; 44 - bool in_context; 45 - u32 value; 40 + /** 41 + * Defined in Intel Open Source PRM. 42 + * Ref: https://01.org/linuxgraphics/documentation/hardware-specification-prms 43 + */ 44 + #define TRVATTL3PTRDW(i) _MMIO(0x4de0 + (i)*4) 45 + #define TRNULLDETCT _MMIO(0x4de8) 46 + #define TRINVTILEDETCT _MMIO(0x4dec) 47 + #define TRVADR _MMIO(0x4df0) 48 + #define TRTTE _MMIO(0x4df4) 49 + #define RING_EXCC(base) _MMIO((base) + 0x28) 50 + #define RING_GFX_MODE(base) _MMIO((base) + 0x29c) 51 + #define VF_GUARDBAND _MMIO(0x83a4) 52 + 53 + /* Raw offset is appened to each line for convenience. */ 54 + static struct engine_mmio gen8_engine_mmio_list[] __cacheline_aligned = { 55 + {RCS, GFX_MODE_GEN7, 0xffff, false}, /* 0x229c */ 56 + {RCS, GEN9_CTX_PREEMPT_REG, 0x0, false}, /* 0x2248 */ 57 + {RCS, HWSTAM, 0x0, false}, /* 0x2098 */ 58 + {RCS, INSTPM, 0xffff, true}, /* 0x20c0 */ 59 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 0), 0, false}, /* 0x24d0 */ 60 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 1), 0, false}, /* 0x24d4 */ 61 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 2), 0, false}, /* 0x24d8 */ 62 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 3), 0, false}, /* 0x24dc */ 63 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 4), 0, false}, /* 0x24e0 */ 64 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 5), 0, false}, /* 0x24e4 */ 65 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 6), 0, false}, /* 0x24e8 */ 66 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 7), 0, false}, /* 0x24ec */ 67 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 8), 0, false}, /* 0x24f0 */ 68 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 9), 0, false}, /* 0x24f4 */ 69 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 10), 0, false}, /* 0x24f8 */ 70 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 11), 0, false}, /* 0x24fc */ 71 + {RCS, CACHE_MODE_1, 0xffff, true}, /* 0x7004 */ 72 + {RCS, GEN7_GT_MODE, 0xffff, true}, /* 0x7008 */ 73 + {RCS, CACHE_MODE_0_GEN7, 0xffff, true}, /* 0x7000 */ 74 + {RCS, GEN7_COMMON_SLICE_CHICKEN1, 0xffff, true}, /* 0x7010 */ 75 + {RCS, HDC_CHICKEN0, 0xffff, true}, /* 0x7300 */ 76 + {RCS, VF_GUARDBAND, 0xffff, true}, /* 0x83a4 */ 77 + 78 + {BCS, RING_GFX_MODE(BLT_RING_BASE), 0xffff, false}, /* 0x2229c */ 79 + {BCS, RING_MI_MODE(BLT_RING_BASE), 0xffff, false}, /* 0x2209c */ 80 + {BCS, RING_INSTPM(BLT_RING_BASE), 0xffff, false}, /* 0x220c0 */ 81 + {BCS, RING_HWSTAM(BLT_RING_BASE), 0x0, false}, /* 0x22098 */ 82 + {BCS, RING_EXCC(BLT_RING_BASE), 0x0, false}, /* 0x22028 */ 83 + { /* Terminated */ } 46 84 }; 47 85 48 - static struct render_mmio gen8_render_mmio_list[] __cacheline_aligned = { 49 - {RCS, _MMIO(0x229c), 0xffff, false}, 50 - {RCS, _MMIO(0x2248), 0x0, false}, 51 - {RCS, _MMIO(0x2098), 0x0, false}, 52 - {RCS, _MMIO(0x20c0), 0xffff, true}, 53 - {RCS, _MMIO(0x24d0), 0, false}, 54 - {RCS, _MMIO(0x24d4), 0, false}, 55 - {RCS, _MMIO(0x24d8), 0, false}, 56 - {RCS, _MMIO(0x24dc), 0, false}, 57 - {RCS, _MMIO(0x24e0), 0, false}, 58 - {RCS, _MMIO(0x24e4), 0, false}, 59 - {RCS, _MMIO(0x24e8), 0, false}, 60 - {RCS, _MMIO(0x24ec), 0, false}, 61 - {RCS, _MMIO(0x24f0), 0, false}, 62 - {RCS, _MMIO(0x24f4), 0, false}, 63 - {RCS, _MMIO(0x24f8), 0, false}, 64 - {RCS, _MMIO(0x24fc), 0, false}, 65 - {RCS, _MMIO(0x7004), 0xffff, true}, 66 - {RCS, _MMIO(0x7008), 0xffff, true}, 67 - {RCS, _MMIO(0x7000), 0xffff, true}, 68 - {RCS, _MMIO(0x7010), 0xffff, true}, 69 - {RCS, _MMIO(0x7300), 0xffff, true}, 70 - {RCS, _MMIO(0x83a4), 0xffff, true}, 86 + static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = { 87 + {RCS, GFX_MODE_GEN7, 0xffff, false}, /* 0x229c */ 88 + {RCS, GEN9_CTX_PREEMPT_REG, 0x0, false}, /* 0x2248 */ 89 + {RCS, HWSTAM, 0x0, false}, /* 0x2098 */ 90 + {RCS, INSTPM, 0xffff, true}, /* 0x20c0 */ 91 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 0), 0, false}, /* 0x24d0 */ 92 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 1), 0, false}, /* 0x24d4 */ 93 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 2), 0, false}, /* 0x24d8 */ 94 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 3), 0, false}, /* 0x24dc */ 95 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 4), 0, false}, /* 0x24e0 */ 96 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 5), 0, false}, /* 0x24e4 */ 97 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 6), 0, false}, /* 0x24e8 */ 98 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 7), 0, false}, /* 0x24ec */ 99 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 8), 0, false}, /* 0x24f0 */ 100 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 9), 0, false}, /* 0x24f4 */ 101 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 10), 0, false}, /* 0x24f8 */ 102 + {RCS, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 11), 0, false}, /* 0x24fc */ 103 + {RCS, CACHE_MODE_1, 0xffff, true}, /* 0x7004 */ 104 + {RCS, GEN7_GT_MODE, 0xffff, true}, /* 0x7008 */ 105 + {RCS, CACHE_MODE_0_GEN7, 0xffff, true}, /* 0x7000 */ 106 + {RCS, GEN7_COMMON_SLICE_CHICKEN1, 0xffff, true}, /* 0x7010 */ 107 + {RCS, HDC_CHICKEN0, 0xffff, true}, /* 0x7300 */ 108 + {RCS, VF_GUARDBAND, 0xffff, true}, /* 0x83a4 */ 71 109 72 - {BCS, _MMIO(0x2229c), 0xffff, false}, 73 - {BCS, _MMIO(0x2209c), 0xffff, false}, 74 - {BCS, _MMIO(0x220c0), 0xffff, false}, 75 - {BCS, _MMIO(0x22098), 0x0, false}, 76 - {BCS, _MMIO(0x22028), 0x0, false}, 77 - }; 110 + {RCS, GEN8_PRIVATE_PAT_LO, 0, false}, /* 0x40e0 */ 111 + {RCS, GEN8_PRIVATE_PAT_HI, 0, false}, /* 0x40e4 */ 112 + {RCS, GEN8_CS_CHICKEN1, 0xffff, true}, /* 0x2580 */ 113 + {RCS, COMMON_SLICE_CHICKEN2, 0xffff, true}, /* 0x7014 */ 114 + {RCS, GEN9_CS_DEBUG_MODE1, 0xffff, false}, /* 0x20ec */ 115 + {RCS, GEN8_L3SQCREG4, 0, false}, /* 0xb118 */ 116 + {RCS, GEN7_HALF_SLICE_CHICKEN1, 0xffff, true}, /* 0xe100 */ 117 + {RCS, HALF_SLICE_CHICKEN2, 0xffff, true}, /* 0xe180 */ 118 + {RCS, HALF_SLICE_CHICKEN3, 0xffff, true}, /* 0xe184 */ 119 + {RCS, GEN9_HALF_SLICE_CHICKEN5, 0xffff, true}, /* 0xe188 */ 120 + {RCS, GEN9_HALF_SLICE_CHICKEN7, 0xffff, true}, /* 0xe194 */ 121 + {RCS, TRVATTL3PTRDW(0), 0, false}, /* 0x4de0 */ 122 + {RCS, TRVATTL3PTRDW(1), 0, false}, /* 0x4de4 */ 123 + {RCS, TRNULLDETCT, 0, false}, /* 0x4de8 */ 124 + {RCS, TRINVTILEDETCT, 0, false}, /* 0x4dec */ 125 + {RCS, TRVADR, 0, false}, /* 0x4df0 */ 126 + {RCS, TRTTE, 0, false}, /* 0x4df4 */ 78 127 79 - static struct render_mmio gen9_render_mmio_list[] __cacheline_aligned = { 80 - {RCS, _MMIO(0x229c), 0xffff, false}, 81 - {RCS, _MMIO(0x2248), 0x0, false}, 82 - {RCS, _MMIO(0x2098), 0x0, false}, 83 - {RCS, _MMIO(0x20c0), 0xffff, true}, 84 - {RCS, _MMIO(0x24d0), 0, false}, 85 - {RCS, _MMIO(0x24d4), 0, false}, 86 - {RCS, _MMIO(0x24d8), 0, false}, 87 - {RCS, _MMIO(0x24dc), 0, false}, 88 - {RCS, _MMIO(0x24e0), 0, false}, 89 - {RCS, _MMIO(0x24e4), 0, false}, 90 - {RCS, _MMIO(0x24e8), 0, false}, 91 - {RCS, _MMIO(0x24ec), 0, false}, 92 - {RCS, _MMIO(0x24f0), 0, false}, 93 - {RCS, _MMIO(0x24f4), 0, false}, 94 - {RCS, _MMIO(0x24f8), 0, false}, 95 - {RCS, _MMIO(0x24fc), 0, false}, 96 - {RCS, _MMIO(0x7004), 0xffff, true}, 97 - {RCS, _MMIO(0x7008), 0xffff, true}, 98 - {RCS, _MMIO(0x7000), 0xffff, true}, 99 - {RCS, _MMIO(0x7010), 0xffff, true}, 100 - {RCS, _MMIO(0x7300), 0xffff, true}, 101 - {RCS, _MMIO(0x83a4), 0xffff, true}, 128 + {BCS, RING_GFX_MODE(BLT_RING_BASE), 0xffff, false}, /* 0x2229c */ 129 + {BCS, RING_MI_MODE(BLT_RING_BASE), 0xffff, false}, /* 0x2209c */ 130 + {BCS, RING_INSTPM(BLT_RING_BASE), 0xffff, false}, /* 0x220c0 */ 131 + {BCS, RING_HWSTAM(BLT_RING_BASE), 0x0, false}, /* 0x22098 */ 132 + {BCS, RING_EXCC(BLT_RING_BASE), 0x0, false}, /* 0x22028 */ 102 133 103 - {RCS, _MMIO(0x40e0), 0, false}, 104 - {RCS, _MMIO(0x40e4), 0, false}, 105 - {RCS, _MMIO(0x2580), 0xffff, true}, 106 - {RCS, _MMIO(0x7014), 0xffff, true}, 107 - {RCS, _MMIO(0x20ec), 0xffff, false}, 108 - {RCS, _MMIO(0xb118), 0, false}, 109 - {RCS, _MMIO(0xe100), 0xffff, true}, 110 - {RCS, _MMIO(0xe180), 0xffff, true}, 111 - {RCS, _MMIO(0xe184), 0xffff, true}, 112 - {RCS, _MMIO(0xe188), 0xffff, true}, 113 - {RCS, _MMIO(0xe194), 0xffff, true}, 114 - {RCS, _MMIO(0x4de0), 0, false}, 115 - {RCS, _MMIO(0x4de4), 0, false}, 116 - {RCS, _MMIO(0x4de8), 0, false}, 117 - {RCS, _MMIO(0x4dec), 0, false}, 118 - {RCS, _MMIO(0x4df0), 0, false}, 119 - {RCS, _MMIO(0x4df4), 0, false}, 134 + {VCS2, RING_EXCC(GEN8_BSD2_RING_BASE), 0xffff, false}, /* 0x1c028 */ 120 135 121 - {BCS, _MMIO(0x2229c), 0xffff, false}, 122 - {BCS, _MMIO(0x2209c), 0xffff, false}, 123 - {BCS, _MMIO(0x220c0), 0xffff, false}, 124 - {BCS, _MMIO(0x22098), 0x0, false}, 125 - {BCS, _MMIO(0x22028), 0x0, false}, 136 + {VECS, RING_EXCC(VEBOX_RING_BASE), 0xffff, false}, /* 0x1a028 */ 126 137 127 - {VCS2, _MMIO(0x1c028), 0xffff, false}, 138 + {RCS, GEN8_HDC_CHICKEN1, 0xffff, true}, /* 0x7304 */ 139 + {RCS, GEN9_CTX_PREEMPT_REG, 0x0, false}, /* 0x2248 */ 140 + {RCS, GEN7_UCGCTL4, 0x0, false}, /* 0x940c */ 141 + {RCS, GAMT_CHKN_BIT_REG, 0x0, false}, /* 0x4ab8 */ 128 142 129 - {VECS, _MMIO(0x1a028), 0xffff, false}, 143 + {RCS, GEN9_GAMT_ECO_REG_RW_IA, 0x0, false}, /* 0x4ab0 */ 144 + {RCS, GEN9_CSFE_CHICKEN1_RCS, 0x0, false}, /* 0x20d4 */ 130 145 131 - {RCS, _MMIO(0x7304), 0xffff, true}, 132 - {RCS, _MMIO(0x2248), 0x0, false}, 133 - {RCS, _MMIO(0x940c), 0x0, false}, 134 - {RCS, _MMIO(0x4ab8), 0x0, false}, 135 - 136 - {RCS, _MMIO(0x4ab0), 0x0, false}, 137 - {RCS, _MMIO(0x20d4), 0x0, false}, 138 - 139 - {RCS, _MMIO(0xb004), 0x0, false}, 140 - {RCS, _MMIO(0x20a0), 0x0, false}, 141 - {RCS, _MMIO(0x20e4), 0xffff, false}, 146 + {RCS, GEN8_GARBCNTL, 0x0, false}, /* 0xb004 */ 147 + {RCS, GEN7_FF_THREAD_MODE, 0x0, false}, /* 0x20a0 */ 148 + {RCS, FF_SLICE_CS_CHICKEN2, 0xffff, false}, /* 0x20e4 */ 149 + { /* Terminated */ } 142 150 }; 143 151 144 152 static u32 gen9_render_mocs[I915_NUM_ENGINES][64]; ··· 275 267 u32 ctx_ctrl = reg_state[CTX_CONTEXT_CONTROL_VAL]; 276 268 u32 inhibit_mask = 277 269 _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); 278 - i915_reg_t last_reg = _MMIO(0); 279 - struct render_mmio *mmio; 270 + struct engine_mmio *mmio; 280 271 u32 v; 281 - int i, array_size; 282 272 283 - if (IS_SKYLAKE(vgpu->gvt->dev_priv) 284 - || IS_KABYLAKE(vgpu->gvt->dev_priv)) { 285 - mmio = gen9_render_mmio_list; 286 - array_size = ARRAY_SIZE(gen9_render_mmio_list); 273 + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) 287 274 load_mocs(vgpu, ring_id); 288 - } else { 289 - mmio = gen8_render_mmio_list; 290 - array_size = ARRAY_SIZE(gen8_render_mmio_list); 291 - } 292 275 293 - for (i = 0; i < array_size; i++, mmio++) { 276 + mmio = vgpu->gvt->engine_mmio_list; 277 + while (i915_mmio_reg_offset((mmio++)->reg)) { 294 278 if (mmio->ring_id != ring_id) 295 279 continue; 296 280 ··· 303 303 v = vgpu_vreg(vgpu, mmio->reg); 304 304 305 305 I915_WRITE_FW(mmio->reg, v); 306 - last_reg = mmio->reg; 307 306 308 307 trace_render_mmio(vgpu->id, "load", 309 308 i915_mmio_reg_offset(mmio->reg), 310 309 mmio->value, v); 311 310 } 312 - 313 - /* Make sure the swiched MMIOs has taken effect. */ 314 - if (likely(INTEL_GVT_MMIO_OFFSET(last_reg))) 315 - I915_READ_FW(last_reg); 316 311 317 312 handle_tlb_pending_event(vgpu, ring_id); 318 313 } ··· 316 321 static void switch_mmio_to_host(struct intel_vgpu *vgpu, int ring_id) 317 322 { 318 323 struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 319 - struct render_mmio *mmio; 320 - i915_reg_t last_reg = _MMIO(0); 324 + struct engine_mmio *mmio; 321 325 u32 v; 322 - int i, array_size; 323 326 324 - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { 325 - mmio = gen9_render_mmio_list; 326 - array_size = ARRAY_SIZE(gen9_render_mmio_list); 327 + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) 327 328 restore_mocs(vgpu, ring_id); 328 - } else { 329 - mmio = gen8_render_mmio_list; 330 - array_size = ARRAY_SIZE(gen8_render_mmio_list); 331 - } 332 329 333 - for (i = 0; i < array_size; i++, mmio++) { 330 + mmio = vgpu->gvt->engine_mmio_list; 331 + while (i915_mmio_reg_offset((mmio++)->reg)) { 334 332 if (mmio->ring_id != ring_id) 335 333 continue; 336 334 ··· 339 351 continue; 340 352 341 353 I915_WRITE_FW(mmio->reg, v); 342 - last_reg = mmio->reg; 343 354 344 355 trace_render_mmio(vgpu->id, "restore", 345 356 i915_mmio_reg_offset(mmio->reg), 346 357 mmio->value, v); 347 358 } 348 - 349 - /* Make sure the swiched MMIOs has taken effect. */ 350 - if (likely(INTEL_GVT_MMIO_OFFSET(last_reg))) 351 - I915_READ_FW(last_reg); 352 359 } 353 360 354 361 /** ··· 386 403 switch_mmio_to_vgpu(next, ring_id); 387 404 388 405 intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 406 + } 407 + 408 + /** 409 + * intel_gvt_init_engine_mmio_context - Initiate the engine mmio list 410 + * @gvt: GVT device 411 + * 412 + */ 413 + void intel_gvt_init_engine_mmio_context(struct intel_gvt *gvt) 414 + { 415 + if (IS_SKYLAKE(gvt->dev_priv) || IS_KABYLAKE(gvt->dev_priv)) 416 + gvt->engine_mmio_list = gen9_engine_mmio_list; 417 + else 418 + gvt->engine_mmio_list = gen8_engine_mmio_list; 389 419 }
+36 -12
drivers/gpu/drm/i915/gvt/render.h drivers/gpu/drm/i915/gvt/dmabuf.h
··· 1 1 /* 2 - * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 2 + * Copyright(c) 2017 Intel Corporation. All rights reserved. 3 3 * 4 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 5 * copy of this software and associated documentation files (the "Software"), ··· 21 21 * SOFTWARE. 22 22 * 23 23 * Authors: 24 - * Eddie Dong <eddie.dong@intel.com> 25 - * Kevin Tian <kevin.tian@intel.com> 24 + * Zhiyuan Lv <zhiyuan.lv@intel.com> 26 25 * 27 26 * Contributors: 28 - * Zhi Wang <zhi.a.wang@intel.com> 29 - * Changbin Du <changbin.du@intel.com> 30 - * Zhenyu Wang <zhenyuw@linux.intel.com> 27 + * Xiaoguang Chen 31 28 * Tina Zhang <tina.zhang@intel.com> 32 - * Bing Niu <bing.niu@intel.com> 33 - * 34 29 */ 35 30 36 - #ifndef __GVT_RENDER_H__ 37 - #define __GVT_RENDER_H__ 31 + #ifndef _GVT_DMABUF_H_ 32 + #define _GVT_DMABUF_H_ 33 + #include <linux/vfio.h> 38 34 39 - void intel_gvt_switch_mmio(struct intel_vgpu *pre, 40 - struct intel_vgpu *next, int ring_id); 35 + struct intel_vgpu_fb_info { 36 + __u64 start; 37 + __u64 start_gpa; 38 + __u64 drm_format_mod; 39 + __u32 drm_format; /* drm format of plane */ 40 + __u32 width; /* width of plane */ 41 + __u32 height; /* height of plane */ 42 + __u32 stride; /* stride of plane */ 43 + __u32 size; /* size of plane in bytes, align on page */ 44 + __u32 x_pos; /* horizontal position of cursor plane */ 45 + __u32 y_pos; /* vertical position of cursor plane */ 46 + __u32 x_hot; /* horizontal position of cursor hotspot */ 47 + __u32 y_hot; /* vertical position of cursor hotspot */ 48 + struct intel_vgpu_dmabuf_obj *obj; 49 + }; 41 50 51 + /** 52 + * struct intel_vgpu_dmabuf_obj- Intel vGPU device buffer object 53 + */ 54 + struct intel_vgpu_dmabuf_obj { 55 + struct intel_vgpu *vgpu; 56 + struct intel_vgpu_fb_info *info; 57 + __u32 dmabuf_id; 58 + struct kref kref; 59 + bool initref; 60 + struct list_head list; 61 + }; 62 + 63 + int intel_vgpu_query_plane(struct intel_vgpu *vgpu, void *args); 64 + int intel_vgpu_get_dmabuf(struct intel_vgpu *vgpu, unsigned int dmabuf_id); 65 + void intel_vgpu_dmabuf_cleanup(struct intel_vgpu *vgpu); 42 66 43 67 #endif
+5
drivers/gpu/drm/i915/gvt/sched_policy.c
··· 372 372 vgpu->gvt->scheduler.sched_ops->start_schedule(vgpu); 373 373 } 374 374 375 + void intel_gvt_kick_schedule(struct intel_gvt *gvt) 376 + { 377 + intel_gvt_request_service(gvt, INTEL_GVT_REQUEST_EVENT_SCHED); 378 + } 379 + 375 380 void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu) 376 381 { 377 382 struct intel_gvt_workload_scheduler *scheduler =
+2
drivers/gpu/drm/i915/gvt/sched_policy.h
··· 57 57 58 58 void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu); 59 59 60 + void intel_gvt_kick_schedule(struct intel_gvt *gvt); 61 + 60 62 #endif
+16 -1
drivers/gpu/drm/i915/gvt/scheduler.c
··· 248 248 return 0; 249 249 } 250 250 251 - void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) 251 + static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) 252 252 { 253 253 if (!wa_ctx->indirect_ctx.obj) 254 254 return; ··· 1039 1039 if (IS_ERR(s->shadow_ctx)) 1040 1040 return PTR_ERR(s->shadow_ctx); 1041 1041 1042 + if (HAS_LOGICAL_RING_PREEMPTION(vgpu->gvt->dev_priv)) 1043 + s->shadow_ctx->priority = INT_MAX; 1044 + 1042 1045 bitmap_zero(s->shadow_ctx_desc_updated, I915_NUM_ENGINES); 1043 1046 1044 1047 s->workloads = kmem_cache_create("gvt-g_vgpu_workload", ··· 1333 1330 } 1334 1331 1335 1332 return workload; 1333 + } 1334 + 1335 + /** 1336 + * intel_vgpu_queue_workload - Qeue a vGPU workload 1337 + * @workload: the workload to queue in 1338 + */ 1339 + void intel_vgpu_queue_workload(struct intel_vgpu_workload *workload) 1340 + { 1341 + list_add_tail(&workload->list, 1342 + workload_q_head(workload->vgpu, workload->ring_id)); 1343 + intel_gvt_kick_schedule(workload->vgpu->gvt); 1344 + wake_up(&workload->vgpu->gvt->scheduler.waitq[workload->ring_id]); 1336 1345 }
+1 -6
drivers/gpu/drm/i915/gvt/scheduler.h
··· 125 125 #define workload_q_head(vgpu, ring_id) \ 126 126 (&(vgpu->submission.workload_q_head[ring_id])) 127 127 128 - #define queue_workload(workload) do { \ 129 - list_add_tail(&workload->list, \ 130 - workload_q_head(workload->vgpu, workload->ring_id)); \ 131 - wake_up(&workload->vgpu->gvt-> \ 132 - scheduler.waitq[workload->ring_id]); \ 133 - } while (0) 128 + void intel_vgpu_queue_workload(struct intel_vgpu_workload *workload); 134 129 135 130 int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt); 136 131
+15 -2
drivers/gpu/drm/i915/gvt/vgpu.c
··· 236 236 } 237 237 238 238 intel_vgpu_stop_schedule(vgpu); 239 + intel_vgpu_dmabuf_cleanup(vgpu); 239 240 240 241 mutex_unlock(&gvt->lock); 241 242 } ··· 266 265 intel_gvt_hypervisor_detach_vgpu(vgpu); 267 266 intel_vgpu_free_resource(vgpu); 268 267 intel_vgpu_clean_mmio(vgpu); 268 + intel_vgpu_dmabuf_cleanup(vgpu); 269 269 vfree(vgpu); 270 270 271 271 intel_gvt_update_vgpu_types(gvt); ··· 351 349 vgpu->handle = param->handle; 352 350 vgpu->gvt = gvt; 353 351 vgpu->sched_ctl.weight = param->weight; 354 - 352 + INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head); 353 + idr_init(&vgpu->object_idr); 355 354 intel_vgpu_init_cfg_space(vgpu, param->primary); 356 355 357 356 ret = intel_vgpu_init_mmio(vgpu); ··· 373 370 if (ret) 374 371 goto out_detach_hypervisor_vgpu; 375 372 376 - ret = intel_vgpu_init_display(vgpu, param->resolution); 373 + ret = intel_vgpu_init_opregion(vgpu); 377 374 if (ret) 378 375 goto out_clean_gtt; 376 + 377 + ret = intel_vgpu_init_display(vgpu, param->resolution); 378 + if (ret) 379 + goto out_clean_opregion; 379 380 380 381 ret = intel_vgpu_setup_submission(vgpu); 381 382 if (ret) ··· 393 386 if (ret) 394 387 goto out_clean_sched_policy; 395 388 389 + ret = intel_gvt_hypervisor_set_opregion(vgpu); 390 + if (ret) 391 + goto out_clean_sched_policy; 392 + 396 393 mutex_unlock(&gvt->lock); 397 394 398 395 return vgpu; ··· 407 396 intel_vgpu_clean_submission(vgpu); 408 397 out_clean_display: 409 398 intel_vgpu_clean_display(vgpu); 399 + out_clean_opregion: 400 + intel_vgpu_clean_opregion(vgpu); 410 401 out_clean_gtt: 411 402 intel_vgpu_clean_gtt(vgpu); 412 403 out_detach_hypervisor_vgpu:
+7 -41
drivers/gpu/drm/i915/i915_debugfs.c
··· 111 111 u64 size = 0; 112 112 struct i915_vma *vma; 113 113 114 - list_for_each_entry(vma, &obj->vma_list, obj_link) { 115 - if (i915_vma_is_ggtt(vma) && drm_mm_node_allocated(&vma->node)) 114 + for_each_ggtt_vma(vma, obj) { 115 + if (drm_mm_node_allocated(&vma->node)) 116 116 size += vma->node.size; 117 117 } 118 118 ··· 522 522 seq_printf(m, "%u display objects (globally pinned), %llu bytes\n", 523 523 dpy_count, dpy_size); 524 524 525 - seq_printf(m, "%llu [%llu] gtt total\n", 526 - ggtt->base.total, ggtt->mappable_end); 525 + seq_printf(m, "%llu [%pa] gtt total\n", 526 + ggtt->base.total, &ggtt->mappable_end); 527 527 seq_printf(m, "Supported page sizes: %s\n", 528 528 stringify_page_sizes(INTEL_INFO(dev_priv)->page_sizes, 529 529 buf, sizeof(buf))); ··· 663 663 664 664 return 0; 665 665 } 666 - 667 - static void i915_ring_seqno_info(struct seq_file *m, 668 - struct intel_engine_cs *engine) 669 - { 670 - struct intel_breadcrumbs *b = &engine->breadcrumbs; 671 - struct rb_node *rb; 672 - 673 - seq_printf(m, "Current sequence (%s): %x\n", 674 - engine->name, intel_engine_get_seqno(engine)); 675 - 676 - spin_lock_irq(&b->rb_lock); 677 - for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { 678 - struct intel_wait *w = rb_entry(rb, typeof(*w), node); 679 - 680 - seq_printf(m, "Waiting (%s): %s [%d] on %x\n", 681 - engine->name, w->tsk->comm, w->tsk->pid, w->seqno); 682 - } 683 - spin_unlock_irq(&b->rb_lock); 684 - } 685 - 686 - static int i915_gem_seqno_info(struct seq_file *m, void *data) 687 - { 688 - struct drm_i915_private *dev_priv = node_to_i915(m->private); 689 - struct intel_engine_cs *engine; 690 - enum intel_engine_id id; 691 - 692 - for_each_engine(engine, dev_priv, id) 693 - i915_ring_seqno_info(m, engine); 694 - 695 - return 0; 696 - } 697 - 698 666 699 667 static int i915_interrupt_info(struct seq_file *m, void *data) 700 668 { ··· 864 896 seq_printf(m, "Graphics Interrupt mask: %08x\n", 865 897 I915_READ(GTIMR)); 866 898 } 867 - for_each_engine(engine, dev_priv, id) { 868 - if (INTEL_GEN(dev_priv) >= 6) { 899 + if (INTEL_GEN(dev_priv) >= 6) { 900 + for_each_engine(engine, dev_priv, id) { 869 901 seq_printf(m, 870 902 "Graphics Interrupt mask (%s): %08x\n", 871 903 engine->name, I915_READ_IMR(engine)); 872 904 } 873 - i915_ring_seqno_info(m, engine); 874 905 } 875 906 intel_runtime_pm_put(dev_priv); 876 907 ··· 3180 3213 3181 3214 p = drm_seq_file_printer(m); 3182 3215 for_each_engine(engine, dev_priv, id) 3183 - intel_engine_dump(engine, &p); 3216 + intel_engine_dump(engine, &p, "%s\n", engine->name); 3184 3217 3185 3218 intel_runtime_pm_put(dev_priv); 3186 3219 ··· 4639 4672 {"i915_gem_objects", i915_gem_object_info, 0}, 4640 4673 {"i915_gem_gtt", i915_gem_gtt_info, 0}, 4641 4674 {"i915_gem_stolen", i915_gem_stolen_list_info }, 4642 - {"i915_gem_seqno", i915_gem_seqno_info, 0}, 4643 4675 {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0}, 4644 4676 {"i915_gem_interrupt", i915_interrupt_info, 0}, 4645 4677 {"i915_gem_batch_pool", i915_gem_batch_pool_info, 0},
+24 -5
drivers/gpu/drm/i915/i915_drv.c
··· 617 617 618 618 mutex_lock(&dev_priv->drm.struct_mutex); 619 619 intel_uc_fini_hw(dev_priv); 620 + intel_uc_fini(dev_priv); 620 621 i915_gem_cleanup_engines(dev_priv); 621 622 i915_gem_contexts_fini(dev_priv); 622 623 mutex_unlock(&dev_priv->drm.struct_mutex); 623 624 625 + intel_uc_fini_wq(dev_priv); 624 626 i915_gem_cleanup_userptr(dev_priv); 625 627 626 628 i915_gem_drain_freed_objects(dev_priv); ··· 728 726 if (!ap) 729 727 return -ENOMEM; 730 728 731 - ap->ranges[0].base = ggtt->mappable_base; 729 + ap->ranges[0].base = ggtt->gmadr.start; 732 730 ap->ranges[0].size = ggtt->mappable_end; 733 731 734 732 primary = ··· 1899 1897 disable_irq(i915->drm.irq); 1900 1898 ret = i915_gem_reset_prepare(i915); 1901 1899 if (ret) { 1902 - DRM_ERROR("GPU recovery failed\n"); 1900 + dev_err(i915->drm.dev, "GPU recovery failed\n"); 1903 1901 intel_gpu_reset(i915, ALL_ENGINES); 1904 - goto error; 1902 + goto taint; 1905 1903 } 1906 1904 1907 1905 if (!intel_has_gpu_reset(i915)) { 1908 - DRM_DEBUG_DRIVER("GPU reset disabled\n"); 1906 + if (i915_modparams.reset) 1907 + dev_err(i915->drm.dev, "GPU reset not supported\n"); 1908 + else 1909 + DRM_DEBUG_DRIVER("GPU reset disabled\n"); 1909 1910 goto error; 1910 1911 } 1911 1912 ··· 1921 1916 } 1922 1917 if (ret) { 1923 1918 dev_err(i915->drm.dev, "Failed to reset chip\n"); 1924 - goto error; 1919 + goto taint; 1925 1920 } 1926 1921 1927 1922 i915_gem_reset(i915); ··· 1964 1959 wake_up_bit(&error->flags, I915_RESET_HANDOFF); 1965 1960 return; 1966 1961 1962 + taint: 1963 + /* 1964 + * History tells us that if we cannot reset the GPU now, we 1965 + * never will. This then impacts everything that is run 1966 + * subsequently. On failing the reset, we mark the driver 1967 + * as wedged, preventing further execution on the GPU. 1968 + * We also want to go one step further and add a taint to the 1969 + * kernel so that any subsequent faults can be traced back to 1970 + * this failure. This is important for CI, where if the 1971 + * GPU/driver fails we would like to reboot and restart testing 1972 + * rather than continue on into oblivion. For everyone else, 1973 + * the system should still plod along, but they have been warned! 1974 + */ 1975 + add_taint(TAINT_WARN, LOCKDEP_STILL_OK); 1967 1976 error: 1968 1977 i915_gem_set_wedged(i915); 1969 1978 i915_gem_retire_requests(i915);
+44 -9
drivers/gpu/drm/i915/i915_drv.h
··· 80 80 81 81 #define DRIVER_NAME "i915" 82 82 #define DRIVER_DESC "Intel Graphics" 83 - #define DRIVER_DATE "20171201" 84 - #define DRIVER_TIMESTAMP 1512176839 83 + #define DRIVER_DATE "20171214" 84 + #define DRIVER_TIMESTAMP 1513282202 85 85 86 86 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and 87 87 * WARN_ON()) for hw state sanity checks to check for unexpected conditions ··· 398 398 POWER_DOMAIN_AUX_D, 399 399 POWER_DOMAIN_GMBUS, 400 400 POWER_DOMAIN_MODESET, 401 + POWER_DOMAIN_GT_IRQ, 401 402 POWER_DOMAIN_INIT, 402 403 403 404 POWER_DOMAIN_NUM, ··· 1538 1537 */ 1539 1538 struct pagevec wc_stash; 1540 1539 1541 - /** Usable portion of the GTT for GEM */ 1542 - dma_addr_t stolen_base; /* limited to low memory (32-bit) */ 1543 - 1544 1540 /** 1545 1541 * tmpfs instance used for shmem backed objects 1546 1542 */ ··· 1585 1587 loff_t start; 1586 1588 loff_t pos; 1587 1589 }; 1590 + 1591 + #define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */ 1588 1592 1589 1593 #define I915_RESET_TIMEOUT (10 * HZ) /* 10s */ 1590 1594 #define I915_FENCE_TIMEOUT (10 * HZ) /* 10s */ ··· 2252 2252 struct kmem_cache *priorities; 2253 2253 2254 2254 const struct intel_device_info info; 2255 + 2256 + /** 2257 + * Data Stolen Memory - aka "i915 stolen memory" gives us the start and 2258 + * end of stolen which we can optionally use to create GEM objects 2259 + * backed by stolen memory. Note that stolen_usable_size tells us 2260 + * exactly how much of this we are actually allowed to use, given that 2261 + * some portion of it is in fact reserved for use by hardware functions. 2262 + */ 2263 + struct resource dsm; 2264 + /** 2265 + * Reseved portion of Data Stolen Memory 2266 + */ 2267 + struct resource dsm_reserved; 2268 + 2269 + /* 2270 + * Stolen memory is segmented in hardware with different portions 2271 + * offlimits to certain functions. 2272 + * 2273 + * The drm_mm is initialised to the total accessible range, as found 2274 + * from the PCI config. On Broadwell+, this is further restricted to 2275 + * avoid the first page! The upper end of stolen memory is reserved for 2276 + * hardware functions and similarly removed from the accessible range. 2277 + */ 2278 + resource_size_t stolen_usable_size; /* Total size minus reserved ranges */ 2255 2279 2256 2280 void __iomem *regs; 2257 2281 ··· 3258 3234 #define HAS_GUC_CT(dev_priv) ((dev_priv)->info.has_guc_ct) 3259 3235 #define HAS_GUC_UCODE(dev_priv) (HAS_GUC(dev_priv)) 3260 3236 #define HAS_GUC_SCHED(dev_priv) (HAS_GUC(dev_priv)) 3237 + 3238 + /* For now, anything with a GuC has also HuC */ 3239 + #define HAS_HUC(dev_priv) (HAS_GUC(dev_priv)) 3261 3240 #define HAS_HUC_UCODE(dev_priv) (HAS_GUC(dev_priv)) 3241 + 3242 + /* Having a GuC is not the same as using a GuC */ 3243 + #define USES_GUC(dev_priv) intel_uc_is_using_guc() 3244 + #define USES_GUC_SUBMISSION(dev_priv) intel_uc_is_using_guc_submission() 3245 + #define USES_HUC(dev_priv) intel_uc_is_using_huc() 3262 3246 3263 3247 #define HAS_RESOURCE_STREAMER(dev_priv) ((dev_priv)->info.has_resource_streamer) 3264 3248 ··· 3911 3879 unsigned int flags); 3912 3880 int i915_gem_evict_vm(struct i915_address_space *vm); 3913 3881 3882 + void i915_gem_flush_ggtt_writes(struct drm_i915_private *dev_priv); 3883 + 3914 3884 /* belongs in i915_gem_gtt.h */ 3915 3885 static inline void i915_gem_chipset_flush(struct drm_i915_private *dev_priv) 3916 3886 { ··· 3934 3900 int i915_gem_init_stolen(struct drm_i915_private *dev_priv); 3935 3901 void i915_gem_cleanup_stolen(struct drm_device *dev); 3936 3902 struct drm_i915_gem_object * 3937 - i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, u32 size); 3903 + i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, 3904 + resource_size_t size); 3938 3905 struct drm_i915_gem_object * 3939 3906 i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv, 3940 - u32 stolen_offset, 3941 - u32 gtt_offset, 3942 - u32 size); 3907 + resource_size_t stolen_offset, 3908 + resource_size_t gtt_offset, 3909 + resource_size_t size); 3943 3910 3944 3911 /* i915_gem_internal.c */ 3945 3912 struct drm_i915_gem_object *
+140 -60
drivers/gpu/drm/i915/i915_gem.c
··· 330 330 * must wait for all rendering to complete to the object (as unbinding 331 331 * must anyway), and retire the requests. 332 332 */ 333 - ret = i915_gem_object_wait(obj, 334 - I915_WAIT_INTERRUPTIBLE | 335 - I915_WAIT_LOCKED | 336 - I915_WAIT_ALL, 337 - MAX_SCHEDULE_TIMEOUT, 338 - NULL); 333 + ret = i915_gem_object_set_to_cpu_domain(obj, false); 339 334 if (ret) 340 335 return ret; 341 - 342 - i915_gem_retire_requests(to_i915(obj->base.dev)); 343 336 344 337 while ((vma = list_first_entry_or_null(&obj->vma_list, 345 338 struct i915_vma, ··· 666 673 obj->frontbuffer_ggtt_origin : ORIGIN_CPU); 667 674 } 668 675 669 - static void 670 - flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains) 676 + void i915_gem_flush_ggtt_writes(struct drm_i915_private *dev_priv) 671 677 { 672 - struct drm_i915_private *dev_priv = to_i915(obj->base.dev); 673 - 674 - if (!(obj->base.write_domain & flush_domains)) 675 - return; 676 - 677 - /* No actual flushing is required for the GTT write domain. Writes 678 - * to it "immediately" go to main memory as far as we know, so there's 679 - * no chipset flush. It also doesn't land in render cache. 678 + /* 679 + * No actual flushing is required for the GTT write domain for reads 680 + * from the GTT domain. Writes to it "immediately" go to main memory 681 + * as far as we know, so there's no chipset flush. It also doesn't 682 + * land in the GPU render cache. 680 683 * 681 684 * However, we do have to enforce the order so that all writes through 682 685 * the GTT land before any writes to the device, such as updates to ··· 683 694 * timing. This issue has only been observed when switching quickly 684 695 * between GTT writes and CPU reads from inside the kernel on recent hw, 685 696 * and it appears to only affect discrete GTT blocks (i.e. on LLC 686 - * system agents we cannot reproduce this behaviour). 697 + * system agents we cannot reproduce this behaviour, until Cannonlake 698 + * that was!). 687 699 */ 700 + 688 701 wmb(); 702 + 703 + intel_runtime_pm_get(dev_priv); 704 + spin_lock_irq(&dev_priv->uncore.lock); 705 + 706 + POSTING_READ_FW(RING_HEAD(RENDER_RING_BASE)); 707 + 708 + spin_unlock_irq(&dev_priv->uncore.lock); 709 + intel_runtime_pm_put(dev_priv); 710 + } 711 + 712 + static void 713 + flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains) 714 + { 715 + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); 716 + struct i915_vma *vma; 717 + 718 + if (!(obj->base.write_domain & flush_domains)) 719 + return; 689 720 690 721 switch (obj->base.write_domain) { 691 722 case I915_GEM_DOMAIN_GTT: 692 - if (!HAS_LLC(dev_priv)) { 693 - intel_runtime_pm_get(dev_priv); 694 - spin_lock_irq(&dev_priv->uncore.lock); 695 - POSTING_READ_FW(RING_HEAD(dev_priv->engine[RCS]->mmio_base)); 696 - spin_unlock_irq(&dev_priv->uncore.lock); 697 - intel_runtime_pm_put(dev_priv); 698 - } 723 + i915_gem_flush_ggtt_writes(dev_priv); 699 724 700 725 intel_fb_obj_flush(obj, 701 726 fb_write_origin(obj, I915_GEM_DOMAIN_GTT)); 727 + 728 + for_each_ggtt_vma(vma, obj) { 729 + if (vma->iomap) 730 + continue; 731 + 732 + i915_vma_unset_ggtt_write(vma); 733 + } 702 734 break; 703 735 704 736 case I915_GEM_DOMAIN_CPU: ··· 1116 1106 page_base += offset & PAGE_MASK; 1117 1107 } 1118 1108 1119 - if (gtt_user_read(&ggtt->mappable, page_base, page_offset, 1109 + if (gtt_user_read(&ggtt->iomap, page_base, page_offset, 1120 1110 user_data, page_length)) { 1121 1111 ret = -EFAULT; 1122 1112 break; ··· 1324 1314 * If the object is non-shmem backed, we retry again with the 1325 1315 * path that handles page fault. 1326 1316 */ 1327 - if (ggtt_write(&ggtt->mappable, page_base, page_offset, 1317 + if (ggtt_write(&ggtt->iomap, page_base, page_offset, 1328 1318 user_data, page_length)) { 1329 1319 ret = -EFAULT; 1330 1320 break; ··· 1566 1556 1567 1557 GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); 1568 1558 1569 - list_for_each_entry(vma, &obj->vma_list, obj_link) { 1570 - if (!i915_vma_is_ggtt(vma)) 1571 - break; 1572 - 1559 + for_each_ggtt_vma(vma, obj) { 1573 1560 if (i915_vma_is_active(vma)) 1574 1561 continue; 1575 1562 ··· 1967 1960 /* Finally, remap it using the new GTT offset */ 1968 1961 ret = remap_io_mapping(area, 1969 1962 area->vm_start + (vma->ggtt_view.partial.offset << PAGE_SHIFT), 1970 - (ggtt->mappable_base + vma->node.start) >> PAGE_SHIFT, 1963 + (ggtt->gmadr.start + vma->node.start) >> PAGE_SHIFT, 1971 1964 min_t(u64, vma->size, area->vm_end - area->vm_start), 1972 - &ggtt->mappable); 1965 + &ggtt->iomap); 1973 1966 if (ret) 1974 1967 goto err_fence; 1975 1968 ··· 1978 1971 if (!i915_vma_set_userfault(vma) && !obj->userfault_count++) 1979 1972 list_add(&obj->userfault_link, &dev_priv->mm.userfault_list); 1980 1973 GEM_BUG_ON(!obj->userfault_count); 1974 + 1975 + i915_vma_set_ggtt_write(vma); 1981 1976 1982 1977 err_fence: 1983 1978 i915_vma_unpin_fence(vma); ··· 2045 2036 drm_vma_node_unmap(&obj->base.vma_node, 2046 2037 obj->base.dev->anon_inode->i_mapping); 2047 2038 2048 - list_for_each_entry(vma, &obj->vma_list, obj_link) { 2049 - if (!i915_vma_is_ggtt(vma)) 2050 - break; 2051 - 2039 + for_each_ggtt_vma(vma, obj) 2052 2040 i915_vma_unset_userfault(vma); 2053 - } 2054 2041 } 2055 2042 2056 2043 /** ··· 3333 3328 * Wait for last execlists context complete, but bail out in case a 3334 3329 * new request is submitted. 3335 3330 */ 3336 - end = ktime_add_ms(ktime_get(), 200); 3331 + end = ktime_add_ms(ktime_get(), I915_IDLE_ENGINES_TIMEOUT); 3337 3332 do { 3338 3333 if (new_requests_since_last_retire(dev_priv)) 3339 3334 return; ··· 3386 3381 3387 3382 if (INTEL_GEN(dev_priv) >= 6) 3388 3383 gen6_rps_idle(dev_priv); 3384 + 3385 + intel_display_power_put(dev_priv, POWER_DOMAIN_GT_IRQ); 3386 + 3389 3387 intel_runtime_pm_put(dev_priv); 3390 3388 out_unlock: 3391 3389 mutex_unlock(&dev_priv->drm.struct_mutex); ··· 3533 3525 3534 3526 static int wait_for_engines(struct drm_i915_private *i915) 3535 3527 { 3536 - if (wait_for(intel_engines_are_idle(i915), 50)) { 3537 - DRM_ERROR("Failed to idle engines, declaring wedged!\n"); 3528 + if (wait_for(intel_engines_are_idle(i915), I915_IDLE_ENGINES_TIMEOUT)) { 3529 + dev_err(i915->drm.dev, 3530 + "Failed to idle engines, declaring wedged!\n"); 3531 + if (drm_debug & DRM_UT_DRIVER) { 3532 + struct drm_printer p = drm_debug_printer(__func__); 3533 + struct intel_engine_cs *engine; 3534 + enum intel_engine_id id; 3535 + 3536 + for_each_engine(engine, i915, id) 3537 + intel_engine_dump(engine, &p, 3538 + "%s", engine->name); 3539 + } 3540 + 3538 3541 i915_gem_set_wedged(i915); 3539 3542 return -EIO; 3540 3543 } ··· 3571 3552 if (ret) 3572 3553 return ret; 3573 3554 } 3574 - 3575 3555 i915_gem_retire_requests(i915); 3576 - GEM_BUG_ON(i915->gt.active_requests); 3577 3556 3578 3557 ret = wait_for_engines(i915); 3579 3558 } else { ··· 3770 3753 return -EBUSY; 3771 3754 } 3772 3755 3773 - if (i915_gem_valid_gtt_space(vma, cache_level)) 3756 + if (!i915_vma_is_closed(vma) && 3757 + i915_gem_valid_gtt_space(vma, cache_level)) 3774 3758 continue; 3775 3759 3776 3760 ret = i915_vma_unbind(vma); ··· 3824 3806 * dropped the fence as all snoopable access is 3825 3807 * supposed to be linear. 3826 3808 */ 3827 - list_for_each_entry(vma, &obj->vma_list, obj_link) { 3809 + for_each_ggtt_vma(vma, obj) { 3828 3810 ret = i915_vma_put_fence(vma); 3829 3811 if (ret) 3830 3812 return ret; ··· 4865 4847 i915_gem_restore_gtt_mappings(i915); 4866 4848 i915_gem_restore_fences(i915); 4867 4849 4868 - /* As we didn't flush the kernel context before suspend, we cannot 4850 + /* 4851 + * As we didn't flush the kernel context before suspend, we cannot 4869 4852 * guarantee that the context image is complete. So let's just reset 4870 4853 * it and start again. 4871 4854 */ ··· 4887 4868 return; 4888 4869 4889 4870 err_wedged: 4890 - DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); 4891 - i915_gem_set_wedged(i915); 4871 + if (!i915_terminally_wedged(&i915->gpu_error)) { 4872 + DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); 4873 + i915_gem_set_wedged(i915); 4874 + } 4892 4875 goto out_unlock; 4893 4876 } 4894 4877 ··· 5163 5142 if (ret) 5164 5143 return ret; 5165 5144 5145 + ret = intel_uc_init_wq(dev_priv); 5146 + if (ret) 5147 + return ret; 5148 + 5166 5149 /* This is just a security blanket to placate dragons. 5167 5150 * On some systems, we very sporadically observe that the first TLBs 5168 5151 * used by the CS may be stale, despite us poking the TLB reset. If ··· 5177 5152 intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 5178 5153 5179 5154 ret = i915_gem_init_ggtt(dev_priv); 5180 - if (ret) 5181 - goto out_unlock; 5155 + if (ret) { 5156 + GEM_BUG_ON(ret == -EIO); 5157 + goto err_unlock; 5158 + } 5182 5159 5183 5160 ret = i915_gem_contexts_init(dev_priv); 5184 - if (ret) 5185 - goto out_unlock; 5161 + if (ret) { 5162 + GEM_BUG_ON(ret == -EIO); 5163 + goto err_ggtt; 5164 + } 5186 5165 5187 5166 ret = intel_engines_init(dev_priv); 5188 - if (ret) 5189 - goto out_unlock; 5167 + if (ret) { 5168 + GEM_BUG_ON(ret == -EIO); 5169 + goto err_context; 5170 + } 5190 5171 5191 5172 intel_init_gt_powersave(dev_priv); 5192 5173 5174 + ret = intel_uc_init(dev_priv); 5175 + if (ret) 5176 + goto err_pm; 5177 + 5193 5178 ret = i915_gem_init_hw(dev_priv); 5194 5179 if (ret) 5195 - goto out_unlock; 5180 + goto err_uc_init; 5196 5181 5197 5182 /* 5198 5183 * Despite its name intel_init_clock_gating applies both display ··· 5216 5181 intel_init_clock_gating(dev_priv); 5217 5182 5218 5183 ret = __intel_engines_record_defaults(dev_priv); 5219 - out_unlock: 5184 + if (ret) 5185 + goto err_init_hw; 5186 + 5187 + if (i915_inject_load_failure()) { 5188 + ret = -ENODEV; 5189 + goto err_init_hw; 5190 + } 5191 + 5192 + if (i915_inject_load_failure()) { 5193 + ret = -EIO; 5194 + goto err_init_hw; 5195 + } 5196 + 5197 + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 5198 + mutex_unlock(&dev_priv->drm.struct_mutex); 5199 + 5200 + return 0; 5201 + 5202 + /* 5203 + * Unwinding is complicated by that we want to handle -EIO to mean 5204 + * disable GPU submission but keep KMS alive. We want to mark the 5205 + * HW as irrevisibly wedged, but keep enough state around that the 5206 + * driver doesn't explode during runtime. 5207 + */ 5208 + err_init_hw: 5209 + i915_gem_wait_for_idle(dev_priv, I915_WAIT_LOCKED); 5210 + i915_gem_contexts_lost(dev_priv); 5211 + intel_uc_fini_hw(dev_priv); 5212 + err_uc_init: 5213 + intel_uc_fini(dev_priv); 5214 + err_pm: 5215 + if (ret != -EIO) { 5216 + intel_cleanup_gt_powersave(dev_priv); 5217 + i915_gem_cleanup_engines(dev_priv); 5218 + } 5219 + err_context: 5220 + if (ret != -EIO) 5221 + i915_gem_contexts_fini(dev_priv); 5222 + err_ggtt: 5223 + err_unlock: 5224 + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 5225 + mutex_unlock(&dev_priv->drm.struct_mutex); 5226 + 5227 + if (ret != -EIO) 5228 + i915_gem_cleanup_userptr(dev_priv); 5229 + 5220 5230 if (ret == -EIO) { 5221 - /* Allow engine initialisation to fail by marking the GPU as 5231 + /* 5232 + * Allow engine initialisation to fail by marking the GPU as 5222 5233 * wedged. But we only want to do this where the GPU is angry, 5223 5234 * for all other failure, such as an allocation failure, bail. 5224 5235 */ ··· 5274 5193 } 5275 5194 ret = 0; 5276 5195 } 5277 - intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 5278 - mutex_unlock(&dev_priv->drm.struct_mutex); 5279 5196 5197 + i915_gem_drain_freed_objects(dev_priv); 5280 5198 return ret; 5281 5199 } 5282 5200
+1 -1
drivers/gpu/drm/i915/i915_gem_clflush.c
··· 167 167 i915_sw_fence_await_reservation(&clflush->wait, 168 168 obj->resv, NULL, 169 169 true, I915_FENCE_TIMEOUT, 170 - GFP_KERNEL); 170 + I915_FENCE_GFP); 171 171 172 172 reservation_object_lock(obj->resv, NULL); 173 173 reservation_object_add_excl_fence(obj->resv, &clflush->dma);
+3 -3
drivers/gpu/drm/i915/i915_gem_context.c
··· 316 316 * present or not in use we still need a small bias as ring wraparound 317 317 * at offset 0 sometimes hangs. No idea why. 318 318 */ 319 - if (HAS_GUC(dev_priv) && i915_modparams.enable_guc_loading) 319 + if (USES_GUC(dev_priv)) 320 320 ctx->ggtt_offset_bias = GUC_WOPCM_TOP; 321 321 else 322 322 ctx->ggtt_offset_bias = I915_GTT_PAGE_SIZE; ··· 409 409 i915_gem_context_set_closed(ctx); /* not user accessible */ 410 410 i915_gem_context_clear_bannable(ctx); 411 411 i915_gem_context_set_force_single_submission(ctx); 412 - if (!i915_modparams.enable_guc_submission) 412 + if (!USES_GUC_SUBMISSION(to_i915(dev))) 413 413 ctx->ring_size = 512 * PAGE_SIZE; /* Max ring buffer size */ 414 414 415 415 GEM_BUG_ON(i915_gem_context_is_kernel(ctx)); ··· 617 617 if (prev) 618 618 i915_sw_fence_await_sw_fence_gfp(&req->submit, 619 619 &prev->submit, 620 - GFP_KERNEL); 620 + I915_FENCE_GFP); 621 621 } 622 622 623 623 /*
+1 -1
drivers/gpu/drm/i915/i915_gem_execbuffer.c
··· 1012 1012 offset += page << PAGE_SHIFT; 1013 1013 } 1014 1014 1015 - vaddr = (void __force *)io_mapping_map_atomic_wc(&ggtt->mappable, 1015 + vaddr = (void __force *)io_mapping_map_atomic_wc(&ggtt->iomap, 1016 1016 offset); 1017 1017 cache->page = page; 1018 1018 cache->vaddr = (unsigned long)vaddr;
+33 -73
drivers/gpu/drm/i915/i915_gem_gtt.c
··· 2912 2912 mutex_unlock(&dev_priv->drm.struct_mutex); 2913 2913 2914 2914 arch_phys_wc_del(ggtt->mtrr); 2915 - io_mapping_fini(&ggtt->mappable); 2915 + io_mapping_fini(&ggtt->iomap); 2916 2916 } 2917 2917 2918 2918 static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) ··· 2947 2947 return 1 << (20 + gmch_ctrl); 2948 2948 2949 2949 return 0; 2950 - } 2951 - 2952 - static size_t gen6_get_stolen_size(u16 snb_gmch_ctl) 2953 - { 2954 - snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT; 2955 - snb_gmch_ctl &= SNB_GMCH_GMS_MASK; 2956 - return (size_t)snb_gmch_ctl << 25; /* 32 MB units */ 2957 - } 2958 - 2959 - static size_t gen8_get_stolen_size(u16 bdw_gmch_ctl) 2960 - { 2961 - bdw_gmch_ctl >>= BDW_GMCH_GMS_SHIFT; 2962 - bdw_gmch_ctl &= BDW_GMCH_GMS_MASK; 2963 - return (size_t)bdw_gmch_ctl << 25; /* 32 MB units */ 2964 - } 2965 - 2966 - static size_t chv_get_stolen_size(u16 gmch_ctrl) 2967 - { 2968 - gmch_ctrl >>= SNB_GMCH_GMS_SHIFT; 2969 - gmch_ctrl &= SNB_GMCH_GMS_MASK; 2970 - 2971 - /* 2972 - * 0x0 to 0x10: 32MB increments starting at 0MB 2973 - * 0x11 to 0x16: 4MB increments starting at 8MB 2974 - * 0x17 to 0x1d: 4MB increments start at 36MB 2975 - */ 2976 - if (gmch_ctrl < 0x11) 2977 - return (size_t)gmch_ctrl << 25; 2978 - else if (gmch_ctrl < 0x17) 2979 - return (size_t)(gmch_ctrl - 0x11 + 2) << 22; 2980 - else 2981 - return (size_t)(gmch_ctrl - 0x17 + 9) << 22; 2982 - } 2983 - 2984 - static size_t gen9_get_stolen_size(u16 gen9_gmch_ctl) 2985 - { 2986 - gen9_gmch_ctl >>= BDW_GMCH_GMS_SHIFT; 2987 - gen9_gmch_ctl &= BDW_GMCH_GMS_MASK; 2988 - 2989 - if (gen9_gmch_ctl < 0xf0) 2990 - return (size_t)gen9_gmch_ctl << 25; /* 32 MB units */ 2991 - else 2992 - /* 4MB increments starting at 0xf0 for 4MB */ 2993 - return (size_t)(gen9_gmch_ctl - 0xf0 + 1) << 22; 2994 2950 } 2995 2951 2996 2952 static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) ··· 3288 3332 int err; 3289 3333 3290 3334 /* TODO: We're not aware of mappable constraints on gen8 yet */ 3291 - ggtt->mappable_base = pci_resource_start(pdev, 2); 3292 - ggtt->mappable_end = pci_resource_len(pdev, 2); 3335 + ggtt->gmadr = 3336 + (struct resource) DEFINE_RES_MEM(pci_resource_start(pdev, 2), 3337 + pci_resource_len(pdev, 2)); 3338 + ggtt->mappable_end = resource_size(&ggtt->gmadr); 3293 3339 3294 3340 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(39)); 3295 3341 if (!err) ··· 3302 3344 pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); 3303 3345 3304 3346 if (INTEL_GEN(dev_priv) >= 9) { 3305 - ggtt->stolen_size = gen9_get_stolen_size(snb_gmch_ctl); 3306 3347 size = gen8_get_total_gtt_size(snb_gmch_ctl); 3307 3348 } else if (IS_CHERRYVIEW(dev_priv)) { 3308 - ggtt->stolen_size = chv_get_stolen_size(snb_gmch_ctl); 3309 3349 size = chv_get_total_gtt_size(snb_gmch_ctl); 3310 3350 } else { 3311 - ggtt->stolen_size = gen8_get_stolen_size(snb_gmch_ctl); 3312 3351 size = gen8_get_total_gtt_size(snb_gmch_ctl); 3313 3352 } 3314 3353 ··· 3345 3390 u16 snb_gmch_ctl; 3346 3391 int err; 3347 3392 3348 - ggtt->mappable_base = pci_resource_start(pdev, 2); 3349 - ggtt->mappable_end = pci_resource_len(pdev, 2); 3393 + ggtt->gmadr = 3394 + (struct resource) DEFINE_RES_MEM(pci_resource_start(pdev, 2), 3395 + pci_resource_len(pdev, 2)); 3396 + ggtt->mappable_end = resource_size(&ggtt->gmadr); 3350 3397 3351 3398 /* 64/512MB is the current min/max we actually know of, but this is just 3352 3399 * a coarse sanity check. 3353 3400 */ 3354 3401 if (ggtt->mappable_end < (64<<20) || ggtt->mappable_end > (512<<20)) { 3355 - DRM_ERROR("Unknown GMADR size (%llx)\n", ggtt->mappable_end); 3402 + DRM_ERROR("Unknown GMADR size (%pa)\n", &ggtt->mappable_end); 3356 3403 return -ENXIO; 3357 3404 } 3358 3405 ··· 3364 3407 if (err) 3365 3408 DRM_ERROR("Can't set DMA mask/consistent mask (%d)\n", err); 3366 3409 pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); 3367 - 3368 - ggtt->stolen_size = gen6_get_stolen_size(snb_gmch_ctl); 3369 3410 3370 3411 size = gen6_get_total_gtt_size(snb_gmch_ctl); 3371 3412 ggtt->base.total = (size / sizeof(gen6_pte_t)) << PAGE_SHIFT; ··· 3401 3446 static int i915_gmch_probe(struct i915_ggtt *ggtt) 3402 3447 { 3403 3448 struct drm_i915_private *dev_priv = ggtt->base.i915; 3449 + phys_addr_t gmadr_base; 3404 3450 int ret; 3405 3451 3406 3452 ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->drm.pdev, NULL); ··· 3411 3455 } 3412 3456 3413 3457 intel_gtt_get(&ggtt->base.total, 3414 - &ggtt->stolen_size, 3415 - &ggtt->mappable_base, 3458 + &gmadr_base, 3416 3459 &ggtt->mappable_end); 3460 + 3461 + ggtt->gmadr = 3462 + (struct resource) DEFINE_RES_MEM(gmadr_base, 3463 + ggtt->mappable_end); 3417 3464 3418 3465 ggtt->do_idle_maps = needs_idle_maps(dev_priv); 3419 3466 ggtt->base.insert_page = i915_ggtt_insert_page; ··· 3462 3503 * currently don't have any bits spare to pass in this upper 3463 3504 * restriction! 3464 3505 */ 3465 - if (HAS_GUC(dev_priv) && i915_modparams.enable_guc_loading) { 3506 + if (USES_GUC(dev_priv)) { 3466 3507 ggtt->base.total = min_t(u64, ggtt->base.total, GUC_GGTT_TOP); 3467 - ggtt->mappable_end = min(ggtt->mappable_end, ggtt->base.total); 3508 + ggtt->mappable_end = min_t(u64, ggtt->mappable_end, ggtt->base.total); 3468 3509 } 3469 3510 3470 3511 if ((ggtt->base.total - 1) >> 32) { ··· 3472 3513 " of address space! Found %lldM!\n", 3473 3514 ggtt->base.total >> 20); 3474 3515 ggtt->base.total = 1ULL << 32; 3475 - ggtt->mappable_end = min(ggtt->mappable_end, ggtt->base.total); 3516 + ggtt->mappable_end = min_t(u64, ggtt->mappable_end, ggtt->base.total); 3476 3517 } 3477 3518 3478 3519 if (ggtt->mappable_end > ggtt->base.total) { 3479 3520 DRM_ERROR("mappable aperture extends past end of GGTT," 3480 - " aperture=%llx, total=%llx\n", 3481 - ggtt->mappable_end, ggtt->base.total); 3521 + " aperture=%pa, total=%llx\n", 3522 + &ggtt->mappable_end, ggtt->base.total); 3482 3523 ggtt->mappable_end = ggtt->base.total; 3483 3524 } 3484 3525 3485 3526 /* GMADR is the PCI mmio aperture into the global GTT. */ 3486 - DRM_INFO("Memory usable by graphics device = %lluM\n", 3487 - ggtt->base.total >> 20); 3488 - DRM_DEBUG_DRIVER("GMADR size = %lldM\n", ggtt->mappable_end >> 20); 3489 - DRM_DEBUG_DRIVER("GTT stolen size = %uM\n", ggtt->stolen_size >> 20); 3527 + DRM_DEBUG_DRIVER("GGTT size = %lluM\n", ggtt->base.total >> 20); 3528 + DRM_DEBUG_DRIVER("GMADR size = %lluM\n", (u64)ggtt->mappable_end >> 20); 3529 + DRM_DEBUG_DRIVER("DSM size = %lluM\n", 3530 + (u64)resource_size(&intel_graphics_stolen_res) >> 20); 3490 3531 if (intel_vtd_active()) 3491 3532 DRM_INFO("VT-d active for gfx access\n"); 3492 3533 ··· 3515 3556 ggtt->base.mm.color_adjust = i915_gtt_color_adjust; 3516 3557 mutex_unlock(&dev_priv->drm.struct_mutex); 3517 3558 3518 - if (!io_mapping_init_wc(&dev_priv->ggtt.mappable, 3519 - dev_priv->ggtt.mappable_base, 3559 + if (!io_mapping_init_wc(&dev_priv->ggtt.iomap, 3560 + dev_priv->ggtt.gmadr.start, 3520 3561 dev_priv->ggtt.mappable_end)) { 3521 3562 ret = -EIO; 3522 3563 goto out_gtt_cleanup; 3523 3564 } 3524 3565 3525 - ggtt->mtrr = arch_phys_wc_add(ggtt->mappable_base, ggtt->mappable_end); 3566 + ggtt->mtrr = arch_phys_wc_add(ggtt->gmadr.start, ggtt->mappable_end); 3526 3567 3527 3568 /* 3528 3569 * Initialise stolen early so that we may reserve preallocated ··· 3552 3593 GEM_BUG_ON(i915->ggtt.invalidate != gen6_ggtt_invalidate); 3553 3594 3554 3595 i915->ggtt.invalidate = guc_ggtt_invalidate; 3596 + 3597 + i915_ggtt_invalidate(i915); 3555 3598 } 3556 3599 3557 3600 void i915_ggtt_disable_guc(struct drm_i915_private *i915) ··· 3562 3601 GEM_BUG_ON(i915->ggtt.invalidate != guc_ggtt_invalidate); 3563 3602 3564 3603 i915->ggtt.invalidate = gen6_ggtt_invalidate; 3604 + 3605 + i915_ggtt_invalidate(i915); 3565 3606 } 3566 3607 3567 3608 void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv) ··· 3583 3620 bool ggtt_bound = false; 3584 3621 struct i915_vma *vma; 3585 3622 3586 - list_for_each_entry(vma, &obj->vma_list, obj_link) { 3587 - if (vma->vm != &ggtt->base) 3588 - continue; 3589 - 3623 + for_each_ggtt_vma(vma, obj) { 3590 3624 if (!i915_vma_unbind(vma)) 3591 3625 continue; 3592 3626
+3 -16
drivers/gpu/drm/i915/i915_gem_gtt.h
··· 368 368 */ 369 369 struct i915_ggtt { 370 370 struct i915_address_space base; 371 - struct io_mapping mappable; /* Mapping to our CPU mappable region */ 372 371 373 - phys_addr_t mappable_base; /* PA of our GMADR */ 374 - u64 mappable_end; /* End offset that we can CPU map */ 375 - 376 - /* Stolen memory is segmented in hardware with different portions 377 - * offlimits to certain functions. 378 - * 379 - * The drm_mm is initialised to the total accessible range, as found 380 - * from the PCI config. On Broadwell+, this is further restricted to 381 - * avoid the first page! The upper end of stolen memory is reserved for 382 - * hardware functions and similarly removed from the accessible range. 383 - */ 384 - u32 stolen_size; /* Total size of stolen memory */ 385 - u32 stolen_usable_size; /* Total size minus reserved ranges */ 386 - u32 stolen_reserved_base; 387 - u32 stolen_reserved_size; 372 + struct io_mapping iomap; /* Mapping to our CPU mappable region */ 373 + struct resource gmadr; /* GMADR resource */ 374 + resource_size_t mappable_end; /* End offset that we can CPU map */ 388 375 389 376 /** "Graphics Stolen Memory" holds the global PTEs */ 390 377 void __iomem *gsm;
+2
drivers/gpu/drm/i915/i915_gem_object.h
··· 261 261 } userptr; 262 262 263 263 unsigned long scratch; 264 + 265 + void *gvt_info; 264 266 }; 265 267 266 268 /** for phys allocated objects */
+32 -7
drivers/gpu/drm/i915/i915_gem_request.c
··· 252 252 GEM_BUG_ON(!i915->gt.active_requests); 253 253 254 254 intel_runtime_pm_get_noresume(i915); 255 + 256 + /* 257 + * It seems that the DMC likes to transition between the DC states a lot 258 + * when there are no connected displays (no active power domains) during 259 + * command submission. 260 + * 261 + * This activity has negative impact on the performance of the chip with 262 + * huge latencies observed in the interrupt handler and elsewhere. 263 + * 264 + * Work around it by grabbing a GT IRQ power domain whilst there is any 265 + * GT activity, preventing any DC state transitions. 266 + */ 267 + intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ); 268 + 255 269 i915->gt.awake = true; 256 270 257 271 intel_enable_gt_powersave(i915); ··· 677 663 * 678 664 * Do not use kmem_cache_zalloc() here! 679 665 */ 680 - req = kmem_cache_alloc(dev_priv->requests, GFP_KERNEL); 681 - if (!req) { 682 - ret = -ENOMEM; 683 - goto err_unreserve; 666 + req = kmem_cache_alloc(dev_priv->requests, 667 + GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); 668 + if (unlikely(!req)) { 669 + /* Ratelimit ourselves to prevent oom from malicious clients */ 670 + ret = i915_gem_wait_for_idle(dev_priv, 671 + I915_WAIT_LOCKED | 672 + I915_WAIT_INTERRUPTIBLE); 673 + if (ret) 674 + goto err_unreserve; 675 + 676 + req = kmem_cache_alloc(dev_priv->requests, GFP_KERNEL); 677 + if (!req) { 678 + ret = -ENOMEM; 679 + goto err_unreserve; 680 + } 684 681 } 685 682 686 683 req->timeline = i915_gem_context_lookup_timeline(ctx, engine); ··· 793 768 if (to->engine == from->engine) { 794 769 ret = i915_sw_fence_await_sw_fence_gfp(&to->submit, 795 770 &from->submit, 796 - GFP_KERNEL); 771 + I915_FENCE_GFP); 797 772 return ret < 0 ? ret : 0; 798 773 } 799 774 ··· 821 796 await_dma_fence: 822 797 ret = i915_sw_fence_await_dma_fence(&to->submit, 823 798 &from->fence, 0, 824 - GFP_KERNEL); 799 + I915_FENCE_GFP); 825 800 return ret < 0 ? ret : 0; 826 801 } 827 802 ··· 872 847 else 873 848 ret = i915_sw_fence_await_dma_fence(&req->submit, fence, 874 849 I915_FENCE_TIMEOUT, 875 - GFP_KERNEL); 850 + I915_FENCE_GFP); 876 851 if (ret < 0) 877 852 return ret; 878 853
+2
drivers/gpu/drm/i915/i915_gem_request.h
··· 204 204 struct list_head client_link; 205 205 }; 206 206 207 + #define I915_FENCE_GFP (GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN) 208 + 207 209 extern const struct dma_fence_ops i915_fence_ops; 208 210 209 211 static inline bool dma_fence_is_i915(const struct dma_fence *fence)
+79 -192
drivers/gpu/drm/i915/i915_gem_stolen.c
··· 30 30 #include <drm/i915_drm.h> 31 31 #include "i915_drv.h" 32 32 33 - #define KB(x) ((x) * 1024) 34 - #define MB(x) (KB(x) * 1024) 35 - 36 33 /* 37 34 * The BIOS typically reserves some of the system's memory for the exclusive 38 35 * use of the integrated graphics. This memory is no longer available for ··· 76 79 mutex_unlock(&dev_priv->mm.stolen_lock); 77 80 } 78 81 79 - static dma_addr_t i915_stolen_to_dma(struct drm_i915_private *dev_priv) 82 + static int i915_adjust_stolen(struct drm_i915_private *dev_priv, 83 + struct resource *dsm) 80 84 { 81 - struct pci_dev *pdev = dev_priv->drm.pdev; 82 85 struct i915_ggtt *ggtt = &dev_priv->ggtt; 83 86 struct resource *r; 84 - dma_addr_t base; 85 87 86 - /* Almost universally we can find the Graphics Base of Stolen Memory 87 - * at register BSM (0x5c) in the igfx configuration space. On a few 88 - * (desktop) machines this is also mirrored in the bridge device at 89 - * different locations, or in the MCHBAR. 90 - * 91 - * On 865 we just check the TOUD register. 92 - * 93 - * On 830/845/85x the stolen memory base isn't available in any 94 - * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size. 95 - * 88 + if (dsm->start == 0 || dsm->end <= dsm->start) 89 + return -EINVAL; 90 + 91 + /* 92 + * TODO: We have yet too encounter the case where the GTT wasn't at the 93 + * end of stolen. With that assumption we could simplify this. 96 94 */ 97 - base = 0; 98 - if (INTEL_GEN(dev_priv) >= 3) { 99 - u32 bsm; 100 95 101 - pci_read_config_dword(pdev, INTEL_BSM, &bsm); 102 - 103 - base = bsm & INTEL_BSM_MASK; 104 - } else if (IS_I865G(dev_priv)) { 105 - u32 tseg_size = 0; 106 - u16 toud = 0; 107 - u8 tmp; 108 - 109 - pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), 110 - I845_ESMRAMC, &tmp); 111 - 112 - if (tmp & TSEG_ENABLE) { 113 - switch (tmp & I845_TSEG_SIZE_MASK) { 114 - case I845_TSEG_SIZE_512K: 115 - tseg_size = KB(512); 116 - break; 117 - case I845_TSEG_SIZE_1M: 118 - tseg_size = MB(1); 119 - break; 120 - } 121 - } 122 - 123 - pci_bus_read_config_word(pdev->bus, PCI_DEVFN(0, 0), 124 - I865_TOUD, &toud); 125 - 126 - base = (toud << 16) + tseg_size; 127 - } else if (IS_I85X(dev_priv)) { 128 - u32 tseg_size = 0; 129 - u32 tom; 130 - u8 tmp; 131 - 132 - pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), 133 - I85X_ESMRAMC, &tmp); 134 - 135 - if (tmp & TSEG_ENABLE) 136 - tseg_size = MB(1); 137 - 138 - pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 1), 139 - I85X_DRB3, &tmp); 140 - tom = tmp * MB(32); 141 - 142 - base = tom - tseg_size - ggtt->stolen_size; 143 - } else if (IS_I845G(dev_priv)) { 144 - u32 tseg_size = 0; 145 - u32 tom; 146 - u8 tmp; 147 - 148 - pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), 149 - I845_ESMRAMC, &tmp); 150 - 151 - if (tmp & TSEG_ENABLE) { 152 - switch (tmp & I845_TSEG_SIZE_MASK) { 153 - case I845_TSEG_SIZE_512K: 154 - tseg_size = KB(512); 155 - break; 156 - case I845_TSEG_SIZE_1M: 157 - tseg_size = MB(1); 158 - break; 159 - } 160 - } 161 - 162 - pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), 163 - I830_DRB3, &tmp); 164 - tom = tmp * MB(32); 165 - 166 - base = tom - tseg_size - ggtt->stolen_size; 167 - } else if (IS_I830(dev_priv)) { 168 - u32 tseg_size = 0; 169 - u32 tom; 170 - u8 tmp; 171 - 172 - pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), 173 - I830_ESMRAMC, &tmp); 174 - 175 - if (tmp & TSEG_ENABLE) { 176 - if (tmp & I830_TSEG_SIZE_1M) 177 - tseg_size = MB(1); 178 - else 179 - tseg_size = KB(512); 180 - } 181 - 182 - pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), 183 - I830_DRB3, &tmp); 184 - tom = tmp * MB(32); 185 - 186 - base = tom - tseg_size - ggtt->stolen_size; 187 - } 188 - 189 - if (base == 0 || add_overflows(base, ggtt->stolen_size)) 190 - return 0; 191 - 192 - /* make sure we don't clobber the GTT if it's within stolen memory */ 96 + /* Make sure we don't clobber the GTT if it's within stolen memory */ 193 97 if (INTEL_GEN(dev_priv) <= 4 && 194 98 !IS_G33(dev_priv) && !IS_PINEVIEW(dev_priv) && !IS_G4X(dev_priv)) { 195 - struct { 196 - dma_addr_t start, end; 197 - } stolen[2] = { 198 - { .start = base, .end = base + ggtt->stolen_size, }, 199 - { .start = base, .end = base + ggtt->stolen_size, }, 200 - }; 201 - u64 ggtt_start, ggtt_end; 99 + struct resource stolen[2] = {*dsm, *dsm}; 100 + struct resource ggtt_res; 101 + resource_size_t ggtt_start; 202 102 203 103 ggtt_start = I915_READ(PGTBL_CTL); 204 104 if (IS_GEN4(dev_priv)) ··· 103 209 (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28; 104 210 else 105 211 ggtt_start &= PGTBL_ADDRESS_LO_MASK; 106 - ggtt_end = ggtt_start + ggtt_total_entries(ggtt) * 4; 107 212 108 - if (ggtt_start >= stolen[0].start && ggtt_start < stolen[0].end) 109 - stolen[0].end = ggtt_start; 110 - if (ggtt_end > stolen[1].start && ggtt_end <= stolen[1].end) 111 - stolen[1].start = ggtt_end; 213 + ggtt_res = 214 + (struct resource) DEFINE_RES_MEM(ggtt_start, 215 + ggtt_total_entries(ggtt) * 4); 112 216 113 - /* pick the larger of the two chunks */ 114 - if (stolen[0].end - stolen[0].start > 115 - stolen[1].end - stolen[1].start) { 116 - base = stolen[0].start; 117 - ggtt->stolen_size = stolen[0].end - stolen[0].start; 118 - } else { 119 - base = stolen[1].start; 120 - ggtt->stolen_size = stolen[1].end - stolen[1].start; 121 - } 217 + if (ggtt_res.start >= stolen[0].start && ggtt_res.start < stolen[0].end) 218 + stolen[0].end = ggtt_res.start; 219 + if (ggtt_res.end > stolen[1].start && ggtt_res.end <= stolen[1].end) 220 + stolen[1].start = ggtt_res.end; 221 + 222 + /* Pick the larger of the two chunks */ 223 + if (resource_size(&stolen[0]) > resource_size(&stolen[1])) 224 + *dsm = stolen[0]; 225 + else 226 + *dsm = stolen[1]; 122 227 123 228 if (stolen[0].start != stolen[1].start || 124 229 stolen[0].end != stolen[1].end) { 125 - dma_addr_t end = base + ggtt->stolen_size - 1; 126 - 127 - DRM_DEBUG_KMS("GTT within stolen memory at 0x%llx-0x%llx\n", 128 - (unsigned long long)ggtt_start, 129 - (unsigned long long)ggtt_end - 1); 130 - DRM_DEBUG_KMS("Stolen memory adjusted to %pad - %pad\n", 131 - &base, &end); 230 + DRM_DEBUG_KMS("GTT within stolen memory at %pR\n", &ggtt_res); 231 + DRM_DEBUG_KMS("Stolen memory adjusted to %pR\n", dsm); 132 232 } 133 233 } 134 234 135 - 136 - /* Verify that nothing else uses this physical address. Stolen 235 + /* 236 + * Verify that nothing else uses this physical address. Stolen 137 237 * memory should be reserved by the BIOS and hidden from the 138 238 * kernel. So if the region is already marked as busy, something 139 239 * is seriously wrong. 140 240 */ 141 - r = devm_request_mem_region(dev_priv->drm.dev, base, ggtt->stolen_size, 241 + r = devm_request_mem_region(dev_priv->drm.dev, dsm->start, 242 + resource_size(dsm), 142 243 "Graphics Stolen Memory"); 143 244 if (r == NULL) { 144 245 /* 145 246 * One more attempt but this time requesting region from 146 - * base + 1, as we have seen that this resolves the region 247 + * start + 1, as we have seen that this resolves the region 147 248 * conflict with the PCI Bus. 148 249 * This is a BIOS w/a: Some BIOS wrap stolen in the root 149 250 * PCI bus, but have an off-by-one error. Hence retry the 150 251 * reservation starting from 1 instead of 0. 151 252 * There's also BIOS with off-by-one on the other end. 152 253 */ 153 - r = devm_request_mem_region(dev_priv->drm.dev, base + 1, 154 - ggtt->stolen_size - 2, 254 + r = devm_request_mem_region(dev_priv->drm.dev, dsm->start + 1, 255 + resource_size(dsm) - 2, 155 256 "Graphics Stolen Memory"); 156 257 /* 157 258 * GEN3 firmware likes to smash pci bridges into the stolen 158 259 * range. Apparently this works. 159 260 */ 160 261 if (r == NULL && !IS_GEN3(dev_priv)) { 161 - dma_addr_t end = base + ggtt->stolen_size; 262 + DRM_ERROR("conflict detected with stolen region: %pR\n", 263 + dsm); 162 264 163 - DRM_ERROR("conflict detected with stolen region: [%pad - %pad]\n", 164 - &base, &end); 165 - base = 0; 265 + return -EBUSY; 166 266 } 167 267 } 168 268 169 - return base; 269 + return 0; 170 270 } 171 271 172 272 void i915_gem_cleanup_stolen(struct drm_device *dev) ··· 174 286 } 175 287 176 288 static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, 177 - dma_addr_t *base, u32 *size) 289 + resource_size_t *base, resource_size_t *size) 178 290 { 179 - struct i915_ggtt *ggtt = &dev_priv->ggtt; 180 291 uint32_t reg_val = I915_READ(IS_GM45(dev_priv) ? 181 292 CTG_STOLEN_RESERVED : 182 293 ELK_STOLEN_RESERVED); 183 - dma_addr_t stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size; 294 + resource_size_t stolen_top = dev_priv->dsm.end + 1; 184 295 185 296 if ((reg_val & G4X_STOLEN_RESERVED_ENABLE) == 0) { 186 297 *base = 0; ··· 208 321 } 209 322 210 323 static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv, 211 - dma_addr_t *base, u32 *size) 324 + resource_size_t *base, resource_size_t *size) 212 325 { 213 326 uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); 214 327 ··· 240 353 } 241 354 242 355 static void gen7_get_stolen_reserved(struct drm_i915_private *dev_priv, 243 - dma_addr_t *base, u32 *size) 356 + resource_size_t *base, resource_size_t *size) 244 357 { 245 358 uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); 246 359 ··· 266 379 } 267 380 268 381 static void chv_get_stolen_reserved(struct drm_i915_private *dev_priv, 269 - dma_addr_t *base, u32 *size) 382 + resource_size_t *base, resource_size_t *size) 270 383 { 271 384 uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); 272 385 ··· 298 411 } 299 412 300 413 static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv, 301 - dma_addr_t *base, u32 *size) 414 + resource_size_t *base, resource_size_t *size) 302 415 { 303 - struct i915_ggtt *ggtt = &dev_priv->ggtt; 304 416 uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); 305 - dma_addr_t stolen_top; 417 + resource_size_t stolen_top; 306 418 307 419 if ((reg_val & GEN6_STOLEN_RESERVED_ENABLE) == 0) { 308 420 *base = 0; ··· 309 423 return; 310 424 } 311 425 312 - stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size; 426 + stolen_top = dev_priv->dsm.end + 1; 313 427 314 428 *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; 315 429 ··· 325 439 326 440 int i915_gem_init_stolen(struct drm_i915_private *dev_priv) 327 441 { 328 - struct i915_ggtt *ggtt = &dev_priv->ggtt; 329 - dma_addr_t reserved_base, stolen_top; 330 - u32 reserved_total, reserved_size; 331 - u32 stolen_usable_start; 442 + resource_size_t reserved_base, stolen_top; 443 + resource_size_t reserved_total, reserved_size; 444 + resource_size_t stolen_usable_start; 332 445 333 446 mutex_init(&dev_priv->mm.stolen_lock); 334 447 ··· 341 456 return 0; 342 457 } 343 458 344 - if (ggtt->stolen_size == 0) 459 + if (resource_size(&intel_graphics_stolen_res) == 0) 345 460 return 0; 346 461 347 - dev_priv->mm.stolen_base = i915_stolen_to_dma(dev_priv); 348 - if (dev_priv->mm.stolen_base == 0) 462 + dev_priv->dsm = intel_graphics_stolen_res; 463 + 464 + if (i915_adjust_stolen(dev_priv, &dev_priv->dsm)) 349 465 return 0; 350 466 351 - stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size; 467 + GEM_BUG_ON(dev_priv->dsm.start == 0); 468 + GEM_BUG_ON(dev_priv->dsm.end <= dev_priv->dsm.start); 469 + 470 + stolen_top = dev_priv->dsm.end + 1; 352 471 reserved_base = 0; 353 472 reserved_size = 0; 354 473 ··· 393 504 reserved_base = stolen_top; 394 505 } 395 506 396 - if (reserved_base < dev_priv->mm.stolen_base || 397 - reserved_base + reserved_size > stolen_top) { 398 - dma_addr_t reserved_top = reserved_base + reserved_size; 399 - DRM_ERROR("Stolen reserved area [%pad - %pad] outside stolen memory [%pad - %pad]\n", 400 - &reserved_base, &reserved_top, 401 - &dev_priv->mm.stolen_base, &stolen_top); 507 + dev_priv->dsm_reserved = 508 + (struct resource) DEFINE_RES_MEM(reserved_base, reserved_size); 509 + 510 + if (!resource_contains(&dev_priv->dsm, &dev_priv->dsm_reserved)) { 511 + DRM_ERROR("Stolen reserved area %pR outside stolen memory %pR\n", 512 + &dev_priv->dsm_reserved, &dev_priv->dsm); 402 513 return 0; 403 514 } 404 - 405 - ggtt->stolen_reserved_base = reserved_base; 406 - ggtt->stolen_reserved_size = reserved_size; 407 515 408 516 /* It is possible for the reserved area to end before the end of stolen 409 517 * memory, so just consider the start. */ 410 518 reserved_total = stolen_top - reserved_base; 411 519 412 - DRM_DEBUG_KMS("Memory reserved for graphics device: %uK, usable: %uK\n", 413 - ggtt->stolen_size >> 10, 414 - (ggtt->stolen_size - reserved_total) >> 10); 520 + DRM_DEBUG_KMS("Memory reserved for graphics device: %lluK, usable: %lluK\n", 521 + (u64)resource_size(&dev_priv->dsm) >> 10, 522 + ((u64)resource_size(&dev_priv->dsm) - reserved_total) >> 10); 415 523 416 524 stolen_usable_start = 0; 417 525 /* WaSkipStolenMemoryFirstPage:bdw+ */ 418 526 if (INTEL_GEN(dev_priv) >= 8) 419 527 stolen_usable_start = 4096; 420 528 421 - ggtt->stolen_usable_size = 422 - ggtt->stolen_size - reserved_total - stolen_usable_start; 529 + dev_priv->stolen_usable_size = 530 + resource_size(&dev_priv->dsm) - reserved_total - stolen_usable_start; 423 531 424 532 /* Basic memrange allocator for stolen space. */ 425 533 drm_mm_init(&dev_priv->mm.stolen, stolen_usable_start, 426 - ggtt->stolen_usable_size); 534 + dev_priv->stolen_usable_size); 427 535 428 536 return 0; 429 537 } 430 538 431 539 static struct sg_table * 432 540 i915_pages_create_for_stolen(struct drm_device *dev, 433 - u32 offset, u32 size) 541 + resource_size_t offset, resource_size_t size) 434 542 { 435 543 struct drm_i915_private *dev_priv = to_i915(dev); 436 544 struct sg_table *st; 437 545 struct scatterlist *sg; 438 546 439 - GEM_BUG_ON(range_overflows(offset, size, dev_priv->ggtt.stolen_size)); 547 + GEM_BUG_ON(range_overflows(offset, size, resource_size(&dev_priv->dsm))); 440 548 441 549 /* We hide that we have no struct page backing our stolen object 442 550 * by wrapping the contiguous physical allocation with a fake ··· 453 567 sg->offset = 0; 454 568 sg->length = size; 455 569 456 - sg_dma_address(sg) = (dma_addr_t)dev_priv->mm.stolen_base + offset; 570 + sg_dma_address(sg) = (dma_addr_t)dev_priv->dsm.start + offset; 457 571 sg_dma_len(sg) = size; 458 572 459 573 return st; ··· 531 645 } 532 646 533 647 struct drm_i915_gem_object * 534 - i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, u32 size) 648 + i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, 649 + resource_size_t size) 535 650 { 536 651 struct drm_i915_gem_object *obj; 537 652 struct drm_mm_node *stolen; ··· 565 678 566 679 struct drm_i915_gem_object * 567 680 i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv, 568 - u32 stolen_offset, 569 - u32 gtt_offset, 570 - u32 size) 681 + resource_size_t stolen_offset, 682 + resource_size_t gtt_offset, 683 + resource_size_t size) 571 684 { 572 685 struct i915_ggtt *ggtt = &dev_priv->ggtt; 573 686 struct drm_i915_gem_object *obj; ··· 580 693 581 694 lockdep_assert_held(&dev_priv->drm.struct_mutex); 582 695 583 - DRM_DEBUG_KMS("creating preallocated stolen object: stolen_offset=%x, gtt_offset=%x, size=%x\n", 584 - stolen_offset, gtt_offset, size); 696 + DRM_DEBUG_KMS("creating preallocated stolen object: stolen_offset=%pa, gtt_offset=%pa, size=%pa\n", 697 + &stolen_offset, &gtt_offset, &size); 585 698 586 699 /* KISS and expect everything to be page-aligned */ 587 700 if (WARN_ON(size == 0) ||
+2 -8
drivers/gpu/drm/i915/i915_gem_tiling.c
··· 205 205 if (tiling_mode == I915_TILING_NONE) 206 206 return 0; 207 207 208 - list_for_each_entry(vma, &obj->vma_list, obj_link) { 209 - if (!i915_vma_is_ggtt(vma)) 210 - break; 211 - 208 + for_each_ggtt_vma(vma, obj) { 212 209 if (i915_vma_fence_prepare(vma, tiling_mode, stride)) 213 210 continue; 214 211 ··· 282 285 } 283 286 mutex_unlock(&obj->mm.lock); 284 287 285 - list_for_each_entry(vma, &obj->vma_list, obj_link) { 286 - if (!i915_vma_is_ggtt(vma)) 287 - break; 288 - 288 + for_each_ggtt_vma(vma, obj) { 289 289 vma->fence_size = 290 290 i915_gem_fence_size(i915, vma->size, tiling, stride); 291 291 vma->fence_alignment =
+1 -4
drivers/gpu/drm/i915/i915_gem_timeline.c
··· 33 33 { 34 34 tl->fence_context = context; 35 35 tl->common = parent; 36 - #ifdef CONFIG_DEBUG_SPINLOCK 37 - __raw_spin_lock_init(&tl->lock.rlock, lockname, lockclass); 38 - #else 39 36 spin_lock_init(&tl->lock); 40 - #endif 37 + lockdep_set_class_and_name(&tl->lock, lockclass, lockname); 41 38 init_request_active(&tl->last_request, NULL); 42 39 INIT_LIST_HEAD(&tl->requests); 43 40 i915_syncmap_init(&tl->sync);
+1 -1
drivers/gpu/drm/i915/i915_gpu_error.c
··· 956 956 ggtt->base.insert_page(&ggtt->base, dma, slot, 957 957 I915_CACHE_NONE, 0); 958 958 959 - s = io_mapping_map_atomic_wc(&ggtt->mappable, slot); 959 + s = io_mapping_map_atomic_wc(&ggtt->iomap, slot); 960 960 ret = compress_page(&compress, (void __force *)s, dst); 961 961 io_mapping_unmap_atomic(s); 962 962
+1 -1
drivers/gpu/drm/i915/i915_irq.c
··· 1400 1400 1401 1401 if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) { 1402 1402 notify_ring(engine); 1403 - tasklet |= i915_modparams.enable_guc_submission; 1403 + tasklet |= USES_GUC_SUBMISSION(engine->i915); 1404 1404 } 1405 1405 1406 1406 if (tasklet)
+4 -7
drivers/gpu/drm/i915/i915_params.c
··· 147 147 "(0=use value from vbt [default], 1=low power swing(200mV)," 148 148 "2=default swing(400mV))"); 149 149 150 - i915_param_named_unsafe(enable_guc_loading, int, 0400, 151 - "Enable GuC firmware loading " 152 - "(-1=auto, 0=never [default], 1=if available, 2=required)"); 153 - 154 - i915_param_named_unsafe(enable_guc_submission, int, 0400, 155 - "Enable GuC submission " 156 - "(-1=auto, 0=never [default], 1=if available, 2=required)"); 150 + i915_param_named_unsafe(enable_guc, int, 0400, 151 + "Enable GuC load for GuC submission and/or HuC load. " 152 + "Required functionality can be selected using bitmask values. " 153 + "(-1=auto, 0=disable [default], 1=GuC submission, 2=HuC load)"); 157 154 158 155 i915_param_named(guc_log_level, int, 0400, 159 156 "GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
+5 -2
drivers/gpu/drm/i915/i915_params.h
··· 25 25 #ifndef _I915_PARAMS_H_ 26 26 #define _I915_PARAMS_H_ 27 27 28 + #include <linux/bitops.h> 28 29 #include <linux/cache.h> /* for __read_mostly */ 30 + 31 + #define ENABLE_GUC_SUBMISSION BIT(0) 32 + #define ENABLE_GUC_LOAD_HUC BIT(1) 29 33 30 34 #define I915_PARAMS_FOR_EACH(param) \ 31 35 param(char *, vbt_firmware, NULL) \ ··· 45 41 param(int, disable_power_well, -1) \ 46 42 param(int, enable_ips, 1) \ 47 43 param(int, invert_brightness, 0) \ 48 - param(int, enable_guc_loading, 0) \ 49 - param(int, enable_guc_submission, 0) \ 44 + param(int, enable_guc, 0) \ 50 45 param(int, guc_log_level, -1) \ 51 46 param(char *, guc_firmware_path, NULL) \ 52 47 param(char *, huc_firmware_path, NULL) \
+5 -1
drivers/gpu/drm/i915/i915_sw_fence.c
··· 303 303 int pending; 304 304 305 305 debug_fence_assert(fence); 306 + might_sleep_if(gfpflags_allow_blocking(gfp)); 306 307 307 308 if (i915_sw_fence_done(signaler)) 308 309 return 0; ··· 368 367 struct dma_fence *dma; 369 368 struct timer_list timer; 370 369 struct irq_work work; 370 + struct rcu_head rcu; 371 371 }; 372 372 373 373 static void timer_i915_sw_fence_wake(struct timer_list *t) ··· 408 406 del_timer_sync(&cb->timer); 409 407 dma_fence_put(cb->dma); 410 408 411 - kfree(cb); 409 + kfree_rcu(cb, rcu); 412 410 } 413 411 414 412 int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, ··· 420 418 int ret; 421 419 422 420 debug_fence_assert(fence); 421 + might_sleep_if(gfpflags_allow_blocking(gfp)); 423 422 424 423 if (dma_fence_is_signaled(dma)) 425 424 return 0; ··· 467 464 int ret = 0, pending; 468 465 469 466 debug_fence_assert(fence); 467 + might_sleep_if(gfpflags_allow_blocking(gfp)); 470 468 471 469 if (write) { 472 470 struct dma_fence **shared;
+32 -2
drivers/gpu/drm/i915/i915_vma.c
··· 142 142 i915_gem_object_get_stride(obj)); 143 143 GEM_BUG_ON(!is_power_of_2(vma->fence_alignment)); 144 144 145 + /* 146 + * We put the GGTT vma at the start of the vma-list, followed 147 + * by the ppGGTT vma. This allows us to break early when 148 + * iterating over only the GGTT vma for an object, see 149 + * for_each_ggtt_vma() 150 + */ 145 151 vma->flags |= I915_VMA_GGTT; 146 152 list_add(&vma->obj_link, &obj->vma_list); 147 153 } else { ··· 311 305 312 306 ptr = vma->iomap; 313 307 if (ptr == NULL) { 314 - ptr = io_mapping_map_wc(&i915_vm_to_ggtt(vma->vm)->mappable, 308 + ptr = io_mapping_map_wc(&i915_vm_to_ggtt(vma->vm)->iomap, 315 309 vma->node.start, 316 310 vma->node.size); 317 311 if (ptr == NULL) { ··· 328 322 if (err) 329 323 goto err_unpin; 330 324 325 + i915_vma_set_ggtt_write(vma); 331 326 return ptr; 332 327 333 328 err_unpin: ··· 337 330 return IO_ERR_PTR(err); 338 331 } 339 332 333 + void i915_vma_flush_writes(struct i915_vma *vma) 334 + { 335 + if (!i915_vma_has_ggtt_write(vma)) 336 + return; 337 + 338 + i915_gem_flush_ggtt_writes(vma->vm->i915); 339 + 340 + i915_vma_unset_ggtt_write(vma); 341 + } 342 + 340 343 void i915_vma_unpin_iomap(struct i915_vma *vma) 341 344 { 342 345 lockdep_assert_held(&vma->obj->base.dev->struct_mutex); 343 346 344 347 GEM_BUG_ON(vma->iomap == NULL); 348 + 349 + i915_vma_flush_writes(vma); 345 350 346 351 i915_vma_unpin_fence(vma); 347 352 i915_vma_unpin(vma); ··· 485 466 u64 start, end; 486 467 int ret; 487 468 469 + GEM_BUG_ON(i915_vma_is_closed(vma)); 488 470 GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND)); 489 471 GEM_BUG_ON(drm_mm_node_allocated(&vma->node)); 490 472 ··· 698 678 GEM_BUG_ON(i915_gem_active_isset(&vma->last_read[i])); 699 679 GEM_BUG_ON(i915_gem_active_isset(&vma->last_fence)); 700 680 681 + list_del(&vma->obj_link); 701 682 list_del(&vma->vm_link); 683 + 702 684 if (!i915_vma_is_ggtt(vma)) 703 685 i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm)); 704 686 ··· 712 690 GEM_BUG_ON(i915_vma_is_closed(vma)); 713 691 vma->flags |= I915_VMA_CLOSED; 714 692 715 - list_del(&vma->obj_link); 716 693 rb_erase(&vma->obj_node, &vma->obj->vma_tree); 717 694 718 695 if (!i915_vma_is_active(vma) && !i915_vma_is_pinned(vma)) ··· 811 790 GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); 812 791 813 792 if (i915_vma_is_map_and_fenceable(vma)) { 793 + /* 794 + * Check that we have flushed all writes through the GGTT 795 + * before the unbind, other due to non-strict nature of those 796 + * indirect writes they may end up referencing the GGTT PTE 797 + * after the unbind. 798 + */ 799 + i915_vma_flush_writes(vma); 800 + GEM_BUG_ON(i915_vma_has_ggtt_write(vma)); 801 + 814 802 /* release the fence reg _after_ flushing */ 815 803 ret = i915_vma_put_fence(vma); 816 804 if (ret)
+34 -1
drivers/gpu/drm/i915/i915_vma.h
··· 90 90 #define I915_VMA_CLOSED BIT(10) 91 91 #define I915_VMA_USERFAULT_BIT 11 92 92 #define I915_VMA_USERFAULT BIT(I915_VMA_USERFAULT_BIT) 93 + #define I915_VMA_GGTT_WRITE BIT(12) 93 94 94 95 unsigned int active; 95 96 struct i915_gem_active last_read[I915_NUM_ENGINES]; ··· 138 137 { 139 138 return vma->flags & I915_VMA_GGTT; 140 139 } 140 + 141 + static inline bool i915_vma_has_ggtt_write(const struct i915_vma *vma) 142 + { 143 + return vma->flags & I915_VMA_GGTT_WRITE; 144 + } 145 + 146 + static inline void i915_vma_set_ggtt_write(struct i915_vma *vma) 147 + { 148 + GEM_BUG_ON(!i915_vma_is_ggtt(vma)); 149 + vma->flags |= I915_VMA_GGTT_WRITE; 150 + } 151 + 152 + static inline void i915_vma_unset_ggtt_write(struct i915_vma *vma) 153 + { 154 + vma->flags &= ~I915_VMA_GGTT_WRITE; 155 + } 156 + 157 + void i915_vma_flush_writes(struct i915_vma *vma); 141 158 142 159 static inline bool i915_vma_is_map_and_fenceable(const struct i915_vma *vma) 143 160 { ··· 408 389 __i915_vma_unpin_fence(vma); 409 390 } 410 391 411 - #endif 392 + #define for_each_until(cond) if (cond) break; else 412 393 394 + /** 395 + * for_each_ggtt_vma - Iterate over the GGTT VMA belonging to an object. 396 + * @V: the #i915_vma iterator 397 + * @OBJ: the #drm_i915_gem_object 398 + * 399 + * GGTT VMA are placed at the being of the object's vma_list, see 400 + * vma_create(), so we can stop our walk as soon as we see a ppgtt VMA, 401 + * or the list is empty ofc. 402 + */ 403 + #define for_each_ggtt_vma(V, OBJ) \ 404 + list_for_each_entry(V, &(OBJ)->vma_list, obj_link) \ 405 + for_each_until(!i915_vma_is_ggtt(V)) 406 + 407 + #endif
+47 -26
drivers/gpu/drm/i915/intel_breadcrumbs.c
··· 27 27 28 28 #include "i915_drv.h" 29 29 30 + #ifdef CONFIG_SMP 31 + #define task_asleep(tsk) ((tsk)->state & TASK_NORMAL && !(tsk)->on_cpu) 32 + #else 33 + #define task_asleep(tsk) ((tsk)->state & TASK_NORMAL) 34 + #endif 35 + 30 36 static unsigned int __intel_breadcrumbs_wakeup(struct intel_breadcrumbs *b) 31 37 { 32 38 struct intel_wait *wait; ··· 42 36 43 37 wait = b->irq_wait; 44 38 if (wait) { 39 + /* 40 + * N.B. Since task_asleep() and ttwu are not atomic, the 41 + * waiter may actually go to sleep after the check, causing 42 + * us to suppress a valid wakeup. We prefer to reduce the 43 + * number of false positive missed_breadcrumb() warnings 44 + * at the expense of a few false negatives, as it it easy 45 + * to trigger a false positive under heavy load. Enough 46 + * signal should remain from genuine missed_breadcrumb() 47 + * for us to detect in CI. 48 + */ 49 + bool was_asleep = task_asleep(wait->tsk); 50 + 45 51 result = ENGINE_WAKEUP_WAITER; 46 - if (wake_up_process(wait->tsk)) 52 + if (wake_up_process(wait->tsk) && was_asleep) 47 53 result |= ENGINE_WAKEUP_ASLEEP; 48 54 } 49 55 ··· 82 64 83 65 static noinline void missed_breadcrumb(struct intel_engine_cs *engine) 84 66 { 85 - DRM_DEBUG_DRIVER("%s missed breadcrumb at %pS, irq posted? %s, current seqno=%x, last=%x\n", 86 - engine->name, __builtin_return_address(0), 87 - yesno(test_bit(ENGINE_IRQ_BREADCRUMB, 88 - &engine->irq_posted)), 89 - intel_engine_get_seqno(engine), 90 - intel_engine_last_submit(engine)); 67 + if (drm_debug & DRM_UT_DRIVER) { 68 + struct drm_printer p = drm_debug_printer(__func__); 69 + 70 + intel_engine_dump(engine, &p, 71 + "%s missed breadcrumb at %pS\n", 72 + engine->name, __builtin_return_address(0)); 73 + } 91 74 92 75 set_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings); 93 76 } 94 77 95 78 static void intel_breadcrumbs_hangcheck(struct timer_list *t) 96 79 { 97 - struct intel_engine_cs *engine = from_timer(engine, t, 98 - breadcrumbs.hangcheck); 80 + struct intel_engine_cs *engine = 81 + from_timer(engine, t, breadcrumbs.hangcheck); 99 82 struct intel_breadcrumbs *b = &engine->breadcrumbs; 100 83 101 84 if (!b->irq_armed) ··· 122 103 */ 123 104 if (intel_engine_wakeup(engine) & ENGINE_WAKEUP_ASLEEP) { 124 105 missed_breadcrumb(engine); 125 - mod_timer(&engine->breadcrumbs.fake_irq, jiffies + 1); 106 + mod_timer(&b->fake_irq, jiffies + 1); 126 107 } else { 127 108 mod_timer(&b->hangcheck, wait_timeout()); 128 109 } ··· 232 213 void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine) 233 214 { 234 215 struct intel_breadcrumbs *b = &engine->breadcrumbs; 235 - struct intel_wait *wait, *n, *first; 216 + struct intel_wait *wait, *n; 236 217 237 218 if (!b->irq_armed) 238 - return; 219 + goto wakeup_signaler; 239 220 240 - /* We only disarm the irq when we are idle (all requests completed), 221 + /* 222 + * We only disarm the irq when we are idle (all requests completed), 241 223 * so if the bottom-half remains asleep, it missed the request 242 224 * completion. 243 225 */ 226 + if (intel_engine_wakeup(engine) & ENGINE_WAKEUP_ASLEEP) 227 + missed_breadcrumb(engine); 244 228 245 229 spin_lock_irq(&b->rb_lock); 246 230 247 231 spin_lock(&b->irq_lock); 248 - first = fetch_and_zero(&b->irq_wait); 232 + b->irq_wait = NULL; 249 233 if (b->irq_armed) 250 234 __intel_engine_disarm_breadcrumbs(engine); 251 235 spin_unlock(&b->irq_lock); 252 236 253 237 rbtree_postorder_for_each_entry_safe(wait, n, &b->waiters, node) { 254 238 RB_CLEAR_NODE(&wait->node); 255 - if (wake_up_process(wait->tsk) && wait == first) 256 - missed_breadcrumb(engine); 239 + wake_up_process(wait->tsk); 257 240 } 258 241 b->waiters = RB_ROOT; 259 242 260 243 spin_unlock_irq(&b->rb_lock); 244 + 245 + /* 246 + * The signaling thread may be asleep holding a reference to a request, 247 + * that had its signaling cancelled prior to being preempted. We need 248 + * to kick the signaler, just in case, to release any such reference. 249 + */ 250 + wakeup_signaler: 251 + wake_up_process(b->signaler); 261 252 } 262 253 263 254 static bool use_fake_irq(const struct intel_breadcrumbs *b) ··· 712 683 } 713 684 714 685 if (unlikely(do_schedule)) { 715 - DEFINE_WAIT(exec); 716 - 717 686 if (kthread_should_park()) 718 687 kthread_parkme(); 719 688 720 - if (kthread_should_stop()) { 721 - GEM_BUG_ON(request); 689 + if (unlikely(kthread_should_stop())) { 690 + i915_gem_request_put(request); 722 691 break; 723 692 } 724 693 725 - if (request) 726 - add_wait_queue(&request->execute, &exec); 727 - 728 694 schedule(); 729 - 730 - if (request) 731 - remove_wait_queue(&request->execute, &exec); 732 695 } 733 696 i915_gem_request_put(request); 734 697 } while (1);
+2 -2
drivers/gpu/drm/i915/intel_csr.c
··· 44 44 MODULE_FIRMWARE(I915_CSR_KBL); 45 45 #define KBL_CSR_VERSION_REQUIRED CSR_VERSION(1, 4) 46 46 47 - #define I915_CSR_SKL "i915/skl_dmc_ver1_26.bin" 47 + #define I915_CSR_SKL "i915/skl_dmc_ver1_27.bin" 48 48 MODULE_FIRMWARE(I915_CSR_SKL); 49 - #define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 26) 49 + #define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 27) 50 50 51 51 #define I915_CSR_BXT "i915/bxt_dmc_ver1_07.bin" 52 52 MODULE_FIRMWARE(I915_CSR_BXT);
+9 -9
drivers/gpu/drm/i915/intel_device_info.c
··· 403 403 freq = f24_mhz; 404 404 break; 405 405 } 406 - } 407 406 408 - /* Now figure out how the command stream's timestamp register 409 - * increments from this frequency (it might increment only 410 - * every few clock cycle). 411 - */ 412 - freq >>= 3 - ((rpm_config_reg & 413 - GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >> 414 - GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT); 407 + /* Now figure out how the command stream's timestamp 408 + * register increments from this frequency (it might 409 + * increment only every few clock cycle). 410 + */ 411 + freq >>= 3 - ((rpm_config_reg & 412 + GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >> 413 + GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT); 414 + } 415 415 416 416 return freq; 417 417 } 418 418 419 - DRM_ERROR("Unknown gen, unable to compute command stream timestamp frequency\n"); 419 + MISSING_CASE("Unknown gen, unable to read command streamer timestamp frequency\n"); 420 420 return 0; 421 421 } 422 422
+6 -33
drivers/gpu/drm/i915/intel_display.c
··· 2639 2639 { 2640 2640 struct drm_device *dev = crtc->base.dev; 2641 2641 struct drm_i915_private *dev_priv = to_i915(dev); 2642 - struct i915_ggtt *ggtt = &dev_priv->ggtt; 2643 2642 struct drm_i915_gem_object *obj = NULL; 2644 2643 struct drm_mode_fb_cmd2 mode_cmd = { 0 }; 2645 2644 struct drm_framebuffer *fb = &plane_config->fb->base; ··· 2654 2655 /* If the FB is too big, just don't use it since fbdev is not very 2655 2656 * important and we should probably use that space with FBC or other 2656 2657 * features. */ 2657 - if (size_aligned * 2 > ggtt->stolen_usable_size) 2658 + if (size_aligned * 2 > dev_priv->stolen_usable_size) 2658 2659 return false; 2659 2660 2660 2661 mutex_lock(&dev->struct_mutex); ··· 9939 9940 } 9940 9941 9941 9942 ret = intel_modeset_setup_plane_state(state, crtc, mode, fb, 0, 0); 9943 + drm_framebuffer_put(fb); 9942 9944 if (ret) 9943 9945 goto fail; 9944 - 9945 - drm_framebuffer_put(fb); 9946 9946 9947 9947 ret = drm_atomic_set_mode_for_crtc(&crtc_state->base, mode); 9948 9948 if (ret) ··· 10963 10965 10964 10966 fail: 10965 10967 return ret; 10966 - } 10967 - 10968 - static void 10969 - intel_modeset_update_crtc_state(struct drm_atomic_state *state) 10970 - { 10971 - struct drm_crtc *crtc; 10972 - struct drm_crtc_state *new_crtc_state; 10973 - int i; 10974 - 10975 - /* Double check state. */ 10976 - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { 10977 - to_intel_crtc(crtc)->config = to_intel_crtc_state(new_crtc_state); 10978 - 10979 - /* 10980 - * Update legacy state to satisfy fbc code. This can 10981 - * be removed when fbc uses the atomic state. 10982 - */ 10983 - if (drm_atomic_get_existing_plane_state(state, crtc->primary)) { 10984 - struct drm_plane_state *plane_state = crtc->primary->state; 10985 - 10986 - crtc->primary->fb = plane_state->fb; 10987 - crtc->x = plane_state->src_x >> 16; 10988 - crtc->y = plane_state->src_y >> 16; 10989 - } 10990 - } 10991 10968 } 10992 10969 10993 10970 static bool intel_fuzzy_clock_check(int clock1, int clock2) ··· 12337 12364 } 12338 12365 } 12339 12366 12340 - /* Only after disabling all output pipelines that will be changed can we 12341 - * update the the output configuration. */ 12342 - intel_modeset_update_crtc_state(state); 12367 + /* FIXME: Eventually get rid of our intel_crtc->config pointer */ 12368 + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) 12369 + to_intel_crtc(crtc)->config = to_intel_crtc_state(new_crtc_state); 12343 12370 12344 12371 if (intel_state->modeset) { 12345 12372 drm_atomic_helper_update_legacy_modeset_state(state->dev, state); ··· 14594 14621 dev->mode_config.cursor_height = MAX_CURSOR_HEIGHT; 14595 14622 } 14596 14623 14597 - dev->mode_config.fb_base = ggtt->mappable_base; 14624 + dev->mode_config.fb_base = ggtt->gmadr.start; 14598 14625 14599 14626 DRM_DEBUG_KMS("%d display pipe%s available.\n", 14600 14627 INTEL_INFO(dev_priv)->num_pipes,
+36 -14
drivers/gpu/drm/i915/intel_engine_cs.c
··· 1513 1513 struct intel_engine_cs *engine; 1514 1514 enum intel_engine_id id; 1515 1515 1516 - if (READ_ONCE(dev_priv->gt.active_requests)) 1517 - return false; 1518 - 1519 - /* If the driver is wedged, HW state may be very inconsistent and 1516 + /* 1517 + * If the driver is wedged, HW state may be very inconsistent and 1520 1518 * report that it is still busy, even though we have stopped using it. 1521 1519 */ 1522 1520 if (i915_terminally_wedged(&dev_priv->gpu_error)) ··· 1594 1596 dev_err(i915->drm.dev, 1595 1597 "%s is not idle before parking\n", 1596 1598 engine->name); 1597 - intel_engine_dump(engine, &p); 1599 + intel_engine_dump(engine, &p, NULL); 1598 1600 } 1599 1601 1600 1602 if (engine->park) ··· 1664 1666 rq->timeline->common->name); 1665 1667 } 1666 1668 1667 - void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m) 1669 + void intel_engine_dump(struct intel_engine_cs *engine, 1670 + struct drm_printer *m, 1671 + const char *header, ...) 1668 1672 { 1669 1673 struct intel_breadcrumbs * const b = &engine->breadcrumbs; 1670 1674 const struct intel_engine_execlists * const execlists = &engine->execlists; ··· 1674 1674 struct drm_i915_private *dev_priv = engine->i915; 1675 1675 struct drm_i915_gem_request *rq; 1676 1676 struct rb_node *rb; 1677 + char hdr[80]; 1677 1678 u64 addr; 1678 1679 1679 - drm_printf(m, "%s\n", engine->name); 1680 + if (header) { 1681 + va_list ap; 1682 + 1683 + va_start(ap, header); 1684 + drm_vprintf(m, header, &ap); 1685 + va_end(ap); 1686 + } 1687 + 1688 + if (i915_terminally_wedged(&engine->i915->gpu_error)) 1689 + drm_printf(m, "*** WEDGED ***\n"); 1690 + 1680 1691 drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n", 1681 1692 intel_engine_get_seqno(engine), 1682 1693 intel_engine_last_submit(engine), 1683 1694 engine->hangcheck.seqno, 1684 1695 jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp), 1685 1696 engine->timeline->inflight_seqnos); 1686 - drm_printf(m, "\tReset count: %d\n", 1687 - i915_reset_engine_count(error, engine)); 1697 + drm_printf(m, "\tReset count: %d (global %d)\n", 1698 + i915_reset_engine_count(error, engine), 1699 + i915_reset_count(error)); 1688 1700 1689 1701 rcu_read_lock(); 1690 1702 ··· 1798 1786 1799 1787 rq = port_unpack(&execlists->port[idx], &count); 1800 1788 if (rq) { 1801 - drm_printf(m, "\t\tELSP[%d] count=%d, ", 1802 - idx, count); 1803 - print_request(m, rq, "rq: "); 1789 + snprintf(hdr, sizeof(hdr), 1790 + "\t\tELSP[%d] count=%d, rq: ", 1791 + idx, count); 1792 + print_request(m, rq, hdr); 1804 1793 } else { 1805 - drm_printf(m, "\t\tELSP[%d] idle\n", 1806 - idx); 1794 + drm_printf(m, "\t\tELSP[%d] idle\n", idx); 1807 1795 } 1808 1796 } 1809 1797 drm_printf(m, "\t\tHW active? 0x%x\n", execlists->active); ··· 1838 1826 } 1839 1827 spin_unlock_irq(&b->rb_lock); 1840 1828 1829 + if (INTEL_GEN(dev_priv) >= 6) { 1830 + drm_printf(m, "\tRING_IMR: %08x\n", I915_READ_IMR(engine)); 1831 + } 1832 + 1833 + drm_printf(m, "IRQ? 0x%lx (breadcrumbs? %s) (execlists? %s)\n", 1834 + engine->irq_posted, 1835 + yesno(test_bit(ENGINE_IRQ_BREADCRUMB, 1836 + &engine->irq_posted)), 1837 + yesno(test_bit(ENGINE_IRQ_EXECLIST, 1838 + &engine->irq_posted))); 1841 1839 drm_printf(m, "Idle? %s\n", yesno(intel_engine_is_idle(engine))); 1842 1840 drm_printf(m, "\n"); 1843 1841 }
+9 -4
drivers/gpu/drm/i915/intel_fbc.c
··· 531 531 int size, 532 532 int fb_cpp) 533 533 { 534 - struct i915_ggtt *ggtt = &dev_priv->ggtt; 535 534 int compression_threshold = 1; 536 535 int ret; 537 536 u64 end; ··· 540 541 * If we enable FBC using a CFB on that memory range we'll get FIFO 541 542 * underruns, even if that range is not reserved by the BIOS. */ 542 543 if (IS_BROADWELL(dev_priv) || IS_GEN9_BC(dev_priv)) 543 - end = ggtt->stolen_size - 8 * 1024 * 1024; 544 + end = resource_size(&dev_priv->dsm) - 8 * 1024 * 1024; 544 545 else 545 546 end = U64_MAX; 546 547 ··· 614 615 615 616 fbc->compressed_llb = compressed_llb; 616 617 618 + GEM_BUG_ON(range_overflows_t(u64, dev_priv->dsm.start, 619 + fbc->compressed_fb.start, 620 + U32_MAX)); 621 + GEM_BUG_ON(range_overflows_t(u64, dev_priv->dsm.start, 622 + fbc->compressed_llb->start, 623 + U32_MAX)); 617 624 I915_WRITE(FBC_CFB_BASE, 618 - dev_priv->mm.stolen_base + fbc->compressed_fb.start); 625 + dev_priv->dsm.start + fbc->compressed_fb.start); 619 626 I915_WRITE(FBC_LL_BASE, 620 - dev_priv->mm.stolen_base + compressed_llb->start); 627 + dev_priv->dsm.start + compressed_llb->start); 621 628 } 622 629 623 630 DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n",
+1 -2
drivers/gpu/drm/i915/intel_fbdev.c
··· 115 115 struct drm_framebuffer *fb; 116 116 struct drm_device *dev = helper->dev; 117 117 struct drm_i915_private *dev_priv = to_i915(dev); 118 - struct i915_ggtt *ggtt = &dev_priv->ggtt; 119 118 struct drm_mode_fb_cmd2 mode_cmd = {}; 120 119 struct drm_i915_gem_object *obj; 121 120 int size, ret; ··· 138 139 * important and we should probably use that space with FBC or other 139 140 * features. */ 140 141 obj = NULL; 141 - if (size * 2 < ggtt->stolen_usable_size) 142 + if (size * 2 < dev_priv->stolen_usable_size) 142 143 obj = i915_gem_object_create_stolen(dev_priv, size); 143 144 if (obj == NULL) 144 145 obj = i915_gem_object_create(dev_priv, size);
+110 -1
drivers/gpu/drm/i915/intel_guc.c
··· 61 61 62 62 void intel_guc_init_early(struct intel_guc *guc) 63 63 { 64 + intel_guc_fw_init_early(guc); 64 65 intel_guc_ct_init_early(&guc->ct); 65 66 66 67 mutex_init(&guc->send_mutex); 67 68 guc->send = intel_guc_send_nop; 68 69 guc->notify = gen8_guc_raise_irq; 70 + } 71 + 72 + int intel_guc_init_wq(struct intel_guc *guc) 73 + { 74 + struct drm_i915_private *dev_priv = guc_to_i915(guc); 75 + 76 + /* 77 + * GuC log buffer flush work item has to do register access to 78 + * send the ack to GuC and this work item, if not synced before 79 + * suspend, can potentially get executed after the GFX device is 80 + * suspended. 81 + * By marking the WQ as freezable, we don't have to bother about 82 + * flushing of this work item from the suspend hooks, the pending 83 + * work item if any will be either executed before the suspend 84 + * or scheduled later on resume. This way the handling of work 85 + * item can be kept same between system suspend & rpm suspend. 86 + */ 87 + guc->log.runtime.flush_wq = alloc_ordered_workqueue("i915-guc_log", 88 + WQ_HIGHPRI | WQ_FREEZABLE); 89 + if (!guc->log.runtime.flush_wq) 90 + return -ENOMEM; 91 + 92 + /* 93 + * Even though both sending GuC action, and adding a new workitem to 94 + * GuC workqueue are serialized (each with its own locking), since 95 + * we're using mutliple engines, it's possible that we're going to 96 + * issue a preempt request with two (or more - each for different 97 + * engine) workitems in GuC queue. In this situation, GuC may submit 98 + * all of them, which will make us very confused. 99 + * Our preemption contexts may even already be complete - before we 100 + * even had the chance to sent the preempt action to GuC!. Rather 101 + * than introducing yet another lock, we can just use ordered workqueue 102 + * to make sure we're always sending a single preemption request with a 103 + * single workitem. 104 + */ 105 + if (HAS_LOGICAL_RING_PREEMPTION(dev_priv) && 106 + USES_GUC_SUBMISSION(dev_priv)) { 107 + guc->preempt_wq = alloc_ordered_workqueue("i915-guc_preempt", 108 + WQ_HIGHPRI); 109 + if (!guc->preempt_wq) { 110 + destroy_workqueue(guc->log.runtime.flush_wq); 111 + return -ENOMEM; 112 + } 113 + } 114 + 115 + return 0; 116 + } 117 + 118 + void intel_guc_fini_wq(struct intel_guc *guc) 119 + { 120 + struct drm_i915_private *dev_priv = guc_to_i915(guc); 121 + 122 + if (HAS_LOGICAL_RING_PREEMPTION(dev_priv) && 123 + USES_GUC_SUBMISSION(dev_priv)) 124 + destroy_workqueue(guc->preempt_wq); 125 + 126 + destroy_workqueue(guc->log.runtime.flush_wq); 127 + } 128 + 129 + static int guc_shared_data_create(struct intel_guc *guc) 130 + { 131 + struct i915_vma *vma; 132 + void *vaddr; 133 + 134 + vma = intel_guc_allocate_vma(guc, PAGE_SIZE); 135 + if (IS_ERR(vma)) 136 + return PTR_ERR(vma); 137 + 138 + vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); 139 + if (IS_ERR(vaddr)) { 140 + i915_vma_unpin_and_release(&vma); 141 + return PTR_ERR(vaddr); 142 + } 143 + 144 + guc->shared_data = vma; 145 + guc->shared_data_vaddr = vaddr; 146 + 147 + return 0; 148 + } 149 + 150 + static void guc_shared_data_destroy(struct intel_guc *guc) 151 + { 152 + i915_gem_object_unpin_map(guc->shared_data->obj); 153 + i915_vma_unpin_and_release(&guc->shared_data); 154 + } 155 + 156 + int intel_guc_init(struct intel_guc *guc) 157 + { 158 + struct drm_i915_private *dev_priv = guc_to_i915(guc); 159 + int ret; 160 + 161 + ret = guc_shared_data_create(guc); 162 + if (ret) 163 + return ret; 164 + GEM_BUG_ON(!guc->shared_data); 165 + 166 + /* We need to notify the guc whenever we change the GGTT */ 167 + i915_ggtt_enable_guc(dev_priv); 168 + 169 + return 0; 170 + } 171 + 172 + void intel_guc_fini(struct intel_guc *guc) 173 + { 174 + struct drm_i915_private *dev_priv = guc_to_i915(guc); 175 + 176 + i915_ggtt_disable_guc(dev_priv); 177 + guc_shared_data_destroy(guc); 69 178 } 70 179 71 180 static u32 get_gt_type(struct drm_i915_private *dev_priv) ··· 237 128 } 238 129 239 130 /* If GuC submission is enabled, set up additional parameters here */ 240 - if (i915_modparams.enable_guc_submission) { 131 + if (USES_GUC_SUBMISSION(dev_priv)) { 241 132 u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT; 242 133 u32 pgs = guc_ggtt_offset(dev_priv->guc.stage_desc_pool); 243 134 u32 ctx_in_16 = GUC_MAX_STAGE_DESCRIPTORS / 16;
+4
drivers/gpu/drm/i915/intel_guc.h
··· 119 119 void intel_guc_init_early(struct intel_guc *guc); 120 120 void intel_guc_init_send_regs(struct intel_guc *guc); 121 121 void intel_guc_init_params(struct intel_guc *guc); 122 + int intel_guc_init_wq(struct intel_guc *guc); 123 + void intel_guc_fini_wq(struct intel_guc *guc); 124 + int intel_guc_init(struct intel_guc *guc); 125 + void intel_guc_fini(struct intel_guc *guc); 122 126 int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len); 123 127 int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len); 124 128 int intel_guc_sample_forcewake(struct intel_guc *guc);
+36 -27
drivers/gpu/drm/i915/intel_guc_fw.c
··· 56 56 57 57 #define I915_GLK_GUC_UCODE GUC_FW_PATH(glk, GLK_FW_MAJOR, GLK_FW_MINOR) 58 58 59 - /** 60 - * intel_guc_fw_select() - selects GuC firmware for uploading 61 - * 62 - * @guc: intel_guc struct 63 - * 64 - * Return: zero when we know firmware, non-zero in other case 65 - */ 66 - int intel_guc_fw_select(struct intel_guc *guc) 59 + static void guc_fw_select(struct intel_uc_fw *guc_fw) 67 60 { 61 + struct intel_guc *guc = container_of(guc_fw, struct intel_guc, fw); 68 62 struct drm_i915_private *dev_priv = guc_to_i915(guc); 69 63 70 - intel_uc_fw_init(&guc->fw, INTEL_UC_FW_TYPE_GUC); 64 + GEM_BUG_ON(guc_fw->type != INTEL_UC_FW_TYPE_GUC); 65 + 66 + if (!HAS_GUC(dev_priv)) 67 + return; 71 68 72 69 if (i915_modparams.guc_firmware_path) { 73 - guc->fw.path = i915_modparams.guc_firmware_path; 74 - guc->fw.major_ver_wanted = 0; 75 - guc->fw.minor_ver_wanted = 0; 70 + guc_fw->path = i915_modparams.guc_firmware_path; 71 + guc_fw->major_ver_wanted = 0; 72 + guc_fw->minor_ver_wanted = 0; 76 73 } else if (IS_SKYLAKE(dev_priv)) { 77 - guc->fw.path = I915_SKL_GUC_UCODE; 78 - guc->fw.major_ver_wanted = SKL_FW_MAJOR; 79 - guc->fw.minor_ver_wanted = SKL_FW_MINOR; 74 + guc_fw->path = I915_SKL_GUC_UCODE; 75 + guc_fw->major_ver_wanted = SKL_FW_MAJOR; 76 + guc_fw->minor_ver_wanted = SKL_FW_MINOR; 80 77 } else if (IS_BROXTON(dev_priv)) { 81 - guc->fw.path = I915_BXT_GUC_UCODE; 82 - guc->fw.major_ver_wanted = BXT_FW_MAJOR; 83 - guc->fw.minor_ver_wanted = BXT_FW_MINOR; 78 + guc_fw->path = I915_BXT_GUC_UCODE; 79 + guc_fw->major_ver_wanted = BXT_FW_MAJOR; 80 + guc_fw->minor_ver_wanted = BXT_FW_MINOR; 84 81 } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { 85 - guc->fw.path = I915_KBL_GUC_UCODE; 86 - guc->fw.major_ver_wanted = KBL_FW_MAJOR; 87 - guc->fw.minor_ver_wanted = KBL_FW_MINOR; 82 + guc_fw->path = I915_KBL_GUC_UCODE; 83 + guc_fw->major_ver_wanted = KBL_FW_MAJOR; 84 + guc_fw->minor_ver_wanted = KBL_FW_MINOR; 88 85 } else if (IS_GEMINILAKE(dev_priv)) { 89 - guc->fw.path = I915_GLK_GUC_UCODE; 90 - guc->fw.major_ver_wanted = GLK_FW_MAJOR; 91 - guc->fw.minor_ver_wanted = GLK_FW_MINOR; 86 + guc_fw->path = I915_GLK_GUC_UCODE; 87 + guc_fw->major_ver_wanted = GLK_FW_MAJOR; 88 + guc_fw->minor_ver_wanted = GLK_FW_MINOR; 92 89 } else { 93 - DRM_ERROR("No GuC firmware known for platform with GuC!\n"); 94 - return -ENOENT; 90 + DRM_WARN("%s: No firmware known for this platform!\n", 91 + intel_uc_fw_type_repr(guc_fw->type)); 95 92 } 93 + } 96 94 97 - return 0; 95 + /** 96 + * intel_guc_fw_init_early() - initializes GuC firmware struct 97 + * @guc: intel_guc struct 98 + * 99 + * On platforms with GuC selects firmware for uploading 100 + */ 101 + void intel_guc_fw_init_early(struct intel_guc *guc) 102 + { 103 + struct intel_uc_fw *guc_fw = &guc->fw; 104 + 105 + intel_uc_fw_init(guc_fw, INTEL_UC_FW_TYPE_GUC); 106 + guc_fw_select(guc_fw); 98 107 } 99 108 100 109 static void guc_prepare_xfer(struct intel_guc *guc)
+1 -1
drivers/gpu/drm/i915/intel_guc_fw.h
··· 27 27 28 28 struct intel_guc; 29 29 30 - int intel_guc_fw_select(struct intel_guc *guc); 30 + void intel_guc_fw_init_early(struct intel_guc *guc); 31 31 int intel_guc_fw_upload(struct intel_guc *guc); 32 32 33 33 #endif
+3 -26
drivers/gpu/drm/i915/intel_guc_log.c
··· 411 411 guc->log.runtime.relay_chan = guc_log_relay_chan; 412 412 413 413 INIT_WORK(&guc->log.runtime.flush_work, capture_logs_work); 414 - 415 - /* 416 - * GuC log buffer flush work item has to do register access to 417 - * send the ack to GuC and this work item, if not synced before 418 - * suspend, can potentially get executed after the GFX device is 419 - * suspended. 420 - * By marking the WQ as freezable, we don't have to bother about 421 - * flushing of this work item from the suspend hooks, the pending 422 - * work item if any will be either executed before the suspend 423 - * or scheduled later on resume. This way the handling of work 424 - * item can be kept same between system suspend & rpm suspend. 425 - */ 426 - guc->log.runtime.flush_wq = alloc_ordered_workqueue("i915-guc_log", 427 - WQ_HIGHPRI | WQ_FREEZABLE); 428 - if (!guc->log.runtime.flush_wq) { 429 - DRM_ERROR("Couldn't allocate the wq for GuC logging\n"); 430 - ret = -ENOMEM; 431 - goto err_relaychan; 432 - } 433 - 434 414 return 0; 435 415 436 - err_relaychan: 437 - relay_close(guc->log.runtime.relay_chan); 438 416 err_vaddr: 439 417 i915_gem_object_unpin_map(guc->log.vma->obj); 440 418 guc->log.runtime.buf_addr = NULL; ··· 428 450 if (!guc_log_has_runtime(guc)) 429 451 return; 430 452 431 - destroy_workqueue(guc->log.runtime.flush_wq); 432 453 relay_close(guc->log.runtime.relay_chan); 433 454 i915_gem_object_unpin_map(guc->log.vma->obj); 434 455 guc->log.runtime.buf_addr = NULL; ··· 482 505 { 483 506 struct drm_i915_private *dev_priv = guc_to_i915(guc); 484 507 485 - if (!i915_modparams.enable_guc_submission || 508 + if (!USES_GUC_SUBMISSION(dev_priv) || 486 509 (i915_modparams.guc_log_level < 0)) 487 510 return; 488 511 ··· 623 646 624 647 void i915_guc_log_register(struct drm_i915_private *dev_priv) 625 648 { 626 - if (!i915_modparams.enable_guc_submission || 649 + if (!USES_GUC_SUBMISSION(dev_priv) || 627 650 (i915_modparams.guc_log_level < 0)) 628 651 return; 629 652 ··· 634 657 635 658 void i915_guc_log_unregister(struct drm_i915_private *dev_priv) 636 659 { 637 - if (!i915_modparams.enable_guc_submission) 660 + if (!USES_GUC_SUBMISSION(dev_priv)) 638 661 return; 639 662 640 663 mutex_lock(&dev_priv->drm.struct_mutex);
+78 -222
drivers/gpu/drm/i915/intel_guc_submission.c
··· 88 88 client->priority == GUC_CLIENT_PRIORITY_HIGH); 89 89 } 90 90 91 - static int __reserve_doorbell(struct intel_guc_client *client) 91 + static int reserve_doorbell(struct intel_guc_client *client) 92 92 { 93 93 unsigned long offset; 94 94 unsigned long end; ··· 120 120 return 0; 121 121 } 122 122 123 - static void __unreserve_doorbell(struct intel_guc_client *client) 123 + static void unreserve_doorbell(struct intel_guc_client *client) 124 124 { 125 125 GEM_BUG_ON(client->doorbell_id == GUC_DOORBELL_INVALID); 126 126 ··· 188 188 return test_bit(client->doorbell_id, client->guc->doorbell_bitmap); 189 189 } 190 190 191 - static int __create_doorbell(struct intel_guc_client *client) 191 + static void __create_doorbell(struct intel_guc_client *client) 192 192 { 193 193 struct guc_doorbell_info *doorbell; 194 - int err; 195 194 196 195 doorbell = __get_doorbell(client); 197 196 doorbell->db_status = GUC_DOORBELL_ENABLED; 198 197 doorbell->cookie = 0; 199 - 200 - err = __guc_allocate_doorbell(client->guc, client->stage_id); 201 - if (err) { 202 - doorbell->db_status = GUC_DOORBELL_DISABLED; 203 - DRM_ERROR("Couldn't create client %u doorbell: %d\n", 204 - client->stage_id, err); 205 - } 206 - 207 - return err; 208 198 } 209 199 210 - static int __destroy_doorbell(struct intel_guc_client *client) 200 + static void __destroy_doorbell(struct intel_guc_client *client) 211 201 { 212 202 struct drm_i915_private *dev_priv = guc_to_i915(client->guc); 213 203 struct guc_doorbell_info *doorbell; 214 204 u16 db_id = client->doorbell_id; 215 205 216 - GEM_BUG_ON(db_id >= GUC_DOORBELL_INVALID); 217 206 218 207 doorbell = __get_doorbell(client); 219 208 doorbell->db_status = GUC_DOORBELL_DISABLED; ··· 214 225 */ 215 226 if (wait_for_us(!(I915_READ(GEN8_DRBREGL(db_id)) & GEN8_DRB_VALID), 10)) 216 227 WARN_ONCE(true, "Doorbell never became invalid after disable\n"); 217 - 218 - return __guc_deallocate_doorbell(client->guc, client->stage_id); 219 228 } 220 229 221 230 static int create_doorbell(struct intel_guc_client *client) 222 231 { 223 232 int ret; 224 233 225 - ret = __reserve_doorbell(client); 226 - if (ret) 227 - return ret; 228 - 229 234 __update_doorbell_desc(client, client->doorbell_id); 235 + __create_doorbell(client); 230 236 231 - ret = __create_doorbell(client); 232 - if (ret) 233 - goto err; 237 + ret = __guc_allocate_doorbell(client->guc, client->stage_id); 238 + if (ret) { 239 + __destroy_doorbell(client); 240 + __update_doorbell_desc(client, GUC_DOORBELL_INVALID); 241 + DRM_ERROR("Couldn't create client %u doorbell: %d\n", 242 + client->stage_id, ret); 243 + return ret; 244 + } 234 245 235 246 return 0; 236 - 237 - err: 238 - __update_doorbell_desc(client, GUC_DOORBELL_INVALID); 239 - __unreserve_doorbell(client); 240 - return ret; 241 247 } 242 248 243 249 static int destroy_doorbell(struct intel_guc_client *client) 244 250 { 245 - int err; 251 + int ret; 246 252 247 253 GEM_BUG_ON(!has_doorbell(client)); 248 254 249 - /* XXX: wait for any interrupts */ 250 - /* XXX: wait for workqueue to drain */ 251 - 252 - err = __destroy_doorbell(client); 253 - if (err) 254 - return err; 255 + __destroy_doorbell(client); 256 + ret = __guc_deallocate_doorbell(client->guc, client->stage_id); 257 + if (ret) 258 + DRM_ERROR("Couldn't destroy client %u doorbell: %d\n", 259 + client->stage_id, ret); 255 260 256 261 __update_doorbell_desc(client, GUC_DOORBELL_INVALID); 257 262 258 - __unreserve_doorbell(client); 259 - 260 - return 0; 263 + return ret; 261 264 } 262 265 263 266 static unsigned long __select_cacheline(struct intel_guc *guc) ··· 426 445 427 446 desc = __get_stage_desc(client); 428 447 memset(desc, 0, sizeof(*desc)); 429 - } 430 - 431 - static int guc_shared_data_create(struct intel_guc *guc) 432 - { 433 - struct i915_vma *vma; 434 - void *vaddr; 435 - 436 - vma = intel_guc_allocate_vma(guc, PAGE_SIZE); 437 - if (IS_ERR(vma)) 438 - return PTR_ERR(vma); 439 - 440 - vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); 441 - if (IS_ERR(vaddr)) { 442 - i915_vma_unpin_and_release(&vma); 443 - return PTR_ERR(vaddr); 444 - } 445 - 446 - guc->shared_data = vma; 447 - guc->shared_data_vaddr = vaddr; 448 - 449 - return 0; 450 - } 451 - 452 - static void guc_shared_data_destroy(struct intel_guc *guc) 453 - { 454 - i915_gem_object_unpin_map(guc->shared_data->obj); 455 - i915_vma_unpin_and_release(&guc->shared_data); 456 448 } 457 449 458 450 /* Construct a Work Item and append it to the GuC's Work Queue */ ··· 820 866 return false; 821 867 } 822 868 823 - /* 824 - * If the GuC thinks that the doorbell is unassigned (e.g. because we reset and 825 - * reloaded the GuC FW) we can use this function to tell the GuC to reassign the 826 - * doorbell to the rightful owner. 827 - */ 828 - static int __reset_doorbell(struct intel_guc_client *client, u16 db_id) 869 + static bool guc_verify_doorbells(struct intel_guc *guc) 829 870 { 830 - int err; 871 + u16 db_id; 831 872 832 - __update_doorbell_desc(client, db_id); 833 - err = __create_doorbell(client); 834 - if (!err) 835 - err = __destroy_doorbell(client); 873 + for (db_id = 0; db_id < GUC_NUM_DOORBELLS; ++db_id) 874 + if (!doorbell_ok(guc, db_id)) 875 + return false; 836 876 837 - return err; 877 + return true; 838 878 } 839 879 840 - /* 841 - * Set up & tear down each unused doorbell in turn, to ensure that all doorbell 842 - * HW is (re)initialised. For that end, we might have to borrow the first 843 - * client. Also, tell GuC about all the doorbells in use by all clients. 844 - * We do this because the KMD, the GuC and the doorbell HW can easily go out of 845 - * sync (e.g. we can reset the GuC, but not the doorbel HW). 846 - */ 847 - static int guc_init_doorbell_hw(struct intel_guc *guc) 880 + static int guc_clients_doorbell_init(struct intel_guc *guc) 848 881 { 849 - struct intel_guc_client *client = guc->execbuf_client; 850 - bool recreate_first_client = false; 851 - u16 db_id; 852 882 int ret; 853 883 854 - /* For unused doorbells, make sure they are disabled */ 855 - for_each_clear_bit(db_id, guc->doorbell_bitmap, GUC_NUM_DOORBELLS) { 856 - if (doorbell_ok(guc, db_id)) 857 - continue; 858 - 859 - if (has_doorbell(client)) { 860 - /* Borrow execbuf_client (we will recreate it later) */ 861 - destroy_doorbell(client); 862 - recreate_first_client = true; 863 - } 864 - 865 - ret = __reset_doorbell(client, db_id); 866 - WARN(ret, "Doorbell %u reset failed, err %d\n", db_id, ret); 867 - } 868 - 869 - if (recreate_first_client) { 870 - ret = __reserve_doorbell(client); 871 - if (unlikely(ret)) { 872 - DRM_ERROR("Couldn't re-reserve first client db: %d\n", 873 - ret); 874 - return ret; 875 - } 876 - 877 - __update_doorbell_desc(client, client->doorbell_id); 878 - } 879 - 880 - /* Now for every client (and not only execbuf_client) make sure their 881 - * doorbells are known by the GuC 882 - */ 883 - ret = __create_doorbell(guc->execbuf_client); 884 + ret = create_doorbell(guc->execbuf_client); 884 885 if (ret) 885 886 return ret; 886 887 887 - ret = __create_doorbell(guc->preempt_client); 888 + ret = create_doorbell(guc->preempt_client); 888 889 if (ret) { 889 - __destroy_doorbell(guc->execbuf_client); 890 + destroy_doorbell(guc->execbuf_client); 890 891 return ret; 891 892 } 892 893 893 - /* Read back & verify all (used & unused) doorbell registers */ 894 - for (db_id = 0; db_id < GUC_NUM_DOORBELLS; ++db_id) 895 - WARN_ON(!doorbell_ok(guc, db_id)); 896 - 897 894 return 0; 895 + } 896 + 897 + static void guc_clients_doorbell_fini(struct intel_guc *guc) 898 + { 899 + /* 900 + * By the time we're here, GuC has already been reset. 901 + * Instead of trying (in vain) to communicate with it, let's just 902 + * cleanup the doorbell HW and our internal state. 903 + */ 904 + __destroy_doorbell(guc->preempt_client); 905 + __update_doorbell_desc(guc->preempt_client, GUC_DOORBELL_INVALID); 906 + __destroy_doorbell(guc->execbuf_client); 907 + __update_doorbell_desc(guc->execbuf_client, GUC_DOORBELL_INVALID); 898 908 } 899 909 900 910 /** ··· 936 1018 guc_proc_desc_init(guc, client); 937 1019 guc_stage_desc_init(guc, client); 938 1020 939 - ret = create_doorbell(client); 1021 + ret = reserve_doorbell(client); 940 1022 if (ret) 941 1023 goto err_vaddr; 942 1024 ··· 960 1042 961 1043 static void guc_client_free(struct intel_guc_client *client) 962 1044 { 963 - /* 964 - * XXX: wait for any outstanding submissions before freeing memory. 965 - * Be sure to drop any locks 966 - */ 967 - 968 - /* FIXME: in many cases, by the time we get here the GuC has been 969 - * reset, so we cannot destroy the doorbell properly. Ignore the 970 - * error message for now 971 - */ 972 - destroy_doorbell(client); 1045 + unreserve_doorbell(client); 973 1046 guc_stage_desc_fini(client->guc, client); 974 1047 i915_gem_object_unpin_map(client->vma->obj); 975 1048 i915_vma_unpin_and_release(&client->vma); ··· 1123 1214 i915_vma_unpin_and_release(&guc->ads_vma); 1124 1215 } 1125 1216 1126 - static int guc_preempt_work_create(struct intel_guc *guc) 1127 - { 1128 - struct drm_i915_private *dev_priv = guc_to_i915(guc); 1129 - struct intel_engine_cs *engine; 1130 - enum intel_engine_id id; 1131 - 1132 - /* 1133 - * Even though both sending GuC action, and adding a new workitem to 1134 - * GuC workqueue are serialized (each with its own locking), since 1135 - * we're using mutliple engines, it's possible that we're going to 1136 - * issue a preempt request with two (or more - each for different 1137 - * engine) workitems in GuC queue. In this situation, GuC may submit 1138 - * all of them, which will make us very confused. 1139 - * Our preemption contexts may even already be complete - before we 1140 - * even had the chance to sent the preempt action to GuC!. Rather 1141 - * than introducing yet another lock, we can just use ordered workqueue 1142 - * to make sure we're always sending a single preemption request with a 1143 - * single workitem. 1144 - */ 1145 - guc->preempt_wq = alloc_ordered_workqueue("i915-guc_preempt", 1146 - WQ_HIGHPRI); 1147 - if (!guc->preempt_wq) 1148 - return -ENOMEM; 1149 - 1150 - for_each_engine(engine, dev_priv, id) { 1151 - guc->preempt_work[id].engine = engine; 1152 - INIT_WORK(&guc->preempt_work[id].work, inject_preempt_context); 1153 - } 1154 - 1155 - return 0; 1156 - } 1157 - 1158 - static void guc_preempt_work_destroy(struct intel_guc *guc) 1159 - { 1160 - struct drm_i915_private *dev_priv = guc_to_i915(guc); 1161 - struct intel_engine_cs *engine; 1162 - enum intel_engine_id id; 1163 - 1164 - for_each_engine(engine, dev_priv, id) 1165 - cancel_work_sync(&guc->preempt_work[id].work); 1166 - 1167 - destroy_workqueue(guc->preempt_wq); 1168 - guc->preempt_wq = NULL; 1169 - } 1170 - 1171 1217 /* 1172 1218 * Set up the memory resources to be shared with the GuC (via the GGTT) 1173 1219 * at firmware loading time. 1174 1220 */ 1175 1221 int intel_guc_submission_init(struct intel_guc *guc) 1176 1222 { 1223 + struct drm_i915_private *dev_priv = guc_to_i915(guc); 1224 + struct intel_engine_cs *engine; 1225 + enum intel_engine_id id; 1177 1226 int ret; 1178 1227 1179 1228 if (guc->stage_desc_pool) ··· 1146 1279 */ 1147 1280 GEM_BUG_ON(!guc->stage_desc_pool); 1148 1281 1149 - ret = guc_shared_data_create(guc); 1150 - if (ret) 1151 - goto err_stage_desc_pool; 1152 - GEM_BUG_ON(!guc->shared_data); 1153 - 1154 1282 ret = intel_guc_log_create(guc); 1155 1283 if (ret < 0) 1156 - goto err_shared_data; 1157 - 1158 - ret = guc_preempt_work_create(guc); 1159 - if (ret) 1160 - goto err_log; 1161 - GEM_BUG_ON(!guc->preempt_wq); 1284 + goto err_stage_desc_pool; 1162 1285 1163 1286 ret = guc_ads_create(guc); 1164 1287 if (ret < 0) 1165 - goto err_wq; 1288 + goto err_log; 1166 1289 GEM_BUG_ON(!guc->ads_vma); 1290 + 1291 + WARN_ON(!guc_verify_doorbells(guc)); 1292 + ret = guc_clients_create(guc); 1293 + if (ret) 1294 + return ret; 1295 + 1296 + for_each_engine(engine, dev_priv, id) { 1297 + guc->preempt_work[id].engine = engine; 1298 + INIT_WORK(&guc->preempt_work[id].work, inject_preempt_context); 1299 + } 1167 1300 1168 1301 return 0; 1169 1302 1170 - err_wq: 1171 - guc_preempt_work_destroy(guc); 1172 1303 err_log: 1173 1304 intel_guc_log_destroy(guc); 1174 - err_shared_data: 1175 - guc_shared_data_destroy(guc); 1176 1305 err_stage_desc_pool: 1177 1306 guc_stage_desc_pool_destroy(guc); 1178 1307 return ret; ··· 1176 1313 1177 1314 void intel_guc_submission_fini(struct intel_guc *guc) 1178 1315 { 1316 + struct drm_i915_private *dev_priv = guc_to_i915(guc); 1317 + struct intel_engine_cs *engine; 1318 + enum intel_engine_id id; 1319 + 1320 + for_each_engine(engine, dev_priv, id) 1321 + cancel_work_sync(&guc->preempt_work[id].work); 1322 + 1323 + guc_clients_destroy(guc); 1324 + WARN_ON(!guc_verify_doorbells(guc)); 1325 + 1179 1326 guc_ads_destroy(guc); 1180 - guc_preempt_work_destroy(guc); 1181 1327 intel_guc_log_destroy(guc); 1182 - guc_shared_data_destroy(guc); 1183 1328 guc_stage_desc_pool_destroy(guc); 1184 1329 } 1185 1330 ··· 1291 1420 sizeof(struct guc_wq_item) * 1292 1421 I915_NUM_ENGINES > GUC_WQ_SIZE); 1293 1422 1294 - /* 1295 - * We're being called on both module initialization and on reset, 1296 - * until this flow is changed, we're using regular client presence to 1297 - * determine which case are we in, and whether we should allocate new 1298 - * clients or just reset their workqueues. 1299 - */ 1300 - if (!guc->execbuf_client) { 1301 - err = guc_clients_create(guc); 1302 - if (err) 1303 - return err; 1304 - } else { 1305 - guc_reset_wq(guc->execbuf_client); 1306 - guc_reset_wq(guc->preempt_client); 1307 - } 1423 + GEM_BUG_ON(!guc->execbuf_client); 1424 + 1425 + guc_reset_wq(guc->execbuf_client); 1426 + guc_reset_wq(guc->preempt_client); 1308 1427 1309 1428 err = intel_guc_sample_forcewake(guc); 1310 1429 if (err) 1311 - goto err_free_clients; 1430 + return err; 1312 1431 1313 - err = guc_init_doorbell_hw(guc); 1432 + err = guc_clients_doorbell_init(guc); 1314 1433 if (err) 1315 - goto err_free_clients; 1434 + return err; 1316 1435 1317 1436 /* Take over from manual control of ELSP (execlists) */ 1318 1437 guc_interrupts_capture(dev_priv); ··· 1319 1458 } 1320 1459 1321 1460 return 0; 1322 - 1323 - err_free_clients: 1324 - guc_clients_destroy(guc); 1325 - return err; 1326 1461 } 1327 1462 1328 1463 void intel_guc_submission_disable(struct intel_guc *guc) ··· 1328 1471 GEM_BUG_ON(dev_priv->gt.awake); /* GT should be parked first */ 1329 1472 1330 1473 guc_interrupts_release(dev_priv); 1474 + guc_clients_doorbell_fini(guc); 1331 1475 1332 1476 /* Revert back to manual ELSP submission */ 1333 1477 intel_engines_reset_default_submission(dev_priv); 1334 - 1335 - guc_clients_destroy(guc); 1336 1478 } 1337 1479 1338 1480 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+2
drivers/gpu/drm/i915/intel_guc_submission.h
··· 77 77 int intel_guc_submission_enable(struct intel_guc *guc); 78 78 void intel_guc_submission_disable(struct intel_guc *guc); 79 79 void intel_guc_submission_fini(struct intel_guc *guc); 80 + int intel_guc_preempt_work_create(struct intel_guc *guc); 81 + void intel_guc_preempt_work_destroy(struct intel_guc *guc); 80 82 81 83 #endif
+1 -1
drivers/gpu/drm/i915/intel_gvt.c
··· 95 95 return 0; 96 96 } 97 97 98 - if (i915_modparams.enable_guc_submission) { 98 + if (USES_GUC_SUBMISSION(dev_priv)) { 99 99 DRM_ERROR("i915 GVT-g loading failed due to Graphics virtualization is not yet supported with GuC submission\n"); 100 100 return -EIO; 101 101 }
+6 -1
drivers/gpu/drm/i915/intel_hangcheck.c
··· 349 349 350 350 case ENGINE_ACTIVE_HEAD: 351 351 case ENGINE_ACTIVE_SUBUNITS: 352 - /* Seqno stuck with still active engine gets leeway, 352 + /* 353 + * Seqno stuck with still active engine gets leeway, 353 354 * in hopes that it is just a long shader. 354 355 */ 355 356 timeout = I915_SEQNO_DEAD_TIMEOUT; 356 357 break; 357 358 358 359 case ENGINE_DEAD: 360 + if (drm_debug & DRM_UT_DRIVER) { 361 + struct drm_printer p = drm_debug_printer("hangcheck"); 362 + intel_engine_dump(engine, &p, "%s", engine->name); 363 + } 359 364 break; 360 365 361 366 default:
+1 -1
drivers/gpu/drm/i915/intel_hdmi.c
··· 1383 1383 } 1384 1384 } 1385 1385 1386 - /* Display Wa #1139 */ 1386 + /* Display WA #1139: glk */ 1387 1387 if (IS_GLK_REVID(dev_priv, 0, GLK_REVID_A1) && 1388 1388 crtc_state->base.adjusted_mode.htotal > 5460) 1389 1389 return false;
+48 -33
drivers/gpu/drm/i915/intel_huc.c
··· 77 77 #define I915_GLK_HUC_UCODE HUC_FW_PATH(glk, GLK_HUC_FW_MAJOR, \ 78 78 GLK_HUC_FW_MINOR, GLK_BLD_NUM) 79 79 80 - /** 81 - * intel_huc_select_fw() - selects HuC firmware for loading 82 - * @huc: intel_huc struct 83 - */ 84 - void intel_huc_select_fw(struct intel_huc *huc) 80 + static void huc_fw_select(struct intel_uc_fw *huc_fw) 85 81 { 82 + struct intel_huc *huc = container_of(huc_fw, struct intel_huc, fw); 86 83 struct drm_i915_private *dev_priv = huc_to_i915(huc); 87 84 88 - intel_uc_fw_init(&huc->fw, INTEL_UC_FW_TYPE_HUC); 85 + GEM_BUG_ON(huc_fw->type != INTEL_UC_FW_TYPE_HUC); 86 + 87 + if (!HAS_HUC(dev_priv)) 88 + return; 89 89 90 90 if (i915_modparams.huc_firmware_path) { 91 - huc->fw.path = i915_modparams.huc_firmware_path; 92 - huc->fw.major_ver_wanted = 0; 93 - huc->fw.minor_ver_wanted = 0; 91 + huc_fw->path = i915_modparams.huc_firmware_path; 92 + huc_fw->major_ver_wanted = 0; 93 + huc_fw->minor_ver_wanted = 0; 94 94 } else if (IS_SKYLAKE(dev_priv)) { 95 - huc->fw.path = I915_SKL_HUC_UCODE; 96 - huc->fw.major_ver_wanted = SKL_HUC_FW_MAJOR; 97 - huc->fw.minor_ver_wanted = SKL_HUC_FW_MINOR; 95 + huc_fw->path = I915_SKL_HUC_UCODE; 96 + huc_fw->major_ver_wanted = SKL_HUC_FW_MAJOR; 97 + huc_fw->minor_ver_wanted = SKL_HUC_FW_MINOR; 98 98 } else if (IS_BROXTON(dev_priv)) { 99 - huc->fw.path = I915_BXT_HUC_UCODE; 100 - huc->fw.major_ver_wanted = BXT_HUC_FW_MAJOR; 101 - huc->fw.minor_ver_wanted = BXT_HUC_FW_MINOR; 99 + huc_fw->path = I915_BXT_HUC_UCODE; 100 + huc_fw->major_ver_wanted = BXT_HUC_FW_MAJOR; 101 + huc_fw->minor_ver_wanted = BXT_HUC_FW_MINOR; 102 102 } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { 103 - huc->fw.path = I915_KBL_HUC_UCODE; 104 - huc->fw.major_ver_wanted = KBL_HUC_FW_MAJOR; 105 - huc->fw.minor_ver_wanted = KBL_HUC_FW_MINOR; 103 + huc_fw->path = I915_KBL_HUC_UCODE; 104 + huc_fw->major_ver_wanted = KBL_HUC_FW_MAJOR; 105 + huc_fw->minor_ver_wanted = KBL_HUC_FW_MINOR; 106 106 } else if (IS_GEMINILAKE(dev_priv)) { 107 - huc->fw.path = I915_GLK_HUC_UCODE; 108 - huc->fw.major_ver_wanted = GLK_HUC_FW_MAJOR; 109 - huc->fw.minor_ver_wanted = GLK_HUC_FW_MINOR; 107 + huc_fw->path = I915_GLK_HUC_UCODE; 108 + huc_fw->major_ver_wanted = GLK_HUC_FW_MAJOR; 109 + huc_fw->minor_ver_wanted = GLK_HUC_FW_MINOR; 110 110 } else { 111 - DRM_ERROR("No HuC firmware known for platform with HuC!\n"); 112 - return; 111 + DRM_WARN("%s: No firmware known for this platform!\n", 112 + intel_uc_fw_type_repr(huc_fw->type)); 113 113 } 114 + } 115 + 116 + /** 117 + * intel_huc_init_early() - initializes HuC struct 118 + * @huc: intel_huc struct 119 + * 120 + * On platforms with HuC selects firmware for uploading 121 + */ 122 + void intel_huc_init_early(struct intel_huc *huc) 123 + { 124 + struct intel_uc_fw *huc_fw = &huc->fw; 125 + 126 + intel_uc_fw_init(huc_fw, INTEL_UC_FW_TYPE_HUC); 127 + huc_fw_select(huc_fw); 114 128 } 115 129 116 130 /** ··· 181 167 * intel_huc_init_hw() - load HuC uCode to device 182 168 * @huc: intel_huc structure 183 169 * 184 - * Called from guc_setup() during driver loading and also after a GPU reset. 185 - * Be note that HuC loading must be done before GuC loading. 170 + * Called from intel_uc_init_hw() during driver loading and also after a GPU 171 + * reset. Be note that HuC loading must be done before GuC loading. 186 172 * 187 173 * The firmware image should have already been fetched into memory by the 188 - * earlier call to intel_huc_init(), so here we need only check that 174 + * earlier call to intel_uc_init_fw(), so here we need only check that 189 175 * is succeeded, and then transfer the image to the h/w. 190 176 * 191 177 */ 192 - void intel_huc_init_hw(struct intel_huc *huc) 178 + int intel_huc_init_hw(struct intel_huc *huc) 193 179 { 194 - intel_uc_fw_upload(&huc->fw, huc_ucode_xfer); 180 + return intel_uc_fw_upload(&huc->fw, huc_ucode_xfer); 195 181 } 196 182 197 183 /** ··· 205 191 * signature through intel_guc_auth_huc(). It then waits for 50ms for 206 192 * firmware verification ACK and unpins the object. 207 193 */ 208 - void intel_huc_auth(struct intel_huc *huc) 194 + int intel_huc_auth(struct intel_huc *huc) 209 195 { 210 196 struct drm_i915_private *i915 = huc_to_i915(huc); 211 197 struct intel_guc *guc = &i915->guc; ··· 213 199 int ret; 214 200 215 201 if (huc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) 216 - return; 202 + return -ENOEXEC; 217 203 218 204 vma = i915_gem_object_ggtt_pin(huc->fw.obj, NULL, 0, 0, 219 205 PIN_OFFSET_BIAS | GUC_WOPCM_TOP); 220 206 if (IS_ERR(vma)) { 221 - DRM_ERROR("failed to pin huc fw object %d\n", 222 - (int)PTR_ERR(vma)); 223 - return; 207 + ret = PTR_ERR(vma); 208 + DRM_ERROR("HuC: Failed to pin huc fw object %d\n", ret); 209 + return ret; 224 210 } 225 211 226 212 ret = intel_guc_auth_huc(guc, ··· 243 229 244 230 out: 245 231 i915_vma_unpin(vma); 232 + return ret; 246 233 }
+3 -3
drivers/gpu/drm/i915/intel_huc.h
··· 34 34 /* HuC-specific additions */ 35 35 }; 36 36 37 - void intel_huc_select_fw(struct intel_huc *huc); 38 - void intel_huc_init_hw(struct intel_huc *huc); 39 - void intel_huc_auth(struct intel_huc *huc); 37 + void intel_huc_init_early(struct intel_huc *huc); 38 + int intel_huc_init_hw(struct intel_huc *huc); 39 + int intel_huc_auth(struct intel_huc *huc); 40 40 41 41 #endif
+6 -7
drivers/gpu/drm/i915/intel_lrc.c
··· 431 431 static void execlists_submit_ports(struct intel_engine_cs *engine) 432 432 { 433 433 struct execlist_port *port = engine->execlists.port; 434 - u32 __iomem *elsp = 435 - engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); 436 434 unsigned int n; 437 435 438 436 for (n = execlists_num_ports(&engine->execlists); n--; ) { ··· 456 458 desc = 0; 457 459 } 458 460 459 - elsp_write(desc, elsp); 461 + elsp_write(desc, engine->execlists.elsp); 460 462 } 461 463 execlists_clear_active(&engine->execlists, EXECLISTS_ACTIVE_HWACK); 462 464 } ··· 494 496 { 495 497 struct intel_context *ce = 496 498 &engine->i915->preempt_context->engine[engine->id]; 497 - u32 __iomem *elsp = 498 - engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); 499 499 unsigned int n; 500 500 501 501 GEM_BUG_ON(engine->i915->preempt_context->hw_id != PREEMPT_ID); ··· 506 510 507 511 GEM_TRACE("\n"); 508 512 for (n = execlists_num_ports(&engine->execlists); --n; ) 509 - elsp_write(0, elsp); 513 + elsp_write(0, engine->execlists.elsp); 510 514 511 - elsp_write(ce->lrc_desc, elsp); 515 + elsp_write(ce->lrc_desc, engine->execlists.elsp); 512 516 execlists_clear_active(&engine->execlists, EXECLISTS_ACTIVE_HWACK); 513 517 } 514 518 ··· 1504 1508 clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); 1505 1509 execlists->csb_head = -1; 1506 1510 execlists->active = 0; 1511 + 1512 + execlists->elsp = 1513 + dev_priv->regs + i915_mmio_reg_offset(RING_ELSP(engine)); 1507 1514 1508 1515 /* After a GPU reset, we may have requests to replay */ 1509 1516 if (execlists->first)
+2 -2
drivers/gpu/drm/i915/intel_overlay.c
··· 219 219 if (OVERLAY_NEEDS_PHYSICAL(dev_priv)) 220 220 regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr; 221 221 else 222 - regs = io_mapping_map_wc(&dev_priv->ggtt.mappable, 222 + regs = io_mapping_map_wc(&dev_priv->ggtt.iomap, 223 223 overlay->flip_addr, 224 224 PAGE_SIZE); 225 225 ··· 1508 1508 regs = (struct overlay_registers __iomem *) 1509 1509 overlay->reg_bo->phys_handle->vaddr; 1510 1510 else 1511 - regs = io_mapping_map_atomic_wc(&dev_priv->ggtt.mappable, 1511 + regs = io_mapping_map_atomic_wc(&dev_priv->ggtt.iomap, 1512 1512 overlay->flip_addr); 1513 1513 1514 1514 return regs;
+18 -17
drivers/gpu/drm/i915/intel_pm.c
··· 58 58 if (HAS_LLC(dev_priv)) { 59 59 /* 60 60 * WaCompressedResourceDisplayNewHashMode:skl,kbl 61 - * Display WA#0390: skl,kbl 61 + * Display WA #0390: skl,kbl 62 62 * 63 63 * Must match Sampler, Pixel Back End, and Media. See 64 64 * WaCompressedResourceSamplerPbeMediaNewHashMode. ··· 6416 6416 6417 6417 static bool bxt_check_bios_rc6_setup(struct drm_i915_private *dev_priv) 6418 6418 { 6419 - struct i915_ggtt *ggtt = &dev_priv->ggtt; 6420 6419 bool enable_rc6 = true; 6421 6420 unsigned long rc6_ctx_base; 6422 6421 u32 rc_ctl; ··· 6440 6441 * for this check. 6441 6442 */ 6442 6443 rc6_ctx_base = I915_READ(RC6_CTX_BASE) & RC6_CTX_BASE_MASK; 6443 - if (!((rc6_ctx_base >= ggtt->stolen_reserved_base) && 6444 - (rc6_ctx_base + PAGE_SIZE <= ggtt->stolen_reserved_base + 6445 - ggtt->stolen_reserved_size))) { 6444 + if (!((rc6_ctx_base >= dev_priv->dsm_reserved.start) && 6445 + (rc6_ctx_base + PAGE_SIZE < dev_priv->dsm_reserved.end))) { 6446 6446 DRM_DEBUG_DRIVER("RC6 Base address not as expected.\n"); 6447 6447 enable_rc6 = false; 6448 6448 } ··· 7018 7020 { 7019 7021 unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095; 7020 7022 7021 - WARN_ON(pctx_addr != dev_priv->mm.stolen_base + 7023 + WARN_ON(pctx_addr != dev_priv->dsm.start + 7022 7024 dev_priv->vlv_pctx->stolen->start); 7023 7025 } 7024 7026 ··· 7033 7035 7034 7036 static void cherryview_setup_pctx(struct drm_i915_private *dev_priv) 7035 7037 { 7036 - struct i915_ggtt *ggtt = &dev_priv->ggtt; 7037 - unsigned long pctx_paddr, paddr; 7038 + resource_size_t pctx_paddr, paddr; 7039 + resource_size_t pctx_size = 32*1024; 7038 7040 u32 pcbr; 7039 - int pctx_size = 32*1024; 7040 7041 7041 7042 pcbr = I915_READ(VLV_PCBR); 7042 7043 if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) { 7043 7044 DRM_DEBUG_DRIVER("BIOS didn't set up PCBR, fixing up\n"); 7044 - paddr = (dev_priv->mm.stolen_base + 7045 - (ggtt->stolen_size - pctx_size)); 7045 + paddr = dev_priv->dsm.end + 1 - pctx_size; 7046 + GEM_BUG_ON(paddr > U32_MAX); 7046 7047 7047 7048 pctx_paddr = (paddr & (~4095)); 7048 7049 I915_WRITE(VLV_PCBR, pctx_paddr); ··· 7053 7056 static void valleyview_setup_pctx(struct drm_i915_private *dev_priv) 7054 7057 { 7055 7058 struct drm_i915_gem_object *pctx; 7056 - unsigned long pctx_paddr; 7059 + resource_size_t pctx_paddr; 7060 + resource_size_t pctx_size = 24*1024; 7057 7061 u32 pcbr; 7058 - int pctx_size = 24*1024; 7059 7062 7060 7063 pcbr = I915_READ(VLV_PCBR); 7061 7064 if (pcbr) { 7062 7065 /* BIOS set it up already, grab the pre-alloc'd space */ 7063 - int pcbr_offset; 7066 + resource_size_t pcbr_offset; 7064 7067 7065 - pcbr_offset = (pcbr & (~4095)) - dev_priv->mm.stolen_base; 7068 + pcbr_offset = (pcbr & (~4095)) - dev_priv->dsm.start; 7066 7069 pctx = i915_gem_object_create_stolen_for_preallocated(dev_priv, 7067 7070 pcbr_offset, 7068 7071 I915_GTT_OFFSET_NONE, ··· 7086 7089 goto out; 7087 7090 } 7088 7091 7089 - pctx_paddr = dev_priv->mm.stolen_base + pctx->stolen->start; 7092 + GEM_BUG_ON(range_overflows_t(u64, 7093 + dev_priv->dsm.start, 7094 + pctx->stolen->start, 7095 + U32_MAX)); 7096 + pctx_paddr = dev_priv->dsm.start + pctx->stolen->start; 7090 7097 I915_WRITE(VLV_PCBR, pctx_paddr); 7091 7098 7092 7099 out: ··· 8418 8417 if (!HAS_PCH_CNP(dev_priv)) 8419 8418 return; 8420 8419 8421 - /* Wa #1181 */ 8420 + /* Display WA #1181: cnp */ 8422 8421 I915_WRITE(SOUTH_DSPCLK_GATE_D, I915_READ(SOUTH_DSPCLK_GATE_D) | 8423 8422 CNP_PWM_CGE_GATING_DISABLE); 8424 8423 }
+9 -1
drivers/gpu/drm/i915/intel_ringbuffer.h
··· 200 200 bool no_priolist; 201 201 202 202 /** 203 + * @elsp: the ExecList Submission Port register 204 + */ 205 + u32 __iomem *elsp; 206 + 207 + /** 203 208 * @port: execlist port states 204 209 * 205 210 * For each hardware ELSP (ExecList Submission Port) we keep ··· 1013 1008 1014 1009 bool intel_engine_can_store_dword(struct intel_engine_cs *engine); 1015 1010 1016 - void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *p); 1011 + __printf(3, 4) 1012 + void intel_engine_dump(struct intel_engine_cs *engine, 1013 + struct drm_printer *m, 1014 + const char *header, ...); 1017 1015 1018 1016 struct intel_engine_cs * 1019 1017 intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance);
+5
drivers/gpu/drm/i915/intel_runtime_pm.c
··· 130 130 return "INIT"; 131 131 case POWER_DOMAIN_MODESET: 132 132 return "MODESET"; 133 + case POWER_DOMAIN_GT_IRQ: 134 + return "GT_IRQ"; 133 135 default: 134 136 MISSING_CASE(domain); 135 137 return "?"; ··· 1707 1705 BIT_ULL(POWER_DOMAIN_INIT)) 1708 1706 #define SKL_DISPLAY_DC_OFF_POWER_DOMAINS ( \ 1709 1707 SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ 1708 + BIT_ULL(POWER_DOMAIN_GT_IRQ) | \ 1710 1709 BIT_ULL(POWER_DOMAIN_MODESET) | \ 1711 1710 BIT_ULL(POWER_DOMAIN_AUX_A) | \ 1712 1711 BIT_ULL(POWER_DOMAIN_INIT)) ··· 1730 1727 BIT_ULL(POWER_DOMAIN_INIT)) 1731 1728 #define BXT_DISPLAY_DC_OFF_POWER_DOMAINS ( \ 1732 1729 BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ 1730 + BIT_ULL(POWER_DOMAIN_GT_IRQ) | \ 1733 1731 BIT_ULL(POWER_DOMAIN_MODESET) | \ 1734 1732 BIT_ULL(POWER_DOMAIN_AUX_A) | \ 1735 1733 BIT_ULL(POWER_DOMAIN_INIT)) ··· 1789 1785 BIT_ULL(POWER_DOMAIN_INIT)) 1790 1786 #define GLK_DISPLAY_DC_OFF_POWER_DOMAINS ( \ 1791 1787 GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ 1788 + BIT_ULL(POWER_DOMAIN_GT_IRQ) | \ 1792 1789 BIT_ULL(POWER_DOMAIN_MODESET) | \ 1793 1790 BIT_ULL(POWER_DOMAIN_AUX_A) | \ 1794 1791 BIT_ULL(POWER_DOMAIN_INIT))
+170 -79
drivers/gpu/drm/i915/intel_uc.c
··· 24 24 25 25 #include "intel_uc.h" 26 26 #include "intel_guc_submission.h" 27 + #include "intel_guc.h" 27 28 #include "i915_drv.h" 28 29 29 30 /* Reset GuC providing us with fresh state for both GuC and HuC. ··· 48 47 return ret; 49 48 } 50 49 50 + static int __get_platform_enable_guc(struct drm_i915_private *dev_priv) 51 + { 52 + struct intel_uc_fw *guc_fw = &dev_priv->guc.fw; 53 + struct intel_uc_fw *huc_fw = &dev_priv->huc.fw; 54 + int enable_guc = 0; 55 + 56 + /* Default is to enable GuC/HuC if we know their firmwares */ 57 + if (intel_uc_fw_is_selected(guc_fw)) 58 + enable_guc |= ENABLE_GUC_SUBMISSION; 59 + if (intel_uc_fw_is_selected(huc_fw)) 60 + enable_guc |= ENABLE_GUC_LOAD_HUC; 61 + 62 + /* Any platform specific fine-tuning can be done here */ 63 + 64 + return enable_guc; 65 + } 66 + 67 + /** 68 + * intel_uc_sanitize_options - sanitize uC related modparam options 69 + * @dev_priv: device private 70 + * 71 + * In case of "enable_guc" option this function will attempt to modify 72 + * it only if it was initially set to "auto(-1)". Default value for this 73 + * modparam varies between platforms and it is hardcoded in driver code. 74 + * Any other modparam value is only monitored against availability of the 75 + * related hardware or firmware definitions. 76 + */ 51 77 void intel_uc_sanitize_options(struct drm_i915_private *dev_priv) 52 78 { 53 - if (!HAS_GUC(dev_priv)) { 54 - if (i915_modparams.enable_guc_loading > 0 || 55 - i915_modparams.enable_guc_submission > 0) 56 - DRM_INFO("Ignoring GuC options, no hardware\n"); 57 - 58 - i915_modparams.enable_guc_loading = 0; 59 - i915_modparams.enable_guc_submission = 0; 60 - return; 61 - } 79 + struct intel_uc_fw *guc_fw = &dev_priv->guc.fw; 80 + struct intel_uc_fw *huc_fw = &dev_priv->huc.fw; 62 81 63 82 /* A negative value means "use platform default" */ 64 - if (i915_modparams.enable_guc_loading < 0) 65 - i915_modparams.enable_guc_loading = HAS_GUC_UCODE(dev_priv); 83 + if (i915_modparams.enable_guc < 0) 84 + i915_modparams.enable_guc = __get_platform_enable_guc(dev_priv); 66 85 67 - /* Verify firmware version */ 68 - if (i915_modparams.enable_guc_loading) { 69 - if (HAS_HUC_UCODE(dev_priv)) 70 - intel_huc_select_fw(&dev_priv->huc); 86 + DRM_DEBUG_DRIVER("enable_guc=%d (submission:%s huc:%s)\n", 87 + i915_modparams.enable_guc, 88 + yesno(intel_uc_is_using_guc_submission()), 89 + yesno(intel_uc_is_using_huc())); 71 90 72 - if (intel_guc_fw_select(&dev_priv->guc)) 73 - i915_modparams.enable_guc_loading = 0; 91 + /* Verify GuC firmware availability */ 92 + if (intel_uc_is_using_guc() && !intel_uc_fw_is_selected(guc_fw)) { 93 + DRM_WARN("Incompatible option detected: enable_guc=%d, %s!\n", 94 + i915_modparams.enable_guc, 95 + !HAS_GUC(dev_priv) ? "no GuC hardware" : 96 + "no GuC firmware"); 74 97 } 75 98 76 - /* Can't enable guc submission without guc loaded */ 77 - if (!i915_modparams.enable_guc_loading) 78 - i915_modparams.enable_guc_submission = 0; 99 + /* Verify HuC firmware availability */ 100 + if (intel_uc_is_using_huc() && !intel_uc_fw_is_selected(huc_fw)) { 101 + DRM_WARN("Incompatible option detected: enable_guc=%d, %s!\n", 102 + i915_modparams.enable_guc, 103 + !HAS_HUC(dev_priv) ? "no HuC hardware" : 104 + "no HuC firmware"); 105 + } 79 106 80 - /* A negative value means "use platform default" */ 81 - if (i915_modparams.enable_guc_submission < 0) 82 - i915_modparams.enable_guc_submission = HAS_GUC_SCHED(dev_priv); 107 + /* Make sure that sanitization was done */ 108 + GEM_BUG_ON(i915_modparams.enable_guc < 0); 83 109 } 84 110 85 111 void intel_uc_init_early(struct drm_i915_private *dev_priv) 86 112 { 87 113 intel_guc_init_early(&dev_priv->guc); 114 + intel_huc_init_early(&dev_priv->huc); 88 115 } 89 116 90 117 void intel_uc_init_fw(struct drm_i915_private *dev_priv) 91 118 { 92 - intel_uc_fw_fetch(dev_priv, &dev_priv->huc.fw); 119 + if (!USES_GUC(dev_priv)) 120 + return; 121 + 122 + if (USES_HUC(dev_priv)) 123 + intel_uc_fw_fetch(dev_priv, &dev_priv->huc.fw); 124 + 93 125 intel_uc_fw_fetch(dev_priv, &dev_priv->guc.fw); 94 126 } 95 127 96 128 void intel_uc_fini_fw(struct drm_i915_private *dev_priv) 97 129 { 130 + if (!USES_GUC(dev_priv)) 131 + return; 132 + 98 133 intel_uc_fw_fini(&dev_priv->guc.fw); 99 - intel_uc_fw_fini(&dev_priv->huc.fw); 134 + 135 + if (USES_HUC(dev_priv)) 136 + intel_uc_fw_fini(&dev_priv->huc.fw); 100 137 } 101 138 102 139 /** ··· 188 149 guc->send = intel_guc_send_nop; 189 150 } 190 151 191 - int intel_uc_init_hw(struct drm_i915_private *dev_priv) 152 + int intel_uc_init_wq(struct drm_i915_private *dev_priv) 192 153 { 193 - struct intel_guc *guc = &dev_priv->guc; 194 - int ret, attempts; 154 + int ret; 195 155 196 - if (!i915_modparams.enable_guc_loading) 156 + if (!USES_GUC(dev_priv)) 197 157 return 0; 198 158 199 - guc_disable_communication(guc); 200 - gen9_reset_guc_interrupts(dev_priv); 159 + ret = intel_guc_init_wq(&dev_priv->guc); 160 + if (ret) { 161 + DRM_ERROR("Couldn't allocate workqueues for GuC\n"); 162 + return ret; 163 + } 201 164 202 - /* We need to notify the guc whenever we change the GGTT */ 203 - i915_ggtt_enable_guc(dev_priv); 165 + return 0; 166 + } 204 167 205 - if (i915_modparams.enable_guc_submission) { 168 + void intel_uc_fini_wq(struct drm_i915_private *dev_priv) 169 + { 170 + if (!USES_GUC(dev_priv)) 171 + return; 172 + 173 + GEM_BUG_ON(!HAS_GUC(dev_priv)); 174 + 175 + intel_guc_fini_wq(&dev_priv->guc); 176 + } 177 + 178 + int intel_uc_init(struct drm_i915_private *dev_priv) 179 + { 180 + struct intel_guc *guc = &dev_priv->guc; 181 + int ret; 182 + 183 + if (!USES_GUC(dev_priv)) 184 + return 0; 185 + 186 + if (!HAS_GUC(dev_priv)) 187 + return -ENODEV; 188 + 189 + ret = intel_guc_init(guc); 190 + if (ret) 191 + return ret; 192 + 193 + if (USES_GUC_SUBMISSION(dev_priv)) { 206 194 /* 207 195 * This is stuff we need to have available at fw load time 208 196 * if we are planning to enable submission later 209 197 */ 210 198 ret = intel_guc_submission_init(guc); 211 - if (ret) 212 - goto err_guc; 199 + if (ret) { 200 + intel_guc_fini(guc); 201 + return ret; 202 + } 213 203 } 204 + 205 + return 0; 206 + } 207 + 208 + void intel_uc_fini(struct drm_i915_private *dev_priv) 209 + { 210 + struct intel_guc *guc = &dev_priv->guc; 211 + 212 + if (!USES_GUC(dev_priv)) 213 + return; 214 + 215 + GEM_BUG_ON(!HAS_GUC(dev_priv)); 216 + 217 + if (USES_GUC_SUBMISSION(dev_priv)) 218 + intel_guc_submission_fini(guc); 219 + 220 + intel_guc_fini(guc); 221 + } 222 + 223 + int intel_uc_init_hw(struct drm_i915_private *dev_priv) 224 + { 225 + struct intel_guc *guc = &dev_priv->guc; 226 + struct intel_huc *huc = &dev_priv->huc; 227 + int ret, attempts; 228 + 229 + if (!USES_GUC(dev_priv)) 230 + return 0; 231 + 232 + GEM_BUG_ON(!HAS_GUC(dev_priv)); 233 + 234 + guc_disable_communication(guc); 235 + gen9_reset_guc_interrupts(dev_priv); 214 236 215 237 /* init WOPCM */ 216 238 I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(dev_priv)); ··· 292 192 */ 293 193 ret = __intel_uc_reset_hw(dev_priv); 294 194 if (ret) 295 - goto err_submission; 195 + goto err_out; 296 196 297 - intel_huc_init_hw(&dev_priv->huc); 197 + if (USES_HUC(dev_priv)) { 198 + ret = intel_huc_init_hw(huc); 199 + if (ret) 200 + goto err_out; 201 + } 202 + 298 203 intel_guc_init_params(guc); 299 204 ret = intel_guc_fw_upload(guc); 300 205 if (ret == 0 || ret != -EAGAIN) ··· 317 212 if (ret) 318 213 goto err_log_capture; 319 214 320 - intel_huc_auth(&dev_priv->huc); 321 - if (i915_modparams.enable_guc_submission) { 215 + if (USES_HUC(dev_priv)) { 216 + ret = intel_huc_auth(huc); 217 + if (ret) 218 + goto err_communication; 219 + } 220 + 221 + if (USES_GUC_SUBMISSION(dev_priv)) { 322 222 if (i915_modparams.guc_log_level >= 0) 323 223 gen9_enable_guc_interrupts(dev_priv); 324 224 ··· 332 222 goto err_interrupts; 333 223 } 334 224 335 - dev_info(dev_priv->drm.dev, "GuC %s (firmware %s [version %u.%u])\n", 336 - i915_modparams.enable_guc_submission ? "submission enabled" : 337 - "loaded", 338 - guc->fw.path, 225 + dev_info(dev_priv->drm.dev, "GuC firmware version %u.%u\n", 339 226 guc->fw.major_ver_found, guc->fw.minor_ver_found); 227 + dev_info(dev_priv->drm.dev, "GuC submission %s\n", 228 + enableddisabled(USES_GUC_SUBMISSION(dev_priv))); 229 + dev_info(dev_priv->drm.dev, "HuC %s\n", 230 + enableddisabled(USES_HUC(dev_priv))); 340 231 341 232 return 0; 342 233 343 234 /* 344 235 * We've failed to load the firmware :( 345 - * 346 - * Decide whether to disable GuC submission and fall back to 347 - * execlist mode, and whether to hide the error by returning 348 - * zero or to return -EIO, which the caller will treat as a 349 - * nonfatal error (i.e. it doesn't prevent driver load, but 350 - * marks the GPU as wedged until reset). 351 236 */ 352 237 err_interrupts: 353 - guc_disable_communication(guc); 354 238 gen9_disable_guc_interrupts(dev_priv); 239 + err_communication: 240 + guc_disable_communication(guc); 355 241 err_log_capture: 356 242 guc_capture_load_err_log(guc); 357 - err_submission: 358 - if (i915_modparams.enable_guc_submission) 359 - intel_guc_submission_fini(guc); 360 - err_guc: 361 - i915_ggtt_disable_guc(dev_priv); 243 + err_out: 244 + /* 245 + * Note that there is no fallback as either user explicitly asked for 246 + * the GuC or driver default option was to run with the GuC enabled. 247 + */ 248 + if (GEM_WARN_ON(ret == -EIO)) 249 + ret = -EINVAL; 362 250 363 - if (i915_modparams.enable_guc_loading > 1 || 364 - i915_modparams.enable_guc_submission > 1) { 365 - DRM_ERROR("GuC init failed. Firmware loading disabled.\n"); 366 - ret = -EIO; 367 - } else { 368 - DRM_NOTE("GuC init failed. Firmware loading disabled.\n"); 369 - ret = 0; 370 - } 371 - 372 - if (i915_modparams.enable_guc_submission) { 373 - i915_modparams.enable_guc_submission = 0; 374 - DRM_NOTE("Falling back from GuC submission to execlist mode\n"); 375 - } 376 - 377 - i915_modparams.enable_guc_loading = 0; 378 - 251 + dev_err(dev_priv->drm.dev, "GuC initialization failed %d\n", ret); 379 252 return ret; 380 253 } 381 254 ··· 368 275 369 276 guc_free_load_err_log(guc); 370 277 371 - if (!i915_modparams.enable_guc_loading) 278 + if (!USES_GUC(dev_priv)) 372 279 return; 373 280 374 - if (i915_modparams.enable_guc_submission) 281 + GEM_BUG_ON(!HAS_GUC(dev_priv)); 282 + 283 + if (USES_GUC_SUBMISSION(dev_priv)) 375 284 intel_guc_submission_disable(guc); 376 285 377 286 guc_disable_communication(guc); 378 287 379 - if (i915_modparams.enable_guc_submission) { 288 + if (USES_GUC_SUBMISSION(dev_priv)) 380 289 gen9_disable_guc_interrupts(dev_priv); 381 - intel_guc_submission_fini(guc); 382 - } 383 - 384 - i915_ggtt_disable_guc(dev_priv); 385 290 }
+23
drivers/gpu/drm/i915/intel_uc.h
··· 26 26 27 27 #include "intel_guc.h" 28 28 #include "intel_huc.h" 29 + #include "i915_params.h" 29 30 30 31 void intel_uc_sanitize_options(struct drm_i915_private *dev_priv); 31 32 void intel_uc_init_early(struct drm_i915_private *dev_priv); 32 33 void intel_uc_init_mmio(struct drm_i915_private *dev_priv); 33 34 void intel_uc_init_fw(struct drm_i915_private *dev_priv); 34 35 void intel_uc_fini_fw(struct drm_i915_private *dev_priv); 36 + int intel_uc_init_wq(struct drm_i915_private *dev_priv); 37 + void intel_uc_fini_wq(struct drm_i915_private *dev_priv); 35 38 int intel_uc_init_hw(struct drm_i915_private *dev_priv); 36 39 void intel_uc_fini_hw(struct drm_i915_private *dev_priv); 40 + int intel_uc_init(struct drm_i915_private *dev_priv); 41 + void intel_uc_fini(struct drm_i915_private *dev_priv); 42 + 43 + static inline bool intel_uc_is_using_guc(void) 44 + { 45 + GEM_BUG_ON(i915_modparams.enable_guc < 0); 46 + return i915_modparams.enable_guc > 0; 47 + } 48 + 49 + static inline bool intel_uc_is_using_guc_submission(void) 50 + { 51 + GEM_BUG_ON(i915_modparams.enable_guc < 0); 52 + return i915_modparams.enable_guc & ENABLE_GUC_SUBMISSION; 53 + } 54 + 55 + static inline bool intel_uc_is_using_huc(void) 56 + { 57 + GEM_BUG_ON(i915_modparams.enable_guc < 0); 58 + return i915_modparams.enable_guc & ENABLE_GUC_LOAD_HUC; 59 + } 37 60 38 61 #endif
+1 -1
drivers/gpu/drm/i915/intel_uc_fw.c
··· 214 214 intel_uc_fw_type_repr(uc_fw->type), uc_fw->path); 215 215 216 216 if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS) 217 - return -EIO; 217 + return -ENOEXEC; 218 218 219 219 uc_fw->load_status = INTEL_UC_FIRMWARE_PENDING; 220 220 DRM_DEBUG_DRIVER("%s fw load %s\n",
+5
drivers/gpu/drm/i915/intel_uc_fw.h
··· 110 110 uc_fw->type = type; 111 111 } 112 112 113 + static inline bool intel_uc_fw_is_selected(struct intel_uc_fw *uc_fw) 114 + { 115 + return uc_fw->path != NULL; 116 + } 117 + 113 118 void intel_uc_fw_fetch(struct drm_i915_private *dev_priv, 114 119 struct intel_uc_fw *uc_fw); 115 120 int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
+2 -2
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
··· 1074 1074 i915_gem_object_get_dma_address(obj, 0), 1075 1075 offset, I915_CACHE_NONE, 0); 1076 1076 1077 - vaddr = io_mapping_map_atomic_wc(&ggtt->mappable, offset); 1077 + vaddr = io_mapping_map_atomic_wc(&ggtt->iomap, offset); 1078 1078 iowrite32(n, vaddr + n); 1079 1079 io_mapping_unmap_atomic(vaddr); 1080 1080 ··· 1092 1092 i915_gem_object_get_dma_address(obj, 0), 1093 1093 offset, I915_CACHE_NONE, 0); 1094 1094 1095 - vaddr = io_mapping_map_atomic_wc(&ggtt->mappable, offset); 1095 + vaddr = io_mapping_map_atomic_wc(&ggtt->iomap, offset); 1096 1096 val = ioread32(vaddr + n); 1097 1097 io_mapping_unmap_atomic(vaddr); 1098 1098
+48 -64
drivers/gpu/drm/i915/selftests/intel_guc.c
··· 85 85 return 0; 86 86 } 87 87 88 + static bool client_doorbell_in_sync(struct intel_guc_client *client) 89 + { 90 + return doorbell_ok(client->guc, client->doorbell_id); 91 + } 92 + 88 93 /* 89 - * Check that guc_init_doorbell_hw is doing what it should. 94 + * Check that we're able to synchronize guc_clients with their doorbells 90 95 * 91 - * During GuC submission enable, we create GuC clients and their doorbells, 92 - * but after resetting the microcontroller (resume & gpu reset), these 93 - * GuC clients are still around, but the status of their doorbells may be 94 - * incorrect. This is the reason behind validating that the doorbells status 95 - * expected by the driver matches what the GuC/HW have. 96 + * We're creating clients and reserving doorbells once, at module load. During 97 + * module lifetime, GuC, doorbell HW, and i915 state may go out of sync due to 98 + * GuC being reset. In other words - GuC clients are still around, but the 99 + * status of their doorbells may be incorrect. This is the reason behind 100 + * validating that the doorbells status expected by the driver matches what the 101 + * GuC/HW have. 96 102 */ 97 - static int igt_guc_init_doorbell_hw(void *args) 103 + static int igt_guc_clients(void *args) 98 104 { 99 105 struct drm_i915_private *dev_priv = args; 100 106 struct intel_guc *guc; 101 - DECLARE_BITMAP(db_bitmap_bk, GUC_NUM_DOORBELLS); 102 - int i, err = 0; 107 + int err = 0; 103 108 104 109 GEM_BUG_ON(!HAS_GUC(dev_priv)); 105 110 mutex_lock(&dev_priv->drm.struct_mutex); ··· 153 148 goto out; 154 149 } 155 150 156 - /* each client should have received a doorbell during alloc */ 151 + /* each client should now have reserved a doorbell */ 157 152 if (!has_doorbell(guc->execbuf_client) || 158 153 !has_doorbell(guc->preempt_client)) { 159 - pr_err("guc_clients_create didn't create doorbells\n"); 154 + pr_err("guc_clients_create didn't reserve doorbells\n"); 155 + err = -EINVAL; 156 + goto out; 157 + } 158 + 159 + /* Now create the doorbells */ 160 + guc_clients_doorbell_init(guc); 161 + 162 + /* each client should now have received a doorbell */ 163 + if (!client_doorbell_in_sync(guc->execbuf_client) || 164 + !client_doorbell_in_sync(guc->preempt_client)) { 165 + pr_err("failed to initialize the doorbells\n"); 160 166 err = -EINVAL; 161 167 goto out; 162 168 } ··· 176 160 * Basic test - an attempt to reallocate a valid doorbell to the 177 161 * client it is currently assigned should not cause a failure. 178 162 */ 179 - err = guc_init_doorbell_hw(guc); 163 + err = guc_clients_doorbell_init(guc); 180 164 if (err) 181 165 goto out; 182 166 183 167 /* 184 168 * Negative test - a client with no doorbell (invalid db id). 185 - * Each client gets a doorbell when it is created, after destroying 186 - * the doorbell, the db id is changed to GUC_DOORBELL_INVALID and the 187 - * firmware will reject any attempt to allocate a doorbell with an 188 - * invalid id (db has to be reserved before allocation). 169 + * After destroying the doorbell, the db id is changed to 170 + * GUC_DOORBELL_INVALID and the firmware will reject any attempt to 171 + * allocate a doorbell with an invalid id (db has to be reserved before 172 + * allocation). 189 173 */ 190 174 destroy_doorbell(guc->execbuf_client); 191 - if (has_doorbell(guc->execbuf_client)) { 175 + if (client_doorbell_in_sync(guc->execbuf_client)) { 192 176 pr_err("destroy db did not work\n"); 193 177 err = -EINVAL; 194 178 goto out; 195 179 } 196 180 197 - err = guc_init_doorbell_hw(guc); 181 + unreserve_doorbell(guc->execbuf_client); 182 + err = guc_clients_doorbell_init(guc); 198 183 if (err != -EIO) { 199 184 pr_err("unexpected (err = %d)", err); 200 185 goto out; ··· 208 191 } 209 192 210 193 /* clean after test */ 194 + err = reserve_doorbell(guc->execbuf_client); 195 + if (err) { 196 + pr_err("failed to reserve back the doorbell back\n"); 197 + } 211 198 err = create_doorbell(guc->execbuf_client); 212 199 if (err) { 213 200 pr_err("recreate doorbell failed\n"); 214 - goto out; 215 - } 216 - 217 - /* 218 - * Negative test - doorbell_bitmap out of sync, will trigger a few of 219 - * WARN_ON(!doorbell_ok(guc, db_id)) but that's ok as long as the 220 - * doorbells from our clients don't fail. 221 - */ 222 - bitmap_copy(db_bitmap_bk, guc->doorbell_bitmap, GUC_NUM_DOORBELLS); 223 - for (i = 0; i < GUC_NUM_DOORBELLS; i++) 224 - if (i % 2) 225 - test_and_change_bit(i, guc->doorbell_bitmap); 226 - 227 - err = guc_init_doorbell_hw(guc); 228 - if (err) { 229 - pr_err("out of sync doorbell caused an error\n"); 230 - goto out; 231 - } 232 - 233 - /* restore 'correct' db bitmap */ 234 - bitmap_copy(guc->doorbell_bitmap, db_bitmap_bk, GUC_NUM_DOORBELLS); 235 - err = guc_init_doorbell_hw(guc); 236 - if (err) { 237 - pr_err("restored doorbell caused an error\n"); 238 201 goto out; 239 202 } 240 203 ··· 223 226 * Leave clean state for other test, plus the driver always destroy the 224 227 * clients during unload. 225 228 */ 229 + destroy_doorbell(guc->execbuf_client); 230 + destroy_doorbell(guc->preempt_client); 226 231 guc_clients_destroy(guc); 227 232 guc_clients_create(guc); 233 + guc_clients_doorbell_init(guc); 228 234 unlock: 229 235 mutex_unlock(&dev_priv->drm.struct_mutex); 230 236 return err; ··· 309 309 310 310 db_id = clients[i]->doorbell_id; 311 311 312 - /* 313 - * Client alloc gives us a doorbell, but we want to exercise 314 - * this ourselves (this resembles guc_init_doorbell_hw) 315 - */ 316 - destroy_doorbell(clients[i]); 317 - if (clients[i]->doorbell_id != GUC_DOORBELL_INVALID) { 318 - pr_err("[%d] destroy db did not work!\n", i); 319 - err = -EINVAL; 320 - goto out; 321 - } 322 - 323 - err = __reserve_doorbell(clients[i]); 324 - if (err) { 325 - pr_err("[%d] Failed to reserve a doorbell\n", i); 326 - goto out; 327 - } 328 - 329 - __update_doorbell_desc(clients[i], clients[i]->doorbell_id); 330 - err = __create_doorbell(clients[i]); 312 + err = create_doorbell(clients[i]); 331 313 if (err) { 332 314 pr_err("[%d] Failed to create a doorbell\n", i); 333 315 goto out; ··· 330 348 331 349 out: 332 350 for (i = 0; i < ATTEMPTS; i++) 333 - if (!IS_ERR_OR_NULL(clients[i])) 351 + if (!IS_ERR_OR_NULL(clients[i])) { 352 + destroy_doorbell(clients[i]); 334 353 guc_client_free(clients[i]); 354 + } 335 355 unlock: 336 356 mutex_unlock(&dev_priv->drm.struct_mutex); 337 357 return err; ··· 342 358 int intel_guc_live_selftest(struct drm_i915_private *dev_priv) 343 359 { 344 360 static const struct i915_subtest tests[] = { 345 - SUBTEST(igt_guc_init_doorbell_hw), 361 + SUBTEST(igt_guc_clients), 346 362 SUBTEST(igt_guc_doorbells), 347 363 }; 348 364 349 - if (!i915_modparams.enable_guc_submission) 365 + if (!USES_GUC_SUBMISSION(dev_priv)) 350 366 return 0; 351 367 352 368 return i915_subtests(tests, dev_priv);
+4 -3
drivers/gpu/drm/i915/selftests/intel_hangcheck.c
··· 619 619 620 620 pr_err("Failed to start request %x, at %x\n", 621 621 rq->fence.seqno, hws_seqno(&h, rq)); 622 - intel_engine_dump(rq->engine, &p); 622 + intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); 623 623 624 624 i915_reset(i915, 0); 625 625 i915_gem_set_wedged(i915); ··· 714 714 715 715 pr_err("Failed to start request %x, at %x\n", 716 716 prev->fence.seqno, hws_seqno(&h, prev)); 717 - intel_engine_dump(rq->engine, &p); 717 + intel_engine_dump(prev->engine, &p, 718 + "%s\n", prev->engine->name); 718 719 719 720 i915_gem_request_put(rq); 720 721 i915_gem_request_put(prev); ··· 821 820 822 821 pr_err("Failed to start request %x, at %x\n", 823 822 rq->fence.seqno, hws_seqno(&h, rq)); 824 - intel_engine_dump(rq->engine, &p); 823 + intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); 825 824 826 825 i915_reset(i915, 0); 827 826 i915_gem_set_wedged(i915);
+6 -1
drivers/gpu/drm/i915/selftests/mock_gem_device.c
··· 85 85 86 86 i915_gemfs_fini(i915); 87 87 88 + drm_mode_config_cleanup(&i915->drm); 89 + 88 90 drm_dev_fini(&i915->drm); 89 91 put_device(&i915->drm.pdev->dev); 90 92 } ··· 189 187 190 188 i915->wq = alloc_ordered_workqueue("mock", 0); 191 189 if (!i915->wq) 192 - goto put_device; 190 + goto err_drv; 193 191 194 192 mock_init_contexts(i915); 195 193 ··· 268 266 kmem_cache_destroy(i915->objects); 269 267 err_wq: 270 268 destroy_workqueue(i915->wq); 269 + err_drv: 270 + drm_mode_config_cleanup(&i915->drm); 271 + drm_dev_fini(&i915->drm); 271 272 put_device: 272 273 put_device(&pdev->dev); 273 274 err:
+2 -2
drivers/gpu/drm/i915/selftests/mock_gtt.c
··· 110 110 111 111 ggtt->base.i915 = i915; 112 112 113 - ggtt->mappable_base = 0; 114 - ggtt->mappable_end = 2048 * PAGE_SIZE; 113 + ggtt->gmadr = (struct resource) DEFINE_RES_MEM(0, 2048 * PAGE_SIZE); 114 + ggtt->mappable_end = resource_size(&ggtt->gmadr); 115 115 ggtt->base.total = 4096 * PAGE_SIZE; 116 116 117 117 ggtt->base.clear_range = nop_clear_range;
+3
include/drm/i915_drm.h
··· 36 36 extern bool i915_gpu_busy(void); 37 37 extern bool i915_gpu_turbo_disable(void); 38 38 39 + /* Exported from arch/x86/kernel/early-quirks.c */ 40 + extern struct resource intel_graphics_stolen_res; 41 + 39 42 /* 40 43 * The Bridge device's PCI config space has information about the 41 44 * fb aperture size and the amount of pre-reserved memory.
+1 -2
include/drm/intel-gtt.h
··· 5 5 #define _DRM_INTEL_GTT_H 6 6 7 7 void intel_gtt_get(u64 *gtt_total, 8 - u32 *stolen_size, 9 8 phys_addr_t *mappable_base, 10 - u64 *mappable_end); 9 + resource_size_t *mappable_end); 11 10 12 11 int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, 13 12 struct agp_bridge_data *bridge);
+62
include/uapi/linux/vfio.h
··· 503 503 504 504 #define VFIO_DEVICE_PCI_HOT_RESET _IO(VFIO_TYPE, VFIO_BASE + 13) 505 505 506 + /** 507 + * VFIO_DEVICE_QUERY_GFX_PLANE - _IOW(VFIO_TYPE, VFIO_BASE + 14, 508 + * struct vfio_device_query_gfx_plane) 509 + * 510 + * Set the drm_plane_type and flags, then retrieve the gfx plane info. 511 + * 512 + * flags supported: 513 + * - VFIO_GFX_PLANE_TYPE_PROBE and VFIO_GFX_PLANE_TYPE_DMABUF are set 514 + * to ask if the mdev supports dma-buf. 0 on support, -EINVAL on no 515 + * support for dma-buf. 516 + * - VFIO_GFX_PLANE_TYPE_PROBE and VFIO_GFX_PLANE_TYPE_REGION are set 517 + * to ask if the mdev supports region. 0 on support, -EINVAL on no 518 + * support for region. 519 + * - VFIO_GFX_PLANE_TYPE_DMABUF or VFIO_GFX_PLANE_TYPE_REGION is set 520 + * with each call to query the plane info. 521 + * - Others are invalid and return -EINVAL. 522 + * 523 + * Note: 524 + * 1. Plane could be disabled by guest. In that case, success will be 525 + * returned with zero-initialized drm_format, size, width and height 526 + * fields. 527 + * 2. x_hot/y_hot is set to 0xFFFFFFFF if no hotspot information available 528 + * 529 + * Return: 0 on success, -errno on other failure. 530 + */ 531 + struct vfio_device_gfx_plane_info { 532 + __u32 argsz; 533 + __u32 flags; 534 + #define VFIO_GFX_PLANE_TYPE_PROBE (1 << 0) 535 + #define VFIO_GFX_PLANE_TYPE_DMABUF (1 << 1) 536 + #define VFIO_GFX_PLANE_TYPE_REGION (1 << 2) 537 + /* in */ 538 + __u32 drm_plane_type; /* type of plane: DRM_PLANE_TYPE_* */ 539 + /* out */ 540 + __u32 drm_format; /* drm format of plane */ 541 + __u64 drm_format_mod; /* tiled mode */ 542 + __u32 width; /* width of plane */ 543 + __u32 height; /* height of plane */ 544 + __u32 stride; /* stride of plane */ 545 + __u32 size; /* size of plane in bytes, align on page*/ 546 + __u32 x_pos; /* horizontal position of cursor plane */ 547 + __u32 y_pos; /* vertical position of cursor plane*/ 548 + __u32 x_hot; /* horizontal position of cursor hotspot */ 549 + __u32 y_hot; /* vertical position of cursor hotspot */ 550 + union { 551 + __u32 region_index; /* region index */ 552 + __u32 dmabuf_id; /* dma-buf id */ 553 + }; 554 + }; 555 + 556 + #define VFIO_DEVICE_QUERY_GFX_PLANE _IO(VFIO_TYPE, VFIO_BASE + 14) 557 + 558 + /** 559 + * VFIO_DEVICE_GET_GFX_DMABUF - _IOW(VFIO_TYPE, VFIO_BASE + 15, __u32) 560 + * 561 + * Return a new dma-buf file descriptor for an exposed guest framebuffer 562 + * described by the provided dmabuf_id. The dmabuf_id is returned from VFIO_ 563 + * DEVICE_QUERY_GFX_PLANE as a token of the exposed guest framebuffer. 564 + */ 565 + 566 + #define VFIO_DEVICE_GET_GFX_DMABUF _IO(VFIO_TYPE, VFIO_BASE + 15) 567 + 506 568 /* -------- API for Type1 VFIO IOMMU -------- */ 507 569 508 570 /**