Expand the MSI/MSI-X API to address some deficiencies in the MSI-X support.

- First off, device drivers really do need to know if they are allocating
  MSI or MSI-X messages.  MSI requires allocating powerof2() messages for
  example where MSI-X does not.  To address this, split out the MSI-X
  support from pci_msi_count() and pci_alloc_msi() into new driver-visible
  functions pci_msix_count() and pci_alloc_msix().  As a result,
  pci_msi_count() now just returns a count of the max supported MSI
  messages for the device, and pci_alloc_msi() only tries to allocate MSI
  messages.  To get a count of the max supported MSI-X messages, use
  pci_msix_count().  To allocate MSI-X messages, use pci_alloc_msix().
  pci_release_msi() still handles both MSI and MSI-X messages, however.
  As a result of this change, drivers using the existing API will only
  use MSI messages and will no longer try to use MSI-X messages.
- Because MSI-X allows for each message to have its own data and address
  values (and thus does not require all of the messages to have their
  MD vectors allocated as a group), some devices allow for "sparse" use
  of MSI-X message slots.  For example, if a device supports 8 messages
  but the OS is only able to allocate 2 messages, the device may make the
  best use of 2 IRQs if it enables the messages at slots 1 and 4 rather
  than default of using the first N slots (or indicies) at 1 and 2.  To
  support this, add a new pci_remap_msix() function that a driver may call
  after a successful pci_alloc_msix() (but before allocating any of the
  SYS_RES_IRQ resources) to allow the allocated IRQ resources to be
  assigned to different message indices.  For example, from the earlier
  example, after pci_alloc_msix() returned a value of 2, the driver would
  call pci_remap_msix() passing in array of integers { 1, 4 } as the
  new message indices to use.  The rid's for the SYS_RES_IRQ resources
  will always match the message indices.  Thus, after the call to
  pci_remap_msix() the driver would be able to access the first message
  in slot 1 at SYS_RES_IRQ rid 1, and the second message at slot 4 at
  SYS_RES_IRQ rid 4.  Note that the message slots/indices are 1-based
  rather than 0-based so that they will always correspond to the rid
  values (SYS_RES_IRQ rid 0 is reserved for the legacy INTx interrupt).
  To support this API, a new PCIB_REMAP_MSIX() method was added to the
  pcib interface to change the message index for a single IRQ.

Tested by:	scottl
This commit is contained in:
John Baldwin 2007-01-22 21:48:44 +00:00
parent 7c32173ba8
commit 5fe82bca57
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=166176
19 changed files with 281 additions and 27 deletions

View File

