Support MSI-X for passthrough devices with a separate PBA BAR.
pci_alloc_msix() requires both the table and PBA BARs to be allocated by the driver. ppt was only allocating the table BAR so would fail for devices with the PBA in a separate BAR. Fix this by allocating the PBA BAR before pci_alloc_msix() if it is stored in a separate BAR. While here, release BARs after calling pci_release_msi() instead of before. Also, don't call bus_teardown_intr() in error handling code if bus_setup_intr() has just failed. Reported by: gallatin Tested by: gallatin Reviewed by: rgrimes, markj MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D20525
This commit is contained in:
parent
004c60515d
commit
e1d9e7fdef
@ -102,7 +102,9 @@ struct pptdev {
|
||||
int num_msgs;
|
||||
int startrid;
|
||||
int msix_table_rid;
|
||||
int msix_pba_rid;
|
||||
struct resource *msix_table_res;
|
||||
struct resource *msix_pba_res;
|
||||
struct resource **res;
|
||||
void **cookie;
|
||||
struct pptintr_arg *arg;
|
||||
@ -292,6 +294,12 @@ ppt_teardown_msix(struct pptdev *ppt)
|
||||
for (i = 0; i < ppt->msix.num_msgs; i++)
|
||||
ppt_teardown_msix_intr(ppt, i);
|
||||
|
||||
free(ppt->msix.res, M_PPTMSIX);
|
||||
free(ppt->msix.cookie, M_PPTMSIX);
|
||||
free(ppt->msix.arg, M_PPTMSIX);
|
||||
|
||||
pci_release_msi(ppt->dev);
|
||||
|
||||
if (ppt->msix.msix_table_res) {
|
||||
bus_release_resource(ppt->dev, SYS_RES_MEMORY,
|
||||
ppt->msix.msix_table_rid,
|
||||
@ -299,12 +307,13 @@ ppt_teardown_msix(struct pptdev *ppt)
|
||||
ppt->msix.msix_table_res = NULL;
|
||||
ppt->msix.msix_table_rid = 0;
|
||||
}
|
||||
|
||||
free(ppt->msix.res, M_PPTMSIX);
|
||||
free(ppt->msix.cookie, M_PPTMSIX);
|
||||
free(ppt->msix.arg, M_PPTMSIX);
|
||||
|
||||
pci_release_msi(ppt->dev);
|
||||
if (ppt->msix.msix_pba_res) {
|
||||
bus_release_resource(ppt->dev, SYS_RES_MEMORY,
|
||||
ppt->msix.msix_pba_rid,
|
||||
ppt->msix.msix_pba_res);
|
||||
ppt->msix.msix_pba_res = NULL;
|
||||
ppt->msix.msix_pba_rid = 0;
|
||||
}
|
||||
|
||||
ppt->msix.num_msgs = 0;
|
||||
}
|
||||
@ -634,6 +643,19 @@ ppt_setup_msix(struct vm *vm, int vcpu, int bus, int slot, int func,
|
||||
}
|
||||
ppt->msix.msix_table_rid = rid;
|
||||
|
||||
if (dinfo->cfg.msix.msix_table_bar !=
|
||||
dinfo->cfg.msix.msix_pba_bar) {
|
||||
rid = dinfo->cfg.msix.msix_pba_bar;
|
||||
ppt->msix.msix_pba_res = bus_alloc_resource_any(
|
||||
ppt->dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
||||
|
||||
if (ppt->msix.msix_pba_res == NULL) {
|
||||
ppt_teardown_msix(ppt);
|
||||
return (ENOSPC);
|
||||
}
|
||||
ppt->msix.msix_pba_rid = rid;
|
||||
}
|
||||
|
||||
alloced = numvec;
|
||||
error = pci_alloc_msix(ppt->dev, &alloced);
|
||||
if (error || alloced != numvec) {
|
||||
@ -665,7 +687,6 @@ ppt_setup_msix(struct vm *vm, int vcpu, int bus, int slot, int func,
|
||||
&ppt->msix.cookie[idx]);
|
||||
|
||||
if (error != 0) {
|
||||
bus_teardown_intr(ppt->dev, ppt->msix.res[idx], ppt->msix.cookie[idx]);
|
||||
bus_release_resource(ppt->dev, SYS_RES_IRQ, rid, ppt->msix.res[idx]);
|
||||
ppt->msix.cookie[idx] = NULL;
|
||||
ppt->msix.res[idx] = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user