From c2cfbd70fea3737090397be943b8b876541e9f34 Mon Sep 17 00:00:00 2001 From: Jerome Duval Date: Fri, 9 Aug 2013 23:32:07 +0200 Subject: [PATCH] intel_extreme: add MSI support --- .../drivers/graphics/intel_extreme/driver.cpp | 17 ++++++++++ .../drivers/graphics/intel_extreme/driver.h | 1 + .../graphics/intel_extreme/intel_extreme.cpp | 33 ++++++++++++++++--- .../intel_extreme/intel_extreme_private.h | 3 ++ 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp index 2fa2ff48fc..cfe5b66c4c 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp @@ -103,6 +103,7 @@ int32 api_version = B_CUR_DRIVER_API_VERSION; char* gDeviceNames[MAX_CARDS + 1]; intel_info* gDeviceInfo[MAX_CARDS]; pci_module_info* gPCI; +pci_x86_module_info* gPCIx86Module = NULL; agp_gart_module_info* gGART; mutex gLock; @@ -185,6 +186,14 @@ init_driver(void) mutex_init(&gLock, "intel extreme ksync"); + // Try to get the PCI x86 module as well so we can enable possible MSIs. + if (get_module(B_PCI_X86_MODULE_NAME, + (module_info **)&gPCIx86Module) != B_OK) { + ERROR("failed to get pci x86 module\n"); + gPCIx86Module = NULL; + } + + // find devices int32 found = 0; @@ -240,6 +249,10 @@ init_driver(void) mutex_destroy(&gLock); put_module(B_AGP_GART_MODULE_NAME); put_module(B_PCI_MODULE_NAME); + if (gPCIx86Module != NULL) { + gPCIx86Module = NULL; + put_module(B_PCI_X86_MODULE_NAME); + } return ENODEV; } @@ -263,6 +276,10 @@ uninit_driver(void) put_module(B_AGP_GART_MODULE_NAME); put_module(B_PCI_MODULE_NAME); + if (gPCIx86Module != NULL) { + gPCIx86Module = NULL; + put_module(B_PCI_X86_MODULE_NAME); + } } diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h index 1c83e729ed..66cebef1a9 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h @@ -20,6 +20,7 @@ extern char* gDeviceNames[]; extern intel_info* gDeviceInfo[]; extern pci_module_info* gPCI; +extern pci_x86_module_info* gPCIx86Module; extern agp_gart_module_info* gGART; extern mutex gLock; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp index 3f50e2ab16..9c087b7e92 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp @@ -131,13 +131,30 @@ init_interrupt_handler(intel_info &info) status = B_ERROR; } - if (status == B_OK && info.pci->u.h0.interrupt_pin != 0x00 - && info.pci->u.h0.interrupt_line != 0xff) { + // Find the right interrupt vector, using MSIs if available. + info.irq = 0xff; + info.use_msi = false; + if (info.pci->u.h0.interrupt_pin != 0x00) + info.irq = info.pci->u.h0.interrupt_line; + if (gPCIx86Module != NULL && gPCIx86Module->get_msi_count(info.pci->bus, + info.pci->device, info.pci->function) >= 1) { + uint8 msiVector = 0; + if (gPCIx86Module->configure_msi(info.pci->bus, info.pci->device, + info.pci->function, 1, &msiVector) == B_OK + && gPCIx86Module->enable_msi(info.pci->bus, info.pci->device, + info.pci->function) == B_OK) { + ERROR("using message signaled interrupts\n"); + info.irq = msiVector; + info.use_msi = true; + } + } + + if (status == B_OK && info.irq != 0xff) { // we've gotten an interrupt line for us to use info.fake_interrupts = false; - status = install_io_interrupt_handler(info.pci->u.h0.interrupt_line, + status = install_io_interrupt_handler(info.irq, &intel_interrupt_handler, (void*)&info, 0); if (status == B_OK) { write32(info, INTEL_DISPLAY_A_PIPE_STATUS, @@ -384,8 +401,14 @@ intel_extreme_uninit(intel_info &info) write16(info, find_reg(info, INTEL_INTERRUPT_ENABLED), 0); write16(info, find_reg(info, INTEL_INTERRUPT_MASK), ~0); - remove_io_interrupt_handler(info.pci->u.h0.interrupt_line, - intel_interrupt_handler, &info); + remove_io_interrupt_handler(info.irq, intel_interrupt_handler, &info); + + if (info.use_msi && gPCIx86Module != NULL) { + gPCIx86Module->disable_msi(info.pci->bus, + info.pci->device, info.pci->function); + gPCIx86Module->unconfigure_msi(info.pci->bus, + info.pci->device, info.pci->function); + } } gGART->unmap_aperture(info.aperture); diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h index 4735393620..58c9fbaf33 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "intel_extreme.h" #include "lock.h" @@ -34,6 +35,8 @@ struct intel_info { struct overlay_registers* overlay_registers; bool fake_interrupts; + uint8 irq; + bool use_msi; const char* device_identifier; DeviceType device_type;