1919
2020#include "pseries.h"
2121
22+ struct pseries_msi_device {
23+ unsigned int msi_quota ;
24+ unsigned int msi_used ;
25+ };
26+
2227static int query_token , change_token ;
2328
2429#define RTAS_QUERY_FN 0
@@ -433,8 +438,28 @@ static int pseries_msi_ops_prepare(struct irq_domain *domain, struct device *dev
433438 struct msi_domain_info * info = domain -> host_data ;
434439 struct pci_dev * pdev = to_pci_dev (dev );
435440 int type = (info -> flags & MSI_FLAG_PCI_MSIX ) ? PCI_CAP_ID_MSIX : PCI_CAP_ID_MSI ;
441+ int ret ;
442+
443+ struct pseries_msi_device * pseries_dev __free (kfree )
444+ = kmalloc (sizeof (* pseries_dev ), GFP_KERNEL );
445+ if (!pseries_dev )
446+ return - ENOMEM ;
447+
448+ while (1 ) {
449+ ret = rtas_prepare_msi_irqs (pdev , nvec , type , arg );
450+ if (!ret )
451+ break ;
452+ else if (ret > 0 )
453+ nvec = ret ;
454+ else
455+ return ret ;
456+ }
436457
437- return rtas_prepare_msi_irqs (pdev , nvec , type , arg );
458+ pseries_dev -> msi_quota = nvec ;
459+ pseries_dev -> msi_used = 0 ;
460+
461+ arg -> scratchpad [0 ].ptr = no_free_ptr (pseries_dev );
462+ return 0 ;
438463}
439464
440465/*
@@ -443,9 +468,13 @@ static int pseries_msi_ops_prepare(struct irq_domain *domain, struct device *dev
443468 */
444469static void pseries_msi_ops_teardown (struct irq_domain * domain , msi_alloc_info_t * arg )
445470{
471+ struct pseries_msi_device * pseries_dev = arg -> scratchpad [0 ].ptr ;
446472 struct pci_dev * pdev = to_pci_dev (domain -> dev );
447473
448474 rtas_disable_msi (pdev );
475+
476+ WARN_ON (pseries_dev -> msi_used );
477+ kfree (pseries_dev );
449478}
450479
451480static void pseries_msi_shutdown (struct irq_data * d )
@@ -546,12 +575,18 @@ static int pseries_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
546575 unsigned int nr_irqs , void * arg )
547576{
548577 struct pci_controller * phb = domain -> host_data ;
578+ struct pseries_msi_device * pseries_dev ;
549579 msi_alloc_info_t * info = arg ;
550580 struct msi_desc * desc = info -> desc ;
551581 struct pci_dev * pdev = msi_desc_to_pci_dev (desc );
552582 int hwirq ;
553583 int i , ret ;
554584
585+ pseries_dev = info -> scratchpad [0 ].ptr ;
586+
587+ if (pseries_dev -> msi_used + nr_irqs > pseries_dev -> msi_quota )
588+ return - ENOSPC ;
589+
555590 hwirq = rtas_query_irq_number (pci_get_pdn (pdev ), desc -> msi_index );
556591 if (hwirq < 0 ) {
557592 dev_err (& pdev -> dev , "Failed to query HW IRQ: %d\n" , hwirq );
@@ -567,9 +602,10 @@ static int pseries_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
567602 goto out ;
568603
569604 irq_domain_set_hwirq_and_chip (domain , virq + i , hwirq + i ,
570- & pseries_msi_irq_chip , domain -> host_data );
605+ & pseries_msi_irq_chip , pseries_dev );
571606 }
572607
608+ pseries_dev -> msi_used ++ ;
573609 return 0 ;
574610
575611out :
@@ -582,9 +618,11 @@ static void pseries_irq_domain_free(struct irq_domain *domain, unsigned int virq
582618 unsigned int nr_irqs )
583619{
584620 struct irq_data * d = irq_domain_get_irq_data (domain , virq );
585- struct pci_controller * phb = irq_data_get_irq_chip_data (d );
621+ struct pseries_msi_device * pseries_dev = irq_data_get_irq_chip_data (d );
622+ struct pci_controller * phb = domain -> host_data ;
586623
587624 pr_debug ("%s bridge %pOF %d #%d\n" , __func__ , phb -> dn , virq , nr_irqs );
625+ pseries_dev -> msi_used -= nr_irqs ;
588626 irq_domain_free_irqs_parent (domain , virq , nr_irqs );
589627}
590628
0 commit comments