2727#include "amdgpu_ih.h"
2828#include "amdgpu_reset.h"
2929
30+ #ifdef CONFIG_LOONGARCH
31+ static void amdgpu_ih_handle_fix_work (struct work_struct * work );
32+ #endif
33+
3034/**
3135 * amdgpu_ih_ring_init - initialize the IH state
3236 *
@@ -72,6 +76,15 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
7276 ih -> wptr_cpu = & ih -> ring [ih -> ring_size / 4 ];
7377 ih -> rptr_addr = dma_addr + ih -> ring_size + 4 ;
7478 ih -> rptr_cpu = & ih -> ring [(ih -> ring_size / 4 ) + 1 ];
79+
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
87+
7588 } else {
7689 unsigned wptr_offs , rptr_offs ;
7790
@@ -99,6 +112,15 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
99112 ih -> wptr_cpu = & adev -> wb .wb [wptr_offs ];
100113 ih -> rptr_addr = adev -> wb .gpu_addr + rptr_offs * 4 ;
101114 ih -> rptr_cpu = & adev -> wb .wb [rptr_offs ];
115+
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+
102124 }
103125
104126 init_waitqueue_head (& ih -> wait_process );
@@ -120,6 +142,10 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
120142 if (!ih -> ring )
121143 return ;
122144
145+ #ifdef CONFIG_LOONGARCH
146+ cancel_work_sync (& adev -> irq .ih .fix_work );
147+ #endif
148+
123149 if (ih -> use_bus_addr ) {
124150
125151 /* add 8 bytes for the rptr/wptr shadows and
@@ -136,6 +162,113 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
136162 }
137163}
138164
165+ #ifdef CONFIG_LOONGARCH
166+
167+ int amdgpu_ih_fix_is_busy (struct amdgpu_device * adev )
168+ {
169+ return atomic_read (& adev -> irq .cs_lock );
170+ }
171+
172+ static int amdgpu_ih_fix_loongarch_pcie_order_start (struct amdgpu_ih_ring * ih ,
173+ u32 rptr , u32 wptr ,
174+ bool forever )
175+ {
176+ int i ;
177+ int check_cnt = 0 ;
178+ u32 ring_end = ih -> ring_size >> 2 ;
179+
180+ if (rptr == wptr )
181+ return 0 ;
182+
183+ rptr = rptr >> 2 ;
184+ wptr = wptr >> 2 ;
185+
186+ wptr = (rptr > wptr ) ? ring_end : wptr ;
187+
188+ restart_check :
189+ if (!forever && ++ check_cnt > 1 )
190+ return - ENAVAIL ;
191+
192+ if (forever )
193+ msleep (20 );
194+
195+ for (i = rptr ; i < wptr ; i += 1 ) {
196+ if (le32_to_cpu (ih -> ring [i ]) == 0xDEADBEFF )
197+ goto restart_check ;
198+ }
199+
200+ if (rptr > wptr ) {
201+ for (i = 0 ; i < wptr ; i += 1 ) {
202+ if (le32_to_cpu (ih -> ring [i ]) == 0xDEADBEFF )
203+ goto restart_check ;
204+ }
205+ }
206+
207+ return 0 ;
208+ }
209+
210+ static int amdgpu_ih_fix_loongarch_pcie_order_end (struct amdgpu_ih_ring * ih ,
211+ u32 rptr , u32 wptr )
212+ {
213+ int i ;
214+ u32 ring_end = ih -> ring_size >> 2 ;
215+
216+ if (rptr == wptr )
217+ return 0 ;
218+
219+ rptr = rptr >> 2 ;
220+ wptr = wptr >> 2 ;
221+
222+ wptr = (rptr > wptr ) ? ring_end : wptr ;
223+
224+ for (i = rptr ; i < wptr ; i += 1 )
225+ ih -> ring [i ] = 0xDEADBEFF ;
226+
227+ if (rptr > wptr ) {
228+ for (i = 0 ; i < wptr ; i += 1 )
229+ ih -> ring [i ] = 0xDEADBEFF ;
230+ }
231+ /* memory barrier for writing into ih ring */
232+ mb ();
233+ return 0 ;
234+ }
235+
236+ static void amdgpu_ih_handle_fix_work (struct work_struct * work )
237+ {
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 ;
241+
242+ u32 wptr ;
243+ u32 old_rptr ;
244+
245+ restart :
246+
247+ wptr = amdgpu_ih_get_wptr (adev , ih );
248+ /* Order reading of wptr vs. reading of IH ring data */
249+ rmb ();
250+
251+ old_rptr = ih -> rptr ;
252+ amdgpu_ih_fix_loongarch_pcie_order_start (& adev -> irq .ih , old_rptr , wptr , true);
253+
254+ while (adev -> irq .ih .rptr != wptr ) {
255+ amdgpu_irq_dispatch (adev , ih );
256+ ih -> rptr &= ih -> ptr_mask ;
257+ }
258+
259+ amdgpu_ih_fix_loongarch_pcie_order_end (& adev -> irq .ih , old_rptr , adev -> irq .ih .rptr );
260+
261+ amdgpu_ih_set_rptr (adev , ih );
262+ /* memory barrier for setting rptr */
263+ mb ();
264+
265+ if (ih -> rptr != amdgpu_ih_get_wptr (adev , ih ))
266+ goto restart ;
267+
268+ atomic_set (& adev -> irq .cs_lock , 0 );
269+ }
270+ #endif
271+
139272/**
140273 * amdgpu_ih_ring_write - write IV to the ring buffer
141274 *
@@ -210,6 +343,10 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
210343{
211344 unsigned int count ;
212345 u32 wptr ;
346+ #ifdef CONFIG_LOONGARCH
347+ u32 old_rptr ;
348+ int r ;
349+ #endif
213350
214351 if (!ih -> enabled || adev -> shutdown )
215352 return IRQ_NONE ;
@@ -223,11 +360,28 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
223360 /* Order reading of wptr vs. reading of IH ring data */
224361 rmb ();
225362
363+ #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);
366+ if (r ) {
367+ if (old_rptr == ((wptr + 16 ) & adev -> irq .ih .ptr_mask ))
368+ return IRQ_NONE ;
369+
370+ atomic_xchg (& adev -> irq .cs_lock , 1 );
371+ schedule_work (& adev -> irq .ih .fix_work );
372+ return IRQ_NONE ;
373+ }
374+ #endif
375+
226376 while (ih -> rptr != wptr && -- count ) {
227377 amdgpu_irq_dispatch (adev , ih );
228378 ih -> rptr &= ih -> ptr_mask ;
229379 }
230380
381+ #ifdef CONFIG_LOONGARCH
382+ amdgpu_ih_fix_loongarch_pcie_order_end (& adev -> irq .ih , old_rptr , adev -> irq .ih .rptr );
383+ #endif
384+
231385 if (!ih -> overflow )
232386 amdgpu_ih_set_rptr (adev , ih );
233387
0 commit comments