xhci: Handle the case when MSI-X BAR is the same as IO BAR.

PCIe allows for MSI-X BAR to be either dedicated, or MSI-X Table may
be co-located in some functional BAR.  In the later case xhci(4) is
unable to allocate active resource for the table because BAR is
already activated.

Handle it by checking for this special case, and not try to alloc
resource if MSI-X BAR is IO.

Reported and tested by:	emaste
Reviewed by:	emaste, hselasky
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
Differential revision:	https://reviews.freebsd.org/D26913
This commit is contained in:
Konstantin Belousov 2020-10-23 18:18:45 +00:00
parent 573456a931
commit 116bc58260
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=366978

View File

@ -277,21 +277,29 @@ xhci_pci_attach(device_t self)
rid = 0;
if (xhci_use_msix && (msix_table = pci_msix_table_bar(self)) >= 0) {
sc->sc_msix_res = bus_alloc_resource_any(self, SYS_RES_MEMORY,
&msix_table, RF_ACTIVE);
if (sc->sc_msix_res == NULL) {
/* May not be enabled */
device_printf(self,
"Unable to map MSI-X table \n");
if (msix_table == PCI_XHCI_CBMEM) {
sc->sc_msix_res = sc->sc_io_res;
} else {
sc->sc_msix_res = bus_alloc_resource_any(self,
SYS_RES_MEMORY, &msix_table, RF_ACTIVE);
if (sc->sc_msix_res == NULL) {
/* May not be enabled */
device_printf(self,
"Unable to map MSI-X table\n");
}
}
if (sc->sc_msix_res != NULL) {
count = 1;
if (pci_alloc_msix(self, &count) == 0) {
if (bootverbose)
device_printf(self, "MSI-X enabled\n");
rid = 1;
} else {
bus_release_resource(self, SYS_RES_MEMORY,
msix_table, sc->sc_msix_res);
if (sc->sc_msix_res != sc->sc_io_res) {
bus_release_resource(self,
SYS_RES_MEMORY,
msix_table, sc->sc_msix_res);
}
sc->sc_msix_res = NULL;
}
}
@ -387,16 +395,16 @@ xhci_pci_detach(device_t self)
sc->sc_irq_res = NULL;
pci_release_msi(self);
}
if (sc->sc_msix_res != NULL && sc->sc_msix_res != sc->sc_io_res) {
bus_release_resource(self, SYS_RES_MEMORY,
rman_get_rid(sc->sc_msix_res), sc->sc_msix_res);
sc->sc_msix_res = NULL;
}
if (sc->sc_io_res) {
bus_release_resource(self, SYS_RES_MEMORY, PCI_XHCI_CBMEM,
sc->sc_io_res);
sc->sc_io_res = NULL;
}
if (sc->sc_msix_res) {
bus_release_resource(self, SYS_RES_MEMORY,
rman_get_rid(sc->sc_msix_res), sc->sc_msix_res);
sc->sc_msix_res = NULL;
}
xhci_uninit(sc);