From 872226839cac3c72ed30dc23f5d8b531e365d7cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= <jerome.duval@gmail.com>
Date: Mon, 29 Jul 2013 23:04:45 +0200
Subject: [PATCH] FreeBSD compat layer: implement MSI-X support.
---
src/libs/compat/freebsd_network/bus.cpp | 61 ++++++++++++++++++++++----------
src/libs/compat/freebsd_network/device.h | 2 ++
2 files changed, 45 insertions(+), 18 deletions(-)
diff --git a/src/libs/compat/freebsd_network/bus.cpp b/src/libs/compat/freebsd_network/bus.cpp
index 22aed56..3353471 100644
a
|
b
|
struct internal_intr {
|
56 | 56 | void *arg; |
57 | 57 | int irq; |
58 | 58 | uint32 flags; |
59 | | bool is_msi; |
60 | 59 | |
61 | 60 | thread_id thread; |
62 | 61 | sem_id sem; |
… |
… |
bus_alloc_resource(device_t dev, int type, int *rid, unsigned long start,
|
170 | 169 | res->r_bustag = 1; |
171 | 170 | res->r_bushandle = info->u.h0.interrupt_line + *rid - 1; |
172 | 171 | result = 0; |
173 | | |
174 | | // TODO: msi-x interrupts |
175 | 172 | } |
176 | 173 | } else if (type == SYS_RES_MEMORY) |
177 | 174 | result = bus_alloc_mem_resource(dev, res, *rid); |
… |
… |
bus_setup_intr(device_t dev, struct resource *res, int flags,
|
349 | 346 | intr->arg = arg; |
350 | 347 | intr->irq = res->r_bushandle; |
351 | 348 | intr->flags = flags; |
352 | | intr->is_msi = false; |
353 | 349 | intr->sem = -1; |
354 | 350 | intr->thread = -1; |
355 | 351 | |
… |
… |
bus_setup_intr(device_t dev, struct resource *res, int flags,
|
386 | 382 | // this is an msi, enable it |
387 | 383 | pci_info *info |
388 | 384 | = &((struct root_device_softc *)dev->root->softc)->pci_info; |
389 | | if (gPCIx86->enable_msi(info->bus, info->device, |
390 | | info->function) != B_OK) { |
391 | | device_printf(dev, "enabling msi failed\n"); |
392 | | bus_teardown_intr(dev, res, intr); |
393 | | return ENODEV; |
| 385 | if (&((struct root_device_softc *)dev->root->softc)->is_msi) { |
| 386 | if (gPCIx86->enable_msi(info->bus, info->device, |
| 387 | info->function) != B_OK) { |
| 388 | device_printf(dev, "enabling msi failed\n"); |
| 389 | bus_teardown_intr(dev, res, intr); |
| 390 | return ENODEV; |
| 391 | } |
| 392 | } else if (&((struct root_device_softc *)dev->root->softc)->is_msix) { |
| 393 | if (gPCIx86->enable_msix(info->bus, info->device, |
| 394 | info->function) != B_OK) { |
| 395 | device_printf(dev, "enabling msix failed\n"); |
| 396 | bus_teardown_intr(dev, res, intr); |
| 397 | return ENODEV; |
| 398 | } |
394 | 399 | } |
395 | | |
396 | | intr->is_msi = true; |
397 | 400 | } |
398 | 401 | |
399 | 402 | if (status < B_OK) { |
… |
… |
int
|
412 | 415 | bus_teardown_intr(device_t dev, struct resource *res, void *arg) |
413 | 416 | { |
414 | 417 | struct internal_intr *intr = (struct internal_intr *)arg; |
| 418 | struct root_device_softc *root = (struct root_device_softc *)dev->root->softc; |
415 | 419 | |
416 | | if (intr->is_msi && gPCIx86 != NULL) { |
| 420 | if ((root->is_msi || root->is_msix) && gPCIx86 != NULL) { |
417 | 421 | // disable msi generation |
418 | | pci_info *info |
419 | | = &((struct root_device_softc *)dev->root->softc)->pci_info; |
| 422 | pci_info *info = &root->pci_info; |
420 | 423 | gPCIx86->disable_msi(info->bus, info->device, info->function); |
421 | 424 | } |
422 | 425 | |
… |
… |
pci_get_domain(device_t dev)
|
613 | 616 | return 0; |
614 | 617 | } |
615 | 618 | |
616 | | uint32_t |
| 619 | uint32_t |
617 | 620 | pci_get_devid(device_t dev) |
618 | 621 | { |
619 | 622 | return pci_read_config(dev, PCI_device_id, 2) << 16 | |
620 | 623 | pci_read_config(dev, PCI_vendor_id, 2); |
621 | 624 | } |
622 | 625 | |
623 | | uint8_t |
| 626 | uint8_t |
624 | 627 | pci_get_cachelnsz(device_t dev) |
625 | 628 | { |
626 | 629 | return pci_read_config(dev, PCI_line_size, 1); |
… |
… |
pci_alloc_msi(device_t dev, int *count)
|
787 | 790 | return ENODEV; |
788 | 791 | } |
789 | 792 | |
| 793 | ((struct root_device_softc *)dev->root->softc)->is_msi = true; |
790 | 794 | info->u.h0.interrupt_line = startVector; |
791 | 795 | return EOK; |
792 | 796 | } |
… |
… |
pci_release_msi(device_t dev)
|
801 | 805 | |
802 | 806 | info = &((struct root_device_softc *)dev->root->softc)->pci_info; |
803 | 807 | gPCIx86->unconfigure_msi(info->bus, info->device, info->function); |
| 808 | ((struct root_device_softc *)dev->root->softc)->is_msi = false; |
| 809 | ((struct root_device_softc *)dev->root->softc)->is_msix = false; |
804 | 810 | return EOK; |
805 | 811 | } |
806 | 812 | |
… |
… |
pci_release_msi(device_t dev)
|
808 | 814 | int |
809 | 815 | pci_msix_count(device_t dev) |
810 | 816 | { |
811 | | return 0; |
| 817 | pci_info *info; |
| 818 | if (gPCIx86 == NULL) |
| 819 | return 0; |
| 820 | |
| 821 | info = &((struct root_device_softc *)dev->root->softc)->pci_info; |
| 822 | return gPCIx86->get_msix_count(info->bus, info->device, info->function); |
812 | 823 | } |
813 | 824 | |
814 | 825 | |
815 | 826 | int |
816 | 827 | pci_alloc_msix(device_t dev, int *count) |
817 | 828 | { |
818 | | return ENODEV; |
| 829 | pci_info *info; |
| 830 | uint8 startVector = 0; |
| 831 | if (gPCIx86 == NULL) |
| 832 | return ENODEV; |
| 833 | |
| 834 | info = &((struct root_device_softc *)dev->root->softc)->pci_info; |
| 835 | |
| 836 | if (gPCIx86->configure_msix(info->bus, info->device, info->function, *count, |
| 837 | &startVector) != B_OK) { |
| 838 | return ENODEV; |
| 839 | } |
| 840 | |
| 841 | ((struct root_device_softc *)dev->root->softc)->is_msix = true; |
| 842 | info->u.h0.interrupt_line = startVector; |
| 843 | return EOK; |
819 | 844 | } |
820 | 845 | |
821 | 846 | |
diff --git a/src/libs/compat/freebsd_network/device.h b/src/libs/compat/freebsd_network/device.h
index 481d4d4..9a63201 100644
a
|
b
|
extern "C" {
|
30 | 30 | |
31 | 31 | struct root_device_softc { |
32 | 32 | struct pci_info pci_info; |
| 33 | bool is_msi; |
| 34 | bool is_msix; |
33 | 35 | }; |
34 | 36 | |
35 | 37 | enum { |