@@ -34,6 +34,7 @@ use kernel::{
3434 Arc , Mutex ,
3535 } ,
3636 uapi,
37+ workqueue:: { self , impl_has_work, new_work, Work , WorkItem } ,
3738} ;
3839
3940const DEBUG_CLASS : DebugFlags = DebugFlags :: WorkQueue ;
@@ -173,6 +174,32 @@ pub(crate) trait GenSubmittedWork: Send + Sync {
173174 fn get_fence ( & self ) -> dma_fence:: Fence ;
174175}
175176
177+ #[ pin_data]
178+ struct SubmittedWorkContainer {
179+ #[ pin]
180+ work : Work < Self > ,
181+ inner : Box < dyn GenSubmittedWork > ,
182+ }
183+
184+ impl_has_work ! {
185+ impl HasWork <Self > for SubmittedWorkContainer { self . work }
186+ }
187+
188+ impl WorkItem for SubmittedWorkContainer {
189+ type Pointer = Pin < Box < SubmittedWorkContainer > > ;
190+
191+ fn run ( this : Pin < Box < SubmittedWorkContainer > > ) {
192+ mod_pr_debug ! ( "WorkQueue: Freeing command @ {:?}\n " , this. inner. gpu_va( ) ) ;
193+ }
194+ }
195+
196+ impl SubmittedWorkContainer {
197+ fn inner_mut ( self : Pin < & mut Self > ) -> & mut Box < dyn GenSubmittedWork > {
198+ // SAFETY: inner does not require structural pinning.
199+ unsafe { & mut self . get_unchecked_mut ( ) . inner }
200+ }
201+ }
202+
176203impl < O : OpaqueGpuObject , C : FnOnce ( & mut O , Option < WorkError > ) + Send + Sync > GenSubmittedWork
177204 for SubmittedWork < O , C >
178205{
@@ -221,7 +248,7 @@ struct WorkQueueInner {
221248 pipe_type : PipeType ,
222249 size : u32 ,
223250 wptr : u32 ,
224- pending : Vec < Box < dyn GenSubmittedWork > > ,
251+ pending : Vec < Pin < Box < SubmittedWorkContainer > > > ,
225252 last_token : Option < event:: Token > ,
226253 pending_jobs : usize ,
227254 last_submitted : Option < event:: EventValue > ,
@@ -270,7 +297,7 @@ pub(crate) struct Job {
270297 wq : Arc < WorkQueue :: ver > ,
271298 event_info : QueueEventInfo :: ver ,
272299 start_value : EventValue ,
273- pending : Vec < Box < dyn GenSubmittedWork > > ,
300+ pending : Vec < Pin < Box < SubmittedWorkContainer > > > ,
274301 committed : bool ,
275302 submitted : bool ,
276303 event_count : usize ,
@@ -319,17 +346,23 @@ impl Job::ver {
319346 return Err ( EINVAL ) ;
320347 }
321348
349+ let fence = self . fence . clone ( ) ;
350+ let value = self . event_info . value . next ( ) ;
351+
322352 self . pending . push (
323- Box :: new (
324- SubmittedWork :: < _ , _ > {
325- object : command,
326- value : self . event_info . value . next ( ) ,
327- error : None ,
328- callback : Some ( callback) ,
329- wptr : 0 ,
330- vm_slot,
331- fence : self . fence . clone ( ) ,
332- } ,
353+ Box :: try_pin_init (
354+ try_pin_init ! ( SubmittedWorkContainer {
355+ work <- new_work!( "SubmittedWorkWrapper::work" ) ,
356+ inner: Box :: new( SubmittedWork :: <_, _> {
357+ object: command,
358+ value,
359+ error: None ,
360+ callback: Some ( callback) ,
361+ wptr: 0 ,
362+ vm_slot,
363+ fence,
364+ } , GFP_KERNEL ) ?
365+ } ) ,
333366 GFP_KERNEL ,
334367 ) ?,
335368 GFP_KERNEL ,
@@ -376,7 +409,7 @@ impl Job::ver {
376409 if inner. free_slots ( ) > self . event_count && inner. free_space ( ) > self . pending . len ( ) {
377410 None
378411 } else if let Some ( work) = inner. pending . first ( ) {
379- Some ( work. get_fence ( ) )
412+ Some ( work. inner . get_fence ( ) )
380413 } else {
381414 pr_err ! (
382415 "WorkQueue: Cannot submit, but queue is empty? {} > {}, {} > {} (pend={} ls={:#x?} lc={:#x?}) ev={:#x?} cur={:#x?} slot {:?}\n " ,
@@ -454,11 +487,11 @@ impl Job::ver {
454487 ) ;
455488
456489 for mut command in self . pending . drain ( ..) {
457- command. set_wptr ( wptr) ;
490+ command. as_mut ( ) . inner_mut ( ) . set_wptr ( wptr) ;
458491
459492 let next_wptr = ( wptr + 1 ) % inner. size ;
460493 assert ! ( inner. doneptr( ) != next_wptr) ;
461- inner. info . ring [ wptr as usize ] = command. gpu_va ( ) . get ( ) ;
494+ inner. info . ring [ wptr as usize ] = command. inner . gpu_va ( ) . get ( ) ;
462495 wptr = next_wptr;
463496
464497 // Cannot fail, since we did a reserve(1) above
@@ -863,11 +896,11 @@ impl WorkQueue for WorkQueue::ver {
863896 let mut completed_commands: usize = 0 ;
864897
865898 for cmd in inner. pending . iter ( ) {
866- if cmd. value ( ) <= value {
899+ if cmd. inner . value ( ) <= value {
867900 mod_pr_debug ! (
868901 "WorkQueue({:?}): Command at value {:#x?} complete\n " ,
869902 inner. pipe_type,
870- cmd. value( )
903+ cmd. inner . value( )
871904 ) ;
872905 completed_commands += 1 ;
873906 } else {
@@ -879,25 +912,17 @@ impl WorkQueue for WorkQueue::ver {
879912 return inner. pending . is_empty ( ) ;
880913 }
881914
882- let mut completed = Vec :: new ( ) ;
883-
884- if completed. reserve ( completed_commands, GFP_KERNEL ) . is_err ( ) {
885- pr_crit ! (
886- "WorkQueue({:?}): Failed to allocate space for {} completed commands\n " ,
887- inner. pipe_type,
888- completed_commands
889- ) ;
890- }
891-
915+ let last_wptr = inner. pending [ completed_commands - 1 ] . inner . wptr ( ) ;
892916 let pipe_type = inner. pipe_type ;
893917
894- for cmd in inner. pending . drain ( ..completed_commands) {
895- if completed. push ( cmd, GFP_KERNEL ) . is_err ( ) {
896- pr_crit ! (
897- "WorkQueue({:?}): Failed to signal a completed command\n " ,
898- pipe_type,
899- ) ;
900- }
918+ for mut cmd in inner. pending . drain ( ..completed_commands) {
919+ mod_pr_debug ! (
920+ "WorkQueue({:?}): Queueing command @ {:?} for cleanup\n " ,
921+ pipe_type,
922+ cmd. inner. gpu_va( )
923+ ) ;
924+ cmd. as_mut ( ) . inner_mut ( ) . complete ( ) ;
925+ workqueue:: system ( ) . enqueue ( cmd) ;
901926 }
902927
903928 mod_pr_debug ! (
@@ -909,12 +934,10 @@ impl WorkQueue for WorkQueue::ver {
909934 inner. last_completed,
910935 ) ;
911936
912- if let Some ( i) = completed. last ( ) {
913- inner
914- . info
915- . state
916- . with ( |raw, _inner| raw. cpu_freeptr . store ( i. wptr ( ) , Ordering :: Release ) ) ;
917- }
937+ inner
938+ . info
939+ . state
940+ . with ( |raw, _inner| raw. cpu_freeptr . store ( last_wptr, Ordering :: Release ) ) ;
918941
919942 let empty = inner. pending . is_empty ( ) ;
920943 if empty && inner. pending_jobs == 0 {
@@ -923,16 +946,6 @@ impl WorkQueue for WorkQueue::ver {
923946 inner. last_completed = None ;
924947 }
925948
926- let dev = inner. dev . clone ( ) ;
927- core:: mem:: drop ( inner) ;
928-
929- for cmd in completed. iter_mut ( ) {
930- cmd. complete ( ) ;
931- }
932-
933- let gpu = & dev. data ( ) . gpu ;
934- gpu. add_completed_work ( completed) ;
935-
936949 empty
937950 }
938951
@@ -961,8 +974,8 @@ impl WorkQueue for WorkQueue::ver {
961974 ) ;
962975
963976 for cmd in inner. pending . iter_mut ( ) {
964- if cmd. value ( ) <= value {
965- cmd. mark_error ( error) ;
977+ if cmd. inner . value ( ) <= value {
978+ cmd. as_mut ( ) . inner_mut ( ) . mark_error ( error) ;
966979 } else {
967980 break ;
968981 }
@@ -1003,8 +1016,8 @@ impl WorkQueue for WorkQueue::ver {
10031016 core:: mem:: drop ( inner) ;
10041017
10051018 for mut cmd in cmds {
1006- cmd. mark_error ( error) ;
1007- cmd. complete ( ) ;
1019+ cmd. as_mut ( ) . inner_mut ( ) . mark_error ( error) ;
1020+ cmd. as_mut ( ) . inner_mut ( ) . complete ( ) ;
10081021 }
10091022 }
10101023}
0 commit comments