@@ -204,28 +204,32 @@ void radeon_uvd_fini(struct radeon_device *rdev)
204
204
205
205
int radeon_uvd_suspend (struct radeon_device * rdev )
206
206
{
207
- unsigned size ;
208
- void * ptr ;
209
- int i ;
207
+ int i , r ;
210
208
211
209
if (rdev -> uvd .vcpu_bo == NULL )
212
210
return 0 ;
213
211
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 ;
217
216
218
- if (i == RADEON_MAX_UVD_HANDLES )
219
- return 0 ;
217
+ radeon_uvd_note_usage (rdev );
220
218
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
+ }
223
225
224
- ptr = rdev -> uvd . cpu_addr ;
225
- ptr += rdev -> uvd_fw -> size ;
226
+ radeon_fence_wait ( fence , false) ;
227
+ radeon_fence_unref ( & fence ) ;
226
228
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
+ }
229
233
230
234
return 0 ;
231
235
}
@@ -246,12 +250,7 @@ int radeon_uvd_resume(struct radeon_device *rdev)
246
250
ptr = rdev -> uvd .cpu_addr ;
247
251
ptr += rdev -> uvd_fw -> size ;
248
252
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 );
255
254
256
255
return 0 ;
257
256
}
@@ -396,6 +395,29 @@ static int radeon_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
396
395
return 0 ;
397
396
}
398
397
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
+
399
421
static int radeon_uvd_cs_msg (struct radeon_cs_parser * p , struct radeon_bo * bo ,
400
422
unsigned offset , unsigned buf_sizes [])
401
423
{
@@ -436,50 +458,70 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
436
458
return - EINVAL ;
437
459
}
438
460
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 ]);
444
467
radeon_bo_kunmap (bo );
445
468
if (r )
446
469
return r ;
447
470
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 :
449
512
/* it's a destroy msg, free the handle */
450
513
for (i = 0 ; i < RADEON_MAX_UVD_HANDLES ; ++ i )
451
514
atomic_cmpxchg (& p -> rdev -> uvd .handles [i ], handle , 0 );
452
515
radeon_bo_kunmap (bo );
453
516
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 );
458
517
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 :
472
519
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 ;
480
522
}
481
523
482
- DRM_ERROR ( "No more free UVD handles!\n" );
524
+ BUG ( );
483
525
return - EINVAL ;
484
526
}
485
527
0 commit comments