1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
4  */
5 
6 #include <linux/kernel.h>
7 #include <linux/msi.h>
8 #include <linux/pci.h>
9 
10 #include <asm/machdep.h>
11 
arch_setup_msi_irqs(struct pci_dev * dev,int nvec,int type)12 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
13 {
14 	struct pci_controller *phb = pci_bus_to_host(dev->bus);
15 
16 	if (!phb->controller_ops.setup_msi_irqs ||
17 	    !phb->controller_ops.teardown_msi_irqs) {
18 		pr_debug("msi: Platform doesn't provide MSI callbacks.\n");
19 		return -ENOSYS;
20 	}
21 
22 	/* PowerPC doesn't support multiple MSI yet */
23 	if (type == PCI_CAP_ID_MSI && nvec > 1)
24 		return 1;
25 
26 	return phb->controller_ops.setup_msi_irqs(dev, nvec, type);
27 }
28 
arch_teardown_msi_irqs(struct pci_dev * dev)29 void arch_teardown_msi_irqs(struct pci_dev *dev)
30 {
31 	struct pci_controller *phb = pci_bus_to_host(dev->bus);
32 
33 	/*
34 	 * We can be called even when arch_setup_msi_irqs() returns -ENOSYS,
35 	 * so check the pointer again.
36 	 */
37 	if (phb->controller_ops.teardown_msi_irqs)
38 		phb->controller_ops.teardown_msi_irqs(dev);
39 }
40