cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pci-hotplug.c (4220B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Derived from "arch/powerpc/platforms/pseries/pci_dlpar.c"
      4 *
      5 * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com>
      6 * Copyright (C) 2005 International Business Machines
      7 *
      8 * Updates, 2005, John Rose <johnrose@austin.ibm.com>
      9 * Updates, 2005, Linas Vepstas <linas@austin.ibm.com>
     10 * Updates, 2013, Gavin Shan <shangw@linux.vnet.ibm.com>
     11 */
     12
     13#include <linux/pci.h>
     14#include <linux/export.h>
     15#include <linux/of.h>
     16#include <asm/pci-bridge.h>
     17#include <asm/ppc-pci.h>
     18#include <asm/firmware.h>
     19#include <asm/eeh.h>
     20
     21static struct pci_bus *find_bus_among_children(struct pci_bus *bus,
     22					       struct device_node *dn)
     23{
     24	struct pci_bus *child = NULL;
     25	struct pci_bus *tmp;
     26
     27	if (pci_bus_to_OF_node(bus) == dn)
     28		return bus;
     29
     30	list_for_each_entry(tmp, &bus->children, node) {
     31		child = find_bus_among_children(tmp, dn);
     32		if (child)
     33			break;
     34	}
     35
     36	return child;
     37}
     38
     39struct pci_bus *pci_find_bus_by_node(struct device_node *dn)
     40{
     41	struct pci_dn *pdn = PCI_DN(dn);
     42
     43	if (!pdn  || !pdn->phb || !pdn->phb->bus)
     44		return NULL;
     45
     46	return find_bus_among_children(pdn->phb->bus, dn);
     47}
     48EXPORT_SYMBOL_GPL(pci_find_bus_by_node);
     49
     50/**
     51 * pcibios_release_device - release PCI device
     52 * @dev: PCI device
     53 *
     54 * The function is called before releasing the indicated PCI device.
     55 */
     56void pcibios_release_device(struct pci_dev *dev)
     57{
     58	struct pci_controller *phb = pci_bus_to_host(dev->bus);
     59	struct pci_dn *pdn = pci_get_pdn(dev);
     60
     61	if (phb->controller_ops.release_device)
     62		phb->controller_ops.release_device(dev);
     63
     64	/* free()ing the pci_dn has been deferred to us, do it now */
     65	if (pdn && (pdn->flags & PCI_DN_FLAG_DEAD)) {
     66		pci_dbg(dev, "freeing dead pdn\n");
     67		kfree(pdn);
     68	}
     69}
     70
     71/**
     72 * pci_hp_remove_devices - remove all devices under this bus
     73 * @bus: the indicated PCI bus
     74 *
     75 * Remove all of the PCI devices under this bus both from the
     76 * linux pci device tree, and from the powerpc EEH address cache.
     77 */
     78void pci_hp_remove_devices(struct pci_bus *bus)
     79{
     80	struct pci_dev *dev, *tmp;
     81	struct pci_bus *child_bus;
     82
     83	/* First go down child busses */
     84	list_for_each_entry(child_bus, &bus->children, node)
     85		pci_hp_remove_devices(child_bus);
     86
     87	pr_debug("PCI: Removing devices on bus %04x:%02x\n",
     88		 pci_domain_nr(bus),  bus->number);
     89	list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {
     90		pr_debug("   Removing %s...\n", pci_name(dev));
     91		pci_stop_and_remove_bus_device(dev);
     92	}
     93}
     94EXPORT_SYMBOL_GPL(pci_hp_remove_devices);
     95
     96/**
     97 * pci_hp_add_devices - adds new pci devices to bus
     98 * @bus: the indicated PCI bus
     99 *
    100 * This routine will find and fixup new pci devices under
    101 * the indicated bus. This routine presumes that there
    102 * might already be some devices under this bridge, so
    103 * it carefully tries to add only new devices.  (And that
    104 * is how this routine differs from other, similar pcibios
    105 * routines.)
    106 */
    107void pci_hp_add_devices(struct pci_bus *bus)
    108{
    109	int slotno, mode, max;
    110	struct pci_dev *dev;
    111	struct pci_controller *phb;
    112	struct device_node *dn = pci_bus_to_OF_node(bus);
    113
    114	phb = pci_bus_to_host(bus);
    115
    116	mode = PCI_PROBE_NORMAL;
    117	if (phb->controller_ops.probe_mode)
    118		mode = phb->controller_ops.probe_mode(bus);
    119
    120	if (mode == PCI_PROBE_DEVTREE) {
    121		/* use ofdt-based probe */
    122		of_rescan_bus(dn, bus);
    123	} else if (mode == PCI_PROBE_NORMAL &&
    124		   dn->child && PCI_DN(dn->child)) {
    125		/*
    126		 * Use legacy probe. In the partial hotplug case, we
    127		 * probably have grandchildren devices unplugged. So
    128		 * we don't check the return value from pci_scan_slot() in
    129		 * order for fully rescan all the way down to pick them up.
    130		 * They can have been removed during partial hotplug.
    131		 */
    132		slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
    133		pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
    134		max = bus->busn_res.start;
    135		/*
    136		 * Scan bridges that are already configured. We don't touch
    137		 * them unless they are misconfigured (which will be done in
    138		 * the second scan below).
    139		 */
    140		for_each_pci_bridge(dev, bus)
    141			max = pci_scan_bridge(bus, dev, max, 0);
    142
    143		/* Scan bridges that need to be reconfigured */
    144		for_each_pci_bridge(dev, bus)
    145			max = pci_scan_bridge(bus, dev, max, 1);
    146	}
    147	pcibios_finish_adding_to_bus(bus);
    148}
    149EXPORT_SYMBOL_GPL(pci_hp_add_devices);