static int gpex_guest_aspace_notification(struct vmm_notifier_block *nb, unsigned long evt, void *data) { int ret = NOTIFY_DONE; int rc; struct gpex_state *gpex = container_of(nb, struct gpex_state, guest_aspace_client); vmm_mutex_lock(&gpex->lock); switch (evt) { case VMM_GUEST_ASPACE_EVENT_RESET: if ((rc = pci_emu_register_controller(gpex->node, gpex->guest, gpex->controller)) != VMM_OK) { GPEX_LOG(LVL_ERR, "Failed to attach PCI controller.\n"); goto _failed; } ret = NOTIFY_OK; break; default: break; } _failed: vmm_mutex_unlock(&gpex->lock); return ret; }
static int gpex_emulator_probe(struct vmm_guest *guest, struct vmm_emudev *edev, const struct vmm_devtree_nodeid *eid) { int rc = VMM_OK, i; char name[64]; struct gpex_state *s; struct pci_class *class; s = vmm_zalloc(sizeof(struct gpex_state)); if (!s) { GPEX_LOG(LVL_ERR, "Failed to allocate gpex state.\n"); rc = VMM_EFAIL; goto _failed; } s->node = edev->node; s->guest = guest; s->controller = vmm_zalloc(sizeof(struct pci_host_controller)); if (!s->controller) { GPEX_LOG(LVL_ERR, "Failed to allocate pci host contoller" "for gpex.\n"); goto _failed; } INIT_MUTEX(&s->lock); INIT_LIST_HEAD(&s->controller->head); INIT_LIST_HEAD(&s->controller->attached_buses); INIT_SPIN_LOCK(&s->controller->lock); /* initialize class */ class = PCI_CONTROLLER_TO_CLASS(s->controller); INIT_SPIN_LOCK(&class->lock); class->conf_header.vendor_id = PCI_VENDOR_ID_REDHAT; class->conf_header.device_id = PCI_DEVICE_ID_REDHAT_PCIE_HOST; class->config_read = gpex_config_read; class->config_write = gpex_config_write; rc = vmm_devtree_read_u32(edev->node, "nr_buses", &s->controller->nr_buses); if (rc) { GPEX_LOG(LVL_ERR, "Failed to get fifo size in guest DTS.\n"); goto _failed; } GPEX_LOG(LVL_VERBOSE, "%s: %d busses on this controller.\n", __func__, s->controller->nr_buses); for (i = 0; i < s->controller->nr_buses; i++) { if ((rc = pci_emu_attach_new_pci_bus(s->controller, i)) != VMM_OK) { GPEX_LOG(LVL_ERR, "Failed to attach PCI bus %d\n", i+1); goto _failed; } } strlcpy(name, guest->name, sizeof(name)); strlcat(name, "/", sizeof(name)); if (strlcat(name, edev->node->name, sizeof(name)) >= sizeof(name)) { rc = VMM_EOVERFLOW; goto _failed; } edev->priv = s; vmm_mutex_lock(&s->lock); if ((rc = pci_emu_register_controller(s->node, s->guest, s->controller)) != VMM_OK) { GPEX_LOG(LVL_ERR, "Failed to attach PCI controller.\n"); goto _controller_failed; } vmm_mutex_unlock(&s->lock); GPEX_LOG(LVL_VERBOSE, "Success.\n"); goto _done; _controller_failed: vmm_mutex_unlock(&s->lock); _failed: if (s && s->controller) vmm_free(s->controller); if (s) vmm_free(s); _done: return rc; }