static void ixdp2400_pci_postinit(void) { struct pci_dev *dev; if (ixdp2x00_master_npu()) { dev = pci_find_slot(1, IXDP2400_SLAVE_ENET_DEVFN); pci_remove_bus_device(dev); } else { dev = pci_find_slot(1, IXDP2400_MASTER_ENET_DEVFN); pci_remove_bus_device(dev); ixdp2x00_slave_pci_postinit(); } }
int shpchp_unconfigure_device(struct slot *p_slot) { int rc = 0; int j; u8 bctl = 0; struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; struct controller *ctrl = p_slot->ctrl; ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); for (j = 0; j < 8 ; j++) { struct pci_dev *temp = pci_get_slot(parent, (p_slot->device << 3) | j); if (!temp) continue; if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); if (bctl & PCI_BRIDGE_CTL_VGA) { ctrl_err(ctrl, "Cannot remove display device %s\n", pci_name(temp)); pci_dev_put(temp); rc = -EINVAL; break; } } pci_remove_bus_device(temp); pci_dev_put(temp); } return rc; }
int cpci_unconfigure_slot(struct slot* slot) { int i; struct pci_dev *dev; dbg("%s - enter", __func__); if (!slot->dev) { err("No device for slot %02x\n", slot->number); return -ENODEV; } for (i = 0; i < 8; i++) { dev = pci_get_slot(slot->bus, PCI_DEVFN(PCI_SLOT(slot->devfn), i)); if (dev) { pci_remove_bus_device(dev); pci_dev_put(dev); } } pci_dev_put(slot->dev); slot->dev = NULL; dbg("%s - exit", __func__); return 0; }
/************************************************************************* * IXDP2x00-common PCI init * * The IXDP2[48]00 has a horrid PCI bus layout. Basically the board * contains two NPUs (ingress and egress) connected over PCI, both running * instances of the kernel. So far so good. Peers on the PCI bus running * Linux is a common design in telecom systems. The problem is that instead * of all the devices being controlled by a single host, different * devices are controlled by different NPUs on the same bus, leading to * multiple hosts on the bus. The exact bus layout looks like: * * Bus 0 * Master NPU <-------------------+-------------------> Slave NPU * | * | * P2P * | * * Bus 1 | * <--+------+---------+---------+------+--> * | | | | | * | | | | | * ... Dev PMC Media Eth0 Eth1 ... * * The master controls all but Eth1, which is controlled by the * slave. What this means is that the both the master and the slave * have to scan the bus, but only one of them can enumerate the bus. * In addition, after the bus is scanned, each kernel must remove * the device(s) it does not control from the PCI dev list otherwise * a driver on each NPU will try to manage it and we will have horrible * conflicts. Oh..and the slave NPU needs to see the master NPU * for Intel's drivers to work properly. Closed source drivers... * * The way we deal with this is fairly simple but ugly: * * 1) Let master scan and enumerate the bus completely. * 2) Master deletes Eth1 from device list. * 3) Slave scans bus and then deletes all but Eth1 (Eth0 on slave) * from device list. * 4) Find HW designers and LART them. * * The boards also do not do normal PCI IRQ routing, or any sort of * sensical swizzling, so we just need to check where on the bus a * device sits and figure out to which CPLD pin the interrupt is routed. * See ixdp2[48]00.c files. * *************************************************************************/ void ixdp2x00_slave_pci_postinit(void) { struct pci_dev *dev; /* * Remove PMC device is there is one */ if((dev = pci_get_bus_and_slot(1, IXDP2X00_PMC_DEVFN))) { pci_remove_bus_device(dev); pci_dev_put(dev); } dev = pci_get_bus_and_slot(0, IXDP2X00_21555_DEVFN); pci_remove_bus_device(dev); pci_dev_put(dev); }
void vpci_remove_vnic() { struct pci_dev *pcidev = NULL; if (vbus == NULL) return; pci_remove_bus_device(pcidev); pci_dev_put(pcidev); }
int __init ixdp2800_pci_init(void) { if (machine_is_ixdp2800()) { struct pci_dev *dev; pci_common_init(&ixdp2800_pci); if (ixdp2x00_master_npu()) { dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN); pci_remove_bus_device(dev); ixdp2800_master_enable_slave(); ixdp2800_master_wait_for_slave_bus_scan(); } else { dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN); pci_remove_bus_device(dev); } } return 0; }
static void pci_remove_bus_device(struct pci_dev *dev) { struct pci_bus *bus = dev->subordinate; struct pci_dev *child, *tmp; if (bus) { list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) pci_remove_bus_device(child); pci_remove_bus(bus); dev->subordinate = NULL; } pci_destroy_dev(dev); }
void pci_remove_root_bus(struct pci_bus *bus) { struct pci_dev *child, *tmp; struct pci_host_bridge *host_bridge; if (!pci_is_root_bus(bus)) return; host_bridge = to_pci_host_bridge(bus->bridge); list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) pci_remove_bus_device(child); pci_remove_bus(bus); host_bridge->bus = NULL; /* remove the host bridge */ device_unregister(&host_bridge->dev); }
/** * pci_stop_and_remove_bus_device - remove a PCI device and any children * @dev: the device to remove * * Remove a PCI device from the device lists, informing the drivers * that the device has been removed. We also remove any subordinate * buses and children in a depth-first manner. * * For each device we remove, delete the device structure from the * device lists, remove the /proc entry, and notify userspace * (/sbin/hotplug). */ void pci_stop_and_remove_bus_device(struct pci_dev *dev) { pci_stop_bus_device(dev); pci_remove_bus_device(dev); }
static int pcifront_detach_devices(struct pcifront_device *pdev) { int err = 0; int i, num_devs; unsigned int domain, bus, slot, func; struct pci_bus *pci_bus; struct pci_dev *pci_dev; char str[64]; spin_lock(&pdev->dev_lock); if (xenbus_read_driver_state(pdev->xdev->nodename) != XenbusStateConnected) goto out; err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, "num_devs", "%d", &num_devs); if (err != 1) { if (err >= 0) err = -EINVAL; xenbus_dev_fatal(pdev->xdev, err, "Error reading number of PCI devices"); goto out; } /* Find devices being detached and remove them. */ for (i = 0; i < num_devs; i++) { int l, state; l = snprintf(str, sizeof(str), "state-%d", i); if (unlikely(l >= (sizeof(str) - 1))) { err = -ENOMEM; goto out; } err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str, "%d", &state); if (err != 1) state = XenbusStateUnknown; if (state != XenbusStateClosing) continue; /* Remove device. */ l = snprintf(str, sizeof(str), "vdev-%d", i); if (unlikely(l >= (sizeof(str) - 1))) { err = -ENOMEM; goto out; } err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str, "%x:%x:%x.%x", &domain, &bus, &slot, &func); if (err != 4) { if (err >= 0) err = -EINVAL; xenbus_dev_fatal(pdev->xdev, err, "Error reading PCI device %d", i); goto out; } pci_bus = pci_find_bus(domain, bus); if(!pci_bus) { dev_dbg(&pdev->xdev->dev, "Cannot get bus %04x:%02x\n", domain, bus); continue; } pci_dev = pci_get_slot(pci_bus, PCI_DEVFN(slot, func)); if(!pci_dev) { dev_dbg(&pdev->xdev->dev, "Cannot get PCI device %04x:%02x:%02x.%02x\n", domain, bus, slot, func); continue; } pci_remove_bus_device(pci_dev); pci_dev_put(pci_dev); dev_dbg(&pdev->xdev->dev, "PCI device %04x:%02x:%02x.%02x removed.\n", domain, bus, slot, func); } err = xenbus_switch_state(pdev->xdev, XenbusStateReconfiguring); out: spin_unlock(&pdev->dev_lock); return err; }