struct pci_devinfo *dinfo = device_get_ivars(child);
struct pcicfg_msi *msi = &dinfo->cfg.msi;
struct resource_list_entry *rle;
- int error, i, irqs[32];
+ int error, i, irqs[32], cpuid = -1;
/* Try MSI-X first. */
error = pci_release_msix(dev, child);
KASSERT(rle != NULL, ("missing MSI resource"));
if (rle->res != NULL)
return (EBUSY);
+ if (i == 0) {
+ cpuid = rle->cpuid;
+ KASSERT(cpuid >= 0 && cpuid < ncpus,
+ ("invalid MSI target cpuid %d\n", cpuid));
+ } else {
+ KASSERT(rle->cpuid == cpuid,
+ ("MSI targets different cpus, "
+ "was cpu%d, now cpu%d", cpuid, rle->cpuid));
+ }
irqs[i] = rle->start;
}
msi->msi_ctrl, 2);
/* Release the messages. */
- PCIB_RELEASE_MSI(device_get_parent(dev), child, msi->msi_alloc, irqs);
+ PCIB_RELEASE_MSI(device_get_parent(dev), child, msi->msi_alloc, irqs,
+ cpuid);
for (i = 0; i < msi->msi_alloc; i++)
resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i + 1);
/* Pass request to release MSI/MSI-X messages up to the parent bridge. */
int
-pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs)
+pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs, int cpuid)
{
device_t bus;
bus = device_get_parent(pcib);
- return (PCIB_RELEASE_MSI(device_get_parent(bus), dev, count, irqs));
+ return (PCIB_RELEASE_MSI(device_get_parent(bus), dev, count, irqs,
+ cpuid));
}
/* Pass request to alloc an MSI-X message up to the parent bridge. */
device_t dev;
int count;
int *irqs;
+ int cpuid;
};
#
void pcib_write_config(device_t dev, int b, int s, int f, int reg, uint32_t val, int width);
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 cpuid);
-int pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs);
+int pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs, int cpuid);
int pcib_alloc_msix(device_t pcib, device_t dev, int *irq);
int pcib_release_msix(device_t pcib, device_t dev, int irq);
int pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data);