Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Interface for Dynamic Logical Partitioning of I/O Slots on
0004  * RPA-compliant PPC64 platform.
0005  *
0006  * John Rose <johnrose@austin.ibm.com>
0007  * Linda Xie <lxie@us.ibm.com>
0008  *
0009  * October 2003
0010  *
0011  * Copyright (C) 2003 IBM.
0012  */
0013 
0014 #undef DEBUG
0015 
0016 #include <linux/init.h>
0017 #include <linux/module.h>
0018 #include <linux/of.h>
0019 #include <linux/pci.h>
0020 #include <linux/string.h>
0021 #include <linux/vmalloc.h>
0022 
0023 #include <asm/pci-bridge.h>
0024 #include <linux/mutex.h>
0025 #include <asm/rtas.h>
0026 #include <asm/vio.h>
0027 #include <linux/firmware.h>
0028 
0029 #include "../pci.h"
0030 #include "rpaphp.h"
0031 #include "rpadlpar.h"
0032 
0033 static DEFINE_MUTEX(rpadlpar_mutex);
0034 
0035 #define DLPAR_MODULE_NAME "rpadlpar_io"
0036 
0037 #define NODE_TYPE_VIO  1
0038 #define NODE_TYPE_SLOT 2
0039 #define NODE_TYPE_PHB  3
0040 
0041 static struct device_node *find_vio_slot_node(char *drc_name)
0042 {
0043     struct device_node *parent = of_find_node_by_name(NULL, "vdevice");
0044     struct device_node *dn;
0045     int rc;
0046 
0047     if (!parent)
0048         return NULL;
0049 
0050     for_each_child_of_node(parent, dn) {
0051         rc = rpaphp_check_drc_props(dn, drc_name, NULL);
0052         if (rc == 0)
0053             break;
0054     }
0055     of_node_put(parent);
0056 
0057     return dn;
0058 }
0059 
0060 /* Find dlpar-capable pci node that contains the specified name and type */
0061 static struct device_node *find_php_slot_pci_node(char *drc_name,
0062                           char *drc_type)
0063 {
0064     struct device_node *np;
0065     int rc;
0066 
0067     for_each_node_by_name(np, "pci") {
0068         rc = rpaphp_check_drc_props(np, drc_name, drc_type);
0069         if (rc == 0)
0070             break;
0071     }
0072 
0073     return np;
0074 }
0075 
0076 /* Returns a device_node with its reference count incremented */
0077 static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
0078 {
0079     struct device_node *dn;
0080 
0081     dn = find_php_slot_pci_node(drc_name, "SLOT");
0082     if (dn) {
0083         *node_type = NODE_TYPE_SLOT;
0084         return dn;
0085     }
0086 
0087     dn = find_php_slot_pci_node(drc_name, "PHB");
0088     if (dn) {
0089         *node_type = NODE_TYPE_PHB;
0090         return dn;
0091     }
0092 
0093     dn = find_vio_slot_node(drc_name);
0094     if (dn) {
0095         *node_type = NODE_TYPE_VIO;
0096         return dn;
0097     }
0098 
0099     return NULL;
0100 }
0101 
0102 /**
0103  * find_php_slot - return hotplug slot structure for device node
0104  * @dn: target &device_node
0105  *
0106  * This routine will return the hotplug slot structure
0107  * for a given device node. Note that built-in PCI slots
0108  * may be dlpar-able, but not hot-pluggable, so this routine
0109  * will return NULL for built-in PCI slots.
0110  */
0111 static struct slot *find_php_slot(struct device_node *dn)
0112 {
0113     struct slot *slot, *next;
0114 
0115     list_for_each_entry_safe(slot, next, &rpaphp_slot_head,
0116                  rpaphp_slot_list) {
0117         if (slot->dn == dn)
0118             return slot;
0119     }
0120 
0121     return NULL;
0122 }
0123 
0124 static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
0125                     struct device_node *dev_dn)
0126 {
0127     struct pci_dev *tmp = NULL;
0128     struct device_node *child_dn;
0129 
0130     list_for_each_entry(tmp, &parent->devices, bus_list) {
0131         child_dn = pci_device_to_OF_node(tmp);
0132         if (child_dn == dev_dn)
0133             return tmp;
0134     }
0135     return NULL;
0136 }
0137 
0138 static void dlpar_pci_add_bus(struct device_node *dn)
0139 {
0140     struct pci_dn *pdn = PCI_DN(dn);
0141     struct pci_controller *phb = pdn->phb;
0142     struct pci_dev *dev = NULL;
0143 
0144     pseries_eeh_init_edev_recursive(pdn);
0145 
0146     /* Add EADS device to PHB bus, adding new entry to bus->devices */
0147     dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);
0148     if (!dev) {
0149         printk(KERN_ERR "%s: failed to create pci dev for %pOF\n",
0150                 __func__, dn);
0151         return;
0152     }
0153 
0154     /* Scan below the new bridge */
0155     if (pci_is_bridge(dev))
0156         of_scan_pci_bridge(dev);
0157 
0158     /* Map IO space for child bus, which may or may not succeed */
0159     pcibios_map_io_space(dev->subordinate);
0160 
0161     /* Finish adding it : resource allocation, adding devices, etc...
0162      * Note that we need to perform the finish pass on the -parent-
0163      * bus of the EADS bridge so the bridge device itself gets
0164      * properly added
0165      */
0166     pcibios_finish_adding_to_bus(phb->bus);
0167 }
0168 
0169 static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
0170 {
0171     struct pci_dev *dev;
0172     struct pci_controller *phb;
0173 
0174     if (pci_find_bus_by_node(dn))
0175         return -EINVAL;
0176 
0177     /* Add pci bus */
0178     dlpar_pci_add_bus(dn);
0179 
0180     /* Confirm new bridge dev was created */
0181     phb = PCI_DN(dn)->phb;
0182     dev = dlpar_find_new_dev(phb->bus, dn);
0183 
0184     if (!dev) {
0185         printk(KERN_ERR "%s: unable to add bus %s\n", __func__,
0186             drc_name);
0187         return -EIO;
0188     }
0189 
0190     if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
0191         printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n",
0192             __func__, dev->hdr_type, drc_name);
0193         return -EIO;
0194     }
0195 
0196     /* Add hotplug slot */
0197     if (rpaphp_add_slot(dn)) {
0198         printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
0199             __func__, drc_name);
0200         return -EIO;
0201     }
0202     return 0;
0203 }
0204 
0205 static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
0206 {
0207     struct slot *slot;
0208     struct pci_dn *pdn;
0209     int rc = 0;
0210 
0211     if (!pci_find_bus_by_node(dn))
0212         return -EINVAL;
0213 
0214     /* If pci slot is hotpluggable, use hotplug to remove it */
0215     slot = find_php_slot(dn);
0216     if (slot && rpaphp_deregister_slot(slot)) {
0217         printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
0218                __func__, drc_name);
0219         return -EIO;
0220     }
0221 
0222     pdn = dn->data;
0223     BUG_ON(!pdn || !pdn->phb);
0224     rc = remove_phb_dynamic(pdn->phb);
0225     if (rc < 0)
0226         return rc;
0227 
0228     pdn->phb = NULL;
0229 
0230     return 0;
0231 }
0232 
0233 static int dlpar_add_phb(char *drc_name, struct device_node *dn)
0234 {
0235     struct pci_controller *phb;
0236 
0237     if (PCI_DN(dn) && PCI_DN(dn)->phb) {
0238         /* PHB already exists */
0239         return -EINVAL;
0240     }
0241 
0242     phb = init_phb_dynamic(dn);
0243     if (!phb)
0244         return -EIO;
0245 
0246     if (rpaphp_add_slot(dn)) {
0247         printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
0248             __func__, drc_name);
0249         return -EIO;
0250     }
0251     return 0;
0252 }
0253 
0254 static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
0255 {
0256     struct vio_dev *vio_dev;
0257 
0258     vio_dev = vio_find_node(dn);
0259     if (vio_dev) {
0260         put_device(&vio_dev->dev);
0261         return -EINVAL;
0262     }
0263 
0264     if (!vio_register_device_node(dn)) {
0265         printk(KERN_ERR
0266             "%s: failed to register vio node %s\n",
0267             __func__, drc_name);
0268         return -EIO;
0269     }
0270     return 0;
0271 }
0272 
0273 /**
0274  * dlpar_add_slot - DLPAR add an I/O Slot
0275  * @drc_name: drc-name of newly added slot
0276  *
0277  * Make the hotplug module and the kernel aware of a newly added I/O Slot.
0278  * Return Codes:
0279  * 0            Success
0280  * -ENODEV      Not a valid drc_name
0281  * -EINVAL      Slot already added
0282  * -ERESTARTSYS     Signalled before obtaining lock
0283  * -EIO         Internal PCI Error
0284  */
0285 int dlpar_add_slot(char *drc_name)
0286 {
0287     struct device_node *dn = NULL;
0288     int node_type;
0289     int rc = -EIO;
0290 
0291     if (mutex_lock_interruptible(&rpadlpar_mutex))
0292         return -ERESTARTSYS;
0293 
0294     /* Find newly added node */
0295     dn = find_dlpar_node(drc_name, &node_type);
0296     if (!dn) {
0297         rc = -ENODEV;
0298         goto exit;
0299     }
0300 
0301     switch (node_type) {
0302         case NODE_TYPE_VIO:
0303             rc = dlpar_add_vio_slot(drc_name, dn);
0304             break;
0305         case NODE_TYPE_SLOT:
0306             rc = dlpar_add_pci_slot(drc_name, dn);
0307             break;
0308         case NODE_TYPE_PHB:
0309             rc = dlpar_add_phb(drc_name, dn);
0310             break;
0311     }
0312     of_node_put(dn);
0313 
0314     printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name);
0315 exit:
0316     mutex_unlock(&rpadlpar_mutex);
0317     return rc;
0318 }
0319 
0320 /**
0321  * dlpar_remove_vio_slot - DLPAR remove a virtual I/O Slot
0322  * @drc_name: drc-name of newly added slot
0323  * @dn: &device_node
0324  *
0325  * Remove the kernel and hotplug representations of an I/O Slot.
0326  * Return Codes:
0327  * 0            Success
0328  * -EINVAL      Vio dev doesn't exist
0329  */
0330 static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn)
0331 {
0332     struct vio_dev *vio_dev;
0333 
0334     vio_dev = vio_find_node(dn);
0335     if (!vio_dev)
0336         return -EINVAL;
0337 
0338     vio_unregister_device(vio_dev);
0339 
0340     put_device(&vio_dev->dev);
0341 
0342     return 0;
0343 }
0344 
0345 /**
0346  * dlpar_remove_pci_slot - DLPAR remove a PCI I/O Slot
0347  * @drc_name: drc-name of newly added slot
0348  * @dn: &device_node
0349  *
0350  * Remove the kernel and hotplug representations of a PCI I/O Slot.
0351  * Return Codes:
0352  * 0            Success
0353  * -ENODEV      Not a valid drc_name
0354  * -EIO         Internal PCI Error
0355  */
0356 static int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
0357 {
0358     struct pci_bus *bus;
0359     struct slot *slot;
0360     int ret = 0;
0361 
0362     pci_lock_rescan_remove();
0363 
0364     bus = pci_find_bus_by_node(dn);
0365     if (!bus) {
0366         ret = -EINVAL;
0367         goto out;
0368     }
0369 
0370     pr_debug("PCI: Removing PCI slot below EADS bridge %s\n",
0371          bus->self ? pci_name(bus->self) : "<!PHB!>");
0372 
0373     slot = find_php_slot(dn);
0374     if (slot) {
0375         pr_debug("PCI: Removing hotplug slot for %04x:%02x...\n",
0376              pci_domain_nr(bus), bus->number);
0377 
0378         if (rpaphp_deregister_slot(slot)) {
0379             printk(KERN_ERR
0380                 "%s: unable to remove hotplug slot %s\n",
0381                 __func__, drc_name);
0382             ret = -EIO;
0383             goto out;
0384         }
0385     }
0386 
0387     /* Remove all devices below slot */
0388     pci_hp_remove_devices(bus);
0389 
0390     /* Unmap PCI IO space */
0391     if (pcibios_unmap_io_space(bus)) {
0392         printk(KERN_ERR "%s: failed to unmap bus range\n",
0393             __func__);
0394         ret = -ERANGE;
0395         goto out;
0396     }
0397 
0398     /* Remove the EADS bridge device itself */
0399     BUG_ON(!bus->self);
0400     pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self));
0401     pci_stop_and_remove_bus_device(bus->self);
0402 
0403  out:
0404     pci_unlock_rescan_remove();
0405     return ret;
0406 }
0407 
0408 /**
0409  * dlpar_remove_slot - DLPAR remove an I/O Slot
0410  * @drc_name: drc-name of newly added slot
0411  *
0412  * Remove the kernel and hotplug representations of an I/O Slot.
0413  * Return Codes:
0414  * 0            Success
0415  * -ENODEV      Not a valid drc_name
0416  * -EINVAL      Slot already removed
0417  * -ERESTARTSYS     Signalled before obtaining lock
0418  * -EIO         Internal Error
0419  */
0420 int dlpar_remove_slot(char *drc_name)
0421 {
0422     struct device_node *dn;
0423     int node_type;
0424     int rc = 0;
0425 
0426     if (mutex_lock_interruptible(&rpadlpar_mutex))
0427         return -ERESTARTSYS;
0428 
0429     dn = find_dlpar_node(drc_name, &node_type);
0430     if (!dn) {
0431         rc = -ENODEV;
0432         goto exit;
0433     }
0434 
0435     switch (node_type) {
0436         case NODE_TYPE_VIO:
0437             rc = dlpar_remove_vio_slot(drc_name, dn);
0438             break;
0439         case NODE_TYPE_PHB:
0440             rc = dlpar_remove_phb(drc_name, dn);
0441             break;
0442         case NODE_TYPE_SLOT:
0443             rc = dlpar_remove_pci_slot(drc_name, dn);
0444             break;
0445     }
0446     of_node_put(dn);
0447     vm_unmap_aliases();
0448 
0449     printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name);
0450 exit:
0451     mutex_unlock(&rpadlpar_mutex);
0452     return rc;
0453 }
0454 
0455 static inline int is_dlpar_capable(void)
0456 {
0457     int rc = rtas_token("ibm,configure-connector");
0458 
0459     return (int) (rc != RTAS_UNKNOWN_SERVICE);
0460 }
0461 
0462 static int __init rpadlpar_io_init(void)
0463 {
0464 
0465     if (!is_dlpar_capable()) {
0466         printk(KERN_WARNING "%s: partition not DLPAR capable\n",
0467             __func__);
0468         return -EPERM;
0469     }
0470 
0471     return dlpar_sysfs_init();
0472 }
0473 
0474 static void __exit rpadlpar_io_exit(void)
0475 {
0476     dlpar_sysfs_exit();
0477 }
0478 
0479 module_init(rpadlpar_io_init);
0480 module_exit(rpadlpar_io_exit);
0481 MODULE_LICENSE("GPL");
0482 MODULE_DESCRIPTION("RPA Dynamic Logical Partitioning driver for I/O slots");