All of lore.kernel.org
 help / color / mirror / Atom feed
* [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
@ 2016-12-23  7:08 Xiangliang Yu
       [not found] ` <1482476904-21674-1-git-send-email-Xiangliang.Yu-5C7GfCeVMHo@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Xiangliang Yu @ 2016-12-23  7:08 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Xiangliang Yu, Monk Liu

KIQ is queue-memory based initialization method: setup KIQ queue
firstly, then send command to KIQ to setup other queues, without
accessing registers.

For virtualization, need KIQ to access virtual function registers
when running on guest mode.

changes in v2:
1. use amdgpu_bo_create/free_kernel to allocate OB.

Signed-off-by: Monk Liu <Monk.Liu@amd.com>
Signed-off-by: Xiangliang Yu <Xiangliang.Yu@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h   |  13 +
 drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 607 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/amd/amdgpu/vid.h      |   2 +
 3 files changed, 620 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 9ea5bf0..c392882 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -186,6 +186,11 @@ enum amdgpu_thermal_irq {
 	AMDGPU_THERMAL_IRQ_LAST
 };
 
+enum amdgpu_kiq_irq {
+	AMDGPU_CP_KIQ_IRQ_DRIVER0 = 0,
+	AMDGPU_CP_KIQ_IRQ_LAST
+};
+
 int amdgpu_set_clockgating_state(struct amdgpu_device *adev,
 				  enum amd_ip_block_type block_type,
 				  enum amd_clockgating_state state);
@@ -778,6 +783,13 @@ struct amdgpu_mec {
 	u32 num_queue;
 };
 
+struct amdgpu_kiq {
+	u64			eop_gpu_addr;
+	struct amdgpu_bo	*eop_obj;
+	struct amdgpu_ring	ring;
+	struct amdgpu_irq_src	irq;
+};
+
 /*
  * GPU scratch registers structures, functions & helpers
  */
@@ -853,6 +865,7 @@ struct amdgpu_gfx {
 	struct amdgpu_gca_config	config;
 	struct amdgpu_rlc		rlc;
 	struct amdgpu_mec		mec;
+	struct amdgpu_kiq		kiq;
 	struct amdgpu_scratch		scratch;
 	const struct firmware		*me_fw;	/* ME firmware */
 	uint32_t			me_fw_version;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index c3e6bfc..a233eeb 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -1367,6 +1367,42 @@ static void gfx_v8_0_mec_fini(struct amdgpu_device *adev)
 	}
 }
 
+static int gfx_v8_0_kiq_init_ring(struct amdgpu_device *adev,
+				  struct amdgpu_ring *ring,
+				  struct amdgpu_irq_src *irq)
+{
+	int r = 0;
+
+	ring->adev = NULL;
+	ring->ring_obj = NULL;
+	ring->use_doorbell = true;
+	ring->doorbell_index = AMDGPU_DOORBELL_KIQ;
+	if (adev->gfx.mec2_fw) {
+		ring->me = 2;
+		ring->pipe = 0;
+	} else {
+		ring->me = 1;
+		ring->pipe = 1;
+	}
+
+	irq->data = ring;
+	ring->queue = 0;
+	sprintf(ring->name, "kiq %d.%d.%d", ring->me, ring->pipe, ring->queue);
+	r = amdgpu_ring_init(adev, ring, 1024,
+			     irq, AMDGPU_CP_KIQ_IRQ_DRIVER0);
+	if (r)
+		dev_warn(adev->dev, "(%d) failed to init kiq ring\n", r);
+
+	return r;
+}
+
+static void gfx_v8_0_kiq_free_ring(struct amdgpu_ring *ring,
+				   struct amdgpu_irq_src *irq)
+{
+	amdgpu_ring_fini(ring);
+	irq->data = NULL;
+}
+
 #define MEC_HPD_SIZE 2048
 
 static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
@@ -1421,6 +1457,35 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
 	return 0;
 }
 
+static void gfx_v8_0_kiq_fini(struct amdgpu_device *adev)
+{
+	struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+
+	amdgpu_bo_free_kernel(&kiq->eop_obj, &kiq->eop_gpu_addr, NULL);
+	kiq->eop_obj = NULL;
+}
+
+static int gfx_v8_0_kiq_init(struct amdgpu_device *adev)
+{
+	int r;
+	u32 *hpd;
+	struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+
+	r = amdgpu_bo_create_kernel(adev, MEC_HPD_SIZE, PAGE_SIZE,
+				    AMDGPU_GEM_DOMAIN_GTT, &kiq->eop_obj,
+				    &kiq->eop_gpu_addr, (void **)&hpd);
+	if (r) {
+		dev_warn(adev->dev, "failed to create KIQ bo (%d).\n", r);
+		return r;
+	}
+
+	memset(hpd, 0, MEC_HPD_SIZE);
+
+	amdgpu_bo_kunmap(kiq->eop_obj);
+
+	return 0;
+}
+
 static const u32 vgpr_init_compute_shader[] =
 {
 	0x7e000209, 0x7e020208,
@@ -1997,8 +2062,14 @@ static int gfx_v8_0_sw_init(void *handle)
 {
 	int i, r;
 	struct amdgpu_ring *ring;
+	struct amdgpu_kiq *kiq;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+	/* KIQ event */
+	r = amdgpu_irq_add_id(adev, 178, &adev->gfx.kiq.irq);
+	if (r)
+		return r;
+
 	/* EOP Event */
 	r = amdgpu_irq_add_id(adev, 181, &adev->gfx.eop_irq);
 	if (r)
@@ -2036,6 +2107,17 @@ static int gfx_v8_0_sw_init(void *handle)
 		return r;
 	}
 
+	r = gfx_v8_0_kiq_init(adev);
+	if (r) {
+		DRM_ERROR("Failed to init KIQ BOs!\n");
+		return r;
+	}
+
+	kiq = &adev->gfx.kiq;
+	r = gfx_v8_0_kiq_init_ring(adev, &kiq->ring, &kiq->irq);
+	if (r)
+		return r;
+
 	/* set up the gfx ring */
 	for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
 		ring = &adev->gfx.gfx_ring[i];
@@ -2119,7 +2201,9 @@ static int gfx_v8_0_sw_fini(void *handle)
 		amdgpu_ring_fini(&adev->gfx.gfx_ring[i]);
 	for (i = 0; i < adev->gfx.num_compute_rings; i++)
 		amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
+	gfx_v8_0_kiq_free_ring(&adev->gfx.kiq.ring, &adev->gfx.kiq.irq);
 
+	gfx_v8_0_kiq_fini(adev);
 	gfx_v8_0_mec_fini(adev);
 	gfx_v8_0_rlc_fini(adev);
 	gfx_v8_0_free_microcode(adev);
@@ -4506,6 +4590,393 @@ static void gfx_v8_0_cp_compute_fini(struct amdgpu_device *adev)
 	}
 }
 
+/* KIQ functions */
+static void gfx_v8_0_kiq_setting(struct amdgpu_ring *ring)
+{
+	uint32_t tmp;
+	struct amdgpu_device *adev = ring->adev;
+
+	/* tell RLC which is KIQ queue */
+	tmp = RREG32(mmRLC_CP_SCHEDULERS);
+	tmp &= 0xffffff00;
+	tmp |= (ring->me << 5) | (ring->pipe << 3) | (ring->queue);
+	WREG32(mmRLC_CP_SCHEDULERS, tmp);
+	tmp |= 0x80;
+	WREG32(mmRLC_CP_SCHEDULERS, tmp);
+}
+
+static void gfx_v8_0_kiq_enable(struct amdgpu_ring *ring)
+{
+	amdgpu_ring_alloc(ring, 8);
+	/* set resources */
+	amdgpu_ring_write(ring, PACKET3(PACKET3_SET_RESOURCES, 6));
+	amdgpu_ring_write(ring, 0);	/* vmid_mask:0 queue_type:0 (KIQ) */
+	amdgpu_ring_write(ring, 0x000000FF);	/* queue mask lo */
+	amdgpu_ring_write(ring, 0);	/* queue mask hi */
+	amdgpu_ring_write(ring, 0);	/* gws mask lo */
+	amdgpu_ring_write(ring, 0);	/* gws mask hi */
+	amdgpu_ring_write(ring, 0);	/* oac mask */
+	amdgpu_ring_write(ring, 0);	/* gds heap base:0, gds heap size:0 */
+	amdgpu_ring_commit(ring);
+	udelay(50);
+}
+
+static void gfx_v8_0_map_queue_enable(struct amdgpu_ring *kiq_ring,
+				   struct amdgpu_ring *ring)
+{
+	struct amdgpu_device *adev = kiq_ring->adev;
+	uint64_t mqd_addr, wptr_addr;
+
+	mqd_addr = amdgpu_bo_gpu_offset(ring->mqd_obj);
+	wptr_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
+	amdgpu_ring_alloc(kiq_ring, 8);
+
+	amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_MAP_QUEUES, 5));
+	/* Q_sel:0, vmid:0, vidmem: 1, engine:0, num_Q:1*/
+	amdgpu_ring_write(kiq_ring, 0x21010000);
+	amdgpu_ring_write(kiq_ring, (ring->doorbell_index << 2) |
+			(ring->queue << 26) |
+			(ring->pipe << 29) |
+			((ring->me == 1 ? 0 : 1) << 31)); /* doorbell */
+	amdgpu_ring_write(kiq_ring, lower_32_bits(mqd_addr));
+	amdgpu_ring_write(kiq_ring, upper_32_bits(mqd_addr));
+	amdgpu_ring_write(kiq_ring, lower_32_bits(wptr_addr));
+	amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
+	amdgpu_ring_commit(kiq_ring);
+	udelay(50);
+}
+
+static int gfx_v8_0_mqd_init(struct amdgpu_device *adev,
+			     struct vi_mqd *mqd,
+			     uint64_t mqd_gpu_addr,
+			     uint64_t eop_gpu_addr,
+			     struct amdgpu_ring *ring)
+{
+	uint64_t hqd_gpu_addr, wb_gpu_addr, eop_base_addr;
+	uint32_t tmp;
+
+	mqd->header = 0xC0310800;
+	mqd->compute_pipelinestat_enable = 0x00000001;
+	mqd->compute_static_thread_mgmt_se0 = 0xffffffff;
+	mqd->compute_static_thread_mgmt_se1 = 0xffffffff;
+	mqd->compute_static_thread_mgmt_se2 = 0xffffffff;
+	mqd->compute_static_thread_mgmt_se3 = 0xffffffff;
+	mqd->compute_misc_reserved = 0x00000003;
+
+	eop_base_addr = eop_gpu_addr >> 8;
+	mqd->cp_hqd_eop_base_addr_lo = eop_base_addr;
+	mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr);
+
+	/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
+	tmp = RREG32(mmCP_HQD_EOP_CONTROL);
+	tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
+			(order_base_2(MEC_HPD_SIZE / 4) - 1));
+
+	mqd->cp_hqd_eop_control = tmp;
+
+	/* enable doorbell? */
+	tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
+
+	if (ring->use_doorbell)
+		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+					 DOORBELL_EN, 1);
+	else
+		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+					 DOORBELL_EN, 0);
+
+	mqd->cp_hqd_pq_doorbell_control = tmp;
+
+	/* disable the queue if it's active */
+	mqd->cp_hqd_dequeue_request = 0;
+	mqd->cp_hqd_pq_rptr = 0;
+	mqd->cp_hqd_pq_wptr = 0;
+
+	/* set the pointer to the MQD */
+	mqd->cp_mqd_base_addr_lo = mqd_gpu_addr & 0xfffffffc;
+	mqd->cp_mqd_base_addr_hi = upper_32_bits(mqd_gpu_addr);
+
+	/* set MQD vmid to 0 */
+	tmp = RREG32(mmCP_MQD_CONTROL);
+	tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0);
+	mqd->cp_mqd_control = tmp;
+
+	/* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
+	hqd_gpu_addr = ring->gpu_addr >> 8;
+	mqd->cp_hqd_pq_base_lo = hqd_gpu_addr;
+	mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr);
+
+	/* set up the HQD, this is similar to CP_RB0_CNTL */
+	tmp = RREG32(mmCP_HQD_PQ_CONTROL);
+	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE,
+			    (order_base_2(ring->ring_size / 4) - 1));
+	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE,
+			((order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1) << 8));
+#ifdef __BIG_ENDIAN
+	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1);
+#endif
+	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0);
+	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ROQ_PQ_IB_FLIP, 0);
+	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1);
+	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1);
+	mqd->cp_hqd_pq_control = tmp;
+
+	/* set the wb address whether it's enabled or not */
+	wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
+	mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc;
+	mqd->cp_hqd_pq_rptr_report_addr_hi =
+		upper_32_bits(wb_gpu_addr) & 0xffff;
+
+	/* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
+	wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
+	mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc;
+	mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff;
+
+	tmp = 0;
+	/* enable the doorbell if requested */
+	if (ring->use_doorbell) {
+		tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
+		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+				DOORBELL_OFFSET, ring->doorbell_index);
+
+		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+					 DOORBELL_EN, 1);
+		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+					 DOORBELL_SOURCE, 0);
+		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+					 DOORBELL_HIT, 0);
+	}
+
+	mqd->cp_hqd_pq_doorbell_control = tmp;
+
+	/* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
+	ring->wptr = 0;
+	mqd->cp_hqd_pq_wptr = ring->wptr;
+	mqd->cp_hqd_pq_rptr = RREG32(mmCP_HQD_PQ_RPTR);
+
+	/* set the vmid for the queue */
+	mqd->cp_hqd_vmid = 0;
+
+	tmp = RREG32(mmCP_HQD_PERSISTENT_STATE);
+	tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53);
+	mqd->cp_hqd_persistent_state = tmp;
+
+	/* activate the queue */
+	mqd->cp_hqd_active = 1;
+
+	return 0;
+}
+
+static int gfx_v8_0_kiq_init_register(struct amdgpu_device *adev,
+				      struct vi_mqd *mqd,
+				      struct amdgpu_ring *ring)
+{
+	uint32_t tmp;
+	int j;
+
+	/* disable wptr polling */
+	tmp = RREG32(mmCP_PQ_WPTR_POLL_CNTL);
+	tmp = REG_SET_FIELD(tmp, CP_PQ_WPTR_POLL_CNTL, EN, 0);
+	WREG32(mmCP_PQ_WPTR_POLL_CNTL, tmp);
+
+	WREG32(mmCP_HQD_EOP_BASE_ADDR, mqd->cp_hqd_eop_base_addr_lo);
+	WREG32(mmCP_HQD_EOP_BASE_ADDR_HI, mqd->cp_hqd_eop_base_addr_hi);
+
+	/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
+	WREG32(mmCP_HQD_EOP_CONTROL, mqd->cp_hqd_eop_control);
+
+	/* enable doorbell? */
+	WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control);
+
+	/* disable the queue if it's active */
+	if (RREG32(mmCP_HQD_ACTIVE) & 1) {
+		WREG32(mmCP_HQD_DEQUEUE_REQUEST, 1);
+		for (j = 0; j < adev->usec_timeout; j++) {
+			if (!(RREG32(mmCP_HQD_ACTIVE) & 1))
+				break;
+			udelay(1);
+		}
+		WREG32(mmCP_HQD_DEQUEUE_REQUEST, mqd->cp_hqd_dequeue_request);
+		WREG32(mmCP_HQD_PQ_RPTR, mqd->cp_hqd_pq_rptr);
+		WREG32(mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);
+	}
+
+	/* set the pointer to the MQD */
+	WREG32(mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr_lo);
+	WREG32(mmCP_MQD_BASE_ADDR_HI, mqd->cp_mqd_base_addr_hi);
+
+	/* set MQD vmid to 0 */
+	WREG32(mmCP_MQD_CONTROL, mqd->cp_mqd_control);
+
+	/* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
+	WREG32(mmCP_HQD_PQ_BASE, mqd->cp_hqd_pq_base_lo);
+	WREG32(mmCP_HQD_PQ_BASE_HI, mqd->cp_hqd_pq_base_hi);
+
+	/* set up the HQD, this is similar to CP_RB0_CNTL */
+	WREG32(mmCP_HQD_PQ_CONTROL, mqd->cp_hqd_pq_control);
+
+	/* set the wb address whether it's enabled or not */
+	WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR,
+				mqd->cp_hqd_pq_rptr_report_addr_lo);
+	WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI,
+				mqd->cp_hqd_pq_rptr_report_addr_hi);
+
+	/* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
+	WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr_lo);
+	WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, mqd->cp_hqd_pq_wptr_poll_addr_hi);
+
+	/* enable the doorbell if requested */
+	if (ring->use_doorbell) {
+		if ((adev->asic_type == CHIP_CARRIZO) ||
+				(adev->asic_type == CHIP_FIJI) ||
+				(adev->asic_type == CHIP_STONEY)) {
+			WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
+						AMDGPU_DOORBELL_KIQ << 2);
+			WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
+						AMDGPU_DOORBELL_MEC_RING7 << 2);
+		}
+	}
+	WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control);
+
+	/* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
+	WREG32(mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);
+
+	/* set the vmid for the queue */
+	WREG32(mmCP_HQD_VMID, mqd->cp_hqd_vmid);
+
+	WREG32(mmCP_HQD_PERSISTENT_STATE, mqd->cp_hqd_persistent_state);
+
+	/* activate the queue */
+	WREG32(mmCP_HQD_ACTIVE, mqd->cp_hqd_active);
+
+	if (ring->use_doorbell) {
+		tmp = RREG32(mmCP_PQ_STATUS);
+		tmp = REG_SET_FIELD(tmp, CP_PQ_STATUS, DOORBELL_ENABLE, 1);
+		WREG32(mmCP_PQ_STATUS, tmp);
+	}
+
+	return 0;
+}
+
+static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring,
+				   struct vi_mqd *mqd,
+				   u64 mqd_gpu_addr)
+{
+	struct amdgpu_device *adev = ring->adev;
+	struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+	uint64_t eop_gpu_addr;
+	bool is_kiq = false;
+
+	if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
+		is_kiq = true;
+
+	if (is_kiq) {
+		eop_gpu_addr = kiq->eop_gpu_addr;
+		gfx_v8_0_kiq_setting(&kiq->ring);
+	} else
+		eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr +
+					ring->queue * MEC_HPD_SIZE;
+
+	mutex_lock(&adev->srbm_mutex);
+	vi_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
+
+	gfx_v8_0_mqd_init(adev, mqd, mqd_gpu_addr, eop_gpu_addr, ring);
+
+	if (is_kiq)
+		gfx_v8_0_kiq_init_register(adev, mqd, ring);
+
+	vi_srbm_select(adev, 0, 0, 0, 0);
+	mutex_unlock(&adev->srbm_mutex);
+
+	if (is_kiq)
+		gfx_v8_0_kiq_enable(ring);
+	else
+		gfx_v8_0_map_queue_enable(&kiq->ring, ring);
+
+	return 0;
+}
+
+static void gfx_v8_0_kiq_free_queue(struct amdgpu_device *adev)
+{
+	struct amdgpu_ring *ring = NULL;
+	int i;
+
+	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+		ring = &adev->gfx.compute_ring[i];
+		amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
+		ring->mqd_obj = NULL;
+	}
+
+	ring = &adev->gfx.kiq.ring;
+	amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
+	ring->mqd_obj = NULL;
+}
+
+static int gfx_v8_0_kiq_setup_queue(struct amdgpu_device *adev,
+				    struct amdgpu_ring *ring)
+{
+	struct vi_mqd *mqd;
+	u64 mqd_gpu_addr;
+	u32 *buf;
+	int r = 0;
+
+	r = amdgpu_bo_create_kernel(adev, sizeof(struct vi_mqd), PAGE_SIZE,
+				    AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
+				    &mqd_gpu_addr, (void **)&buf);
+	if (r) {
+		dev_warn(adev->dev, "failed to create ring mqd ob (%d)", r);
+		return r;
+	}
+
+	/* init the mqd struct */
+	memset(buf, 0, sizeof(struct vi_mqd));
+	mqd = (struct vi_mqd *)buf;
+
+	r = gfx_v8_0_kiq_init_queue(ring, mqd, mqd_gpu_addr);
+	if (r)
+		return r;
+
+	amdgpu_bo_kunmap(ring->mqd_obj);
+
+	return 0;
+}
+
+static int gfx_v8_0_kiq_resume(struct amdgpu_device *adev)
+{
+	struct amdgpu_ring *ring = NULL;
+	int r, i;
+
+	ring = &adev->gfx.kiq.ring;
+	r = gfx_v8_0_kiq_setup_queue(adev, ring);
+	if (r)
+		return r;
+
+	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+		ring = &adev->gfx.compute_ring[i];
+		r = gfx_v8_0_kiq_setup_queue(adev, ring);
+		if (r)
+			return r;
+	}
+
+	gfx_v8_0_cp_compute_enable(adev, true);
+
+	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+		ring = &adev->gfx.compute_ring[i];
+
+		ring->ready = true;
+		r = amdgpu_ring_test_ring(ring);
+		if (r)
+			ring->ready = false;
+	}
+
+	ring = &adev->gfx.kiq.ring;
+	ring->ready = true;
+	r = amdgpu_ring_test_ring(ring);
+	if (r)
+		ring->ready = false;
+
+	return 0;
+}
+
 static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
 {
 	int r, i, j;
@@ -4806,7 +5277,10 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
 	if (r)
 		return r;
 
-	r = gfx_v8_0_cp_compute_resume(adev);
+	if (amdgpu_sriov_vf(adev))
+		r = gfx_v8_0_kiq_resume(adev);
+	else
+		r = gfx_v8_0_cp_compute_resume(adev);
 	if (r)
 		return r;
 
@@ -4845,6 +5319,7 @@ static int gfx_v8_0_hw_fini(void *handle)
 	amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
 	amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
 	if (amdgpu_sriov_vf(adev)) {
+		gfx_v8_0_kiq_free_queue(adev);
 		pr_debug("For SRIOV client, shouldn't do anything.\n");
 		return 0;
 	}
@@ -6011,7 +6486,8 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 {
 	u32 ref_and_mask, reg_mem_engine;
 
-	if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
+	if ((ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) ||
+	    (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)) {
 		switch (ring->me) {
 		case 1:
 			ref_and_mask = GPU_HDP_FLUSH_DONE__CP2_MASK << ring->pipe;
@@ -6224,6 +6700,32 @@ static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
 	amdgpu_ring_write(ring, upper_32_bits(seq));
 }
 
+static void gfx_v8_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
+					 u64 seq, unsigned int flags)
+{
+	/* we only allocate 32bit for each seq wb address */
+	if (flags & AMDGPU_FENCE_FLAG_64BIT)
+		BUG();
+
+	/* write fence seq to the "addr" */
+	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+				 WRITE_DATA_DST_SEL(5) | WR_CONFIRM));
+	amdgpu_ring_write(ring, lower_32_bits(addr));
+	amdgpu_ring_write(ring, upper_32_bits(addr));
+	amdgpu_ring_write(ring, lower_32_bits(seq));
+
+	if (flags & AMDGPU_FENCE_FLAG_INT) {
+		/* set register to trigger INT */
+		amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+		amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+					 WRITE_DATA_DST_SEL(0) | WR_CONFIRM));
+		amdgpu_ring_write(ring, mmCPC_INT_STATUS);
+		amdgpu_ring_write(ring, 0);
+		amdgpu_ring_write(ring, 0x20000000); /* src_id is 178 */
+	}
+}
+
 static void gfx_v8_ring_emit_sb(struct amdgpu_ring *ring)
 {
 	amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
@@ -6405,6 +6907,72 @@ static int gfx_v8_0_priv_inst_irq(struct amdgpu_device *adev,
 	return 0;
 }
 
+static int gfx_v8_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
+					    struct amdgpu_irq_src *src,
+					    unsigned int type,
+					    enum amdgpu_interrupt_state state)
+{
+	uint32_t tmp, target;
+	struct amdgpu_ring *ring = (struct amdgpu_ring *)src->data;
+
+	BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
+
+	if (ring->me == 1)
+		target = mmCP_ME1_PIPE0_INT_CNTL;
+	else
+		target = mmCP_ME2_PIPE0_INT_CNTL;
+	target += ring->pipe;
+
+	switch (type) {
+	case AMDGPU_CP_KIQ_IRQ_DRIVER0:
+		if (state == AMDGPU_IRQ_STATE_DISABLE) {
+			tmp = RREG32(mmCPC_INT_CNTL);
+			tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
+						 GENERIC2_INT_ENABLE, 0);
+			WREG32(mmCPC_INT_CNTL, tmp);
+
+			tmp = RREG32(target);
+			tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
+						 GENERIC2_INT_ENABLE, 0);
+			WREG32(target, tmp);
+		} else {
+			tmp = RREG32(mmCPC_INT_CNTL);
+			tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
+						 GENERIC2_INT_ENABLE, 1);
+			WREG32(mmCPC_INT_CNTL, tmp);
+
+			tmp = RREG32(target);
+			tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
+						 GENERIC2_INT_ENABLE, 1);
+			WREG32(target, tmp);
+		}
+		break;
+	default:
+		BUG(); /* kiq only support GENERIC2_INT now */
+		break;
+	}
+	return 0;
+}
+
+static int gfx_v8_0_kiq_irq(struct amdgpu_device *adev,
+			    struct amdgpu_irq_src *source,
+			    struct amdgpu_iv_entry *entry)
+{
+	u8 me_id, pipe_id, queue_id;
+	struct amdgpu_ring *ring = (struct amdgpu_ring *)source->data;
+
+	BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
+
+	me_id = (entry->ring_id & 0x0c) >> 2;
+	pipe_id = (entry->ring_id & 0x03) >> 0;
+	queue_id = (entry->ring_id & 0x70) >> 4;
+	DRM_DEBUG("IH: CPC GENERIC2_INT, me:%d, pipe:%d, queue:%d\n",
+		   me_id, pipe_id, queue_id);
+
+	amdgpu_fence_process(ring);
+	return 0;
+}
+
 static const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
 	.name = "gfx_v8_0",
 	.early_init = gfx_v8_0_early_init,
@@ -6485,10 +7053,37 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 };
 
+static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_kiq = {
+	.type = AMDGPU_RING_TYPE_KIQ,
+	.align_mask = 0xff,
+	.nop = PACKET3(PACKET3_NOP, 0x3FFF),
+	.get_rptr = gfx_v8_0_ring_get_rptr,
+	.get_wptr = gfx_v8_0_ring_get_wptr_compute,
+	.set_wptr = gfx_v8_0_ring_set_wptr_compute,
+	.emit_frame_size =
+		20 + /* gfx_v8_0_ring_emit_gds_switch */
+		7 + /* gfx_v8_0_ring_emit_hdp_flush */
+		5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
+		7 + /* gfx_v8_0_ring_emit_pipeline_sync */
+		17 + /* gfx_v8_0_ring_emit_vm_flush */
+		7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_kiq x3 for user fence, vm fence */
+	.emit_ib_size =	4, /* gfx_v8_0_ring_emit_ib_compute */
+	.emit_ib = gfx_v8_0_ring_emit_ib_compute,
+	.emit_fence = gfx_v8_0_ring_emit_fence_kiq,
+	.emit_hdp_flush = gfx_v8_0_ring_emit_hdp_flush,
+	.emit_hdp_invalidate = gfx_v8_0_ring_emit_hdp_invalidate,
+	.test_ring = gfx_v8_0_ring_test_ring,
+	.test_ib = gfx_v8_0_ring_test_ib,
+	.insert_nop = amdgpu_ring_insert_nop,
+	.pad_ib = amdgpu_ring_generic_pad_ib,
+};
+
 static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev)
 {
 	int i;
 
+	adev->gfx.kiq.ring.funcs = &gfx_v8_0_ring_funcs_kiq;
+
 	for (i = 0; i < adev->gfx.num_gfx_rings; i++)
 		adev->gfx.gfx_ring[i].funcs = &gfx_v8_0_ring_funcs_gfx;
 
@@ -6511,6 +7106,11 @@ static const struct amdgpu_irq_src_funcs gfx_v8_0_priv_inst_irq_funcs = {
 	.process = gfx_v8_0_priv_inst_irq,
 };
 
+static const struct amdgpu_irq_src_funcs gfx_v8_0_kiq_irq_funcs = {
+	.set = gfx_v8_0_kiq_set_interrupt_state,
+	.process = gfx_v8_0_kiq_irq,
+};
+
 static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev)
 {
 	adev->gfx.eop_irq.num_types = AMDGPU_CP_IRQ_LAST;
@@ -6521,6 +7121,9 @@ static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev)
 
 	adev->gfx.priv_inst_irq.num_types = 1;
 	adev->gfx.priv_inst_irq.funcs = &gfx_v8_0_priv_inst_irq_funcs;
+
+	adev->gfx.kiq.irq.num_types = AMDGPU_CP_KIQ_IRQ_LAST;
+	adev->gfx.kiq.irq.funcs = &gfx_v8_0_kiq_irq_funcs;
 }
 
 static void gfx_v8_0_set_rlc_funcs(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/vid.h b/drivers/gpu/drm/amd/amdgpu/vid.h
index 11746f2..7a3863a 100644
--- a/drivers/gpu/drm/amd/amdgpu/vid.h
+++ b/drivers/gpu/drm/amd/amdgpu/vid.h
@@ -360,6 +360,8 @@
 #define	PACKET3_WAIT_ON_CE_COUNTER			0x86
 #define	PACKET3_WAIT_ON_DE_COUNTER_DIFF			0x88
 #define	PACKET3_SWITCH_BUFFER				0x8B
+#define	PACKET3_SET_RESOURCES				0xA0
+#define	PACKET3_MAP_QUEUES				0xA2
 
 #define VCE_CMD_NO_OP		0x00000000
 #define VCE_CMD_END		0x00000001
-- 
2.7.4

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* RE: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found] ` <1482476904-21674-1-git-send-email-Xiangliang.Yu-5C7GfCeVMHo@public.gmane.org>
@ 2016-12-28  2:27   ` Yu, Xiangliang
       [not found]     ` <CY4PR12MB1701D664FEB2EF8FCFD4EBDBEB680-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  2016-12-31  6:53   ` Alex Deucher
  1 sibling, 1 reply; 14+ messages in thread
From: Yu, Xiangliang @ 2016-12-28  2:27 UTC (permalink / raw)
  To: Yu, Xiangliang, amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Liu, Monk

Does anyone can give some comments? 
This is urgent case.


Thanks!
Xiangliang Yu

> -----Original Message-----
> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On Behalf
> Of Xiangliang Yu
> Sent: Friday, December 23, 2016 3:08 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Yu, Xiangliang <Xiangliang.Yu@amd.com>; Liu, Monk
> <Monk.Liu@amd.com>
> Subject: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
> 
> KIQ is queue-memory based initialization method: setup KIQ queue firstly,
> then send command to KIQ to setup other queues, without accessing
> registers.
> 
> For virtualization, need KIQ to access virtual function registers when running
> on guest mode.
> 
> changes in v2:
> 1. use amdgpu_bo_create/free_kernel to allocate OB.
> 
> Signed-off-by: Monk Liu <Monk.Liu@amd.com>
> Signed-off-by: Xiangliang Yu <Xiangliang.Yu@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h   |  13 +
>  drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 607
> +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/amd/amdgpu/vid.h      |   2 +
>  3 files changed, 620 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 9ea5bf0..c392882 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -186,6 +186,11 @@ enum amdgpu_thermal_irq {
>  	AMDGPU_THERMAL_IRQ_LAST
>  };
> 
> +enum amdgpu_kiq_irq {
> +	AMDGPU_CP_KIQ_IRQ_DRIVER0 = 0,
> +	AMDGPU_CP_KIQ_IRQ_LAST
> +};
> +
>  int amdgpu_set_clockgating_state(struct amdgpu_device *adev,
>  				  enum amd_ip_block_type block_type,
>  				  enum amd_clockgating_state state); @@ -
> 778,6 +783,13 @@ struct amdgpu_mec {
>  	u32 num_queue;
>  };
> 
> +struct amdgpu_kiq {
> +	u64			eop_gpu_addr;
> +	struct amdgpu_bo	*eop_obj;
> +	struct amdgpu_ring	ring;
> +	struct amdgpu_irq_src	irq;
> +};
> +
>  /*
>   * GPU scratch registers structures, functions & helpers
>   */
> @@ -853,6 +865,7 @@ struct amdgpu_gfx {
>  	struct amdgpu_gca_config	config;
>  	struct amdgpu_rlc		rlc;
>  	struct amdgpu_mec		mec;
> +	struct amdgpu_kiq		kiq;
>  	struct amdgpu_scratch		scratch;
>  	const struct firmware		*me_fw;	/* ME firmware */
>  	uint32_t			me_fw_version;
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> index c3e6bfc..a233eeb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> @@ -1367,6 +1367,42 @@ static void gfx_v8_0_mec_fini(struct
> amdgpu_device *adev)
>  	}
>  }
> 
> +static int gfx_v8_0_kiq_init_ring(struct amdgpu_device *adev,
> +				  struct amdgpu_ring *ring,
> +				  struct amdgpu_irq_src *irq)
> +{
> +	int r = 0;
> +
> +	ring->adev = NULL;
> +	ring->ring_obj = NULL;
> +	ring->use_doorbell = true;
> +	ring->doorbell_index = AMDGPU_DOORBELL_KIQ;
> +	if (adev->gfx.mec2_fw) {
> +		ring->me = 2;
> +		ring->pipe = 0;
> +	} else {
> +		ring->me = 1;
> +		ring->pipe = 1;
> +	}
> +
> +	irq->data = ring;
> +	ring->queue = 0;
> +	sprintf(ring->name, "kiq %d.%d.%d", ring->me, ring->pipe, ring-
> >queue);
> +	r = amdgpu_ring_init(adev, ring, 1024,
> +			     irq, AMDGPU_CP_KIQ_IRQ_DRIVER0);
> +	if (r)
> +		dev_warn(adev->dev, "(%d) failed to init kiq ring\n", r);
> +
> +	return r;
> +}
> +
> +static void gfx_v8_0_kiq_free_ring(struct amdgpu_ring *ring,
> +				   struct amdgpu_irq_src *irq)
> +{
> +	amdgpu_ring_fini(ring);
> +	irq->data = NULL;
> +}
> +
>  #define MEC_HPD_SIZE 2048
> 
>  static int gfx_v8_0_mec_init(struct amdgpu_device *adev) @@ -1421,6
> +1457,35 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
>  	return 0;
>  }
> 
> +static void gfx_v8_0_kiq_fini(struct amdgpu_device *adev) {
> +	struct amdgpu_kiq *kiq = &adev->gfx.kiq;
> +
> +	amdgpu_bo_free_kernel(&kiq->eop_obj, &kiq->eop_gpu_addr,
> NULL);
> +	kiq->eop_obj = NULL;
> +}
> +
> +static int gfx_v8_0_kiq_init(struct amdgpu_device *adev) {
> +	int r;
> +	u32 *hpd;
> +	struct amdgpu_kiq *kiq = &adev->gfx.kiq;
> +
> +	r = amdgpu_bo_create_kernel(adev, MEC_HPD_SIZE, PAGE_SIZE,
> +				    AMDGPU_GEM_DOMAIN_GTT, &kiq-
> >eop_obj,
> +				    &kiq->eop_gpu_addr, (void **)&hpd);
> +	if (r) {
> +		dev_warn(adev->dev, "failed to create KIQ bo (%d).\n", r);
> +		return r;
> +	}
> +
> +	memset(hpd, 0, MEC_HPD_SIZE);
> +
> +	amdgpu_bo_kunmap(kiq->eop_obj);
> +
> +	return 0;
> +}
> +
>  static const u32 vgpr_init_compute_shader[] =  {
>  	0x7e000209, 0x7e020208,
> @@ -1997,8 +2062,14 @@ static int gfx_v8_0_sw_init(void *handle)  {
>  	int i, r;
>  	struct amdgpu_ring *ring;
> +	struct amdgpu_kiq *kiq;
>  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> 
> +	/* KIQ event */
> +	r = amdgpu_irq_add_id(adev, 178, &adev->gfx.kiq.irq);
> +	if (r)
> +		return r;
> +
>  	/* EOP Event */
>  	r = amdgpu_irq_add_id(adev, 181, &adev->gfx.eop_irq);
>  	if (r)
> @@ -2036,6 +2107,17 @@ static int gfx_v8_0_sw_init(void *handle)
>  		return r;
>  	}
> 
> +	r = gfx_v8_0_kiq_init(adev);
> +	if (r) {
> +		DRM_ERROR("Failed to init KIQ BOs!\n");
> +		return r;
> +	}
> +
> +	kiq = &adev->gfx.kiq;
> +	r = gfx_v8_0_kiq_init_ring(adev, &kiq->ring, &kiq->irq);
> +	if (r)
> +		return r;
> +
>  	/* set up the gfx ring */
>  	for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
>  		ring = &adev->gfx.gfx_ring[i];
> @@ -2119,7 +2201,9 @@ static int gfx_v8_0_sw_fini(void *handle)
>  		amdgpu_ring_fini(&adev->gfx.gfx_ring[i]);
>  	for (i = 0; i < adev->gfx.num_compute_rings; i++)
>  		amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
> +	gfx_v8_0_kiq_free_ring(&adev->gfx.kiq.ring, &adev->gfx.kiq.irq);
> 
> +	gfx_v8_0_kiq_fini(adev);
>  	gfx_v8_0_mec_fini(adev);
>  	gfx_v8_0_rlc_fini(adev);
>  	gfx_v8_0_free_microcode(adev);
> @@ -4506,6 +4590,393 @@ static void gfx_v8_0_cp_compute_fini(struct
> amdgpu_device *adev)
>  	}
>  }
> 
> +/* KIQ functions */
> +static void gfx_v8_0_kiq_setting(struct amdgpu_ring *ring) {
> +	uint32_t tmp;
> +	struct amdgpu_device *adev = ring->adev;
> +
> +	/* tell RLC which is KIQ queue */
> +	tmp = RREG32(mmRLC_CP_SCHEDULERS);
> +	tmp &= 0xffffff00;
> +	tmp |= (ring->me << 5) | (ring->pipe << 3) | (ring->queue);
> +	WREG32(mmRLC_CP_SCHEDULERS, tmp);
> +	tmp |= 0x80;
> +	WREG32(mmRLC_CP_SCHEDULERS, tmp);
> +}
> +
> +static void gfx_v8_0_kiq_enable(struct amdgpu_ring *ring) {
> +	amdgpu_ring_alloc(ring, 8);
> +	/* set resources */
> +	amdgpu_ring_write(ring, PACKET3(PACKET3_SET_RESOURCES, 6));
> +	amdgpu_ring_write(ring, 0);	/* vmid_mask:0 queue_type:0 (KIQ)
> */
> +	amdgpu_ring_write(ring, 0x000000FF);	/* queue mask lo */
> +	amdgpu_ring_write(ring, 0);	/* queue mask hi */
> +	amdgpu_ring_write(ring, 0);	/* gws mask lo */
> +	amdgpu_ring_write(ring, 0);	/* gws mask hi */
> +	amdgpu_ring_write(ring, 0);	/* oac mask */
> +	amdgpu_ring_write(ring, 0);	/* gds heap base:0, gds heap size:0
> */
> +	amdgpu_ring_commit(ring);
> +	udelay(50);
> +}
> +
> +static void gfx_v8_0_map_queue_enable(struct amdgpu_ring *kiq_ring,
> +				   struct amdgpu_ring *ring)
> +{
> +	struct amdgpu_device *adev = kiq_ring->adev;
> +	uint64_t mqd_addr, wptr_addr;
> +
> +	mqd_addr = amdgpu_bo_gpu_offset(ring->mqd_obj);
> +	wptr_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
> +	amdgpu_ring_alloc(kiq_ring, 8);
> +
> +	amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_MAP_QUEUES, 5));
> +	/* Q_sel:0, vmid:0, vidmem: 1, engine:0, num_Q:1*/
> +	amdgpu_ring_write(kiq_ring, 0x21010000);
> +	amdgpu_ring_write(kiq_ring, (ring->doorbell_index << 2) |
> +			(ring->queue << 26) |
> +			(ring->pipe << 29) |
> +			((ring->me == 1 ? 0 : 1) << 31)); /* doorbell */
> +	amdgpu_ring_write(kiq_ring, lower_32_bits(mqd_addr));
> +	amdgpu_ring_write(kiq_ring, upper_32_bits(mqd_addr));
> +	amdgpu_ring_write(kiq_ring, lower_32_bits(wptr_addr));
> +	amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
> +	amdgpu_ring_commit(kiq_ring);
> +	udelay(50);
> +}
> +
> +static int gfx_v8_0_mqd_init(struct amdgpu_device *adev,
> +			     struct vi_mqd *mqd,
> +			     uint64_t mqd_gpu_addr,
> +			     uint64_t eop_gpu_addr,
> +			     struct amdgpu_ring *ring)
> +{
> +	uint64_t hqd_gpu_addr, wb_gpu_addr, eop_base_addr;
> +	uint32_t tmp;
> +
> +	mqd->header = 0xC0310800;
> +	mqd->compute_pipelinestat_enable = 0x00000001;
> +	mqd->compute_static_thread_mgmt_se0 = 0xffffffff;
> +	mqd->compute_static_thread_mgmt_se1 = 0xffffffff;
> +	mqd->compute_static_thread_mgmt_se2 = 0xffffffff;
> +	mqd->compute_static_thread_mgmt_se3 = 0xffffffff;
> +	mqd->compute_misc_reserved = 0x00000003;
> +
> +	eop_base_addr = eop_gpu_addr >> 8;
> +	mqd->cp_hqd_eop_base_addr_lo = eop_base_addr;
> +	mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr);
> +
> +	/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
> +	tmp = RREG32(mmCP_HQD_EOP_CONTROL);
> +	tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
> +			(order_base_2(MEC_HPD_SIZE / 4) - 1));
> +
> +	mqd->cp_hqd_eop_control = tmp;
> +
> +	/* enable doorbell? */
> +	tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
> +
> +	if (ring->use_doorbell)
> +		tmp = REG_SET_FIELD(tmp,
> CP_HQD_PQ_DOORBELL_CONTROL,
> +					 DOORBELL_EN, 1);
> +	else
> +		tmp = REG_SET_FIELD(tmp,
> CP_HQD_PQ_DOORBELL_CONTROL,
> +					 DOORBELL_EN, 0);
> +
> +	mqd->cp_hqd_pq_doorbell_control = tmp;
> +
> +	/* disable the queue if it's active */
> +	mqd->cp_hqd_dequeue_request = 0;
> +	mqd->cp_hqd_pq_rptr = 0;
> +	mqd->cp_hqd_pq_wptr = 0;
> +
> +	/* set the pointer to the MQD */
> +	mqd->cp_mqd_base_addr_lo = mqd_gpu_addr & 0xfffffffc;
> +	mqd->cp_mqd_base_addr_hi = upper_32_bits(mqd_gpu_addr);
> +
> +	/* set MQD vmid to 0 */
> +	tmp = RREG32(mmCP_MQD_CONTROL);
> +	tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0);
> +	mqd->cp_mqd_control = tmp;
> +
> +	/* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
> +	hqd_gpu_addr = ring->gpu_addr >> 8;
> +	mqd->cp_hqd_pq_base_lo = hqd_gpu_addr;
> +	mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr);
> +
> +	/* set up the HQD, this is similar to CP_RB0_CNTL */
> +	tmp = RREG32(mmCP_HQD_PQ_CONTROL);
> +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE,
> +			    (order_base_2(ring->ring_size / 4) - 1));
> +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL,
> RPTR_BLOCK_SIZE,
> +			((order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1)
> << 8)); #ifdef
> +__BIG_ENDIAN
> +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP,
> 1); #endif
> +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL,
> UNORD_DISPATCH, 0);
> +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL,
> ROQ_PQ_IB_FLIP, 0);
> +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1);
> +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE,
> 1);
> +	mqd->cp_hqd_pq_control = tmp;
> +
> +	/* set the wb address whether it's enabled or not */
> +	wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
> +	mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc;
> +	mqd->cp_hqd_pq_rptr_report_addr_hi =
> +		upper_32_bits(wb_gpu_addr) & 0xffff;
> +
> +	/* only used if
> CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
> +	wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
> +	mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc;
> +	mqd->cp_hqd_pq_wptr_poll_addr_hi =
> upper_32_bits(wb_gpu_addr) &
> +0xffff;
> +
> +	tmp = 0;
> +	/* enable the doorbell if requested */
> +	if (ring->use_doorbell) {
> +		tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
> +		tmp = REG_SET_FIELD(tmp,
> CP_HQD_PQ_DOORBELL_CONTROL,
> +				DOORBELL_OFFSET, ring->doorbell_index);
> +
> +		tmp = REG_SET_FIELD(tmp,
> CP_HQD_PQ_DOORBELL_CONTROL,
> +					 DOORBELL_EN, 1);
> +		tmp = REG_SET_FIELD(tmp,
> CP_HQD_PQ_DOORBELL_CONTROL,
> +					 DOORBELL_SOURCE, 0);
> +		tmp = REG_SET_FIELD(tmp,
> CP_HQD_PQ_DOORBELL_CONTROL,
> +					 DOORBELL_HIT, 0);
> +	}
> +
> +	mqd->cp_hqd_pq_doorbell_control = tmp;
> +
> +	/* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
> +	ring->wptr = 0;
> +	mqd->cp_hqd_pq_wptr = ring->wptr;
> +	mqd->cp_hqd_pq_rptr = RREG32(mmCP_HQD_PQ_RPTR);
> +
> +	/* set the vmid for the queue */
> +	mqd->cp_hqd_vmid = 0;
> +
> +	tmp = RREG32(mmCP_HQD_PERSISTENT_STATE);
> +	tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE,
> PRELOAD_SIZE, 0x53);
> +	mqd->cp_hqd_persistent_state = tmp;
> +
> +	/* activate the queue */
> +	mqd->cp_hqd_active = 1;
> +
> +	return 0;
> +}
> +
> +static int gfx_v8_0_kiq_init_register(struct amdgpu_device *adev,
> +				      struct vi_mqd *mqd,
> +				      struct amdgpu_ring *ring)
> +{
> +	uint32_t tmp;
> +	int j;
> +
> +	/* disable wptr polling */
> +	tmp = RREG32(mmCP_PQ_WPTR_POLL_CNTL);
> +	tmp = REG_SET_FIELD(tmp, CP_PQ_WPTR_POLL_CNTL, EN, 0);
> +	WREG32(mmCP_PQ_WPTR_POLL_CNTL, tmp);
> +
> +	WREG32(mmCP_HQD_EOP_BASE_ADDR, mqd-
> >cp_hqd_eop_base_addr_lo);
> +	WREG32(mmCP_HQD_EOP_BASE_ADDR_HI, mqd-
> >cp_hqd_eop_base_addr_hi);
> +
> +	/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
> +	WREG32(mmCP_HQD_EOP_CONTROL, mqd->cp_hqd_eop_control);
> +
> +	/* enable doorbell? */
> +	WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, mqd-
> >cp_hqd_pq_doorbell_control);
> +
> +	/* disable the queue if it's active */
> +	if (RREG32(mmCP_HQD_ACTIVE) & 1) {
> +		WREG32(mmCP_HQD_DEQUEUE_REQUEST, 1);
> +		for (j = 0; j < adev->usec_timeout; j++) {
> +			if (!(RREG32(mmCP_HQD_ACTIVE) & 1))
> +				break;
> +			udelay(1);
> +		}
> +		WREG32(mmCP_HQD_DEQUEUE_REQUEST, mqd-
> >cp_hqd_dequeue_request);
> +		WREG32(mmCP_HQD_PQ_RPTR, mqd->cp_hqd_pq_rptr);
> +		WREG32(mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);
> +	}
> +
> +	/* set the pointer to the MQD */
> +	WREG32(mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr_lo);
> +	WREG32(mmCP_MQD_BASE_ADDR_HI, mqd-
> >cp_mqd_base_addr_hi);
> +
> +	/* set MQD vmid to 0 */
> +	WREG32(mmCP_MQD_CONTROL, mqd->cp_mqd_control);
> +
> +	/* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
> +	WREG32(mmCP_HQD_PQ_BASE, mqd->cp_hqd_pq_base_lo);
> +	WREG32(mmCP_HQD_PQ_BASE_HI, mqd->cp_hqd_pq_base_hi);
> +
> +	/* set up the HQD, this is similar to CP_RB0_CNTL */
> +	WREG32(mmCP_HQD_PQ_CONTROL, mqd->cp_hqd_pq_control);
> +
> +	/* set the wb address whether it's enabled or not */
> +	WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR,
> +				mqd->cp_hqd_pq_rptr_report_addr_lo);
> +	WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI,
> +				mqd->cp_hqd_pq_rptr_report_addr_hi);
> +
> +	/* only used if
> CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
> +	WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd-
> >cp_hqd_pq_wptr_poll_addr_lo);
> +	WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR_HI,
> +mqd->cp_hqd_pq_wptr_poll_addr_hi);
> +
> +	/* enable the doorbell if requested */
> +	if (ring->use_doorbell) {
> +		if ((adev->asic_type == CHIP_CARRIZO) ||
> +				(adev->asic_type == CHIP_FIJI) ||
> +				(adev->asic_type == CHIP_STONEY)) {
> +			WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
> +						AMDGPU_DOORBELL_KIQ <<
> 2);
> +			WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
> +
> 	AMDGPU_DOORBELL_MEC_RING7 << 2);
> +		}
> +	}
> +	WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, mqd-
> >cp_hqd_pq_doorbell_control);
> +
> +	/* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
> +	WREG32(mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);
> +
> +	/* set the vmid for the queue */
> +	WREG32(mmCP_HQD_VMID, mqd->cp_hqd_vmid);
> +
> +	WREG32(mmCP_HQD_PERSISTENT_STATE, mqd-
> >cp_hqd_persistent_state);
> +
> +	/* activate the queue */
> +	WREG32(mmCP_HQD_ACTIVE, mqd->cp_hqd_active);
> +
> +	if (ring->use_doorbell) {
> +		tmp = RREG32(mmCP_PQ_STATUS);
> +		tmp = REG_SET_FIELD(tmp, CP_PQ_STATUS,
> DOORBELL_ENABLE, 1);
> +		WREG32(mmCP_PQ_STATUS, tmp);
> +	}
> +
> +	return 0;
> +}
> +
> +static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring,
> +				   struct vi_mqd *mqd,
> +				   u64 mqd_gpu_addr)
> +{
> +	struct amdgpu_device *adev = ring->adev;
> +	struct amdgpu_kiq *kiq = &adev->gfx.kiq;
> +	uint64_t eop_gpu_addr;
> +	bool is_kiq = false;
> +
> +	if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
> +		is_kiq = true;
> +
> +	if (is_kiq) {
> +		eop_gpu_addr = kiq->eop_gpu_addr;
> +		gfx_v8_0_kiq_setting(&kiq->ring);
> +	} else
> +		eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr +
> +					ring->queue * MEC_HPD_SIZE;
> +
> +	mutex_lock(&adev->srbm_mutex);
> +	vi_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
> +
> +	gfx_v8_0_mqd_init(adev, mqd, mqd_gpu_addr, eop_gpu_addr,
> ring);
> +
> +	if (is_kiq)
> +		gfx_v8_0_kiq_init_register(adev, mqd, ring);
> +
> +	vi_srbm_select(adev, 0, 0, 0, 0);
> +	mutex_unlock(&adev->srbm_mutex);
> +
> +	if (is_kiq)
> +		gfx_v8_0_kiq_enable(ring);
> +	else
> +		gfx_v8_0_map_queue_enable(&kiq->ring, ring);
> +
> +	return 0;
> +}
> +
> +static void gfx_v8_0_kiq_free_queue(struct amdgpu_device *adev) {
> +	struct amdgpu_ring *ring = NULL;
> +	int i;
> +
> +	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
> +		ring = &adev->gfx.compute_ring[i];
> +		amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
> +		ring->mqd_obj = NULL;
> +	}
> +
> +	ring = &adev->gfx.kiq.ring;
> +	amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
> +	ring->mqd_obj = NULL;
> +}
> +
> +static int gfx_v8_0_kiq_setup_queue(struct amdgpu_device *adev,
> +				    struct amdgpu_ring *ring)
> +{
> +	struct vi_mqd *mqd;
> +	u64 mqd_gpu_addr;
> +	u32 *buf;
> +	int r = 0;
> +
> +	r = amdgpu_bo_create_kernel(adev, sizeof(struct vi_mqd),
> PAGE_SIZE,
> +				    AMDGPU_GEM_DOMAIN_GTT, &ring-
> >mqd_obj,
> +				    &mqd_gpu_addr, (void **)&buf);
> +	if (r) {
> +		dev_warn(adev->dev, "failed to create ring mqd ob (%d)", r);
> +		return r;
> +	}
> +
> +	/* init the mqd struct */
> +	memset(buf, 0, sizeof(struct vi_mqd));
> +	mqd = (struct vi_mqd *)buf;
> +
> +	r = gfx_v8_0_kiq_init_queue(ring, mqd, mqd_gpu_addr);
> +	if (r)
> +		return r;
> +
> +	amdgpu_bo_kunmap(ring->mqd_obj);
> +
> +	return 0;
> +}
> +
> +static int gfx_v8_0_kiq_resume(struct amdgpu_device *adev) {
> +	struct amdgpu_ring *ring = NULL;
> +	int r, i;
> +
> +	ring = &adev->gfx.kiq.ring;
> +	r = gfx_v8_0_kiq_setup_queue(adev, ring);
> +	if (r)
> +		return r;
> +
> +	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
> +		ring = &adev->gfx.compute_ring[i];
> +		r = gfx_v8_0_kiq_setup_queue(adev, ring);
> +		if (r)
> +			return r;
> +	}
> +
> +	gfx_v8_0_cp_compute_enable(adev, true);
> +
> +	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
> +		ring = &adev->gfx.compute_ring[i];
> +
> +		ring->ready = true;
> +		r = amdgpu_ring_test_ring(ring);
> +		if (r)
> +			ring->ready = false;
> +	}
> +
> +	ring = &adev->gfx.kiq.ring;
> +	ring->ready = true;
> +	r = amdgpu_ring_test_ring(ring);
> +	if (r)
> +		ring->ready = false;
> +
> +	return 0;
> +}
> +
>  static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)  {
>  	int r, i, j;
> @@ -4806,7 +5277,10 @@ static int gfx_v8_0_cp_resume(struct
> amdgpu_device *adev)
>  	if (r)
>  		return r;
> 
> -	r = gfx_v8_0_cp_compute_resume(adev);
> +	if (amdgpu_sriov_vf(adev))
> +		r = gfx_v8_0_kiq_resume(adev);
> +	else
> +		r = gfx_v8_0_cp_compute_resume(adev);
>  	if (r)
>  		return r;
> 
> @@ -4845,6 +5319,7 @@ static int gfx_v8_0_hw_fini(void *handle)
>  	amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
>  	amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
>  	if (amdgpu_sriov_vf(adev)) {
> +		gfx_v8_0_kiq_free_queue(adev);
>  		pr_debug("For SRIOV client, shouldn't do anything.\n");
>  		return 0;
>  	}
> @@ -6011,7 +6486,8 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct
> amdgpu_ring *ring)  {
>  	u32 ref_and_mask, reg_mem_engine;
> 
> -	if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
> +	if ((ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) ||
> +	    (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)) {
>  		switch (ring->me) {
>  		case 1:
>  			ref_and_mask =
> GPU_HDP_FLUSH_DONE__CP2_MASK << ring->pipe; @@ -6224,6 +6700,32
> @@ static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring
> *ring,
>  	amdgpu_ring_write(ring, upper_32_bits(seq));  }
> 
> +static void gfx_v8_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64
> addr,
> +					 u64 seq, unsigned int flags)
> +{
> +	/* we only allocate 32bit for each seq wb address */
> +	if (flags & AMDGPU_FENCE_FLAG_64BIT)
> +		BUG();
> +
> +	/* write fence seq to the "addr" */
> +	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
> +	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
> +				 WRITE_DATA_DST_SEL(5) | WR_CONFIRM));
> +	amdgpu_ring_write(ring, lower_32_bits(addr));
> +	amdgpu_ring_write(ring, upper_32_bits(addr));
> +	amdgpu_ring_write(ring, lower_32_bits(seq));
> +
> +	if (flags & AMDGPU_FENCE_FLAG_INT) {
> +		/* set register to trigger INT */
> +		amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA,
> 3));
> +		amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
> +					 WRITE_DATA_DST_SEL(0) |
> WR_CONFIRM));
> +		amdgpu_ring_write(ring, mmCPC_INT_STATUS);
> +		amdgpu_ring_write(ring, 0);
> +		amdgpu_ring_write(ring, 0x20000000); /* src_id is 178 */
> +	}
> +}
> +
>  static void gfx_v8_ring_emit_sb(struct amdgpu_ring *ring)  {
>  	amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
> @@ -6405,6 +6907,72 @@ static int gfx_v8_0_priv_inst_irq(struct
> amdgpu_device *adev,
>  	return 0;
>  }
> 
> +static int gfx_v8_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
> +					    struct amdgpu_irq_src *src,
> +					    unsigned int type,
> +					    enum amdgpu_interrupt_state
> state) {
> +	uint32_t tmp, target;
> +	struct amdgpu_ring *ring = (struct amdgpu_ring *)src->data;
> +
> +	BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
> +
> +	if (ring->me == 1)
> +		target = mmCP_ME1_PIPE0_INT_CNTL;
> +	else
> +		target = mmCP_ME2_PIPE0_INT_CNTL;
> +	target += ring->pipe;
> +
> +	switch (type) {
> +	case AMDGPU_CP_KIQ_IRQ_DRIVER0:
> +		if (state == AMDGPU_IRQ_STATE_DISABLE) {
> +			tmp = RREG32(mmCPC_INT_CNTL);
> +			tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
> +						 GENERIC2_INT_ENABLE, 0);
> +			WREG32(mmCPC_INT_CNTL, tmp);
> +
> +			tmp = RREG32(target);
> +			tmp = REG_SET_FIELD(tmp,
> CP_ME2_PIPE0_INT_CNTL,
> +						 GENERIC2_INT_ENABLE, 0);
> +			WREG32(target, tmp);
> +		} else {
> +			tmp = RREG32(mmCPC_INT_CNTL);
> +			tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
> +						 GENERIC2_INT_ENABLE, 1);
> +			WREG32(mmCPC_INT_CNTL, tmp);
> +
> +			tmp = RREG32(target);
> +			tmp = REG_SET_FIELD(tmp,
> CP_ME2_PIPE0_INT_CNTL,
> +						 GENERIC2_INT_ENABLE, 1);
> +			WREG32(target, tmp);
> +		}
> +		break;
> +	default:
> +		BUG(); /* kiq only support GENERIC2_INT now */
> +		break;
> +	}
> +	return 0;
> +}
> +
> +static int gfx_v8_0_kiq_irq(struct amdgpu_device *adev,
> +			    struct amdgpu_irq_src *source,
> +			    struct amdgpu_iv_entry *entry)
> +{
> +	u8 me_id, pipe_id, queue_id;
> +	struct amdgpu_ring *ring = (struct amdgpu_ring *)source->data;
> +
> +	BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
> +
> +	me_id = (entry->ring_id & 0x0c) >> 2;
> +	pipe_id = (entry->ring_id & 0x03) >> 0;
> +	queue_id = (entry->ring_id & 0x70) >> 4;
> +	DRM_DEBUG("IH: CPC GENERIC2_INT, me:%d, pipe:%d,
> queue:%d\n",
> +		   me_id, pipe_id, queue_id);
> +
> +	amdgpu_fence_process(ring);
> +	return 0;
> +}
> +
>  static const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
>  	.name = "gfx_v8_0",
>  	.early_init = gfx_v8_0_early_init,
> @@ -6485,10 +7053,37 @@ static const struct amdgpu_ring_funcs
> gfx_v8_0_ring_funcs_compute = {
>  	.pad_ib = amdgpu_ring_generic_pad_ib,
>  };
> 
> +static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_kiq = {
> +	.type = AMDGPU_RING_TYPE_KIQ,
> +	.align_mask = 0xff,
> +	.nop = PACKET3(PACKET3_NOP, 0x3FFF),
> +	.get_rptr = gfx_v8_0_ring_get_rptr,
> +	.get_wptr = gfx_v8_0_ring_get_wptr_compute,
> +	.set_wptr = gfx_v8_0_ring_set_wptr_compute,
> +	.emit_frame_size =
> +		20 + /* gfx_v8_0_ring_emit_gds_switch */
> +		7 + /* gfx_v8_0_ring_emit_hdp_flush */
> +		5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
> +		7 + /* gfx_v8_0_ring_emit_pipeline_sync */
> +		17 + /* gfx_v8_0_ring_emit_vm_flush */
> +		7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_kiq x3 for user fence,
> vm fence */
> +	.emit_ib_size =	4, /* gfx_v8_0_ring_emit_ib_compute */
> +	.emit_ib = gfx_v8_0_ring_emit_ib_compute,
> +	.emit_fence = gfx_v8_0_ring_emit_fence_kiq,
> +	.emit_hdp_flush = gfx_v8_0_ring_emit_hdp_flush,
> +	.emit_hdp_invalidate = gfx_v8_0_ring_emit_hdp_invalidate,
> +	.test_ring = gfx_v8_0_ring_test_ring,
> +	.test_ib = gfx_v8_0_ring_test_ib,
> +	.insert_nop = amdgpu_ring_insert_nop,
> +	.pad_ib = amdgpu_ring_generic_pad_ib,
> +};
> +
>  static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev)  {
>  	int i;
> 
> +	adev->gfx.kiq.ring.funcs = &gfx_v8_0_ring_funcs_kiq;
> +
>  	for (i = 0; i < adev->gfx.num_gfx_rings; i++)
>  		adev->gfx.gfx_ring[i].funcs = &gfx_v8_0_ring_funcs_gfx;
> 
> @@ -6511,6 +7106,11 @@ static const struct amdgpu_irq_src_funcs
> gfx_v8_0_priv_inst_irq_funcs = {
>  	.process = gfx_v8_0_priv_inst_irq,
>  };
> 
> +static const struct amdgpu_irq_src_funcs gfx_v8_0_kiq_irq_funcs = {
> +	.set = gfx_v8_0_kiq_set_interrupt_state,
> +	.process = gfx_v8_0_kiq_irq,
> +};
> +
>  static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev)  {
>  	adev->gfx.eop_irq.num_types = AMDGPU_CP_IRQ_LAST; @@ -
> 6521,6 +7121,9 @@ static void gfx_v8_0_set_irq_funcs(struct
> amdgpu_device *adev)
> 
>  	adev->gfx.priv_inst_irq.num_types = 1;
>  	adev->gfx.priv_inst_irq.funcs = &gfx_v8_0_priv_inst_irq_funcs;
> +
> +	adev->gfx.kiq.irq.num_types = AMDGPU_CP_KIQ_IRQ_LAST;
> +	adev->gfx.kiq.irq.funcs = &gfx_v8_0_kiq_irq_funcs;
>  }
> 
>  static void gfx_v8_0_set_rlc_funcs(struct amdgpu_device *adev) diff --git
> a/drivers/gpu/drm/amd/amdgpu/vid.h
> b/drivers/gpu/drm/amd/amdgpu/vid.h
> index 11746f2..7a3863a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vid.h
> +++ b/drivers/gpu/drm/amd/amdgpu/vid.h
> @@ -360,6 +360,8 @@
>  #define	PACKET3_WAIT_ON_CE_COUNTER			0x86
>  #define	PACKET3_WAIT_ON_DE_COUNTER_DIFF
> 	0x88
>  #define	PACKET3_SWITCH_BUFFER				0x8B
> +#define	PACKET3_SET_RESOURCES				0xA0
> +#define	PACKET3_MAP_QUEUES				0xA2
> 
>  #define VCE_CMD_NO_OP		0x00000000
>  #define VCE_CMD_END		0x00000001
> --
> 2.7.4
> 
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]     ` <CY4PR12MB1701D664FEB2EF8FCFD4EBDBEB680-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
@ 2016-12-28  2:31       ` zhoucm1
       [not found]         ` <58632418.5040408-5C7GfCeVMHo@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: zhoucm1 @ 2016-12-28  2:31 UTC (permalink / raw)
  To: Yu, Xiangliang, amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Liu, Monk



On 2016年12月28日 10:27, Yu, Xiangliang wrote:
> +
> >+	amdgpu_bo_kunmap(kiq->eop_obj);
> >+
I see it is in many places, which is don't need I think, 
amdgpu_bo_free_kernel will handle it if I'm correct.

Regards,
David zhou
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]         ` <58632418.5040408-5C7GfCeVMHo@public.gmane.org>
@ 2016-12-28  2:59           ` Yu, Xiangliang
       [not found]             ` <CY4PR12MB1701E0582B28FDC9AF4A1CF7EB680-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  2016-12-28  3:20           ` 答复: " Liu, Monk
  1 sibling, 1 reply; 14+ messages in thread