@ -120,6 +120,7 @@ static device_method_t mptable_hostb_methods[] = {
DEVMETHOD(pcib_alloc_msi, mptable_hostb_alloc_msi),
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, mptable_hostb_alloc_msix),
DEVMETHOD(pcib_remap_msix, pcib_remap_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
{ 0, 0 }
@ -176,6 +177,7 @@ static device_method_t mptable_pcib_pci_methods[] = {
DEVMETHOD(pcib_alloc_msi, pcib_alloc_msi),
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix),
DEVMETHOD(pcib_remap_msix, pcib_remap_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
{0, 0}

View File

@ -479,6 +479,30 @@ msix_alloc(device_t dev, int index, int *irq, int *new)
return (0);
}
int
msix_remap(int index, int irq)
{
struct msi_intsrc *msi;
sx_xlock(&msi_sx);
msi = (struct msi_intsrc *)intr_lookup_source(irq);
if (msi == NULL) {
sx_xunlock(&msi_sx);
return (ENOENT);
}
/* Make sure this is an MSI-X message. */
if (!msi->msi_msix) {
sx_xunlock(&msi_sx);
return (EINVAL);
}
KASSERT(msi->msi_dev != NULL, ("unowned message"));
msi->msi_index = index;
sx_xunlock(&msi_sx);
return (0);
}
int
msix_release(int irq)
{

View File

@ -105,6 +105,7 @@ static void nexus_delete_resource(device_t, device_t, int, int);
static int nexus_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs);
static int nexus_release_msi(device_t pcib, device_t dev, int count, int *irqs);
static int nexus_alloc_msix(device_t pcib, device_t dev, int index, int *irq);
static int nexus_remap_msix(device_t pcib, device_t dev, int index, int irq);
static int nexus_release_msix(device_t pcib, device_t dev, int irq);
static device_method_t nexus_methods[] = {
@ -135,6 +136,7 @@ static device_method_t nexus_methods[] = {
DEVMETHOD(pcib_alloc_msi, nexus_alloc_msi),
DEVMETHOD(pcib_release_msi, nexus_release_msi),
DEVMETHOD(pcib_alloc_msix, nexus_alloc_msix),
DEVMETHOD(pcib_remap_msix, nexus_remap_msix),
DEVMETHOD(pcib_release_msix, nexus_release_msix),
{ 0, 0 }
@ -509,6 +511,13 @@ nexus_alloc_msix(device_t pcib, device_t dev, int index, int *irq)
return (error);
}
static int
nexus_remap_msix(device_t pcib, device_t dev, int index, int irq)
{
return (msix_remap(index, irq));
}
static int
nexus_release_msix(device_t pcib, device_t dev, int irq)
{

View File

@ -152,6 +152,7 @@ int msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq,
void msi_init(void);
int msi_release(int *irqs, int count);
int msix_alloc(device_t dev, int index, int *irq, int *new);
int msix_remap(int index, int irq);
int msix_release(int irq);
#endif /* !LOCORE */

View File

@ -347,6 +347,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_alloc_msi, legacy_pcib_alloc_msi),
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, legacy_pcib_alloc_msix),
DEVMETHOD(pcib_remap_msix, pcib_remap_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
{ 0, 0 }

View File

@ -110,6 +110,7 @@ static device_method_t acpi_pcib_acpi_methods[] = {
DEVMETHOD(pcib_alloc_msi, acpi_pcib_alloc_msi),
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, acpi_pcib_alloc_msix),
DEVMETHOD(pcib_remap_msix, pcib_remap_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
{0, 0}

View File

@ -96,6 +96,7 @@ static device_method_t acpi_pcib_pci_methods[] = {
DEVMETHOD(pcib_alloc_msi, pcib_alloc_msi),
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix),
DEVMETHOD(pcib_remap_msix, pcib_remap_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
{0, 0}

View File

@ -101,6 +101,7 @@ static void pci_write_vpd_reg(device_t pcib, pcicfgregs *cfg,
int reg, uint32_t data);
#endif
static void pci_read_vpd(device_t pcib, pcicfgregs *cfg);
static int pci_msi_blacklisted(void);
static device_method_t pci_methods[] = {
/* Device interface */
@ -145,8 +146,11 @@ static device_method_t pci_methods[] = {
DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method),
DEVMETHOD(pci_find_extcap, pci_find_extcap_method),
DEVMETHOD(pci_alloc_msi, pci_alloc_msi_method),
DEVMETHOD(pci_alloc_msix, pci_alloc_msix_method),
DEVMETHOD(pci_remap_msix, pci_remap_msix_method),
DEVMETHOD(pci_release_msi, pci_release_msi_method),
DEVMETHOD(pci_msi_count, pci_msi_count_method),
DEVMETHOD(pci_msix_count, pci_msix_count_method),
{ 0, 0 }
};
@ -1024,14 +1028,36 @@ pci_pending_msix(device_t dev, u_int index)
return (bus_read_4(cfg->msix.msix_pba_res, offset) & bit);
}
static int
pci_alloc_msix(device_t dev, device_t child, int *count)
/*
* Attempt to allocate *count MSI-X messages. The actual number allocated is
* returned in *count. After this function returns, each message will be
* available to the driver as SYS_RES_IRQ resources starting at rid 1.
*/
int
pci_alloc_msix_method(device_t dev, device_t child, int *count)
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
struct resource_list_entry *rle;
int actual, error, i, irq, max;
/* Don't let count == 0 get us into trouble. */
if (*count == 0)
return (EINVAL);
/* If rid 0 is allocated, then fail. */
rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, 0);
if (rle != NULL && rle->res != NULL)
return (ENXIO);
/* Already have allocated messages? */
if (cfg->msi.msi_alloc != 0 || cfg->msix.msix_alloc != 0)
return (ENXIO);
/* If MSI is blacklisted for this system, fail. */
if (pci_msi_blacklisted())
return (ENXIO);
/* MSI-X capability present? */
if (cfg->msix.msix_location == 0 || !pci_do_msix)
return (ENODEV);
@ -1052,10 +1078,6 @@ pci_alloc_msix(device_t dev, device_t child, int *count)
}
cfg->msix.msix_pba_res = rle->res;
/* Already have allocated messages? */
if (cfg->msix.msix_alloc != 0)
return (ENXIO);
if (bootverbose)
device_printf(child,
"attempting to allocate %d MSI-X vectors (%d supported)\n",
@ -1132,24 +1154,105 @@ pci_alloc_msix(device_t dev, device_t child, int *count)
return (0);
}
/*
* By default, pci_alloc_msix() will assign the allocated IRQ resources to
* the first N messages in the MSI-X table. However, device drivers may
* want to use different layouts in the case that they do not allocate a
* full table. This method allows the driver to specify what layout it
* wants. It must be called after a successful pci_alloc_msix() but
* before any of the associated SYS_RES_IRQ resources are allocated via
* bus_alloc_resource(). The 'indices' array contains N (where N equals
* the 'count' returned from pci_alloc_msix()) message indices. The
* indices are 1-based (meaning the first message is at index 1). On
* successful return, each of the messages in the 'indices' array will
* have an associated SYS_RES_IRQ whose rid is equal to the index. Thus,
* if indices contains { 2, 4 }, then upon successful return, the 'child'
* device will have two SYS_RES_IRQ resources available at rids 2 and 4.
*/
int
pci_remap_msix_method(device_t dev, device_t child, u_int *indices)
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
struct resource_list_entry *rle;
int count, error, i, j, *irqs;
/* Sanity check the indices. */
for (i = 0; i < cfg->msix.msix_alloc; i++)
if (indices[i] == 0 || indices[i] > cfg->msix.msix_msgnum)
return (EINVAL);
/* Check for duplicates. */
for (i = 0; i < cfg->msix.msix_alloc; i++)
for (j = i + 1; j < cfg->msix.msix_alloc; j++)
if (indices[i] == indices[j])
return (EINVAL);
/* Make sure none of the resources are allocated. */
for (i = 1, count = 0; count < cfg->msix.msix_alloc; i++) {
rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i);
if (rle == NULL)
continue;
if (rle->res != NULL)
return (EBUSY);
count++;
}
/* Save the IRQ values and free the existing resources. */
irqs = malloc(sizeof(int) * cfg->msix.msix_alloc, M_TEMP, M_WAITOK);
for (i = 1, count = 0; count < cfg->msix.msix_alloc; i++) {
rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i);
if (rle == NULL)
continue;
irqs[count] = rle->start;
resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i);
count++;
}
/* Map the IRQ values to the new message indices and rids. */
for (i = 0; i < cfg->msix.msix_alloc; i++) {
resource_list_add(&dinfo->resources, SYS_RES_IRQ, indices[i],
irqs[i], irqs[i], 1);
error = PCIB_REMAP_MSIX(device_get_parent(dev), child,
indices[i], irqs[i]);
KASSERT(error == 0, ("Failed to remap MSI-X message"));
}
if (bootverbose) {
if (cfg->msix.msix_alloc == 1)
device_printf(child,
"Remapped MSI-X IRQ to index %d\n", indices[0]);
else {
device_printf(child, "Remapped MSI-X IRQs to indices");
for (i = 0; i < cfg->msix.msix_alloc - 1; i++)
printf(" %d,", indices[i]);
printf(" %d\n", indices[cfg->msix.msix_alloc - 1]);
}
}
free(irqs, M_TEMP);
return (0);
}
static int
pci_release_msix(device_t dev, device_t child)
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
struct resource_list_entry *rle;
int i;
int count, i;
/* Do we have any messages to release? */
if (cfg->msix.msix_alloc == 0)
return (ENODEV);
/* Make sure none of the resources are allocated. */
for (i = 0; i < cfg->msix.msix_alloc; i++) {
rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i + 1);
KASSERT(rle != NULL, ("missing MSI resource"));
for (i = 1, count = 0; count < cfg->msix.msix_alloc; i++) {
rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i);
if (rle == NULL)
continue;
if (rle->res != NULL)
return (EBUSY);
count++;
}
/* Update control register with to disable MSI-X. */
@ -1158,11 +1261,14 @@ pci_release_msix(device_t dev, device_t child)
cfg->msix.msix_ctrl, 2);
/* Release the messages. */
for (i = 0; i < cfg->msix.msix_alloc; i++) {
rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i + 1);
for (i = 1, count = 0; count < cfg->msix.msix_alloc; i++) {
rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i);
if (rle == NULL)
continue;
PCIB_RELEASE_MSIX(device_get_parent(dev), child,
rle->start);
resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i + 1);
resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i);
count++;
}
/* Update alloc count. */
@ -1170,6 +1276,23 @@ pci_release_msix(device_t dev, device_t child)
return (0);
}
/*
* Return the max supported MSI-X messages this device supports.
* Basically, assuming the MD code can alloc messages, this function
* should return the maximum value that pci_alloc_msix() can return.
* Thus, it is subject to the tunables, etc.
*/
int
pci_msix_count_method(device_t dev, device_t child)
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
if (pci_do_msix && cfg->msix.msix_location != 0)
return (cfg->msix.msix_msgnum);
return (0);
}
/*
* Support for MSI message signalled interrupts.
*/
@ -1294,23 +1417,18 @@ pci_alloc_msi_method(device_t dev, device_t child, int *count)
if (rle != NULL && rle->res != NULL)
return (ENXIO);
/* Already have allocated messages? */
if (cfg->msi.msi_alloc != 0 || cfg->msix.msix_alloc != 0)
return (ENXIO);
/* If MSI is blacklisted for this system, fail. */
if (pci_msi_blacklisted())
return (ENXIO);
/* Try MSI-X first. */
error = pci_alloc_msix(dev, child, count);
if (error != ENODEV)
return (error);
/* MSI capability present? */
if (cfg->msi.msi_location == 0 || !pci_do_msi)
return (ENODEV);
/* Already have allocated messages? */
if (cfg->msi.msi_alloc != 0)
return (ENXIO);
if (bootverbose)
device_printf(child,
"attempting to allocate %d MSI vectors (%d supported)\n",
@ -1444,10 +1562,10 @@ pci_release_msi_method(device_t dev, device_t child)
}
/*
* Return the max supported MSI or MSI-X messages this device supports.
* Return the max supported MSI messages this device supports.
* Basically, assuming the MD code can alloc messages, this function
* should return the maximum value that pci_alloc_msi() can return. Thus,
* it is subject to the tunables, etc.
* should return the maximum value that pci_alloc_msi() can return.
* Thus, it is subject to the tunables, etc.
*/
int
pci_msi_count_method(device_t dev, device_t child)
@ -1455,8 +1573,6 @@ pci_msi_count_method(device_t dev, device_t child)
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
if (pci_do_msix && cfg->msix.msix_location != 0)
return (cfg->msix.msix_msgnum);
if (pci_do_msi && cfg->msi.msi_location != 0)
return (cfg->msi.msi_msgnum);
return (0);

