0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/pci.h>
0013 #include <linux/export.h>
0014 #include <asm/pci-bridge.h>
0015 #include <asm/ppc-pci.h>
0016 #include <asm/firmware.h>
0017 #include <asm/eeh.h>
0018
0019 #include "pseries.h"
0020
0021 struct pci_controller *init_phb_dynamic(struct device_node *dn)
0022 {
0023 struct pci_controller *phb;
0024
0025 pr_debug("PCI: Initializing new hotplug PHB %pOF\n", dn);
0026
0027 phb = pcibios_alloc_controller(dn);
0028 if (!phb)
0029 return NULL;
0030 rtas_setup_phb(phb);
0031 pci_process_bridge_OF_ranges(phb, dn, 0);
0032 phb->controller_ops = pseries_pci_controller_ops;
0033
0034 pci_devs_phb_init_dynamic(phb);
0035
0036 pseries_msi_allocate_domains(phb);
0037
0038
0039 eeh_phb_pe_create(phb);
0040
0041 if (dn->child)
0042 pseries_eeh_init_edev_recursive(PCI_DN(dn));
0043
0044 pcibios_scan_phb(phb);
0045 pcibios_finish_adding_to_bus(phb->bus);
0046
0047 return phb;
0048 }
0049 EXPORT_SYMBOL_GPL(init_phb_dynamic);
0050
0051
0052 int remove_phb_dynamic(struct pci_controller *phb)
0053 {
0054 struct pci_bus *b = phb->bus;
0055 struct pci_host_bridge *host_bridge = to_pci_host_bridge(b->bridge);
0056 struct resource *res;
0057 int rc, i;
0058
0059 pr_debug("PCI: Removing PHB %04x:%02x...\n",
0060 pci_domain_nr(b), b->number);
0061
0062
0063 if (!(list_empty(&b->children) && list_empty(&b->devices)))
0064 return -EBUSY;
0065
0066
0067
0068
0069 res = &phb->io_resource;
0070 if (res->flags & IORESOURCE_IO) {
0071 rc = pcibios_unmap_io_space(b);
0072 if (rc) {
0073 printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
0074 __func__, b->name);
0075 return 1;
0076 }
0077 }
0078
0079 pseries_msi_free_domains(phb);
0080
0081
0082 get_device(&host_bridge->dev);
0083
0084
0085 phb->bus = NULL;
0086 pci_remove_bus(b);
0087 host_bridge->bus = NULL;
0088 device_unregister(&host_bridge->dev);
0089
0090
0091 if (res->flags & IORESOURCE_IO)
0092 release_resource(res);
0093
0094
0095 for (i = 0; i < 3; ++i) {
0096 res = &phb->mem_resources[i];
0097 if (!(res->flags & IORESOURCE_MEM))
0098 continue;
0099 release_resource(res);
0100 }
0101
0102
0103
0104
0105
0106
0107 put_device(&host_bridge->dev);
0108
0109 return 0;
0110 }
0111 EXPORT_SYMBOL_GPL(remove_phb_dynamic);