From: Yu, Xiangliang @ 2016-12-28  2:59 UTC (permalink / raw)
  To: Zhou, David(ChunMing), amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Liu, Monk


> -----Original Message-----
> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On Behalf
> Of zhoucm1
> Sent: Wednesday, December 28, 2016 10:32 AM
> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>; amd-
> gfx@lists.freedesktop.org
> Cc: Liu, Monk <Monk.Liu@amd.com>
> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface
> queue(KIQ)
> 
> 
> 
> On 2016年12月28日 10:27, Yu, Xiangliang wrote:
> > +
> > >+	amdgpu_bo_kunmap(kiq->eop_obj);
> > >+
> I see it is in many places, which is don't need I think,
> amdgpu_bo_free_kernel will handle it if I'm correct.

Memory kmap should be free ASAP from memory management point.

> 
> Regards,
> David zhou
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* 答复: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]         ` <58632418.5040408-5C7GfCeVMHo@public.gmane.org>
  2016-12-28  2:59           ` Yu, Xiangliang
@ 2016-12-28  3:20           ` Liu, Monk
  1 sibling, 0 replies; 14+ messages in thread
From: Liu, Monk @ 2016-12-28  3:20 UTC (permalink / raw)
  To: Zhou, David(ChunMing),
	Yu, Xiangliang, amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW


[-- Attachment #1.1: Type: text/plain, Size: 853 bytes --]

kiq->eop_obj won't allowed to be freed until GFX finish, so we still better unmap this object as long as we don't need to access it via CPU

________________________________
发件人: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> 代表 zhoucm1 <david1.zhou@amd.com>
发送时间: 2016年12月28日 10:31:52
收件人: Yu, Xiangliang; amd-gfx@lists.freedesktop.org
抄送: Liu, Monk
主题: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)



On 2016年12月28日 10:27, Yu, Xiangliang wrote:
> +
> >+    amdgpu_bo_kunmap(kiq->eop_obj);
> >+
I see it is in many places, which is don't need I think,
amdgpu_bo_free_kernel will handle it if I'm correct.

Regards,
David zhou
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[-- Attachment #1.2: Type: text/html, Size: 2085 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found] ` <1482476904-21674-1-git-send-email-Xiangliang.Yu-5C7GfCeVMHo@public.gmane.org>
  2016-12-28  2:27   ` Yu, Xiangliang
@ 2016-12-31  6:53   ` Alex Deucher
       [not found]     ` <CADnq5_MyKwYUfEAtkUgSjLZMbGNbmc_n3pzCwG=B8B2Xpfw+Zw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  1 sibling, 1 reply; 14+ messages in thread
From: Alex Deucher @ 2016-12-31  6:53 UTC (permalink / raw)
  To: Xiangliang Yu; +Cc: Monk Liu, amd-gfx list

On Fri, Dec 23, 2016 at 2:08 AM, Xiangliang Yu <Xiangliang.Yu@amd.com> wrote:
> KIQ is queue-memory based initialization method: setup KIQ queue
> firstly, then send command to KIQ to setup other queues, without
> accessing registers.
>
> For virtualization, need KIQ to access virtual function registers
> when running on guest mode.
>
> changes in v2:
> 1. use amdgpu_bo_create/free_kernel to allocate OB.
>
> Signed-off-by: Monk Liu <Monk.Liu@amd.com>
> Signed-off-by: Xiangliang Yu <Xiangliang.Yu@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h   |  13 +
>  drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 607 +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/amd/amdgpu/vid.h      |   2 +
>  3 files changed, 620 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 9ea5bf0..c392882 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -186,6 +186,11 @@ enum amdgpu_thermal_irq {
>         AMDGPU_THERMAL_IRQ_LAST
>  };
>
> +enum amdgpu_kiq_irq {
> +       AMDGPU_CP_KIQ_IRQ_DRIVER0 = 0,
> +       AMDGPU_CP_KIQ_IRQ_LAST
> +};

Is there a reason to make this a separate enum rather than just adding
it to amdgpu_cp_irq?

> +
>  int amdgpu_set_clockgating_state(struct amdgpu_device *adev,
>                                   enum amd_ip_block_type block_type,
>                                   enum amd_clockgating_state state);
> @@ -778,6 +783,13 @@ struct amdgpu_mec {
>         u32 num_queue;
>  };
>
> +struct amdgpu_kiq {
> +       u64                     eop_gpu_addr;
> +       struct amdgpu_bo        *eop_obj;
> +       struct amdgpu_ring      ring;
> +       struct amdgpu_irq_src   irq;
> +};
> +
>  /*
>   * GPU scratch registers structures, functions & helpers
>   */
> @@ -853,6 +865,7 @@ struct amdgpu_gfx {
>         struct amdgpu_gca_config        config;
>         struct amdgpu_rlc               rlc;
>         struct amdgpu_mec               mec;
> +       struct amdgpu_kiq               kiq;
>         struct amdgpu_scratch           scratch;
>         const struct firmware           *me_fw; /* ME firmware */
>         uint32_t                        me_fw_version;
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> index c3e6bfc..a233eeb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> @@ -1367,6 +1367,42 @@ static void gfx_v8_0_mec_fini(struct amdgpu_device *adev)
>         }
>  }
>
> +static int gfx_v8_0_kiq_init_ring(struct amdgpu_device *adev,
> +                                 struct amdgpu_ring *ring,
> +                                 struct amdgpu_irq_src *irq)
> +{
> +       int r = 0;
> +
> +       ring->adev = NULL;
> +       ring->ring_obj = NULL;
> +       ring->use_doorbell = true;
> +       ring->doorbell_index = AMDGPU_DOORBELL_KIQ;
> +       if (adev->gfx.mec2_fw) {
> +               ring->me = 2;
> +               ring->pipe = 0;
> +       } else {
> +               ring->me = 1;
> +               ring->pipe = 1;
> +       }
> +
> +       irq->data = ring;
> +       ring->queue = 0;
> +       sprintf(ring->name, "kiq %d.%d.%d", ring->me, ring->pipe, ring->queue);
> +       r = amdgpu_ring_init(adev, ring, 1024,
> +                            irq, AMDGPU_CP_KIQ_IRQ_DRIVER0);
> +       if (r)
> +               dev_warn(adev->dev, "(%d) failed to init kiq ring\n", r);
> +
> +       return r;
> +}
> +
> +static void gfx_v8_0_kiq_free_ring(struct amdgpu_ring *ring,
> +                                  struct amdgpu_irq_src *irq)
> +{
> +       amdgpu_ring_fini(ring);
> +       irq->data = NULL;
> +}
> +
>  #define MEC_HPD_SIZE 2048
>
>  static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
> @@ -1421,6 +1457,35 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
>         return 0;
>  }
>
> +static void gfx_v8_0_kiq_fini(struct amdgpu_device *adev)
> +{
> +       struct amdgpu_kiq *kiq = &adev->gfx.kiq;
> +
> +       amdgpu_bo_free_kernel(&kiq->eop_obj, &kiq->eop_gpu_addr, NULL);
> +       kiq->eop_obj = NULL;
> +}
> +
> +static int gfx_v8_0_kiq_init(struct amdgpu_device *adev)
> +{
> +       int r;
> +       u32 *hpd;
> +       struct amdgpu_kiq *kiq = &adev->gfx.kiq;
> +
> +       r = amdgpu_bo_create_kernel(adev, MEC_HPD_SIZE, PAGE_SIZE,
> +                                   AMDGPU_GEM_DOMAIN_GTT, &kiq->eop_obj,
> +                                   &kiq->eop_gpu_addr, (void **)&hpd);
> +       if (r) {
> +               dev_warn(adev->dev, "failed to create KIQ bo (%d).\n", r);
> +               return r;
> +       }
> +
> +       memset(hpd, 0, MEC_HPD_SIZE);
> +
> +       amdgpu_bo_kunmap(kiq->eop_obj);
> +
> +       return 0;
> +}
> +
>  static const u32 vgpr_init_compute_shader[] =
>  {
>         0x7e000209, 0x7e020208,
> @@ -1997,8 +2062,14 @@ static int gfx_v8_0_sw_init(void *handle)
>  {
>         int i, r;
>         struct amdgpu_ring *ring;
> +       struct amdgpu_kiq *kiq;
>         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
>
> +       /* KIQ event */
> +       r = amdgpu_irq_add_id(adev, 178, &adev->gfx.kiq.irq);
> +       if (r)
> +               return r;
> +
>         /* EOP Event */
>         r = amdgpu_irq_add_id(adev, 181, &adev->gfx.eop_irq);
>         if (r)
> @@ -2036,6 +2107,17 @@ static int gfx_v8_0_sw_init(void *handle)
>                 return r;
>         }
>
> +       r = gfx_v8_0_kiq_init(adev);
> +       if (r) {
> +               DRM_ERROR("Failed to init KIQ BOs!\n");
> +               return r;
> +       }
> +
> +       kiq = &adev->gfx.kiq;
> +       r = gfx_v8_0_kiq_init_ring(adev, &kiq->ring, &kiq->irq);
> +       if (r)
> +               return r;
> +
>         /* set up the gfx ring */
>         for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
>                 ring = &adev->gfx.gfx_ring[i];
> @@ -2119,7 +2201,9 @@ static int gfx_v8_0_sw_fini(void *handle)
>                 amdgpu_ring_fini(&adev->gfx.gfx_ring[i]);
>         for (i = 0; i < adev->gfx.num_compute_rings; i++)
>                 amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
> +       gfx_v8_0_kiq_free_ring(&adev->gfx.kiq.ring, &adev->gfx.kiq.irq);
>
> +       gfx_v8_0_kiq_fini(adev);
>         gfx_v8_0_mec_fini(adev);
>         gfx_v8_0_rlc_fini(adev);
>         gfx_v8_0_free_microcode(adev);
> @@ -4506,6 +4590,393 @@ static void gfx_v8_0_cp_compute_fini(struct amdgpu_device *adev)
>         }
>  }
>
> +/* KIQ functions */
> +static void gfx_v8_0_kiq_setting(struct amdgpu_ring *ring)
> +{
> +       uint32_t tmp;
> +       struct amdgpu_device *adev = ring->adev;
> +
> +       /* tell RLC which is KIQ queue */
> +       tmp = RREG32(mmRLC_CP_SCHEDULERS);
> +       tmp &= 0xffffff00;
> +       tmp |= (ring->me << 5) | (ring->pipe << 3) | (ring->queue);
> +       WREG32(mmRLC_CP_SCHEDULERS, tmp);
> +       tmp |= 0x80;
> +       WREG32(mmRLC_CP_SCHEDULERS, tmp);
> +}
> +
> +static void gfx_v8_0_kiq_enable(struct amdgpu_ring *ring)
> +{
> +       amdgpu_ring_alloc(ring, 8);
> +       /* set resources */
> +       amdgpu_ring_write(ring, PACKET3(PACKET3_SET_RESOURCES, 6));
> +       amdgpu_ring_write(ring, 0);     /* vmid_mask:0 queue_type:0 (KIQ) */
> +       amdgpu_ring_write(ring, 0x000000FF);    /* queue mask lo */
> +       amdgpu_ring_write(ring, 0);     /* queue mask hi */
> +       amdgpu_ring_write(ring, 0);     /* gws mask lo */
> +       amdgpu_ring_write(ring, 0);     /* gws mask hi */
> +       amdgpu_ring_write(ring, 0);     /* oac mask */
> +       amdgpu_ring_write(ring, 0);     /* gds heap base:0, gds heap size:0 */
> +       amdgpu_ring_commit(ring);
> +       udelay(50);
> +}
> +
> +static void gfx_v8_0_map_queue_enable(struct amdgpu_ring *kiq_ring,
> +                                  struct amdgpu_ring *ring)
> +{
> +       struct amdgpu_device *adev = kiq_ring->adev;
> +       uint64_t mqd_addr, wptr_addr;
> +
> +       mqd_addr = amdgpu_bo_gpu_offset(ring->mqd_obj);
> +       wptr_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
> +       amdgpu_ring_alloc(kiq_ring, 8);
> +
> +       amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_MAP_QUEUES, 5));
> +       /* Q_sel:0, vmid:0, vidmem: 1, engine:0, num_Q:1*/
> +       amdgpu_ring_write(kiq_ring, 0x21010000);
> +       amdgpu_ring_write(kiq_ring, (ring->doorbell_index << 2) |
> +                       (ring->queue << 26) |
> +                       (ring->pipe << 29) |
> +                       ((ring->me == 1 ? 0 : 1) << 31)); /* doorbell */
> +       amdgpu_ring_write(kiq_ring, lower_32_bits(mqd_addr));
> +       amdgpu_ring_write(kiq_ring, upper_32_bits(mqd_addr));
> +       amdgpu_ring_write(kiq_ring, lower_32_bits(wptr_addr));
> +       amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
> +       amdgpu_ring_commit(kiq_ring);
> +       udelay(50);
> +}
> +
> +static int gfx_v8_0_mqd_init(struct amdgpu_device *adev,
> +                            struct vi_mqd *mqd,
> +                            uint64_t mqd_gpu_addr,
> +                            uint64_t eop_gpu_addr,
> +                            struct amdgpu_ring *ring)
> +{
> +       uint64_t hqd_gpu_addr, wb_gpu_addr, eop_base_addr;
> +       uint32_t tmp;
> +
> +       mqd->header = 0xC0310800;
> +       mqd->compute_pipelinestat_enable = 0x00000001;
> +       mqd->compute_static_thread_mgmt_se0 = 0xffffffff;
> +       mqd->compute_static_thread_mgmt_se1 = 0xffffffff;
> +       mqd->compute_static_thread_mgmt_se2 = 0xffffffff;
> +       mqd->compute_static_thread_mgmt_se3 = 0xffffffff;
> +       mqd->compute_misc_reserved = 0x00000003;
> +
> +       eop_base_addr = eop_gpu_addr >> 8;
> +       mqd->cp_hqd_eop_base_addr_lo = eop_base_addr;
> +       mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr);
> +
> +       /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
> +       tmp = RREG32(mmCP_HQD_EOP_CONTROL);
> +       tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
> +                       (order_base_2(MEC_HPD_SIZE / 4) - 1));
> +
> +       mqd->cp_hqd_eop_control = tmp;
> +
> +       /* enable doorbell? */
> +       tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
> +
> +       if (ring->use_doorbell)
> +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> +                                        DOORBELL_EN, 1);
> +       else
> +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> +                                        DOORBELL_EN, 0);
> +
> +       mqd->cp_hqd_pq_doorbell_control = tmp;
> +
> +       /* disable the queue if it's active */
> +       mqd->cp_hqd_dequeue_request = 0;
> +       mqd->cp_hqd_pq_rptr = 0;
> +       mqd->cp_hqd_pq_wptr = 0;
> +
> +       /* set the pointer to the MQD */
> +       mqd->cp_mqd_base_addr_lo = mqd_gpu_addr & 0xfffffffc;
> +       mqd->cp_mqd_base_addr_hi = upper_32_bits(mqd_gpu_addr);
> +
> +       /* set MQD vmid to 0 */
> +       tmp = RREG32(mmCP_MQD_CONTROL);
> +       tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0);
> +       mqd->cp_mqd_control = tmp;
> +
> +       /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
> +       hqd_gpu_addr = ring->gpu_addr >> 8;
> +       mqd->cp_hqd_pq_base_lo = hqd_gpu_addr;
> +       mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr);
> +
> +       /* set up the HQD, this is similar to CP_RB0_CNTL */
> +       tmp = RREG32(mmCP_HQD_PQ_CONTROL);
> +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE,
> +                           (order_base_2(ring->ring_size / 4) - 1));
> +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE,
> +                       ((order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1) << 8));
> +#ifdef __BIG_ENDIAN
> +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1);
> +#endif
> +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0);
> +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ROQ_PQ_IB_FLIP, 0);
> +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1);
> +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1);
> +       mqd->cp_hqd_pq_control = tmp;
> +
> +       /* set the wb address whether it's enabled or not */
> +       wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
> +       mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc;
> +       mqd->cp_hqd_pq_rptr_report_addr_hi =
> +               upper_32_bits(wb_gpu_addr) & 0xffff;
> +
> +       /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
> +       wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
> +       mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc;
> +       mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff;
> +
> +       tmp = 0;
> +       /* enable the doorbell if requested */
> +       if (ring->use_doorbell) {
> +               tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
> +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> +                               DOORBELL_OFFSET, ring->doorbell_index);
> +
> +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> +                                        DOORBELL_EN, 1);
> +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> +                                        DOORBELL_SOURCE, 0);
> +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> +                                        DOORBELL_HIT, 0);
> +       }
> +
> +       mqd->cp_hqd_pq_doorbell_control = tmp;
> +
> +       /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
> +       ring->wptr = 0;
> +       mqd->cp_hqd_pq_wptr = ring->wptr;
> +       mqd->cp_hqd_pq_rptr = RREG32(mmCP_HQD_PQ_RPTR);
> +
> +       /* set the vmid for the queue */
> +       mqd->cp_hqd_vmid = 0;
> +
> +       tmp = RREG32(mmCP_HQD_PERSISTENT_STATE);
> +       tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53);
> +       mqd->cp_hqd_persistent_state = tmp;
> +
> +       /* activate the queue */
> +       mqd->cp_hqd_active = 1;
> +
> +       return 0;
> +}
> +
> +static int gfx_v8_0_kiq_init_register(struct amdgpu_device *adev,
> +                                     struct vi_mqd *mqd,
> +                                     struct amdgpu_ring *ring)
> +{
> +       uint32_t tmp;
> +       int j;
> +
> +       /* disable wptr polling */
> +       tmp = RREG32(mmCP_PQ_WPTR_POLL_CNTL);
> +       tmp = REG_SET_FIELD(tmp, CP_PQ_WPTR_POLL_CNTL, EN, 0);
> +       WREG32(mmCP_PQ_WPTR_POLL_CNTL, tmp);
> +
> +       WREG32(mmCP_HQD_EOP_BASE_ADDR, mqd->cp_hqd_eop_base_addr_lo);
> +       WREG32(mmCP_HQD_EOP_BASE_ADDR_HI, mqd->cp_hqd_eop_base_addr_hi);
> +
> +       /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
> +       WREG32(mmCP_HQD_EOP_CONTROL, mqd->cp_hqd_eop_control);
> +
> +       /* enable doorbell? */
> +       WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control);
> +
> +       /* disable the queue if it's active */
> +       if (RREG32(mmCP_HQD_ACTIVE) & 1) {
> +               WREG32(mmCP_HQD_DEQUEUE_REQUEST, 1);
> +               for (j = 0; j < adev->usec_timeout; j++) {
> +                       if (!(RREG32(mmCP_HQD_ACTIVE) & 1))
> +                               break;
> +                       udelay(1);
> +               }
> +               WREG32(mmCP_HQD_DEQUEUE_REQUEST, mqd->cp_hqd_dequeue_request);
> +               WREG32(mmCP_HQD_PQ_RPTR, mqd->cp_hqd_pq_rptr);
> +               WREG32(mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);
> +       }
> +
> +       /* set the pointer to the MQD */
> +       WREG32(mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr_lo);
> +       WREG32(mmCP_MQD_BASE_ADDR_HI, mqd->cp_mqd_base_addr_hi);
> +
> +       /* set MQD vmid to 0 */
> +       WREG32(mmCP_MQD_CONTROL, mqd->cp_mqd_control);
> +
> +       /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
> +       WREG32(mmCP_HQD_PQ_BASE, mqd->cp_hqd_pq_base_lo);
> +       WREG32(mmCP_HQD_PQ_BASE_HI, mqd->cp_hqd_pq_base_hi);
> +
> +       /* set up the HQD, this is similar to CP_RB0_CNTL */
> +       WREG32(mmCP_HQD_PQ_CONTROL, mqd->cp_hqd_pq_control);
> +
> +       /* set the wb address whether it's enabled or not */
> +       WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR,
> +                               mqd->cp_hqd_pq_rptr_report_addr_lo);
> +       WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI,
> +                               mqd->cp_hqd_pq_rptr_report_addr_hi);
> +
> +       /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
> +       WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr_lo);
> +       WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, mqd->cp_hqd_pq_wptr_poll_addr_hi);
> +
> +       /* enable the doorbell if requested */
> +       if (ring->use_doorbell) {
> +               if ((adev->asic_type == CHIP_CARRIZO) ||
> +                               (adev->asic_type == CHIP_FIJI) ||
> +                               (adev->asic_type == CHIP_STONEY)) {
> +                       WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
> +                                               AMDGPU_DOORBELL_KIQ << 2);
> +                       WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
> +                                               AMDGPU_DOORBELL_MEC_RING7 << 2);
> +               }
> +       }
> +       WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control);
> +
> +       /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
> +       WREG32(mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);
> +
> +       /* set the vmid for the queue */
> +       WREG32(mmCP_HQD_VMID, mqd->cp_hqd_vmid);
> +
> +       WREG32(mmCP_HQD_PERSISTENT_STATE, mqd->cp_hqd_persistent_state);
> +
> +       /* activate the queue */
> +       WREG32(mmCP_HQD_ACTIVE, mqd->cp_hqd_active);
> +
> +       if (ring->use_doorbell) {
> +               tmp = RREG32(mmCP_PQ_STATUS);
> +               tmp = REG_SET_FIELD(tmp, CP_PQ_STATUS, DOORBELL_ENABLE, 1);
> +               WREG32(mmCP_PQ_STATUS, tmp);
> +       }
> +
> +       return 0;
> +}
> +
> +static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring,
> +                                  struct vi_mqd *mqd,
> +                                  u64 mqd_gpu_addr)
> +{
> +       struct amdgpu_device *adev = ring->adev;
> +       struct amdgpu_kiq *kiq = &adev->gfx.kiq;
> +       uint64_t eop_gpu_addr;
> +       bool is_kiq = false;
> +
> +       if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
> +               is_kiq = true;
> +
> +       if (is_kiq) {
> +               eop_gpu_addr = kiq->eop_gpu_addr;
> +               gfx_v8_0_kiq_setting(&kiq->ring);
> +       } else
> +               eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr +
> +                                       ring->queue * MEC_HPD_SIZE;
> +
> +       mutex_lock(&adev->srbm_mutex);
> +       vi_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
> +
> +       gfx_v8_0_mqd_init(adev, mqd, mqd_gpu_addr, eop_gpu_addr, ring);
> +
> +       if (is_kiq)
> +               gfx_v8_0_kiq_init_register(adev, mqd, ring);
> +
> +       vi_srbm_select(adev, 0, 0, 0, 0);
> +       mutex_unlock(&adev->srbm_mutex);
> +
> +       if (is_kiq)
> +               gfx_v8_0_kiq_enable(ring);
> +       else
> +               gfx_v8_0_map_queue_enable(&kiq->ring, ring);
> +
> +       return 0;
> +}
> +
> +static void gfx_v8_0_kiq_free_queue(struct amdgpu_device *adev)
> +{
> +       struct amdgpu_ring *ring = NULL;
> +       int i;
> +
> +       for (i = 0; i < adev->gfx.num_compute_rings; i++) {
> +               ring = &adev->gfx.compute_ring[i];
> +               amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
> +               ring->mqd_obj = NULL;
> +       }
> +
> +       ring = &adev->gfx.kiq.ring;
> +       amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
> +       ring->mqd_obj = NULL;
> +}
> +
> +static int gfx_v8_0_kiq_setup_queue(struct amdgpu_device *adev,
> +                                   struct amdgpu_ring *ring)
> +{
> +       struct vi_mqd *mqd;
> +       u64 mqd_gpu_addr;
> +       u32 *buf;
> +       int r = 0;
> +
> +       r = amdgpu_bo_create_kernel(adev, sizeof(struct vi_mqd), PAGE_SIZE,
> +                                   AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
> +                                   &mqd_gpu_addr, (void **)&buf);
> +       if (r) {
> +               dev_warn(adev->dev, "failed to create ring mqd ob (%d)", r);
> +               return r;
> +       }
> +
> +       /* init the mqd struct */
> +       memset(buf, 0, sizeof(struct vi_mqd));
> +       mqd = (struct vi_mqd *)buf;
> +
> +       r = gfx_v8_0_kiq_init_queue(ring, mqd, mqd_gpu_addr);
> +       if (r)
> +               return r;
> +
> +       amdgpu_bo_kunmap(ring->mqd_obj);
> +
> +       return 0;
> +}
> +
> +static int gfx_v8_0_kiq_resume(struct amdgpu_device *adev)
> +{
> +       struct amdgpu_ring *ring = NULL;
> +       int r, i;
> +
> +       ring = &adev->gfx.kiq.ring;
> +       r = gfx_v8_0_kiq_setup_queue(adev, ring);
> +       if (r)
> +               return r;
> +
> +       for (i = 0; i < adev->gfx.num_compute_rings; i++) {
> +               ring = &adev->gfx.compute_ring[i];
> +               r = gfx_v8_0_kiq_setup_queue(adev, ring);
> +               if (r)
> +                       return r;
> +       }
> +
> +       gfx_v8_0_cp_compute_enable(adev, true);
> +
> +       for (i = 0; i < adev->gfx.num_compute_rings; i++) {
> +               ring = &adev->gfx.compute_ring[i];
> +
> +               ring->ready = true;
> +               r = amdgpu_ring_test_ring(ring);
> +               if (r)
> +                       ring->ready = false;
> +       }
> +
> +       ring = &adev->gfx.kiq.ring;
> +       ring->ready = true;
> +       r = amdgpu_ring_test_ring(ring);
> +       if (r)
> +               ring->ready = false;
> +
> +       return 0;
> +}
> +
>  static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
>  {
>         int r, i, j;
> @@ -4806,7 +5277,10 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
>         if (r)
>                 return r;
>
> -       r = gfx_v8_0_cp_compute_resume(adev);
> +       if (amdgpu_sriov_vf(adev))
> +               r = gfx_v8_0_kiq_resume(adev);
> +       else
> +               r = gfx_v8_0_cp_compute_resume(adev);

Is there any reason why we shouldn't use KIQ for the non-sr-iov case
as well?  I think KIQ is used to manage the compute rings in other
OSes.  Doesn't necessarily have to happen now, but we should look into
it.

>         if (r)
>                 return r;
>
> @@ -4845,6 +5319,7 @@ static int gfx_v8_0_hw_fini(void *handle)
>         amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
>         amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
>         if (amdgpu_sriov_vf(adev)) {
> +               gfx_v8_0_kiq_free_queue(adev);
>                 pr_debug("For SRIOV client, shouldn't do anything.\n");
>                 return 0;
>         }
> @@ -6011,7 +6486,8 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
>  {
>         u32 ref_and_mask, reg_mem_engine;
>
> -       if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
> +       if ((ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) ||
> +           (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)) {
>                 switch (ring->me) {
>                 case 1:
>                         ref_and_mask = GPU_HDP_FLUSH_DONE__CP2_MASK << ring->pipe;
> @@ -6224,6 +6700,32 @@ static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
>         amdgpu_ring_write(ring, upper_32_bits(seq));
>  }
>
> +static void gfx_v8_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
> +                                        u64 seq, unsigned int flags)
> +{
> +       /* we only allocate 32bit for each seq wb address */
> +       if (flags & AMDGPU_FENCE_FLAG_64BIT)
> +               BUG();
> +
> +       /* write fence seq to the "addr" */
> +       amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
> +       amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
> +                                WRITE_DATA_DST_SEL(5) | WR_CONFIRM));
> +       amdgpu_ring_write(ring, lower_32_bits(addr));
> +       amdgpu_ring_write(ring, upper_32_bits(addr));
> +       amdgpu_ring_write(ring, lower_32_bits(seq));
> +
> +       if (flags & AMDGPU_FENCE_FLAG_INT) {
> +               /* set register to trigger INT */
> +               amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
> +               amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
> +                                        WRITE_DATA_DST_SEL(0) | WR_CONFIRM));
> +               amdgpu_ring_write(ring, mmCPC_INT_STATUS);
> +               amdgpu_ring_write(ring, 0);
> +               amdgpu_ring_write(ring, 0x20000000); /* src_id is 178 */
> +       }
> +}
> +
>  static void gfx_v8_ring_emit_sb(struct amdgpu_ring *ring)
>  {
>         amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
> @@ -6405,6 +6907,72 @@ static int gfx_v8_0_priv_inst_irq(struct amdgpu_device *adev,
>         return 0;
>  }
>
> +static int gfx_v8_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
> +                                           struct amdgpu_irq_src *src,
> +                                           unsigned int type,
> +                                           enum amdgpu_interrupt_state state)
> +{
> +       uint32_t tmp, target;
> +       struct amdgpu_ring *ring = (struct amdgpu_ring *)src->data;
> +
> +       BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
> +
> +       if (ring->me == 1)
> +               target = mmCP_ME1_PIPE0_INT_CNTL;
> +       else
> +               target = mmCP_ME2_PIPE0_INT_CNTL;
> +       target += ring->pipe;
> +
> +       switch (type) {
> +       case AMDGPU_CP_KIQ_IRQ_DRIVER0:
> +               if (state == AMDGPU_IRQ_STATE_DISABLE) {
> +                       tmp = RREG32(mmCPC_INT_CNTL);
> +                       tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
> +                                                GENERIC2_INT_ENABLE, 0);
> +                       WREG32(mmCPC_INT_CNTL, tmp);
> +
> +                       tmp = RREG32(target);
> +                       tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
> +                                                GENERIC2_INT_ENABLE, 0);
> +                       WREG32(target, tmp);
> +               } else {
> +                       tmp = RREG32(mmCPC_INT_CNTL);
> +                       tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
> +                                                GENERIC2_INT_ENABLE, 1);
> +                       WREG32(mmCPC_INT_CNTL, tmp);
> +
> +                       tmp = RREG32(target);
> +                       tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
> +                                                GENERIC2_INT_ENABLE, 1);
> +                       WREG32(target, tmp);
> +               }
> +               break;
> +       default:
> +               BUG(); /* kiq only support GENERIC2_INT now */
> +               break;
> +       }
> +       return 0;
> +}
> +
> +static int gfx_v8_0_kiq_irq(struct amdgpu_device *adev,
> +                           struct amdgpu_irq_src *source,
> +                           struct amdgpu_iv_entry *entry)
> +{
> +       u8 me_id, pipe_id, queue_id;
> +       struct amdgpu_ring *ring = (struct amdgpu_ring *)source->data;
> +
> +       BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
> +
> +       me_id = (entry->ring_id & 0x0c) >> 2;
> +       pipe_id = (entry->ring_id & 0x03) >> 0;
> +       queue_id = (entry->ring_id & 0x70) >> 4;
> +       DRM_DEBUG("IH: CPC GENERIC2_INT, me:%d, pipe:%d, queue:%d\n",
> +                  me_id, pipe_id, queue_id);
> +
> +       amdgpu_fence_process(ring);
> +       return 0;
> +}
> +
>  static const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
>         .name = "gfx_v8_0",
>         .early_init = gfx_v8_0_early_init,
> @@ -6485,10 +7053,37 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
>         .pad_ib = amdgpu_ring_generic_pad_ib,
>  };
>
> +static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_kiq = {
> +       .type = AMDGPU_RING_TYPE_KIQ,
> +       .align_mask = 0xff,
> +       .nop = PACKET3(PACKET3_NOP, 0x3FFF),
> +       .get_rptr = gfx_v8_0_ring_get_rptr,
> +       .get_wptr = gfx_v8_0_ring_get_wptr_compute,
> +       .set_wptr = gfx_v8_0_ring_set_wptr_compute,
> +       .emit_frame_size =
> +               20 + /* gfx_v8_0_ring_emit_gds_switch */
> +               7 + /* gfx_v8_0_ring_emit_hdp_flush */
> +               5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
> +               7 + /* gfx_v8_0_ring_emit_pipeline_sync */
> +               17 + /* gfx_v8_0_ring_emit_vm_flush */
> +               7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_kiq x3 for user fence, vm fence */
> +       .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_compute */
> +       .emit_ib = gfx_v8_0_ring_emit_ib_compute,
> +       .emit_fence = gfx_v8_0_ring_emit_fence_kiq,
> +       .emit_hdp_flush = gfx_v8_0_ring_emit_hdp_flush,
> +       .emit_hdp_invalidate = gfx_v8_0_ring_emit_hdp_invalidate,
> +       .test_ring = gfx_v8_0_ring_test_ring,
> +       .test_ib = gfx_v8_0_ring_test_ib,
> +       .insert_nop = amdgpu_ring_insert_nop,
> +       .pad_ib = amdgpu_ring_generic_pad_ib,
> +};
> +
>  static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev)
>  {
>         int i;
>
> +       adev->gfx.kiq.ring.funcs = &gfx_v8_0_ring_funcs_kiq;
> +
>         for (i = 0; i < adev->gfx.num_gfx_rings; i++)
>                 adev->gfx.gfx_ring[i].funcs = &gfx_v8_0_ring_funcs_gfx;
>
> @@ -6511,6 +7106,11 @@ static const struct amdgpu_irq_src_funcs gfx_v8_0_priv_inst_irq_funcs = {
>         .process = gfx_v8_0_priv_inst_irq,
>  };
>
> +static const struct amdgpu_irq_src_funcs gfx_v8_0_kiq_irq_funcs = {
> +       .set = gfx_v8_0_kiq_set_interrupt_state,
> +       .process = gfx_v8_0_kiq_irq,
> +};
> +
>  static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev)
>  {
>         adev->gfx.eop_irq.num_types = AMDGPU_CP_IRQ_LAST;
> @@ -6521,6 +7121,9 @@ static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev)
>
>         adev->gfx.priv_inst_irq.num_types = 1;
>         adev->gfx.priv_inst_irq.funcs = &gfx_v8_0_priv_inst_irq_funcs;
> +
> +       adev->gfx.kiq.irq.num_types = AMDGPU_CP_KIQ_IRQ_LAST;
> +       adev->gfx.kiq.irq.funcs = &gfx_v8_0_kiq_irq_funcs;
>  }
>
>  static void gfx_v8_0_set_rlc_funcs(struct amdgpu_device *adev)
> diff --git a/drivers/gpu/drm/amd/amdgpu/vid.h b/drivers/gpu/drm/amd/amdgpu/vid.h
> index 11746f2..7a3863a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vid.h
> +++ b/drivers/gpu/drm/amd/amdgpu/vid.h
> @@ -360,6 +360,8 @@
>  #define        PACKET3_WAIT_ON_CE_COUNTER                      0x86
>  #define        PACKET3_WAIT_ON_DE_COUNTER_DIFF                 0x88
>  #define        PACKET3_SWITCH_BUFFER                           0x8B
> +#define        PACKET3_SET_RESOURCES                           0xA0
> +#define        PACKET3_MAP_QUEUES                              0xA2
>
>  #define VCE_CMD_NO_OP          0x00000000
>  #define VCE_CMD_END            0x00000001
> --
> 2.7.4
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]     ` <CADnq5_MyKwYUfEAtkUgSjLZMbGNbmc_n3pzCwG=B8B2Xpfw+Zw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2017-01-01 14:38       ` Yu, Xiangliang
  2017-01-01 14:52       ` Yu, Xiangliang
  1 sibling, 0 replies; 14+ messages in thread
