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