Subversion Repositories Kolibri OS

Rev

Rev 6320 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6320 Rev 6937
Line 21... Line 21...
21
 * IN THE SOFTWARE.
21
 * IN THE SOFTWARE.
22
 *
22
 *
23
 */
23
 */
24
#include 
24
#include 
25
#include 
25
#include 
26
#include "intel_drv.h"
26
#include "i915_drv.h"
27
#include "intel_guc.h"
27
#include "intel_guc.h"
Line 28... Line 28...
28
 
28
 
29
/**
29
/**
30
 * DOC: GuC Client
30
 * DOC: GuC-based command submission
31
 *
31
 *
32
 * i915_guc_client:
32
 * i915_guc_client:
33
 * We use the term client to avoid confusion with contexts. A i915_guc_client is
33
 * We use the term client to avoid confusion with contexts. A i915_guc_client is
34
 * equivalent to GuC object guc_context_desc. This context descriptor is
34
 * equivalent to GuC object guc_context_desc. This context descriptor is
Line 84... Line 84...
84
 
84
 
85
	if (WARN_ON(len < 1 || len > 15))
85
	if (WARN_ON(len < 1 || len > 15))
Line 86... Line 86...
86
		return -EINVAL;
86
		return -EINVAL;
87
 
-
 
Line 88... Line 87...
88
	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
87
 
89
	spin_lock(&dev_priv->guc.host2guc_lock);
88
	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
Line 90... Line 89...
90
 
89
 
Line 117... Line 116...
117
		dev_priv->guc.action_fail += 1;
116
		dev_priv->guc.action_fail += 1;
118
		dev_priv->guc.action_err = ret;
117
		dev_priv->guc.action_err = ret;
119
	}
118
	}
120
	dev_priv->guc.action_status = status;
119
	dev_priv->guc.action_status = status;
Line 121... Line -...
121
 
-
 
122
	spin_unlock(&dev_priv->guc.host2guc_lock);
120
 
Line 123... Line 121...
123
	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
121
	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
124
 
122
 
Line 159... Line 157...
159
	u32 data[2];
157
	u32 data[2];
Line 160... Line 158...
160
 
158
 
161
	data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE;
159
	data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE;
162
	/* WaRsDisableCoarsePowerGating:skl,bxt */
160
	/* WaRsDisableCoarsePowerGating:skl,bxt */
163
	if (!intel_enable_rc6(dev_priv->dev) ||
161
	if (!intel_enable_rc6(dev_priv->dev) ||
164
	    (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) ||
162
	    IS_BXT_REVID(dev, 0, BXT_REVID_A1) ||
165
	    (IS_SKL_GT3(dev) && (INTEL_REVID(dev) <= SKL_REVID_E0)) ||
163
	    (IS_SKL_GT3(dev) && IS_SKL_REVID(dev, 0, SKL_REVID_E0)) ||
166
	    (IS_SKL_GT4(dev) && (INTEL_REVID(dev) <= SKL_REVID_E0)))
164
	    (IS_SKL_GT4(dev) && IS_SKL_REVID(dev, 0, SKL_REVID_E0)))
167
		data[1] = 0;
165
		data[1] = 0;
168
	else
166
	else
169
		/* bit 0 and 1 are for Render and Media domain separately */
167
		/* bit 0 and 1 are for Render and Media domain separately */
Line 256... Line 254...
256
				 struct i915_guc_client *client)
254
				 struct i915_guc_client *client)