From: Yu, Xiangliang @ 2017-01-01 14:38 UTC (permalink / raw)
  To: Alex Deucher; +Cc: Liu, Monk, amd-gfx list

> -----Original Message-----
> From: Alex Deucher [mailto:alexdeucher@gmail.com]
> Sent: Saturday, December 31, 2016 2:54 PM
> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>
> Cc: amd-gfx list <amd-gfx@lists.freedesktop.org>; Liu, Monk
> <Monk.Liu@amd.com>
> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface
> queue(KIQ)
> 
> On Fri, Dec 23, 2016 at 2:08 AM, Xiangliang Yu <Xiangliang.Yu@amd.com>
> wrote:
> > KIQ is queue-memory based initialization method: setup KIQ queue
> > firstly, then send command to KIQ to setup other queues, without
> > accessing registers.
> >
> > For virtualization, need KIQ to access virtual function registers when
> > running on guest mode.
> >
> > changes in v2:
> > 1. use amdgpu_bo_create/free_kernel to allocate OB.
> >
> > Signed-off-by: Monk Liu <Monk.Liu@amd.com>
> > Signed-off-by: Xiangliang Yu <Xiangliang.Yu@amd.com>
> > ---
> >  drivers/gpu/drm/amd/amdgpu/amdgpu.h   |  13 +
> >  drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 607
> +++++++++++++++++++++++++++++++++-
> >  drivers/gpu/drm/amd/amdgpu/vid.h      |   2 +
> >  3 files changed, 620 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > index 9ea5bf0..c392882 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > @@ -186,6 +186,11 @@ enum amdgpu_thermal_irq {
> >         AMDGPU_THERMAL_IRQ_LAST
> >  };
> >
> > +enum amdgpu_kiq_irq {
> > +       AMDGPU_CP_KIQ_IRQ_DRIVER0 = 0,
> > +       AMDGPU_CP_KIQ_IRQ_LAST
> > +};
> 
> Is there a reason to make this a separate enum rather than just adding it to
> amdgpu_cp_irq?
> 
> > +
> >  int amdgpu_set_clockgating_state(struct amdgpu_device *adev,
> >                                   enum amd_ip_block_type block_type,
> >                                   enum amd_clockgating_state state);
> > @@ -778,6 +783,13 @@ struct amdgpu_mec {
> >         u32 num_queue;
> >  };
> >
> > +struct amdgpu_kiq {
> > +       u64                     eop_gpu_addr;
> > +       struct amdgpu_bo        *eop_obj;
> > +       struct amdgpu_ring      ring;
> > +       struct amdgpu_irq_src   irq;
> > +};
> > +
> >  /*
> >   * GPU scratch registers structures, functions & helpers
> >   */
> > @@ -853,6 +865,7 @@ struct amdgpu_gfx {
> >         struct amdgpu_gca_config        config;
> >         struct amdgpu_rlc               rlc;
> >         struct amdgpu_mec               mec;
> > +       struct amdgpu_kiq               kiq;
> >         struct amdgpu_scratch           scratch;
> >         const struct firmware           *me_fw; /* ME firmware */
> >         uint32_t                        me_fw_version;
> > diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> > b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> > index c3e6bfc..a233eeb 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> > @@ -1367,6 +1367,42 @@ static void gfx_v8_0_mec_fini(struct
> amdgpu_device *adev)
> >         }
> >  }
> >
> > +static int gfx_v8_0_kiq_init_ring(struct amdgpu_device *adev,
> > +                                 struct amdgpu_ring *ring,
> > +                                 struct amdgpu_irq_src *irq) {
> > +       int r = 0;
> > +
> > +       ring->adev = NULL;
> > +       ring->ring_obj = NULL;
> > +       ring->use_doorbell = true;
> > +       ring->doorbell_index = AMDGPU_DOORBELL_KIQ;
> > +       if (adev->gfx.mec2_fw) {
> > +               ring->me = 2;
> > +               ring->pipe = 0;
> > +       } else {
> > +               ring->me = 1;
> > +               ring->pipe = 1;
> > +       }
> > +
> > +       irq->data = ring;
> > +       ring->queue = 0;
> > +       sprintf(ring->name, "kiq %d.%d.%d", ring->me, ring->pipe, ring-
> >queue);
> > +       r = amdgpu_ring_init(adev, ring, 1024,
> > +                            irq, AMDGPU_CP_KIQ_IRQ_DRIVER0);
> > +       if (r)
> > +               dev_warn(adev->dev, "(%d) failed to init kiq ring\n",
> > + r);
> > +
> > +       return r;
> > +}
> > +
> > +static void gfx_v8_0_kiq_free_ring(struct amdgpu_ring *ring,
> > +                                  struct amdgpu_irq_src *irq) {
> > +       amdgpu_ring_fini(ring);
> > +       irq->data = NULL;
> > +}
> > +
> >  #define MEC_HPD_SIZE 2048
> >
> >  static int gfx_v8_0_mec_init(struct amdgpu_device *adev) @@ -1421,6
> > +1457,35 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
> >         return 0;
> >  }
> >
> > +static void gfx_v8_0_kiq_fini(struct amdgpu_device *adev) {
> > +       struct amdgpu_kiq *kiq = &adev->gfx.kiq;
> > +
> > +       amdgpu_bo_free_kernel(&kiq->eop_obj, &kiq->eop_gpu_addr,
> NULL);
> > +       kiq->eop_obj = NULL;
> > +}
> > +
> > +static int gfx_v8_0_kiq_init(struct amdgpu_device *adev) {
> > +       int r;
> > +       u32 *hpd;
> > +       struct amdgpu_kiq *kiq = &adev->gfx.kiq;
> > +
> > +       r = amdgpu_bo_create_kernel(adev, MEC_HPD_SIZE, PAGE_SIZE,
> > +                                   AMDGPU_GEM_DOMAIN_GTT, &kiq->eop_obj,
> > +                                   &kiq->eop_gpu_addr, (void **)&hpd);
> > +       if (r) {
> > +               dev_warn(adev->dev, "failed to create KIQ bo (%d).\n", r);
> > +               return r;
> > +       }
> > +
> > +       memset(hpd, 0, MEC_HPD_SIZE);
> > +
> > +       amdgpu_bo_kunmap(kiq->eop_obj);
> > +
> > +       return 0;
> > +}
> > +
> >  static const u32 vgpr_init_compute_shader[] =  {
> >         0x7e000209, 0x7e020208,
> > @@ -1997,8 +2062,14 @@ static int gfx_v8_0_sw_init(void *handle)  {
> >         int i, r;
> >         struct amdgpu_ring *ring;
> > +       struct amdgpu_kiq *kiq;
> >         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> >
> > +       /* KIQ event */
> > +       r = amdgpu_irq_add_id(adev, 178, &adev->gfx.kiq.irq);
> > +       if (r)
> > +               return r;
> > +
> >         /* EOP Event */
> >         r = amdgpu_irq_add_id(adev, 181, &adev->gfx.eop_irq);
> >         if (r)
> > @@ -2036,6 +2107,17 @@ static int gfx_v8_0_sw_init(void *handle)
> >                 return r;
> >         }
> >
> > +       r = gfx_v8_0_kiq_init(adev);
> > +       if (r) {
> > +               DRM_ERROR("Failed to init KIQ BOs!\n");
> > +               return r;
> > +       }
> > +
> > +       kiq = &adev->gfx.kiq;
> > +       r = gfx_v8_0_kiq_init_ring(adev, &kiq->ring, &kiq->irq);
> > +       if (r)
> > +               return r;
> > +
> >         /* set up the gfx ring */
> >         for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
> >                 ring = &adev->gfx.gfx_ring[i]; @@ -2119,7 +2201,9 @@
> > static int gfx_v8_0_sw_fini(void *handle)
> >                 amdgpu_ring_fini(&adev->gfx.gfx_ring[i]);
> >         for (i = 0; i < adev->gfx.num_compute_rings; i++)
> >                 amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
> > +       gfx_v8_0_kiq_free_ring(&adev->gfx.kiq.ring,
> > + &adev->gfx.kiq.irq);
> >
> > +       gfx_v8_0_kiq_fini(adev);
> >         gfx_v8_0_mec_fini(adev);
> >         gfx_v8_0_rlc_fini(adev);
> >         gfx_v8_0_free_microcode(adev); @@ -4506,6 +4590,393 @@ static
> > void gfx_v8_0_cp_compute_fini(struct amdgpu_device *adev)
> >         }
> >  }
> >
> > +/* KIQ functions */
> > +static void gfx_v8_0_kiq_setting(struct amdgpu_ring *ring) {
> > +       uint32_t tmp;
> > +       struct amdgpu_device *adev = ring->adev;
> > +
> > +       /* tell RLC which is KIQ queue */
> > +       tmp = RREG32(mmRLC_CP_SCHEDULERS);
> > +       tmp &= 0xffffff00;
> > +       tmp |= (ring->me << 5) | (ring->pipe << 3) | (ring->queue);
> > +       WREG32(mmRLC_CP_SCHEDULERS, tmp);
> > +       tmp |= 0x80;
> > +       WREG32(mmRLC_CP_SCHEDULERS, tmp); }
> > +
> > +static void gfx_v8_0_kiq_enable(struct amdgpu_ring *ring) {
> > +       amdgpu_ring_alloc(ring, 8);
> > +       /* set resources */
> > +       amdgpu_ring_write(ring, PACKET3(PACKET3_SET_RESOURCES, 6));
> > +       amdgpu_ring_write(ring, 0);     /* vmid_mask:0 queue_type:0 (KIQ) */
> > +       amdgpu_ring_write(ring, 0x000000FF);    /* queue mask lo */
> > +       amdgpu_ring_write(ring, 0);     /* queue mask hi */
> > +       amdgpu_ring_write(ring, 0);     /* gws mask lo */
> > +       amdgpu_ring_write(ring, 0);     /* gws mask hi */
> > +       amdgpu_ring_write(ring, 0);     /* oac mask */
> > +       amdgpu_ring_write(ring, 0);     /* gds heap base:0, gds heap size:0 */
> > +       amdgpu_ring_commit(ring);
> > +       udelay(50);
> > +}
> > +
> > +static void gfx_v8_0_map_queue_enable(struct amdgpu_ring *kiq_ring,
> > +                                  struct amdgpu_ring *ring) {
> > +       struct amdgpu_device *adev = kiq_ring->adev;
> > +       uint64_t mqd_addr, wptr_addr;
> > +
> > +       mqd_addr = amdgpu_bo_gpu_offset(ring->mqd_obj);
> > +       wptr_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
> > +       amdgpu_ring_alloc(kiq_ring, 8);
> > +
> > +       amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_MAP_QUEUES, 5));
> > +       /* Q_sel:0, vmid:0, vidmem: 1, engine:0, num_Q:1*/
> > +       amdgpu_ring_write(kiq_ring, 0x21010000);
> > +       amdgpu_ring_write(kiq_ring, (ring->doorbell_index << 2) |
> > +                       (ring->queue << 26) |
> > +                       (ring->pipe << 29) |
> > +                       ((ring->me == 1 ? 0 : 1) << 31)); /* doorbell */
> > +       amdgpu_ring_write(kiq_ring, lower_32_bits(mqd_addr));
> > +       amdgpu_ring_write(kiq_ring, upper_32_bits(mqd_addr));
> > +       amdgpu_ring_write(kiq_ring, lower_32_bits(wptr_addr));
> > +       amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
> > +       amdgpu_ring_commit(kiq_ring);
> > +       udelay(50);
> > +}
> > +
> > +static int gfx_v8_0_mqd_init(struct amdgpu_device *adev,
> > +                            struct vi_mqd *mqd,
> > +                            uint64_t mqd_gpu_addr,
> > +                            uint64_t eop_gpu_addr,
> > +                            struct amdgpu_ring *ring) {
> > +       uint64_t hqd_gpu_addr, wb_gpu_addr, eop_base_addr;
> > +       uint32_t tmp;
> > +
> > +       mqd->header = 0xC0310800;
> > +       mqd->compute_pipelinestat_enable = 0x00000001;
> > +       mqd->compute_static_thread_mgmt_se0 = 0xffffffff;
> > +       mqd->compute_static_thread_mgmt_se1 = 0xffffffff;
> > +       mqd->compute_static_thread_mgmt_se2 = 0xffffffff;
> > +       mqd->compute_static_thread_mgmt_se3 = 0xffffffff;
> > +       mqd->compute_misc_reserved = 0x00000003;
> > +
> > +       eop_base_addr = eop_gpu_addr >> 8;
> > +       mqd->cp_hqd_eop_base_addr_lo = eop_base_addr;
> > +       mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr);
> > +
> > +       /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
> > +       tmp = RREG32(mmCP_HQD_EOP_CONTROL);
> > +       tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
> > +                       (order_base_2(MEC_HPD_SIZE / 4) - 1));
> > +
> > +       mqd->cp_hqd_eop_control = tmp;
> > +
> > +       /* enable doorbell? */
> > +       tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
> > +
> > +       if (ring->use_doorbell)
> > +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> > +                                        DOORBELL_EN, 1);
> > +       else
> > +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> > +                                        DOORBELL_EN, 0);
> > +
> > +       mqd->cp_hqd_pq_doorbell_control = tmp;
> > +
> > +       /* disable the queue if it's active */
> > +       mqd->cp_hqd_dequeue_request = 0;
> > +       mqd->cp_hqd_pq_rptr = 0;
> > +       mqd->cp_hqd_pq_wptr = 0;
> > +
> > +       /* set the pointer to the MQD */
> > +       mqd->cp_mqd_base_addr_lo = mqd_gpu_addr & 0xfffffffc;
> > +       mqd->cp_mqd_base_addr_hi = upper_32_bits(mqd_gpu_addr);
> > +
> > +       /* set MQD vmid to 0 */
> > +       tmp = RREG32(mmCP_MQD_CONTROL);
> > +       tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0);
> > +       mqd->cp_mqd_control = tmp;
> > +
> > +       /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
> > +       hqd_gpu_addr = ring->gpu_addr >> 8;
> > +       mqd->cp_hqd_pq_base_lo = hqd_gpu_addr;
> > +       mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr);
> > +
> > +       /* set up the HQD, this is similar to CP_RB0_CNTL */
> > +       tmp = RREG32(mmCP_HQD_PQ_CONTROL);
> > +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE,
> > +                           (order_base_2(ring->ring_size / 4) - 1));
> > +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL,
> RPTR_BLOCK_SIZE,
> > +                       ((order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1)
> > +<< 8)); #ifdef __BIG_ENDIAN
> > +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP,
> 1);
> > +#endif
> > +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL,
> UNORD_DISPATCH, 0);
> > +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ROQ_PQ_IB_FLIP,
> 0);
> > +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1);
> > +       tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1);
> > +       mqd->cp_hqd_pq_control = tmp;
> > +
> > +       /* set the wb address whether it's enabled or not */
> > +       wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
> > +       mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc;
> > +       mqd->cp_hqd_pq_rptr_report_addr_hi =
> > +               upper_32_bits(wb_gpu_addr) & 0xffff;
> > +
> > +       /* only used if
> CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
> > +       wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
> > +       mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc;
> > +       mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr)
> > + & 0xffff;
> > +
> > +       tmp = 0;
> > +       /* enable the doorbell if requested */
> > +       if (ring->use_doorbell) {
> > +               tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
> > +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> > +                               DOORBELL_OFFSET,
> > + ring->doorbell_index);
> > +
> > +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> > +                                        DOORBELL_EN, 1);
> > +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> > +                                        DOORBELL_SOURCE, 0);
> > +               tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
> > +                                        DOORBELL_HIT, 0);
> > +       }
> > +
> > +       mqd->cp_hqd_pq_doorbell_control = tmp;
> > +
> > +       /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
> > +       ring->wptr = 0;
> > +       mqd->cp_hqd_pq_wptr = ring->wptr;
> > +       mqd->cp_hqd_pq_rptr = RREG32(mmCP_HQD_PQ_RPTR);
> > +
> > +       /* set the vmid for the queue */
> > +       mqd->cp_hqd_vmid = 0;
> > +
> > +       tmp = RREG32(mmCP_HQD_PERSISTENT_STATE);
> > +       tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE,
> PRELOAD_SIZE, 0x53);
> > +       mqd->cp_hqd_persistent_state = tmp;
> > +
> > +       /* activate the queue */
> > +       mqd->cp_hqd_active = 1;
> > +
> > +       return 0;
> > +}
> > +
> > +static int gfx_v8_0_kiq_init_register(struct amdgpu_device *adev,
> > +                                     struct vi_mqd *mqd,
> > +                                     struct amdgpu_ring *ring) {
> > +       uint32_t tmp;
> > +       int j;
> > +
> > +       /* disable wptr polling */
> > +       tmp = RREG32(mmCP_PQ_WPTR_POLL_CNTL);
> > +       tmp = REG_SET_FIELD(tmp, CP_PQ_WPTR_POLL_CNTL, EN, 0);
> > +       WREG32(mmCP_PQ_WPTR_POLL_CNTL, tmp);
> > +
> > +       WREG32(mmCP_HQD_EOP_BASE_ADDR, mqd-
> >cp_hqd_eop_base_addr_lo);
> > +       WREG32(mmCP_HQD_EOP_BASE_ADDR_HI,
> > + mqd->cp_hqd_eop_base_addr_hi);
> > +
> > +       /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
> > +       WREG32(mmCP_HQD_EOP_CONTROL, mqd->cp_hqd_eop_control);
> > +
> > +       /* enable doorbell? */
> > +       WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL,
> > + mqd->cp_hqd_pq_doorbell_control);
> > +
> > +       /* disable the queue if it's active */
> > +       if (RREG32(mmCP_HQD_ACTIVE) & 1) {
> > +               WREG32(mmCP_HQD_DEQUEUE_REQUEST, 1);
> > +               for (j = 0; j < adev->usec_timeout; j++) {
> > +                       if (!(RREG32(mmCP_HQD_ACTIVE) & 1))
> > +                               break;
> > +                       udelay(1);
> > +               }
> > +               WREG32(mmCP_HQD_DEQUEUE_REQUEST, mqd-
> >cp_hqd_dequeue_request);
> > +               WREG32(mmCP_HQD_PQ_RPTR, mqd->cp_hqd_pq_rptr);
> > +               WREG32(mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);
> > +       }
> > +
> > +       /* set the pointer to the MQD */
> > +       WREG32(mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr_lo);
> > +       WREG32(mmCP_MQD_BASE_ADDR_HI, mqd-
> >cp_mqd_base_addr_hi);
> > +
> > +       /* set MQD vmid to 0 */
> > +       WREG32(mmCP_MQD_CONTROL, mqd->cp_mqd_control);
> > +
> > +       /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
> > +       WREG32(mmCP_HQD_PQ_BASE, mqd->cp_hqd_pq_base_lo);
> > +       WREG32(mmCP_HQD_PQ_BASE_HI, mqd->cp_hqd_pq_base_hi);
> > +
> > +       /* set up the HQD, this is similar to CP_RB0_CNTL */
> > +       WREG32(mmCP_HQD_PQ_CONTROL, mqd->cp_hqd_pq_control);
> > +
> > +       /* set the wb address whether it's enabled or not */
> > +       WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR,
> > +                               mqd->cp_hqd_pq_rptr_report_addr_lo);
> > +       WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI,
> > +                               mqd->cp_hqd_pq_rptr_report_addr_hi);
> > +
> > +       /* only used if
> CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
> > +       WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd-
> >cp_hqd_pq_wptr_poll_addr_lo);
> > +       WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR_HI,
> > + mqd->cp_hqd_pq_wptr_poll_addr_hi);
> > +
> > +       /* enable the doorbell if requested */
> > +       if (ring->use_doorbell) {
> > +               if ((adev->asic_type == CHIP_CARRIZO) ||
> > +                               (adev->asic_type == CHIP_FIJI) ||
> > +                               (adev->asic_type == CHIP_STONEY)) {
> > +                       WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
> > +                                               AMDGPU_DOORBELL_KIQ << 2);
> > +                       WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
> > +                                               AMDGPU_DOORBELL_MEC_RING7 << 2);
> > +               }
> > +       }
> > +       WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL,
> > + mqd->cp_hqd_pq_doorbell_control);
> > +
> > +       /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
> > +       WREG32(mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);
> > +
> > +       /* set the vmid for the queue */
> > +       WREG32(mmCP_HQD_VMID, mqd->cp_hqd_vmid);
> > +
> > +       WREG32(mmCP_HQD_PERSISTENT_STATE,
> > + mqd->cp_hqd_persistent_state);
> > +
> > +       /* activate the queue */
> > +       WREG32(mmCP_HQD_ACTIVE, mqd->cp_hqd_active);
> > +
> > +       if (ring->use_doorbell) {
> > +               tmp = RREG32(mmCP_PQ_STATUS);
> > +               tmp = REG_SET_FIELD(tmp, CP_PQ_STATUS, DOORBELL_ENABLE,
> 1);
> > +               WREG32(mmCP_PQ_STATUS, tmp);
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring,
> > +                                  struct vi_mqd *mqd,
> > +                                  u64 mqd_gpu_addr) {
> > +       struct amdgpu_device *adev = ring->adev;
> > +       struct amdgpu_kiq *kiq = &adev->gfx.kiq;
> > +       uint64_t eop_gpu_addr;
> > +       bool is_kiq = false;
> > +
> > +       if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
> > +               is_kiq = true;
> > +
> > +       if (is_kiq) {
> > +               eop_gpu_addr = kiq->eop_gpu_addr;
> > +               gfx_v8_0_kiq_setting(&kiq->ring);
> > +       } else
> > +               eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr +
> > +                                       ring->queue * MEC_HPD_SIZE;
> > +
> > +       mutex_lock(&adev->srbm_mutex);
> > +       vi_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
> > +
> > +       gfx_v8_0_mqd_init(adev, mqd, mqd_gpu_addr, eop_gpu_addr,
> > + ring);
> > +
> > +       if (is_kiq)
> > +               gfx_v8_0_kiq_init_register(adev, mqd, ring);
> > +
> > +       vi_srbm_select(adev, 0, 0, 0, 0);
> > +       mutex_unlock(&adev->srbm_mutex);
> > +
> > +       if (is_kiq)
> > +               gfx_v8_0_kiq_enable(ring);
> > +       else
> > +               gfx_v8_0_map_queue_enable(&kiq->ring, ring);
> > +
> > +       return 0;
> > +}
> > +
> > +static void gfx_v8_0_kiq_free_queue(struct amdgpu_device *adev) {
> > +       struct amdgpu_ring *ring = NULL;
> > +       int i;
> > +
> > +       for (i = 0; i < adev->gfx.num_compute_rings; i++) {
> > +               ring = &adev->gfx.compute_ring[i];
> > +               amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
> > +               ring->mqd_obj = NULL;
> > +       }
> > +
> > +       ring = &adev->gfx.kiq.ring;
> > +       amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
> > +       ring->mqd_obj = NULL;
> > +}
> > +
> > +static int gfx_v8_0_kiq_setup_queue(struct amdgpu_device *adev,
> > +                                   struct amdgpu_ring *ring) {
> > +       struct vi_mqd *mqd;
> > +       u64 mqd_gpu_addr;
> > +       u32 *buf;
> > +       int r = 0;
> > +
> > +       r = amdgpu_bo_create_kernel(adev, sizeof(struct vi_mqd),
> PAGE_SIZE,
> > +                                   AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
> > +                                   &mqd_gpu_addr, (void **)&buf);
> > +       if (r) {
> > +               dev_warn(adev->dev, "failed to create ring mqd ob (%d)", r);
> > +               return r;
> > +       }
> > +
> > +       /* init the mqd struct */
> > +       memset(buf, 0, sizeof(struct vi_mqd));
> > +       mqd = (struct vi_mqd *)buf;
> > +
> > +       r = gfx_v8_0_kiq_init_queue(ring, mqd, mqd_gpu_addr);
> > +       if (r)
> > +               return r;
> > +
> > +       amdgpu_bo_kunmap(ring->mqd_obj);
> > +
> > +       return 0;
> > +}
> > +
> > +static int gfx_v8_0_kiq_resume(struct amdgpu_device *adev) {
> > +       struct amdgpu_ring *ring = NULL;
> > +       int r, i;
> > +
> > +       ring = &adev->gfx.kiq.ring;
> > +       r = gfx_v8_0_kiq_setup_queue(adev, ring);
> > +       if (r)
> > +               return r;
> > +
> > +       for (i = 0; i < adev->gfx.num_compute_rings; i++) {
> > +               ring = &adev->gfx.compute_ring[i];
> > +               r = gfx_v8_0_kiq_setup_queue(adev, ring);
> > +               if (r)
> > +                       return r;
> > +       }
> > +
> > +       gfx_v8_0_cp_compute_enable(adev, true);
> > +
> > +       for (i = 0; i < adev->gfx.num_compute_rings; i++) {
> > +               ring = &adev->gfx.compute_ring[i];
> > +
> > +               ring->ready = true;
> > +               r = amdgpu_ring_test_ring(ring);
> > +               if (r)
> > +                       ring->ready = false;
> > +       }
> > +
> > +       ring = &adev->gfx.kiq.ring;
> > +       ring->ready = true;
> > +       r = amdgpu_ring_test_ring(ring);
> > +       if (r)
> > +               ring->ready = false;
> > +
> > +       return 0;
> > +}
> > +
> >  static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)  {
> >         int r, i, j;
> > @@ -4806,7 +5277,10 @@ static int gfx_v8_0_cp_resume(struct
> amdgpu_device *adev)
> >         if (r)
> >                 return r;
> >
> > -       r = gfx_v8_0_cp_compute_resume(adev);
> > +       if (amdgpu_sriov_vf(adev))
> > +               r = gfx_v8_0_kiq_resume(adev);
> > +       else
> > +               r = gfx_v8_0_cp_compute_resume(adev);
> 
> Is there any reason why we shouldn't use KIQ for the non-sr-iov case as well?
> I think KIQ is used to manage the compute rings in other OSes.  Doesn't
> necessarily have to happen now, but we should look into it.
> 

I have no time to test it on bare metal and no one help me to test it. So right now I use kiq only for sriov and it will not affect bare metal. As kiq is optional feature for bare metal, I'll try it on bare metal after finishing all sriov patches.

> >         if (r)
> >                 return r;
> >
> > @@ -4845,6 +5319,7 @@ static int gfx_v8_0_hw_fini(void *handle)
> >         amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
> >         amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
> >         if (amdgpu_sriov_vf(adev)) {
> > +               gfx_v8_0_kiq_free_queue(adev);
> >                 pr_debug("For SRIOV client, shouldn't do anything.\n");
> >                 return 0;
> >         }
> > @@ -6011,7 +6486,8 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct
> > amdgpu_ring *ring)  {
> >         u32 ref_and_mask, reg_mem_engine;
> >
> > -       if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
> > +       if ((ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) ||
> > +           (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)) {
> >                 switch (ring->me) {
> >                 case 1:
> >                         ref_and_mask = GPU_HDP_FLUSH_DONE__CP2_MASK <<
> > ring->pipe; @@ -6224,6 +6700,32 @@ static void
> gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
> >         amdgpu_ring_write(ring, upper_32_bits(seq));  }
> >
> > +static void gfx_v8_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64
> addr,
> > +                                        u64 seq, unsigned int flags)
> > +{
> > +       /* we only allocate 32bit for each seq wb address */
> > +       if (flags & AMDGPU_FENCE_FLAG_64BIT)
> > +               BUG();
> > +
> > +       /* write fence seq to the "addr" */
> > +       amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
> > +       amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
> > +                                WRITE_DATA_DST_SEL(5) | WR_CONFIRM));
> > +       amdgpu_ring_write(ring, lower_32_bits(addr));
> > +       amdgpu_ring_write(ring, upper_32_bits(addr));
> > +       amdgpu_ring_write(ring, lower_32_bits(seq));
> > +
> > +       if (flags & AMDGPU_FENCE_FLAG_INT) {
> > +               /* set register to trigger INT */
> > +               amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
> > +               amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
> > +                                        WRITE_DATA_DST_SEL(0) | WR_CONFIRM));
> > +               amdgpu_ring_write(ring, mmCPC_INT_STATUS);
> > +               amdgpu_ring_write(ring, 0);
> > +               amdgpu_ring_write(ring, 0x20000000); /* src_id is 178 */
> > +       }
> > +}
> > +
> >  static void gfx_v8_ring_emit_sb(struct amdgpu_ring *ring)  {
> >         amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
> @@
> > -6405,6 +6907,72 @@ static int gfx_v8_0_priv_inst_irq(struct
> amdgpu_device *adev,
> >         return 0;
> >  }
> >
> > +static int gfx_v8_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
> > +                                           struct amdgpu_irq_src *src,
> > +                                           unsigned int type,
> > +                                           enum
> > +amdgpu_interrupt_state state) {
> > +       uint32_t tmp, target;
> > +       struct amdgpu_ring *ring = (struct amdgpu_ring *)src->data;
> > +
> > +       BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
> > +
> > +       if (ring->me == 1)
> > +               target = mmCP_ME1_PIPE0_INT_CNTL;
> > +       else
> > +               target = mmCP_ME2_PIPE0_INT_CNTL;
> > +       target += ring->pipe;
> > +
> > +       switch (type) {
> > +       case AMDGPU_CP_KIQ_IRQ_DRIVER0:
> > +               if (state == AMDGPU_IRQ_STATE_DISABLE) {
> > +                       tmp = RREG32(mmCPC_INT_CNTL);
> > +                       tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
> > +                                                GENERIC2_INT_ENABLE, 0);
> > +                       WREG32(mmCPC_INT_CNTL, tmp);
> > +
> > +                       tmp = RREG32(target);
> > +                       tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
> > +                                                GENERIC2_INT_ENABLE, 0);
> > +                       WREG32(target, tmp);
> > +               } else {
> > +                       tmp = RREG32(mmCPC_INT_CNTL);
> > +                       tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
> > +                                                GENERIC2_INT_ENABLE, 1);
> > +                       WREG32(mmCPC_INT_CNTL, tmp);
> > +
> > +                       tmp = RREG32(target);
> > +                       tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
> > +                                                GENERIC2_INT_ENABLE, 1);
> > +                       WREG32(target, tmp);
> > +               }
> > +               break;
> > +       default:
> > +               BUG(); /* kiq only support GENERIC2_INT now */
> > +               break;
> > +       }
> > +       return 0;
> > +}
> > +
> > +static int gfx_v8_0_kiq_irq(struct amdgpu_device *adev,
> > +                           struct amdgpu_irq_src *source,
> > +                           struct amdgpu_iv_entry *entry) {
> > +       u8 me_id, pipe_id, queue_id;
> > +       struct amdgpu_ring *ring = (struct amdgpu_ring *)source->data;
> > +
> > +       BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
> > +
> > +       me_id = (entry->ring_id & 0x0c) >> 2;
> > +       pipe_id = (entry->ring_id & 0x03) >> 0;
> > +       queue_id = (entry->ring_id & 0x70) >> 4;
> > +       DRM_DEBUG("IH: CPC GENERIC2_INT, me:%d, pipe:%d, queue:%d\n",
> > +                  me_id, pipe_id, queue_id);
> > +
> > +       amdgpu_fence_process(ring);
> > +       return 0;
> > +}
> > +
> >  static const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
> >         .name = "gfx_v8_0",
> >         .early_init = gfx_v8_0_early_init, @@ -6485,10 +7053,37 @@
> > static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
> >         .pad_ib = amdgpu_ring_generic_pad_ib,  };
> >
> > +static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_kiq = {
> > +       .type = AMDGPU_RING_TYPE_KIQ,
> > +       .align_mask = 0xff,
> > +       .nop = PACKET3(PACKET3_NOP, 0x3FFF),
> > +       .get_rptr = gfx_v8_0_ring_get_rptr,
> > +       .get_wptr = gfx_v8_0_ring_get_wptr_compute,
> > +       .set_wptr = gfx_v8_0_ring_set_wptr_compute,
> > +       .emit_frame_size =
> > +               20 + /* gfx_v8_0_ring_emit_gds_switch */
> > +               7 + /* gfx_v8_0_ring_emit_hdp_flush */
> > +               5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
> > +               7 + /* gfx_v8_0_ring_emit_pipeline_sync */
> > +               17 + /* gfx_v8_0_ring_emit_vm_flush */
> > +               7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_kiq x3 for user fence, vm
> fence */
> > +       .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_compute */
> > +       .emit_ib = gfx_v8_0_ring_emit_ib_compute,
> > +       .emit_fence = gfx_v8_0_ring_emit_fence_kiq,
> > +       .emit_hdp_flush = gfx_v8_0_ring_emit_hdp_flush,
> > +       .emit_hdp_invalidate = gfx_v8_0_ring_emit_hdp_invalidate,
> > +       .test_ring = gfx_v8_0_ring_test_ring,
> > +       .test_ib = gfx_v8_0_ring_test_ib,
> > +       .insert_nop = amdgpu_ring_insert_nop,
> > +       .pad_ib = amdgpu_ring_generic_pad_ib, };
> > +
> >  static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev)  {
> >         int i;
> >
> > +       adev->gfx.kiq.ring.funcs = &gfx_v8_0_ring_funcs_kiq;
> > +
> >         for (i = 0; i < adev->gfx.num_gfx_rings; i++)
> >                 adev->gfx.gfx_ring[i].funcs =
> > &gfx_v8_0_ring_funcs_gfx;
> >
> > @@ -6511,6 +7106,11 @@ static const struct amdgpu_irq_src_funcs
> gfx_v8_0_priv_inst_irq_funcs = {
> >         .process = gfx_v8_0_priv_inst_irq,  };
> >
> > +static const struct amdgpu_irq_src_funcs gfx_v8_0_kiq_irq_funcs = {
> > +       .set = gfx_v8_0_kiq_set_interrupt_state,
> > +       .process = gfx_v8_0_kiq_irq,
> > +};
> > +
> >  static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev)  {
> >         adev->gfx.eop_irq.num_types = AMDGPU_CP_IRQ_LAST; @@ -6521,6
> > +7121,9 @@ static void gfx_v8_0_set_irq_funcs(struct amdgpu_device
> > *adev)
> >
> >         adev->gfx.priv_inst_irq.num_types = 1;
> >         adev->gfx.priv_inst_irq.funcs = &gfx_v8_0_priv_inst_irq_funcs;
> > +
> > +       adev->gfx.kiq.irq.num_types = AMDGPU_CP_KIQ_IRQ_LAST;
> > +       adev->gfx.kiq.irq.funcs = &gfx_v8_0_kiq_irq_funcs;
> >  }
> >
> >  static void gfx_v8_0_set_rlc_funcs(struct amdgpu_device *adev) diff
> > --git a/drivers/gpu/drm/amd/amdgpu/vid.h
> > b/drivers/gpu/drm/amd/amdgpu/vid.h
> > index 11746f2..7a3863a 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/vid.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/vid.h
> > @@ -360,6 +360,8 @@
> >  #define        PACKET3_WAIT_ON_CE_COUNTER                      0x86
> >  #define        PACKET3_WAIT_ON_DE_COUNTER_DIFF                 0x88
> >  #define        PACKET3_SWITCH_BUFFER                           0x8B
> > +#define        PACKET3_SET_RESOURCES                           0xA0
> > +#define        PACKET3_MAP_QUEUES                              0xA2
> >
> >  #define VCE_CMD_NO_OP          0x00000000
> >  #define VCE_CMD_END            0x00000001
> > --
> > 2.7.4
> >
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]     ` <CADnq5_MyKwYUfEAtkUgSjLZMbGNbmc_n3pzCwG=B8B2Xpfw+Zw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2017-01-01 14:38       ` Yu, Xiangliang
@ 2017-01-01 14:52       ` Yu, Xiangliang
  1 sibling, 0 replies; 14+ messages in thread
From: Yu, Xiangliang @ 2017-01-01 14:52 UTC (permalink / raw)
  To: Alex Deucher; +Cc: Liu, Monk, amd-gfx list

> > changes in v2:
> > 1. use amdgpu_bo_create/free_kernel to allocate OB.
> >
> > Signed-off-by: Monk Liu <Monk.Liu@amd.com>
> > Signed-off-by: Xiangliang Yu <Xiangliang.Yu@amd.com>
> > ---
> >  drivers/gpu/drm/amd/amdgpu/amdgpu.h   |  13 +
> >  drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 607
> +++++++++++++++++++++++++++++++++-
> >  drivers/gpu/drm/amd/amdgpu/vid.h      |   2 +
> >  3 files changed, 620 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > index 9ea5bf0..c392882 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > @@ -186,6 +186,11 @@ enum amdgpu_thermal_irq {
> >         AMDGPU_THERMAL_IRQ_LAST
> >  };
> >
> > +enum amdgpu_kiq_irq {
> > +       AMDGPU_CP_KIQ_IRQ_DRIVER0 = 0,
> > +       AMDGPU_CP_KIQ_IRQ_LAST
> > +};
> 
> Is there a reason to make this a separate enum rather than just adding it to
> amdgpu_cp_irq?

Ok, I'll add CP_KIQ_IRQ into amdgpu_cp_irq and remove the enum. Thanks!
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]             ` <CY4PR12MB1701E0582B28FDC9AF4A1CF7EB680-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
@ 2017-01-04 10:27               ` Christian König
       [not found]                 ` <d3a848b9-1789-0788-a9b1-e80d814a8e01-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Christian König @ 2017-01-04 10:27 UTC (permalink / raw)
  To: Yu, Xiangliang, Zhou, David(ChunMing),
	amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Liu, Monk

