FreeBSD compat layer: implement MSI-X support.
This commit is contained in:
@@ -56,7 +56,6 @@ struct internal_intr {
|
|||||||
void *arg;
|
void *arg;
|
||||||
int irq;
|
int irq;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
bool is_msi;
|
|
||||||
|
|
||||||
thread_id thread;
|
thread_id thread;
|
||||||
sem_id sem;
|
sem_id sem;
|
||||||
@@ -170,8 +169,6 @@ bus_alloc_resource(device_t dev, int type, int *rid, unsigned long start,
|
|||||||
res->r_bustag = 1;
|
res->r_bustag = 1;
|
||||||
res->r_bushandle = info->u.h0.interrupt_line + *rid - 1;
|
res->r_bushandle = info->u.h0.interrupt_line + *rid - 1;
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
||||||
// TODO: msi-x interrupts
|
|
||||||
}
|
}
|
||||||
} else if (type == SYS_RES_MEMORY)
|
} else if (type == SYS_RES_MEMORY)
|
||||||
result = bus_alloc_mem_resource(dev, res, *rid);
|
result = bus_alloc_mem_resource(dev, res, *rid);
|
||||||
@@ -349,7 +346,6 @@ bus_setup_intr(device_t dev, struct resource *res, int flags,
|
|||||||
intr->arg = arg;
|
intr->arg = arg;
|
||||||
intr->irq = res->r_bushandle;
|
intr->irq = res->r_bushandle;
|
||||||
intr->flags = flags;
|
intr->flags = flags;
|
||||||
intr->is_msi = false;
|
|
||||||
intr->sem = -1;
|
intr->sem = -1;
|
||||||
intr->thread = -1;
|
intr->thread = -1;
|
||||||
|
|
||||||
@@ -386,14 +382,21 @@ bus_setup_intr(device_t dev, struct resource *res, int flags,
|
|||||||
// this is an msi, enable it
|
// this is an msi, enable it
|
||||||
pci_info *info
|
pci_info *info
|
||||||
= &((struct root_device_softc *)dev->root->softc)->pci_info;
|
= &((struct root_device_softc *)dev->root->softc)->pci_info;
|
||||||
if (gPCIx86->enable_msi(info->bus, info->device,
|
if (&((struct root_device_softc *)dev->root->softc)->is_msi) {
|
||||||
info->function) != B_OK) {
|
if (gPCIx86->enable_msi(info->bus, info->device,
|
||||||
device_printf(dev, "enabling msi failed\n");
|
info->function) != B_OK) {
|
||||||
bus_teardown_intr(dev, res, intr);
|
device_printf(dev, "enabling msi failed\n");
|
||||||
return ENODEV;
|
bus_teardown_intr(dev, res, intr);
|
||||||
|
return ENODEV;
|
||||||
|
}
|
||||||
|
} else if (&((struct root_device_softc *)dev->root->softc)->is_msix) {
|
||||||
|
if (gPCIx86->enable_msix(info->bus, info->device,
|
||||||
|
info->function) != B_OK) {
|
||||||
|
device_printf(dev, "enabling msix failed\n");
|
||||||
|
bus_teardown_intr(dev, res, intr);
|
||||||
|
return ENODEV;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
intr->is_msi = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
@@ -412,11 +415,11 @@ int
|
|||||||
bus_teardown_intr(device_t dev, struct resource *res, void *arg)
|
bus_teardown_intr(device_t dev, struct resource *res, void *arg)
|
||||||
{
|
{
|
||||||
struct internal_intr *intr = (struct internal_intr *)arg;
|
struct internal_intr *intr = (struct internal_intr *)arg;
|
||||||
|
struct root_device_softc *root = (struct root_device_softc *)dev->root->softc;
|
||||||
|
|
||||||
if (intr->is_msi && gPCIx86 != NULL) {
|
if ((root->is_msi || root->is_msix) && gPCIx86 != NULL) {
|
||||||
// disable msi generation
|
// disable msi generation
|
||||||
pci_info *info
|
pci_info *info = &root->pci_info;
|
||||||
= &((struct root_device_softc *)dev->root->softc)->pci_info;
|
|
||||||
gPCIx86->disable_msi(info->bus, info->device, info->function);
|
gPCIx86->disable_msi(info->bus, info->device, info->function);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,14 +616,14 @@ pci_get_domain(device_t dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
pci_get_devid(device_t dev)
|
pci_get_devid(device_t dev)
|
||||||
{
|
{
|
||||||
return pci_read_config(dev, PCI_device_id, 2) << 16 |
|
return pci_read_config(dev, PCI_device_id, 2) << 16 |
|
||||||
pci_read_config(dev, PCI_vendor_id, 2);
|
pci_read_config(dev, PCI_vendor_id, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pci_get_cachelnsz(device_t dev)
|
pci_get_cachelnsz(device_t dev)
|
||||||
{
|
{
|
||||||
return pci_read_config(dev, PCI_line_size, 1);
|
return pci_read_config(dev, PCI_line_size, 1);
|
||||||
@@ -787,6 +790,7 @@ pci_alloc_msi(device_t dev, int *count)
|
|||||||
return ENODEV;
|
return ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
((struct root_device_softc *)dev->root->softc)->is_msi = true;
|
||||||
info->u.h0.interrupt_line = startVector;
|
info->u.h0.interrupt_line = startVector;
|
||||||
return EOK;
|
return EOK;
|
||||||
}
|
}
|
||||||
@@ -801,6 +805,8 @@ pci_release_msi(device_t dev)
|
|||||||
|
|
||||||
info = &((struct root_device_softc *)dev->root->softc)->pci_info;
|
info = &((struct root_device_softc *)dev->root->softc)->pci_info;
|
||||||
gPCIx86->unconfigure_msi(info->bus, info->device, info->function);
|
gPCIx86->unconfigure_msi(info->bus, info->device, info->function);
|
||||||
|
((struct root_device_softc *)dev->root->softc)->is_msi = false;
|
||||||
|
((struct root_device_softc *)dev->root->softc)->is_msix = false;
|
||||||
return EOK;
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -808,14 +814,33 @@ pci_release_msi(device_t dev)
|
|||||||
int
|
int
|
||||||
pci_msix_count(device_t dev)
|
pci_msix_count(device_t dev)
|
||||||
{
|
{
|
||||||
return 0;
|
pci_info *info;
|
||||||
|
if (gPCIx86 == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
info = &((struct root_device_softc *)dev->root->softc)->pci_info;
|
||||||
|
return gPCIx86->get_msix_count(info->bus, info->device, info->function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
pci_alloc_msix(device_t dev, int *count)
|
pci_alloc_msix(device_t dev, int *count)
|
||||||
{
|
{
|
||||||
return ENODEV;
|
pci_info *info;
|
||||||
|
uint8 startVector = 0;
|
||||||
|
if (gPCIx86 == NULL)
|
||||||
|
return ENODEV;
|
||||||
|
|
||||||
|
info = &((struct root_device_softc *)dev->root->softc)->pci_info;
|
||||||
|
|
||||||
|
if (gPCIx86->configure_msix(info->bus, info->device, info->function, *count,
|
||||||
|
&startVector) != B_OK) {
|
||||||
|
return ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
((struct root_device_softc *)dev->root->softc)->is_msix = true;
|
||||||
|
info->u.h0.interrupt_line = startVector;
|
||||||
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ extern "C" {
|
|||||||
|
|
||||||
struct root_device_softc {
|
struct root_device_softc {
|
||||||
struct pci_info pci_info;
|
struct pci_info pci_info;
|
||||||
|
bool is_msi;
|
||||||
|
bool is_msix;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|||||||
Reference in New Issue
Block a user