~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sparc/kernel/pci_msi.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /arch/sparc/kernel/pci_msi.c (Architecture sparc64) and /arch/alpha/kernel/pci_msi.c (Architecture alpha)


  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /* pci_msi.c: Sparc64 MSI support common layer    
  3  *                                                
  4  * Copyright (C) 2007 David S. Miller (davem@d    
  5  */                                               
  6 #include <linux/kernel.h>                         
  7 #include <linux/interrupt.h>                      
  8 #include <linux/of.h>                             
  9 #include <linux/platform_device.h>                
 10 #include <linux/slab.h>                           
 11 #include <linux/irq.h>                            
 12                                                   
 13 #include "pci_impl.h"                             
 14                                                   
 15 static irqreturn_t sparc64_msiq_interrupt(int     
 16 {                                                 
 17         struct sparc64_msiq_cookie *msiq_cooki    
 18         struct pci_pbm_info *pbm = msiq_cookie    
 19         unsigned long msiqid = msiq_cookie->ms    
 20         const struct sparc64_msiq_ops *ops;       
 21         unsigned long orig_head, head;            
 22         int err;                                  
 23                                                   
 24         ops = pbm->msi_ops;                       
 25                                                   
 26         err = ops->get_head(pbm, msiqid, &head    
 27         if (unlikely(err < 0))                    
 28                 goto err_get_head;                
 29                                                   
 30         orig_head = head;                         
 31         for (;;) {                                
 32                 unsigned long msi;                
 33                                                   
 34                 err = ops->dequeue_msi(pbm, ms    
 35                 if (likely(err > 0)) {            
 36                         unsigned int irq;         
 37                                                   
 38                         irq = pbm->msi_irq_tab    
 39                         generic_handle_irq(irq    
 40                 }                                 
 41                                                   
 42                 if (unlikely(err < 0))            
 43                         goto err_dequeue;         
 44                                                   
 45                 if (err == 0)                     
 46                         break;                    
 47         }                                         
 48         if (likely(head != orig_head)) {          
 49                 err = ops->set_head(pbm, msiqi    
 50                 if (unlikely(err < 0))            
 51                         goto err_set_head;        
 52         }                                         
 53         return IRQ_HANDLED;                       
 54                                                   
 55 err_get_head:                                     
 56         printk(KERN_EMERG "MSI: Get head on ms    
 57                msiqid, err);                      
 58         goto err_out;                             
 59                                                   
 60 err_dequeue:                                      
 61         printk(KERN_EMERG "MSI: Dequeue head[%    
 62                "gives error %d\n",                
 63                head, msiqid, err);                
 64         goto err_out;                             
 65                                                   
 66 err_set_head:                                     
 67         printk(KERN_EMERG "MSI: Set head[%lu]     
 68                "gives error %d\n",                
 69                head, msiqid, err);                
 70         goto err_out;                             
 71                                                   
 72 err_out:                                          
 73         return IRQ_NONE;                          
 74 }                                                 
 75                                                   
 76 static u32 pick_msiq(struct pci_pbm_info *pbm)    
 77 {                                                 
 78         static DEFINE_SPINLOCK(rotor_lock);       
 79         unsigned long flags;                      
 80         u32 ret, rotor;                           
 81                                                   
 82         spin_lock_irqsave(&rotor_lock, flags);    
 83                                                   
 84         rotor = pbm->msiq_rotor;                  
 85         ret = pbm->msiq_first + rotor;            
 86                                                   
 87         if (++rotor >= pbm->msiq_num)             
 88                 rotor = 0;                        
 89         pbm->msiq_rotor = rotor;                  
 90                                                   
 91         spin_unlock_irqrestore(&rotor_lock, fl    
 92                                                   
 93         return ret;                               
 94 }                                                 
 95                                                   
 96                                                   
 97 static int alloc_msi(struct pci_pbm_info *pbm)    
 98 {                                                 
 99         int i;                                    
100                                                   
101         for (i = 0; i < pbm->msi_num; i++) {      
102                 if (!test_and_set_bit(i, pbm->    
103                         return i + pbm->msi_fi    
104         }                                         
105                                                   
106         return -ENOENT;                           
107 }                                                 
108                                                   
109 static void free_msi(struct pci_pbm_info *pbm,    
110 {                                                 
111         msi_num -= pbm->msi_first;                
112         clear_bit(msi_num, pbm->msi_bitmap);      
113 }                                                 
114                                                   
115 static struct irq_chip msi_irq = {                
116         .name           = "PCI-MSI",              
117         .irq_mask       = pci_msi_mask_irq,       
118         .irq_unmask     = pci_msi_unmask_irq,     
119         .irq_enable     = pci_msi_unmask_irq,     
120         .irq_disable    = pci_msi_mask_irq,       
121         /* XXX affinity XXX */                    
122 };                                                
123                                                   
124 static int sparc64_setup_msi_irq(unsigned int     
125                                  struct pci_de    
126                                  struct msi_de    
127 {                                                 
128         struct pci_pbm_info *pbm = pdev->dev.a    
129         const struct sparc64_msiq_ops *ops = p    
130         struct msi_msg msg;                       
131         int msi, err;                             
132         u32 msiqid;                               
133                                                   
134         *irq_p = irq_alloc(0, 0);                 
135         err = -ENOMEM;                            
136         if (!*irq_p)                              
137                 goto out_err;                     
138                                                   
139         irq_set_chip_and_handler_name(*irq_p,     
140                                       "MSI");     
141                                                   
142         err = alloc_msi(pbm);                     
143         if (unlikely(err < 0))                    
144                 goto out_irq_free;                
145                                                   
146         msi = err;                                
147                                                   
148         msiqid = pick_msiq(pbm);                  
149                                                   
150         err = ops->msi_setup(pbm, msiqid, msi,    
151                              (entry->pci.msi_a    
152         if (err)                                  
153                 goto out_msi_free;                
154                                                   
155         pbm->msi_irq_table[msi - pbm->msi_firs    
156                                                   
157         if (entry->pci.msi_attrib.is_64) {        
158                 msg.address_hi = pbm->msi64_st    
159                 msg.address_lo = pbm->msi64_st    
160         } else {                                  
161                 msg.address_hi = 0;               
162                 msg.address_lo = pbm->msi32_st    
163         }                                         
164         msg.data = msi;                           
165                                                   
166         irq_set_msi_desc(*irq_p, entry);          
167         pci_write_msi_msg(*irq_p, &msg);          
168                                                   
169         return 0;                                 
170                                                   
171 out_msi_free:                                     
172         free_msi(pbm, msi);                       
173                                                   
174 out_irq_free:                                     
175         irq_set_chip(*irq_p, NULL);               
176         irq_free(*irq_p);                         
177         *irq_p = 0;                               
178                                                   
179 out_err:                                          
180         return err;                               
181 }                                                 
182                                                   
183 static void sparc64_teardown_msi_irq(unsigned     
184                                      struct pc    
185 {                                                 
186         struct pci_pbm_info *pbm = pdev->dev.a    
187         const struct sparc64_msiq_ops *ops = p    
188         unsigned int msi_num;                     
189         int i, err;                               
190                                                   
191         for (i = 0; i < pbm->msi_num; i++) {      
192                 if (pbm->msi_irq_table[i] == i    
193                         break;                    
194         }                                         
195         if (i >= pbm->msi_num) {                  
196                 pci_err(pdev, "%s: teardown: N    
197                         irq);                     
198                 return;                           
199         }                                         
200                                                   
201         msi_num = pbm->msi_first + i;             
202         pbm->msi_irq_table[i] = ~0U;              
203                                                   
204         err = ops->msi_teardown(pbm, msi_num);    
205         if (err) {                                
206                 pci_err(pdev, "%s: teardown: o    
207                         "irq %u, gives error %    
208                         err);                     
209                 return;                           
210         }                                         
211                                                   
212         free_msi(pbm, msi_num);                   
213                                                   
214         irq_set_chip(irq, NULL);                  
215         irq_free(irq);                            
216 }                                                 
217                                                   
218 static int msi_bitmap_alloc(struct pci_pbm_inf    
219 {                                                 
220         unsigned long size, bits_per_ulong;       
221                                                   
222         bits_per_ulong = sizeof(unsigned long)    
223         size = (pbm->msi_num + (bits_per_ulong    
224         size /= 8;                                
225         BUG_ON(size % sizeof(unsigned long));     
226                                                   
227         pbm->msi_bitmap = kzalloc(size, GFP_KE    
228         if (!pbm->msi_bitmap)                     
229                 return -ENOMEM;                   
230                                                   
231         return 0;                                 
232 }                                                 
233                                                   
234 static void msi_bitmap_free(struct pci_pbm_inf    
235 {                                                 
236         kfree(pbm->msi_bitmap);                   
237         pbm->msi_bitmap = NULL;                   
238 }                                                 
239                                                   
240 static int msi_table_alloc(struct pci_pbm_info    
241 {                                                 
242         int size, i;                              
243                                                   
244         size = pbm->msiq_num * sizeof(struct s    
245         pbm->msiq_irq_cookies = kzalloc(size,     
246         if (!pbm->msiq_irq_cookies)               
247                 return -ENOMEM;                   
248                                                   
249         for (i = 0; i < pbm->msiq_num; i++) {     
250                 struct sparc64_msiq_cookie *p;    
251                                                   
252                 p = &pbm->msiq_irq_cookies[i];    
253                 p->pbm = pbm;                     
254                 p->msiqid = pbm->msiq_first +     
255         }                                         
256                                                   
257         size = pbm->msi_num * sizeof(unsigned     
258         pbm->msi_irq_table = kzalloc(size, GFP    
259         if (!pbm->msi_irq_table) {                
260                 kfree(pbm->msiq_irq_cookies);     
261                 pbm->msiq_irq_cookies = NULL;     
262                 return -ENOMEM;                   
263         }                                         
264                                                   
265         return 0;                                 
266 }                                                 
267                                                   
268 static void msi_table_free(struct pci_pbm_info    
269 {                                                 
270         kfree(pbm->msiq_irq_cookies);             
271         pbm->msiq_irq_cookies = NULL;             
272                                                   
273         kfree(pbm->msi_irq_table);                
274         pbm->msi_irq_table = NULL;                
275 }                                                 
276                                                   
277 static int bringup_one_msi_queue(struct pci_pb    
278                                  const struct     
279                                  unsigned long    
280                                  unsigned long    
281 {                                                 
282         int irq = ops->msiq_build_irq(pbm, msi    
283         int err, nid;                             
284                                                   
285         if (irq < 0)                              
286                 return irq;                       
287                                                   
288         nid = pbm->numa_node;                     
289         if (nid != -1) {                          
290                 irq_set_affinity(irq, cpumask_    
291         }                                         
292         err = request_irq(irq, sparc64_msiq_in    
293                           "MSIQ",                 
294                           &pbm->msiq_irq_cooki    
295         if (err)                                  
296                 return err;                       
297                                                   
298         return 0;                                 
299 }                                                 
300                                                   
301 static int sparc64_bringup_msi_queues(struct p    
302                                       const st    
303 {                                                 
304         int i;                                    
305                                                   
306         for (i = 0; i < pbm->msiq_num; i++) {     
307                 unsigned long msiqid = i + pbm    
308                 unsigned long devino = i + pbm    
309                 int err;                          
310                                                   
311                 err = bringup_one_msi_queue(pb    
312                 if (err)                          
313                         return err;               
314         }                                         
315                                                   
316         return 0;                                 
317 }                                                 
318                                                   
319 void sparc64_pbm_msi_init(struct pci_pbm_info     
320                           const struct sparc64    
321 {                                                 
322         const u32 *val;                           
323         int len;                                  
324                                                   
325         val = of_get_property(pbm->op->dev.of_    
326         if (!val || len != 4)                     
327                 goto no_msi;                      
328         pbm->msiq_num = *val;                     
329         if (pbm->msiq_num) {                      
330                 const struct msiq_prop {          
331                         u32 first_msiq;           
332                         u32 num_msiq;             
333                         u32 first_devino;         
334                 } *mqp;                           
335                 const struct msi_range_prop {     
336                         u32 first_msi;            
337                         u32 num_msi;              
338                 } *mrng;                          
339                 const struct addr_range_prop {    
340                         u32 msi32_high;           
341                         u32 msi32_low;            
342                         u32 msi32_len;            
343                         u32 msi64_high;           
344                         u32 msi64_low;            
345                         u32 msi64_len;            
346                 } *arng;                          
347                                                   
348                 val = of_get_property(pbm->op-    
349                 if (!val || len != 4)             
350                         goto no_msi;              
351                                                   
352                 pbm->msiq_ent_count = *val;       
353                                                   
354                 mqp = of_get_property(pbm->op-    
355                                       "msi-eq-    
356                 if (!mqp)                         
357                         mqp = of_get_property(    
358                                                   
359                 if (!mqp || len != sizeof(stru    
360                         goto no_msi;              
361                                                   
362                 pbm->msiq_first = mqp->first_m    
363                 pbm->msiq_first_devino = mqp->    
364                                                   
365                 val = of_get_property(pbm->op-    
366                 if (!val || len != 4)             
367                         goto no_msi;              
368                 pbm->msi_num = *val;              
369                                                   
370                 mrng = of_get_property(pbm->op    
371                 if (!mrng || len != sizeof(str    
372                         goto no_msi;              
373                 pbm->msi_first = mrng->first_m    
374                                                   
375                 val = of_get_property(pbm->op-    
376                 if (!val || len != 4)             
377                         goto no_msi;              
378                 pbm->msi_data_mask = *val;        
379                                                   
380                 val = of_get_property(pbm->op-    
381                 if (!val || len != 4)             
382                         goto no_msi;              
383                 pbm->msix_data_width = *val;      
384                                                   
385                 arng = of_get_property(pbm->op    
386                                        &len);     
387                 if (!arng || len != sizeof(str    
388                         goto no_msi;              
389                 pbm->msi32_start = ((u64)arng-    
390                         (u64) arng->msi32_low;    
391                 pbm->msi64_start = ((u64)arng-    
392                         (u64) arng->msi64_low;    
393                 pbm->msi32_len = arng->msi32_l    
394                 pbm->msi64_len = arng->msi64_l    
395                                                   
396                 if (msi_bitmap_alloc(pbm))        
397                         goto no_msi;              
398                                                   
399                 if (msi_table_alloc(pbm)) {       
400                         msi_bitmap_free(pbm);     
401                         goto no_msi;              
402                 }                                 
403                                                   
404                 if (ops->msiq_alloc(pbm)) {       
405                         msi_table_free(pbm);      
406                         msi_bitmap_free(pbm);     
407                         goto no_msi;              
408                 }                                 
409                                                   
410                 if (sparc64_bringup_msi_queues    
411                         ops->msiq_free(pbm);      
412                         msi_table_free(pbm);      
413                         msi_bitmap_free(pbm);     
414                         goto no_msi;              
415                 }                                 
416                                                   
417                 printk(KERN_INFO "%s: MSI Queu    
418                        "devino[0x%x]\n",          
419                        pbm->name,                 
420                        pbm->msiq_first, pbm->m    
421                        pbm->msiq_ent_count,       
422                        pbm->msiq_first_devino)    
423                 printk(KERN_INFO "%s: MSI firs    
424                        "width[%u]\n",             
425                        pbm->name,                 
426                        pbm->msi_first, pbm->ms    
427                        pbm->msix_data_width);     
428                 printk(KERN_INFO "%s: MSI addr    
429                        "addr64[0x%llx:0x%x]\n"    
430                        pbm->name,                 
431                        pbm->msi32_start, pbm->    
432                        pbm->msi64_start, pbm->    
433                 printk(KERN_INFO "%s: MSI queu    
434                        pbm->name,                 
435                        __pa(pbm->msi_queues));    
436                                                   
437                 pbm->msi_ops = ops;               
438                 pbm->setup_msi_irq = sparc64_s    
439                 pbm->teardown_msi_irq = sparc6    
440         }                                         
441         return;                                   
442                                                   
443 no_msi:                                           
444         pbm->msiq_num = 0;                        
445         printk(KERN_INFO "%s: No MSI support.\    
446 }                                                 
447                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php