drm/radeon/si: Add support for CP DMA to CS checker for compute v2
Also add a new RADEON_INFO query to check that CP DMA packets are supported on the compute ring. CP DMA has been supported since the 3.8 kernel, but due to an oversight we forgot to teach the CS checker that the CP DMA packet was legal for the compute ring on Southern Islands GPUs. This patch fixes a bug where the radeon driver will incorrectly reject a legal CP DMA packet from user space. I would like to have the patch backported to stable so that we don't have to require Mesa users to use a bleeding edge kernel in order to take advantage of this feature which is already present in the stable kernels (3.8 and newer). v2: - Don't bump kms version, so this patch can be backported to stable kernels. Cc: stable@vger.kernel.org Signed-off-by: Tom Stellard <thomas.stellard@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:

committed by
Alex Deucher

parent
773dc10a8a
commit
e5b9e7503e
@@ -4051,13 +4051,64 @@ static int si_vm_packet3_ce_check(struct radeon_device *rdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int si_vm_packet3_cp_dma_check(u32 *ib, u32 idx)
|
||||
{
|
||||
u32 start_reg, reg, i;
|
||||
u32 command = ib[idx + 4];
|
||||
u32 info = ib[idx + 1];
|
||||
u32 idx_value = ib[idx];
|
||||
if (command & PACKET3_CP_DMA_CMD_SAS) {
|
||||
/* src address space is register */
|
||||
if (((info & 0x60000000) >> 29) == 0) {
|
||||
start_reg = idx_value << 2;
|
||||
if (command & PACKET3_CP_DMA_CMD_SAIC) {
|
||||
reg = start_reg;
|
||||
if (!si_vm_reg_valid(reg)) {
|
||||
DRM_ERROR("CP DMA Bad SRC register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < (command & 0x1fffff); i++) {
|
||||
reg = start_reg + (4 * i);
|
||||
if (!si_vm_reg_valid(reg)) {
|
||||
DRM_ERROR("CP DMA Bad SRC register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (command & PACKET3_CP_DMA_CMD_DAS) {
|
||||
/* dst address space is register */
|
||||
if (((info & 0x00300000) >> 20) == 0) {
|
||||
start_reg = ib[idx + 2];
|
||||
if (command & PACKET3_CP_DMA_CMD_DAIC) {
|
||||
reg = start_reg;
|
||||
if (!si_vm_reg_valid(reg)) {
|
||||
DRM_ERROR("CP DMA Bad DST register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < (command & 0x1fffff); i++) {
|
||||
reg = start_reg + (4 * i);
|
||||
if (!si_vm_reg_valid(reg)) {
|
||||
DRM_ERROR("CP DMA Bad DST register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int si_vm_packet3_gfx_check(struct radeon_device *rdev,
|
||||
u32 *ib, struct radeon_cs_packet *pkt)
|
||||
{
|
||||
int r;
|
||||
u32 idx = pkt->idx + 1;
|
||||
u32 idx_value = ib[idx];
|
||||
u32 start_reg, end_reg, reg, i;
|
||||
u32 command, info;
|
||||
|
||||
switch (pkt->opcode) {
|
||||
case PACKET3_NOP:
|
||||
@@ -4158,50 +4209,9 @@ static int si_vm_packet3_gfx_check(struct radeon_device *rdev,
|
||||
}
|
||||
break;
|
||||
case PACKET3_CP_DMA:
|
||||
command = ib[idx + 4];
|
||||
info = ib[idx + 1];
|
||||
if (command & PACKET3_CP_DMA_CMD_SAS) {
|
||||
/* src address space is register */
|
||||
if (((info & 0x60000000) >> 29) == 0) {
|
||||
start_reg = idx_value << 2;
|
||||
if (command & PACKET3_CP_DMA_CMD_SAIC) {
|
||||
reg = start_reg;
|
||||
if (!si_vm_reg_valid(reg)) {
|
||||
DRM_ERROR("CP DMA Bad SRC register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < (command & 0x1fffff); i++) {
|
||||
reg = start_reg + (4 * i);
|
||||
if (!si_vm_reg_valid(reg)) {
|
||||
DRM_ERROR("CP DMA Bad SRC register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (command & PACKET3_CP_DMA_CMD_DAS) {
|
||||
/* dst address space is register */
|
||||
if (((info & 0x00300000) >> 20) == 0) {
|
||||
start_reg = ib[idx + 2];
|
||||
if (command & PACKET3_CP_DMA_CMD_DAIC) {
|
||||
reg = start_reg;
|
||||
if (!si_vm_reg_valid(reg)) {
|
||||
DRM_ERROR("CP DMA Bad DST register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < (command & 0x1fffff); i++) {
|
||||
reg = start_reg + (4 * i);
|
||||
if (!si_vm_reg_valid(reg)) {
|
||||
DRM_ERROR("CP DMA Bad DST register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r = si_vm_packet3_cp_dma_check(ib, idx);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Invalid GFX packet3: 0x%x\n", pkt->opcode);
|
||||
@@ -4213,6 +4223,7 @@ static int si_vm_packet3_gfx_check(struct radeon_device *rdev,
|
||||
static int si_vm_packet3_compute_check(struct radeon_device *rdev,
|
||||
u32 *ib, struct radeon_cs_packet *pkt)
|
||||
{
|
||||
int r;
|
||||
u32 idx = pkt->idx + 1;
|
||||
u32 idx_value = ib[idx];
|
||||
u32 start_reg, reg, i;
|
||||
@@ -4285,6 +4296,11 @@ static int si_vm_packet3_compute_check(struct radeon_device *rdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_CP_DMA:
|
||||
r = si_vm_packet3_cp_dma_check(ib, idx);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Invalid Compute packet3: 0x%x\n", pkt->opcode);
|
||||
return -EINVAL;
|
||||
|
Reference in New Issue
Block a user