1414//! up its associated event.
1515
1616use crate :: debug:: * ;
17- use crate :: fw:: channels:: PipeType ;
17+ use crate :: fw:: channels:: { ChannelErrorType , PipeType } ;
1818use crate :: fw:: types:: * ;
1919use crate :: fw:: workqueue:: * ;
2020use crate :: no_debug;
2121use crate :: object:: OpaqueGpuObject ;
2222use crate :: regs:: FaultReason ;
2323use crate :: { channel, driver, event, fw, gpu, object, regs} ;
24+ use core:: any:: Any ;
2425use core:: num:: NonZeroU64 ;
2526use core:: sync:: atomic:: Ordering ;
2627use kernel:: {
@@ -47,6 +48,8 @@ pub(crate) enum WorkError {
4748 Fault ( regs:: FaultInfo ) ,
4849 /// Work failed due to an error caused by other concurrent GPU work.
4950 Killed ,
51+ /// Channel error
52+ ChannelError ( ChannelErrorType ) ,
5053 /// The GPU crashed.
5154 NoDevice ,
5255 /// Unknown reason.
@@ -78,6 +81,9 @@ impl From<WorkError> for uapi::drm_asahi_result_info {
7881 status : match a {
7982 WorkError :: Timeout => uapi:: drm_asahi_status_DRM_ASAHI_STATUS_TIMEOUT,
8083 WorkError :: Killed => uapi:: drm_asahi_status_DRM_ASAHI_STATUS_KILLED,
84+ WorkError :: ChannelError ( _) => {
85+ uapi:: drm_asahi_status_DRM_ASAHI_STATUS_CHANNEL_ERROR
86+ }
8187 WorkError :: NoDevice => uapi:: drm_asahi_status_DRM_ASAHI_STATUS_NO_DEVICE,
8288 _ => uapi:: drm_asahi_status_DRM_ASAHI_STATUS_UNKNOWN_ERROR,
8389 } ,
@@ -96,6 +102,7 @@ impl From<WorkError> for kernel::error::Error {
96102 WorkError :: Unknown => ENODATA ,
97103 WorkError :: Killed => ECANCELED ,
98104 WorkError :: NoDevice => ENODEV ,
105+ WorkError :: ChannelError ( _) => EIO ,
99106 }
100107 }
101108}
@@ -600,20 +607,26 @@ impl WorkQueue::ver {
600607 size : u32 ,
601608 ) -> Result < Arc < WorkQueue :: ver > > {
602609 let gpu_buf = alloc. private . array_empty_tagged ( 0x2c18 , b"GPBF" ) ?;
603- let shared = & mut alloc. shared ;
610+ let mut state = alloc. shared . new_default :: < RingState > ( ) ?;
611+ let ring = alloc. shared . array_empty ( size as usize ) ?;
604612 let inner = WorkQueueInner :: ver {
605613 dev : dev. into ( ) ,
606614 event_manager,
607- info : alloc. private . new_init (
615+ // Use shared (coherent) state with verbose faults so we can dump state correctly
616+ info : if debug_enabled ( DebugFlags :: VerboseFaults ) {
617+ & mut alloc. shared
618+ } else {
619+ & mut alloc. private
620+ }
621+ . new_init (
608622 try_init ! ( QueueInfo :: ver {
609623 state: {
610- let mut s = shared. new_default:: <RingState >( ) ?;
611- s. with_mut( |raw, _inner| {
624+ state. with_mut( |raw, _inner| {
612625 raw. rb_size = size;
613626 } ) ;
614- s
627+ state
615628 } ,
616- ring: shared . array_empty ( size as usize ) ? ,
629+ ring,
617630 gpu_buf,
618631 notifier_list: notifier_list,
619632 gpu_context: gpu_context,
@@ -638,7 +651,7 @@ impl WorkQueue::ver {
638651 #[ ver( V >= V13_2 && G < G14X ) ]
639652 unk_84_0: 0 ,
640653 unk_84_state: Default :: default ( ) ,
641- unk_88 : 0 ,
654+ error_count : Default :: default ( ) ,
642655 unk_8c: 0 ,
643656 unk_90: 0 ,
644657 unk_94: 0 ,
@@ -743,18 +756,46 @@ impl WorkQueue::ver {
743756 pub ( crate ) fn pipe_type ( & self ) -> PipeType {
744757 self . inner . lock ( ) . pipe_type
745758 }
759+
760+ pub ( crate ) fn dump_info ( & self ) {
761+ pr_info ! ( "WorkQueue @ {:?}:" , self . info_pointer) ;
762+ self . inner . lock ( ) . info . with ( |raw, _inner| {
763+ pr_info ! ( " GPU rptr1: {:#x}" , raw. gpu_rptr1. load( Ordering :: Relaxed ) ) ;
764+ pr_info ! ( " GPU rptr1: {:#x}" , raw. gpu_rptr2. load( Ordering :: Relaxed ) ) ;
765+ pr_info ! ( " GPU rptr1: {:#x}" , raw. gpu_rptr3. load( Ordering :: Relaxed ) ) ;
766+ pr_info ! ( " Event ID: {:#x}" , raw. event_id. load( Ordering :: Relaxed ) ) ;
767+ pr_info ! ( " Busy: {:#x}" , raw. busy. load( Ordering :: Relaxed ) ) ;
768+ pr_info ! ( " Unk 84: {:#x}" , raw. unk_84_state. load( Ordering :: Relaxed ) ) ;
769+ pr_info ! (
770+ " Error count: {:#x}" ,
771+ raw. error_count. load( Ordering :: Relaxed )
772+ ) ;
773+ pr_info ! ( " Pending: {:#x}" , raw. pending. load( Ordering :: Relaxed ) ) ;
774+ } ) ;
775+ }
776+
777+ pub ( crate ) fn info_pointer ( & self ) -> GpuWeakPointer < QueueInfo :: ver > {
778+ self . info_pointer
779+ }
746780}
747781
748782/// Trait used to erase the version-specific type of WorkQueues, to avoid leaking
749783/// version-specificity into the event module.
750784pub ( crate ) trait WorkQueue {
785+ /// Cast as an Any type.
786+ fn as_any ( & self ) -> & dyn Any ;
787+
751788 fn signal ( & self ) -> bool ;
752789 fn mark_error ( & self , value : event:: EventValue , error : WorkError ) ;
753790 fn fail_all ( & self , error : WorkError ) ;
754791}
755792
756793#[ versions( AGX ) ]
757794impl WorkQueue for WorkQueue :: ver {
795+ fn as_any ( & self ) -> & dyn Any {
796+ self
797+ }
798+
758799 /// Signal a workqueue that some work was completed.
759800 ///
760801 /// This will check the event stamp value to find out exactly how many commands were processed.
0 commit comments