Lines Matching +full:pci +full:- +full:domain
1 // SPDX-License-Identifier: GPL-2.0
3 * Xen PCI Frontend
15 #include <linux/pci.h>
18 #include <asm/xen/pci.h>
28 #include <asm/xen/swiotlb-xen.h>
30 #define INVALID_EVTCHN (-1)
65 return sd->pdev; in pcifront_get_pdev()
69 unsigned int domain, unsigned int bus, in pcifront_init_sd() argument
73 sd->sd.node = first_online_node; in pcifront_init_sd()
74 sd->sd.domain = domain; in pcifront_init_sd()
75 sd->pdev = pdev; in pcifront_init_sd()
105 if (test_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags) in schedule_pcifront_aer_op()
106 && !test_and_set_bit(_PDEVB_op_active, &pdev->flags)) { in schedule_pcifront_aer_op()
107 dev_dbg(&pdev->xdev->dev, "schedule aer frontend job\n"); in schedule_pcifront_aer_op()
108 schedule_work(&pdev->op_work); in schedule_pcifront_aer_op()
115 struct xen_pci_op *active_op = &pdev->sh_info->op; in do_pci_op()
117 evtchn_port_t port = pdev->evtchn; in do_pci_op()
118 unsigned irq = pdev->irq; in do_pci_op()
121 spin_lock_irqsave(&pdev->sh_info_lock, irq_flags); in do_pci_op()
127 set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags); in do_pci_op()
133 * (in the latter case we end up continually re-executing poll() with a in do_pci_op()
141 (unsigned long *)&pdev->sh_info->flags)) { in do_pci_op()
146 dev_err(&pdev->xdev->dev, in do_pci_op()
149 (unsigned long *)&pdev->sh_info->flags); in do_pci_op()
157 * reuse same evtchn with pci_conf backend response. So re-schedule in do_pci_op()
161 (unsigned long *)&pdev->sh_info->flags)) { in do_pci_op()
162 dev_err(&pdev->xdev->dev, in do_pci_op()
169 err = op->err; in do_pci_op()
171 spin_unlock_irqrestore(&pdev->sh_info_lock, irq_flags); in do_pci_op()
175 /* Access to this function is spinlocked in drivers/pci/access.c */
182 .domain = pci_domain_nr(bus), in pcifront_bus_read()
183 .bus = bus->number, in pcifront_bus_read()
188 struct pcifront_sd *sd = bus->sysdata; in pcifront_bus_read()
191 dev_dbg(&pdev->xdev->dev, in pcifront_bus_read()
192 "read dev=%04x:%02x:%02x.%d - offset %x size %d\n", in pcifront_bus_read()
193 pci_domain_nr(bus), bus->number, PCI_SLOT(devfn), in pcifront_bus_read()
199 dev_dbg(&pdev->xdev->dev, "read got back value %x\n", in pcifront_bus_read()
203 } else if (err == -ENODEV) { in pcifront_bus_read()
212 /* Access to this function is spinlocked in drivers/pci/access.c */
218 .domain = pci_domain_nr(bus), in pcifront_bus_write()
219 .bus = bus->number, in pcifront_bus_write()
225 struct pcifront_sd *sd = bus->sysdata; in pcifront_bus_write()
228 dev_dbg(&pdev->xdev->dev, in pcifront_bus_write()
229 "write dev=%04x:%02x:%02x.%d - offset %x size %d val %x\n", in pcifront_bus_write()
230 pci_domain_nr(bus), bus->number, in pcifront_bus_write()
249 .domain = pci_domain_nr(dev->bus), in pci_frontend_enable_msix()
250 .bus = dev->bus->number, in pci_frontend_enable_msix()
251 .devfn = dev->devfn, in pci_frontend_enable_msix()
254 struct pcifront_sd *sd = dev->bus->sysdata; in pci_frontend_enable_msix()
259 pci_err(dev, "too many vectors (0x%x) for PCI frontend:" in pci_frontend_enable_msix()
261 return -EINVAL; in pci_frontend_enable_msix()
266 op.msix_entries[i].entry = entry->msi_attrib.entry_nr; in pci_frontend_enable_msix()
268 op.msix_entries[i].vector = -1; in pci_frontend_enable_msix()
279 pci_warn(dev, "MSI-X entry %d is invalid: %d!\n", in pci_frontend_enable_msix()
281 err = -EINVAL; in pci_frontend_enable_msix()
282 vector[i] = -1; in pci_frontend_enable_msix()
302 .domain = pci_domain_nr(dev->bus), in pci_frontend_disable_msix()
303 .bus = dev->bus->number, in pci_frontend_disable_msix()
304 .devfn = dev->devfn, in pci_frontend_disable_msix()
306 struct pcifront_sd *sd = dev->bus->sysdata; in pci_frontend_disable_msix()
321 .domain = pci_domain_nr(dev->bus), in pci_frontend_enable_msi()
322 .bus = dev->bus->number, in pci_frontend_enable_msi()
323 .devfn = dev->devfn, in pci_frontend_enable_msi()
325 struct pcifront_sd *sd = dev->bus->sysdata; in pci_frontend_enable_msi()
334 err = -EINVAL; in pci_frontend_enable_msi()
335 vector[0] = -1; in pci_frontend_enable_msi()
338 pci_err(dev, "pci frontend enable msi failed for dev " in pci_frontend_enable_msi()
340 err = -EINVAL; in pci_frontend_enable_msi()
350 .domain = pci_domain_nr(dev->bus), in pci_frontend_disable_msi()
351 .bus = dev->bus->number, in pci_frontend_disable_msi()
352 .devfn = dev->devfn, in pci_frontend_disable_msi()
354 struct pcifront_sd *sd = dev->bus->sysdata; in pci_frontend_disable_msi()
386 /* Claim resources for the PCI frontend as-is, backend won't allow changes */
394 r = &dev->resource[i]; in pcifront_claim_resource()
396 if (!r->parent && r->start && r->flags) { in pcifront_claim_resource()
397 dev_info(&pdev->xdev->dev, "claiming resource %s/%d\n", in pcifront_claim_resource()
400 dev_err(&pdev->xdev->dev, "Could not claim resource %s/%d! " in pcifront_claim_resource()
411 unsigned int domain, unsigned int bus, in pcifront_scan_bus() argument
418 * We omit handling of PCI bridge attachment because pciback prevents in pcifront_scan_bus()
431 dev_info(&pdev->xdev->dev, "New device on " in pcifront_scan_bus()
432 "%04x:%02x:%02x.%d found.\n", domain, bus, in pcifront_scan_bus()
440 unsigned int domain, unsigned int bus) in pcifront_scan_root() argument
454 if (domain != 0) { in pcifront_scan_root()
455 dev_err(&pdev->xdev->dev, in pcifront_scan_root()
456 "PCI Root in non-zero PCI Domain! domain=%d\n", domain); in pcifront_scan_root()
457 dev_err(&pdev->xdev->dev, in pcifront_scan_root()
459 err = -EINVAL; in pcifront_scan_root()
464 dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n", in pcifront_scan_root()
465 domain, bus); in pcifront_scan_root()
470 err = -ENOMEM; in pcifront_scan_root()
476 pcifront_init_sd(sd, domain, bus, pdev); in pcifront_scan_root()
480 b = pci_scan_root_bus(&pdev->xdev->dev, bus, in pcifront_scan_root()
483 dev_err(&pdev->xdev->dev, in pcifront_scan_root()
484 "Error creating PCI Frontend Bus!\n"); in pcifront_scan_root()
485 err = -ENOMEM; in pcifront_scan_root()
491 bus_entry->bus = b; in pcifront_scan_root()
493 list_add(&bus_entry->list, &pdev->root_buses); in pcifront_scan_root()
497 err = pcifront_scan_bus(pdev, domain, bus, b); in pcifront_scan_root()
516 unsigned int domain, unsigned int bus) in pcifront_rescan_root() argument
522 if (domain != 0) { in pcifront_rescan_root()
523 dev_err(&pdev->xdev->dev, in pcifront_rescan_root()
524 "PCI Root in non-zero PCI Domain! domain=%d\n", domain); in pcifront_rescan_root()
525 dev_err(&pdev->xdev->dev, in pcifront_rescan_root()
527 return -EINVAL; in pcifront_rescan_root()
531 dev_info(&pdev->xdev->dev, "Rescanning PCI Frontend Bus %04x:%02x\n", in pcifront_rescan_root()
532 domain, bus); in pcifront_rescan_root()
534 b = pci_find_bus(domain, bus); in pcifront_rescan_root()
537 return pcifront_scan_root(pdev, domain, bus); in pcifront_rescan_root()
539 err = pcifront_scan_bus(pdev, domain, bus, b); in pcifront_rescan_root()
554 while (!list_empty(&bus->devices)) { in free_root_bus_devs()
555 dev = container_of(bus->devices.next, struct pci_dev, in free_root_bus_devs()
566 dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n"); in pcifront_free_roots()
569 list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) { in pcifront_free_roots()
570 list_del(&bus_entry->list); in pcifront_free_roots()
572 free_root_bus_devs(bus_entry->bus); in pcifront_free_roots()
574 kfree(bus_entry->bus->sysdata); in pcifront_free_roots()
576 device_unregister(bus_entry->bus->bridge); in pcifront_free_roots()
577 pci_remove_bus(bus_entry->bus); in pcifront_free_roots()
590 int bus = pdev->sh_info->aer_op.bus; in pcifront_common_process()
591 int devfn = pdev->sh_info->aer_op.devfn; in pcifront_common_process()
592 int domain = pdev->sh_info->aer_op.domain; in pcifront_common_process() local
596 dev_dbg(&pdev->xdev->dev, in pcifront_common_process()
601 pcidev = pci_get_domain_bus_and_slot(domain, bus, devfn); in pcifront_common_process()
602 if (!pcidev || !pcidev->driver) { in pcifront_common_process()
603 dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n"); in pcifront_common_process()
607 pdrv = pcidev->driver; in pcifront_common_process()
610 if (pdrv->err_handler && pdrv->err_handler->error_detected) { in pcifront_common_process()
616 result = pdrv->err_handler-> in pcifront_common_process()
620 result = pdrv->err_handler-> in pcifront_common_process()
624 result = pdrv->err_handler-> in pcifront_common_process()
628 pdrv->err_handler->resume(pcidev); in pcifront_common_process()
631 dev_err(&pdev->xdev->dev, in pcifront_common_process()
650 int cmd = pdev->sh_info->aer_op.cmd; in pcifront_do_aer()
652 (pci_channel_state_t)pdev->sh_info->aer_op.err; in pcifront_do_aer()
656 dev_dbg(&pdev->xdev->dev, in pcifront_do_aer()
658 pdev->sh_info->aer_op.bus, pdev->sh_info->aer_op.devfn); in pcifront_do_aer()
660 pdev->sh_info->aer_op.err = pcifront_common_process(cmd, pdev, state); in pcifront_do_aer()
664 clear_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags); in pcifront_do_aer()
665 notify_remote_via_evtchn(pdev->evtchn); in pcifront_do_aer()
669 clear_bit(_PDEVB_op_active, &pdev->flags); in pcifront_do_aer()
689 dev_info(&pdev->xdev->dev, "Installing PCI frontend\n"); in pcifront_connect_and_init_dma()
692 err = -EEXIST; in pcifront_connect_and_init_dma()
699 dev_err(&pdev->xdev->dev, "Could not setup SWIOTLB!\n"); in pcifront_connect_and_init_dma()
709 dev_info(&pdev->xdev->dev, in pcifront_disconnect()
710 "Disconnecting PCI Frontend Buses\n"); in pcifront_disconnect()
724 pdev->sh_info = in alloc_pdev()
726 if (pdev->sh_info == NULL) { in alloc_pdev()
731 pdev->sh_info->flags = 0; in alloc_pdev()
734 set_bit(_XEN_PCIB_AERHANDLER, (void *)&pdev->sh_info->flags); in alloc_pdev()
736 dev_set_drvdata(&xdev->dev, pdev); in alloc_pdev()
737 pdev->xdev = xdev; in alloc_pdev()
739 INIT_LIST_HEAD(&pdev->root_buses); in alloc_pdev()
741 spin_lock_init(&pdev->sh_info_lock); in alloc_pdev()
743 pdev->evtchn = INVALID_EVTCHN; in alloc_pdev()
744 pdev->gnt_ref = INVALID_GRANT_REF; in alloc_pdev()
745 pdev->irq = -1; in alloc_pdev()
747 INIT_WORK(&pdev->op_work, pcifront_do_aer); in alloc_pdev()
749 dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @ 0x%p\n", in alloc_pdev()
750 pdev, pdev->sh_info); in alloc_pdev()
757 dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev); in free_pdev()
761 cancel_work_sync(&pdev->op_work); in free_pdev()
763 if (pdev->irq >= 0) in free_pdev()
764 unbind_from_irqhandler(pdev->irq, pdev); in free_pdev()
766 if (pdev->evtchn != INVALID_EVTCHN) in free_pdev()
767 xenbus_free_evtchn(pdev->xdev, pdev->evtchn); in free_pdev()
769 if (pdev->gnt_ref != INVALID_GRANT_REF) in free_pdev()
770 gnttab_end_foreign_access(pdev->gnt_ref, 0 /* r/w page */, in free_pdev()
771 (unsigned long)pdev->sh_info); in free_pdev()
773 free_page((unsigned long)pdev->sh_info); in free_pdev()
775 dev_set_drvdata(&pdev->xdev->dev, NULL); in free_pdev()
786 err = xenbus_grant_ring(pdev->xdev, pdev->sh_info, 1, &gref); in pcifront_publish_info()
790 pdev->gnt_ref = gref; in pcifront_publish_info()
792 err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn); in pcifront_publish_info()
796 err = bind_evtchn_to_irqhandler(pdev->evtchn, pcifront_handler_aer, in pcifront_publish_info()
802 pdev->irq = err; in pcifront_publish_info()
807 xenbus_dev_fatal(pdev->xdev, err, in pcifront_publish_info()
813 err = xenbus_printf(trans, pdev->xdev->nodename, in pcifront_publish_info()
814 "pci-op-ref", "%u", pdev->gnt_ref); in pcifront_publish_info()
816 err = xenbus_printf(trans, pdev->xdev->nodename, in pcifront_publish_info()
817 "event-channel", "%u", pdev->evtchn); in pcifront_publish_info()
819 err = xenbus_printf(trans, pdev->xdev->nodename, in pcifront_publish_info()
824 xenbus_dev_fatal(pdev->xdev, err, in pcifront_publish_info()
829 if (err == -EAGAIN) in pcifront_publish_info()
832 xenbus_dev_fatal(pdev->xdev, err, in pcifront_publish_info()
839 xenbus_switch_state(pdev->xdev, XenbusStateInitialised); in pcifront_publish_info()
841 dev_dbg(&pdev->xdev->dev, "publishing successful!\n"); in pcifront_publish_info()
849 int err = -EFAULT; in pcifront_try_connect()
852 unsigned int domain, bus; in pcifront_try_connect() local
856 if (xenbus_read_driver_state(pdev->xdev->nodename) != in pcifront_try_connect()
861 if (err && err != -EEXIST) { in pcifront_try_connect()
862 xenbus_dev_fatal(pdev->xdev, err, in pcifront_try_connect()
863 "Error setting up PCI Frontend"); in pcifront_try_connect()
867 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, in pcifront_try_connect()
869 if (err == -ENOENT) { in pcifront_try_connect()
870 xenbus_dev_error(pdev->xdev, err, in pcifront_try_connect()
871 "No PCI Roots found, trying 0000:00"); in pcifront_try_connect()
874 xenbus_dev_fatal(pdev->xdev, err, in pcifront_try_connect()
875 "Error scanning PCI root 0000:00"); in pcifront_try_connect()
881 err = -EINVAL; in pcifront_try_connect()
882 xenbus_dev_fatal(pdev->xdev, err, in pcifront_try_connect()
883 "Error reading number of PCI roots"); in pcifront_try_connect()
888 len = snprintf(str, sizeof(str), "root-%d", i); in pcifront_try_connect()
889 if (unlikely(len >= (sizeof(str) - 1))) { in pcifront_try_connect()
890 err = -ENOMEM; in pcifront_try_connect()
894 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str, in pcifront_try_connect()
895 "%x:%x", &domain, &bus); in pcifront_try_connect()
898 err = -EINVAL; in pcifront_try_connect()
899 xenbus_dev_fatal(pdev->xdev, err, in pcifront_try_connect()
900 "Error reading PCI root %d", i); in pcifront_try_connect()
904 err = pcifront_scan_root(pdev, domain, bus); in pcifront_try_connect()
906 xenbus_dev_fatal(pdev->xdev, err, in pcifront_try_connect()
907 "Error scanning PCI root %04x:%02x", in pcifront_try_connect()
908 domain, bus); in pcifront_try_connect()
913 err = xenbus_switch_state(pdev->xdev, XenbusStateConnected); in pcifront_try_connect()
925 prev_state = xenbus_read_driver_state(pdev->xdev->nodename); in pcifront_try_disconnect()
935 err = xenbus_switch_state(pdev->xdev, XenbusStateClosed); in pcifront_try_disconnect()
944 int err = -EFAULT; in pcifront_attach_devices()
946 unsigned int domain, bus; in pcifront_attach_devices() local
949 if (xenbus_read_driver_state(pdev->xdev->nodename) != in pcifront_attach_devices()
953 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, in pcifront_attach_devices()
955 if (err == -ENOENT) { in pcifront_attach_devices()
956 xenbus_dev_error(pdev->xdev, err, in pcifront_attach_devices()
957 "No PCI Roots found, trying 0000:00"); in pcifront_attach_devices()
960 xenbus_dev_fatal(pdev->xdev, err, in pcifront_attach_devices()
961 "Error scanning PCI root 0000:00"); in pcifront_attach_devices()
967 err = -EINVAL; in pcifront_attach_devices()
968 xenbus_dev_fatal(pdev->xdev, err, in pcifront_attach_devices()
969 "Error reading number of PCI roots"); in pcifront_attach_devices()
974 len = snprintf(str, sizeof(str), "root-%d", i); in pcifront_attach_devices()
975 if (unlikely(len >= (sizeof(str) - 1))) { in pcifront_attach_devices()
976 err = -ENOMEM; in pcifront_attach_devices()
980 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str, in pcifront_attach_devices()
981 "%x:%x", &domain, &bus); in pcifront_attach_devices()
984 err = -EINVAL; in pcifront_attach_devices()
985 xenbus_dev_fatal(pdev->xdev, err, in pcifront_attach_devices()
986 "Error reading PCI root %d", i); in pcifront_attach_devices()
990 err = pcifront_rescan_root(pdev, domain, bus); in pcifront_attach_devices()
992 xenbus_dev_fatal(pdev->xdev, err, in pcifront_attach_devices()
993 "Error scanning PCI root %04x:%02x", in pcifront_attach_devices()
994 domain, bus); in pcifront_attach_devices()
999 xenbus_switch_state(pdev->xdev, XenbusStateConnected); in pcifront_attach_devices()
1009 unsigned int domain, bus, slot, func; in pcifront_detach_devices() local
1013 if (xenbus_read_driver_state(pdev->xdev->nodename) != in pcifront_detach_devices()
1017 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, "num_devs", "%d", in pcifront_detach_devices()
1021 err = -EINVAL; in pcifront_detach_devices()
1022 xenbus_dev_fatal(pdev->xdev, err, in pcifront_detach_devices()
1023 "Error reading number of PCI devices"); in pcifront_detach_devices()
1030 l = snprintf(str, sizeof(str), "state-%d", i); in pcifront_detach_devices()
1031 if (unlikely(l >= (sizeof(str) - 1))) { in pcifront_detach_devices()
1032 err = -ENOMEM; in pcifront_detach_devices()
1035 state = xenbus_read_unsigned(pdev->xdev->otherend, str, in pcifront_detach_devices()
1042 l = snprintf(str, sizeof(str), "vdev-%d", i); in pcifront_detach_devices()
1043 if (unlikely(l >= (sizeof(str) - 1))) { in pcifront_detach_devices()
1044 err = -ENOMEM; in pcifront_detach_devices()
1047 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str, in pcifront_detach_devices()
1048 "%x:%x:%x.%x", &domain, &bus, &slot, &func); in pcifront_detach_devices()
1051 err = -EINVAL; in pcifront_detach_devices()
1052 xenbus_dev_fatal(pdev->xdev, err, in pcifront_detach_devices()
1053 "Error reading PCI device %d", i); in pcifront_detach_devices()
1057 pci_dev = pci_get_domain_bus_and_slot(domain, bus, in pcifront_detach_devices()
1060 dev_dbg(&pdev->xdev->dev, in pcifront_detach_devices()
1061 "Cannot get PCI device %04x:%02x:%02x.%d\n", in pcifront_detach_devices()
1062 domain, bus, slot, func); in pcifront_detach_devices()
1070 dev_dbg(&pdev->xdev->dev, in pcifront_detach_devices()
1071 "PCI device %04x:%02x:%02x.%d removed.\n", in pcifront_detach_devices()
1072 domain, bus, slot, func); in pcifront_detach_devices()
1075 err = xenbus_switch_state(pdev->xdev, XenbusStateReconfiguring); in pcifront_detach_devices()
1084 struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev); in pcifront_backend_changed()
1098 if (xdev->state == XenbusStateClosed) in pcifront_backend_changed()
1102 dev_warn(&xdev->dev, "backend going away!\n"); in pcifront_backend_changed()
1123 err = -ENOMEM; in pcifront_xenbus_probe()
1139 struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev); in pcifront_xenbus_remove()
1147 {"pci"},
1162 return -ENODEV; in pcifront_init()
1165 return -ENODEV; in pcifront_init()
1180 MODULE_DESCRIPTION("Xen PCI passthrough frontend.");
1182 MODULE_ALIAS("xen:pci");