Revision fd704adc
b/hw/vfio_pci.c | ||
---|---|---|
72 | 72 |
}; |
73 | 73 |
|
74 | 74 |
ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); |
75 |
|
|
76 |
vdev->interrupt = VFIO_INT_NONE; |
|
77 | 75 |
} |
78 | 76 |
|
79 | 77 |
/* |
... | ... | |
278 | 276 |
|
279 | 277 |
g_free(irq_set); |
280 | 278 |
|
281 |
if (!ret) { |
|
282 |
vdev->interrupt = msix ? VFIO_INT_MSIX : VFIO_INT_MSI; |
|
283 |
} |
|
284 |
|
|
285 | 279 |
return ret; |
286 | 280 |
} |
287 | 281 |
|
... | ... | |
296 | 290 |
vdev->host.domain, vdev->host.bus, vdev->host.slot, |
297 | 291 |
vdev->host.function, nr); |
298 | 292 |
|
299 |
if (vdev->interrupt != VFIO_INT_MSIX) { |
|
300 |
vfio_disable_interrupts(vdev); |
|
301 |
} |
|
302 |
|
|
303 |
if (!vdev->msi_vectors) { |
|
304 |
vdev->msi_vectors = g_malloc0(vdev->msix->entries * |
|
305 |
sizeof(VFIOMSIVector)); |
|
306 |
} |
|
307 |
|
|
308 | 293 |
vector = &vdev->msi_vectors[nr]; |
309 | 294 |
vector->vdev = vdev; |
310 | 295 |
vector->use = true; |
... | ... | |
457 | 442 |
pci_set_word(config + PCI_MSI_FLAGS, flags); |
458 | 443 |
} |
459 | 444 |
|
445 |
static void vfio_enable_msix(VFIODevice *vdev) |
|
446 |
{ |
|
447 |
vfio_disable_interrupts(vdev); |
|
448 |
|
|
449 |
vdev->msi_vectors = g_malloc0(vdev->msix->entries * sizeof(VFIOMSIVector)); |
|
450 |
|
|
451 |
vdev->interrupt = VFIO_INT_MSIX; |
|
452 |
|
|
453 |
if (msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use, |
|
454 |
vfio_msix_vector_release)) { |
|
455 |
error_report("vfio: msix_set_vector_notifiers failed\n"); |
|
456 |
} |
|
457 |
|
|
458 |
DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, |
|
459 |
vdev->host.bus, vdev->host.slot, vdev->host.function); |
|
460 |
} |
|
461 |
|
|
460 | 462 |
static void vfio_enable_msi(VFIODevice *vdev) |
461 | 463 |
{ |
462 | 464 |
int ret, i; |
... | ... | |
529 | 531 |
|
530 | 532 |
msi_set_qsize(&vdev->pdev, vdev->nr_vectors); |
531 | 533 |
|
534 |
vdev->interrupt = VFIO_INT_MSI; |
|
535 |
|
|
532 | 536 |
DPRINTF("%s(%04x:%02x:%02x.%x) Enabled %d MSI vectors\n", __func__, |
533 | 537 |
vdev->host.domain, vdev->host.bus, vdev->host.slot, |
534 | 538 |
vdev->host.function, vdev->nr_vectors); |
535 | 539 |
} |
536 | 540 |
|
537 |
static void vfio_disable_msi_x(VFIODevice *vdev, bool msix) |
|
541 |
static void vfio_disable_msi_common(VFIODevice *vdev) |
|
542 |
{ |
|
543 |
g_free(vdev->msi_vectors); |
|
544 |
vdev->msi_vectors = NULL; |
|
545 |
vdev->nr_vectors = 0; |
|
546 |
vdev->interrupt = VFIO_INT_NONE; |
|
547 |
|
|
548 |
vfio_enable_intx(vdev); |
|
549 |
} |
|
550 |
|
|
551 |
static void vfio_disable_msix(VFIODevice *vdev) |
|
552 |
{ |
|
553 |
msix_unset_vector_notifiers(&vdev->pdev); |
|
554 |
|
|
555 |
if (vdev->nr_vectors) { |
|
556 |
vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX); |
|
557 |
} |
|
558 |
|
|
559 |
vfio_disable_msi_common(vdev); |
|
560 |
|
|
561 |
DPRINTF("%s(%04x:%02x:%02x.%x, msi%s)\n", __func__, |
|
562 |
vdev->host.domain, vdev->host.bus, vdev->host.slot, |
|
563 |
vdev->host.function, msix ? "x" : ""); |
|
564 |
} |
|
565 |
|
|
566 |
static void vfio_disable_msi(VFIODevice *vdev) |
|
538 | 567 |
{ |
539 | 568 |
int i; |
540 | 569 |
|
541 |
vfio_disable_irqindex(vdev, msix ? VFIO_PCI_MSIX_IRQ_INDEX : |
|
542 |
VFIO_PCI_MSI_IRQ_INDEX); |
|
570 |
vfio_disable_irqindex(vdev, VFIO_PCI_MSI_IRQ_INDEX); |
|
543 | 571 |
|
544 | 572 |
for (i = 0; i < vdev->nr_vectors; i++) { |
545 | 573 |
VFIOMSIVector *vector = &vdev->msi_vectors[i]; |
... | ... | |
558 | 586 |
NULL, NULL, NULL); |
559 | 587 |
} |
560 | 588 |
|
561 |
if (msix) { |
|
562 |
msix_vector_unuse(&vdev->pdev, i); |
|
563 |
} |
|
564 |
|
|
565 | 589 |
event_notifier_cleanup(&vector->interrupt); |
566 | 590 |
} |
567 | 591 |
|
568 |
g_free(vdev->msi_vectors); |
|
569 |
vdev->msi_vectors = NULL; |
|
570 |
vdev->nr_vectors = 0; |
|
571 |
|
|
572 |
if (!msix) { |
|
573 |
msi_set_qsize(&vdev->pdev, 0); /* Actually still means 1 vector */ |
|
574 |
} |
|
592 |
vfio_disable_msi_common(vdev); |
|
575 | 593 |
|
576 |
DPRINTF("%s(%04x:%02x:%02x.%x, msi%s)\n", __func__, |
|
577 |
vdev->host.domain, vdev->host.bus, vdev->host.slot, |
|
578 |
vdev->host.function, msix ? "x" : ""); |
|
594 |
msi_set_qsize(&vdev->pdev, 0); /* Actually still means 1 vector */ |
|
579 | 595 |
|
580 |
vfio_enable_intx(vdev); |
|
596 |
DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, |
|
597 |
vdev->host.bus, vdev->host.slot, vdev->host.function); |
|
581 | 598 |
} |
582 | 599 |
|
583 | 600 |
/* |
... | ... | |
763 | 780 |
if (!was_enabled && is_enabled) { |
764 | 781 |
vfio_enable_msi(vdev); |
765 | 782 |
} else if (was_enabled && !is_enabled) { |
766 |
vfio_disable_msi_x(vdev, false);
|
|
783 |
vfio_disable_msi(vdev);
|
|
767 | 784 |
} |
768 | 785 |
} |
769 | 786 |
|
... | ... | |
776 | 793 |
is_enabled = msix_enabled(pdev); |
777 | 794 |
|
778 | 795 |
if (!was_enabled && is_enabled) { |
779 |
/* vfio_msix_vector_use handles this automatically */
|
|
796 |
vfio_enable_msix(vdev);
|
|
780 | 797 |
} else if (was_enabled && !is_enabled) { |
781 |
vfio_disable_msi_x(vdev, true);
|
|
798 |
vfio_disable_msix(vdev);
|
|
782 | 799 |
} |
783 | 800 |
} |
784 | 801 |
} |
... | ... | |
973 | 990 |
vfio_disable_intx(vdev); |
974 | 991 |
break; |
975 | 992 |
case VFIO_INT_MSI: |
976 |
vfio_disable_msi_x(vdev, false);
|
|
993 |
vfio_disable_msi(vdev);
|
|
977 | 994 |
break; |
978 | 995 |
case VFIO_INT_MSIX: |
979 |
vfio_disable_msi_x(vdev, true);
|
|
996 |
vfio_disable_msix(vdev);
|
|
980 | 997 |
break; |
981 | 998 |
} |
982 | 999 |
} |
... | ... | |
1094 | 1111 |
return ret; |
1095 | 1112 |
} |
1096 | 1113 |
|
1097 |
ret = msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use, |
|
1098 |
vfio_msix_vector_release); |
|
1099 |
if (ret) { |
|
1100 |
error_report("vfio: msix_set_vector_notifiers failed %d\n", ret); |
|
1101 |
msix_uninit(&vdev->pdev, &vdev->bars[vdev->msix->table_bar].mem, |
|
1102 |
&vdev->bars[vdev->msix->pba_bar].mem); |
|
1103 |
return ret; |
|
1104 |
} |
|
1105 |
|
|
1106 | 1114 |
return 0; |
1107 | 1115 |
} |
1108 | 1116 |
|
... | ... | |
1111 | 1119 |
msi_uninit(&vdev->pdev); |
1112 | 1120 |
|
1113 | 1121 |
if (vdev->msix) { |
1114 |
/* FIXME: Why can't unset just silently do nothing?? */ |
|
1115 |
if (vdev->pdev.msix_vector_use_notifier && |
|
1116 |
vdev->pdev.msix_vector_release_notifier) { |
|
1117 |
msix_unset_vector_notifiers(&vdev->pdev); |
|
1118 |
} |
|
1119 |
|
|
1120 | 1122 |
msix_uninit(&vdev->pdev, &vdev->bars[vdev->msix->table_bar].mem, |
1121 | 1123 |
&vdev->bars[vdev->msix->pba_bar].mem); |
1122 | 1124 |
} |
Also available in: Unified diff