2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) Siemens AG, 2014-2015
7 * Jan Kiszka <jan.kiszka@siemens.com>
8 * Henning Schild <henning.schild@siemens.com>
10 * This work is licensed under the terms of the GNU GPL, version 2. See
11 * the COPYING file in the top-level directory.
14 #include <linux/pci.h>
18 static void jailhouse_pci_add_device(const struct jailhouse_pci_device *dev)
23 bus = pci_find_bus(dev->domain, PCI_BUS_NUM(dev->bdf));
25 num = pci_scan_slot(bus, dev->bdf & 0xff);
27 pci_lock_rescan_remove();
28 pci_bus_assign_resources(bus);
29 pci_bus_add_devices(bus);
30 pci_unlock_rescan_remove();
35 static void jailhouse_pci_remove_device(const struct jailhouse_pci_device *dev)
37 struct pci_dev *l_dev;
39 l_dev = pci_get_bus_and_slot(PCI_BUS_NUM(dev->bdf), dev->bdf & 0xff);
41 pci_stop_and_remove_bus_device_locked(l_dev);
44 void jailhouse_pci_do_all_devices(struct cell *cell, unsigned int type,
48 const struct jailhouse_pci_device *dev;
50 dev = cell->pci_devices;
51 for (n = cell->num_pci_devices; n > 0; n--) {
52 if (dev->type == type) {
53 if (action == JAILHOUSE_PCI_ACTION_ADD)
54 jailhouse_pci_add_device(dev);
55 else if (action == JAILHOUSE_PCI_ACTION_DEL)
56 jailhouse_pci_remove_device(dev);
62 int jailhouse_pci_cell_setup(struct cell *cell,
63 const struct jailhouse_cell_desc *cell_desc)
65 if (cell_desc->num_pci_devices == 0)
66 /* cell is zero-initialized, no need to set pci fields */
69 if (cell_desc->num_pci_devices >=
70 ULONG_MAX / sizeof(struct jailhouse_pci_device))
73 cell->num_pci_devices = cell_desc->num_pci_devices;
74 cell->pci_devices = vmalloc(sizeof(struct jailhouse_pci_device) *
75 cell->num_pci_devices);
76 if (!cell->pci_devices)
79 memcpy(cell->pci_devices,
80 jailhouse_cell_pci_devices(cell_desc),
81 sizeof(struct jailhouse_pci_device) * cell->num_pci_devices);
86 void jailhouse_pci_cell_cleanup(struct cell *cell)
88 vfree(cell->pci_devices);