Fix problem with suspend and resume when using Skylake chipsets. Make
sure the XHCI controller is reset after halting it. The problem is clearly a BIOS bug as the suspend and resume is failing without loading the XHCI driver. The same happens when using Linux and the XHCI driver is not loaded. Submitted by: Yanko Yankulov <yanko.yankulov@gmail.com> PR: 216261 MFC after: 1 week
This commit is contained in:
parent
a9d8825913
commit
69cdfeb2a7
@ -347,6 +347,7 @@ xhci_start_controller(struct xhci_softc *sc)
|
||||
struct usb_page_search buf_res;
|
||||
struct xhci_hw_root *phwr;
|
||||
struct xhci_dev_ctx_addr *pdctxa;
|
||||
usb_error_t err;
|
||||
uint64_t addr;
|
||||
uint32_t temp;
|
||||
uint16_t i;
|
||||
@ -358,22 +359,9 @@ xhci_start_controller(struct xhci_softc *sc)
|
||||
sc->sc_command_ccs = 1;
|
||||
sc->sc_command_idx = 0;
|
||||
|
||||
/* Reset controller */
|
||||
XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_HCRST);
|
||||
|
||||
for (i = 0; i != 100; i++) {
|
||||
usb_pause_mtx(NULL, hz / 100);
|
||||
temp = (XREAD4(sc, oper, XHCI_USBCMD) & XHCI_CMD_HCRST) |
|
||||
(XREAD4(sc, oper, XHCI_USBSTS) & XHCI_STS_CNR);
|
||||
if (!temp)
|
||||
break;
|
||||
}
|
||||
|
||||
if (temp) {
|
||||
device_printf(sc->sc_bus.parent, "Controller "
|
||||
"reset timeout.\n");
|
||||
return (USB_ERR_IOERROR);
|
||||
}
|
||||
err = xhci_reset_controller(sc);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
/* set up number of device slots */
|
||||
DPRINTF("CONFIG=0x%08x -> 0x%08x\n",
|
||||
@ -520,6 +508,33 @@ xhci_halt_controller(struct xhci_softc *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
usb_error_t
|
||||
xhci_reset_controller(struct xhci_softc *sc)
|
||||
{
|
||||
uint32_t temp = 0;
|
||||
uint16_t i;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
/* Reset controller */
|
||||
XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_HCRST);
|
||||
|
||||
for (i = 0; i != 100; i++) {
|
||||
usb_pause_mtx(NULL, hz / 100);
|
||||
temp = (XREAD4(sc, oper, XHCI_USBCMD) & XHCI_CMD_HCRST) |
|
||||
(XREAD4(sc, oper, XHCI_USBSTS) & XHCI_STS_CNR);
|
||||
if (!temp)
|
||||
break;
|
||||
}
|
||||
|
||||
if (temp) {
|
||||
device_printf(sc->sc_bus.parent, "Controller "
|
||||
"reset timeout.\n");
|
||||
return (USB_ERR_IOERROR);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
usb_error_t
|
||||
xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32)
|
||||
{
|
||||
@ -671,10 +686,12 @@ xhci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state)
|
||||
case USB_HW_POWER_SUSPEND:
|
||||
DPRINTF("Stopping the XHCI\n");
|
||||
xhci_halt_controller(sc);
|
||||
xhci_reset_controller(sc);
|
||||
break;
|
||||
case USB_HW_POWER_SHUTDOWN:
|
||||
DPRINTF("Stopping the XHCI\n");
|
||||
xhci_halt_controller(sc);
|
||||
xhci_reset_controller(sc);
|
||||
break;
|
||||
case USB_HW_POWER_RESUME:
|
||||
DPRINTF("Starting the XHCI\n");
|
||||
|
@ -525,6 +525,7 @@ struct xhci_softc {
|
||||
|
||||
uint8_t xhci_use_polling(void);
|
||||
usb_error_t xhci_halt_controller(struct xhci_softc *);
|
||||
usb_error_t xhci_reset_controller(struct xhci_softc *);
|
||||
usb_error_t xhci_init(struct xhci_softc *, device_t, uint8_t);
|
||||
usb_error_t xhci_start_controller(struct xhci_softc *);
|
||||
void xhci_interrupt(struct xhci_softc *);
|
||||
|
@ -348,6 +348,7 @@ xhci_pci_detach(device_t self)
|
||||
|
||||
usb_callout_drain(&sc->sc_callout);
|
||||
xhci_halt_controller(sc);
|
||||
xhci_reset_controller(sc);
|
||||
|
||||
pci_disable_busmaster(self);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user