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:: {
@@ -48,6 +49,8 @@ pub(crate) enum WorkError {
4849 Fault ( regs:: FaultInfo ) ,
4950 /// Work failed due to an error caused by other concurrent GPU work.
5051 Killed ,
52+ /// Channel error
53+ ChannelError ( ChannelErrorType ) ,
5154 /// The GPU crashed.
5255 NoDevice ,
5356 /// Unknown reason.
@@ -79,6 +82,9 @@ impl From<WorkError> for uapi::drm_asahi_result_info {
7982 status : match a {
8083 WorkError :: Timeout => uapi:: drm_asahi_status_DRM_ASAHI_STATUS_TIMEOUT,
8184 WorkError :: Killed => uapi:: drm_asahi_status_DRM_ASAHI_STATUS_KILLED,
85+ WorkError :: ChannelError ( _) => {
86+ uapi:: drm_asahi_status_DRM_ASAHI_STATUS_CHANNEL_ERROR
87+ }
8288 WorkError :: NoDevice => uapi:: drm_asahi_status_DRM_ASAHI_STATUS_NO_DEVICE,
8389 _ => uapi:: drm_asahi_status_DRM_ASAHI_STATUS_UNKNOWN_ERROR,
8490 } ,
@@ -97,6 +103,7 @@ impl From<WorkError> for kernel::error::Error {
97103 WorkError :: Unknown => ENODATA ,
98104 WorkError :: Killed => ECANCELED ,
99105 WorkError :: NoDevice => ENODEV ,
106+ WorkError :: ChannelError ( _) => EIO ,
100107 }
101108 }
102109}
@@ -601,20 +608,26 @@ impl WorkQueue::ver {
601608 size : u32 ,
602609 ) -> Result < Arc < WorkQueue :: ver > > {
603610 let gpu_buf = alloc. private . array_empty_tagged ( 0x2c18 , b"GPBF" ) ?;
604- let shared = & mut alloc. shared ;
611+ let mut state = alloc. shared . new_default :: < RingState > ( ) ?;
612+ let ring = alloc. shared . array_empty ( size as usize ) ?;
605613 let inner = WorkQueueInner :: ver {
606614 dev : dev. into ( ) ,
607615 event_manager,
608- info : alloc. private . new_init (
616+ // Use shared (coherent) state with verbose faults so we can dump state correctly
617+ info : if debug_enabled ( DebugFlags :: VerboseFaults ) {
618+ & mut alloc. shared
619+ } else {
620+ & mut alloc. private
621+ }
622+ . new_init (
609623 try_init ! ( QueueInfo :: ver {
610624 state: {
611- let mut s = shared. new_default:: <RingState >( ) ?;
612- s. with_mut( |raw, _inner| {
625+ state. with_mut( |raw, _inner| {
613626 raw. rb_size = size;
614627 } ) ;
615- s
628+ state
616629 } ,
617- ring: shared . array_empty ( size as usize ) ? ,
630+ ring,
618631 gpu_buf,
619632 notifier_list: notifier_list,
620633 gpu_context: gpu_context,
@@ -639,7 +652,7 @@ impl WorkQueue::ver {
639652 #[ ver( V >= V13_2 && G < G14X ) ]
640653 unk_84_0: 0 ,
641654 unk_84_state: Default :: default ( ) ,
642- unk_88 : 0 ,
655+ error_count : Default :: default ( ) ,
643656 unk_8c: 0 ,
644657 unk_90: 0 ,
645658 unk_94: 0 ,
@@ -744,18 +757,46 @@ impl WorkQueue::ver {
744757 pub ( crate ) fn pipe_type ( & self ) -> PipeType {
745758 self . inner . lock ( ) . pipe_type
746759 }
760+
761+ pub ( crate ) fn dump_info ( & self ) {
762+ pr_info ! ( "WorkQueue @ {:?}:" , self . info_pointer) ;
763+ self . inner . lock ( ) . info . with ( |raw, _inner| {
764+ pr_info ! ( " GPU rptr1: {:#x}" , raw. gpu_rptr1. load( Ordering :: Relaxed ) ) ;
765+ pr_info ! ( " GPU rptr1: {:#x}" , raw. gpu_rptr2. load( Ordering :: Relaxed ) ) ;
766+ pr_info ! ( " GPU rptr1: {:#x}" , raw. gpu_rptr3. load( Ordering :: Relaxed ) ) ;
767+ pr_info ! ( " Event ID: {:#x}" , raw. event_id. load( Ordering :: Relaxed ) ) ;
768+ pr_info ! ( " Busy: {:#x}" , raw. busy. load( Ordering :: Relaxed ) ) ;
769+ pr_info ! ( " Unk 84: {:#x}" , raw. unk_84_state. load( Ordering :: Relaxed ) ) ;
770+ pr_info ! (
771+ " Error count: {:#x}" ,
772+ raw. error_count. load( Ordering :: Relaxed )
773+ ) ;
774+ pr_info ! ( " Pending: {:#x}" , raw. pending. load( Ordering :: Relaxed ) ) ;
775+ } ) ;
776+ }
777+
778+ pub ( crate ) fn info_pointer ( & self ) -> GpuWeakPointer < QueueInfo :: ver > {
779+ self . info_pointer
780+ }
747781}
748782
749783/// Trait used to erase the version-specific type of WorkQueues, to avoid leaking
750784/// version-specificity into the event module.
751785pub ( crate ) trait WorkQueue {
786+ /// Cast as an Any type.
787+ fn as_any ( & self ) -> & dyn Any ;
788+
752789 fn signal ( & self ) -> bool ;
753790 fn mark_error ( & self , value : event:: EventValue , error : WorkError ) ;
754791 fn fail_all ( & self , error : WorkError ) ;
755792}
756793
757794#[ versions( AGX ) ]
758795impl WorkQueue for WorkQueue :: ver {
796+ fn as_any ( & self ) -> & dyn Any {
797+ self
798+ }
799+
759800 /// Signal a workqueue that some work was completed.
760801 ///
761802 /// This will check the event stamp value to find out exactly how many commands were processed.
0 commit comments