Add support for polling the XHCI interrupt handler when
the regular interrupt handler is not working properly or in case of MSI interrupts which are not yet supported. Remove interrupt setup code for FreeBSD versions older than 700031. MFC after: 1 week PR: usb/179342
This commit is contained in:
parent
a9205626a7
commit
97d729cf33
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=251499
@ -90,6 +90,7 @@
|
|||||||
#ifdef USB_DEBUG
|
#ifdef USB_DEBUG
|
||||||
static int xhcidebug;
|
static int xhcidebug;
|
||||||
static int xhciroute;
|
static int xhciroute;
|
||||||
|
static int xhcipolling;
|
||||||
|
|
||||||
static SYSCTL_NODE(_hw_usb, OID_AUTO, xhci, CTLFLAG_RW, 0, "USB XHCI");
|
static SYSCTL_NODE(_hw_usb, OID_AUTO, xhci, CTLFLAG_RW, 0, "USB XHCI");
|
||||||
SYSCTL_INT(_hw_usb_xhci, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
|
SYSCTL_INT(_hw_usb_xhci, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
|
||||||
@ -98,6 +99,9 @@ TUNABLE_INT("hw.usb.xhci.debug", &xhcidebug);
|
|||||||
SYSCTL_INT(_hw_usb_xhci, OID_AUTO, xhci_port_route, CTLFLAG_RW | CTLFLAG_TUN,
|
SYSCTL_INT(_hw_usb_xhci, OID_AUTO, xhci_port_route, CTLFLAG_RW | CTLFLAG_TUN,
|
||||||
&xhciroute, 0, "Routing bitmap for switching EHCI ports to XHCI controller");
|
&xhciroute, 0, "Routing bitmap for switching EHCI ports to XHCI controller");
|
||||||
TUNABLE_INT("hw.usb.xhci.xhci_port_route", &xhciroute);
|
TUNABLE_INT("hw.usb.xhci.xhci_port_route", &xhciroute);
|
||||||
|
SYSCTL_INT(_hw_usb_xhci, OID_AUTO, use_polling, CTLFLAG_RW | CTLFLAG_TUN,
|
||||||
|
&xhcipolling, 0, "Set to enable software interrupt polling for XHCI controller");
|
||||||
|
TUNABLE_INT("hw.usb.xhci.use_polling", &xhcipolling);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define XHCI_INTR_ENDPT 1
|
#define XHCI_INTR_ENDPT 1
|
||||||
@ -194,6 +198,16 @@ xhci_get_port_route(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
xhci_use_polling(void)
|
||||||
|
{
|
||||||
|
#ifdef USB_DEBUG
|
||||||
|
return (xhcipolling != 0);
|
||||||
|
#else
|
||||||
|
return (0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
|
xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
|
||||||
{
|
{
|
||||||
|
@ -438,6 +438,8 @@ struct xhci_softc {
|
|||||||
/* configure message */
|
/* configure message */
|
||||||
struct usb_bus_msg sc_config_msg[2];
|
struct usb_bus_msg sc_config_msg[2];
|
||||||
|
|
||||||
|
struct usb_callout sc_callout;
|
||||||
|
|
||||||
union xhci_hub_desc sc_hub_desc;
|
union xhci_hub_desc sc_hub_desc;
|
||||||
|
|
||||||
struct cv sc_cmd_cv;
|
struct cv sc_cmd_cv;
|
||||||
@ -500,6 +502,7 @@ struct xhci_softc {
|
|||||||
/* prototypes */
|
/* prototypes */
|
||||||
|
|
||||||
uint32_t xhci_get_port_route(void);
|
uint32_t xhci_get_port_route(void);
|
||||||
|
uint8_t xhci_use_polling(void);
|
||||||
usb_error_t xhci_halt_controller(struct xhci_softc *);
|
usb_error_t xhci_halt_controller(struct xhci_softc *);
|
||||||
usb_error_t xhci_init(struct xhci_softc *, device_t);
|
usb_error_t xhci_init(struct xhci_softc *, device_t);
|
||||||
usb_error_t xhci_start_controller(struct xhci_softc *);
|
usb_error_t xhci_start_controller(struct xhci_softc *);
|
||||||
|
@ -132,6 +132,16 @@ xhci_pci_probe(device_t self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xhci_interrupt_poll(void *_sc)
|
||||||
|
{
|
||||||
|
struct xhci_softc *sc = _sc;
|
||||||
|
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||||
|
xhci_interrupt(sc);
|
||||||
|
USB_BUS_LOCK(&sc->sc_bus);
|
||||||
|
usb_callout_reset(&sc->sc_callout, 1, (void *)&xhci_interrupt_poll, sc);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
xhci_pci_attach(device_t self)
|
xhci_pci_attach(device_t self)
|
||||||
{
|
{
|
||||||
@ -159,12 +169,13 @@ xhci_pci_attach(device_t self)
|
|||||||
sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
|
sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
|
||||||
sc->sc_io_size = rman_get_size(sc->sc_io_res);
|
sc->sc_io_size = rman_get_size(sc->sc_io_res);
|
||||||
|
|
||||||
|
usb_callout_init_mtx(&sc->sc_callout, &sc->sc_bus.bus_mtx, 0);
|
||||||
|
|
||||||
rid = 0;
|
rid = 0;
|
||||||
sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
|
sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
|
||||||
RF_SHAREABLE | RF_ACTIVE);
|
RF_SHAREABLE | RF_ACTIVE);
|
||||||
if (sc->sc_irq_res == NULL) {
|
if (sc->sc_irq_res == NULL) {
|
||||||
device_printf(self, "Could not allocate IRQ\n");
|
device_printf(self, "Could not allocate IRQ\n");
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
|
sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
|
||||||
if (sc->sc_bus.bdev == NULL) {
|
if (sc->sc_bus.bdev == NULL) {
|
||||||
@ -175,18 +186,22 @@ xhci_pci_attach(device_t self)
|
|||||||
|
|
||||||
sprintf(sc->sc_vendor, "0x%04x", pci_get_vendor(self));
|
sprintf(sc->sc_vendor, "0x%04x", pci_get_vendor(self));
|
||||||
|
|
||||||
#if (__FreeBSD_version >= 700031)
|
if (sc->sc_irq_res != NULL) {
|
||||||
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||||
NULL, (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl);
|
NULL, (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl);
|
||||||
#else
|
if (err != 0) {
|
||||||
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
device_printf(self, "Could not setup IRQ, err=%d\n", err);
|
||||||
(driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl);
|
sc->sc_intr_hdl = NULL;
|
||||||
#endif
|
}
|
||||||
if (err) {
|
|
||||||
device_printf(self, "Could not setup IRQ, err=%d\n", err);
|
|
||||||
sc->sc_intr_hdl = NULL;
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
if (sc->sc_irq_res == NULL || sc->sc_intr_hdl == NULL ||
|
||||||
|
xhci_use_polling() != 0) {
|
||||||
|
device_printf(self, "Interrupt polling at %dHz\n", hz);
|
||||||
|
USB_BUS_LOCK(&sc->sc_bus);
|
||||||
|
xhci_interrupt_poll(sc);
|
||||||
|
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||||
|
}
|
||||||
|
|
||||||
xhci_pci_take_controller(self);
|
xhci_pci_take_controller(self);
|
||||||
|
|
||||||
err = xhci_halt_controller(sc);
|
err = xhci_halt_controller(sc);
|
||||||
@ -222,12 +237,14 @@ xhci_pci_detach(device_t self)
|
|||||||
/* during module unload there are lots of children leftover */
|
/* during module unload there are lots of children leftover */
|
||||||
device_delete_children(self);
|
device_delete_children(self);
|
||||||
|
|
||||||
|
if (sc->sc_io_res) {
|
||||||
|
usb_callout_drain(&sc->sc_callout);
|
||||||
|
xhci_halt_controller(sc);
|
||||||
|
}
|
||||||
|
|
||||||
pci_disable_busmaster(self);
|
pci_disable_busmaster(self);
|
||||||
|
|
||||||
if (sc->sc_irq_res && sc->sc_intr_hdl) {
|
if (sc->sc_irq_res && sc->sc_intr_hdl) {
|
||||||
|
|
||||||
xhci_halt_controller(sc);
|
|
||||||
|
|
||||||
bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
|
bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
|
||||||
sc->sc_intr_hdl = NULL;
|
sc->sc_intr_hdl = NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user