Am 28.12.2016 um 03:59 schrieb Yu, Xiangliang:
>> -----Original Message-----
>> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On Behalf
>> Of zhoucm1
>> Sent: Wednesday, December 28, 2016 10:32 AM
>> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>; amd-
>> gfx@lists.freedesktop.org
>> Cc: Liu, Monk <Monk.Liu@amd.com>
>> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface
>> queue(KIQ)
>>
>>
>>
>> On 2016年12月28日 10:27, Yu, Xiangliang wrote:
>>> +
>>>> +	amdgpu_bo_kunmap(kiq->eop_obj);
>>>> +
>> I see it is in many places, which is don't need I think,
>> amdgpu_bo_free_kernel will handle it if I'm correct.
> Memory kmap should be free ASAP from memory management point.

No, that is completely unnecessary as long as you don't run a 32bit 
system with tight address space.

Regards,
Christian.

>
>> Regards,
>> David zhou
>> _______________________________________________
>> amd-gfx mailing list
>> amd-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]                 ` <d3a848b9-1789-0788-a9b1-e80d814a8e01-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org>
@ 2017-01-04 11:34                   ` Yu, Xiangliang
       [not found]                     ` <CY4PR12MB17018945F695389E673D2FBFEB610-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Yu, Xiangliang @ 2017-01-04 11:34 UTC (permalink / raw)
  To: Christian König, Zhou, David(ChunMing),
	amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Liu, Monk

> -----Original Message-----
> From: Christian König [mailto:deathsimple@vodafone.de]
> Sent: Wednesday, January 04, 2017 6:27 PM
> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>; Zhou, David(ChunMing)
> <David1.Zhou@amd.com>; amd-gfx@lists.freedesktop.org
> Cc: Liu, Monk <Monk.Liu@amd.com>
> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface
> queue(KIQ)
> 
> Am 28.12.2016 um 03:59 schrieb Yu, Xiangliang:
> >> -----Original Message-----
> >> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On
> >> Behalf Of zhoucm1
> >> Sent: Wednesday, December 28, 2016 10:32 AM
> >> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>; amd-
> >> gfx@lists.freedesktop.org
> >> Cc: Liu, Monk <Monk.Liu@amd.com>
> >> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface
> >> queue(KIQ)
> >>
> >>
> >>
> >> On 2016年12月28日 10:27, Yu, Xiangliang wrote:
> >>> +
> >>>> +	amdgpu_bo_kunmap(kiq->eop_obj);
> >>>> +
> >> I see it is in many places, which is don't need I think,
> >> amdgpu_bo_free_kernel will handle it if I'm correct.
> > Memory kmap should be free ASAP from memory management point.
> 
> No, that is completely unnecessary as long as you don't run a 32bit system
> with tight address space.

We can't decide what OS to use.  I agree with monk's comment that better to unmap it if cpu don't use.

> 
> 
> >
> >> Regards,
> >> David zhou
> >> _______________________________________________
> >> amd-gfx mailing list
> >> amd-gfx@lists.freedesktop.org
> >> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/amd-gfx
> 

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]                     ` <CY4PR12MB17018945F695389E673D2FBFEB610-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
@ 2017-01-04 12:59                       ` Christian König
       [not found]                         ` <09f8ecf6-5a0a-c65b-caf6-63ecae763e9b-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Christian König @ 2017-01-04 12:59 UTC (permalink / raw)
  To: Yu, Xiangliang, Zhou, David(ChunMing),
	amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Liu, Monk