View File

@ -118,6 +118,18 @@ METHOD int alloc_msi {
int *count;
};
METHOD int alloc_msix {
device_t dev;
device_t child;
int *count;
};
METHOD int remap_msix {
device_t dev;
device_t child;
u_int *indices;
};
METHOD int release_msi {
device_t dev;
device_t child;
@ -127,3 +139,8 @@ METHOD int msi_count {
device_t dev;
device_t child;
} DEFAULT null_msi_count;
METHOD int msix_count {
device_t dev;
device_t child;
} DEFAULT null_msi_count;

View File

@ -82,6 +82,7 @@ static device_method_t pcib_methods[] = {
DEVMETHOD(pcib_alloc_msi, pcib_alloc_msi),
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix),
DEVMETHOD(pcib_remap_msix, pcib_remap_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
{ 0, 0 }
@ -583,6 +584,16 @@ pcib_alloc_msix(device_t pcib, device_t dev, int index, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, index, irq));
}
/* Pass request to remap an MSI-X message up to the parent bridge. */
int
pcib_remap_msix(device_t pcib, device_t dev, int index, int irq)
{
device_t bus;
bus = device_get_parent(pcib);
return (PCIB_REMAP_MSIX(device_get_parent(bus), dev, index, irq));
}
/* Pass request to release an MSI-X message up to the parent bridge. */
int
pcib_release_msix(device_t pcib, device_t dev, int irq)