257
{
255
{
258
	struct drm_i915_private *dev_priv = guc_to_i915(guc);
256
	struct drm_i915_private *dev_priv = guc_to_i915(guc);
259
	struct guc_doorbell_info *doorbell;
257
	struct guc_doorbell_info *doorbell;
260
	void *base;
258
	void *base;
261
	int drbreg = GEN8_DRBREGL(client->doorbell_id);
259
	i915_reg_t drbreg = GEN8_DRBREGL(client->doorbell_id);
262
	int value;
260
	int value;
Line 263... Line 261...
263
 
261
 
264
	base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
262
	base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
Line 290... Line 288...
290
static uint32_t select_doorbell_cacheline(struct intel_guc *guc)
288
static uint32_t select_doorbell_cacheline(struct intel_guc *guc)
291
{
289
{
292
	const uint32_t cacheline_size = cache_line_size();
290
	const uint32_t cacheline_size = cache_line_size();
293
	uint32_t offset;
291
	uint32_t offset;
Line 294... Line -...
294
 
-
 
295
	spin_lock(&guc->host2guc_lock);
-
 
296
 
292
 
297
	/* Doorbell uses a single cache line within a page */
293
	/* Doorbell uses a single cache line within a page */
Line 298... Line 294...
298
	offset = offset_in_page(guc->db_cacheline);
294
	offset = offset_in_page(guc->db_cacheline);
299
 
295
 
Line 300... Line -...
300
	/* Moving to next cache line to reduce contention */
-
 
301
	guc->db_cacheline += cacheline_size;
-
 
302
 
296
	/* Moving to next cache line to reduce contention */
303
	spin_unlock(&guc->host2guc_lock);
297
	guc->db_cacheline += cacheline_size;
Line 304... Line 298...
304
 
298
 
305
	DRM_DEBUG_DRIVER("selected doorbell cacheline 0x%x, next 0x%x, linesize %u\n",
299
	DRM_DEBUG_DRIVER("selected doorbell cacheline 0x%x, next 0x%x, linesize %u\n",
Line 320... Line 314...
320
	const uint16_t half = GUC_MAX_DOORBELLS / 2;
314
	const uint16_t half = GUC_MAX_DOORBELLS / 2;
321
	const uint16_t start = hi_pri ? half : 0;
315
	const uint16_t start = hi_pri ? half : 0;
322
	const uint16_t end = start + half;
316
	const uint16_t end = start + half;
323
	uint16_t id;
317
	uint16_t id;
Line 324... Line -...
324
 
-
 
325
	spin_lock(&guc->host2guc_lock);
318
 
326
	id = find_next_zero_bit(guc->doorbell_bitmap, end, start);
319
	id = find_next_zero_bit(guc->doorbell_bitmap, end, start);
327
	if (id == end)
320
	if (id == end)
328
		id = GUC_INVALID_DOORBELL_ID;
321
		id = GUC_INVALID_DOORBELL_ID;
329
	else
322
	else
330
		bitmap_set(guc->doorbell_bitmap, id, 1);
-
 
Line 331... Line 323...
331
	spin_unlock(&guc->host2guc_lock);
323
		bitmap_set(guc->doorbell_bitmap, id, 1);
332
 
324
 
Line 333... Line 325...
333
	DRM_DEBUG_DRIVER("assigned %s priority doorbell id 0x%x\n",
325
	DRM_DEBUG_DRIVER("assigned %s priority doorbell id 0x%x\n",
334
			hi_pri ? "high" : "normal", id);
326
			hi_pri ? "high" : "normal", id);
Line 335... Line 327...
335
 
327
 
336
	return id;
328
	return id;
337
}
-
 
338
 
329
}
339
static void release_doorbell(struct intel_guc *guc, uint16_t id)
-
 
340
{
330
 
Line 341... Line 331...
341
	spin_lock(&guc->host2guc_lock);
331
static void release_doorbell(struct intel_guc *guc, uint16_t id)
342
	bitmap_clear(guc->doorbell_bitmap, id, 1);
332
{
343
	spin_unlock(&guc->host2guc_lock);
333
	bitmap_clear(guc->doorbell_bitmap, id, 1);
Line 485... Line 475...
485
static int guc_get_workqueue_space(struct i915_guc_client *gc, u32 *offset)
475
static int guc_get_workqueue_space(struct i915_guc_client *gc, u32 *offset)
486
{
476
{
487
	struct guc_process_desc *desc;
477
	struct guc_process_desc *desc;
488
	void *base;
478
	void *base;
489
	u32 size = sizeof(struct guc_wq_item);
479
	u32 size = sizeof(struct guc_wq_item);
490
	int ret = 0, timeout_counter = 200;
480
	int ret = -ETIMEDOUT, timeout_counter = 200;
Line 491... Line 481...
491
 
481
 
492
	base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0));
482
	base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0));
Line 493... Line 483...
493
	desc = base + gc->proc_desc_offset;
483
	desc = base + gc->proc_desc_offset;
494
 
484
 
495
	while (timeout_counter-- > 0) {
-
 
496
		ret = wait_for_atomic(CIRC_SPACE(gc->wq_tail, desc->head,
-
 
497
				gc->wq_size) >= size, 1);
-
 
498
 
485
	while (timeout_counter-- > 0) {
Line 499... Line 486...
499
		if (!ret) {
486
		if (CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size) >= size) {
500
			*offset = gc->wq_tail;
487
			*offset = gc->wq_tail;
501
 
488
 
Line 502... Line 489...
502
			/* advance the tail for next workqueue item */
489
			/* advance the tail for next workqueue item */
503
			gc->wq_tail += size;
490
			gc->wq_tail += size;
-
 
491
			gc->wq_tail &= gc->wq_size - 1;
504
			gc->wq_tail &= gc->wq_size - 1;
492
 
-
 
493
			/* this will break the loop */
-
 
494
			timeout_counter = 0;
-
 
495
			ret = 0;
505
 
496
		}
Line 506... Line 497...
506
			/* this will break the loop */
497
 
Line 507... Line 498...
507
			timeout_counter = 0;
498
		if (timeout_counter)
Line 575... Line 566...
575
 
566
 
576
	BUG_ON(!ctx_obj);
567
	BUG_ON(!ctx_obj);
577
	WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
568
	WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
Line 578... Line 569...
578
	WARN_ON(!i915_gem_obj_is_pinned(rb_obj));
569
	WARN_ON(!i915_gem_obj_is_pinned(rb_obj));
579
 
570
 
Line 580... Line 571...
580
	page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
571
	page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
Line 581... Line 572...
581
	reg_state = kmap_atomic(page);
572
	reg_state = kmap_atomic(page);
582
 
573
 
Line 583... Line 574...
583
	reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj);
574
	reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj);
584
 
575
 
585
	kunmap_atomic(reg_state);
576
	kunmap_atomic(reg_state);
586
}
-
 
587
 
577
}
588
/**
578
 
589
 * i915_guc_submit() - Submit commands through GuC
579
/**
590
 * @client:	the guc client where commands will go through
580
 * i915_guc_submit() - Submit commands through GuC
591
 * @ctx:	LRC where commands come from
581
 * @client:	the guc client where commands will go through
592
 * @ring:	HW engine that will excute the commands
582
 * @rq:		request associated with the commands
593
 *
583
 *
594
 * Return:	0 if succeed
584
 * Return:	0 if succeed
595
 */
585
 */
596
int i915_guc_submit(struct i915_guc_client *client,
-
 
597
		    struct drm_i915_gem_request *rq)
586
int i915_guc_submit(struct i915_guc_client *client,
Line 598... Line 587...
598
{
587
		    struct drm_i915_gem_request *rq)
599
	struct intel_guc *guc = client->guc;
588
{
600
	enum intel_ring_id ring_id = rq->ring->id;
589
	struct intel_guc *guc = client->guc;
Line 601... Line -...
601
	unsigned long flags;
-
 
602
	int q_ret, b_ret;
-
 
603
 
590
	enum intel_ring_id ring_id = rq->ring->id;
604
	/* Need this because of the deferred pin ctx and ring */
591
	int q_ret, b_ret;
605
	/* Shall we move this right after ring is pinned? */
592
 
Line 606... Line 593...
606
	lr_context_update(rq);
593
	/* Need this because of the deferred pin ctx and ring */
Line 619... Line 606...
619
		client->b_fail += 1;
606
		client->b_fail += 1;
620
		client->retcode = q_ret = b_ret;
607
		client->retcode = q_ret = b_ret;
621
	} else {
608
	} else {
622
		client->retcode = 0;
609
		client->retcode = 0;
623
	}
610
	}
624
	spin_unlock_irqrestore(&client->wq_lock, flags);
-
 
625
 
-
 
626
	spin_lock(&guc->host2guc_lock);
-
 
627
	guc->submissions[ring_id] += 1;
611
	guc->submissions[ring_id] += 1;
628
	guc->last_seqno[ring_id] = rq->seqno;
612
	guc->last_seqno[ring_id] = rq->seqno;
629
	spin_unlock(&guc->host2guc_lock);
-
 
Line 630... Line 613...
630
 
613
 
631
	return q_ret;
614
	return q_ret;
Line 632... Line 615...
632
}
615
}
Line 729... Line 712...
729
 * @dev:	drm device