Am 04.01.2017 um 12:34 schrieb Yu, Xiangliang:
>> -----Original Message-----
>> From: Christian König [mailto:deathsimple@vodafone.de]
>> Sent: Wednesday, January 04, 2017 6:27 PM
>> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>; Zhou, David(ChunMing)
>> <David1.Zhou@amd.com>; amd-gfx@lists.freedesktop.org
>> Cc: Liu, Monk <Monk.Liu@amd.com>
>> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface
>> queue(KIQ)
>>
>> Am 28.12.2016 um 03:59 schrieb Yu, Xiangliang:
>>>> -----Original Message-----
>>>> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On
>>>> Behalf Of zhoucm1
>>>> Sent: Wednesday, December 28, 2016 10:32 AM
>>>> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>; amd-
>>>> gfx@lists.freedesktop.org
>>>> Cc: Liu, Monk <Monk.Liu@amd.com>
>>>> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface
>>>> queue(KIQ)
>>>>
>>>>
>>>>
>>>> On 2016年12月28日 10:27, Yu, Xiangliang wrote:
>>>>> +
>>>>>> +	amdgpu_bo_kunmap(kiq->eop_obj);
>>>>>> +
>>>> I see it is in many places, which is don't need I think,
>>>> amdgpu_bo_free_kernel will handle it if I'm correct.
>>> Memory kmap should be free ASAP from memory management point.
>> No, that is completely unnecessary as long as you don't run a 32bit system
>> with tight address space.
> We can't decide what OS to use.  I agree with monk's comment that better to unmap it if cpu don't use.