View File

@ -67,8 +67,12 @@ int pci_disable_io_method(device_t dev, device_t child, int space);
int pci_find_extcap_method(device_t dev, device_t child,
int capability, int *capreg);
int pci_alloc_msi_method(device_t dev, device_t child, int *count);
int pci_alloc_msix_method(device_t dev, device_t child, int *count);
int pci_remap_msix_method(device_t dev, device_t child,
u_int *indices);
int pci_release_msi_method(device_t dev, device_t child);
int pci_msi_count_method(device_t dev, device_t child);
int pci_msix_count_method(device_t dev, device_t child);
struct resource *pci_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count,
u_int flags);

View File

@ -125,6 +125,16 @@ METHOD int alloc_msix {
int *irq;
};
#
# Remap a single MSI-X message to a different index.
#
METHOD int remap_msix {
device_t pcib;
device_t dev;
int index;
int irq;
};
#
# Release a single MSI-X message mapped onto 'irq'.
#

View File

@ -78,6 +78,7 @@ int pcib_route_interrupt(device_t pcib, device_t dev, int pin);
int pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs);
int pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs);
int pcib_alloc_msix(device_t pcib, device_t dev, int index, int *irq);
int pcib_remap_msix(device_t pcib, device_t dev, int index, int irq);
int pcib_release_msix(device_t pcib, device_t dev, int irq);
#endif

