Commit 062b389c authored by Jerome Glisse's avatar Jerome Glisse Committed by Dave Airlie

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=15186Signed-off-by: default avatarJerome Glisse <jglisse@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent c38c7b64
...@@ -2900,3 +2900,18 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev) ...@@ -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 { ...@@ -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 = { ...@@ -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 = { ...@@ -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 = { ...@@ -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 = { ...@@ -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 = { ...@@ -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 = { ...@@ -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 = { ...@@ -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 = { ...@@ -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); ...@@ -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 = { ...@@ -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 = { ...@@ -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, ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment