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

drm/i915/selftests: ring all doorbells in igt_guc_doorbells

We currently verify that all doorbells can be registered with GuC and
HW but don't check that all works as expected after a db ring.

Do a nop ring of all doorbells to make sure we haven't misprogrammed
any WQ or stage descriptor data. This will also help validating
upcoming changes in the db programming flow.

Cc: Michel Thierry <michel.thierry@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Reviewed-by: Michel Thierry <michel.thierry@intel.com>
Acked-by: Katarzyna Dec <katarzyna.dec@intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20180827223614.22789-1-daniele.ceraolospurio@intel.com

authored by

Daniele Ceraolo Spurio and committed by
Chris Wilson
5382bed3 65df9c79

+59 -9
+1
drivers/gpu/drm/i915/intel_guc_fwif.h
··· 49 49 #define WQ_TYPE_BATCH_BUF (0x1 << WQ_TYPE_SHIFT) 50 50 #define WQ_TYPE_PSEUDO (0x2 << WQ_TYPE_SHIFT) 51 51 #define WQ_TYPE_INORDER (0x3 << WQ_TYPE_SHIFT) 52 + #define WQ_TYPE_NOOP (0x4 << WQ_TYPE_SHIFT) 52 53 #define WQ_TARGET_SHIFT 10 53 54 #define WQ_LEN_SHIFT 16 54 55 #define WQ_NO_WCFLUSH_WAIT (1 << 27)
+16 -9
drivers/gpu/drm/i915/intel_guc_submission.c
··· 456 456 */ 457 457 BUILD_BUG_ON(wqi_size != 16); 458 458 459 + /* We expect the WQ to be active if we're appending items to it */ 460 + GEM_BUG_ON(desc->wq_status != WQ_STATUS_ACTIVE); 461 + 459 462 /* Free space is guaranteed. */ 460 463 wq_off = READ_ONCE(desc->tail); 461 464 GEM_BUG_ON(CIRC_SPACE(wq_off, READ_ONCE(desc->head), ··· 468 465 /* WQ starts from the page after doorbell / process_desc */ 469 466 wqi = client->vaddr + wq_off + GUC_DB_SIZE; 470 467 471 - /* Now fill in the 4-word work queue item */ 472 - wqi->header = WQ_TYPE_INORDER | 473 - (wqi_len << WQ_LEN_SHIFT) | 474 - (target_engine << WQ_TARGET_SHIFT) | 475 - WQ_NO_WCFLUSH_WAIT; 476 - wqi->context_desc = context_desc; 477 - wqi->submit_element_info = ring_tail << WQ_RING_TAIL_SHIFT; 478 - GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX); 479 - wqi->fence_id = fence_id; 468 + if (I915_SELFTEST_ONLY(client->use_nop_wqi)) { 469 + wqi->header = WQ_TYPE_NOOP | (wqi_len << WQ_LEN_SHIFT); 470 + } else { 471 + /* Now fill in the 4-word work queue item */ 472 + wqi->header = WQ_TYPE_INORDER | 473 + (wqi_len << WQ_LEN_SHIFT) | 474 + (target_engine << WQ_TARGET_SHIFT) | 475 + WQ_NO_WCFLUSH_WAIT; 476 + wqi->context_desc = context_desc; 477 + wqi->submit_element_info = ring_tail << WQ_RING_TAIL_SHIFT; 478 + GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX); 479 + wqi->fence_id = fence_id; 480 + } 480 481 481 482 /* Make the update visible to GuC */ 482 483 WRITE_ONCE(desc->tail, (wq_off + wqi_size) & (GUC_WQ_SIZE - 1));
+4
drivers/gpu/drm/i915/intel_guc_submission.h
··· 28 28 #include <linux/spinlock.h> 29 29 30 30 #include "i915_gem.h" 31 + #include "i915_selftest.h" 31 32 32 33 struct drm_i915_private; 33 34 ··· 72 71 spinlock_t wq_lock; 73 72 /* Per-engine counts of GuC submissions */ 74 73 u64 submissions[I915_NUM_ENGINES]; 74 + 75 + /* For testing purposes, use nop WQ items instead of real ones */ 76 + I915_SELFTEST_DECLARE(bool use_nop_wqi); 75 77 }; 76 78 77 79 int intel_guc_submission_init(struct intel_guc *guc);
+38
drivers/gpu/drm/i915/selftests/intel_guc.c
··· 65 65 return 0; 66 66 } 67 67 68 + static int ring_doorbell_nop(struct intel_guc_client *client) 69 + { 70 + struct guc_process_desc *desc = __get_process_desc(client); 71 + int err; 72 + 73 + client->use_nop_wqi = true; 74 + 75 + spin_lock_irq(&client->wq_lock); 76 + 77 + guc_wq_item_append(client, 0, 0, 0, 0); 78 + guc_ring_doorbell(client); 79 + 80 + spin_unlock_irq(&client->wq_lock); 81 + 82 + client->use_nop_wqi = false; 83 + 84 + /* if there are no issues GuC will update the WQ head and keep the 85 + * WQ in active status 86 + */ 87 + err = wait_for(READ_ONCE(desc->head) == READ_ONCE(desc->tail), 10); 88 + if (err) { 89 + pr_err("doorbell %u ring failed!\n", client->doorbell_id); 90 + return -EIO; 91 + } 92 + 93 + if (desc->wq_status != WQ_STATUS_ACTIVE) { 94 + pr_err("doorbell %u ring put WQ in bad state (%u)!\n", 95 + client->doorbell_id, desc->wq_status); 96 + return -EIO; 97 + } 98 + 99 + return 0; 100 + } 101 + 68 102 /* 69 103 * Basic client sanity check, handy to validate create_clients. 70 104 */ ··· 364 330 } 365 331 366 332 err = check_all_doorbells(guc); 333 + if (err) 334 + goto out; 335 + 336 + err = ring_doorbell_nop(clients[i]); 367 337 if (err) 368 338 goto out; 369 339 }