@@ -493,25 +493,35 @@ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi,
493
493
*
494
494
* @p: parser context
495
495
* @handle: handle to validate
496
+ * @allocated: allocated a new handle?
496
497
*
497
498
* Validates the handle and return the found session index or -EINVAL
498
499
* we we don't have another free session index.
499
500
*/
500
- int radeon_vce_validate_handle (struct radeon_cs_parser * p , uint32_t handle )
501
+ static int radeon_vce_validate_handle (struct radeon_cs_parser * p ,
502
+ uint32_t handle , bool * allocated )
501
503
{
502
504
unsigned i ;
503
505
506
+ * allocated = false;
507
+
504
508
/* validate the handle */
505
509
for (i = 0 ; i < RADEON_MAX_VCE_HANDLES ; ++ i ) {
506
- if (atomic_read (& p -> rdev -> vce .handles [i ]) == handle )
510
+ if (atomic_read (& p -> rdev -> vce .handles [i ]) == handle ) {
511
+ if (p -> rdev -> vce .filp [i ] != p -> filp ) {
512
+ DRM_ERROR ("VCE handle collision detected!\n" );
513
+ return - EINVAL ;
514
+ }
507
515
return i ;
516
+ }
508
517
}
509
518
510
519
/* handle not found try to alloc a new one */
511
520
for (i = 0 ; i < RADEON_MAX_VCE_HANDLES ; ++ i ) {
512
521
if (!atomic_cmpxchg (& p -> rdev -> vce .handles [i ], 0 , handle )) {
513
522
p -> rdev -> vce .filp [i ] = p -> filp ;
514
523
p -> rdev -> vce .img_size [i ] = 0 ;
524
+ * allocated = true;
515
525
return i ;
516
526
}
517
527
}
@@ -529,29 +539,32 @@ int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle)
529
539
int radeon_vce_cs_parse (struct radeon_cs_parser * p )
530
540
{
531
541
int session_idx = -1 ;
532
- bool destroyed = false;
542
+ bool destroyed = false, created = false, allocated = false ;
533
543
uint32_t tmp , handle = 0 ;
534
544
uint32_t * size = & tmp ;
535
- int i , r ;
545
+ int i , r = 0 ;
536
546
537
547
while (p -> idx < p -> chunk_ib -> length_dw ) {
538
548
uint32_t len = radeon_get_ib_value (p , p -> idx );
539
549
uint32_t cmd = radeon_get_ib_value (p , p -> idx + 1 );
540
550
541
551
if ((len < 8 ) || (len & 3 )) {
542
552
DRM_ERROR ("invalid VCE command length (%d)!\n" , len );
543
- return - EINVAL ;
553
+ r = - EINVAL ;
554
+ goto out ;
544
555
}
545
556
546
557
if (destroyed ) {
547
558
DRM_ERROR ("No other command allowed after destroy!\n" );
548
- return - EINVAL ;
559
+ r = - EINVAL ;
560
+ goto out ;
549
561
}
550
562
551
563
switch (cmd ) {
552
564
case 0x00000001 : // session
553
565
handle = radeon_get_ib_value (p , p -> idx + 2 );
554
- session_idx = radeon_vce_validate_handle (p , handle );
566
+ session_idx = radeon_vce_validate_handle (p , handle ,
567
+ & allocated );
555
568
if (session_idx < 0 )
556
569
return session_idx ;
557
570
size = & p -> rdev -> vce .img_size [session_idx ];
@@ -561,6 +574,13 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
561
574
break ;
562
575
563
576
case 0x01000001 : // create
577
+ created = true;
578
+ if (!allocated ) {
579
+ DRM_ERROR ("Handle already in use!\n" );
580
+ r = - EINVAL ;
581
+ goto out ;
582
+ }
583
+
564
584
* size = radeon_get_ib_value (p , p -> idx + 8 ) *
565
585
radeon_get_ib_value (p , p -> idx + 10 ) *
566
586
8 * 3 / 2 ;
@@ -578,12 +598,12 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
578
598
r = radeon_vce_cs_reloc (p , p -> idx + 10 , p -> idx + 9 ,
579
599
* size );
580
600
if (r )
581
- return r ;
601
+ goto out ;
582
602
583
603
r = radeon_vce_cs_reloc (p , p -> idx + 12 , p -> idx + 11 ,
584
604
* size / 3 );
585
605
if (r )
586
- return r ;
606
+ goto out ;
587
607
break ;
588
608
589
609
case 0x02000001 : // destroy
@@ -594,44 +614,55 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
594
614
r = radeon_vce_cs_reloc (p , p -> idx + 3 , p -> idx + 2 ,
595
615
* size * 2 );
596
616
if (r )
597
- return r ;
617
+ goto out ;
598
618
break ;
599
619
600
620
case 0x05000004 : // video bitstream buffer
601
621
tmp = radeon_get_ib_value (p , p -> idx + 4 );
602
622
r = radeon_vce_cs_reloc (p , p -> idx + 3 , p -> idx + 2 ,
603
623
tmp );
604
624
if (r )
605
- return r ;
625
+ goto out ;
606
626
break ;
607
627
608
628
case 0x05000005 : // feedback buffer
609
629
r = radeon_vce_cs_reloc (p , p -> idx + 3 , p -> idx + 2 ,
610
630
4096 );
611
631
if (r )
612
- return r ;
632
+ goto out ;
613
633
break ;
614
634
615
635
default :
616
636
DRM_ERROR ("invalid VCE command (0x%x)!\n" , cmd );
617
- return - EINVAL ;
637
+ r = - EINVAL ;
638
+ goto out ;
618
639
}
619
640
620
641
if (session_idx == -1 ) {
621
642
DRM_ERROR ("no session command at start of IB\n" );
622
- return - EINVAL ;
643
+ r = - EINVAL ;
644
+ goto out ;
623
645
}
624
646
625
647
p -> idx += len / 4 ;
626
648
}
627
649
628
- if (destroyed ) {
629
- /* IB contains a destroy msg, free the handle */
650
+ if (allocated && !created ) {
651
+ DRM_ERROR ("New session without create command!\n" );
652
+ r = - ENOENT ;
653
+ }
654
+
655
+ out :
656
+ if ((!r && destroyed ) || (r && allocated )) {
657
+ /*
658
+ * IB contains a destroy msg or we have allocated an
659
+ * handle and got an error, anyway free the handle
660
+ */
630
661
for (i = 0 ; i < RADEON_MAX_VCE_HANDLES ; ++ i )
631
662
atomic_cmpxchg (& p -> rdev -> vce .handles [i ], handle , 0 );
632
663
}
633
664
634
- return 0 ;
665
+ return r ;
635
666
}
636
667
637
668
/**
0 commit comments