Convert the number of MSI IRQs on x86 from a constant to a tunable.
The number of MSI IRQs still defaults to 512, but it can now be changed at boot time via the machdep.num_msi_irqs tunable. Reviewed by: kib, royger (older version) Reviewed by: markj MFC after: 1 month Relnotes: yes Differential Revision: https://reviews.freebsd.org/D17977
This commit is contained in:
parent
aaf1f854e1
commit
b6b42932db
@ -58,11 +58,11 @@
|
||||
* the minimum IRQ value for MSI interrupts to attempt to leave 255
|
||||
* unused since 255 is used in PCI to indicate an invalid INTx IRQ.
|
||||
*/
|
||||
#define NUM_MSI_INTS 512
|
||||
#define MINIMUM_MSI_INT 256
|
||||
|
||||
extern u_int first_msi_irq;
|
||||
extern u_int num_io_irqs;
|
||||
extern u_int num_msi_irqs;
|
||||
|
||||
/*
|
||||
* Default base address for MSI messages on x86 platforms.
|
||||
|
@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
@ -153,6 +154,10 @@ struct pic msi_pic = {
|
||||
|
||||
u_int first_msi_irq;
|
||||
|
||||
u_int num_msi_irqs = 512;
|
||||
SYSCTL_UINT(_machdep, OID_AUTO, num_msi_irqs, CTLFLAG_RDTUN, &num_msi_irqs, 0,
|
||||
"Number of IRQs reserved for MSI and MSI-X interrupts");
|
||||
|
||||
#ifdef SMP
|
||||
/**
|
||||
* Xen hypervisors prior to 4.6.0 do not properly handle updates to
|
||||
@ -331,8 +336,13 @@ msi_init(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (num_msi_irqs == 0)
|
||||
return;
|
||||
|
||||
first_msi_irq = max(MINIMUM_MSI_INT, num_io_irqs);
|
||||
num_io_irqs = first_msi_irq + NUM_MSI_INTS;
|
||||
if (num_msi_irqs > UINT_MAX - first_msi_irq)
|
||||
panic("num_msi_irq too high");
|
||||
num_io_irqs = first_msi_irq + num_msi_irqs;
|
||||
|
||||
msi_enabled = 1;
|
||||
intr_register_pic(&msi_pic);
|
||||
@ -346,7 +356,7 @@ msi_create_source(void)
|
||||
u_int irq;
|
||||
|
||||
mtx_lock(&msi_lock);
|
||||
if (msi_last_irq >= NUM_MSI_INTS) {
|
||||
if (msi_last_irq >= num_msi_irqs) {
|
||||
mtx_unlock(&msi_lock);
|
||||
return;
|
||||
}
|
||||
@ -390,7 +400,7 @@ msi_alloc(device_t dev, int count, int maxcount, int *irqs)
|
||||
|
||||
/* Try to find 'count' free IRQs. */
|
||||
cnt = 0;
|
||||
for (i = first_msi_irq; i < first_msi_irq + NUM_MSI_INTS; i++) {
|
||||
for (i = first_msi_irq; i < first_msi_irq + num_msi_irqs; i++) {
|
||||
msi = (struct msi_intsrc *)intr_lookup_source(i);
|
||||
|
||||
/* End of allocated sources, so break. */
|
||||
@ -409,7 +419,7 @@ msi_alloc(device_t dev, int count, int maxcount, int *irqs)
|
||||
/* Do we need to create some new sources? */
|
||||
if (cnt < count) {
|
||||
/* If we would exceed the max, give up. */
|
||||
if (i + (count - cnt) > first_msi_irq + NUM_MSI_INTS) {
|
||||
if (i + (count - cnt) > first_msi_irq + num_msi_irqs) {
|
||||
mtx_unlock(&msi_lock);
|
||||
free(mirqs, M_MSI);
|
||||
return (ENXIO);
|
||||
@ -585,7 +595,7 @@ msi_map(int irq, uint64_t *addr, uint32_t *data)
|
||||
#ifdef ACPI_DMAR
|
||||
if (!msi->msi_msix) {
|
||||
for (k = msi->msi_count - 1, i = first_msi_irq; k > 0 &&
|
||||
i < first_msi_irq + NUM_MSI_INTS; i++) {
|
||||
i < first_msi_irq + num_msi_irqs; i++) {
|
||||
if (i == msi->msi_irq)
|
||||
continue;
|
||||
msi1 = (struct msi_intsrc *)intr_lookup_source(i);
|
||||
@ -635,7 +645,7 @@ msix_alloc(device_t dev, int *irq)
|
||||
mtx_lock(&msi_lock);
|
||||
|
||||
/* Find a free IRQ. */
|
||||
for (i = first_msi_irq; i < first_msi_irq + NUM_MSI_INTS; i++) {
|
||||
for (i = first_msi_irq; i < first_msi_irq + num_msi_irqs; i++) {
|
||||
msi = (struct msi_intsrc *)intr_lookup_source(i);
|
||||
|
||||
/* End of allocated sources, so break. */
|
||||
@ -648,7 +658,7 @@ msix_alloc(device_t dev, int *irq)
|
||||
}
|
||||
|
||||
/* Are all IRQs in use? */
|
||||
if (i == first_msi_irq + NUM_MSI_INTS) {
|
||||
if (i == first_msi_irq + num_msi_irqs) {
|
||||
mtx_unlock(&msi_lock);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
@ -690,6 +690,8 @@ void
|
||||
xen_intr_alloc_irqs(void)
|
||||
{
|
||||
|
||||
if (num_io_irqs > UINT_MAX - NR_EVENT_CHANNELS)
|
||||
panic("IRQ allocation overflow (num_msi_irqs too high?)");
|
||||
first_evtchn_irq = num_io_irqs;
|
||||
num_io_irqs += NR_EVENT_CHANNELS;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
@ -57,7 +58,9 @@ xen_msi_init(void)
|
||||
|
||||
MPASS(num_io_irqs > 0);
|
||||
first_msi_irq = min(MINIMUM_MSI_INT, num_io_irqs);
|
||||
num_io_irqs = first_msi_irq + NUM_MSI_INTS;
|
||||
if (num_msi_irqs > UINT_MAX - first_msi_irq)
|
||||
panic("num_msi_irq too high");
|
||||
num_io_irqs = first_msi_irq + num_msi_irqs;
|
||||
|
||||
mtx_init(&msi_lock, "msi", NULL, MTX_DEF);
|
||||
}
|
||||
@ -73,7 +76,7 @@ xen_msi_alloc(device_t dev, int count, int maxcount, int *irqs)
|
||||
mtx_lock(&msi_lock);
|
||||
|
||||
/* If we would exceed the max, give up. */
|
||||
if ((msi_last_irq + count) > NUM_MSI_INTS) {
|
||||
if (msi_last_irq + count > num_msi_irqs) {
|
||||
mtx_unlock(&msi_lock);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user