drm/radeon/kms: fix regression rendering issue on R6XX/R7XX
It seems that some R6XX/R7XX silently ignore HDP flush when programmed through ring, this patch addback an ioctl callback to allow R6XX/R7XX hw to perform such flush through MMIO in order to fix a regression. For more details see: http://bugzilla.kernel.org/show_bug.cgi?id=15186 Signed-off-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
committed by
Dave Airlie
parent
c38c7b64a2
commit
062b389c87
@@ -2900,3 +2900,18 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev)
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* r600_ioctl_wait_idle - flush host path cache on wait idle ioctl
|
||||||
|
* rdev: radeon device structure
|
||||||
|
* bo: buffer object struct which userspace is waiting for idle
|
||||||
|
*
|
||||||
|
* Some R6XX/R7XX doesn't seems to take into account HDP flush performed
|
||||||
|
* through ring buffer, this leads to corruption in rendering, see
|
||||||
|
* http://bugzilla.kernel.org/show_bug.cgi?id=15186 to avoid this we
|
||||||
|
* directly perform HDP flush by writing register through MMIO.
|
||||||
|
*/
|
||||||
|
void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
|
||||||
|
{
|
||||||
|
WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
|
||||||
|
}
|
||||||
|
@@ -661,6 +661,13 @@ struct radeon_asic {
|
|||||||
void (*hpd_fini)(struct radeon_device *rdev);
|
void (*hpd_fini)(struct radeon_device *rdev);
|
||||||
bool (*hpd_sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
bool (*hpd_sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
||||||
void (*hpd_set_polarity)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
void (*hpd_set_polarity)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
||||||
|
/* ioctl hw specific callback. Some hw might want to perform special
|
||||||
|
* operation on specific ioctl. For instance on wait idle some hw
|
||||||
|
* might want to perform and HDP flush through MMIO as it seems that
|
||||||
|
* some R6XX/R7XX hw doesn't take HDP flush into account if programmed
|
||||||
|
* through ring.
|
||||||
|
*/
|
||||||
|
void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -117,6 +117,7 @@ static struct radeon_asic r100_asic = {
|
|||||||
.hpd_fini = &r100_hpd_fini,
|
.hpd_fini = &r100_hpd_fini,
|
||||||
.hpd_sense = &r100_hpd_sense,
|
.hpd_sense = &r100_hpd_sense,
|
||||||
.hpd_set_polarity = &r100_hpd_set_polarity,
|
.hpd_set_polarity = &r100_hpd_set_polarity,
|
||||||
|
.ioctl_wait_idle = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -176,6 +177,7 @@ static struct radeon_asic r300_asic = {
|
|||||||
.hpd_fini = &r100_hpd_fini,
|
.hpd_fini = &r100_hpd_fini,
|
||||||
.hpd_sense = &r100_hpd_sense,
|
.hpd_sense = &r100_hpd_sense,
|
||||||
.hpd_set_polarity = &r100_hpd_set_polarity,
|
.hpd_set_polarity = &r100_hpd_set_polarity,
|
||||||
|
.ioctl_wait_idle = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -219,6 +221,7 @@ static struct radeon_asic r420_asic = {
|
|||||||
.hpd_fini = &r100_hpd_fini,
|
.hpd_fini = &r100_hpd_fini,
|
||||||
.hpd_sense = &r100_hpd_sense,
|
.hpd_sense = &r100_hpd_sense,
|
||||||
.hpd_set_polarity = &r100_hpd_set_polarity,
|
.hpd_set_polarity = &r100_hpd_set_polarity,
|
||||||
|
.ioctl_wait_idle = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -267,6 +270,7 @@ static struct radeon_asic rs400_asic = {
|
|||||||
.hpd_fini = &r100_hpd_fini,
|
.hpd_fini = &r100_hpd_fini,
|
||||||
.hpd_sense = &r100_hpd_sense,
|
.hpd_sense = &r100_hpd_sense,
|
||||||
.hpd_set_polarity = &r100_hpd_set_polarity,
|
.hpd_set_polarity = &r100_hpd_set_polarity,
|
||||||
|
.ioctl_wait_idle = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -323,6 +327,7 @@ static struct radeon_asic rs600_asic = {
|
|||||||
.hpd_fini = &rs600_hpd_fini,
|
.hpd_fini = &rs600_hpd_fini,
|
||||||
.hpd_sense = &rs600_hpd_sense,
|
.hpd_sense = &rs600_hpd_sense,
|
||||||
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
||||||
|
.ioctl_wait_idle = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -370,6 +375,7 @@ static struct radeon_asic rs690_asic = {
|
|||||||
.hpd_fini = &rs600_hpd_fini,
|
.hpd_fini = &rs600_hpd_fini,
|
||||||
.hpd_sense = &rs600_hpd_sense,
|
.hpd_sense = &rs600_hpd_sense,
|
||||||
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
||||||
|
.ioctl_wait_idle = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -421,6 +427,7 @@ static struct radeon_asic rv515_asic = {
|
|||||||
.hpd_fini = &rs600_hpd_fini,
|
.hpd_fini = &rs600_hpd_fini,
|
||||||
.hpd_sense = &rs600_hpd_sense,
|
.hpd_sense = &rs600_hpd_sense,
|
||||||
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
||||||
|
.ioctl_wait_idle = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -463,6 +470,7 @@ static struct radeon_asic r520_asic = {
|
|||||||
.hpd_fini = &rs600_hpd_fini,
|
.hpd_fini = &rs600_hpd_fini,
|
||||||
.hpd_sense = &rs600_hpd_sense,
|
.hpd_sense = &rs600_hpd_sense,
|
||||||
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
||||||
|
.ioctl_wait_idle = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -504,6 +512,7 @@ void r600_hpd_fini(struct radeon_device *rdev);
|
|||||||
bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
||||||
void r600_hpd_set_polarity(struct radeon_device *rdev,
|
void r600_hpd_set_polarity(struct radeon_device *rdev,
|
||||||
enum radeon_hpd_id hpd);
|
enum radeon_hpd_id hpd);
|
||||||
|
extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo);
|
||||||
|
|
||||||
static struct radeon_asic r600_asic = {
|
static struct radeon_asic r600_asic = {
|
||||||
.init = &r600_init,
|
.init = &r600_init,
|
||||||
@@ -538,6 +547,7 @@ static struct radeon_asic r600_asic = {
|
|||||||
.hpd_fini = &r600_hpd_fini,
|
.hpd_fini = &r600_hpd_fini,
|
||||||
.hpd_sense = &r600_hpd_sense,
|
.hpd_sense = &r600_hpd_sense,
|
||||||
.hpd_set_polarity = &r600_hpd_set_polarity,
|
.hpd_set_polarity = &r600_hpd_set_polarity,
|
||||||
|
.ioctl_wait_idle = r600_ioctl_wait_idle,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -582,6 +592,7 @@ static struct radeon_asic rv770_asic = {
|
|||||||
.hpd_fini = &r600_hpd_fini,
|
.hpd_fini = &r600_hpd_fini,
|
||||||
.hpd_sense = &r600_hpd_sense,
|
.hpd_sense = &r600_hpd_sense,
|
||||||
.hpd_set_polarity = &r600_hpd_set_polarity,
|
.hpd_set_polarity = &r600_hpd_set_polarity,
|
||||||
|
.ioctl_wait_idle = r600_ioctl_wait_idle,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -308,6 +308,9 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
|
|||||||
}
|
}
|
||||||
robj = gobj->driver_private;
|
robj = gobj->driver_private;
|
||||||
r = radeon_bo_wait(robj, NULL, false);
|
r = radeon_bo_wait(robj, NULL, false);
|
||||||
|
/* callback hw specific functions if any */
|
||||||
|
if (robj->rdev->asic->ioctl_wait_idle)
|
||||||
|
robj->rdev->asic->ioctl_wait_idle(robj->rdev, robj);
|
||||||
mutex_lock(&dev->struct_mutex);
|
mutex_lock(&dev->struct_mutex);
|
||||||
drm_gem_object_unreference(gobj);
|
drm_gem_object_unreference(gobj);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
Reference in New Issue
Block a user