rpaphp_pci.c revision 7fec77e4793f307b30846a3d4015d329ffc0b685
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
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rpaphp_get_sensor_state(struct slot *slot, int *state)
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc;
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int setlevel;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc < 0) {
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rc == -EFAULT || rc == -EEXIST) {
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dbg("%s: slot must be power up to get sensor-state\n",
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    __FUNCTION__);
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* some slots have to be powered up
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * before get-sensor will succeed.
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rc = rtas_set_power_level(slot->power_domain, POWER_ON,
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  &setlevel);
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (rc < 0) {
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dbg("%s: power on slot[%s] failed rc=%d.\n",
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    __FUNCTION__, slot->name, rc);
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rc = rtas_get_sensor(DR_ENTITY_SENSE,
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						     slot->index, state);
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (rc == -ENODEV)
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			info("%s: slot is unusable\n", __FUNCTION__);
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err("%s failed to get sensor state\n", __FUNCTION__);
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get_pci_adapter_status - get the status of a slot
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0-- slot is empty
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1-- adapter is configured
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2-- adapter is not configured
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3-- not valid
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
770945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose	struct pci_bus *bus;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int state, rc;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*value = NOT_VALID;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = rpaphp_get_sensor_state(slot, &state);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc)
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8556d8456b06ad1316bff3c75caed5e06e786f20d8John Rose 	if (state == EMPTY)
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		*value = EMPTY;
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	else if (state == PRESENT) {
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!is_init) {
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* at run-time slot->state can be changed by */
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* config/unconfig adapter */
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*value = slot->state;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
9301657868be1c21b2b8b0e683ea24bdcc2331d522Linas Vepstas			bus = pcibios_find_pci_bus(slot->dn);
940945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose			if (bus && !list_empty(&bus->devices))
950945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose				*value = CONFIGURED;
960945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose			else
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*value = NOT_CONFIGURED;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
104940903c5a5a906c622a79b3101586deb1a1b3480John Rosestatic void print_slot_pci_funcs(struct pci_bus *bus)
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
106940903c5a5a906c622a79b3101586deb1a1b3480John Rose	struct device_node *dn;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
109940903c5a5a906c622a79b3101586deb1a1b3480John Rose	dn = pci_bus_to_OF_node(bus);
110940903c5a5a906c622a79b3101586deb1a1b3480John Rose	if (!dn)
111940903c5a5a906c622a79b3101586deb1a1b3480John Rose		return;
112940903c5a5a906c622a79b3101586deb1a1b3480John Rose
113940903c5a5a906c622a79b3101586deb1a1b3480John Rose	dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name);
114940903c5a5a906c622a79b3101586deb1a1b3480John Rose	list_for_each_entry (dev, &bus->devices, bus_list)
1155eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose		dbg("\t%s\n", pci_name(dev));
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eeh_remove_device(dev);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct pci_bus *bus = dev->subordinate;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct list_head *ln;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!bus)
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct pci_dev *pdev = pci_dev_b(ln);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (pdev)
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rpaphp_eeh_remove_bus_device(pdev);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
137934199e95d6ac28f42686fe3009877eff33e06c3Linas Vepstasint rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1399c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct pci_dev *dev, *tmp;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141934199e95d6ac28f42686fe3009877eff33e06c3Linas Vepstas	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rpaphp_eeh_remove_bus_device(dev);
1439c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		pci_remove_bus_device(dev);
1449c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	}
145934199e95d6ac28f42686fe3009877eff33e06c3Linas Vepstas	return 0;
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1475fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John RoseEXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter);
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int setup_pci_hotplug_slot_info(struct slot *slot)
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
151f5c99dfc11dce8f26c1ceedb6595fa0eac335ea3Jesper Juhl	struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info;
152f5c99dfc11dce8f26c1ceedb6595fa0eac335ea3Jesper Juhl
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("%s Initilize the PCI slot's hotplug->info structure ...\n",
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    __FUNCTION__);
155f5c99dfc11dce8f26c1ceedb6595fa0eac335ea3Jesper Juhl	rpaphp_get_power_status(slot, &hotplug_slot_info->power_status);
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rpaphp_get_pci_adapter_status(slot, 1,
157f5c99dfc11dce8f26c1ceedb6595fa0eac335ea3Jesper Juhl				      &hotplug_slot_info->adapter_status);
158f5c99dfc11dce8f26c1ceedb6595fa0eac335ea3Jesper Juhl	if (hotplug_slot_info->adapter_status == NOT_VALID) {
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("%s: NOT_VALID: skip dn->full_name=%s\n",
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __FUNCTION__, slot->dn->full_name);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1669c209c919df95f83aa042b3352c43841ad15a02bJohn Rosestatic void set_slot_name(struct slot *slot)
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1689c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct pci_bus *bus = slot->bus;
1699c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct pci_dev *bridge;
1709c209c919df95f83aa042b3352c43841ad15a02bJohn Rose
1719c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	bridge = bus->self;
1729c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	if (bridge)
1739c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		strcpy(slot->name, pci_name(bridge));
1749c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	else
1759c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
1769c209c919df95f83aa042b3352c43841ad15a02bJohn Rose			bus->number);
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int setup_pci_slot(struct slot *slot)
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1819c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	struct device_node *dn = slot->dn;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *bus;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1849c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	BUG_ON(!dn);
18501657868be1c21b2b8b0e683ea24bdcc2331d522Linas Vepstas	bus = pcibios_find_pci_bus(dn);
1869c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	if (!bus) {
1879c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
1889c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		goto exit_rc;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1919c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	slot->bus = bus;
1929c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	slot->pci_devs = &bus->devices;
1939c209c919df95f83aa042b3352c43841ad15a02bJohn Rose	set_slot_name(slot);
1949c209c919df95f83aa042b3352c43841ad15a02bJohn Rose
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* find slot's pci_dev if it's not empty */
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (slot->hotplug_slot->info->adapter_status == EMPTY) {
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->state = EMPTY;	/* slot is empty */
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* slot is occupied */
2009c209c919df95f83aa042b3352c43841ad15a02bJohn Rose		if (!dn->child) {
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* non-empty slot has to have child */
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				__FUNCTION__, slot->name);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto exit_rc;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dbg("%s CONFIGURING pci adapter in slot[%s]\n",
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				__FUNCTION__, slot->name);
2107fec77e4793f307b30846a3d4015d329ffc0b685Linas Vepstas			pcibios_add_pci_devices(slot->bus);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) {
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				__FUNCTION__, slot->name);
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto exit_rc;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
217940903c5a5a906c622a79b3101586deb1a1b3480John Rose		print_slot_pci_funcs(slot->bus);
2185eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose		if (!list_empty(slot->pci_devs)) {
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			slot->state = CONFIGURED;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* DLPAR add as opposed to
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 	 * boot time */
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			slot->state = NOT_CONFIGURED;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit_rc:
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dealloc_slot_struct(slot);
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EINVAL;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint register_pci_slot(struct slot *slot)
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc = -EINVAL;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (setup_pci_hotplug_slot_info(slot))
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit_rc;
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (setup_pci_slot(slot))
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit_rc;
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = register_slot(slot);
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit_rc:
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_enable_pci_slot(struct slot *slot)
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval = 0, state;
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = rpaphp_get_sensor_state(slot, &state);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval)
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("%s: sensor state[%d]\n", __FUNCTION__, state);
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if slot is not empty, enable the adapter */
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (state == PRESENT) {
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name);
2567fec77e4793f307b30846a3d4015d329ffc0b685Linas Vepstas		pcibios_add_pci_devices(slot->bus);
2577fec77e4793f307b30846a3d4015d329ffc0b685Linas Vepstas		slot->state = CONFIGURED;
2587fec77e4793f307b30846a3d4015d329ffc0b685Linas Vepstas		info("%s: devices in slot[%s] configured\n",
2595fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose					__FUNCTION__, slot->name);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (state == EMPTY) {
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->state = EMPTY;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("%s: slot[%s] is in invalid state\n", __FUNCTION__,
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    slot->name);
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->state = NOT_VALID;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = -EINVAL;
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
273