1/* 2 * PCI Dynamic LPAR, PCI Hot Plug and PCI EEH recovery code 3 * for RPA-compliant PPC64 platform. 4 * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com> 5 * Copyright (C) 2005 International Business Machines 6 * 7 * Updates, 2005, John Rose <johnrose@austin.ibm.com> 8 * Updates, 2005, Linas Vepstas <linas@austin.ibm.com> 9 * 10 * All rights reserved. 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or (at 15 * your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 20 * NON INFRINGEMENT. See the GNU General Public License for more 21 * details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 26 */ 27 28#include <linux/pci.h> 29#include <linux/export.h> 30#include <asm/pci-bridge.h> 31#include <asm/ppc-pci.h> 32#include <asm/firmware.h> 33#include <asm/eeh.h> 34 35#include "pseries.h" 36 37struct pci_controller *init_phb_dynamic(struct device_node *dn) 38{ 39 struct pci_controller *phb; 40 41 pr_debug("PCI: Initializing new hotplug PHB %pOF\n", dn); 42 43 phb = pcibios_alloc_controller(dn); 44 if (!phb) 45 return NULL; 46 rtas_setup_phb(phb); 47 pci_process_bridge_OF_ranges(phb, dn, 0); 48 phb->controller_ops = pseries_pci_controller_ops; 49 50 pci_devs_phb_init_dynamic(phb); 51 52 /* Create EEH devices for the PHB */ 53 eeh_dev_phb_init_dynamic(phb); 54 55 if (dn->child) 56 eeh_add_device_tree_early(PCI_DN(dn)); 57 58 pcibios_scan_phb(phb); 59 pcibios_finish_adding_to_bus(phb->bus); 60 61 return phb; 62} 63EXPORT_SYMBOL_GPL(init_phb_dynamic); 64 65/* RPA-specific bits for removing PHBs */ 66int remove_phb_dynamic(struct pci_controller *phb) 67{ 68 struct pci_bus *b = phb->bus; 69 struct resource *res; 70 int rc, i; 71 72 pr_debug("PCI: Removing PHB %04x:%02x...\n", 73 pci_domain_nr(b), b->number); 74 75 /* We cannot to remove a root bus that has children */ 76 if (!(list_empty(&b->children) && list_empty(&b->devices))) 77 return -EBUSY; 78 79 /* We -know- there aren't any child devices anymore at this stage 80 * and thus, we can safely unmap the IO space as it's not in use 81 */ 82 res = &phb->io_resource; 83 if (res->flags & IORESOURCE_IO) { 84 rc = pcibios_unmap_io_space(b); 85 if (rc) { 86 printk(KERN_ERR "%s: failed to unmap IO on bus %s\n", 87 __func__, b->name); 88 return 1; 89 } 90 } 91 92 /* Remove the PCI bus and unregister the bridge device from sysfs */ 93 phb->bus = NULL; 94 pci_remove_bus(b); 95 device_unregister(b->bridge); 96 97 /* Now release the IO resource */ 98 if (res->flags & IORESOURCE_IO) 99 release_resource(res); 100 101 /* Release memory resources */ 102 for (i = 0; i < 3; ++i) { 103 res = &phb->mem_resources[i]; 104 if (!(res->flags & IORESOURCE_MEM)) 105 continue; 106 release_resource(res); 107 } 108 109 /* 110 * The pci_controller data structure is freed by 111 * the pcibios_free_controller_deferred() callback; 112 * see pseries_root_bridge_prepare(). 113 */ 114 115 return 0; 116} 117EXPORT_SYMBOL_GPL(remove_phb_dynamic); 118