No it isn't. As I said this is only necessary on 32bit systems with 
tight address space. In other words we simply don't really support that 
configuration any more.

If you don't need it then why do you want to kmap it in the first place?

Regards,
Christian.

>
>>
>>>> Regards,
>>>> David zhou
>>>> _______________________________________________
>>>> amd-gfx mailing list
>>>> amd-gfx@lists.freedesktop.org
>>>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>>> _______________________________________________
>>> amd-gfx mailing list
>>> amd-gfx@lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]                         ` <09f8ecf6-5a0a-c65b-caf6-63ecae763e9b-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org>
@ 2017-01-04 13:26                           ` Yu, Xiangliang
       [not found]                             ` <CY4PR12MB1701517F2E7D90C0258C6029EB610-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Yu, Xiangliang @ 2017-01-04 13:26 UTC (permalink / raw)
  To: Christian König, Zhou, David(ChunMing),
	amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Liu, Monk

> >> Am 28.12.2016 um 03:59 schrieb Yu, Xiangliang:
> >>>> -----Original Message-----
> >>>> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On
> >>>> Behalf Of zhoucm1
> >>>> Sent: Wednesday, December 28, 2016 10:32 AM
> >>>> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>; amd-
> >>>> gfx@lists.freedesktop.org
> >>>> Cc: Liu, Monk <Monk.Liu@amd.com>
> >>>> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface
> >>>> queue(KIQ)
> >>>>
> >>>>
> >>>>
> >>>> On 2016年12月28日 10:27, Yu, Xiangliang wrote:
> >>>>> +
> >>>>>> +	amdgpu_bo_kunmap(kiq->eop_obj);
> >>>>>> +
> >>>> I see it is in many places, which is don't need I think,
> >>>> amdgpu_bo_free_kernel will handle it if I'm correct.
> >>> Memory kmap should be free ASAP from memory management point.
> >> No, that is completely unnecessary as long as you don't run a 32bit
> >> system with tight address space.
> > We can't decide what OS to use.  I agree with monk's comment that better
> to unmap it if cpu don't use.
> 
> No it isn't. As I said this is only necessary on 32bit systems with tight address
> space. In other words we simply don't really support that configuration any
> more.
> 
> If you don't need it then why do you want to kmap it in the first place?
> 

In my patch, first get mqd address to fill out mqd context through kmap, then setup compute queue with kiq ring.

And I see there are lot of similar usage in amdgpu, for example, gfx_v8_0_rlc_init function. Could you help to explain it?


_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]                             ` <CY4PR12MB1701517F2E7D90C0258C6029EB610-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
@ 2017-01-04 14:12                               ` Christian König
       [not found]                                 ` <0467aa48-0bde-9a47-cc04-6f791fec77d3-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Christian König @ 2017-01-04 14:12 UTC (permalink / raw)
  To: Yu, Xiangliang, Zhou, David(ChunMing),
	amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Liu, Monk