View File

@ -395,6 +395,18 @@ pci_alloc_msi(device_t dev, int *count)
return (PCI_ALLOC_MSI(device_get_parent(dev), dev, count));
}
static __inline int
pci_alloc_msix(device_t dev, int *count)
{
return (PCI_ALLOC_MSIX(device_get_parent(dev), dev, count));
}
static __inline int
pci_remap_msix(device_t dev, u_int *indices)
{
return (PCI_REMAP_MSIX(device_get_parent(dev), dev, indices));
}
static __inline int
pci_release_msi(device_t dev)
{
@ -407,6 +419,12 @@ pci_msi_count(device_t dev)
return (PCI_MSI_COUNT(device_get_parent(dev), dev));
}
static __inline int
pci_msix_count(device_t dev)
{
return (PCI_MSIX_COUNT(device_get_parent(dev), dev));
}
device_t pci_find_bsf(uint8_t, uint8_t, uint8_t);
device_t pci_find_device(uint16_t, uint16_t);

View File

@ -120,6 +120,7 @@ static device_method_t mptable_hostb_methods[] = {
DEVMETHOD(pcib_alloc_msi, mptable_hostb_alloc_msi),
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, mptable_hostb_alloc_msix),
DEVMETHOD(pcib_remap_msix, pcib_remap_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
{ 0, 0 }
@ -176,6 +177,7 @@ static device_method_t mptable_pcib_pci_methods[] = {
DEVMETHOD(pcib_alloc_msi, pcib_alloc_msi),
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix),
DEVMETHOD(pcib_remap_msix, pcib_remap_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
{0, 0}

View File

@ -479,6 +479,30 @@ msix_alloc(device_t dev, int index, int *irq, int *new)
return (0);
}
int
msix_remap(int index, int irq)
{
struct msi_intsrc *msi;
sx_xlock(&msi_sx);
msi = (struct msi_intsrc *)intr_lookup_source(irq);
if (msi == NULL) {
sx_xunlock(&msi_sx);
return (ENOENT);
}
/* Make sure this is an MSI-X message. */
if (!msi->msi_msix) {
sx_xunlock(&msi_sx);
return (EINVAL);
}
KASSERT(msi->msi_dev != NULL, ("unowned message"));
msi->msi_index = index;
sx_xunlock(&msi_sx);
return (0);
}
int
msix_release(int irq)
{

View File

@ -113,6 +113,7 @@ static void nexus_delete_resource(device_t, device_t, int, int);
static int nexus_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs);
static int nexus_release_msi(device_t pcib, device_t dev, int count, int *irqs);
static int nexus_alloc_msix(device_t pcib, device_t dev, int index, int *irq);
static int nexus_remap_msix(device_t pcib, device_t dev, int index, int irq);
static int nexus_release_msix(device_t pcib, device_t dev, int irq);
#endif
@ -145,6 +146,7 @@ static device_method_t nexus_methods[] = {
DEVMETHOD(pcib_alloc_msi, nexus_alloc_msi),
DEVMETHOD(pcib_release_msi, nexus_release_msi),
DEVMETHOD(pcib_alloc_msix, nexus_alloc_msix),
DEVMETHOD(pcib_remap_msix, nexus_remap_msix),
DEVMETHOD(pcib_release_msix, nexus_release_msix),
#endif
@ -565,6 +567,13 @@ nexus_alloc_msix(device_t pcib, device_t dev, int index, int *irq)
return (error);
}
static int
nexus_remap_msix(device_t pcib, device_t dev, int index, int irq)
{
return (msix_remap(index, irq));
}
static int
nexus_release_msix(device_t pcib, device_t dev, int irq)
{

View File

@ -149,6 +149,7 @@ int msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq,
void msi_init(void);
int msi_release(int* irqs, int count);
int msix_alloc(device_t dev, int index, int *irq, int *new);
int msix_remap(int index, int irq);
int msix_release(int irq);
#endif /* !LOCORE */

View File

@ -559,6 +559,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_alloc_msi, legacy_pcib_alloc_msi),
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, legacy_pcib_alloc_msix),
DEVMETHOD(pcib_remap_msix, pcib_remap_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
{ 0, 0 }
@ -652,6 +653,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_alloc_msi, pcib_alloc_msi),
DEVMETHOD(pcib_release_msi, pcib_release_msi),
DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix),
DEVMETHOD(pcib_remap_msix, pcib_remap_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
{0, 0}