712
 * @dev:	drm device
730
 * @priority:	four levels priority _CRITICAL, _HIGH, _NORMAL and _LOW
713
 * @priority:	four levels priority _CRITICAL, _HIGH, _NORMAL and _LOW
731
 * 		The kernel client to replace ExecList submission is created with
714
 * 		The kernel client to replace ExecList submission is created with
732
 * 		NORMAL priority. Priority of a client for scheduler can be HIGH,
715
 * 		NORMAL priority. Priority of a client for scheduler can be HIGH,
733
 * 		while a preemption context can use CRITICAL.
716
 * 		while a preemption context can use CRITICAL.
734
 * @ctx		the context to own the client (we use the default render context)
717
 * @ctx:	the context that owns the client (we use the default render
-
 
718
 * 		context)
735
 *
719
 *
736
 * Return:	An i915_guc_client object if success.
720
 * Return:	An i915_guc_client object if success.
737
 */
721
 */
738
static struct i915_guc_client *guc_client_alloc(struct drm_device *dev,
722
static struct i915_guc_client *guc_client_alloc(struct drm_device *dev,
739
						uint32_t priority,
723
						uint32_t priority,
Line 766... Line 750...
766
		goto err;
750
		goto err;
Line 767... Line 751...
767
 
751
 
768
	client->client_obj = obj;
752
	client->client_obj = obj;
769
	client->wq_offset = GUC_DB_SIZE;
753
	client->wq_offset = GUC_DB_SIZE;
770
	client->wq_size = GUC_WQ_SIZE;
-
 
Line 771... Line 754...
771
	spin_lock_init(&client->wq_lock);
754
	client->wq_size = GUC_WQ_SIZE;
Line 772... Line 755...
772
 
755
 
773
	client->doorbell_offset = select_doorbell_cacheline(guc);
756
	client->doorbell_offset = select_doorbell_cacheline(guc);
Line 869... Line 852...
869
 
852
 
870
	guc->ctx_pool_obj = gem_allocate_guc_obj(dev_priv->dev, gemsize);
853
	guc->ctx_pool_obj = gem_allocate_guc_obj(dev_priv->dev, gemsize);
871
	if (!guc->ctx_pool_obj)
854
	if (!guc->ctx_pool_obj)
Line 872... Line -...
872
		return -ENOMEM;
-
 
873
 
-
 
874
	spin_lock_init(&dev_priv->guc.host2guc_lock);
855
		return -ENOMEM;
Line 875... Line 856...
875
 
856
 
Line 876... Line 857...
876
	ida_init(&guc->ctx_ids);
857
	ida_init(&guc->ctx_ids);