Am 04.01.2017 um 14:26 schrieb Yu, Xiangliang:
>>>> Am 28.12.2016 um 03:59 schrieb Yu, Xiangliang:
>>>>>> -----Original Message-----
>>>>>> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On
>>>>>> Behalf Of zhoucm1
>>>>>> Sent: Wednesday, December 28, 2016 10:32 AM
>>>>>> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>; amd-
>>>>>> gfx@lists.freedesktop.org
>>>>>> Cc: Liu, Monk <Monk.Liu@amd.com>
>>>>>> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface
>>>>>> queue(KIQ)
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 2016年12月28日 10:27, Yu, Xiangliang wrote:
>>>>>>> +
>>>>>>>> +	amdgpu_bo_kunmap(kiq->eop_obj);
>>>>>>>> +
>>>>>> I see it is in many places, which is don't need I think,
>>>>>> amdgpu_bo_free_kernel will handle it if I'm correct.
>>>>> Memory kmap should be free ASAP from memory management point.
>>>> No, that is completely unnecessary as long as you don't run a 32bit
>>>> system with tight address space.
>>> We can't decide what OS to use.  I agree with monk's comment that better
>> to unmap it if cpu don't use.
>>
>> No it isn't. As I said this is only necessary on 32bit systems with tight address
>> space. In other words we simply don't really support that configuration any
>> more.
>>
>> If you don't need it then why do you want to kmap it in the first place?
>>
> In my patch, first get mqd address to fill out mqd context through kmap, then setup compute queue with kiq ring.
>
> And I see there are lot of similar usage in amdgpu, for example, gfx_v8_0_rlc_init function. Could you help to explain it?

