77#include <linux/crash_dump.h>
88#include <linux/device.h>
99#include <linux/irq.h>
10+ #include <linux/irqchip/irq-msi-lib.h>
1011#include <linux/irqdomain.h>
1112#include <linux/msi.h>
1213#include <linux/seq_file.h>
@@ -429,8 +430,9 @@ static int rtas_prepare_msi_irqs(struct pci_dev *pdev, int nvec_in, int type,
429430static int pseries_msi_ops_prepare (struct irq_domain * domain , struct device * dev ,
430431 int nvec , msi_alloc_info_t * arg )
431432{
433+ struct msi_domain_info * info = domain -> host_data ;
432434 struct pci_dev * pdev = to_pci_dev (dev );
433- int type = pdev -> msix_enabled ? PCI_CAP_ID_MSIX : PCI_CAP_ID_MSI ;
435+ int type = ( info -> flags & MSI_FLAG_PCI_MSIX ) ? PCI_CAP_ID_MSIX : PCI_CAP_ID_MSI ;
434436
435437 return rtas_prepare_msi_irqs (pdev , nvec , type , arg );
436438}
@@ -439,38 +441,21 @@ static int pseries_msi_ops_prepare(struct irq_domain *domain, struct device *dev
439441 * RTAS can not disable one MSI at a time. It's all or nothing. Do it
440442 * at the end after all IRQs have been freed.
441443 */
442- static void pseries_msi_post_free (struct irq_domain * domain , struct device * dev )
444+ static void pseries_msi_ops_teardown (struct irq_domain * domain , msi_alloc_info_t * arg )
443445{
444- if ( WARN_ON_ONCE (! dev_is_pci ( dev )))
445- return ;
446+ struct msi_desc * desc = arg -> desc ;
447+ struct pci_dev * pdev = msi_desc_to_pci_dev ( desc ) ;
446448
447- rtas_disable_msi (to_pci_dev ( dev ) );
449+ rtas_disable_msi (pdev );
448450}
449451
450- static struct msi_domain_ops pseries_pci_msi_domain_ops = {
451- .msi_prepare = pseries_msi_ops_prepare ,
452- .msi_post_free = pseries_msi_post_free ,
453- };
454-
455452static void pseries_msi_shutdown (struct irq_data * d )
456453{
457454 d = d -> parent_data ;
458455 if (d -> chip -> irq_shutdown )
459456 d -> chip -> irq_shutdown (d );
460457}
461458
462- static void pseries_msi_mask (struct irq_data * d )
463- {
464- pci_msi_mask_irq (d );
465- irq_chip_mask_parent (d );
466- }
467-
468- static void pseries_msi_unmask (struct irq_data * d )
469- {
470- pci_msi_unmask_irq (d );
471- irq_chip_unmask_parent (d );
472- }
473-
474459static void pseries_msi_write_msg (struct irq_data * data , struct msi_msg * msg )
475460{
476461 struct msi_desc * entry = irq_data_get_msi_desc (data );
@@ -485,27 +470,39 @@ static void pseries_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
485470 entry -> msg = * msg ;
486471}
487472
488- static struct irq_chip pseries_pci_msi_irq_chip = {
489- .name = "pSeries-PCI-MSI" ,
490- .irq_shutdown = pseries_msi_shutdown ,
491- .irq_mask = pseries_msi_mask ,
492- .irq_unmask = pseries_msi_unmask ,
493- .irq_eoi = irq_chip_eoi_parent ,
494- .irq_write_msi_msg = pseries_msi_write_msg ,
495- };
473+ static bool pseries_init_dev_msi_info (struct device * dev , struct irq_domain * domain ,
474+ struct irq_domain * real_parent , struct msi_domain_info * info )
475+ {
476+ struct irq_chip * chip = info -> chip ;
496477
478+ if (!msi_lib_init_dev_msi_info (dev , domain , real_parent , info ))
479+ return false;
497480
498- /*
499- * Set MSI_FLAG_MSIX_CONTIGUOUS as there is no way to express to
500- * firmware to request a discontiguous or non-zero based range of
501- * MSI-X entries. Core code will reject such setup attempts.
502- */
503- static struct msi_domain_info pseries_msi_domain_info = {
504- .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
505- MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX |
506- MSI_FLAG_MSIX_CONTIGUOUS ),
507- .ops = & pseries_pci_msi_domain_ops ,
508- .chip = & pseries_pci_msi_irq_chip ,
481+ chip -> irq_shutdown = pseries_msi_shutdown ;
482+ chip -> irq_write_msi_msg = pseries_msi_write_msg ;
483+
484+ info -> ops -> msi_prepare = pseries_msi_ops_prepare ;
485+ info -> ops -> msi_teardown = pseries_msi_ops_teardown ;
486+
487+ return true;
488+ }
489+
490+ #define PSERIES_PCI_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \
491+ MSI_FLAG_USE_DEF_CHIP_OPS | \
492+ MSI_FLAG_PCI_MSI_MASK_PARENT)
493+ #define PSERIES_PCI_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \
494+ MSI_FLAG_PCI_MSIX | \
495+ MSI_FLAG_MSIX_CONTIGUOUS | \
496+ MSI_FLAG_MULTI_PCI_MSI)
497+
498+ static const struct msi_parent_ops pseries_msi_parent_ops = {
499+ .required_flags = PSERIES_PCI_MSI_FLAGS_REQUIRED ,
500+ .supported_flags = PSERIES_PCI_MSI_FLAGS_SUPPORTED ,
501+ .chip_flags = MSI_CHIP_FLAG_SET_EOI ,
502+ .bus_select_token = DOMAIN_BUS_NEXUS ,
503+ .bus_select_mask = MATCH_PCI_MSI ,
504+ .prefix = "pSeries-" ,
505+ .init_dev_msi_info = pseries_init_dev_msi_info ,
509506};
510507
511508static void pseries_msi_compose_msg (struct irq_data * data , struct msi_msg * msg )
@@ -593,6 +590,7 @@ static void pseries_irq_domain_free(struct irq_domain *domain, unsigned int virq
593590}
594591
595592static const struct irq_domain_ops pseries_irq_domain_ops = {
593+ .select = msi_lib_irq_domain_select ,
596594 .alloc = pseries_irq_domain_alloc ,
597595 .free = pseries_irq_domain_free ,
598596};
@@ -601,30 +599,18 @@ static int __pseries_msi_allocate_domains(struct pci_controller *phb,
601599 unsigned int count )
602600{
603601 struct irq_domain * parent = irq_get_default_domain ();
604-
605- phb -> fwnode = irq_domain_alloc_named_id_fwnode ( "pSeries-MSI" ,
606- phb -> global_number );
607- if (! phb -> fwnode )
608- return - ENOMEM ;
609-
610- phb -> dev_domain = irq_domain_create_hierarchy ( parent , 0 , count ,
611- phb -> fwnode ,
612- & pseries_irq_domain_ops , phb );
602+ struct irq_domain_info info = {
603+ . fwnode = of_fwnode_handle ( phb -> dn ) ,
604+ . ops = & pseries_irq_domain_ops ,
605+ . host_data = phb ,
606+ . size = count ,
607+ . parent = parent ,
608+ };
609+
610+ phb -> dev_domain = msi_create_parent_irq_domain ( & info , & pseries_msi_parent_ops );
613611 if (!phb -> dev_domain ) {
614- pr_err ("PCI: failed to create IRQ domain bridge %pOF (domain %d)\n" ,
615- phb -> dn , phb -> global_number );
616- irq_domain_free_fwnode (phb -> fwnode );
617- return - ENOMEM ;
618- }
619-
620- phb -> msi_domain = pci_msi_create_irq_domain (of_fwnode_handle (phb -> dn ),
621- & pseries_msi_domain_info ,
622- phb -> dev_domain );
623- if (!phb -> msi_domain ) {
624612 pr_err ("PCI: failed to create MSI IRQ domain bridge %pOF (domain %d)\n" ,
625613 phb -> dn , phb -> global_number );
626- irq_domain_free_fwnode (phb -> fwnode );
627- irq_domain_remove (phb -> dev_domain );
628614 return - ENOMEM ;
629615 }
630616
@@ -646,12 +632,8 @@ int pseries_msi_allocate_domains(struct pci_controller *phb)
646632
647633void pseries_msi_free_domains (struct pci_controller * phb )
648634{
649- if (phb -> msi_domain )
650- irq_domain_remove (phb -> msi_domain );
651635 if (phb -> dev_domain )
652636 irq_domain_remove (phb -> dev_domain );
653- if (phb -> fwnode )
654- irq_domain_free_fwnode (phb -> fwnode );
655637}
656638
657639static void rtas_msi_pci_irq_fixup (struct pci_dev * pdev )
0 commit comments