@@ -531,7 +531,7 @@ impl File {
531531
532532 match data. op {
533533 uapi:: drm_asahi_bind_op_ASAHI_BIND_OP_BIND => Self :: do_gem_bind ( device, data, file) ,
534- uapi:: drm_asahi_bind_op_ASAHI_BIND_OP_UNBIND => Err ( ENOTSUPP ) ,
534+ uapi:: drm_asahi_bind_op_ASAHI_BIND_OP_UNBIND => Self :: do_gem_unbind ( device , data , file ) ,
535535 uapi:: drm_asahi_bind_op_ASAHI_BIND_OP_UNBIND_ALL => {
536536 Self :: do_gem_unbind_all ( device, data, file)
537537 }
@@ -621,6 +621,66 @@ impl File {
621621 Ok ( 0 )
622622 }
623623
624+ pub ( crate ) fn do_gem_unbind (
625+ _device : & AsahiDevice ,
626+ data : & mut uapi:: drm_asahi_gem_bind ,
627+ file : & DrmFile ,
628+ ) -> Result < u32 > {
629+ if data. offset != 0 || data. flags != 0 || data. handle != 0 {
630+ cls_pr_debug ! ( Errors , "gem_unbind: offset/flags/handle not zero\n " ) ;
631+ return Err ( EINVAL ) ;
632+ }
633+
634+ if ( data. addr | data. range ) as usize & mmu:: UAT_PGMSK != 0 {
635+ cls_pr_debug ! (
636+ Errors ,
637+ "gem_bind: Addr/range/offset not page aligned: {:#x} {:#x}\n " ,
638+ data. addr,
639+ data. range
640+ ) ;
641+ return Err ( EINVAL ) ; // Must be page aligned
642+ }
643+
644+ let start = data. addr ;
645+ let end = data. addr . checked_add ( data. range ) . ok_or ( EINVAL ) ?;
646+ let range = start..end;
647+
648+ if !VM_USER_RANGE . is_superset ( range. clone ( ) ) {
649+ cls_pr_debug ! (
650+ Errors ,
651+ "gem_bind: Invalid unmap range {:#x}..{:#x} (not contained in user range)\n " ,
652+ start,
653+ end
654+ ) ;
655+ return Err ( EINVAL ) ; // Invalid map range
656+ }
657+
658+ let guard = file
659+ . inner ( )
660+ . vms ( )
661+ . get ( data. vm_id . try_into ( ) ?)
662+ . ok_or ( ENOENT ) ?;
663+
664+ // Clone it immediately so we aren't holding the XArray lock
665+ let vm = guard. borrow ( ) . vm . clone ( ) ;
666+ let kernel_range = guard. borrow ( ) . kernel_range . clone ( ) ;
667+ core:: mem:: drop ( guard) ;
668+
669+ if kernel_range. overlaps ( range. clone ( ) ) {
670+ cls_pr_debug ! (
671+ Errors ,
672+ "gem_bind: Invalid unmap range {:#x}..{:#x} (intrudes in kernel range)\n " ,
673+ start,
674+ end
675+ ) ;
676+ return Err ( EINVAL ) ;
677+ }
678+
679+ vm. unmap_range ( range. start , range. range ( ) ) ?;
680+
681+ Ok ( 0 )
682+ }
683+
624684 pub ( crate ) fn unbind_gem_object ( file : & DrmFile , bo : & gem:: Object ) -> Result {
625685 let mut index = 0 ;
626686 loop {
0 commit comments