Skip to content

Commit b1d778b

Browse files
committed
Merge branch 'drm-fixes-3.8' of git://people.freedesktop.org/~agd5f/linux into drm-next
Misc fixes for reset and new packets for userspace usage. * 'drm-fixes-3.8' of git://people.freedesktop.org/~agd5f/linux: drm/radeon: add WAIT_UNTIL to evergreen VM safe reg list drm/radeon: add support for MEM_WRITE packet drm/radeon: restore modeset late in GPU reset path drm/radeon: avoid deadlock in pm path when waiting for fence drm/radeon: don't leave fence blocked process on failed GPU reset
2 parents 344f906 + 668bbc8 commit b1d778b

File tree

7 files changed

+122
-24
lines changed

7 files changed

+122
-24
lines changed

drivers/gpu/drm/radeon/evergreen_cs.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,6 +2654,35 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
26542654
ib[idx+4] = upper_32_bits(offset) & 0xff;
26552655
}
26562656
break;
2657+
case PACKET3_MEM_WRITE:
2658+
{
2659+
u64 offset;
2660+
2661+
if (pkt->count != 3) {
2662+
DRM_ERROR("bad MEM_WRITE (invalid count)\n");
2663+
return -EINVAL;
2664+
}
2665+
r = evergreen_cs_packet_next_reloc(p, &reloc);
2666+
if (r) {
2667+
DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
2668+
return -EINVAL;
2669+
}
2670+
offset = radeon_get_ib_value(p, idx+0);
2671+
offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL;
2672+
if (offset & 0x7) {
2673+
DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n");
2674+
return -EINVAL;
2675+
}
2676+
if ((offset + 8) > radeon_bo_size(reloc->robj)) {
2677+
DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n",
2678+
offset + 8, radeon_bo_size(reloc->robj));
2679+
return -EINVAL;
2680+
}
2681+
offset += reloc->lobj.gpu_offset;
2682+
ib[idx+0] = offset;
2683+
ib[idx+1] = upper_32_bits(offset) & 0xff;
2684+
break;
2685+
}
26572686
case PACKET3_COPY_DW:
26582687
if (pkt->count != 4) {
26592688
DRM_ERROR("bad COPY_DW (invalid count)\n");
@@ -3287,6 +3316,7 @@ static bool evergreen_vm_reg_valid(u32 reg)
32873316

32883317
/* check config regs */
32893318
switch (reg) {
3319+
case WAIT_UNTIL:
32903320
case GRBM_GFX_INDEX:
32913321
case CP_STRMOUT_CNTL:
32923322
case CP_COHER_CNTL:

drivers/gpu/drm/radeon/r600_cs.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,6 +2294,35 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
22942294
ib[idx+4] = upper_32_bits(offset) & 0xff;
22952295
}
22962296
break;
2297+
case PACKET3_MEM_WRITE:
2298+
{
2299+
u64 offset;
2300+
2301+
if (pkt->count != 3) {
2302+
DRM_ERROR("bad MEM_WRITE (invalid count)\n");
2303+
return -EINVAL;
2304+
}
2305+
r = r600_cs_packet_next_reloc(p, &reloc);
2306+
if (r) {
2307+
DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
2308+
return -EINVAL;
2309+
}
2310+
offset = radeon_get_ib_value(p, idx+0);
2311+
offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL;
2312+
if (offset & 0x7) {
2313+
DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n");
2314+
return -EINVAL;
2315+
}
2316+
if ((offset + 8) > radeon_bo_size(reloc->robj)) {
2317+
DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n",
2318+
offset + 8, radeon_bo_size(reloc->robj));
2319+
return -EINVAL;
2320+
}
2321+
offset += reloc->lobj.gpu_offset;
2322+
ib[idx+0] = offset;
2323+
ib[idx+1] = upper_32_bits(offset) & 0xff;
2324+
break;
2325+
}
22972326
case PACKET3_COPY_DW:
22982327
if (pkt->count != 4) {
22992328
DRM_ERROR("bad COPY_DW (invalid count)\n");

drivers/gpu/drm/radeon/radeon.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,13 @@ struct radeon_fence {
225225
int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
226226
int radeon_fence_driver_init(struct radeon_device *rdev);
227227
void radeon_fence_driver_fini(struct radeon_device *rdev);
228+
void radeon_fence_driver_force_completion(struct radeon_device *rdev);
228229
int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring);
229230
void radeon_fence_process(struct radeon_device *rdev, int ring);
230231
bool radeon_fence_signaled(struct radeon_fence *fence);
231232
int radeon_fence_wait(struct radeon_fence *fence, bool interruptible);
232233
int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring);
233-
void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring);
234+
int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring);
234235
int radeon_fence_wait_any(struct radeon_device *rdev,
235236
struct radeon_fence **fences,
236237
bool intr);

drivers/gpu/drm/radeon/radeon_device.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
11641164
struct drm_crtc *crtc;
11651165
struct drm_connector *connector;
11661166
int i, r;
1167+
bool force_completion = false;
11671168

11681169
if (dev == NULL || dev->dev_private == NULL) {
11691170
return -ENODEV;
@@ -1206,8 +1207,16 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
12061207

12071208
mutex_lock(&rdev->ring_lock);
12081209
/* wait for gpu to finish processing current batch */
1209-
for (i = 0; i < RADEON_NUM_RINGS; i++)
1210-
radeon_fence_wait_empty_locked(rdev, i);
1210+
for (i = 0; i < RADEON_NUM_RINGS; i++) {
1211+
r = radeon_fence_wait_empty_locked(rdev, i);
1212+
if (r) {
1213+
/* delay GPU reset to resume */
1214+
force_completion = true;
1215+
}
1216+
}
1217+
if (force_completion) {
1218+
radeon_fence_driver_force_completion(rdev);
1219+
}
12111220
mutex_unlock(&rdev->ring_lock);
12121221

12131222
radeon_save_bios_scratch_regs(rdev);
@@ -1338,7 +1347,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
13381347
}
13391348

