11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Interface for Dynamic Logical Partitioning of I/O Slots on 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * RPA-compliant PPC64 platform. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * John Rose <johnrose@austin.ibm.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Linda Xie <lxie@us.ibm.com> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * October 2003 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003 IBM. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as published by the Free Software Foundation; either version 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 of the License, or (at your option) any later version. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt 18fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt#undef DEBUG 19fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 21eefa9cfc891d18aa83744353d2a3fbe95a86ee2dPaul Gortmaker#include <linux/module.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 234e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/string.h> 24b4a26be9f6f8bb72998e445cc75fc6dc0c29513aBenjamin Herrenschmidt#include <linux/vmalloc.h> 254e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pci-bridge.h> 2714cc3e2b633bb64063698980974df4535368e98fIngo Molnar#include <linux/mutex.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/rtas.h> 295eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose#include <asm/vio.h> 304e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "../pci.h" 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "rpaphp.h" 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "rpadlpar.h" 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3514cc3e2b633bb64063698980974df4535368e98fIngo Molnarstatic DEFINE_MUTEX(rpadlpar_mutex); 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3756d8456b06ad1316bff3c75caed5e06e786f20d8John Rose#define DLPAR_MODULE_NAME "rpadlpar_io" 3856d8456b06ad1316bff3c75caed5e06e786f20d8John Rose 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NODE_TYPE_VIO 1 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NODE_TYPE_SLOT 2 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NODE_TYPE_PHB 3 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 435eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rosestatic struct device_node *find_vio_slot_node(char *drc_name) 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device_node *parent = of_find_node_by_name(NULL, "vdevice"); 465eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose struct device_node *dn = NULL; 475eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose char *name; 485eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose int rc; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!parent) 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 535eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose while ((dn = of_get_next_child(parent, dn))) { 545eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL); 555eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose if ((rc == 0) && (!strcmp(drc_name, name))) 565eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose break; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 595eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose return dn; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Find dlpar-capable pci node that contains the specified name and type */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct device_node *find_php_slot_pci_node(char *drc_name, 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *drc_type) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device_node *np = NULL; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *name; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *type; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71a57ed79ef1b71f6da44ebeabb41d019d172fb261John Rose while ((np = of_find_node_by_name(np, "pci"))) { 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = rpaphp_get_drc_props(np, NULL, &name, &type, NULL); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc == 0) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strcmp(drc_name, name) && !strcmp(drc_type, type)) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return np; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 815eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rosestatic struct device_node *find_dlpar_node(char *drc_name, int *node_type) 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device_node *dn; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dn = find_php_slot_pci_node(drc_name, "SLOT"); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dn) { 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *node_type = NODE_TYPE_SLOT; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dn; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dn = find_php_slot_pci_node(drc_name, "PHB"); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dn) { 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *node_type = NODE_TYPE_PHB; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dn; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 975eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose dn = find_vio_slot_node(drc_name); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dn) { 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *node_type = NODE_TYPE_VIO; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dn; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1068485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas/** 1078485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas * find_php_slot - return hotplug slot structure for device node 10826e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @dn: target &device_node 1098485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas * 1108485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas * This routine will return the hotplug slot structure 1118485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas * for a given device node. Note that built-in PCI slots 1128485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas * may be dlpar-able, but not hot-pluggable, so this routine 1138485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas * will return NULL for built-in PCI slots. 1148485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas */ 1158485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstasstatic struct slot *find_php_slot(struct device_node *dn) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *tmp, *n; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct slot *slot; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1208737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas list_for_each_safe(tmp, n, &rpaphp_slot_head) { 1218737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas slot = list_entry(tmp, struct slot, rpaphp_slot_list); 1228737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas if (slot->dn == dn) 1238737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas return slot; 1248737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas } 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1268737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas return NULL; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1290945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rosestatic struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, 1300945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose struct device_node *dev_dn) 1310945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose{ 1320945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose struct pci_dev *tmp = NULL; 1330945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose struct device_node *child_dn; 1340945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose 1350945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose list_for_each_entry(tmp, &parent->devices, bus_list) { 1360945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose child_dn = pci_device_to_OF_node(tmp); 1370945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose if (child_dn == dev_dn) 1380945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose return tmp; 1390945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose } 1400945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose return NULL; 1410945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose} 1420945cd5f908a09ad99bf42d7ded16f26f24f317dJohn Rose 1438737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstasstatic void dlpar_pci_add_bus(struct device_node *dn) 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1458737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas struct pci_dn *pdn = PCI_DN(dn); 1465fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose struct pci_controller *phb = pdn->phb; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *dev = NULL; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 149d681db4aed4453c7d34adfbb64956271186514e9Linas Vepstas eeh_add_device_tree_early(dn); 150d681db4aed4453c7d34adfbb64956271186514e9Linas Vepstas 1515fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose /* Add EADS device to PHB bus, adding new entry to bus->devices */ 1525fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); 1535fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose if (!dev) { 1545fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose printk(KERN_ERR "%s: failed to create pci dev for %s\n", 15566bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__, dn->full_name); 1568737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas return; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 159fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt /* Scan below the new bridge */ 1605fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || 1615fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) 16298d9f30c820d509145757e6ecbc36013aa02f7bcBenjamin Herrenschmidt of_scan_pci_bridge(dev); 1635fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose 1643d5134ee8341bffc4f539049abb9e90d469b448dBenjamin Herrenschmidt /* Map IO space for child bus, which may or may not succeed */ 1653d5134ee8341bffc4f539049abb9e90d469b448dBenjamin Herrenschmidt pcibios_map_io_space(dev->subordinate); 1665fa80fcdca9d20d30c9ecec30d4dbff4ed93a5c6John Rose 167fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt /* Finish adding it : resource allocation, adding devices, etc... 168fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt * Note that we need to perform the finish pass on the -parent- 169fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt * bus of the EADS bridge so the bridge device itself gets 170fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt * properly added 171fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt */ 172fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt pcibios_finish_adding_to_bus(phb->bus); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 175940903c5a5a906c622a79b3101586deb1a1b3480John Rosestatic int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *dev; 1788737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas struct pci_controller *phb; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18001657868be1c21b2b8b0e683ea24bdcc2331d522Linas Vepstas if (pcibios_find_pci_bus(dn)) 18156d8456b06ad1316bff3c75caed5e06e786f20d8John Rose return -EINVAL; 18256d8456b06ad1316bff3c75caed5e06e786f20d8John Rose 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Add pci bus */ 1848737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas dlpar_pci_add_bus(dn); 1858737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas 1868737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas /* Confirm new bridge dev was created */ 1878737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas phb = PCI_DN(dn)->phb; 1888737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas dev = dlpar_find_new_dev(phb->bus, dn); 1898737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) { 19166bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison printk(KERN_ERR "%s: unable to add bus %s\n", __func__, 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drc_name); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1968737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { 1978737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n", 19866bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__, dev->hdr_type, drc_name); 1998737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas return -EIO; 2008737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas } 2018737d6a90cd8b085c2ea9cb4c7443c87f86c3429Linas Vepstas 2025eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose /* Add hotplug slot */ 2035eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose if (rpaphp_add_slot(dn)) { 2045eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose printk(KERN_ERR "%s: unable to add hotplug slot %s\n", 20566bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__, drc_name); 2065eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose return -EIO; 2075eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose } 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21156d8456b06ad1316bff3c75caed5e06e786f20d8John Rosestatic int dlpar_remove_phb(char *drc_name, struct device_node *dn) 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21356d8456b06ad1316bff3c75caed5e06e786f20d8John Rose struct slot *slot; 2141635317facea3094ddf34082cd86797efb1d9f7ePaul Mackerras struct pci_dn *pdn; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc = 0; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21701657868be1c21b2b8b0e683ea24bdcc2331d522Linas Vepstas if (!pcibios_find_pci_bus(dn)) 21856d8456b06ad1316bff3c75caed5e06e786f20d8John Rose return -EINVAL; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2208485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas /* If pci slot is hotplugable, use hotplug to remove it */ 2218485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas slot = find_php_slot(dn); 222fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt if (slot && rpaphp_deregister_slot(slot)) { 223fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", 224fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt __func__, drc_name); 225fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt return -EIO; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281635317facea3094ddf34082cd86797efb1d9f7ePaul Mackerras pdn = dn->data; 2291635317facea3094ddf34082cd86797efb1d9f7ePaul Mackerras BUG_ON(!pdn || !pdn->phb); 230fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt rc = remove_phb_dynamic(pdn->phb); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc < 0) 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341635317facea3094ddf34082cd86797efb1d9f7ePaul Mackerras pdn->phb = NULL; 23556d8456b06ad1316bff3c75caed5e06e786f20d8John Rose 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2395eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rosestatic int dlpar_add_phb(char *drc_name, struct device_node *dn) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_controller *phb; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 243fe98aeab8494cf431ef62e080cbe1dc1b6f5bd49Linas Vepstas if (PCI_DN(dn) && PCI_DN(dn)->phb) { 24456d8456b06ad1316bff3c75caed5e06e786f20d8John Rose /* PHB already exists */ 24556d8456b06ad1316bff3c75caed5e06e786f20d8John Rose return -EINVAL; 24656d8456b06ad1316bff3c75caed5e06e786f20d8John Rose } 24756d8456b06ad1316bff3c75caed5e06e786f20d8John Rose 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phb = init_phb_dynamic(dn); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!phb) 25056d8456b06ad1316bff3c75caed5e06e786f20d8John Rose return -EIO; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2525eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose if (rpaphp_add_slot(dn)) { 2535eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose printk(KERN_ERR "%s: unable to add hotplug slot %s\n", 25466bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__, drc_name); 2555eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose return -EIO; 2565eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose } 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26056d8456b06ad1316bff3c75caed5e06e786f20d8John Rosestatic int dlpar_add_vio_slot(char *drc_name, struct device_node *dn) 26156d8456b06ad1316bff3c75caed5e06e786f20d8John Rose{ 26256d8456b06ad1316bff3c75caed5e06e786f20d8John Rose if (vio_find_node(dn)) 26356d8456b06ad1316bff3c75caed5e06e786f20d8John Rose return -EINVAL; 26456d8456b06ad1316bff3c75caed5e06e786f20d8John Rose 26556d8456b06ad1316bff3c75caed5e06e786f20d8John Rose if (!vio_register_device_node(dn)) { 26656d8456b06ad1316bff3c75caed5e06e786f20d8John Rose printk(KERN_ERR 26756d8456b06ad1316bff3c75caed5e06e786f20d8John Rose "%s: failed to register vio node %s\n", 26866bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__, drc_name); 26956d8456b06ad1316bff3c75caed5e06e786f20d8John Rose return -EIO; 27056d8456b06ad1316bff3c75caed5e06e786f20d8John Rose } 27156d8456b06ad1316bff3c75caed5e06e786f20d8John Rose return 0; 27256d8456b06ad1316bff3c75caed5e06e786f20d8John Rose} 27356d8456b06ad1316bff3c75caed5e06e786f20d8John Rose 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dlpar_add_slot - DLPAR add an I/O Slot 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drc_name: drc-name of newly added slot 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27826e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Make the hotplug module and the kernel aware of a newly added I/O Slot. 27926e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Return Codes: 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 Success 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ENODEV Not a valid drc_name 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL Slot already added 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ERESTARTSYS Signalled before obtaining lock 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EIO Internal PCI Error 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dlpar_add_slot(char *drc_name) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device_node *dn = NULL; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int node_type; 29056d8456b06ad1316bff3c75caed5e06e786f20d8John Rose int rc = -EIO; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29214cc3e2b633bb64063698980974df4535368e98fIngo Molnar if (mutex_lock_interruptible(&rpadlpar_mutex)) 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ERESTARTSYS; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2955eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose /* Find newly added node */ 2965eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose dn = find_dlpar_node(drc_name, &node_type); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dn) { 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -ENODEV; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (node_type) { 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case NODE_TYPE_VIO: 30456d8456b06ad1316bff3c75caed5e06e786f20d8John Rose rc = dlpar_add_vio_slot(drc_name, dn); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case NODE_TYPE_SLOT: 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = dlpar_add_pci_slot(drc_name, dn); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case NODE_TYPE_PHB: 3105eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose rc = dlpar_add_phb(drc_name, dn); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31456d8456b06ad1316bff3c75caed5e06e786f20d8John Rose printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 31614cc3e2b633bb64063698980974df4535368e98fIngo Molnar mutex_unlock(&rpadlpar_mutex); 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dlpar_remove_vio_slot - DLPAR remove a virtual I/O Slot 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drc_name: drc-name of newly added slot 32326e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @dn: &device_node 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 32526e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Remove the kernel and hotplug representations of an I/O Slot. 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return Codes: 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 Success 32856d8456b06ad1316bff3c75caed5e06e786f20d8John Rose * -EINVAL Vio dev doesn't exist 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 33056d8456b06ad1316bff3c75caed5e06e786f20d8John Rosestatic int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn) 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3325eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose struct vio_dev *vio_dev; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3345eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose vio_dev = vio_find_node(dn); 33556d8456b06ad1316bff3c75caed5e06e786f20d8John Rose if (!vio_dev) 33656d8456b06ad1316bff3c75caed5e06e786f20d8John Rose return -EINVAL; 3375eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose 3385eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose vio_unregister_device(vio_dev); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 34326e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * dlpar_remove_pci_slot - DLPAR remove a PCI I/O Slot 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drc_name: drc-name of newly added slot 34526e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @dn: &device_node 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 34726e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Remove the kernel and hotplug representations of a PCI I/O Slot. 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return Codes: 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 Success 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ENODEV Not a valid drc_name 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EIO Internal PCI Error 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 35356d8456b06ad1316bff3c75caed5e06e786f20d8John Roseint dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 35556d8456b06ad1316bff3c75caed5e06e786f20d8John Rose struct pci_bus *bus; 35656d8456b06ad1316bff3c75caed5e06e786f20d8John Rose struct slot *slot; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35801657868be1c21b2b8b0e683ea24bdcc2331d522Linas Vepstas bus = pcibios_find_pci_bus(dn); 35956d8456b06ad1316bff3c75caed5e06e786f20d8John Rose if (!bus) 36056d8456b06ad1316bff3c75caed5e06e786f20d8John Rose return -EINVAL; 36156d8456b06ad1316bff3c75caed5e06e786f20d8John Rose 362fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt pr_debug("PCI: Removing PCI slot below EADS bridge %s\n", 363fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt bus->self ? pci_name(bus->self) : "<!PHB!>"); 364fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt 3658485d1a123e0d367bbcbfec36acf134e6895f39aLinas Vepstas slot = find_php_slot(dn); 36656d8456b06ad1316bff3c75caed5e06e786f20d8John Rose if (slot) { 367fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt pr_debug("PCI: Removing hotplug slot for %04x:%02x...\n", 368fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt pci_domain_nr(bus), bus->number); 369fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt 370f6afbad82c6b7bab0198442592b110341fb419baLinas Vepstas if (rpaphp_deregister_slot(slot)) { 37156d8456b06ad1316bff3c75caed5e06e786f20d8John Rose printk(KERN_ERR 37256d8456b06ad1316bff3c75caed5e06e786f20d8John Rose "%s: unable to remove hotplug slot %s\n", 37366bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__, drc_name); 37456d8456b06ad1316bff3c75caed5e06e786f20d8John Rose return -EIO; 37556d8456b06ad1316bff3c75caed5e06e786f20d8John Rose } 376fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt } 377fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt 378fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt /* Remove all devices below slot */ 379fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt pcibios_remove_pci_devices(bus); 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt /* Unmap PCI IO space */ 3823d5134ee8341bffc4f539049abb9e90d469b448dBenjamin Herrenschmidt if (pcibios_unmap_io_space(bus)) { 3839c209c919df95f83aa042b3352c43841ad15a02bJohn Rose printk(KERN_ERR "%s: failed to unmap bus range\n", 38466bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__); 3859c209c919df95f83aa042b3352c43841ad15a02bJohn Rose return -ERANGE; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3879c209c919df95f83aa042b3352c43841ad15a02bJohn Rose 388fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt /* Remove the EADS bridge device itself */ 3899c209c919df95f83aa042b3352c43841ad15a02bJohn Rose BUG_ON(!bus->self); 390fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self)); 391fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt eeh_remove_bus_device(bus->self); 392210647af897af8ef2d00828aa2a6b1b42206aae6Yinghai Lu pci_stop_and_remove_bus_device(bus->self); 393fd6852c8fa060bd45c82a2593e18f933f6c6204fBenjamin Herrenschmidt 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dlpar_remove_slot - DLPAR remove an I/O Slot 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drc_name: drc-name of newly added slot 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 40126e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * Remove the kernel and hotplug representations of an I/O Slot. 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return Codes: 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 Success 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ENODEV Not a valid drc_name 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL Slot already removed 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ERESTARTSYS Signalled before obtaining lock 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EIO Internal Error 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dlpar_remove_slot(char *drc_name) 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4115eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose struct device_node *dn; 4125eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose int node_type; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc = 0; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41514cc3e2b633bb64063698980974df4535368e98fIngo Molnar if (mutex_lock_interruptible(&rpadlpar_mutex)) 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ERESTARTSYS; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4185eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose dn = find_dlpar_node(drc_name, &node_type); 4195eeb8c63a38ff20285f3bbe7bcfe5e7c33c8ba14John Rose if (!dn) { 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -ENODEV; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42456d8456b06ad1316bff3c75caed5e06e786f20d8John Rose switch (node_type) { 42556d8456b06ad1316bff3c75caed5e06e786f20d8John Rose case NODE_TYPE_VIO: 42656d8456b06ad1316bff3c75caed5e06e786f20d8John Rose rc = dlpar_remove_vio_slot(drc_name, dn); 42756d8456b06ad1316bff3c75caed5e06e786f20d8John Rose break; 42856d8456b06ad1316bff3c75caed5e06e786f20d8John Rose case NODE_TYPE_PHB: 42956d8456b06ad1316bff3c75caed5e06e786f20d8John Rose rc = dlpar_remove_phb(drc_name, dn); 43056d8456b06ad1316bff3c75caed5e06e786f20d8John Rose break; 43156d8456b06ad1316bff3c75caed5e06e786f20d8John Rose case NODE_TYPE_SLOT: 43256d8456b06ad1316bff3c75caed5e06e786f20d8John Rose rc = dlpar_remove_pci_slot(drc_name, dn); 43356d8456b06ad1316bff3c75caed5e06e786f20d8John Rose break; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 435b4a26be9f6f8bb72998e445cc75fc6dc0c29513aBenjamin Herrenschmidt vm_unmap_aliases(); 436b4a26be9f6f8bb72998e445cc75fc6dc0c29513aBenjamin Herrenschmidt 43756d8456b06ad1316bff3c75caed5e06e786f20d8John Rose printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 43914cc3e2b633bb64063698980974df4535368e98fIngo Molnar mutex_unlock(&rpadlpar_mutex); 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int is_dlpar_capable(void) 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc = rtas_token("ibm,configure-connector"); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (int) (rc != RTAS_UNKNOWN_SERVICE); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init rpadlpar_io_init(void) 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc = 0; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!is_dlpar_capable()) { 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "%s: partition not DLPAR capable\n", 45666bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = dlpar_sysfs_init(); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid rpadlpar_io_exit(void) 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dlpar_sysfs_exit(); 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(rpadlpar_io_init); 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(rpadlpar_io_exit); 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 473