@@ -77,13 +77,6 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
7777 ih -> rptr_addr = dma_addr + ih -> ring_size + 4 ;
7878 ih -> rptr_cpu = & ih -> ring [(ih -> ring_size / 4 ) + 1 ];
7979
80- #ifdef CONFIG_LOONGARCH
81- INIT_WORK (& adev -> irq .ih .fix_work , amdgpu_ih_handle_fix_work );
82- for (r = 0 ; r < (adev -> irq .ih .ring_size >> 2 ); r ++ )
83- adev -> irq .ih .ring [r ] = 0xDEADBEFF ;
84- /* memory barrier for writing into ih ring */
85- mb ();
86- #endif
8780
8881 } else {
8982 unsigned wptr_offs , rptr_offs ;
@@ -113,16 +106,17 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
113106 ih -> rptr_addr = adev -> wb .gpu_addr + rptr_offs * 4 ;
114107 ih -> rptr_cpu = & adev -> wb .wb [rptr_offs ];
115108
116- #ifdef CONFIG_LOONGARCH
117- INIT_WORK (& adev -> irq .ih .fix_work , amdgpu_ih_handle_fix_work );
118- for (r = 0 ; r < (adev -> irq .ih .ring_size >> 2 ); r ++ )
119- adev -> irq .ih .ring [r ] = 0xDEADBEFF ;
120- /* memory barrier for writing into ih ring */
121- mb ();
122- #endif
123-
124109 }
125110
111+ #ifdef CONFIG_LOONGARCH
112+ INIT_WORK (& ih -> fix_work , amdgpu_ih_handle_fix_work );
113+ ih -> adev = adev ;
114+ atomic_set (& ih -> lock , 0 );
115+ for (r = 0 ; r < (ih -> ring_size >> 2 ); r ++ )
116+ ih -> ring [r ] = 0xDEADBEFF ;
117+ /* ensure data active */
118+ mb ();
119+ #endif
126120 init_waitqueue_head (& ih -> wait_process );
127121 return 0 ;
128122}
@@ -143,7 +137,7 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
143137 return ;
144138
145139#ifdef CONFIG_LOONGARCH
146- cancel_work_sync (& adev -> irq . ih . fix_work );
140+ cancel_work_sync (& ih -> fix_work );
147141#endif
148142
149143 if (ih -> use_bus_addr ) {
@@ -173,7 +167,7 @@ static int amdgpu_ih_fix_loongarch_pcie_order_start(struct amdgpu_ih_ring *ih,
173167 u32 rptr , u32 wptr ,
174168 bool forever )
175169{
176- int i ;
170+ int i , j ;
177171 int check_cnt = 0 ;
178172 u32 ring_end = ih -> ring_size >> 2 ;
179173
@@ -193,13 +187,19 @@ static int amdgpu_ih_fix_loongarch_pcie_order_start(struct amdgpu_ih_ring *ih,
193187 msleep (20 );
194188
195189 for (i = rptr ; i < wptr ; i += 1 ) {
196- if (le32_to_cpu (ih -> ring [i ]) == 0xDEADBEFF && (i % 4 ) != 3 )
190+ j = i + 1 ;
191+ j = (j < wptr ) ? j : rptr ;
192+ if (le32_to_cpu (ih -> ring [i ]) == 0xDEADBEFF &&
193+ le32_to_cpu (ih -> ring [j ]) == 0xDEADBEFF )
197194 goto restart_check ;
198195 }
199196
200197 if (rptr > wptr ) {
201198 for (i = 0 ; i < wptr ; i += 1 ) {
202- if (le32_to_cpu (ih -> ring [i ]) == 0xDEADBEFF && (i % 4 ) != 3 )
199+ j = i + 1 ;
200+ j = (j < wptr ) ? j : 0 ;
201+ if (le32_to_cpu (ih -> ring [i ]) == 0xDEADBEFF &&
202+ le32_to_cpu (ih -> ring [j ]) == 0xDEADBEFF )
203203 goto restart_check ;
204204 }
205205 }
@@ -235,35 +235,42 @@ static int amdgpu_ih_fix_loongarch_pcie_order_end(struct amdgpu_ih_ring *ih,
235235
236236static void amdgpu_ih_handle_fix_work (struct work_struct * work )
237237{
238- struct amdgpu_device * adev =
239- container_of (work , struct amdgpu_device , irq . ih . fix_work );
240- struct amdgpu_ih_ring * ih = & adev -> irq . ih ;
238+ struct amdgpu_ih_ring * ih =
239+ container_of (work , struct amdgpu_ih_ring , fix_work );
240+ struct amdgpu_device * adev = ih -> adev ;
241241
242242 u32 wptr ;
243243 u32 old_rptr ;
244+ int restart_fg = 0 ;
244245
245246restart :
247+ if (restart_fg && atomic_xchg (& ih -> lock , 1 )) {
248+ atomic_set (& adev -> irq .cs_lock , 0 );
249+ return ;
250+ }
246251
247252 wptr = amdgpu_ih_get_wptr (adev , ih );
248253 /* Order reading of wptr vs. reading of IH ring data */
249254 rmb ();
250255
251256 old_rptr = ih -> rptr ;
252- amdgpu_ih_fix_loongarch_pcie_order_start (& adev -> irq . ih , old_rptr , wptr , true);
257+ amdgpu_ih_fix_loongarch_pcie_order_start (ih , old_rptr , wptr , true);
253258
254- while (adev -> irq . ih . rptr != wptr ) {
259+ while (ih -> rptr != wptr ) {
255260 amdgpu_irq_dispatch (adev , ih );
256261 ih -> rptr &= ih -> ptr_mask ;
257262 }
258263
259- amdgpu_ih_fix_loongarch_pcie_order_end (& adev -> irq . ih , old_rptr , adev -> irq . ih . rptr );
264+ amdgpu_ih_fix_loongarch_pcie_order_end (ih , old_rptr , ih -> rptr );
260265
261266 amdgpu_ih_set_rptr (adev , ih );
262- /* memory barrier for setting rptr */
267+ atomic_set ( & ih -> lock , 0 );
263268 mb ();
264269
265- if (ih -> rptr != amdgpu_ih_get_wptr (adev , ih ))
270+ if (ih -> rptr != amdgpu_ih_get_wptr (adev , ih )) {
271+ restart_fg = 1 ;
266272 goto restart ;
273+ }
267274
268275 atomic_set (& adev -> irq .cs_lock , 0 );
269276}
@@ -354,22 +361,28 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
354361 wptr = amdgpu_ih_get_wptr (adev , ih );
355362
356363restart_ih :
364+ #ifdef CONFIG_LOONGARCH
365+ /* is somebody else already processing irqs? */
366+ if (atomic_xchg (& ih -> lock , 1 ))
367+ return IRQ_NONE ;
368+ #endif
357369 count = AMDGPU_IH_MAX_NUM_IVS ;
358370 dev_dbg (adev -> dev , "%s: rptr %d, wptr %d\n" , __func__ , ih -> rptr , wptr );
359371
360372 /* Order reading of wptr vs. reading of IH ring data */
361373 rmb ();
362374
363375#ifdef CONFIG_LOONGARCH
364- old_rptr = adev -> irq . ih . rptr ;
365- r = amdgpu_ih_fix_loongarch_pcie_order_start (& adev -> irq . ih , old_rptr , wptr , false);
376+ old_rptr = ih -> rptr ;
377+ r = amdgpu_ih_fix_loongarch_pcie_order_start (ih , old_rptr , wptr , false);
366378 if (r ) {
367- if (old_rptr == ((wptr + 16 ) & adev -> irq .ih .ptr_mask ) ||
368- old_rptr == ((wptr + 32 ) & adev -> irq .ih .ptr_mask ))
379+ if (old_rptr == ((wptr + 16 ) & ih -> ptr_mask ) ||
380+ old_rptr == ((wptr + 32 ) & ih -> ptr_mask )) {
381+ atomic_set (& ih -> lock , 0 );
369382 return IRQ_NONE ;
370-
383+ }
371384 atomic_xchg (& adev -> irq .cs_lock , 1 );
372- schedule_work (& adev -> irq . ih . fix_work );
385+ schedule_work (& ih -> fix_work );
373386 return IRQ_NONE ;
374387 }
375388#endif
@@ -380,12 +393,15 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
380393 }
381394
382395#ifdef CONFIG_LOONGARCH
383- amdgpu_ih_fix_loongarch_pcie_order_end (& adev -> irq . ih , old_rptr , adev -> irq . ih . rptr );
396+ amdgpu_ih_fix_loongarch_pcie_order_end (ih , old_rptr , ih -> rptr );
384397#endif
385398
386399 if (!ih -> overflow )
387400 amdgpu_ih_set_rptr (adev , ih );
388401
402+ #ifdef CONFIG_LOONGARCH
403+ atomic_set (& ih -> lock , 0 );
404+ #endif
389405 wake_up_all (& ih -> wait_process );
390406
391407 /* make sure wptr hasn't changed while processing */
0 commit comments