pci: extend MSI interrupt vector number to 32 bits

Also increase MSI message data size to 32 bits according to PCIe spec.

Remove 0xff check for MSI interrupts because it is potentially valid
interrupt vector number. Reject 0xff only for legacy pin interrupts.

- MSI-X supports up to 2048 interrupts per device that do not fit to
`uint8`.

- Non-x86 systems may use separate interrupt vector ranges for
hard-wired interrupts and MSI interrupts so `uint8` is not enough to
represent all of them.

Change-Id: Iaf9ffb197ec23db0f97ffe3ea756d28d7bfc8705
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7433
Reviewed-by: waddlesplash <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
X512
2024-02-28 23:17:42 +00:00
committed by waddlesplash
parent da24b14bf2
commit 629f071bb9
31 changed files with 143 additions and 106 deletions
+6 -6
View File
@@ -186,7 +186,7 @@ struct pci_module_info {
status_t (*get_powerstate)(uint8 bus, uint8 device, uint8 function, uint8* state);
status_t (*set_powerstate)(uint8 bus, uint8 device, uint8 function, uint8 newState);
uint8 (*get_msi_count)(
uint32 (*get_msi_count)(
uint8 bus, /* bus number */
uint8 device, /* device # on bus */
uint8 function); /* function # in device */
@@ -195,8 +195,8 @@ struct pci_module_info {
uint8 bus, /* bus number */
uint8 device, /* device # on bus */
uint8 function, /* function # in device */
uint8 count, /* count of vectors desired */
uint8 *startVector); /* first configured vector */
uint32 count, /* count of vectors desired */
uint32 *startVector); /* first configured vector */
status_t (*unconfigure_msi)(
uint8 bus, /* bus number */
uint8 device, /* device # on bus */
@@ -211,7 +211,7 @@ struct pci_module_info {
uint8 device, /* device # on bus */
uint8 function); /* function # in device */
uint8 (*get_msix_count)(
uint32 (*get_msix_count)(
uint8 bus, /* bus number */
uint8 device, /* device # on bus */
uint8 function); /* function # in device */
@@ -220,8 +220,8 @@ struct pci_module_info {
uint8 bus, /* bus number */
uint8 device, /* device # on bus */
uint8 function, /* function # in device */
uint8 count, /* count of vectors desired */
uint8 *startVector); /* first configured vector */
uint32 count, /* count of vectors desired */
uint32 *startVector); /* first configured vector */
status_t (*enable_msix)(
uint8 bus, /* bus number */
uint8 device, /* device # on bus */
+6 -6
View File
@@ -40,19 +40,19 @@ typedef struct pci_device_module_info {
void (*set_powerstate)(pci_device *device, uint8 state);
// MSI/MSI-X
uint8 (*get_msi_count)(pci_device *device);
uint32 (*get_msi_count)(pci_device *device);
status_t (*configure_msi)(pci_device *device,
uint8 count,
uint8 *startVector);
uint32 count,
uint32 *startVector);
status_t (*unconfigure_msi)(pci_device *device);
status_t (*enable_msi)(pci_device *device);
status_t (*disable_msi)(pci_device *device);
uint8 (*get_msix_count)(pci_device *device);
uint32 (*get_msix_count)(pci_device *device);
status_t (*configure_msix)(pci_device *device,
uint8 count,
uint8 *startVector);
uint32 count,
uint32 *startVector);
status_t (*enable_msix)(pci_device *device);
} pci_device_module_info;
+5 -5
View File
@@ -13,8 +13,8 @@
class MSIInterface {
public:
virtual status_t AllocateVectors(
uint8 count, uint8& startVector, uint64& address, uint16& data) = 0;
virtual void FreeVectors(uint8 count, uint8 startVector) = 0;
uint32 count, uint32& startVector, uint64& address, uint32& data) = 0;
virtual void FreeVectors(uint32 count, uint32 startVector) = 0;
};
@@ -23,9 +23,9 @@ void msi_set_interface(MSIInterface* interface);
#endif
bool msi_supported();
status_t msi_allocate_vectors(uint8 count, uint8 *startVector,
uint64 *address, uint16 *data);
void msi_free_vectors(uint8 count, uint8 startVector);
status_t msi_allocate_vectors(uint32 count, uint32 *startVector,
uint64 *address, uint32 *data);
void msi_free_vectors(uint32 count, uint32 startVector);
#ifdef __cplusplus
}
+1 -1
View File
@@ -24,7 +24,7 @@
#define MSI_DELIVERY_MODE_EXT_INT 0x00000700
void msi_assign_interrupt_to_cpu(uint8 irq, int32 cpu);
void msi_assign_interrupt_to_cpu(uint32 irq, int32 cpu);
#endif // _KERNEL_ARCH_x86_MSI_H
+5 -5
View File
@@ -1917,7 +1917,7 @@ PCI::SetPowerstate(uint8 domain, uint8 bus, uint8 _device, uint8 function,
//#pragma mark - MSI
uint8
uint32
PCI::GetMSICount(PCIDev *device)
{
if (!msi_supported())
@@ -1932,7 +1932,7 @@ PCI::GetMSICount(PCIDev *device)
status_t
PCI::ConfigureMSI(PCIDev *device, uint8 count, uint8 *startVector)
PCI::ConfigureMSI(PCIDev *device, uint32 count, uint32 *startVector)
{
if (!msi_supported())
return B_UNSUPPORTED;
@@ -2070,7 +2070,7 @@ PCI::DisableMSI(PCIDev *device)
}
uint8
uint32
PCI::GetMSIXCount(PCIDev *device)
{
if (!msi_supported())
@@ -2085,7 +2085,7 @@ PCI::GetMSIXCount(PCIDev *device)
status_t
PCI::ConfigureMSIX(PCIDev *device, uint8 count, uint8 *startVector)
PCI::ConfigureMSIX(PCIDev *device, uint32 count, uint32 *startVector)
{
if (!msi_supported())
return B_UNSUPPORTED;
@@ -2170,7 +2170,7 @@ PCI::ConfigureMSIX(PCIDev *device, uint8 count, uint8 *startVector)
info->configured_count = count;
*startVector = info->start_vector;
dprintf("msix configured for %d vectors\n", count);
dprintf("msix configured for %" B_PRIu32 " vectors\n", count);
return B_OK;
}
+4 -4
View File
@@ -140,13 +140,13 @@ public:
uint8 device, uint8 function,
uint8 newInterruptLineValue);
uint8 GetMSICount(PCIDev *device);
status_t ConfigureMSI(PCIDev *device, uint8 count, uint8 *startVector);
uint32 GetMSICount(PCIDev *device);
status_t ConfigureMSI(PCIDev *device, uint32 count, uint32 *startVector);
status_t UnconfigureMSI(PCIDev *device);
status_t EnableMSI(PCIDev *device);
status_t DisableMSI(PCIDev *device);
uint8 GetMSIXCount(PCIDev *device);
status_t ConfigureMSIX(PCIDev *device, uint8 count, uint8 *startVector);
uint32 GetMSIXCount(PCIDev *device);
status_t ConfigureMSIX(PCIDev *device, uint32 count, uint32 *startVector);
status_t EnableMSIX(PCIDev *device);
private:
@@ -134,7 +134,7 @@ pci_device_module_info gPCIDeviceModule = {
.get_msi_count = [](pci_device *device) {
return gPCI->GetMSICount(device->device);
},
.configure_msi = [](pci_device *device, uint8 count, uint8 *startVector) {
.configure_msi = [](pci_device *device, uint32 count, uint32 *startVector) {
return gPCI->ConfigureMSI(device->device, count, startVector);
},
.unconfigure_msi = [](pci_device *device) {
@@ -149,7 +149,7 @@ pci_device_module_info gPCIDeviceModule = {
.get_msix_count = [](pci_device *device) {
return gPCI->GetMSIXCount(device->device);
},
.configure_msix = [](pci_device *device, uint8 count, uint8 *startVector) {
.configure_msix = [](pci_device *device, uint32 count, uint32 *startVector) {
return gPCI->ConfigureMSIX(device->device, count, startVector);
},
.enable_msix = [](pci_device *device) {
@@ -95,10 +95,11 @@ static struct pci_module_info sOldPCIModule = {
.get_msi_count = [](uint8 bus, uint8 device, uint8 function) {
PCIDev* dev;
if (ResolveBDF(bus, device, function, dev) < B_OK)
return (uint8)0;
return (uint32)0;
return gPCI->GetMSICount(dev);
},
.configure_msi = [](uint8 bus, uint8 device, uint8 function, uint8 count, uint8 *startVector) {
.configure_msi = [](uint8 bus, uint8 device, uint8 function, uint32 count,
uint32 *startVector) {
PCIDev* dev;
CHECK_RET(ResolveBDF(bus, device, function, dev));
return gPCI->ConfigureMSI(dev, count, startVector);
@@ -121,10 +122,11 @@ static struct pci_module_info sOldPCIModule = {
.get_msix_count = [](uint8 bus, uint8 device, uint8 function) {
PCIDev* dev;
if (ResolveBDF(bus, device, function, dev) < B_OK)
return (uint8)0;
return (uint32)0;
return gPCI->GetMSIXCount(dev);
},
.configure_msix = [](uint8 bus, uint8 device, uint8 function, uint8 count, uint8 *startVector) {
.configure_msix = [](uint8 bus, uint8 device, uint8 function, uint32 count,
uint32 *startVector) {
PCIDev* dev;
CHECK_RET(ResolveBDF(bus, device, function, dev));
return gPCI->ConfigureMSIX(dev, count, startVector);
@@ -17,11 +17,11 @@
typedef struct msi_info {
bool msi_capable;
uint8 capability_offset;
uint8 message_count;
uint8 configured_count;
uint8 start_vector;
uint32 message_count;
uint32 configured_count;
uint32 start_vector;
uint16 control_value;
uint16 data_value;
uint32 data_value;
uint64 address_value;
} msi_info;
@@ -30,7 +30,7 @@ typedef struct msi_info {
typedef struct msix_info {
bool msix_capable;
uint8 capability_offset;
uint8 message_count;
uint32 message_count;
uint8 table_bar;
uint32 table_offset;
area_id table_area_id;
@@ -39,10 +39,10 @@ typedef struct msix_info {
uint32 pba_offset;
area_id pba_area_id;
addr_t pba_address;
uint8 configured_count;
uint8 start_vector;
uint32 configured_count;
uint32 start_vector;
uint16 control_value;
uint16 data_value;
uint32 data_value;
uint64 address_value;
} msix_info;
@@ -402,7 +402,7 @@ init_bus(device_node* node, void** bus_cookie)
gDeviceManager->put_node(parent);
TRACE_ALWAYS("init_bus() addr 0x%" B_PRIxPHYSADDR " size 0x%" B_PRIx64
" irq 0x%x\n", bus->base_addr, bus->map_size, bus->irq);
" irq 0x%" B_PRIx32 "\n", bus->base_addr, bus->map_size, bus->irq);
bus->registersArea = map_physical_memory("PCHI2C memory mapped registers",
bus->base_addr, bus->map_size, B_ANY_KERNEL_ADDRESS,
+2 -2
View File
@@ -53,7 +53,7 @@ acpi_status pch_i2c_scan_bus_callback(acpi_handle object, uint32 nestingLevel,
struct pch_i2c_crs {
uint16 i2c_addr;
uint8 irq;
uint32 irq;
uint8 irq_triggering;
uint8 irq_polarity;
uint8 irq_shareable;
@@ -73,7 +73,7 @@ typedef enum {
typedef struct {
phys_addr_t base_addr;
uint64 map_size;
uint8 irq;
uint32 irq;
i2c_bus sim;
device_node* node;
@@ -150,10 +150,10 @@ init_device(device_node* node, void** device_cookie)
// try MSI-X
if (pci->get_msix_count(device) >= 1) {
uint8 vector;
uint32 vector;
if (pci->configure_msix(device, 1, &vector) == B_OK
&& pci->enable_msix(device) == B_OK) {
TRACE_ALWAYS("using MSI-X vector %u\n", vector);
TRACE_ALWAYS("using MSI-X vector %" B_PRIu32 "\n", vector);
bus->info.irq = vector;
bus->irq_type = PCH_I2C_IRQ_MSI_X_SHARED;
} else {
@@ -161,10 +161,10 @@ init_device(device_node* node, void** device_cookie)
}
} else if (pci->get_msi_count(device) >= 1) {
// try MSI
uint8 vector;
uint32 vector;
if (pci->configure_msi(device, 1, &vector) == B_OK
&& pci->enable_msi(device) == B_OK) {
TRACE_ALWAYS("using MSI vector %u\n", vector);
TRACE_ALWAYS("using MSI vector %" B_PRIu32 "\n", vector);
bus->info.irq = vector;
bus->irq_type = PCH_I2C_IRQ_MSI;
} else {
@@ -173,9 +173,12 @@ init_device(device_node* node, void** device_cookie)
}
if (bus->irq_type == PCH_I2C_IRQ_LEGACY) {
bus->info.irq = pciInfo->u.h0.interrupt_line;
TRACE_ALWAYS("using legacy interrupt %u\n", bus->info.irq);
if (bus->info.irq == 0xff)
bus->info.irq = 0;
TRACE_ALWAYS("using legacy interrupt %" B_PRIu32 "\n", bus->info.irq);
}
if (bus->info.irq == 0 || bus->info.irq == 0xff) {
if (bus->info.irq == 0) {
ERROR("PCI IRQ not assigned\n");
status = B_ERROR;
goto err;
@@ -165,9 +165,9 @@ public:
status_t Init(PciDbiRegs volatile* dbiRegs, int32 msiIrq);
status_t AllocateVectors(uint8 count, uint8& startVector, uint64& address,
uint16& data) final;
void FreeVectors(uint8 count, uint8 startVector) final;
status_t AllocateVectors(uint32 count, uint32& startVector, uint64& address,
uint32& data) final;
void FreeVectors(uint32 count, uint32 startVector) final;
private:
@@ -53,7 +53,8 @@ MsiInterruptCtrlDW::Init(PciDbiRegs volatile* dbiRegs, int32 msiIrq)
status_t
MsiInterruptCtrlDW::AllocateVectors(uint8 count, uint8& startVector, uint64& address, uint16& data)
MsiInterruptCtrlDW::AllocateVectors(uint32 count, uint32& startVector, uint64& address,
uint32& data)
{
if (count != 1)
return B_ERROR;
@@ -74,7 +75,7 @@ MsiInterruptCtrlDW::AllocateVectors(uint8 count, uint8& startVector, uint64& add
void
MsiInterruptCtrlDW::FreeVectors(uint8 count, uint8 startVector)
MsiInterruptCtrlDW::FreeVectors(uint32 count, uint32 startVector)
{
int32 irq = (int32)startVector - fMsiStartIrq;
while (count > 0) {
@@ -102,18 +102,21 @@ AHCIController::Init()
}
fIRQ = pciInfo.u.h0.interrupt_line;
if (fIRQ == 0xff)
fIRQ = 0;
if (fPCI->get_msi_count(fPCIDevice) >= 1) {
uint8 vector;
uint32 vector;
if (fPCI->configure_msi(fPCIDevice, 1, &vector) == B_OK
&& fPCI->enable_msi(fPCIDevice) == B_OK) {
TRACE("using MSI vector %u\n", vector);
TRACE("using MSI vector %" B_PRIu32 "\n", vector);
fIRQ = vector;
fUseMSI = true;
} else {
TRACE("couldn't use MSI\n");
}
}
if (fIRQ == 0 || fIRQ == 0xff) {
if (fIRQ == 0) {
TRACE("Error: PCI IRQ not assigned\n");
return B_ERROR;
}
@@ -215,7 +218,7 @@ AHCIController::Init()
TRACE("Ports Implemented Mask: %#08" B_PRIx32 " Number of Available Ports:"
" %d\n", fPortImplementedMask, count_bits_set(fPortImplementedMask));
TRACE("AHCI Version %02" B_PRIx32 "%02" B_PRIx32 ".%02" B_PRIx32 ".%02"
B_PRIx32 " Interrupt %u\n", fRegs->vs >> 24, (fRegs->vs >> 16) & 0xff,
B_PRIx32 " Interrupt %" B_PRIu32 "\n", fRegs->vs >> 24, (fRegs->vs >> 16) & 0xff,
(fRegs->vs >> 8) & 0xff, fRegs->vs & 0xff, fIRQ);
// setup interrupt handler
@@ -51,7 +51,7 @@ private:
int fCommandSlotCount;
int fPortCount;
uint32 fPortImplementedMask;
uint8 fIRQ;
uint32 fIRQ;
bool fUseMSI;
AHCIPort * fPort[32];
+5 -2
View File
@@ -572,8 +572,11 @@ EHCI::EHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stac
} else {
// Find the right interrupt vector, using MSIs if available.
fIRQ = fPCIInfo->u.h0.interrupt_line;
if (fIRQ == 0xFF)
fIRQ = 0;
if (fPci->get_msi_count(fDevice) >= 1) {
uint8 msiVector = 0;
uint32 msiVector = 0;
if (fPci->configure_msi(fDevice, 1, &msiVector) == B_OK
&& fPci->enable_msi(fDevice) == B_OK) {
TRACE_ALWAYS("using message signaled interrupts\n");
@@ -582,7 +585,7 @@ EHCI::EHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stac
}
}
if (fIRQ == 0 || fIRQ == 0xFF) {
if (fIRQ == 0) {
TRACE_MODULE_ERROR("device PCI:%d:%d:%d was assigned an invalid IRQ\n",
fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function);
return;
+1 -1
View File
@@ -255,7 +255,7 @@ inline uint32 ReadCapReg32(uint32 reg);
// Interrupt polling
thread_id fInterruptPollThread;
uint8 fIRQ;
uint32 fIRQ;
bool fUseMSI;
};
+5 -2
View File
@@ -544,8 +544,11 @@ OHCI::OHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stac
// Find the right interrupt vector, using MSIs if available.
fIRQ = fPCIInfo->u.h0.interrupt_line;
if (fIRQ == 0xFF)
fIRQ = 0;
if (fPci->get_msi_count(fDevice) >= 1) {
uint8 msiVector = 0;
uint32 msiVector = 0;
if (fPci->configure_msi(fDevice, 1, &msiVector) == B_OK
&& fPci->enable_msi(fDevice) == B_OK) {
TRACE_ALWAYS("using message signaled interrupts\n");
@@ -554,7 +557,7 @@ OHCI::OHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stac
}
}
if (fIRQ == 0 || fIRQ == 0xFF) {
if (fIRQ == 0) {
TRACE_MODULE_ERROR("device PCI:%d:%d:%d was assigned an invalid IRQ\n",
fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function);
return;
+1 -1
View File
@@ -220,7 +220,7 @@ inline uint32 _ReadReg(uint32 reg);
// Port management
uint8 fPortCount;
uint8 fIRQ;
uint32 fIRQ;
bool fUseMSI;
};
+5 -2
View File
@@ -684,8 +684,11 @@ UHCI::UHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stac
// Find the right interrupt vector, using MSIs if available.
fIRQ = fPCIInfo->u.h0.interrupt_line;
if (fIRQ == 0xFF)
fIRQ = 0;
if (fPci->get_msi_count(fDevice) >= 1) {
uint8 msiVector = 0;
uint32 msiVector = 0;
if (fPci->configure_msi(fDevice, 1, &msiVector) == B_OK
&& fPci->enable_msi(fDevice) == B_OK) {
TRACE_ALWAYS("using message signaled interrupts\n");
@@ -694,7 +697,7 @@ UHCI::UHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stac
}
}
if (fIRQ == 0 || fIRQ == 0xFF) {
if (fIRQ == 0) {
TRACE_MODULE_ERROR("device PCI:%d:%d:%d was assigned an invalid IRQ\n",
fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function);
return;
+1 -1
View File
@@ -256,7 +256,7 @@ inline uint32 ReadReg32(uint32 reg);
uint8 fRootHubAddress;
uint8 fPortResetChange;
uint8 fIRQ;
uint32 fIRQ;
bool fUseMSI;
};
+5 -2
View File
@@ -528,6 +528,9 @@ XHCI::XHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Sta
// Find the right interrupt vector, using MSIs if available.
fIRQ = fPCIInfo->u.h0.interrupt_line;
if (fIRQ == 0xFF)
fIRQ = 0;
#if 0
if (fPci->get_msix_count(fDevice) >= 1) {
uint8 msiVector = 0;
@@ -540,7 +543,7 @@ XHCI::XHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Sta
} else
#endif
if (fPci->get_msi_count(fDevice) >= 1) {
uint8 msiVector = 0;
uint32 msiVector = 0;
if (fPci->configure_msi(fDevice, 1, &msiVector) == B_OK
&& fPci->enable_msi(fDevice) == B_OK) {
TRACE_ALWAYS("using message signaled interrupts\n");
@@ -549,7 +552,7 @@ XHCI::XHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Sta
}
}
if (fIRQ == 0 || fIRQ == 0xFF) {
if (fIRQ == 0) {
TRACE_MODULE_ERROR("device PCI:%d:%d:%d was assigned an invalid IRQ\n",
fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function);
return;
+1 -1
View File
@@ -236,7 +236,7 @@ private:
pci_device* fDevice;
Stack * fStack;
uint8 fIRQ;
uint32 fIRQ;
bool fUseMSI;
area_id fErstArea;
@@ -54,7 +54,7 @@ typedef struct {
addr_t isrAddr;
addr_t notifyAddr;
uint32 notifyOffsetMultiplier;
uint8 irq;
uint32 irq;
virtio_irq_type irq_type;
virtio_sim sim;
uint16 queue_count;
@@ -460,28 +460,29 @@ setup_interrupt(void* cookie, uint16 queueCount)
bus->queue_count = queueCount;
// try MSI-X
uint8 msixCount = bus->pci->get_msix_count(bus->device);
uint32 msixCount = bus->pci->get_msix_count(bus->device);
if (msixCount >= 2) {
if (msixCount >= (queueCount + 1)) {
uint8 vector;
uint32 vectorCount = queueCount + 1;
if (msixCount >= vectorCount) {
uint32 vector;
bus->cookies = new(std::nothrow)
virtio_pci_queue_cookie[queueCount];
if (bus->cookies != NULL
&& bus->pci->configure_msix(bus->device, queueCount + 1,
&& bus->pci->configure_msix(bus->device, vectorCount,
&vector) == B_OK
&& bus->pci->enable_msix(bus->device) == B_OK) {
TRACE_ALWAYS("using MSI-X count %u starting at %d\n",
queueCount + 1, vector);
TRACE_ALWAYS("using MSI-X count %" B_PRIu32 " starting at %" B_PRIu32 "\n",
vectorCount, vector);
bus->irq = vector;
bus->irq_type = VIRTIO_IRQ_MSI_X;
} else {
ERROR("couldn't use MSI-X\n");
}
} else {
uint8 vector;
uint32 vector;
if (bus->pci->configure_msix(bus->device, 2, &vector) == B_OK
&& bus->pci->enable_msix(bus->device) == B_OK) {
TRACE_ALWAYS("using MSI-X vector shared %u\n", vector);
TRACE_ALWAYS("using MSI-X vector shared %" B_PRIu32 "\n", vector);
bus->irq = vector;
bus->irq_type = VIRTIO_IRQ_MSI_X_SHARED;
} else {
@@ -492,9 +493,11 @@ setup_interrupt(void* cookie, uint16 queueCount)
if (bus->irq_type == VIRTIO_IRQ_LEGACY) {
bus->irq = pciInfo->u.h0.interrupt_line;
TRACE_ALWAYS("using legacy interrupt %u\n", bus->irq);
if (bus->irq == 0xff)
bus->irq = 0;
TRACE_ALWAYS("using legacy interrupt %" B_PRIu32 "\n", bus->irq);
}
if (bus->irq == 0 || bus->irq == 0xff) {
if (bus->irq == 0) {
ERROR("PCI IRQ not assigned\n");
delete bus;
return B_ERROR;
@@ -1153,20 +1153,28 @@ hda_hw_init(hda_controller* controller)
controller->irq = pciInfo.u.h0.interrupt_line;
controller->msi = false;
if (controller->irq == 0xff)
controller->irq = 0;
if ((quirks & HDA_QUIRK_NO_MSI) == 0
&& gPci->get_msi_count(pciInfo.bus, pciInfo.device,
pciInfo.function) >= 1) {
// Try MSI first
uint8 vector;
uint32 vector;
if (gPci->configure_msi(pciInfo.bus, pciInfo.device,
pciInfo.function, 1, &vector) == B_OK && gPci->enable_msi(
pciInfo.bus, pciInfo.device, pciInfo.function) == B_OK) {
dprintf("hda: using MSI vector %u\n", vector);
dprintf("hda: using MSI vector %" B_PRIu32 "\n", vector);
controller->irq = vector;
controller->msi = true;
}
}
if (controller->irq == 0) {
status = ENODEV;
goto no_irq_handler;
}
status = install_io_interrupt_handler(controller->irq,
(interrupt_handler)hda_interrupt_handler, controller, 0);
if (status != B_OK)
@@ -229,16 +229,19 @@ nvme_disk_init_device(void* _info, void** _cookie)
command &= ~(PCI_command_int_disable);
pci->write_pci_config(pcidev, PCI_command, 2, command);
uint8 irq = info->info.u.h0.interrupt_line;
uint32 irq = info->info.u.h0.interrupt_line;
if (irq == 0xFF)
irq = 0;
if (pci->get_msix_count(pcidev)) {
uint8 msixVector = 0;
uint32 msixVector = 0;
if (pci->configure_msix(pcidev, 1, &msixVector) == B_OK
&& pci->enable_msix(pcidev) == B_OK) {
TRACE_ALWAYS("using MSI-X\n");
irq = msixVector;
}
} else if (pci->get_msi_count(pcidev) >= 1) {
uint8 msiVector = 0;
uint32 msiVector = 0;
if (pci->configure_msi(pcidev, 1, &msiVector) == B_OK
&& pci->enable_msi(pcidev) == B_OK) {
TRACE_ALWAYS("using message signaled interrupts\n");
@@ -246,7 +249,7 @@ nvme_disk_init_device(void* _info, void** _cookie)
}
}
if (irq == 0 || irq == 0xFF) {
if (irq == 0) {
TRACE_ERROR("device PCI:%d:%d:%d was assigned an invalid IRQ\n",
info->info.bus, info->info.device, info->info.function);
info->polling = 1;
@@ -443,13 +443,16 @@ init_interrupt_handler(intel_info &info)
}
// Find the right interrupt vector, using MSIs if available.
info.irq = 0xff;
info.irq = 0;
info.use_msi = false;
if (info.pci->u.h0.interrupt_pin != 0x00)
if (info.pci->u.h0.interrupt_pin != 0x00) {
info.irq = info.pci->u.h0.interrupt_line;
if (info.irq == 0xff)
info.irq = 0;
}
if (gPCI->get_msi_count(info.pci->bus,
info.pci->device, info.pci->function) >= 1) {
uint8 msiVector = 0;
uint32 msiVector = 0;
if (gPCI->configure_msi(info.pci->bus, info.pci->device,
info.pci->function, 1, &msiVector) == B_OK
&& gPCI->enable_msi(info.pci->bus, info.pci->device,
@@ -460,7 +463,7 @@ init_interrupt_handler(intel_info &info)
}
}
if (status == B_OK && info.irq != 0xff) {
if (status == B_OK && info.irq != 0) {
// we've gotten an interrupt line for us to use
info.fake_interrupts = false;
+2 -2
View File
@@ -265,7 +265,7 @@ int
pci_alloc_msi(device_t dev, int *count)
{
pci_info* info = get_device_pci_info(dev);
uint8 startVector = 0;
uint32 startVector = 0;
if (gPci->configure_msi(info->bus, info->device, info->function, *count,
&startVector) != B_OK) {
return ENODEV;
@@ -318,7 +318,7 @@ int
pci_alloc_msix(device_t dev, int *count)
{
pci_info* info = get_device_pci_info(dev);
uint8 startVector = 0;
uint32 startVector = 0;
if (gPci->configure_msix(info->bus, info->device, info->function, *count,
&startVector) != B_OK) {
return ENODEV;
@@ -25,15 +25,14 @@ msi_supported()
status_t
msi_allocate_vectors(uint8 count, uint8 *startVector, uint64 *address, uint16 *data)
msi_allocate_vectors(uint32 count, uint32 *startVector, uint64 *address, uint32 *data)
{
return sMSIInterface->AllocateVectors(count, *startVector, *address, *data);
}
void
msi_free_vectors(uint8 count, uint8 startVector)
msi_free_vectors(uint32 count, uint32 startVector)
{
sMSIInterface->FreeVectors(count, startVector);
}
+8 -8
View File
@@ -14,7 +14,7 @@
struct MSIConfiguration {
uint64* fAddress;
uint16* fData;
uint32* fData;
};
static MSIConfiguration sMSIConfigurations[NUM_IO_VECTORS];
@@ -45,8 +45,8 @@ msi_supported()
status_t
msi_allocate_vectors(uint8 count, uint8 *startVector, uint64 *address,
uint16 *data)
msi_allocate_vectors(uint32 count, uint32 *startVector, uint64 *address,
uint32 *data)
{
if (!sMSISupported)
return B_UNSUPPORTED;
@@ -66,27 +66,27 @@ msi_allocate_vectors(uint8 count, uint8 *startVector, uint64 *address,
sMSIConfigurations[vector].fData = data;
x86_set_irq_source(vector, IRQ_SOURCE_MSI);
*startVector = (uint8)vector;
*startVector = (uint32)vector;
*address = MSI_ADDRESS_BASE | (sBootCPUAPICId << MSI_DESTINATION_ID_SHIFT)
| MSI_NO_REDIRECTION | MSI_DESTINATION_MODE_PHYSICAL;
*data = MSI_TRIGGER_MODE_EDGE | MSI_DELIVERY_MODE_FIXED
| ((uint16)vector + ARCH_INTERRUPT_BASE);
dprintf("msi_allocate_vectors: allocated %u vectors starting from %u\n",
dprintf("msi_allocate_vectors: allocated %" B_PRIu32 " vectors starting from %" B_PRIu32 "\n",
count, *startVector);
return B_OK;
}
void
msi_free_vectors(uint8 count, uint8 startVector)
msi_free_vectors(uint32 count, uint32 startVector)
{
if (!sMSISupported) {
panic("trying to free msi vectors but msi not supported\n");
return;
}
dprintf("msi_free_vectors: freeing %u vectors starting from %u\n", count,
dprintf("msi_free_vectors: freeing %" B_PRIu32 " vectors starting from %" B_PRIu32 "\n", count,
startVector);
free_io_interrupt_vectors(count, startVector);
@@ -94,7 +94,7 @@ msi_free_vectors(uint8 count, uint8 startVector)
void
msi_assign_interrupt_to_cpu(uint8 irq, int32 cpu)
msi_assign_interrupt_to_cpu(uint32 irq, int32 cpu)
{
uint32 apic_id = x86_get_cpu_apic_id(cpu);