rpaphp_pci.c revision 56d8456b06ad1316bff3c75caed5e06e786f20d8
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
8fbb7a2dc2be493c87399550bdc2ddaa510cdf450Bob Moore * 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>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pci-bridge.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/rtas.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/machdep.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "../pci.h"		/* for pci_add_new_bus */
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "rpaphp.h"
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_bus *find_bus_among_children(struct pci_bus *bus,
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					struct device_node *dn)
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *child = NULL;
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head *tmp;
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device_node *busdn;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	busdn = pci_bus_to_OF_node(bus);
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (busdn == dn)
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return bus;
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each(tmp, &bus->children) {
45e2f7a7772880458edff1b1cc5a988947229fac26Len Brown		child = find_bus_among_children(pci_bus_b(tmp), dn);
46e2f7a7772880458edff1b1cc5a988947229fac26Len Brown		if (child)
47e2f7a7772880458edff1b1cc5a988947229fac26Len Brown			break;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return child;
504be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown}
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52b7a69806308600711589e4ca306d18dd029ef0cfBob Moorestruct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
53b7a69806308600711589e4ca306d18dd029ef0cfBob Moore{
54b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	if (!dn->phb || !dn->phb->bus)
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return find_bus_among_children(dn->phb->bus, dn);
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
59ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob MooreEXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
60ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_claim_resource(struct pci_dev *dev, int resource)
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource *res = &dev->resource[resource];
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource *root = pci_find_parent_resource(dev, res);
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
6644f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore	int err = -EINVAL;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (root != NULL) {
69b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		err = request_resource(root, res);
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
714be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	if (err) {
734be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		err("PCI: %s region %d of %s %s [%lx:%lx]\n",
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    root ? "Address space collision on" :
754be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    "No parent found for",
764be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    resource, dtype, pci_name(dev), res->start, res->end);
774be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	}
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
79b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore}
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(rpaphp_claim_resource);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
83793c2388cae3fd023b3b5166354931752d42353cBob Moorestatic int rpaphp_get_sensor_state(struct slot *slot, int *state)
84793c2388cae3fd023b3b5166354931752d42353cBob Moore{
85793c2388cae3fd023b3b5166354931752d42353cBob Moore	int rc;
86793c2388cae3fd023b3b5166354931752d42353cBob Moore	int setlevel;
87793c2388cae3fd023b3b5166354931752d42353cBob Moore
88793c2388cae3fd023b3b5166354931752d42353cBob Moore	rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
89793c2388cae3fd023b3b5166354931752d42353cBob Moore
90793c2388cae3fd023b3b5166354931752d42353cBob Moore	if (rc < 0) {
91793c2388cae3fd023b3b5166354931752d42353cBob Moore		if (rc == -EFAULT || rc == -EEXIST) {
92793c2388cae3fd023b3b5166354931752d42353cBob Moore			dbg("%s: slot must be power up to get sensor-state\n",
93793c2388cae3fd023b3b5166354931752d42353cBob Moore			    __FUNCTION__);
94793c2388cae3fd023b3b5166354931752d42353cBob Moore
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* some slots have to be powered up
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * before get-sensor will succeed.
974be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			 */
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rc = rtas_set_power_level(slot->power_domain, POWER_ON,
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  &setlevel);
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (rc < 0) {
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dbg("%s: power on slot[%s] failed rc=%d.\n",
1024be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    __FUNCTION__, slot->name, rc);
1038313524a0d466f451a62709aaedf988d8257b21cBob Moore			} else {
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rc = rtas_get_sensor(DR_ENTITY_SENSE,
1054be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown						     slot->index, state);
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (rc == -ENODEV)
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			info("%s: slot is unusable\n", __FUNCTION__);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err("%s failed to get sensor state\n", __FUNCTION__);
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1144be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get_pci_adapter_status - get the status of a slot
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0-- slot is empty
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1-- adapter is configured
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2-- adapter is not configured
121ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore * 3-- not valid
122ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore */
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *bus;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int state, rc;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12844f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore	*value = NOT_VALID;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = rpaphp_get_sensor_state(slot, &state);
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc)
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1334be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 	if (state == EMPTY)
1344be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 		*value = EMPTY;
1354be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 	else if (state == PRESENT) {
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!is_init) {
137b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore			/* at run-time slot->state can be changed by */
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* config/unconfig adapter */
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*value = slot->state;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
1414be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			bus = rpaphp_find_pci_bus(slot->dn);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (bus && !list_empty(&bus->devices))
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*value = CONFIGURED;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
1454be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				*value = NOT_CONFIGURED;
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
152ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore/* Must be called before pci_bus_add_devices */
153ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moorestatic void
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(dev, &bus->devices, bus_list) {
15944f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore		/*
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Skip already-present devices (which are on the
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * global device list.)
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (list_empty(&dev->global_list)) {
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int i;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1664be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			/* Need to setup IOMMU tables */
1674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			ppc_md.iommu_dev_setup(dev);
1684be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if(fix_bus)
1704be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				pcibios_fixup_device_resources(dev, bus);
1715df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore			pci_read_irq_line(dev);
1724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1734be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				struct resource *r = &dev->resource[i];
1744be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
1754be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				if (r->parent || !r->start || !r->flags)
176b7a69806308600711589e4ca306d18dd029ef0cfBob Moore					continue;
1774be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				rpaphp_claim_resource(dev, i);
1784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			}
1794be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		}
180b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore	}
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rpaphp_pci_config_bridge(struct pci_dev *dev)
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 sec_busno;
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *child_bus;
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *child_dev;
1884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
1894be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	dbg("Enter %s:  BRIDGE dev=%s\n", __FUNCTION__, pci_name(dev));
1904be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
1914be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	/* get busno of downstream bus */
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* add to children of PCI bridge dev->bus */
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!child_bus) {
1978313524a0d466f451a62709aaedf988d8257b21cBob Moore		err("%s: could not add second bus\n", __FUNCTION__);
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
1994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	}
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* do pci_scan_child_bus */
202c45b5c097001480e66d4c523eb715ad317a4ef77Alexey Starikovskiy	pci_scan_child_bus(child_bus);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eeh_add_device_late(child_dev);
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 /* fixup new pci devices without touching bus struct */
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rpaphp_fixup_new_pci_devices(child_bus, 0);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make the discovered devices available */
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_bus_add_devices(child_bus);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpaphp_pci_config_slot() will  configure all devices under the
21852fc0b026e99b5d5d585095148d997d5634bbc25Bob Moore given slot->dn and return the the first pci_dev.
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_dev *
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrpaphp_pci_config_slot(struct pci_bus *bus)
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
223b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	struct device_node *dn = pci_bus_to_OF_node(bus);
224b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	struct pci_dev *dev = NULL;
225b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	int slotno;
226b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	int num;
227b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
228b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
229b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	if (!dn || !dn->child)
2301f86e8c1c9f129d450fd75e42d25ddba69a522acLv Zheng		return NULL;
231b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
232b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	slotno = PCI_SLOT(dn->child->devfn);
233b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
2349f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore	/* pci_scan_slot should find all children */
2359f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore	num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
2369f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore	if (num) {
237b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		rpaphp_fixup_new_pci_devices(bus, 1);
238b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		pci_bus_add_devices(bus);
239b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	}
240b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	if (list_empty(&bus->devices)) {
241d4913dc6d0c680aa106d1d80b5ad2a9325367afdBob Moore		err("%s: No new device found\n", __FUNCTION__);
242d4913dc6d0c680aa106d1d80b5ad2a9325367afdBob Moore		return NULL;
243b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	}
244b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	list_for_each_entry(dev, &bus->devices, bus_list) {
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rpaphp_pci_config_bridge(dev);
247b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	}
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev;
250c45b5c097001480e66d4c523eb715ad317a4ef77Alexey Starikovskiy}
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void enable_eeh(struct device_node *dn)
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2544be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct device_node *sib;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (sib = dn->child; sib; sib = sib->sibling)
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enable_eeh(sib);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eeh_add_device_early(dn);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void print_slot_pci_funcs(struct pci_bus *bus)
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device_node *dn;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2688313524a0d466f451a62709aaedf988d8257b21cBob Moore	dn = pci_bus_to_OF_node(bus);
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dn)
2704be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		return;
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry (dev, &bus->devices, bus_list)
2749f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore		dbg("\t%s\n", pci_name(dev));
2759f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore	return;
276b7a69806308600711589e4ca306d18dd029ef0cfBob Moore}
277b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
278b7a69806308600711589e4ca306d18dd029ef0cfBob Mooreint rpaphp_config_pci_adapter(struct pci_bus *bus)
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
280b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	struct device_node *dn = pci_bus_to_OF_node(bus);
281b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	struct pci_dev *dev;
282c45b5c097001480e66d4c523eb715ad317a4ef77Alexey Starikovskiy	int rc = -ENODEV;
283b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
284b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name);
285b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	if (!dn)
286e6917317c0f6a930442c40dc38a6f21710adf961Jesper Juhl		goto exit;
287b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
288b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	enable_eeh(dn);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev = rpaphp_pci_config_slot(bus);
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev) {
29195abccb576c44bc593e05fa1245d0ad26ce6107bBob Moore		err("%s: can't find any devices.\n", __FUNCTION__);
29295abccb576c44bc593e05fa1245d0ad26ce6107bBob Moore		goto exit;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
294d4913dc6d0c680aa106d1d80b5ad2a9325367afdBob Moore	print_slot_pci_funcs(bus);
295d4913dc6d0c680aa106d1d80b5ad2a9325367afdBob Moore	rc = 0;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("Exit %s:  rc=%d\n", __FUNCTION__, rc);
2989f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore	return rc;
2999f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore}
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter);
3014be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
3024be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
3034be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown{
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eeh_remove_device(dev);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct pci_bus *bus = dev->subordinate;
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct list_head *ln;
308d4913dc6d0c680aa106d1d80b5ad2a9325367afdBob Moore		if (!bus)
309d4913dc6d0c680aa106d1d80b5ad2a9325367afdBob Moore			return;
3104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
3114be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			struct pci_dev *pdev = pci_dev_b(ln);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (pdev)
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rpaphp_eeh_remove_bus_device(pdev);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
316d4913dc6d0c680aa106d1d80b5ad2a9325367afdBob Moore	}
317d4913dc6d0c680aa106d1d80b5ad2a9325367afdBob Moore	return;
3184be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown}
3194be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_unconfig_pci_adapter(struct slot *slot)
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32295abccb576c44bc593e05fa1245d0ad26ce6107bBob Moore	struct pci_dev *dev, *tmp;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval = 0;
32495abccb576c44bc593e05fa1245d0ad26ce6107bBob Moore
32595abccb576c44bc593e05fa1245d0ad26ce6107bBob Moore	list_for_each_entry_safe(dev, tmp, slot->pci_devs, bus_list) {
32695abccb576c44bc593e05fa1245d0ad26ce6107bBob Moore		rpaphp_eeh_remove_bus_device(dev);
32795abccb576c44bc593e05fa1245d0ad26ce6107bBob Moore		pci_remove_bus_device(dev);
32895abccb576c44bc593e05fa1245d0ad26ce6107bBob Moore	}
32995abccb576c44bc593e05fa1245d0ad26ce6107bBob Moore
33095abccb576c44bc593e05fa1245d0ad26ce6107bBob Moore	slot->state = NOT_CONFIGURED;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     slot->name);
3334be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return retval;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int setup_pci_hotplug_slot_info(struct slot *slot)
337b7a69806308600711589e4ca306d18dd029ef0cfBob Moore{
338b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	dbg("%s Initilize the PCI slot's hotplug->info structure ...\n",
339b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	    __FUNCTION__);
340ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore	rpaphp_get_power_status(slot, &slot->hotplug_slot->info->power_status);
341b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	rpaphp_get_pci_adapter_status(slot, 1,
342b7a69806308600711589e4ca306d18dd029ef0cfBob Moore				      &slot->hotplug_slot->info->
343b7a69806308600711589e4ca306d18dd029ef0cfBob Moore				      adapter_status);
344b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	if (slot->hotplug_slot->info->adapter_status == NOT_VALID) {
345b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		err("%s: NOT_VALID: skip dn->full_name=%s\n",
346b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		    __FUNCTION__, slot->dn->full_name);
347b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		return -EINVAL;
348b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	}
349b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	return 0;
350b7a69806308600711589e4ca306d18dd029ef0cfBob Moore}
351b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
35278e25fef2751434f38c7f711ecbf8762f79f7318Lv Zhengstatic void set_slot_name(struct slot *slot)
35378e25fef2751434f38c7f711ecbf8762f79f7318Lv Zheng{
35467a119f990063f5662574f6d6414fe9bc5ece86aBob Moore	struct pci_bus *bus = slot->bus;
35515b8dd53f5ffaf8e2d9095c423f713423f576c0fBob Moore	struct pci_dev *bridge;
356b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
3579f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore	bridge = bus->self;
3589f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore	if (bridge)
359b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		strcpy(slot->name, pci_name(bridge));
360b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	else
361b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
362b7a69806308600711589e4ca306d18dd029ef0cfBob Moore			bus->number);
363b7a69806308600711589e4ca306d18dd029ef0cfBob Moore}
36415b8dd53f5ffaf8e2d9095c423f713423f576c0fBob Moore
36515b8dd53f5ffaf8e2d9095c423f713423f576c0fBob Moorestatic int setup_pci_slot(struct slot *slot)
36615b8dd53f5ffaf8e2d9095c423f713423f576c0fBob Moore{
36715b8dd53f5ffaf8e2d9095c423f713423f576c0fBob Moore	struct device_node *dn = slot->dn;
368b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	struct pci_bus *bus;
369b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
370b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	BUG_ON(!dn);
3719f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore	bus = rpaphp_find_pci_bus(dn);
3729f15fc666ef54afc7aff31dfa31edecf00e0d81aBob Moore	if (!bus) {
373b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
374b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		goto exit_rc;
375b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	}
376b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
377b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	slot->bus = bus;
378b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	slot->pci_devs = &bus->devices;
379b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	set_slot_name(slot);
380b7a69806308600711589e4ca306d18dd029ef0cfBob Moore
38115b8dd53f5ffaf8e2d9095c423f713423f576c0fBob Moore	/* find slot's pci_dev if it's not empty */
382b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	if (slot->hotplug_slot->info->adapter_status == EMPTY) {
383b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		slot->state = EMPTY;	/* slot is empty */
384b7a69806308600711589e4ca306d18dd029ef0cfBob Moore	} else {
385b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		/* slot is occupied */
386b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		if (!dn->child) {
387b7a69806308600711589e4ca306d18dd029ef0cfBob Moore			/* non-empty slot has to have child */
388b7a69806308600711589e4ca306d18dd029ef0cfBob Moore			err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
389b7a69806308600711589e4ca306d18dd029ef0cfBob Moore				__FUNCTION__, slot->name);
390b7a69806308600711589e4ca306d18dd029ef0cfBob Moore			goto exit_rc;
391b7a69806308600711589e4ca306d18dd029ef0cfBob Moore		}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dbg("%s CONFIGURING pci adapter in slot[%s]\n",
395ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore				__FUNCTION__, slot->name);
396ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore			if (rpaphp_config_pci_adapter(slot->bus)) {
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err("%s: CONFIG pci adapter failed\n", __FUNCTION__);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto exit_rc;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) {
402ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore			err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				__FUNCTION__, slot->name);
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto exit_rc;
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		print_slot_pci_funcs(slot->bus);
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!list_empty(slot->pci_devs)) {
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			slot->state = CONFIGURED;
4094be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		} else {
4104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			/* DLPAR add as opposed to
4114be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		 	 * boot time */
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			slot->state = NOT_CONFIGURED;
413b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore		}
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4154be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return 0;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit_rc:
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dealloc_slot_struct(slot);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EINVAL;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint register_pci_slot(struct slot *slot)
422ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore{
423ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore	int rc = -EINVAL;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (setup_pci_hotplug_slot_info(slot))
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit_rc;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (setup_pci_slot(slot))
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit_rc;
42944f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore	rc = register_slot(slot);
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit_rc:
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_enable_pci_slot(struct slot *slot)
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4364be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	int retval = 0, state;
4374be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
4384be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	retval = rpaphp_get_sensor_state(slot, &state);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval)
440b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore		goto exit;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dbg("%s: sensor state[%d]\n", __FUNCTION__, state);
4424be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	/* if slot is not empty, enable the adapter */
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (state == PRESENT) {
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = rpaphp_config_pci_adapter(slot->bus);
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!retval) {
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			slot->state = CONFIGURED;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dbg("%s: PCI devices in slot[%s] has been configured\n",
449ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore				__FUNCTION__, slot->name);
450ba494beeaa69bc0fb01eb89464ad5d57d26e3901Bob Moore		} else {
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			slot->state = NOT_CONFIGURED;
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dbg("%s: no pci_dev struct for adapter in slot[%s]\n",
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    __FUNCTION__, slot->name);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (state == EMPTY) {
45644f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore		dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name);
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		slot->state = EMPTY;
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err("%s: slot[%s] is in invalid state\n", __FUNCTION__,
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    slot->name);
4614be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		slot->state = NOT_VALID;
4624be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		retval = -EINVAL;
4634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	}
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
465b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds