rpaphp_pci.c revision cd5b50be8d8e8e6170da3a261fc625fd603f9dc4
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 Torvaldsstatic int rpaphp_get_sensor_state(struct slot *slot, int *state) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int setlevel; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc < 0) { 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc == -EFAULT || rc == -EEXIST) { 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s: slot must be power up to get sensor-state\n", 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __FUNCTION__); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* some slots have to be powered up 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * before get-sensor will succeed. 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = rtas_set_power_level(slot->power_domain, POWER_ON, 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &setlevel); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc < 0) { 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s: power on slot[%s] failed rc=%d.\n", 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __FUNCTION__, slot->name, rc); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = rtas_get_sensor(DR_ENTITY_SENSE, 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->index, state); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (rc == -ENODEV) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info("%s: slot is unusable\n", __FUNCTION__); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("%s failed to get sensor state\n", __FUNCTION__); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get_pci_adapter_status - get the status of a slot 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0-- slot is empty 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1-- adapter is configured 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2-- adapter is not configured 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3-- not valid 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value) 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1070945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose struct pci_bus *bus; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int state, rc; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value = NOT_VALID; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = rpaphp_get_sensor_state(slot, &state); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11556d8456b06ad1316bff3c75caed5e06e786f20d8John Rose if (state == EMPTY) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value = EMPTY; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (state == PRESENT) { 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!is_init) { 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* at run-time slot->state can be changed by */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* config/unconfig adapter */ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value = slot->state; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1230945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose bus = rpaphp_find_pci_bus(slot->dn); 1240945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose if (bus && !list_empty(&bus->devices)) 1250945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose *value = CONFIGURED; 1260945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose else 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value = NOT_CONFIGURED; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Must be called before pci_bus_add_devices */ 1355fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rosevoid rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *dev; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(dev, &bus->devices, bus_list) { 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Skip already-present devices (which are on the 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * global device list.) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (list_empty(&dev->global_list)) { 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Need to setup IOMMU tables */ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ppc_md.iommu_dev_setup(dev); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(fix_bus) 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcibios_fixup_device_resources(dev, bus); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_irq_line(dev); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < PCI_NUM_RESOURCES; i++) { 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *r = &dev->resource[i]; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (r->parent || !r->start || !r->flags) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 158cd5b50be8d8e8e6170da3a261fc625fd603f9dc4Linas Vepstas pci_claim_resource(dev, i); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1645fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rosestatic void rpaphp_eeh_add_bus_device(struct pci_bus *bus) 1655fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose{ 1665fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose struct pci_dev *dev; 1675fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose 1685fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose list_for_each_entry(dev, &bus->devices, bus_list) { 1695fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose eeh_add_device_late(dev); 1705fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 1715fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose struct pci_bus *subbus = dev->subordinate; 1725fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose if (subbus) 1735fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose rpaphp_eeh_add_bus_device (subbus); 1745fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose } 1755fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose } 1765fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose} 1775fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rpaphp_pci_config_bridge(struct pci_dev *dev) 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 sec_busno; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_bus *child_bus; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *child_dev; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("Enter %s: BRIDGE dev=%s\n", __FUNCTION__, pci_name(dev)); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get busno of downstream bus */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* add to children of PCI bridge dev->bus */ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds child_bus = pci_add_new_bus(dev->bus, dev, sec_busno); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!child_bus) { 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("%s: could not add second bus\n", __FUNCTION__); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* do pci_scan_child_bus */ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_scan_child_bus(child_bus); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(child_dev, &child_bus->devices, bus_list) { 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeh_add_device_late(child_dev); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fixup new pci devices without touching bus struct */ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpaphp_fixup_new_pci_devices(child_bus, 0); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make the discovered devices available */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_bus_add_devices(child_bus); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2115fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rosevoid rpaphp_init_new_devs(struct pci_bus *bus) 2125fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose{ 2135fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose rpaphp_fixup_new_pci_devices(bus, 0); 2145fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose rpaphp_eeh_add_bus_device(bus); 2155fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose} 2165fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John RoseEXPORT_SYMBOL_GPL(rpaphp_init_new_devs); 2175fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose 218bde168412440084e649e7e04938bd1ab6e7bf978John Rose/***************************************************************************** 219bde168412440084e649e7e04938bd1ab6e7bf978John Rose rpaphp_pci_config_slot() will configure all devices under the 220bde168412440084e649e7e04938bd1ab6e7bf978John Rose given slot->dn and return the the first pci_dev. 221bde168412440084e649e7e04938bd1ab6e7bf978John Rose *****************************************************************************/ 222bde168412440084e649e7e04938bd1ab6e7bf978John Rosestatic struct pci_dev * 223940903c5a5a906c622a79b3101586deb1a1b3480John Roserpaphp_pci_config_slot(struct pci_bus *bus) 224bde168412440084e649e7e04938bd1ab6e7bf978John Rose{ 225940903c5a5a906c622a79b3101586deb1a1b3480John Rose struct device_node *dn = pci_bus_to_OF_node(bus); 226bde168412440084e649e7e04938bd1ab6e7bf978John Rose struct pci_dev *dev = NULL; 2279c209c919df95f83aa042b3352c43841ad15a02bJohn Rose int slotno; 228bde168412440084e649e7e04938bd1ab6e7bf978John Rose int num; 229bde168412440084e649e7e04938bd1ab6e7bf978John Rose 230bde168412440084e649e7e04938bd1ab6e7bf978John Rose dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name); 231940903c5a5a906c622a79b3101586deb1a1b3480John Rose if (!dn || !dn->child) 2320945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose return NULL; 233bde168412440084e649e7e04938bd1ab6e7bf978John Rose 23489a071b80767c3a7ed56e13ae5e810f751b19eebAndrew Morton if (_machine == PLATFORM_PSERIES_LPAR) { 2355fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose of_scan_bus(dn, bus); 2365fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose if (list_empty(&bus->devices)) { 2375fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose err("%s: No new device found\n", __FUNCTION__); 2385fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose return NULL; 2395fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose } 2409c209c919df95f83aa042b3352c43841ad15a02bJohn Rose 2415fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose rpaphp_init_new_devs(bus); 2420945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose pci_bus_add_devices(bus); 2435fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose dev = list_entry(&bus->devices, struct pci_dev, bus_list); 2445fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose } else { 2455fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); 2465fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose 2475fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose /* pci_scan_slot should find all children */ 2485fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); 2495fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose if (num) { 2505fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose rpaphp_fixup_new_pci_devices(bus, 1); 2515fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose pci_bus_add_devices(bus); 2525fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose } 2535fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose if (list_empty(&bus->devices)) { 2545fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose err("%s: No new device found\n", __FUNCTION__); 2555fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose return NULL; 2565fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose } 2575fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose list_for_each_entry(dev, &bus->devices, bus_list) { 2585fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) 2595fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose rpaphp_pci_config_bridge(dev); 2605fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose 2615fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose rpaphp_eeh_add_bus_device(bus); 2625fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose } 263bde168412440084e649e7e04938bd1ab6e7bf978John Rose } 2640945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose 265bde168412440084e649e7e04938bd1ab6e7bf978John Rose return dev; 266bde168412440084e649e7e04938bd1ab6e7bf978John Rose} 267bde168412440084e649e7e04938bd1ab6e7bf978John Rose 268940903c5a5a906c622a79b3101586deb1a1b3480John Rosestatic void print_slot_pci_funcs(struct pci_bus *bus) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 270940903c5a5a906c622a79b3101586deb1a1b3480John Rose struct device_node *dn; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *dev; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 273940903c5a5a906c622a79b3101586deb1a1b3480John Rose dn = pci_bus_to_OF_node(bus); 274940903c5a5a906c622a79b3101586deb1a1b3480John Rose if (!dn) 275940903c5a5a906c622a79b3101586deb1a1b3480John Rose return; 276940903c5a5a906c622a79b3101586deb1a1b3480John Rose 277940903c5a5a906c622a79b3101586deb1a1b3480John Rose dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name); 278940903c5a5a906c622a79b3101586deb1a1b3480John Rose list_for_each_entry (dev, &bus->devices, bus_list) 2795eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose dbg("\t%s\n", pci_name(dev)); 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 283940903c5a5a906c622a79b3101586deb1a1b3480John Roseint rpaphp_config_pci_adapter(struct pci_bus *bus) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 285940903c5a5a906c622a79b3101586deb1a1b3480John Rose struct device_node *dn = pci_bus_to_OF_node(bus); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *dev; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc = -ENODEV; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289940903c5a5a906c622a79b3101586deb1a1b3480John Rose dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name); 290940903c5a5a906c622a79b3101586deb1a1b3480John Rose if (!dn) 291940903c5a5a906c622a79b3101586deb1a1b3480John Rose goto exit; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 293d681db4aed4453c7d34adfbb64956271186514e9Linas Vepstas eeh_add_device_tree_early(dn); 294940903c5a5a906c622a79b3101586deb1a1b3480John Rose dev = rpaphp_pci_config_slot(bus); 2959c209c919df95f83aa042b3352c43841ad15a02bJohn Rose if (!dev) { 2969c209c919df95f83aa042b3352c43841ad15a02bJohn Rose err("%s: can't find any devices.\n", __FUNCTION__); 2979c209c919df95f83aa042b3352c43841ad15a02bJohn Rose goto exit; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 299940903c5a5a906c622a79b3101586deb1a1b3480John Rose print_slot_pci_funcs(bus); 3009c209c919df95f83aa042b3352c43841ad15a02bJohn Rose rc = 0; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("Exit %s: rc=%d\n", __FUNCTION__, rc); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 305940903c5a5a906c622a79b3101586deb1a1b3480John RoseEXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rpaphp_eeh_remove_bus_device(struct pci_dev *dev) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeh_remove_device(dev); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_bus *bus = dev->subordinate; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *ln; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bus) 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *pdev = pci_dev_b(ln); 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev) 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpaphp_eeh_remove_bus_device(pdev); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 325934199e95d6ac28f42686fe3009877eff33e06c3Linas Vepstasint rpaphp_unconfig_pci_adapter(struct pci_bus *bus) 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3279c209c919df95f83aa042b3352c43841ad15a02bJohn Rose struct pci_dev *dev, *tmp; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 329934199e95d6ac28f42686fe3009877eff33e06c3Linas Vepstas list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpaphp_eeh_remove_bus_device(dev); 3319c209c919df95f83aa042b3352c43841ad15a02bJohn Rose pci_remove_bus_device(dev); 3329c209c919df95f83aa042b3352c43841ad15a02bJohn Rose } 333934199e95d6ac28f42686fe3009877eff33e06c3Linas Vepstas return 0; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3355fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John RoseEXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int setup_pci_hotplug_slot_info(struct slot *slot) 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s Initilize the PCI slot's hotplug->info structure ...\n", 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __FUNCTION__); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpaphp_get_power_status(slot, &slot->hotplug_slot->info->power_status); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpaphp_get_pci_adapter_status(slot, 1, 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &slot->hotplug_slot->info-> 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter_status); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (slot->hotplug_slot->info->adapter_status == NOT_VALID) { 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("%s: NOT_VALID: skip dn->full_name=%s\n", 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __FUNCTION__, slot->dn->full_name); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3539c209c919df95f83aa042b3352c43841ad15a02bJohn Rosestatic void set_slot_name(struct slot *slot) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3559c209c919df95f83aa042b3352c43841ad15a02bJohn Rose struct pci_bus *bus = slot->bus; 3569c209c919df95f83aa042b3352c43841ad15a02bJohn Rose struct pci_dev *bridge; 3579c209c919df95f83aa042b3352c43841ad15a02bJohn Rose 3589c209c919df95f83aa042b3352c43841ad15a02bJohn Rose bridge = bus->self; 3599c209c919df95f83aa042b3352c43841ad15a02bJohn Rose if (bridge) 3609c209c919df95f83aa042b3352c43841ad15a02bJohn Rose strcpy(slot->name, pci_name(bridge)); 3619c209c919df95f83aa042b3352c43841ad15a02bJohn Rose else 3629c209c919df95f83aa042b3352c43841ad15a02bJohn Rose sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus), 3639c209c919df95f83aa042b3352c43841ad15a02bJohn Rose bus->number); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int setup_pci_slot(struct slot *slot) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3689c209c919df95f83aa042b3352c43841ad15a02bJohn Rose struct device_node *dn = slot->dn; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_bus *bus; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3719c209c919df95f83aa042b3352c43841ad15a02bJohn Rose BUG_ON(!dn); 3729c209c919df95f83aa042b3352c43841ad15a02bJohn Rose bus = rpaphp_find_pci_bus(dn); 3739c209c919df95f83aa042b3352c43841ad15a02bJohn Rose if (!bus) { 3749c209c919df95f83aa042b3352c43841ad15a02bJohn Rose err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name); 3759c209c919df95f83aa042b3352c43841ad15a02bJohn Rose goto exit_rc; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3789c209c919df95f83aa042b3352c43841ad15a02bJohn Rose slot->bus = bus; 3799c209c919df95f83aa042b3352c43841ad15a02bJohn Rose slot->pci_devs = &bus->devices; 3809c209c919df95f83aa042b3352c43841ad15a02bJohn Rose set_slot_name(slot); 3819c209c919df95f83aa042b3352c43841ad15a02bJohn Rose 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* find slot's pci_dev if it's not empty */ 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (slot->hotplug_slot->info->adapter_status == EMPTY) { 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->state = EMPTY; /* slot is empty */ 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* slot is occupied */ 3879c209c919df95f83aa042b3352c43841ad15a02bJohn Rose if (!dn->child) { 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* non-empty slot has to have child */ 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("%s: slot[%s]'s device_node doesn't have child for adapter\n", 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __FUNCTION__, slot->name); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit_rc; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) { 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s CONFIGURING pci adapter in slot[%s]\n", 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __FUNCTION__, slot->name); 397940903c5a5a906c622a79b3101586deb1a1b3480John Rose if (rpaphp_config_pci_adapter(slot->bus)) { 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("%s: CONFIG pci adapter failed\n", __FUNCTION__); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit_rc; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) { 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("%s: slot[%s]'s adapter_status is NOT_VALID.\n", 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __FUNCTION__, slot->name); 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit_rc; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 407940903c5a5a906c622a79b3101586deb1a1b3480John Rose print_slot_pci_funcs(slot->bus); 4085eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose if (!list_empty(slot->pci_devs)) { 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->state = CONFIGURED; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* DLPAR add as opposed to 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * boot time */ 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->state = NOT_CONFIGURED; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit_rc: 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dealloc_slot_struct(slot); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint register_pci_slot(struct slot *slot) 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc = -EINVAL; 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (setup_pci_hotplug_slot_info(slot)) 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit_rc; 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (setup_pci_slot(slot)) 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit_rc; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = register_slot(slot); 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit_rc: 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rpaphp_enable_pci_slot(struct slot *slot) 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0, state; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = rpaphp_get_sensor_state(slot, &state); 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s: sensor state[%d]\n", __FUNCTION__, state); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if slot is not empty, enable the adapter */ 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state == PRESENT) { 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name); 446940903c5a5a906c622a79b3101586deb1a1b3480John Rose retval = rpaphp_config_pci_adapter(slot->bus); 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!retval) { 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->state = CONFIGURED; 4495fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose info("%s: devices in slot[%s] configured\n", 4505fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose __FUNCTION__, slot->name); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->state = NOT_CONFIGURED; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s: no pci_dev struct for adapter in slot[%s]\n", 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __FUNCTION__, slot->name); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (state == EMPTY) { 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->state = EMPTY; 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("%s: slot[%s] is in invalid state\n", __FUNCTION__, 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->name); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->state = NOT_VALID; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINVAL; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 469