13401349
radeon_restore_bios_scratch_regs(rdev);
1341-
drm_helper_resume_force_mode(rdev->ddev);
13421350

13431351
if (!r) {
13441352
for (i = 0; i < RADEON_NUM_RINGS; ++i) {
@@ -1358,11 +1366,14 @@ int radeon_gpu_reset(struct radeon_device *rdev)
13581366
}
13591367
}
13601368
} else {
1369+
radeon_fence_driver_force_completion(rdev);
13611370
for (i = 0; i < RADEON_NUM_RINGS; ++i) {
13621371
kfree(ring_data[i]);
13631372
}
13641373
}
13651374

1375+
drm_helper_resume_force_mode(rdev->ddev);
1376+
13661377
ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
13671378
if (r) {
13681379
/* bad news, how to tell it to userspace ? */

drivers/gpu/drm/radeon/radeon_drv.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,10 @@
6868
* 2.25.0 - eg+: new info request for num SE and num SH
6969
* 2.26.0 - r600-eg: fix htile size computation
7070
* 2.27.0 - r600-SI: Add CS ioctl support for async DMA
71+
* 2.28.0 - r600-eg: Add MEM_WRITE packet support
7172
*/
7273
#define KMS_DRIVER_MAJOR 2
73-
#define KMS_DRIVER_MINOR 27
74+
#define KMS_DRIVER_MINOR 28
7475
#define KMS_DRIVER_PATCHLEVEL 0
7576
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
7677
int radeon_driver_unload_kms(struct drm_device *dev);

drivers/gpu/drm/radeon/radeon_fence.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -609,26 +609,20 @@ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring)
609609
* Returns 0 if the fences have passed, error for all other cases.
610610
* Caller must hold ring lock.
611611
*/
612-
void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring)
612+
int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring)
613613
{
614614
uint64_t seq = rdev->fence_drv[ring].sync_seq[ring];
615+
int r;
615616

616-
while(1) {
617-
int r;
618-
r = radeon_fence_wait_seq(rdev, seq, ring, false, false);
617+
r = radeon_fence_wait_seq(rdev, seq, ring, false, false);
618+
if (r) {
619619
if (r == -EDEADLK) {
620-
mutex_unlock(&rdev->ring_lock);
621-
r = radeon_gpu_reset(rdev);
622-
mutex_lock(&rdev->ring_lock);
623-
if (!r)
624-
continue;
625-
}
626-
if (r) {
627-
dev_err(rdev->dev, "error waiting for ring to become"
628-
" idle (%d)\n", r);
620+
return -EDEADLK;
629621
}
630-
return;
622+
dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n",
623+
ring, r);
631624
}
625+
return 0;
632626
}
633627

634628
/**
@@ -854,20 +848,43 @@ int radeon_fence_driver_init(struct radeon_device *rdev)
854848
*/
855849
void radeon_fence_driver_fini(struct radeon_device *rdev)
856850
{
857-
int ring;
851+
int ring, r;
858852

859853
mutex_lock(&rdev->ring_lock);
860854
for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
861855
if (!rdev->fence_drv[ring].initialized)
862856
continue;
863-
radeon_fence_wait_empty_locked(rdev, ring);
857+
r = radeon_fence_wait_empty_locked(rdev, ring);
858+
if (r) {
859+
/* no need to trigger GPU reset as we are unloading */
860+
radeon_fence_driver_force_completion(rdev);
861+
}
864862
wake_up_all(&rdev->fence_queue);
865863
radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
866864
rdev->fence_drv[ring].initialized = false;
867865
}
868866
mutex_unlock(&rdev->ring_lock);
869867
}
870868

869+
/**
870+
* radeon_fence_driver_force_completion - force all fence waiter to complete
871+
*
872+
* @rdev: radeon device pointer
873+
*
874+
* In case of GPU reset failure make sure no process keep waiting on fence
875+
* that will never complete.
876+
*/
877+
void radeon_fence_driver_force_completion(struct radeon_device *rdev)
878+
{
879+
int ring;
880+
881+
for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
882+
if (!rdev->fence_drv[ring].initialized)
883+
continue;
884+
radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring);
885+
}
886+
}
887+
871888

872889
/*
873890
* Fence debugfs

drivers/gpu/drm/radeon/radeon_pm.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ static void radeon_set_power_state(struct radeon_device *rdev)
234234

235235
static void radeon_pm_set_clocks(struct radeon_device *rdev)
236236
{
237-
int i;
237+
int i, r;
238238

239239
/* no need to take locks, etc. if nothing's going to change */
240240
if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
@@ -248,8 +248,17 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
248248
/* wait for the rings to drain */
249249
for (i = 0; i < RADEON_NUM_RINGS; i++) {
250250
struct radeon_ring *ring = &rdev->ring[i];
251-
if (ring->ready)
252-
radeon_fence_wait_empty_locked(rdev, i);
251+
if (!ring->ready) {
252+
continue;
253+
}
254+
r = radeon_fence_wait_empty_locked(rdev, i);
255+
if (r) {
256+
/* needs a GPU reset dont reset here */
257+
mutex_unlock(&rdev->ring_lock);
258+
up_write(&rdev->pm.mclk_lock);
259+
mutex_unlock(&rdev->ddev->struct_mutex);
260+
return;
261+
}
253262
}
254263

255264
radeon_unmap_vram_bos(rdev);

0 commit comments

Comments
 (0)