[PATCH] drm/amdgpu: Process bif doorbell event

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When BACO exit is triggered by doorbell transaction,
firmware will config bif to issue msi interrupt to
indicate doorbell transaction. If bif ring is not
enabled in such case, driver needs to ack the interrupt
by clearing the interrupt status.

Signed-off-by: Hawking Zhang <Hawking.Zhang@xxxxxxx>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h |  2 +
 drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c   | 56 ++++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/soc21.c       | 14 +++++-
 3 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
index 7b8c03be1d9e..db341921cfc1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
@@ -102,6 +102,7 @@ struct amdgpu_nbio_funcs {
 	u32 (*get_memory_partition_mode)(struct amdgpu_device *adev,
 					 u32 *supp_modes);
 	u64 (*get_pcie_replay_count)(struct amdgpu_device *adev);
+	u32 (*init_bif_doorbell_event)(struct amdgpu_device *adev);
 };
 
 struct amdgpu_nbio {
@@ -111,6 +112,7 @@ struct amdgpu_nbio {
 	struct ras_common_if *ras_if;
 	const struct amdgpu_nbio_funcs *funcs;
 	struct amdgpu_nbio_ras  *ras;
+	struct amdgpu_irq_src bif_doorbell_irq;
 };
 
 int amdgpu_nbio_ras_sw_init(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c
index 7f88a298ac5f..e5a331b6eee9 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c
@@ -477,6 +477,61 @@ static void nbio_v4_3_program_aspm(struct amdgpu_device *adev)
 #endif
 }
 
+static int nbio_v4_3_set_bif_doorbell_irq_state(struct amdgpu_device *adev,
+						struct amdgpu_irq_src *src,
+						unsigned type,
+						enum amdgpu_interrupt_state state)
+{
+        /*let firmware to config bif doorbell irq state */
+        return 0;
+}
+
+static int nbio_v4_3_process_bif_doorbell_irq(struct amdgpu_device *adev,
+					      struct amdgpu_irq_src *source,
+					      struct amdgpu_iv_entry *entry)
+{
+	/* pmfw will config bif doorbell irq to host if baco exit
+	 * is triggered by doorbell transaction. In such case, driver
+	 * needs to clear the interrupt status */
+
+	uint32_t reg_data;
+
+	reg_data = RREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_RB_CNTL);
+
+	/* if bif ring is enabled, do nothing */
+	if (REG_GET_FIELD(reg_data, BIF_BX0_BIF_RB_CNTL, RB_ENABLE))
+		return 0;
+
+	/* write 1 to clear doorbell interrupt */
+	reg_data = RREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_DOORBELL_INT_CNTL);
+	if (REG_GET_FIELD(reg_data, BIF_BX0_BIF_DOORBELL_INT_CNTL, DOORBELL_INTERRUPT_STATUS)) {
+		reg_data = REG_SET_FIELD(reg_data,
+					 BIF_BX0_BIF_DOORBELL_INT_CNTL,
+					 DOORBELL_INTERRUPT_CLEAR, 1);
+		WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_DOORBELL_INT_CNTL, reg_data);
+	}
+
+	return 0;
+}
+
+static const struct amdgpu_irq_src_funcs nbio_v4_3_bif_doorbell_irq_funcs = {
+	.set = nbio_v4_3_set_bif_doorbell_irq_state,
+	.process = nbio_v4_3_process_bif_doorbell_irq,
+};
+
+static u32 nbio_v4_3_init_bif_doorbell_event(struct amdgpu_device *adev)
+{
+	u32 r;
+
+	adev->nbio.bif_doorbell_irq.funcs = &nbio_v4_3_bif_doorbell_irq_funcs;
+	adev->nbio.bif_doorbell_irq.num_types = 1;
+
+	r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_BIF,
+			      NBIF_7_4__SRCID__DOORBELL_INTERRUPT,
+			      &adev->nbio.bif_doorbell_irq);
+	return r;
+}
+
 const struct amdgpu_nbio_funcs nbio_v4_3_funcs = {
 	.get_hdp_flush_req_offset = nbio_v4_3_get_hdp_flush_req_offset,
 	.get_hdp_flush_done_offset = nbio_v4_3_get_hdp_flush_done_offset,
@@ -499,6 +554,7 @@ const struct amdgpu_nbio_funcs nbio_v4_3_funcs = {
 	.remap_hdp_registers = nbio_v4_3_remap_hdp_registers,
 	.get_rom_offset = nbio_v4_3_get_rom_offset,
 	.program_aspm = nbio_v4_3_program_aspm,
+	.init_bif_doorbell_event = nbio_v4_3_init_bif_doorbell_event,
 };
 
 
diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c
index abe319b0f063..ee6d810589c0 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc21.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc21.c
@@ -792,6 +792,9 @@ static int soc21_common_late_init(void *handle)
 			 * nbio v4_3 only support fatal error hanlding
 			 * just enable the interrupt directly */
 			amdgpu_irq_get(adev, &adev->nbio.ras_err_event_athub_irq, 0);
+		if (adev->nbio.bif_doorbell_irq.funcs &&
+		    adev->nbio.funcs && adev->nbio.funcs->init_bif_doorbell_event)
+			amdgpu_irq_get(adev, &adev->nbio.bif_doorbell_irq, 0);
 	}
 
 	/* Enable selfring doorbell aperture late because doorbell BAR
@@ -806,8 +809,12 @@ static int soc21_common_sw_init(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	if (amdgpu_sriov_vf(adev))
+	if (amdgpu_sriov_vf(adev)) {
 		xgpu_nv_mailbox_add_irq_id(adev);
+	} else if (adev->nbio.funcs &&
+		   adev->nbio.funcs->init_bif_doorbell_event) {
+		adev->nbio.funcs->init_bif_doorbell_event(adev);
+	}
 
 	return 0;
 }
@@ -855,6 +862,11 @@ static int soc21_common_hw_fini(void *handle)
 		if (adev->nbio.ras &&
 		    adev->nbio.ras_err_event_athub_irq.funcs)
 			amdgpu_irq_put(adev, &adev->nbio.ras_err_event_athub_irq, 0);
+
+		if (adev->nbio.funcs &&
+		    adev->nbio.funcs->init_bif_doorbell_event &&
+		    adev->nbio.bif_doorbell_irq.funcs)
+			amdgpu_irq_put(adev, &adev->nbio.bif_doorbell_irq, 0);
 	}
 
 	return 0;
-- 
2.17.1




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux