1 /* 2 * Interface for Dynamic Logical Partitioning of I/O Slots on 3 * RPA-compliant PPC64 platform. 4 * 5 * John Rose <johnrose@austin.ibm.com> 6 * Linda Xie <lxie@us.ibm.com> 7 * 8 * October 2003 9 * 10 * Copyright (C) 2003 IBM. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 15 * 2 of the License, or (at your option) any later version. 16 */ 17 #include <linux/init.h> 18 #include <linux/pci.h> 19 #include <linux/string.h> 20 21 #include <asm/pci-bridge.h> 22 #include <linux/mutex.h> 23 #include <asm/rtas.h> 24 #include <asm/vio.h> 25 26 #include "../pci.h" 27 #include "rpaphp.h" 28 #include "rpadlpar.h" 29 30 static DEFINE_MUTEX(rpadlpar_mutex); 31 32 #define DLPAR_MODULE_NAME "rpadlpar_io" 33 34 #define NODE_TYPE_VIO 1 35 #define NODE_TYPE_SLOT 2 36 #define NODE_TYPE_PHB 3 37 38 static struct device_node *find_vio_slot_node(char *drc_name) 39 { 40 struct device_node *parent = of_find_node_by_name(NULL, "vdevice"); 41 struct device_node *dn = NULL; 42 char *name; 43 int rc; 44 45 if (!parent) 46 return NULL; 47 48 while ((dn = of_get_next_child(parent, dn))) { 49 rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL); 50 if ((rc == 0) && (!strcmp(drc_name, name))) 51 break; 52 } 53 54 return dn; 55 } 56 57 /* Find dlpar-capable pci node that contains the specified name and type */ 58 static struct device_node *find_php_slot_pci_node(char *drc_name, 59 char *drc_type) 60 { 61 struct device_node *np = NULL; 62 char *name; 63 char *type; 64 int rc; 65 66 while ((np = of_find_node_by_name(np, "pci"))) { 67 rc = rpaphp_get_drc_props(np, NULL, &name, &type, NULL); 68 if (rc == 0) 69 if (!strcmp(drc_name, name) && !strcmp(drc_type, type)) 70 break; 71 } 72 73 return np; 74 } 75 76 static struct device_node *find_dlpar_node(char *drc_name, int *node_type) 77 { 78 struct device_node *dn; 79 80 dn = find_php_slot_pci_node(drc_name, "SLOT"); 81 if (dn) { 82 *node_type = NODE_TYPE_SLOT; 83 return dn; 84 } 85 86 dn = find_php_slot_pci_node(drc_name, "PHB"); 87 if (dn) { 88 *node_type = NODE_TYPE_PHB; 89 return dn; 90 } 91 92 dn = find_vio_slot_node(drc_name); 93 if (dn) { 94 *node_type = NODE_TYPE_VIO; 95 return dn; 96 } 97 98 return NULL; 99 } 100 101 /** 102 * find_php_slot - return hotplug slot structure for device node 103 * @dn: target &device_node 104 * 105 * This routine will return the hotplug slot structure 106 * for a given device node. Note that built-in PCI slots 107 * may be dlpar-able, but not hot-pluggable, so this routine 108 * will return NULL for built-in PCI slots. 109 */ 110 static struct slot *find_php_slot(struct device_node *dn) 111 { 112 struct list_head *tmp, *n; 113 struct slot *slot; 114 115 list_for_each_safe(tmp, n, &rpaphp_slot_head) { 116 slot = list_entry(tmp, struct slot, rpaphp_slot_list); 117 if (slot->dn == dn) 118 return slot; 119 } 120 121 return NULL; 122 } 123 124 static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, 125 struct device_node *dev_dn) 126 { 127 struct pci_dev *tmp = NULL; 128 struct device_node *child_dn; 129 130 list_for_each_entry(tmp, &parent->devices, bus_list) { 131 child_dn = pci_device_to_OF_node(tmp); 132 if (child_dn == dev_dn) 133 return tmp; 134 } 135 return NULL; 136 } 137 138 static void dlpar_pci_add_bus(struct device_node *dn) 139 { 140 struct pci_dn *pdn = PCI_DN(dn); 141 struct pci_controller *phb = pdn->phb; 142 struct pci_dev *dev = NULL; 143 144 eeh_add_device_tree_early(dn); 145 146 /* Add EADS device to PHB bus, adding new entry to bus->devices */ 147 dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); 148 if (!dev) { 149 printk(KERN_ERR "%s: failed to create pci dev for %s\n", 150 __func__, dn->full_name); 151 return; 152 } 153 154 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || 155 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) 156 of_scan_pci_bridge(dn, dev); 157 158 pcibios_fixup_new_pci_devices(dev->subordinate); 159 160 /* Claim new bus resources */ 161 pcibios_claim_one_bus(dev->bus); 162 163 /* Map IO space for child bus, which may or may not succeed */ 164 pcibios_map_io_space(dev->subordinate); 165 166 /* Add new devices to global lists. Register in proc, sysfs. */ 167 pci_bus_add_devices(phb->bus); 168 } 169 170 static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) 171 { 172 struct pci_dev *dev; 173 struct pci_controller *phb; 174 175 if (pcibios_find_pci_bus(dn)) 176 return -EINVAL; 177 178 /* Add pci bus */ 179 dlpar_pci_add_bus(dn); 180 181 /* Confirm new bridge dev was created */ 182 phb = PCI_DN(dn)->phb; 183 dev = dlpar_find_new_dev(phb->bus, dn); 184 185 if (!dev) { 186 printk(KERN_ERR "%s: unable to add bus %s\n", __func__, 187 drc_name); 188 return -EIO; 189 } 190 191 if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { 192 printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n", 193 __func__, dev->hdr_type, drc_name); 194 return -EIO; 195 } 196 197 /* Add hotplug slot */ 198 if (rpaphp_add_slot(dn)) { 199 printk(KERN_ERR "%s: unable to add hotplug slot %s\n", 200 __func__, drc_name); 201 return -EIO; 202 } 203 return 0; 204 } 205 206 static int dlpar_remove_root_bus(struct pci_controller *phb) 207 { 208 struct pci_bus *phb_bus; 209 int rc; 210 211 phb_bus = phb->bus; 212 if (!(list_empty(&phb_bus->children) && 213 list_empty(&phb_bus->devices))) { 214 return -EBUSY; 215 } 216 217 rc = pcibios_remove_root_bus(phb); 218 if (rc) 219 return -EIO; 220 221 device_unregister(phb_bus->bridge); 222 pci_remove_bus(phb_bus); 223 224 return 0; 225 } 226 227 static int dlpar_remove_phb(char *drc_name, struct device_node *dn) 228 { 229 struct slot *slot; 230 struct pci_dn *pdn; 231 int rc = 0; 232 233 if (!pcibios_find_pci_bus(dn)) 234 return -EINVAL; 235 236 /* If pci slot is hotplugable, use hotplug to remove it */ 237 slot = find_php_slot(dn); 238 if (slot) { 239 if (rpaphp_deregister_slot(slot)) { 240 printk(KERN_ERR 241 "%s: unable to remove hotplug slot %s\n", 242 __func__, drc_name); 243 return -EIO; 244 } 245 } 246 247 pdn = dn->data; 248 BUG_ON(!pdn || !pdn->phb); 249 rc = dlpar_remove_root_bus(pdn->phb); 250 if (rc < 0) 251 return rc; 252 253 pdn->phb = NULL; 254 255 return 0; 256 } 257 258 static int dlpar_add_phb(char *drc_name, struct device_node *dn) 259 { 260 struct pci_controller *phb; 261 262 if (PCI_DN(dn) && PCI_DN(dn)->phb) { 263 /* PHB already exists */ 264 return -EINVAL; 265 } 266 267 phb = init_phb_dynamic(dn); 268 if (!phb) 269 return -EIO; 270 271 if (rpaphp_add_slot(dn)) { 272 printk(KERN_ERR "%s: unable to add hotplug slot %s\n", 273 __func__, drc_name); 274 return -EIO; 275 } 276 return 0; 277 } 278 279 static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn) 280 { 281 if (vio_find_node(dn)) 282 return -EINVAL; 283 284 if (!vio_register_device_node(dn)) { 285 printk(KERN_ERR 286 "%s: failed to register vio node %s\n", 287 __func__, drc_name); 288 return -EIO; 289 } 290 return 0; 291 } 292 293 /** 294 * dlpar_add_slot - DLPAR add an I/O Slot 295 * @drc_name: drc-name of newly added slot 296 * 297 * Make the hotplug module and the kernel aware of a newly added I/O Slot. 298 * Return Codes: 299 * 0 Success 300 * -ENODEV Not a valid drc_name 301 * -EINVAL Slot already added 302 * -ERESTARTSYS Signalled before obtaining lock 303 * -EIO Internal PCI Error 304 */ 305 int dlpar_add_slot(char *drc_name) 306 { 307 struct device_node *dn = NULL; 308 int node_type; 309 int rc = -EIO; 310 311 if (mutex_lock_interruptible(&rpadlpar_mutex)) 312 return -ERESTARTSYS; 313 314 /* Find newly added node */ 315 dn = find_dlpar_node(drc_name, &node_type); 316 if (!dn) { 317 rc = -ENODEV; 318 goto exit; 319 } 320 321 switch (node_type) { 322 case NODE_TYPE_VIO: 323 rc = dlpar_add_vio_slot(drc_name, dn); 324 break; 325 case NODE_TYPE_SLOT: 326 rc = dlpar_add_pci_slot(drc_name, dn); 327 break; 328 case NODE_TYPE_PHB: 329 rc = dlpar_add_phb(drc_name, dn); 330 break; 331 } 332 333 printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name); 334 exit: 335 mutex_unlock(&rpadlpar_mutex); 336 return rc; 337 } 338 339 /** 340 * dlpar_remove_vio_slot - DLPAR remove a virtual I/O Slot 341 * @drc_name: drc-name of newly added slot 342 * @dn: &device_node 343 * 344 * Remove the kernel and hotplug representations of an I/O Slot. 345 * Return Codes: 346 * 0 Success 347 * -EINVAL Vio dev doesn't exist 348 */ 349 static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn) 350 { 351 struct vio_dev *vio_dev; 352 353 vio_dev = vio_find_node(dn); 354 if (!vio_dev) 355 return -EINVAL; 356 357 vio_unregister_device(vio_dev); 358 return 0; 359 } 360 361 /** 362 * dlpar_remove_pci_slot - DLPAR remove a PCI I/O Slot 363 * @drc_name: drc-name of newly added slot 364 * @dn: &device_node 365 * 366 * Remove the kernel and hotplug representations of a PCI I/O Slot. 367 * Return Codes: 368 * 0 Success 369 * -ENODEV Not a valid drc_name 370 * -EIO Internal PCI Error 371 */ 372 int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) 373 { 374 struct pci_bus *bus; 375 struct slot *slot; 376 377 bus = pcibios_find_pci_bus(dn); 378 if (!bus) 379 return -EINVAL; 380 381 /* If pci slot is hotplugable, use hotplug to remove it */ 382 slot = find_php_slot(dn); 383 if (slot) { 384 if (rpaphp_deregister_slot(slot)) { 385 printk(KERN_ERR 386 "%s: unable to remove hotplug slot %s\n", 387 __func__, drc_name); 388 return -EIO; 389 } 390 } else 391 pcibios_remove_pci_devices(bus); 392 393 if (pcibios_unmap_io_space(bus)) { 394 printk(KERN_ERR "%s: failed to unmap bus range\n", 395 __func__); 396 return -ERANGE; 397 } 398 399 BUG_ON(!bus->self); 400 pci_remove_bus_device(bus->self); 401 return 0; 402 } 403 404 /** 405 * dlpar_remove_slot - DLPAR remove an I/O Slot 406 * @drc_name: drc-name of newly added slot 407 * 408 * Remove the kernel and hotplug representations of an I/O Slot. 409 * Return Codes: 410 * 0 Success 411 * -ENODEV Not a valid drc_name 412 * -EINVAL Slot already removed 413 * -ERESTARTSYS Signalled before obtaining lock 414 * -EIO Internal Error 415 */ 416 int dlpar_remove_slot(char *drc_name) 417 { 418 struct device_node *dn; 419 int node_type; 420 int rc = 0; 421 422 if (mutex_lock_interruptible(&rpadlpar_mutex)) 423 return -ERESTARTSYS; 424 425 dn = find_dlpar_node(drc_name, &node_type); 426 if (!dn) { 427 rc = -ENODEV; 428 goto exit; 429 } 430 431 switch (node_type) { 432 case NODE_TYPE_VIO: 433 rc = dlpar_remove_vio_slot(drc_name, dn); 434 break; 435 case NODE_TYPE_PHB: 436 rc = dlpar_remove_phb(drc_name, dn); 437 break; 438 case NODE_TYPE_SLOT: 439 rc = dlpar_remove_pci_slot(drc_name, dn); 440 break; 441 } 442 printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name); 443 exit: 444 mutex_unlock(&rpadlpar_mutex); 445 return rc; 446 } 447 448 static inline int is_dlpar_capable(void) 449 { 450 int rc = rtas_token("ibm,configure-connector"); 451 452 return (int) (rc != RTAS_UNKNOWN_SERVICE); 453 } 454 455 int __init rpadlpar_io_init(void) 456 { 457 int rc = 0; 458 459 if (!is_dlpar_capable()) { 460 printk(KERN_WARNING "%s: partition not DLPAR capable\n", 461 __func__); 462 return -EPERM; 463 } 464 465 rc = dlpar_sysfs_init(); 466 return rc; 467 } 468 469 void rpadlpar_io_exit(void) 470 { 471 dlpar_sysfs_exit(); 472 return; 473 } 474 475 module_init(rpadlpar_io_init); 476 module_exit(rpadlpar_io_exit); 477 MODULE_LICENSE("GPL"); 478