Commit 1a1fd436 authored by Robert Sprowson's avatar Robert Sprowson

Improve transfer callout handling

xhci.c: Merge changes from NetBSD 1.28.2.51; previously timeouts were only applied to control transfers and were cancelled post transfer complete, now all transfer types are covered and are called prior to usbd_transfer_complete() being called.
glue.c: More faithfully implement callout_reset(). The spec for this function is supposed to extend a callout for ones that are already running, but since the callx library ultimately uses OS_CallAfter what actually happened was two callafters were scheduled. This caused a NULL pointer exception if USBDriver cancelled a transaction before the timeout completed (because the cancel caused a 2nd OS_CallAfter to be scheduled, but the cancel caused usbd_transfer_complete() to consume then free the xfer, then the 2nd OS_CallAfter fired and passed a free'd list to usbd_transfer_complete()).

Also removed redundant headers usb_mem.h and usb_quirks.h.
Tested over 3 weeks on a Titanium (waiting for the right sequence of events to cause 2 OS_CallAfters to trigger took several days each!).

Version 0.19. Tagged as 'XHCIDriver-0_19'
parent 98cfb82d
/* (0.18)
/* (0.19)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.18
#define Module_MajorVersion_CMHG 0.19
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 30 Jun 2017
#define Module_Date_CMHG 13 Jul 2017
#define Module_MajorVersion "0.18"
#define Module_Version 18
#define Module_MajorVersion "0.19"
#define Module_Version 19
#define Module_MinorVersion ""
#define Module_Date "30 Jun 2017"
#define Module_Date "13 Jul 2017"
#define Module_ApplicationDate "30-Jun-17"
#define Module_ApplicationDate "13-Jul-17"
#define Module_ComponentName "XHCIDriver"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/USB/Controllers/XHCIDriver"
#define Module_FullVersion "0.18"
#define Module_HelpVersion "0.18 (30 Jun 2017)"
#define Module_LibraryVersionInfo "0:18"
#define Module_FullVersion "0.19"
#define Module_HelpVersion "0.19 (13 Jul 2017)"
#define Module_LibraryVersionInfo "0:19"
......@@ -51,8 +51,6 @@
#include "dev/usb/usb.h"
#include "dev/usb/usbdi.h"
#include "dev/usb/usbdivar.h"
#include "dev/usb/usb_mem.h"
#include "dev/usb/usb_quirks.h"
#include "glue.h"
......@@ -231,11 +229,17 @@ static _kernel_oserror *callout_handler(_kernel_swi_regs *r, void *pw, void *arg
void callout_stop(struct callout *c)
{
c->c_func = NULL;
callx_remove_callafter(callout_handler, c);
}
void callout_reset(struct callout *c, int i, void (*f)(void *), void *v)
{
if ((c->c_arg == v) && (c->c_func == f))
{
/* Reschedule existing (cancel then rebook) */
callout_stop(c);
}
c->c_arg = v;
c->c_func = f;
......@@ -373,8 +377,6 @@ void usb_delay_ms(usbd_bus_handle h, u_int d)
UNUSED(h);
}
const struct usbd_quirks usbd_no_quirk = { 0 };
const char *usbd_errstr(usbd_status s)
{
UNUSED(s);
......
......@@ -73,8 +73,6 @@ __KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.29 2015/08/19 06:23:35 skrll Exp $");
#include "dev/usb/usb.h"
#include "dev/usb/usbdi.h"
#include "dev/usb/usbdivar.h"
#include "dev/usb/usb_mem.h"
#include "dev/usb/usb_quirks.h"
#include "dev/usb/usbroothub_subr.h"
#include "glue.h"
......@@ -1649,9 +1647,15 @@ xhci_handle_event(struct xhci_softc * const sc,
//mutex_enter(&sc->sc_lock); /* XXX ??? */
if ((trb_3 & XHCI_TRB_3_ED_BIT) != 0) {
if ((trb_0 & 0x3) == 0x0) {
#ifdef BRANCH_NHUSB /* timeout cancel */
callout_stop(&xfer->timeout_handle);
#endif
usb_transfer_complete(xfer);
}
} else {
#ifdef BRANCH_NHUSB /* timeout cancel */
callout_stop(&xfer->timeout_handle);
#endif
usb_transfer_complete(xfer);
}
//mutex_exit(&sc->sc_lock); /* XXX ??? */
......@@ -3356,8 +3360,9 @@ xhci_device_ctrl_done(usbd_xfer_handle xfer)
{
XHCIHIST_FUNC(); XHCIHIST_CALLED();
#ifndef BRANCH_NHUSB
callout_stop(&xfer->timeout_handle); /* XXX wrong place */
#endif
}
static void
......@@ -3454,6 +3459,13 @@ xhci_device_bulk_start(usbd_xfer_handle xfer)
xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci);
#ifdef BRANCH_NHUSB /* timeout start */
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle, mstohz(xfer->timeout),
xhci_timeout, xfer);
}
#endif
if (sc->sc_bus.use_polling) {
DPRINTFN(1, "polling", 0, 0, 0, 0);
//xhci_waitintr(sc, xfer);
......@@ -3476,7 +3488,9 @@ xhci_device_bulk_done(usbd_xfer_handle xfer)
DPRINTFN(15, "%p slot %u dci %u", xfer, xs->xs_idx, dci, 0);
#ifndef BRANCH_NHUSB
callout_stop(&xfer->timeout_handle); /* XXX wrong place */
#endif
usb_syncmem(&xfer->dmabuf, 0, xfer->length,
isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
......@@ -3564,6 +3578,13 @@ xhci_device_intr_start(usbd_xfer_handle xfer)
xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci);
#ifdef BRANCH_NHUSB /* timeout start */
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle, mstohz(xfer->timeout),
xhci_timeout, xfer);
}
#endif
if (sc->sc_bus.use_polling) {
DPRINTFN(1, "polling", 0, 0, 0, 0);
//xhci_waitintr(sc, xfer);
......@@ -3603,10 +3624,11 @@ xhci_device_intr_done(usbd_xfer_handle xfer)
if (xfer->pipe->repeat) {
xfer->status = xhci_device_intr_start(xfer);
#ifndef BRANCH_NHUSB
} else {
callout_stop(&xfer->timeout_handle); /* XXX */
#endif
}
}
static void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment