summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/pci_dn.c
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2016-05-20 08:41:37 +0200
committerMichael Ellerman <mpe@ellerman.id.au>2016-06-21 07:30:56 +0200
commit8cc7581cdb84a232468c41bc417183a423dfbb07 (patch)
treedc5e57aedc13410f948fd6c95bab8fb0f5d79084 /arch/powerpc/kernel/pci_dn.c
parentpowerpc/pci: Update bridge windows on PCI plug (diff)
downloadlinux-8cc7581cdb84a232468c41bc417183a423dfbb07.tar.xz
linux-8cc7581cdb84a232468c41bc417183a423dfbb07.zip
powerpc/pci: Delay populating pdn
The pdn (struct pci_dn) instances are allocated from memblock or bootmem when creating PCI controller (hoses) in setup_arch(). PCI hotplug, which will be supported by proceeding patches, releases PCI device nodes and their corresponding pdn on unplugging event. The memory chunks for pdn instances allocated from memblock or bootmem are hard to reused after being released. This delays creating pdn by pci_devs_phb_init() from setup_arch() to core_initcall() so that they are allocated from slab. The memory consumed by pdn can be released to system without problem during PCI unplugging time. It indicates that pci_dn is unavailable in setup_arch() and the the fixup on pdn (like AGP's) can't be carried out that time. We have to do that in pcibios_root_bridge_prepare() on maple/pasemi/powermac platforms where/when the pdn is available. pcibios_root_bridge_prepare is called from subsys_initcall() which is executed after core_initcall() so the code flow does not change. At the mean while, the EEH device is created when pdn is populated, meaning pdn and EEH device have same life cycle. In turn, we needn't call eeh_dev_init() to create EEH device explicitly. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/kernel/pci_dn.c')
-rw-r--r--arch/powerpc/kernel/pci_dn.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index afeda26c2ebc..bfe60a1e70d9 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -212,8 +212,7 @@ struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
#ifdef CONFIG_EEH
/* Create the EEH device for the VF */
- eeh_dev_init(pdn, pci_bus_to_host(pdev->bus));
- edev = pdn_to_eeh_dev(pdn);
+ edev = eeh_dev_init(pdn);
BUG_ON(!edev);
edev->physfn = pdev;
#endif /* CONFIG_EEH */
@@ -295,8 +294,11 @@ struct pci_dn *pci_add_device_node_info(struct pci_controller *hose,
const __be32 *regs;
struct device_node *parent;
struct pci_dn *pdn;
+#ifdef CONFIG_EEH
+ struct eeh_dev *edev;
+#endif
- pdn = zalloc_maybe_bootmem(sizeof(*pdn), GFP_KERNEL);
+ pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
if (pdn == NULL)
return NULL;
dn->data = pdn;
@@ -325,6 +327,15 @@ struct pci_dn *pci_add_device_node_info(struct pci_controller *hose,
/* Extended config space */
pdn->pci_ext_config_space = (type && of_read_number(type, 1) == 1);
+ /* Create EEH device */
+#ifdef CONFIG_EEH
+ edev = eeh_dev_init(pdn);
+ if (!edev) {
+ kfree(pdn);
+ return NULL;
+ }
+#endif
+
/* Attach to parent node */
INIT_LIST_HEAD(&pdn->child_list);
INIT_LIST_HEAD(&pdn->list);
@@ -510,15 +521,19 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb)
* pci device found underneath. This routine runs once,
* early in the boot sequence.
*/
-void __init pci_devs_phb_init(void)
+static int __init pci_devs_phb_init(void)
{
struct pci_controller *phb, *tmp;
/* This must be done first so the device nodes have valid pci info! */
list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
pci_devs_phb_init_dynamic(phb);
+
+ return 0;
}
+core_initcall(pci_devs_phb_init);
+
static void pci_dev_pdn_setup(struct pci_dev *pdev)
{
struct pci_dn *pdn;