Lines Matching +full:msi +full:- +full:capable
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
59 * If the MSI-X table is located in the middle of a BAR then that MMIO
60 * region gets split into two segments - one segment above the MSI-X table
61 * and the other segment below the MSI-X table - with a hole in place of
62 * the MSI-X table so accesses to it can be trapped and emulated.
68 MALLOC_DEFINE(M_PPTMSIX, "pptmsix", "Passthru MSI-X resources");
94 } msi; member
133 * - be allowed by administrator to be used in this role in ppt_probe()
134 * - be an endpoint device in ppt_probe()
136 if ((dinfo->cfg.hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL) in ppt_probe()
143 * SR-IOV infrastructure specified as "ppt" passthrough devices. in ppt_probe()
164 ppt->dev = dev; in ppt_attach()
179 if (ppt->vm != NULL) in ppt_detach()
181 num_pptdevs--; in ppt_detach()
209 dev = ppt->dev; in ppt_find()
219 if (ppt->vm != vm) /* Make sure we own this device */ in ppt_find()
232 seg = &ppt->mmio[i]; in ppt_unmap_all_mmio()
233 if (seg->len == 0) in ppt_unmap_all_mmio()
235 (void)vm_unmap_mmio(vm, seg->gpa, seg->len); in ppt_unmap_all_mmio()
247 if (ppt->msi.num_msgs == 0) in ppt_teardown_msi()
250 for (i = 0; i < ppt->msi.num_msgs; i++) { in ppt_teardown_msi()
251 rid = ppt->msi.startrid + i; in ppt_teardown_msi()
252 res = ppt->msi.res[i]; in ppt_teardown_msi()
253 cookie = ppt->msi.cookie[i]; in ppt_teardown_msi()
256 bus_teardown_intr(ppt->dev, res, cookie); in ppt_teardown_msi()
259 bus_release_resource(ppt->dev, SYS_RES_IRQ, rid, res); in ppt_teardown_msi()
261 ppt->msi.res[i] = NULL; in ppt_teardown_msi()
262 ppt->msi.cookie[i] = NULL; in ppt_teardown_msi()
265 if (ppt->msi.startrid == 1) in ppt_teardown_msi()
266 pci_release_msi(ppt->dev); in ppt_teardown_msi()
268 ppt->msi.num_msgs = 0; in ppt_teardown_msi()
278 rid = ppt->msix.startrid + idx; in ppt_teardown_msix_intr()
279 res = ppt->msix.res[idx]; in ppt_teardown_msix_intr()
280 cookie = ppt->msix.cookie[idx]; in ppt_teardown_msix_intr()
283 bus_teardown_intr(ppt->dev, res, cookie); in ppt_teardown_msix_intr()
286 bus_release_resource(ppt->dev, SYS_RES_IRQ, rid, res); in ppt_teardown_msix_intr()
288 ppt->msix.res[idx] = NULL; in ppt_teardown_msix_intr()
289 ppt->msix.cookie[idx] = NULL; in ppt_teardown_msix_intr()
297 if (ppt->msix.num_msgs == 0) in ppt_teardown_msix()
300 for (i = 0; i < ppt->msix.num_msgs; i++) in ppt_teardown_msix()
303 free(ppt->msix.res, M_PPTMSIX); in ppt_teardown_msix()
304 free(ppt->msix.cookie, M_PPTMSIX); in ppt_teardown_msix()
305 free(ppt->msix.arg, M_PPTMSIX); in ppt_teardown_msix()
307 pci_release_msi(ppt->dev); in ppt_teardown_msix()
309 if (ppt->msix.msix_table_res) { in ppt_teardown_msix()
310 bus_release_resource(ppt->dev, SYS_RES_MEMORY, in ppt_teardown_msix()
311 ppt->msix.msix_table_rid, in ppt_teardown_msix()
312 ppt->msix.msix_table_res); in ppt_teardown_msix()
313 ppt->msix.msix_table_res = NULL; in ppt_teardown_msix()
314 ppt->msix.msix_table_rid = 0; in ppt_teardown_msix()
316 if (ppt->msix.msix_pba_res) { in ppt_teardown_msix()
317 bus_release_resource(ppt->dev, SYS_RES_MEMORY, in ppt_teardown_msix()
318 ppt->msix.msix_pba_rid, in ppt_teardown_msix()
319 ppt->msix.msix_pba_res); in ppt_teardown_msix()
320 ppt->msix.msix_pba_res = NULL; in ppt_teardown_msix()
321 ppt->msix.msix_pba_rid = 0; in ppt_teardown_msix()
324 ppt->msix.num_msgs = 0; in ppt_teardown_msix()
342 if (ppt->vm == vm) in ppt_assigned_devices()
356 if (ppt->vm != vm) in ppt_is_mmio()
360 seg = &ppt->mmio[i]; in ppt_is_mmio()
361 if (seg->len == 0) in ppt_is_mmio()
363 if (gpa >= seg->gpa && gpa < seg->gpa + seg->len) in ppt_is_mmio()
389 for (pm = pci_first_bar(ppt->dev); pm != NULL; pm = pci_next_bar(pm)) { in ppt_bar_enables()
390 if (PCI_BAR_IO(pm->pm_value)) in ppt_bar_enables()
392 if (PCI_BAR_MEM(pm->pm_value)) in ppt_bar_enables()
410 pci_save_state(ppt->dev); in ppt_assign_device()
411 ppt_pci_reset(ppt->dev); in ppt_assign_device()
412 pci_restore_state(ppt->dev); in ppt_assign_device()
413 ppt->vm = vm; in ppt_assign_device()
414 iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); in ppt_assign_device()
415 cmd = pci_read_config(ppt->dev, PCIR_COMMAND, 2); in ppt_assign_device()
417 pci_write_config(ppt->dev, PCIR_COMMAND, cmd, 2); in ppt_assign_device()
432 cmd = pci_read_config(ppt->dev, PCIR_COMMAND, 2); in ppt_unassign_device()
434 pci_write_config(ppt->dev, PCIR_COMMAND, cmd, 2); in ppt_unassign_device()
435 pci_save_state(ppt->dev); in ppt_unassign_device()
436 ppt_pci_reset(ppt->dev); in ppt_unassign_device()
437 pci_restore_state(ppt->dev); in ppt_unassign_device()
441 iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); in ppt_unassign_device()
442 ppt->vm = NULL; in ppt_unassign_device()
454 if (ppt->vm == vm) { in ppt_unassign_all()
455 dev = ppt->dev; in ppt_unassign_all()
472 for (pm = pci_first_bar(ppt->dev); pm != NULL; pm = pci_next_bar(pm)) { in ppt_valid_bar_mapping()
473 if (!PCI_BAR_MEM(pm->pm_value)) in ppt_valid_bar_mapping()
475 base = pm->pm_value & PCIM_BAR_MEM_BASE; in ppt_valid_bar_mapping()
476 size = (pci_addr_t)1 << pm->pm_size; in ppt_valid_bar_mapping()
503 seg = &ppt->mmio[i]; in ppt_map_mmio()
504 if (seg->len == 0) { in ppt_map_mmio()
507 seg->gpa = gpa; in ppt_map_mmio()
508 seg->len = len; in ppt_map_mmio()
529 seg = &ppt->mmio[i]; in ppt_unmap_mmio()
530 if (seg->gpa == gpa && seg->len == len) { in ppt_unmap_mmio()
531 error = vm_unmap_mmio(vm, seg->gpa, seg->len); in ppt_unmap_mmio()
533 seg->gpa = 0; in ppt_unmap_mmio()
534 seg->len = 0; in ppt_unmap_mmio()
549 ppt = pptarg->pptdev; in pptintr()
551 if (ppt->vm != NULL) in pptintr()
552 lapic_intr_msi(ppt->vm, pptarg->addr, pptarg->msg_data); in pptintr()
556 * This is not expected to happen - panic? in pptintr()
564 if (ppt->msi.startrid == 0) in pptintr()
585 /* Reject attempts to enable MSI while MSI-X is active. */ in ppt_setup_msi()
586 if (ppt->msix.num_msgs != 0 && numvec != 0) in ppt_setup_msi()
596 msi_count = pci_msi_count(ppt->dev); in ppt_setup_msi()
602 startrid = 1; /* MSI */ in ppt_setup_msi()
605 * The device must be capable of supporting the number of vectors in ppt_setup_msi()
612 * Make sure that we can allocate all the MSI vectors that are needed in ppt_setup_msi()
617 error = pci_alloc_msi(ppt->dev, &tmp); in ppt_setup_msi()
621 pci_release_msi(ppt->dev); in ppt_setup_msi()
628 ppt->msi.startrid = startrid; in ppt_setup_msi()
634 ppt->msi.num_msgs = i + 1; in ppt_setup_msi()
635 ppt->msi.cookie[i] = NULL; in ppt_setup_msi()
638 ppt->msi.res[i] = bus_alloc_resource_any(ppt->dev, SYS_RES_IRQ, in ppt_setup_msi()
640 if (ppt->msi.res[i] == NULL) in ppt_setup_msi()
643 ppt->msi.arg[i].pptdev = ppt; in ppt_setup_msi()
644 ppt->msi.arg[i].addr = addr; in ppt_setup_msi()
645 ppt->msi.arg[i].msg_data = msg + i; in ppt_setup_msi()
647 error = bus_setup_intr(ppt->dev, ppt->msi.res[i], in ppt_setup_msi()
649 pptintr, NULL, &ppt->msi.arg[i], in ppt_setup_msi()
650 &ppt->msi.cookie[i]); in ppt_setup_msi()
676 /* Reject attempts to enable MSI-X while MSI is active. */ in ppt_setup_msix()
677 if (ppt->msi.num_msgs != 0) in ppt_setup_msix()
680 dinfo = device_get_ivars(ppt->dev); in ppt_setup_msix()
685 * First-time configuration: in ppt_setup_msix()
686 * Allocate the MSI-X table in ppt_setup_msix()
688 * Set up some variables in ppt->msix in ppt_setup_msix()
690 if (ppt->msix.num_msgs == 0) { in ppt_setup_msix()
691 numvec = pci_msix_count(ppt->dev); in ppt_setup_msix()
695 ppt->msix.startrid = 1; in ppt_setup_msix()
696 ppt->msix.num_msgs = numvec; in ppt_setup_msix()
698 res_size = numvec * sizeof(ppt->msix.res[0]); in ppt_setup_msix()
699 cookie_size = numvec * sizeof(ppt->msix.cookie[0]); in ppt_setup_msix()
700 arg_size = numvec * sizeof(ppt->msix.arg[0]); in ppt_setup_msix()
702 ppt->msix.res = malloc(res_size, M_PPTMSIX, M_WAITOK | M_ZERO); in ppt_setup_msix()
703 ppt->msix.cookie = malloc(cookie_size, M_PPTMSIX, in ppt_setup_msix()
705 ppt->msix.arg = malloc(arg_size, M_PPTMSIX, M_WAITOK | M_ZERO); in ppt_setup_msix()
707 rid = dinfo->cfg.msix.msix_table_bar; in ppt_setup_msix()
708 ppt->msix.msix_table_res = bus_alloc_resource_any(ppt->dev, in ppt_setup_msix()
711 if (ppt->msix.msix_table_res == NULL) { in ppt_setup_msix()
715 ppt->msix.msix_table_rid = rid; in ppt_setup_msix()
717 if (dinfo->cfg.msix.msix_table_bar != in ppt_setup_msix()
718 dinfo->cfg.msix.msix_pba_bar) { in ppt_setup_msix()
719 rid = dinfo->cfg.msix.msix_pba_bar; in ppt_setup_msix()
720 ppt->msix.msix_pba_res = bus_alloc_resource_any( in ppt_setup_msix()
721 ppt->dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); in ppt_setup_msix()
723 if (ppt->msix.msix_pba_res == NULL) { in ppt_setup_msix()
727 ppt->msix.msix_pba_rid = rid; in ppt_setup_msix()
731 error = pci_alloc_msix(ppt->dev, &alloced); in ppt_setup_msix()
743 ppt->msix.cookie[idx] = NULL; in ppt_setup_msix()
744 rid = ppt->msix.startrid + idx; in ppt_setup_msix()
745 ppt->msix.res[idx] = bus_alloc_resource_any(ppt->dev, SYS_RES_IRQ, in ppt_setup_msix()
747 if (ppt->msix.res[idx] == NULL) in ppt_setup_msix()
750 ppt->msix.arg[idx].pptdev = ppt; in ppt_setup_msix()
751 ppt->msix.arg[idx].addr = addr; in ppt_setup_msix()
752 ppt->msix.arg[idx].msg_data = msg; in ppt_setup_msix()
754 /* Setup the MSI-X interrupt */ in ppt_setup_msix()
755 error = bus_setup_intr(ppt->dev, ppt->msix.res[idx], in ppt_setup_msix()
757 pptintr, NULL, &ppt->msix.arg[idx], in ppt_setup_msix()
758 &ppt->msix.cookie[idx]); in ppt_setup_msix()
761 bus_release_resource(ppt->dev, SYS_RES_IRQ, rid, ppt->msix.res[idx]); in ppt_setup_msix()
762 ppt->msix.cookie[idx] = NULL; in ppt_setup_msix()
763 ppt->msix.res[idx] = NULL; in ppt_setup_msix()