Skip to content

Commit 7122e50

Browse files
committed
Merge branch 'drm-fixes-4.1' of git://people.freedesktop.org/~agd5f/linux into drm-fixes
Mostly stability fixes for UVD and VCE, plus a few other bug and regression fixes. * 'drm-fixes-4.1' of git://people.freedesktop.org/~agd5f/linux: drm/radeon: stop trying to suspend UVD sessions drm/radeon: more strictly validate the UVD codec drm/radeon: make UVD handle checking more strict drm/radeon: make VCE handle check more strict drm/radeon: fix userptr lockup drm/radeon: fix userptr BO unpin bug v3 drm/radeon: don't setup audio on asics that don't support it drm/radeon: disable semaphores for UVD V1 (v2)
2 parents 5ebe6af + 12e49fe commit 7122e50

File tree

11 files changed

+190
-87
lines changed

11 files changed

+190
-87
lines changed

drivers/gpu/drm/radeon/radeon.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1673,7 +1673,6 @@ struct radeon_uvd {
16731673
struct radeon_bo *vcpu_bo;
16741674
void *cpu_addr;
16751675
uint64_t gpu_addr;
1676-
void *saved_bo;
16771676
atomic_t handles[RADEON_MAX_UVD_HANDLES];
16781677
struct drm_file *filp[RADEON_MAX_UVD_HANDLES];
16791678
unsigned img_size[RADEON_MAX_UVD_HANDLES];

drivers/gpu/drm/radeon/radeon_asic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1202,7 +1202,7 @@ static struct radeon_asic rs780_asic = {
12021202
static struct radeon_asic_ring rv770_uvd_ring = {
12031203
.ib_execute = &uvd_v1_0_ib_execute,
12041204
.emit_fence = &uvd_v2_2_fence_emit,
1205-
.emit_semaphore = &uvd_v1_0_semaphore_emit,
1205+
.emit_semaphore = &uvd_v2_2_semaphore_emit,
12061206
.cs_parse = &radeon_uvd_cs_parse,
12071207
.ring_test = &uvd_v1_0_ring_test,
12081208
.ib_test = &uvd_v1_0_ib_test,

drivers/gpu/drm/radeon/radeon_asic.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,10 @@ void uvd_v1_0_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
949949
int uvd_v2_2_resume(struct radeon_device *rdev);
950950
void uvd_v2_2_fence_emit(struct radeon_device *rdev,
951951
struct radeon_fence *fence);
952+
bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev,
953+
struct radeon_ring *ring,
954+
struct radeon_semaphore *semaphore,
955+
bool emit_wait);
952956

953957
/* uvd v3.1 */
954958
bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev,

drivers/gpu/drm/radeon/radeon_audio.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,10 @@ void radeon_audio_detect(struct drm_connector *connector,
464464
return;
465465

466466
rdev = connector->encoder->dev->dev_private;
467+
468+
if (!radeon_audio_chipset_supported(rdev))
469+
return;
470+
467471
radeon_encoder = to_radeon_encoder(connector->encoder);
468472
dig = radeon_encoder->enc_priv;
469473

drivers/gpu/drm/radeon/radeon_mn.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ static void radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
142142

143143
list_for_each_entry(bo, &node->bos, mn_list) {
144144

145+
if (!bo->tbo.ttm || bo->tbo.ttm->state != tt_bound)
146+
continue;
147+
145148
r = radeon_bo_reserve(bo, true);
146149
if (r) {
147150
DRM_ERROR("(%ld) failed to reserve user bo\n", r);

drivers/gpu/drm/radeon/radeon_ttm.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -591,8 +591,7 @@ static void radeon_ttm_tt_unpin_userptr(struct ttm_tt *ttm)
591591
{
592592
struct radeon_device *rdev = radeon_get_rdev(ttm->bdev);
593593
struct radeon_ttm_tt *gtt = (void *)ttm;
594-
struct scatterlist *sg;
595-
int i;
594+
struct sg_page_iter sg_iter;
596595

597596
int write = !(gtt->userflags & RADEON_GEM_USERPTR_READONLY);
598597
enum dma_data_direction direction = write ?
@@ -605,9 +604,8 @@ static void radeon_ttm_tt_unpin_userptr(struct ttm_tt *ttm)
605604
/* free the sg table and pages again */
606605
dma_unmap_sg(rdev->dev, ttm->sg->sgl, ttm->sg->nents, direction);
607606

608-
for_each_sg(ttm->sg->sgl, sg, ttm->sg->nents, i) {
609-
struct page *page = sg_page(sg);
610-
607+
for_each_sg_page(ttm->sg->sgl, &sg_iter, ttm->sg->nents, 0) {
608+
struct page *page = sg_page_iter_page(&sg_iter);
611609
if (!(gtt->userflags & RADEON_GEM_USERPTR_READONLY))
612610
set_page_dirty(page);
613611

drivers/gpu/drm/radeon/radeon_uvd.c

Lines changed: 93 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -204,28 +204,32 @@ void radeon_uvd_fini(struct radeon_device *rdev)
204204

205205
int radeon_uvd_suspend(struct radeon_device *rdev)
206206
{
207-
unsigned size;
208-
void *ptr;
209-
int i;
207+
int i, r;
210208

211209
if (rdev->uvd.vcpu_bo == NULL)
212210
return 0;
213211

214-
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
215-
if (atomic_read(&rdev->uvd.handles[i]))
216-
break;
212+
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
213+
uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
214+
if (handle != 0) {
215+
struct radeon_fence *fence;
217216

218-
if (i == RADEON_MAX_UVD_HANDLES)
219-
return 0;
217+
radeon_uvd_note_usage(rdev);
220218

221-
size = radeon_bo_size(rdev->uvd.vcpu_bo);
222-
size -= rdev->uvd_fw->size;
219+
r = radeon_uvd_get_destroy_msg(rdev,
220+
R600_RING_TYPE_UVD_INDEX, handle, &fence);
221+
if (r) {
222+
DRM_ERROR("Error destroying UVD (%d)!\n", r);
223+
continue;
224+
}
223225

224-
ptr = rdev->uvd.cpu_addr;
225-
ptr += rdev->uvd_fw->size;
226+
radeon_fence_wait(fence, false);
227+
radeon_fence_unref(&fence);
226228

227-
rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
228-
memcpy(rdev->uvd.saved_bo, ptr, size);
229+
rdev->uvd.filp[i] = NULL;
230+
atomic_set(&rdev->uvd.handles[i], 0);
231+
}
232+
}
229233

230234
return 0;
231235
}
@@ -246,12 +250,7 @@ int radeon_uvd_resume(struct radeon_device *rdev)
246250
ptr = rdev->uvd.cpu_addr;
247251
ptr += rdev->uvd_fw->size;
248252

249-
if (rdev->uvd.saved_bo != NULL) {
250-
memcpy(ptr, rdev->uvd.saved_bo, size);
251-
kfree(rdev->uvd.saved_bo);
252-
rdev->uvd.saved_bo = NULL;
253-
} else
254-
memset(ptr, 0, size);
253+
memset(ptr, 0, size);
255254

256255
return 0;
257256
}
@@ -396,6 +395,29 @@ static int radeon_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
396395
return 0;
397396
}
398397

398+
static int radeon_uvd_validate_codec(struct radeon_cs_parser *p,
399+
unsigned stream_type)
400+
{
401+
switch (stream_type) {
402+
case 0: /* H264 */
403+
case 1: /* VC1 */
404+
/* always supported */
405+
return 0;
406+
407+
case 3: /* MPEG2 */
408+
case 4: /* MPEG4 */
409+
/* only since UVD 3 */
410+
if (p->rdev->family >= CHIP_PALM)
411+
return 0;
412+
413+
/* fall through */
414+
default:
415+
DRM_ERROR("UVD codec not supported by hardware %d!\n",
416+
stream_type);
417+
return -EINVAL;
418+
}
419+
}
420+
399421
static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
400422
unsigned offset, unsigned buf_sizes[])
401423
{
@@ -436,50 +458,70 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
436458
return -EINVAL;
437459
}
438460

439-
if (msg_type == 1) {
440-
/* it's a decode msg, calc buffer sizes */
441-
r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
442-
/* calc image size (width * height) */
443-
img_size = msg[6] * msg[7];
461+
switch (msg_type) {
462+
case 0:
463+
/* it's a create msg, calc image size (width * height) */
464+
img_size = msg[7] * msg[8];
465+
466+
r = radeon_uvd_validate_codec(p, msg[4]);
444467
radeon_bo_kunmap(bo);
445468
if (r)
446469
return r;
447470

448-
} else if (msg_type == 2) {
471+
/* try to alloc a new handle */
472+
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
473+
if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
474+
DRM_ERROR("Handle 0x%x already in use!\n", handle);
475+
return -EINVAL;
476+
}
477+
478+
if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
479+
p->rdev->uvd.filp[i] = p->filp;
480+
p->rdev->uvd.img_size[i] = img_size;
481+
return 0;
482+
}
483+
}
484+
485+
DRM_ERROR("No more free UVD handles!\n");
486+
return -EINVAL;
487+
488+
case 1:
489+
/* it's a decode msg, validate codec and calc buffer sizes */
490+
r = radeon_uvd_validate_codec(p, msg[4]);
491+
if (!r)
492+
r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
493+
radeon_bo_kunmap(bo);
494+
if (r)
495+
return r;
496+
497+
/* validate the handle */
498+
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
499+
if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
500+
if (p->rdev->uvd.filp[i] != p->filp) {
501+
DRM_ERROR("UVD handle collision detected!\n");
502+
return -EINVAL;
503+
}
504+
return 0;
505+
}
506+
}
507+
508+
DRM_ERROR("Invalid UVD handle 0x%x!\n", handle);
509+
return -ENOENT;
510+
511+
case 2:
449512
/* it's a destroy msg, free the handle */
450513
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
451514
atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
452515
radeon_bo_kunmap(bo);
453516
return 0;
454-
} else {
455-
/* it's a create msg, calc image size (width * height) */
456-
img_size = msg[7] * msg[8];
457-
radeon_bo_kunmap(bo);
458517

459-
if (msg_type != 0) {
460-
DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
461-
return -EINVAL;
462-
}
463-
464-
/* it's a create msg, no special handling needed */
465-
}
466-
467-
/* create or decode, validate the handle */
468-
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
469-
if (atomic_read(&p->rdev->uvd.handles[i]) == handle)
470-
return 0;
471-
}
518+
default:
472519

473-
/* handle not found try to alloc a new one */
474-
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
475-
if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
476-
p->rdev->uvd.filp[i] = p->filp;
477-
p->rdev->uvd.img_size[i] = img_size;
478-
return 0;
479-
}
520+
DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
521+
return -EINVAL;
480522
}
481523

482-
DRM_ERROR("No more free UVD handles!\n");
524+
BUG();
483525
return -EINVAL;
484526
}
485527

0 commit comments

Comments
 (0)