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 int 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
419 * We omit handling of PCI bridge attachment because pciback prevents in pcifront_scan_bus()
432 dev_info(&pdev->xdev->dev, "New device on " in pcifront_scan_bus()
433 "%04x:%02x:%02x.%d found.\n", domain, bus, in pcifront_scan_bus()
441 unsigned int domain, unsigned int bus) in pcifront_scan_root() argument
455 if (domain != 0) { in pcifront_scan_root()
456 dev_err(&pdev->xdev->dev, in pcifront_scan_root()
457 "PCI Root in non-zero PCI Domain! domain=%d\n", domain); in pcifront_scan_root()
458 dev_err(&pdev->xdev->dev, in pcifront_scan_root()
460 err = -EINVAL; in pcifront_scan_root()
465 dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n", in pcifront_scan_root()
466 domain, bus); in pcifront_scan_root()
471 err = -ENOMEM; in pcifront_scan_root()
477 pcifront_init_sd(sd, domain, bus, pdev); in pcifront_scan_root()
481 b = pci_scan_root_bus(&pdev->xdev->dev, bus, in pcifront_scan_root()
484 dev_err(&pdev->xdev->dev, in pcifront_scan_root()
485 "Error creating PCI Frontend Bus!\n"); in pcifront_scan_root()
486 err = -ENOMEM; in pcifront_scan_root()
492 bus_entry->bus = b; in pcifront_scan_root()
494 list_add(&bus_entry->list, &pdev->root_buses); in pcifront_scan_root()
500 err = pcifront_scan_bus(pdev, domain, bus, b); in pcifront_scan_root()
519 unsigned int domain, unsigned int bus) in pcifront_rescan_root() argument
525 if (domain != 0) { in pcifront_rescan_root()
526 dev_err(&pdev->xdev->dev, in pcifront_rescan_root()
527 "PCI Root in non-zero PCI Domain! domain=%d\n", domain); in pcifront_rescan_root()
528 dev_err(&pdev->xdev->dev, in pcifront_rescan_root()
530 return -EINVAL; in pcifront_rescan_root()
534 dev_info(&pdev->xdev->dev, "Rescanning PCI Frontend Bus %04x:%02x\n", in pcifront_rescan_root()
535 domain, bus); in pcifront_rescan_root()
537 b = pci_find_bus(domain, bus); in pcifront_rescan_root()
540 return pcifront_scan_root(pdev, domain, bus); in pcifront_rescan_root()
542 err = pcifront_scan_bus(pdev, domain, bus, b); in pcifront_rescan_root()
557 while (!list_empty(&bus->devices)) { in free_root_bus_devs()
558 dev = container_of(bus->devices.next, struct pci_dev, in free_root_bus_devs()
569 dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n"); in pcifront_free_roots()
572 list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) { in pcifront_free_roots()
573 list_del(&bus_entry->list); in pcifront_free_roots()
575 free_root_bus_devs(bus_entry->bus); in pcifront_free_roots()
577 kfree(bus_entry->bus->sysdata); in pcifront_free_roots()
579 device_unregister(bus_entry->bus->bridge); in pcifront_free_roots()
580 pci_remove_bus(bus_entry->bus); in pcifront_free_roots()
593 int bus = pdev->sh_info->aer_op.bus; in pcifront_common_process()
594 int devfn = pdev->sh_info->aer_op.devfn; in pcifront_common_process()
595 int domain = pdev->sh_info->aer_op.domain; in pcifront_common_process() local
599 dev_dbg(&pdev->xdev->dev, in pcifront_common_process()
604 pcidev = pci_get_domain_bus_and_slot(domain, bus, devfn); in pcifront_common_process()
605 if (!pcidev || !pcidev->driver) { in pcifront_common_process()
606 dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n"); in pcifront_common_process()
610 pdrv = pcidev->driver; in pcifront_common_process()
613 if (pdrv->err_handler && pdrv->err_handler->error_detected) { in pcifront_common_process()
619 result = pdrv->err_handler-> in pcifront_common_process()
623 result = pdrv->err_handler-> in pcifront_common_process()
627 result = pdrv->err_handler-> in pcifront_common_process()
631 pdrv->err_handler->resume(pcidev); in pcifront_common_process()
634 dev_err(&pdev->xdev->dev, in pcifront_common_process()
653 int cmd = pdev->sh_info->aer_op.cmd; in pcifront_do_aer()
655 (pci_channel_state_t)pdev->sh_info->aer_op.err; in pcifront_do_aer()
661 dev_dbg(&pdev->xdev->dev, in pcifront_do_aer()
663 pdev->sh_info->aer_op.bus, pdev->sh_info->aer_op.devfn); in pcifront_do_aer()
665 pdev->sh_info->aer_op.err = pcifront_common_process(cmd, pdev, state); in pcifront_do_aer()
669 clear_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags); in pcifront_do_aer()
670 notify_remote_via_evtchn(pdev->evtchn); in pcifront_do_aer()
674 clear_bit(_PDEVB_op_active, &pdev->flags); in pcifront_do_aer()
695 dev_info(&pdev->xdev->dev, "Installing PCI frontend\n"); in pcifront_connect_and_init_dma()
698 err = -EEXIST; in pcifront_connect_and_init_dma()
702 if (!err && !is_swiotlb_active(&pdev->xdev->dev)) { in pcifront_connect_and_init_dma()
705 dev_err(&pdev->xdev->dev, "Could not setup SWIOTLB!\n"); in pcifront_connect_and_init_dma()
715 dev_info(&pdev->xdev->dev, in pcifront_disconnect()
716 "Disconnecting PCI Frontend Buses\n"); in pcifront_disconnect()
730 pdev->sh_info = in alloc_pdev()
732 if (pdev->sh_info == NULL) { in alloc_pdev()
737 pdev->sh_info->flags = 0; in alloc_pdev()
740 set_bit(_XEN_PCIB_AERHANDLER, (void *)&pdev->sh_info->flags); in alloc_pdev()
742 dev_set_drvdata(&xdev->dev, pdev); in alloc_pdev()
743 pdev->xdev = xdev; in alloc_pdev()
745 INIT_LIST_HEAD(&pdev->root_buses); in alloc_pdev()
747 spin_lock_init(&pdev->sh_info_lock); in alloc_pdev()
749 pdev->evtchn = INVALID_EVTCHN; in alloc_pdev()
750 pdev->gnt_ref = INVALID_GRANT_REF; in alloc_pdev()
751 pdev->irq = -1; in alloc_pdev()
753 INIT_WORK(&pdev->op_work, pcifront_do_aer); in alloc_pdev()
755 dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @ 0x%p\n", in alloc_pdev()
756 pdev, pdev->sh_info); in alloc_pdev()
763 dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev); in free_pdev()
767 cancel_work_sync(&pdev->op_work); in free_pdev()
769 if (pdev->irq >= 0) in free_pdev()
770 unbind_from_irqhandler(pdev->irq, pdev); in free_pdev()
772 if (pdev->evtchn != INVALID_EVTCHN) in free_pdev()
773 xenbus_free_evtchn(pdev->xdev, pdev->evtchn); in free_pdev()
775 if (pdev->gnt_ref != INVALID_GRANT_REF) in free_pdev()
776 gnttab_end_foreign_access(pdev->gnt_ref, 0 /* r/w page */, in free_pdev()
777 (unsigned long)pdev->sh_info); in free_pdev()
779 free_page((unsigned long)pdev->sh_info); in free_pdev()
781 dev_set_drvdata(&pdev->xdev->dev, NULL); in free_pdev()
792 err = xenbus_grant_ring(pdev->xdev, pdev->sh_info, 1, &gref); in pcifront_publish_info()
796 pdev->gnt_ref = gref; in pcifront_publish_info()
798 err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn); in pcifront_publish_info()
802 err = bind_evtchn_to_irqhandler(pdev->evtchn, pcifront_handler_aer, in pcifront_publish_info()
808 pdev->irq = err; in pcifront_publish_info()
813 xenbus_dev_fatal(pdev->xdev, err, in pcifront_publish_info()
819 err = xenbus_printf(trans, pdev->xdev->nodename, in pcifront_publish_info()
820 "pci-op-ref", "%u", pdev->gnt_ref); in pcifront_publish_info()
822 err = xenbus_printf(trans, pdev->xdev->nodename, in pcifront_publish_info()
823 "event-channel", "%u", pdev->evtchn); in pcifront_publish_info()
825 err = xenbus_printf(trans, pdev->xdev->nodename, in pcifront_publish_info()
830 xenbus_dev_fatal(pdev->xdev, err, in pcifront_publish_info()
835 if (err == -EAGAIN) in pcifront_publish_info()
838 xenbus_dev_fatal(pdev->xdev, err, in pcifront_publish_info()
845 xenbus_switch_state(pdev->xdev, XenbusStateInitialised); in pcifront_publish_info()
847 dev_dbg(&pdev->xdev->dev, "publishing successful!\n"); in pcifront_publish_info()
855 int err = -EFAULT; in pcifront_try_connect()
858 unsigned int domain, bus; in pcifront_try_connect() local
862 if (xenbus_read_driver_state(pdev->xdev->nodename) != in pcifront_try_connect()
867 if (err && err != -EEXIST) { in pcifront_try_connect()
868 xenbus_dev_fatal(pdev->xdev, err, in pcifront_try_connect()
869 "Error setting up PCI Frontend"); in pcifront_try_connect()
873 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, in pcifront_try_connect()
875 if (err == -ENOENT) { in pcifront_try_connect()
876 xenbus_dev_error(pdev->xdev, err, in pcifront_try_connect()
877 "No PCI Roots found, trying 0000:00"); in pcifront_try_connect()
880 xenbus_dev_fatal(pdev->xdev, err, in pcifront_try_connect()
881 "Error scanning PCI root 0000:00"); in pcifront_try_connect()
887 err = -EINVAL; in pcifront_try_connect()
888 xenbus_dev_fatal(pdev->xdev, err, in pcifront_try_connect()
889 "Error reading number of PCI roots"); in pcifront_try_connect()
894 len = snprintf(str, sizeof(str), "root-%d", i); in pcifront_try_connect()
895 if (unlikely(len >= (sizeof(str) - 1))) { in pcifront_try_connect()
896 err = -ENOMEM; in pcifront_try_connect()
900 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str, in pcifront_try_connect()
901 "%x:%x", &domain, &bus); in pcifront_try_connect()
904 err = -EINVAL; in pcifront_try_connect()
905 xenbus_dev_fatal(pdev->xdev, err, in pcifront_try_connect()
906 "Error reading PCI root %d", i); in pcifront_try_connect()
910 err = pcifront_scan_root(pdev, domain, bus); in pcifront_try_connect()
912 xenbus_dev_fatal(pdev->xdev, err, in pcifront_try_connect()
913 "Error scanning PCI root %04x:%02x", in pcifront_try_connect()
914 domain, bus); in pcifront_try_connect()
919 err = xenbus_switch_state(pdev->xdev, XenbusStateConnected); in pcifront_try_connect()
931 prev_state = xenbus_read_driver_state(pdev->xdev->nodename); in pcifront_try_disconnect()
941 err = xenbus_switch_state(pdev->xdev, XenbusStateClosed); in pcifront_try_disconnect()
950 int err = -EFAULT; in pcifront_attach_devices()
952 unsigned int domain, bus; in pcifront_attach_devices() local
955 if (xenbus_read_driver_state(pdev->xdev->nodename) != in pcifront_attach_devices()
959 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, in pcifront_attach_devices()
961 if (err == -ENOENT) { in pcifront_attach_devices()
962 xenbus_dev_error(pdev->xdev, err, in pcifront_attach_devices()
963 "No PCI Roots found, trying 0000:00"); in pcifront_attach_devices()
966 xenbus_dev_fatal(pdev->xdev, err, in pcifront_attach_devices()
967 "Error scanning PCI root 0000:00"); in pcifront_attach_devices()
973 err = -EINVAL; in pcifront_attach_devices()
974 xenbus_dev_fatal(pdev->xdev, err, in pcifront_attach_devices()
975 "Error reading number of PCI roots"); in pcifront_attach_devices()
980 len = snprintf(str, sizeof(str), "root-%d", i); in pcifront_attach_devices()
981 if (unlikely(len >= (sizeof(str) - 1))) { in pcifront_attach_devices()
982 err = -ENOMEM; in pcifront_attach_devices()
986 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str, in pcifront_attach_devices()
987 "%x:%x", &domain, &bus); in pcifront_attach_devices()
990 err = -EINVAL; in pcifront_attach_devices()
991 xenbus_dev_fatal(pdev->xdev, err, in pcifront_attach_devices()
992 "Error reading PCI root %d", i); in pcifront_attach_devices()
996 err = pcifront_rescan_root(pdev, domain, bus); in pcifront_attach_devices()
998 xenbus_dev_fatal(pdev->xdev, err, in pcifront_attach_devices()
999 "Error scanning PCI root %04x:%02x", in pcifront_attach_devices()
1000 domain, bus); in pcifront_attach_devices()
1005 xenbus_switch_state(pdev->xdev, XenbusStateConnected); in pcifront_attach_devices()
1015 unsigned int domain, bus, slot, func; in pcifront_detach_devices() local
1019 if (xenbus_read_driver_state(pdev->xdev->nodename) != in pcifront_detach_devices()
1023 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, "num_devs", "%d", in pcifront_detach_devices()
1027 err = -EINVAL; in pcifront_detach_devices()
1028 xenbus_dev_fatal(pdev->xdev, err, in pcifront_detach_devices()
1029 "Error reading number of PCI devices"); in pcifront_detach_devices()
1037 l = snprintf(str, sizeof(str), "state-%d", i); in pcifront_detach_devices()
1038 if (unlikely(l >= (sizeof(str) - 1))) { in pcifront_detach_devices()
1039 err = -ENOMEM; in pcifront_detach_devices()
1042 state = xenbus_read_unsigned(pdev->xdev->otherend, str, in pcifront_detach_devices()
1049 l = snprintf(str, sizeof(str), "vdev-%d", i); in pcifront_detach_devices()
1050 if (unlikely(l >= (sizeof(str) - 1))) { in pcifront_detach_devices()
1051 err = -ENOMEM; in pcifront_detach_devices()
1054 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str, in pcifront_detach_devices()
1055 "%x:%x:%x.%x", &domain, &bus, &slot, &func); in pcifront_detach_devices()
1058 err = -EINVAL; in pcifront_detach_devices()
1059 xenbus_dev_fatal(pdev->xdev, err, in pcifront_detach_devices()
1060 "Error reading PCI device %d", i); in pcifront_detach_devices()
1064 pci_dev = pci_get_domain_bus_and_slot(domain, bus, in pcifront_detach_devices()
1067 dev_dbg(&pdev->xdev->dev, in pcifront_detach_devices()
1068 "Cannot get PCI device %04x:%02x:%02x.%d\n", in pcifront_detach_devices()
1069 domain, bus, slot, func); in pcifront_detach_devices()
1077 dev_dbg(&pdev->xdev->dev, in pcifront_detach_devices()
1078 "PCI device %04x:%02x:%02x.%d removed.\n", in pcifront_detach_devices()
1079 domain, bus, slot, func); in pcifront_detach_devices()
1082 err = xenbus_switch_state(pdev->xdev, XenbusStateReconfiguring); in pcifront_detach_devices()
1091 struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev); in pcifront_backend_changed()
1105 if (xdev->state == XenbusStateClosed) in pcifront_backend_changed()
1109 dev_warn(&xdev->dev, "backend going away!\n"); in pcifront_backend_changed()
1130 err = -ENOMEM; in pcifront_xenbus_probe()
1146 struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev); in pcifront_xenbus_remove()
1155 {"pci"},
1170 return -ENODEV; in pcifront_init()
1173 return -ENODEV; in pcifront_init()
1188 MODULE_DESCRIPTION("Xen PCI passthrough frontend.");
1190 MODULE_ALIAS("xen:pci");