Commit c13276a1 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'amd-drm-fixes-6.15-2025-05-01' of...

Merge tag 'amd-drm-fixes-6.15-2025-05-01' of https://gitlab.freedesktop.org/agd5f/linux

 into drm-fixes

amd-drm-fixes-6.15-2025-05-01:

amdgpu:
- Fix possible UAF in HDCP
- XGMI dma-buf fix
- NBIO 7.11 fix
- VCN 5.0.1 fix

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://lore.kernel.org/r/20250501185634.4132187-1-alexander.deucher@amd.com
parents 1cbbec17 6718b10a
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -199,6 +199,11 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
		break;

	case TTM_PL_VRAM:
		/* XGMI-accessible memory should never be DMA-mapped */
		if (WARN_ON(amdgpu_dmabuf_is_xgmi_accessible(
				dma_buf_attach_adev(attach), bo)))
			return ERR_PTR(-EINVAL);

		r = amdgpu_vram_mgr_alloc_sgt(adev, bo->tbo.resource, 0,
					      bo->tbo.base.size, attach->dev,
					      dir, &sgt);
+1 −1
Original line number Diff line number Diff line
@@ -360,7 +360,7 @@ static void nbio_v7_11_get_clockgating_state(struct amdgpu_device *adev,
		*flags |= AMD_CG_SUPPORT_BIF_LS;
}

#define MMIO_REG_HOLE_OFFSET (0x80000 - PAGE_SIZE)
#define MMIO_REG_HOLE_OFFSET 0x44000

static void nbio_v7_11_set_reg_remap(struct amdgpu_device *adev)
{
+54 −0
Original line number Diff line number Diff line
@@ -502,6 +502,52 @@ static void vcn_v5_0_1_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
{
}

/**
 * vcn_v5_0_1_pause_dpg_mode - VCN pause with dpg mode
 *
 * @vinst: VCN instance
 * @new_state: pause state
 *
 * Pause dpg mode for VCN block
 */
static int vcn_v5_0_1_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
				     struct dpg_pause_state *new_state)
{
	struct amdgpu_device *adev = vinst->adev;
	uint32_t reg_data = 0;
	int vcn_inst;

	vcn_inst = GET_INST(VCN, vinst->inst);

	/* pause/unpause if state is changed */
	if (vinst->pause_state.fw_based != new_state->fw_based) {
		DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d %s\n",
			vinst->pause_state.fw_based, new_state->fw_based,
			new_state->fw_based ? "VCN_DPG_STATE__PAUSE" : "VCN_DPG_STATE__UNPAUSE");
		reg_data = RREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE) &
			(~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);

		if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
			/* pause DPG */
			reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
			WREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE, reg_data);

			/* wait for ACK */
			SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_DPG_PAUSE,
					UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
					UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
		} else {
			/* unpause DPG, no need to wait */
			reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
			WREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE, reg_data);
		}
		vinst->pause_state.fw_based = new_state->fw_based;
	}

	return 0;
}


/**
 * vcn_v5_0_1_start_dpg_mode - VCN start with dpg mode
 *
@@ -518,6 +564,7 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
	volatile struct amdgpu_vcn5_fw_shared *fw_shared =
		adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
	struct amdgpu_ring *ring;
	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__PAUSE};
	int vcn_inst;
	uint32_t tmp;

@@ -582,6 +629,9 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
	if (indirect)
		amdgpu_vcn_psp_update_sram(adev, inst_idx, AMDGPU_UCODE_ID_VCN0_RAM);

	/* Pause dpg */
	vcn_v5_0_1_pause_dpg_mode(vinst, &state);

	ring = &adev->vcn.inst[inst_idx].ring_enc[0];

	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, lower_32_bits(ring->gpu_addr));
@@ -775,9 +825,13 @@ static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
	int inst_idx = vinst->inst;
	uint32_t tmp;
	int vcn_inst;
	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};

	vcn_inst = GET_INST(VCN, inst_idx);

	/* Unpause dpg */
	vcn_v5_0_1_pause_dpg_mode(vinst, &state);

	/* Wait for power status to be 1 */
	SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,
		UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+16 −3
Original line number Diff line number Diff line
@@ -173,6 +173,9 @@ void hdcp_update_display(struct hdcp_workqueue *hdcp_work,
	unsigned int conn_index = aconnector->base.index;

	guard(mutex)(&hdcp_w->mutex);
	drm_connector_get(&aconnector->base);
	if (hdcp_w->aconnector[conn_index])
		drm_connector_put(&hdcp_w->aconnector[conn_index]->base);
	hdcp_w->aconnector[conn_index] = aconnector;

	memset(&link_adjust, 0, sizeof(link_adjust));
@@ -220,7 +223,6 @@ static void hdcp_remove_display(struct hdcp_workqueue *hdcp_work,
	unsigned int conn_index = aconnector->base.index;

	guard(mutex)(&hdcp_w->mutex);
	hdcp_w->aconnector[conn_index] = aconnector;

	/* the removal of display will invoke auth reset -> hdcp destroy and
	 * we'd expect the Content Protection (CP) property changed back to
@@ -236,7 +238,10 @@ static void hdcp_remove_display(struct hdcp_workqueue *hdcp_work,
	}

	mod_hdcp_remove_display(&hdcp_w->hdcp, aconnector->base.index, &hdcp_w->output);

	if (hdcp_w->aconnector[conn_index]) {
		drm_connector_put(&hdcp_w->aconnector[conn_index]->base);
		hdcp_w->aconnector[conn_index] = NULL;
	}
	process_output(hdcp_w);
}

@@ -254,6 +259,10 @@ void hdcp_reset_display(struct hdcp_workqueue *hdcp_work, unsigned int link_inde
	for (conn_index = 0; conn_index < AMDGPU_DM_MAX_DISPLAY_INDEX; conn_index++) {
		hdcp_w->encryption_status[conn_index] =
			MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
		if (hdcp_w->aconnector[conn_index]) {
			drm_connector_put(&hdcp_w->aconnector[conn_index]->base);
			hdcp_w->aconnector[conn_index] = NULL;
		}
	}

	process_output(hdcp_w);
@@ -488,6 +497,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
	struct hdcp_workqueue *hdcp_work = handle;
	struct amdgpu_dm_connector *aconnector = config->dm_stream_ctx;
	int link_index = aconnector->dc_link->link_index;
	unsigned int conn_index = aconnector->base.index;
	struct mod_hdcp_display *display = &hdcp_work[link_index].display;
	struct mod_hdcp_link *link = &hdcp_work[link_index].link;
	struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
@@ -544,7 +554,10 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
	guard(mutex)(&hdcp_w->mutex);

	mod_hdcp_add_display(&hdcp_w->hdcp, link, display, &hdcp_w->output);

	drm_connector_get(&aconnector->base);
	if (hdcp_w->aconnector[conn_index])
		drm_connector_put(&hdcp_w->aconnector[conn_index]->base);
	hdcp_w->aconnector[conn_index] = aconnector;
	process_output(hdcp_w);
}