rpaphp_pci.c revision 89a071b80767c3a7ed56e13ae5e810f751b19eeb
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform.
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com>
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All rights reserved.
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * your option) any later version.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NON INFRINGEMENT.  See the GNU General Public License for more
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * details.
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send feedback to <lxie@us.ibm.com>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
264e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/string.h>
274e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pci-bridge.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/rtas.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/machdep.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
324e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include "../pci.h"		/* for pci_add_new_bus */
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "rpaphp.h"
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
350945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rosestatic struct pci_bus *find_bus_among_children(struct pci_bus *bus,
369c209c919df95f83aa042b3352c43841ad15a02bJohn Rose					struct device_node *dn)
379c209c919df95f83aa042b3352c43841ad15a02bJohn Rose{
389c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct pci_bus *child = NULL;
399c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct list_head *tmp;
409c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct device_node *busdn;
419c209c919df95f83aa042b3352c43841ad15a02bJohn Rose
429c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	busdn = pci_bus_to_OF_node(bus);
439c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	if (busdn == dn)
449c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		return bus;
459c209c919df95f83aa042b3352c43841ad15a02bJohn Rose
469c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	list_for_each(tmp, &bus->children) {
479c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		child = find_bus_among_children(pci_bus_b(tmp), dn);
489c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		if (child)
499c209c919df95f83aa042b3352c43841ad15a02bJohn Rose			break;
509c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	}
519c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	return child;
529c209c919df95f83aa042b3352c43841ad15a02bJohn Rose}
539c209c919df95f83aa042b3352c43841ad15a02bJohn Rose
5456d8456b06ad1316bff3c75caed5e06e786f20d8John Rosestruct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
559c209c919df95f83aa042b3352c43841ad15a02bJohn Rose{
561635317facea3094ddf34082cd86797efb1d9f7ePaul Mackerras	struct pci_dn *pdn = dn->data;
571635317facea3094ddf34082cd86797efb1d9f7ePaul Mackerras
581635317facea3094ddf34082cd86797efb1d9f7ePaul Mackerras	if (!pdn  || !pdn->phb || !pdn->phb->bus)
590945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose		return NULL;
609c209c919df95f83aa042b3352c43841ad15a02bJohn Rose
611635317facea3094ddf34082cd86797efb1d9f7ePaul Mackerras	return find_bus_among_children(pdn->phb->bus, dn);
629c209c919df95f83aa042b3352c43841ad15a02bJohn Rose}
6356d8456b06ad1316bff3c75caed5e06e786f20d8John RoseEXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
649c209c919df95f83aa042b3352c43841ad15a02bJohn Rose
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_claim_resource(struct pci_dev *dev, int resource)
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource *res = &dev->resource[resource];
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource *root = pci_find_parent_resource(dev, res);
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = -EINVAL;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (root != NULL) {
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = request_resource(root, res);
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err) {
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("PCI: %s region %d of %s %s [%lx:%lx]\n",
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    root ? "Address space collision on" :
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    "No parent found for",
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    resource, dtype, pci_name(dev), res->start, res->end);
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(rpaphp_claim_resource);
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rpaphp_get_sensor_state(struct slot *slot, int *state)
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int setlevel;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc < 0) {
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc == -EFAULT || rc == -EEXIST) {
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dbg("%s: slot must be power up to get sensor-state\n",
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    __FUNCTION__);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* some slots have to be powered up
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * before get-sensor will succeed.
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rc = rtas_set_power_level(slot->power_domain, POWER_ON,
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  &setlevel);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (rc < 0) {
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dbg("%s: power on slot[%s] failed rc=%d.\n",
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    __FUNCTION__, slot->name, rc);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rc = rtas_get_sensor(DR_ENTITY_SENSE,
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						     slot->index, state);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (rc == -ENODEV)
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			info("%s: slot is unusable\n", __FUNCTION__);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err("%s failed to get sensor state\n", __FUNCTION__);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get_pci_adapter_status - get the status of a slot
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0-- slot is empty
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1-- adapter is configured
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2-- adapter is not configured
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3-- not valid
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1290945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose	struct pci_bus *bus;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int state, rc;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*value = NOT_VALID;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = rpaphp_get_sensor_state(slot, &state);
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc)
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13756d8456b06ad1316bff3c75caed5e06e786f20d8John Rose 	if (state == EMPTY)
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		*value = EMPTY;
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	else if (state == PRESENT) {
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!is_init) {
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* at run-time slot->state can be changed by */
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* config/unconfig adapter */
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*value = slot->state;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
1450945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose			bus = rpaphp_find_pci_bus(slot->dn);
1460945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose			if (bus && !list_empty(&bus->devices))
1470945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose				*value = CONFIGURED;
1480945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose			else
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*value = NOT_CONFIGURED;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Must be called before pci_bus_add_devices */
1575fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rosevoid rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(dev, &bus->devices, bus_list) {
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Skip already-present devices (which are on the
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * global device list.)
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (list_empty(&dev->global_list)) {
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int i;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Need to setup IOMMU tables */
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ppc_md.iommu_dev_setup(dev);
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if(fix_bus)
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pcibios_fixup_device_resources(dev, bus);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_irq_line(dev);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				struct resource *r = &dev->resource[i];
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (r->parent || !r->start || !r->flags)
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					continue;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rpaphp_claim_resource(dev, i);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1865fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rosestatic void rpaphp_eeh_add_bus_device(struct pci_bus *bus)
1875fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose{
1885fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose	struct pci_dev *dev;
1895fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose
1905fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose	list_for_each_entry(dev, &bus->devices, bus_list) {
1915fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		eeh_add_device_late(dev);
1925fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
1935fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			struct pci_bus *subbus = dev->subordinate;
1945fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			if (subbus)
1955fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose				rpaphp_eeh_add_bus_device (subbus);
1965fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		}
1975fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose	}
1985fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose}
1995fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rpaphp_pci_config_bridge(struct pci_dev *dev)
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 sec_busno;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *child_bus;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *child_dev;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("Enter %s:  BRIDGE dev=%s\n", __FUNCTION__, pci_name(dev));
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* get busno of downstream bus */
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* add to children of PCI bridge dev->bus */
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!child_bus) {
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("%s: could not add second bus\n", __FUNCTION__);
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* do pci_scan_child_bus */
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_scan_child_bus(child_bus);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eeh_add_device_late(child_dev);
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 /* fixup new pci devices without touching bus struct */
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rpaphp_fixup_new_pci_devices(child_bus, 0);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make the discovered devices available */
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_bus_add_devices(child_bus);
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2335fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rosevoid rpaphp_init_new_devs(struct pci_bus *bus)
2345fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose{
2355fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose	rpaphp_fixup_new_pci_devices(bus, 0);
2365fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose	rpaphp_eeh_add_bus_device(bus);
2375fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose}
2385fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John RoseEXPORT_SYMBOL_GPL(rpaphp_init_new_devs);
2395fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose
240bde168412440084e649e7e04938bd1ab6e7bf978John Rose/*****************************************************************************
241bde168412440084e649e7e04938bd1ab6e7bf978John Rose rpaphp_pci_config_slot() will  configure all devices under the
242bde168412440084e649e7e04938bd1ab6e7bf978John Rose given slot->dn and return the the first pci_dev.
243bde168412440084e649e7e04938bd1ab6e7bf978John Rose *****************************************************************************/
244bde168412440084e649e7e04938bd1ab6e7bf978John Rosestatic struct pci_dev *
245940903c5a5a906c622a79b3101586deb1a1b3480John Roserpaphp_pci_config_slot(struct pci_bus *bus)
246bde168412440084e649e7e04938bd1ab6e7bf978John Rose{
247940903c5a5a906c622a79b3101586deb1a1b3480John Rose	struct device_node *dn = pci_bus_to_OF_node(bus);
248bde168412440084e649e7e04938bd1ab6e7bf978John Rose	struct pci_dev *dev = NULL;
2499c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	int slotno;
250bde168412440084e649e7e04938bd1ab6e7bf978John Rose	int num;
251bde168412440084e649e7e04938bd1ab6e7bf978John Rose
252bde168412440084e649e7e04938bd1ab6e7bf978John Rose	dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
253940903c5a5a906c622a79b3101586deb1a1b3480John Rose	if (!dn || !dn->child)
2540945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose		return NULL;
255bde168412440084e649e7e04938bd1ab6e7bf978John Rose
25689a071b80767c3a7ed56e13ae5e810f751b19eebAndrew Morton	if (_machine == PLATFORM_PSERIES_LPAR) {
2575fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		of_scan_bus(dn, bus);
2585fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		if (list_empty(&bus->devices)) {
2595fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			err("%s: No new device found\n", __FUNCTION__);
2605fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			return NULL;
2615fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		}
2629c209c919df95f83aa042b3352c43841ad15a02bJohn Rose
2635fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		rpaphp_init_new_devs(bus);
2640945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose		pci_bus_add_devices(bus);
2655fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		dev = list_entry(&bus->devices, struct pci_dev, bus_list);
2665fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose	} else {
2675fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
2685fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose
2695fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		/* pci_scan_slot should find all children */
2705fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
2715fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		if (num) {
2725fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			rpaphp_fixup_new_pci_devices(bus, 1);
2735fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			pci_bus_add_devices(bus);
2745fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		}
2755fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		if (list_empty(&bus->devices)) {
2765fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			err("%s: No new device found\n", __FUNCTION__);
2775fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			return NULL;
2785fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		}
2795fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		list_for_each_entry(dev, &bus->devices, bus_list) {
2805fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
2815fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose				rpaphp_pci_config_bridge(dev);
2825fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose
2835fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			rpaphp_eeh_add_bus_device(bus);
2845fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		}
285bde168412440084e649e7e04938bd1ab6e7bf978John Rose	}
2860945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose
287bde168412440084e649e7e04938bd1ab6e7bf978John Rose	return dev;
288bde168412440084e649e7e04938bd1ab6e7bf978John Rose}
289bde168412440084e649e7e04938bd1ab6e7bf978John Rose
2905fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rosevoid rpaphp_eeh_init_nodes(struct device_node *dn)
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device_node *sib;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (sib = dn->child; sib; sib = sib->sibling)
2955fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose		rpaphp_eeh_init_nodes(sib);
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eeh_add_device_early(dn);
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3005fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John RoseEXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
302940903c5a5a906c622a79b3101586deb1a1b3480John Rosestatic void print_slot_pci_funcs(struct pci_bus *bus)
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
304940903c5a5a906c622a79b3101586deb1a1b3480John Rose	struct device_node *dn;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
307940903c5a5a906c622a79b3101586deb1a1b3480John Rose	dn = pci_bus_to_OF_node(bus);
308940903c5a5a906c622a79b3101586deb1a1b3480John Rose	if (!dn)
309940903c5a5a906c622a79b3101586deb1a1b3480John Rose		return;
310940903c5a5a906c622a79b3101586deb1a1b3480John Rose
311940903c5a5a906c622a79b3101586deb1a1b3480John Rose	dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name);
312940903c5a5a906c622a79b3101586deb1a1b3480John Rose	list_for_each_entry (dev, &bus->devices, bus_list)
3135eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose		dbg("\t%s\n", pci_name(dev));
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
317940903c5a5a906c622a79b3101586deb1a1b3480John Roseint rpaphp_config_pci_adapter(struct pci_bus *bus)
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
319940903c5a5a906c622a79b3101586deb1a1b3480John Rose	struct device_node *dn = pci_bus_to_OF_node(bus);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc = -ENODEV;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
323940903c5a5a906c622a79b3101586deb1a1b3480John Rose	dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name);
324940903c5a5a906c622a79b3101586deb1a1b3480John Rose	if (!dn)
325940903c5a5a906c622a79b3101586deb1a1b3480John Rose		goto exit;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3275fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose	rpaphp_eeh_init_nodes(dn);
328940903c5a5a906c622a79b3101586deb1a1b3480John Rose	dev = rpaphp_pci_config_slot(bus);
3299c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	if (!dev) {
3309c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		err("%s: can't find any devices.\n", __FUNCTION__);
3319c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		goto exit;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
333940903c5a5a906c622a79b3101586deb1a1b3480John Rose	print_slot_pci_funcs(bus);
3349c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	rc = 0;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("Exit %s:  rc=%d\n", __FUNCTION__, rc);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
339940903c5a5a906c622a79b3101586deb1a1b3480John RoseEXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter);
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eeh_remove_device(dev);
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct pci_bus *bus = dev->subordinate;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct list_head *ln;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!bus)
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct pci_dev *pdev = pci_dev_b(ln);
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (pdev)
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rpaphp_eeh_remove_bus_device(pdev);
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
359934199e95d6ac28f42686fe3009877eff33e06c3Linas Vepstasint rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3619c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct pci_dev *dev, *tmp;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
363934199e95d6ac28f42686fe3009877eff33e06c3Linas Vepstas	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rpaphp_eeh_remove_bus_device(dev);
3659c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		pci_remove_bus_device(dev);
3669c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	}
367934199e95d6ac28f42686fe3009877eff33e06c3Linas Vepstas	return 0;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3695fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John RoseEXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter);
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int setup_pci_hotplug_slot_info(struct slot *slot)
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("%s Initilize the PCI slot's hotplug->info structure ...\n",
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    __FUNCTION__);
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rpaphp_get_power_status(slot, &slot->hotplug_slot->info->power_status);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rpaphp_get_pci_adapter_status(slot, 1,
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      &slot->hotplug_slot->info->
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      adapter_status);
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (slot->hotplug_slot->info->adapter_status == NOT_VALID) {
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("%s: NOT_VALID: skip dn->full_name=%s\n",
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __FUNCTION__, slot->dn->full_name);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3879c209c919df95f83aa042b3352c43841ad15a02bJohn Rosestatic void set_slot_name(struct slot *slot)
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3899c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct pci_bus *bus = slot->bus;
3909c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct pci_dev *bridge;
3919c209c919df95f83aa042b3352c43841ad15a02bJohn Rose
3929c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	bridge = bus->self;
3939c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	if (bridge)
3949c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		strcpy(slot->name, pci_name(bridge));
3959c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	else
3969c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
3979c209c919df95f83aa042b3352c43841ad15a02bJohn Rose			bus->number);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int setup_pci_slot(struct slot *slot)
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4029c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct device_node *dn = slot->dn;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *bus;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4059c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	BUG_ON(!dn);
4069c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	bus = rpaphp_find_pci_bus(dn);
4079c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	if (!bus) {
4089c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
4099c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		goto exit_rc;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4129c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	slot->bus = bus;
4139c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	slot->pci_devs = &bus->devices;
4149c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	set_slot_name(slot);
4159c209c919df95f83aa042b3352c43841ad15a02bJohn Rose
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* find slot's pci_dev if it's not empty */
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (slot->hotplug_slot->info->adapter_status == EMPTY) {
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->state = EMPTY;	/* slot is empty */
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* slot is occupied */
4219c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		if (!dn->child) {
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* non-empty slot has to have child */
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				__FUNCTION__, slot->name);
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto exit_rc;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dbg("%s CONFIGURING pci adapter in slot[%s]\n",
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				__FUNCTION__, slot->name);
431940903c5a5a906c622a79b3101586deb1a1b3480John Rose			if (rpaphp_config_pci_adapter(slot->bus)) {
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err("%s: CONFIG pci adapter failed\n", __FUNCTION__);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto exit_rc;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) {
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				__FUNCTION__, slot->name);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto exit_rc;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
441940903c5a5a906c622a79b3101586deb1a1b3480John Rose		print_slot_pci_funcs(slot->bus);
4425eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose		if (!list_empty(slot->pci_devs)) {
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			slot->state = CONFIGURED;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* DLPAR add as opposed to
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 	 * boot time */
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			slot->state = NOT_CONFIGURED;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit_rc:
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dealloc_slot_struct(slot);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EINVAL;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint register_pci_slot(struct slot *slot)
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc = -EINVAL;
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (setup_pci_hotplug_slot_info(slot))
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit_rc;
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (setup_pci_slot(slot))
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit_rc;
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = register_slot(slot);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit_rc:
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_enable_pci_slot(struct slot *slot)
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval = 0, state;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = rpaphp_get_sensor_state(slot, &state);
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval)
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("%s: sensor state[%d]\n", __FUNCTION__, state);
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if slot is not empty, enable the adapter */
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (state == PRESENT) {
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name);
480940903c5a5a906c622a79b3101586deb1a1b3480John Rose		retval = rpaphp_config_pci_adapter(slot->bus);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!retval) {
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			slot->state = CONFIGURED;
4835fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose			info("%s: devices in slot[%s] configured\n",
4845fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose					__FUNCTION__, slot->name);
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			slot->state = NOT_CONFIGURED;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dbg("%s: no pci_dev struct for adapter in slot[%s]\n",
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    __FUNCTION__, slot->name);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (state == EMPTY) {
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->state = EMPTY;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("%s: slot[%s] is in invalid state\n", __FUNCTION__,
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    slot->name);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->state = NOT_VALID;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = -EINVAL;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
503