22
33use core:: {
44 cmp,
5- mem,
6- sync:: atomic:: {
7- fence,
8- Ordering , //
9- } , //
5+ mem, //
106} ;
117
128use kernel:: {
@@ -146,30 +142,36 @@ static_assert!(align_of::<MsgqData>() == GSP_PAGE_SIZE);
146142#[ repr( C ) ]
147143// There is no struct defined for this in the open-gpu-kernel-source headers.
148144// Instead it is defined by code in `GspMsgQueuesInit()`.
149- struct Msgq {
145+ // TODO: Revert to private once `IoView` projections replace the `gsp_mem` module.
146+ pub ( super ) struct Msgq {
150147 /// Header for sending messages, including the write pointer.
151- tx : MsgqTxHeader ,
148+ pub ( super ) tx : MsgqTxHeader ,
152149 /// Header for receiving messages, including the read pointer.
153- rx : MsgqRxHeader ,
150+ pub ( super ) rx : MsgqRxHeader ,
154151 /// The message queue proper.
155152 msgq : MsgqData ,
156153}
157154
158155/// Structure shared between the driver and the GSP and containing the command and message queues.
159156#[ repr( C ) ]
160- struct GspMem {
157+ // TODO: Revert to private once `IoView` projections replace the `gsp_mem` module.
158+ pub ( super ) struct GspMem {
161159 /// Self-mapping page table entries.
162- ptes : PteArray < { GSP_PAGE_SIZE / size_of :: < u64 > ( ) } > ,
160+ ptes : PteArray < { Self :: PTE_ARRAY_SIZE } > ,
163161 /// CPU queue: the driver writes commands here, and the GSP reads them. It also contains the
164162 /// write and read pointers that the CPU updates.
165163 ///
166164 /// This member is read-only for the GSP.
167- cpuq : Msgq ,
165+ pub ( super ) cpuq : Msgq ,
168166 /// GSP queue: the GSP writes messages here, and the driver reads them. It also contains the
169167 /// write and read pointers that the GSP updates.
170168 ///
171169 /// This member is read-only for the driver.
172- gspq : Msgq ,
170+ pub ( super ) gspq : Msgq ,
171+ }
172+
173+ impl GspMem {
174+ const PTE_ARRAY_SIZE : usize = GSP_PAGE_SIZE / size_of :: < u64 > ( ) ;
173175}
174176
175177// SAFETY: These structs don't meet the no-padding requirements of AsBytes but
@@ -201,9 +203,19 @@ impl DmaGspMem {
201203
202204 let gsp_mem =
203205 CoherentAllocation :: < GspMem > :: alloc_coherent ( dev, 1 , GFP_KERNEL | __GFP_ZERO) ?;
204- dma_write ! ( gsp_mem[ 0 ] . ptes = PteArray :: new( gsp_mem. dma_handle( ) ) ?) ?;
205- dma_write ! ( gsp_mem[ 0 ] . cpuq. tx = MsgqTxHeader :: new( MSGQ_SIZE , RX_HDR_OFF , MSGQ_NUM_PAGES ) ) ?;
206- dma_write ! ( gsp_mem[ 0 ] . cpuq. rx = MsgqRxHeader :: new( ) ) ?;
206+
207+ let start = gsp_mem. dma_handle ( ) ;
208+ // Write values one by one to avoid an on-stack instance of `PteArray`.
209+ for i in 0 ..GspMem :: PTE_ARRAY_SIZE {
210+ dma_write ! ( gsp_mem, [ 0 ] ?. ptes. 0 [ i] , PteArray :: <0 >:: entry( start, i) ?) ;
211+ }
212+
213+ dma_write ! (
214+ gsp_mem,
215+ [ 0 ] ?. cpuq. tx,
216+ MsgqTxHeader :: new( MSGQ_SIZE , RX_HDR_OFF , MSGQ_NUM_PAGES )
217+ ) ;
218+ dma_write ! ( gsp_mem, [ 0 ] ?. cpuq. rx, MsgqRxHeader :: new( ) ) ;
207219
208220 Ok ( Self ( gsp_mem) )
209221 }
@@ -317,12 +329,7 @@ impl DmaGspMem {
317329 //
318330 // - The returned value is between `0` and `MSGQ_NUM_PAGES`.
319331 fn gsp_write_ptr ( & self ) -> u32 {
320- let gsp_mem = self . 0 . start_ptr ( ) ;
321-
322- // SAFETY:
323- // - The 'CoherentAllocation' contains at least one object.
324- // - By the invariants of `CoherentAllocation` the pointer is valid.
325- ( unsafe { ( * gsp_mem) . gspq . tx . write_ptr ( ) } % MSGQ_NUM_PAGES )
332+ super :: fw:: gsp_mem:: gsp_write_ptr ( & self . 0 )
326333 }
327334
328335 // Returns the index of the memory page the GSP will read the next command from.
@@ -331,12 +338,7 @@ impl DmaGspMem {
331338 //
332339 // - The returned value is between `0` and `MSGQ_NUM_PAGES`.
333340 fn gsp_read_ptr ( & self ) -> u32 {
334- let gsp_mem = self . 0 . start_ptr ( ) ;
335-
336- // SAFETY:
337- // - The 'CoherentAllocation' contains at least one object.
338- // - By the invariants of `CoherentAllocation` the pointer is valid.
339- ( unsafe { ( * gsp_mem) . gspq . rx . read_ptr ( ) } % MSGQ_NUM_PAGES )
341+ super :: fw:: gsp_mem:: gsp_read_ptr ( & self . 0 )
340342 }
341343
342344 // Returns the index of the memory page the CPU can read the next message from.
@@ -345,27 +347,12 @@ impl DmaGspMem {
345347 //
346348 // - The returned value is between `0` and `MSGQ_NUM_PAGES`.
347349 fn cpu_read_ptr ( & self ) -> u32 {
348- let gsp_mem = self . 0 . start_ptr ( ) ;
349-
350- // SAFETY:
351- // - The ['CoherentAllocation'] contains at least one object.
352- // - By the invariants of CoherentAllocation the pointer is valid.
353- ( unsafe { ( * gsp_mem) . cpuq . rx . read_ptr ( ) } % MSGQ_NUM_PAGES )
350+ super :: fw:: gsp_mem:: cpu_read_ptr ( & self . 0 )
354351 }
355352
356353 // Informs the GSP that it can send `elem_count` new pages into the message queue.
357354 fn advance_cpu_read_ptr ( & mut self , elem_count : u32 ) {
358- let rptr = self . cpu_read_ptr ( ) . wrapping_add ( elem_count) % MSGQ_NUM_PAGES ;
359-
360- // Ensure read pointer is properly ordered.
361- fence ( Ordering :: SeqCst ) ;
362-
363- let gsp_mem = self . 0 . start_ptr_mut ( ) ;
364-
365- // SAFETY:
366- // - The 'CoherentAllocation' contains at least one object.
367- // - By the invariants of `CoherentAllocation` the pointer is valid.
368- unsafe { ( * gsp_mem) . cpuq . rx . set_read_ptr ( rptr) } ;
355+ super :: fw:: gsp_mem:: advance_cpu_read_ptr ( & self . 0 , elem_count)
369356 }
370357
371358 // Returns the index of the memory page the CPU can write the next command to.
@@ -374,26 +361,12 @@ impl DmaGspMem {
374361 //
375362 // - The returned value is between `0` and `MSGQ_NUM_PAGES`.
376363 fn cpu_write_ptr ( & self ) -> u32 {
377- let gsp_mem = self . 0 . start_ptr ( ) ;
378-
379- // SAFETY:
380- // - The 'CoherentAllocation' contains at least one object.
381- // - By the invariants of `CoherentAllocation` the pointer is valid.
382- ( unsafe { ( * gsp_mem) . cpuq . tx . write_ptr ( ) } % MSGQ_NUM_PAGES )
364+ super :: fw:: gsp_mem:: cpu_write_ptr ( & self . 0 )
383365 }
384366
385367 // Informs the GSP that it can process `elem_count` new pages from the command queue.
386368 fn advance_cpu_write_ptr ( & mut self , elem_count : u32 ) {
387- let wptr = self . cpu_write_ptr ( ) . wrapping_add ( elem_count) & MSGQ_NUM_PAGES ;
388- let gsp_mem = self . 0 . start_ptr_mut ( ) ;
389-
390- // SAFETY:
391- // - The 'CoherentAllocation' contains at least one object.
392- // - By the invariants of `CoherentAllocation` the pointer is valid.
393- unsafe { ( * gsp_mem) . cpuq . tx . set_write_ptr ( wptr) } ;
394-
395- // Ensure all command data is visible before triggering the GSP read.
396- fence ( Ordering :: SeqCst ) ;
369+ super :: fw:: gsp_mem:: advance_cpu_write_ptr ( & self . 0 , elem_count)
397370 }
398371}
399372
0 commit comments