Ah! So you only map it initially to fill in some data structure during 
initialization? Yeah, in this case just map the BO temporary, fill in 
the data and unmap it again.

Sorry, judging from the comments I thought that you map/unmap the BO 
multiple times on each IOCTL. That is really something we should try to 
avoid.

Just make sure that you don't store the pointer returned by kmap 
anywhere, it is only valid temporarily.

Regards,
Christian.

>
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ)
       [not found]                                 ` <0467aa48-0bde-9a47-cc04-6f791fec77d3-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org>
@ 2017-01-04 14:49                                   ` Yu, Xiangliang
  0 siblings, 0 replies; 14+ messages in thread
From: Yu, Xiangliang @ 2017-01-04 14:49 UTC (permalink / raw)
  To: Christian König, Zhou, David(ChunMing),
	amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Liu, Monk

> -----Original Message-----
> From: Christian König [mailto:deathsimple@vodafone.de]
> Sent: Wednesday, January 04, 2017 10:13 PM
> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>; Zhou, David(ChunMing)
> <David1.Zhou@amd.com>; amd-gfx@lists.freedesktop.org; Liu, Monk
> <Monk.Liu@amd.com>
> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel interface
> queue(KIQ)
> 
> Am 04.01.2017 um 14:26 schrieb Yu, Xiangliang:
> >>>> Am 28.12.2016 um 03:59 schrieb Yu, Xiangliang:
> >>>>>> -----Original Message-----
> >>>>>> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On
> >>>>>> Behalf Of zhoucm1
> >>>>>> Sent: Wednesday, December 28, 2016 10:32 AM
> >>>>>> To: Yu, Xiangliang <Xiangliang.Yu@amd.com>; amd-
> >>>>>> gfx@lists.freedesktop.org
> >>>>>> Cc: Liu, Monk <Monk.Liu@amd.com>
> >>>>>> Subject: Re: [V2 1/1] drm/amdgpu/gfx8: add support kernel
> >>>>>> interface
> >>>>>> queue(KIQ)
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> On 2016年12月28日 10:27, Yu, Xiangliang wrote:
> >>>>>>> +
> >>>>>>>> +	amdgpu_bo_kunmap(kiq->eop_obj);
> >>>>>>>> +
> >>>>>> I see it is in many places, which is don't need I think,
> >>>>>> amdgpu_bo_free_kernel will handle it if I'm correct.
> >>>>> Memory kmap should be free ASAP from memory management point.
> >>>> No, that is completely unnecessary as long as you don't run a 32bit
> >>>> system with tight address space.
> >>> We can't decide what OS to use.  I agree with monk's comment that
> >>> better
> >> to unmap it if cpu don't use.
> >>
> >> No it isn't. As I said this is only necessary on 32bit systems with
> >> tight address space. In other words we simply don't really support
> >> that configuration any more.
> >>
> >> If you don't need it then why do you want to kmap it in the first place?
> >>
> > In my patch, first get mqd address to fill out mqd context through kmap,
> then setup compute queue with kiq ring.
> >
> > And I see there are lot of similar usage in amdgpu, for example,
> gfx_v8_0_rlc_init function. Could you help to explain it?
> 
> Ah! So you only map it initially to fill in some data structure during
> initialization? Yeah, in this case just map the BO temporary, fill in the data and
> unmap it again.

Yes.

> 
> Sorry, judging from the comments I thought that you map/unmap the BO
> multiple times on each IOCTL. That is really something we should try to avoid.
> 
> Just make sure that you don't store the pointer returned by kmap anywhere,
> it is only valid temporarily.

Got it. Thanks!
 

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2017-01-04 14:49 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-23  7:08 [V2 1/1] drm/amdgpu/gfx8: add support kernel interface queue(KIQ) Xiangliang Yu
     [not found] ` <1482476904-21674-1-git-send-email-Xiangliang.Yu-5C7GfCeVMHo@public.gmane.org>
2016-12-28  2:27   ` Yu, Xiangliang
     [not found]     ` <CY4PR12MB1701D664FEB2EF8FCFD4EBDBEB680-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2016-12-28  2:31       ` zhoucm1
     [not found]         ` <58632418.5040408-5C7GfCeVMHo@public.gmane.org>
2016-12-28  2:59           ` Yu, Xiangliang
     [not found]             ` <CY4PR12MB1701E0582B28FDC9AF4A1CF7EB680-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2017-01-04 10:27               ` Christian König
     [not found]                 ` <d3a848b9-1789-0788-a9b1-e80d814a8e01-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org>
2017-01-04 11:34                   ` Yu, Xiangliang
     [not found]                     ` <CY4PR12MB17018945F695389E673D2FBFEB610-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2017-01-04 12:59                       ` Christian König
     [not found]                         ` <09f8ecf6-5a0a-c65b-caf6-63ecae763e9b-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org>
2017-01-04 13:26                           ` Yu, Xiangliang
     [not found]                             ` <CY4PR12MB1701517F2E7D90C0258C6029EB610-rpdhrqHFk05QaJCA3gGb3wdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2017-01-04 14:12                               ` Christian König
     [not found]                                 ` <0467aa48-0bde-9a47-cc04-6f791fec77d3-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org>
2017-01-04 14:49                                   ` Yu, Xiangliang
2016-12-28  3:20           ` 答复: " Liu, Monk
2016-12-31  6:53   ` Alex Deucher
     [not found]     ` <CADnq5_MyKwYUfEAtkUgSjLZMbGNbmc_n3pzCwG=B8B2Xpfw+Zw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-01-01 14:38       ` Yu, Xiangliang
2017-01-01 14:52       ` Yu, Xiangliang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.