Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/pseries/msi: Switch to msi_create_parent_irq_domain()

Move away from the legacy MSI domain setup, switch to use
msi_create_parent_irq_domain().

Signed-off-by: Nam Cao <namcao@linutronix.de>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/c7a6d8f27fd217021dea4daad777e81a525ae460.1754903590.git.namcao@linutronix.de

authored by

Nam Cao and committed by
Madhavan Srinivasan
daaa574a f0ac60e6

+48 -67
-2
arch/powerpc/include/asm/pci-bridge.h
··· 133 133 134 134 /* IRQ domain hierarchy */ 135 135 struct irq_domain *dev_domain; 136 - struct irq_domain *msi_domain; 137 - struct fwnode_handle *fwnode; 138 136 139 137 /* iommu_ops support */ 140 138 struct iommu_device iommu;
+1
arch/powerpc/platforms/pseries/Kconfig
··· 7 7 select OF_DYNAMIC 8 8 select FORCE_PCI 9 9 select PCI_MSI 10 + select IRQ_MSI_LIB 10 11 select GENERIC_ALLOCATOR 11 12 select PPC_XICS 12 13 select PPC_XIVE_SPAPR
+47 -65
arch/powerpc/platforms/pseries/msi.c
··· 7 7 #include <linux/crash_dump.h> 8 8 #include <linux/device.h> 9 9 #include <linux/irq.h> 10 + #include <linux/irqchip/irq-msi-lib.h> 10 11 #include <linux/irqdomain.h> 11 12 #include <linux/msi.h> 12 13 #include <linux/seq_file.h> ··· 430 429 static int pseries_msi_ops_prepare(struct irq_domain *domain, struct device *dev, 431 430 int nvec, msi_alloc_info_t *arg) 432 431 { 432 + struct msi_domain_info *info = domain->host_data; 433 433 struct pci_dev *pdev = to_pci_dev(dev); 434 - int type = pdev->msix_enabled ? PCI_CAP_ID_MSIX : PCI_CAP_ID_MSI; 434 + int type = (info->flags & MSI_FLAG_PCI_MSIX) ? PCI_CAP_ID_MSIX : PCI_CAP_ID_MSI; 435 435 436 436 return rtas_prepare_msi_irqs(pdev, nvec, type, arg); 437 437 } ··· 441 439 * RTAS can not disable one MSI at a time. It's all or nothing. Do it 442 440 * at the end after all IRQs have been freed. 443 441 */ 444 - static void pseries_msi_post_free(struct irq_domain *domain, struct device *dev) 442 + static void pseries_msi_ops_teardown(struct irq_domain *domain, msi_alloc_info_t *arg) 445 443 { 446 - if (WARN_ON_ONCE(!dev_is_pci(dev))) 447 - return; 444 + struct msi_desc *desc = arg->desc; 445 + struct pci_dev *pdev = msi_desc_to_pci_dev(desc); 448 446 449 - rtas_disable_msi(to_pci_dev(dev)); 447 + rtas_disable_msi(pdev); 450 448 } 451 - 452 - static struct msi_domain_ops pseries_pci_msi_domain_ops = { 453 - .msi_prepare = pseries_msi_ops_prepare, 454 - .msi_post_free = pseries_msi_post_free, 455 - }; 456 449 457 450 static void pseries_msi_shutdown(struct irq_data *d) 458 451 { 459 452 d = d->parent_data; 460 453 if (d->chip->irq_shutdown) 461 454 d->chip->irq_shutdown(d); 462 - } 463 - 464 - static void pseries_msi_mask(struct irq_data *d) 465 - { 466 - pci_msi_mask_irq(d); 467 - irq_chip_mask_parent(d); 468 - } 469 - 470 - static void pseries_msi_unmask(struct irq_data *d) 471 - { 472 - pci_msi_unmask_irq(d); 473 - irq_chip_unmask_parent(d); 474 455 } 475 456 476 457 static void pseries_msi_write_msg(struct irq_data *data, struct msi_msg *msg) ··· 470 485 entry->msg = *msg; 471 486 } 472 487 473 - static struct irq_chip pseries_pci_msi_irq_chip = { 474 - .name = "pSeries-PCI-MSI", 475 - .irq_shutdown = pseries_msi_shutdown, 476 - .irq_mask = pseries_msi_mask, 477 - .irq_unmask = pseries_msi_unmask, 478 - .irq_eoi = irq_chip_eoi_parent, 479 - .irq_write_msi_msg = pseries_msi_write_msg, 480 - }; 488 + static bool pseries_init_dev_msi_info(struct device *dev, struct irq_domain *domain, 489 + struct irq_domain *real_parent, struct msi_domain_info *info) 490 + { 491 + struct irq_chip *chip = info->chip; 481 492 493 + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) 494 + return false; 482 495 483 - /* 484 - * Set MSI_FLAG_MSIX_CONTIGUOUS as there is no way to express to 485 - * firmware to request a discontiguous or non-zero based range of 486 - * MSI-X entries. Core code will reject such setup attempts. 487 - */ 488 - static struct msi_domain_info pseries_msi_domain_info = { 489 - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 490 - MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX | 491 - MSI_FLAG_MSIX_CONTIGUOUS), 492 - .ops = &pseries_pci_msi_domain_ops, 493 - .chip = &pseries_pci_msi_irq_chip, 496 + chip->irq_shutdown = pseries_msi_shutdown; 497 + chip->irq_write_msi_msg = pseries_msi_write_msg; 498 + 499 + info->ops->msi_prepare = pseries_msi_ops_prepare; 500 + info->ops->msi_teardown = pseries_msi_ops_teardown; 501 + 502 + return true; 503 + } 504 + 505 + #define PSERIES_PCI_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 506 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 507 + MSI_FLAG_PCI_MSI_MASK_PARENT) 508 + #define PSERIES_PCI_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ 509 + MSI_FLAG_PCI_MSIX | \ 510 + MSI_FLAG_MSIX_CONTIGUOUS | \ 511 + MSI_FLAG_MULTI_PCI_MSI) 512 + 513 + static const struct msi_parent_ops pseries_msi_parent_ops = { 514 + .required_flags = PSERIES_PCI_MSI_FLAGS_REQUIRED, 515 + .supported_flags = PSERIES_PCI_MSI_FLAGS_SUPPORTED, 516 + .chip_flags = MSI_CHIP_FLAG_SET_EOI, 517 + .bus_select_token = DOMAIN_BUS_NEXUS, 518 + .bus_select_mask = MATCH_PCI_MSI, 519 + .prefix = "pSeries-", 520 + .init_dev_msi_info = pseries_init_dev_msi_info, 494 521 }; 495 522 496 523 static void pseries_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) ··· 590 593 } 591 594 592 595 static const struct irq_domain_ops pseries_irq_domain_ops = { 596 + .select = msi_lib_irq_domain_select, 593 597 .alloc = pseries_irq_domain_alloc, 594 598 .free = pseries_irq_domain_free, 595 599 }; ··· 599 601 unsigned int count) 600 602 { 601 603 struct irq_domain *parent = irq_get_default_domain(); 604 + struct irq_domain_info info = { 605 + .fwnode = of_fwnode_handle(phb->dn), 606 + .ops = &pseries_irq_domain_ops, 607 + .host_data = phb, 608 + .size = count, 609 + .parent = parent, 610 + }; 602 611 603 - phb->fwnode = irq_domain_alloc_named_id_fwnode("pSeries-MSI", 604 - phb->global_number); 605 - if (!phb->fwnode) 606 - return -ENOMEM; 607 - 608 - phb->dev_domain = irq_domain_create_hierarchy(parent, 0, count, 609 - phb->fwnode, 610 - &pseries_irq_domain_ops, phb); 612 + phb->dev_domain = msi_create_parent_irq_domain(&info, &pseries_msi_parent_ops); 611 613 if (!phb->dev_domain) { 612 - pr_err("PCI: failed to create IRQ domain bridge %pOF (domain %d)\n", 613 - phb->dn, phb->global_number); 614 - irq_domain_free_fwnode(phb->fwnode); 615 - return -ENOMEM; 616 - } 617 - 618 - phb->msi_domain = pci_msi_create_irq_domain(of_fwnode_handle(phb->dn), 619 - &pseries_msi_domain_info, 620 - phb->dev_domain); 621 - if (!phb->msi_domain) { 622 614 pr_err("PCI: failed to create MSI IRQ domain bridge %pOF (domain %d)\n", 623 615 phb->dn, phb->global_number); 624 - irq_domain_free_fwnode(phb->fwnode); 625 - irq_domain_remove(phb->dev_domain); 626 616 return -ENOMEM; 627 617 } 628 618 ··· 632 646 633 647 void pseries_msi_free_domains(struct pci_controller *phb) 634 648 { 635 - if (phb->msi_domain) 636 - irq_domain_remove(phb->msi_domain); 637 649 if (phb->dev_domain) 638 650 irq_domain_remove(phb->dev_domain); 639 - if (phb->fwnode) 640 - irq_domain_free_fwnode(phb->fwnode); 641 651 } 642 652 643 653 static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev)