@@ -35,6 +35,7 @@ use kernel::{
3535 } ,
3636 types:: ForeignOwnable ,
3737 uapi,
38+ workqueue:: { self , impl_has_work, new_work, Work , WorkItem } ,
3839} ;
3940
4041const DEBUG_CLASS : DebugFlags = DebugFlags :: WorkQueue ;
@@ -175,6 +176,32 @@ pub(crate) trait GenSubmittedWork: Send + Sync {
175176 fn get_fence ( & self ) -> dma_fence:: Fence ;
176177}
177178
179+ #[ pin_data]
180+ struct SubmittedWorkContainer {
181+ #[ pin]
182+ work : Work < Self > ,
183+ inner : KBox < dyn GenSubmittedWork > ,
184+ }
185+
186+ impl_has_work ! {
187+ impl HasWork <Self > for SubmittedWorkContainer { self . work }
188+ }
189+
190+ impl WorkItem for SubmittedWorkContainer {
191+ type Pointer = Pin < KBox < SubmittedWorkContainer > > ;
192+
193+ fn run ( this : Pin < KBox < SubmittedWorkContainer > > ) {
194+ mod_pr_debug ! ( "WorkQueue: Freeing command @ {:?}\n " , this. inner. gpu_va( ) ) ;
195+ }
196+ }
197+
198+ impl SubmittedWorkContainer {
199+ fn inner_mut ( self : Pin < & mut Self > ) -> & mut KBox < dyn GenSubmittedWork > {
200+ // SAFETY: inner does not require structural pinning.
201+ unsafe { & mut self . get_unchecked_mut ( ) . inner }
202+ }
203+ }
204+
178205impl < O : OpaqueGpuObject , C : FnOnce ( & mut O , Option < WorkError > ) + Send + Sync > GenSubmittedWork
179206 for SubmittedWork < O , C >
180207{
@@ -223,7 +250,7 @@ struct WorkQueueInner {
223250 pipe_type : PipeType ,
224251 size : u32 ,
225252 wptr : u32 ,
226- pending : Vec < Box < dyn GenSubmittedWork > > ,
253+ pending : KVec < Pin < KBox < SubmittedWorkContainer > > > ,
227254 last_token : Option < event:: Token > ,
228255 pending_jobs : usize ,
229256 last_submitted : Option < event:: EventValue > ,
@@ -272,7 +299,7 @@ pub(crate) struct Job {
272299 wq : Arc < WorkQueue :: ver > ,
273300 event_info : QueueEventInfo :: ver ,
274301 start_value : EventValue ,
275- pending : Vec < Box < dyn GenSubmittedWork > > ,
302+ pending : KVec < Pin < KBox < SubmittedWorkContainer > > > ,
276303 committed : bool ,
277304 submitted : bool ,
278305 event_count : usize ,
@@ -321,17 +348,23 @@ impl Job::ver {
321348 return Err ( EINVAL ) ;
322349 }
323350
351+ let fence = self . fence . clone ( ) ;
352+ let value = self . event_info . value . next ( ) ;
353+
324354 self . pending . push (
325- Box :: new (
326- SubmittedWork :: < _ , _ > {
327- object : command,
328- value : self . event_info . value . next ( ) ,
329- error : None ,
330- callback : Some ( callback) ,
331- wptr : 0 ,
332- vm_slot,
333- fence : self . fence . clone ( ) ,
334- } ,
355+ KBox :: try_pin_init (
356+ try_pin_init ! ( SubmittedWorkContainer {
357+ work <- new_work!( "SubmittedWorkWrapper::work" ) ,
358+ inner: KBox :: new( SubmittedWork :: <_, _> {
359+ object: command,
360+ value,
361+ error: None ,
362+ callback: Some ( callback) ,
363+ wptr: 0 ,
364+ vm_slot,
365+ fence,
366+ } , GFP_KERNEL ) ?
367+ } ) ,
335368 GFP_KERNEL ,
336369 ) ?,
337370 GFP_KERNEL ,
@@ -378,7 +411,7 @@ impl Job::ver {
378411 if inner. free_slots ( ) > self . event_count && inner. free_space ( ) > self . pending . len ( ) {
379412 None
380413 } else if let Some ( work) = inner. pending . first ( ) {
381- Some ( work. get_fence ( ) )
414+ Some ( work. inner . get_fence ( ) )
382415 } else {
383416 pr_err ! (
384417 "WorkQueue: Cannot submit, but queue is empty? {} > {}, {} > {} (pend={} ls={:#x?} lc={:#x?}) ev={:#x?} cur={:#x?} slot {:?}\n " ,
@@ -456,11 +489,11 @@ impl Job::ver {
456489 ) ;
457490
458491 for mut command in self . pending . drain ( ..) {
459- command. set_wptr ( wptr) ;
492+ command. as_mut ( ) . inner_mut ( ) . set_wptr ( wptr) ;
460493
461494 let next_wptr = ( wptr + 1 ) % inner. size ;
462495 assert ! ( inner. doneptr( ) != next_wptr) ;
463- inner. info . ring [ wptr as usize ] = command. gpu_va ( ) . get ( ) ;
496+ inner. info . ring [ wptr as usize ] = command. inner . gpu_va ( ) . get ( ) ;
464497 wptr = next_wptr;
465498
466499 // Cannot fail, since we did a reserve(1) above
@@ -865,11 +898,11 @@ impl WorkQueue for WorkQueue::ver {
865898 let mut completed_commands: usize = 0 ;
866899
867900 for cmd in inner. pending . iter ( ) {
868- if cmd. value ( ) <= value {
901+ if cmd. inner . value ( ) <= value {
869902 mod_pr_debug ! (
870903 "WorkQueue({:?}): Command at value {:#x?} complete\n " ,
871904 inner. pipe_type,
872- cmd. value( )
905+ cmd. inner . value( )
873906 ) ;
874907 completed_commands += 1 ;
875908 } else {
@@ -881,25 +914,17 @@ impl WorkQueue for WorkQueue::ver {
881914 return inner. pending . is_empty ( ) ;
882915 }
883916
884- let mut completed = Vec :: new ( ) ;
885-
886- if completed. reserve ( completed_commands, GFP_KERNEL ) . is_err ( ) {
887- pr_crit ! (
888- "WorkQueue({:?}): Failed to allocate space for {} completed commands\n " ,
889- inner. pipe_type,
890- completed_commands
891- ) ;
892- }
893-
917+ let last_wptr = inner. pending [ completed_commands - 1 ] . inner . wptr ( ) ;
894918 let pipe_type = inner. pipe_type ;
895919
896- for cmd in inner. pending . drain ( ..completed_commands) {
897- if completed. push ( cmd, GFP_KERNEL ) . is_err ( ) {
898- pr_crit ! (
899- "WorkQueue({:?}): Failed to signal a completed command\n " ,
900- pipe_type,
901- ) ;
902- }
920+ for mut cmd in inner. pending . drain ( ..completed_commands) {
921+ mod_pr_debug ! (
922+ "WorkQueue({:?}): Queueing command @ {:?} for cleanup\n " ,
923+ pipe_type,
924+ cmd. inner. gpu_va( )
925+ ) ;
926+ cmd. as_mut ( ) . inner_mut ( ) . complete ( ) ;
927+ workqueue:: system ( ) . enqueue ( cmd) ;
903928 }
904929
905930 mod_pr_debug ! (
@@ -911,12 +936,10 @@ impl WorkQueue for WorkQueue::ver {
911936 inner. last_completed,
912937 ) ;
913938
914- if let Some ( i) = completed. last ( ) {
915- inner
916- . info
917- . state
918- . with ( |raw, _inner| raw. cpu_freeptr . store ( i. wptr ( ) , Ordering :: Release ) ) ;
919- }
939+ inner
940+ . info
941+ . state
942+ . with ( |raw, _inner| raw. cpu_freeptr . store ( last_wptr, Ordering :: Release ) ) ;
920943
921944 let empty = inner. pending . is_empty ( ) ;
922945 if empty && inner. pending_jobs == 0 {
@@ -925,16 +948,6 @@ impl WorkQueue for WorkQueue::ver {
925948 inner. last_completed = None ;
926949 }
927950
928- let dev = inner. dev . clone ( ) ;
929- core:: mem:: drop ( inner) ;
930-
931- for cmd in completed. iter_mut ( ) {
932- cmd. complete ( ) ;
933- }
934-
935- let gpu = & dev. data ( ) . gpu ;
936- gpu. add_completed_work ( completed) ;
937-
938951 empty
939952 }
940953
@@ -963,8 +976,8 @@ impl WorkQueue for WorkQueue::ver {
963976 ) ;
964977
965978 for cmd in inner. pending . iter_mut ( ) {
966- if cmd. value ( ) <= value {
967- cmd. mark_error ( error) ;
979+ if cmd. inner . value ( ) <= value {
980+ cmd. as_mut ( ) . inner_mut ( ) . mark_error ( error) ;
968981 } else {
969982 break ;
970983 }
@@ -1005,8 +1018,8 @@ impl WorkQueue for WorkQueue::ver {
10051018 core:: mem:: drop ( inner) ;
10061019
10071020 for mut cmd in cmds {
1008- cmd. mark_error ( error) ;
1009- cmd. complete ( ) ;
1021+ cmd. as_mut ( ) . inner_mut ( ) . mark_error ( error) ;
1022+ cmd. as_mut ( ) . inner_mut ( ) . complete ( ) ;
10101023 }
10111024 }
10121025}
0 commit comments