From owner-svn-src-all@FreeBSD.ORG Mon Sep 28 07:46:23 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3BCE5106566C; Mon, 28 Sep 2009 07:46:23 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 219CB8FC0A; Mon, 28 Sep 2009 07:46:23 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n8S7kNM6047171; Mon, 28 Sep 2009 07:46:23 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n8S7kNm5047169; Mon, 28 Sep 2009 07:46:23 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <200909280746.n8S7kNm5047169@svn.freebsd.org> From: Andrew Thompson Date: Mon, 28 Sep 2009 07:46:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r197562 - head/sys/dev/usb X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Sep 2009 07:46:23 -0000 Author: thompsa Date: Mon Sep 28 07:46:22 2009 New Revision: 197562 URL: http://svn.freebsd.org/changeset/base/197562 Log: Add extra safety locking when clobbering xfer->flags_int.started in start and stop functions, because xfer->flags_int is also updated by the USB controller, under the controller lock. Submitted by: Hans Petter Selasky Modified: head/sys/dev/usb/usb_transfer.c Modified: head/sys/dev/usb/usb_transfer.c ============================================================================== --- head/sys/dev/usb/usb_transfer.c Mon Sep 28 07:42:59 2009 (r197561) +++ head/sys/dev/usb/usb_transfer.c Mon Sep 28 07:46:22 2009 (r197562) @@ -1332,7 +1332,9 @@ usbd_setup_ctrl_transfer(struct usb_xfer /* check if there is a length mismatch */ if (len > xfer->flags_int.control_rem) { - DPRINTFN(0, "Length greater than remaining length!\n"); + DPRINTFN(0, "Length (%d) greater than " + "remaining length (%d)!\n", len, + xfer->flags_int.control_rem); goto error; } /* check if we are doing a short transfer */ @@ -1620,7 +1622,10 @@ usbd_transfer_start(struct usb_xfer *xfe /* mark the USB transfer started */ if (!xfer->flags_int.started) { + /* lock the BUS lock to avoid races updating flags_int */ + USB_BUS_LOCK(xfer->xroot->bus); xfer->flags_int.started = 1; + USB_BUS_UNLOCK(xfer->xroot->bus); } /* check if the USB transfer callback is already transferring */ @@ -1655,14 +1660,21 @@ usbd_transfer_stop(struct usb_xfer *xfer /* check if the USB transfer was ever opened */ if (!xfer->flags_int.open) { - /* nothing to do except clearing the "started" flag */ - xfer->flags_int.started = 0; + if (xfer->flags_int.started) { + /* nothing to do except clearing the "started" flag */ + /* lock the BUS lock to avoid races updating flags_int */ + USB_BUS_LOCK(xfer->xroot->bus); + xfer->flags_int.started = 0; + USB_BUS_UNLOCK(xfer->xroot->bus); + } return; } /* try to stop the current USB transfer */ USB_BUS_LOCK(xfer->xroot->bus); - xfer->error = USB_ERR_CANCELLED;/* override any previous error */ + /* override any previous error */ + xfer->error = USB_ERR_CANCELLED; + /* * Clear "open" and "started" when both private and USB lock * is locked so that we don't get a race updating "flags_int" @@ -2121,9 +2133,6 @@ usb_dma_delay_done_cb(void *arg) DPRINTFN(3, "Completed %p\n", xfer); - /* only delay once */ - xfer->flags_int.did_dma_delay = 1; - /* queue callback for execution, again */ usbd_transfer_done(xfer, 0); } @@ -2193,6 +2202,8 @@ usbd_transfer_done(struct usb_xfer *xfer */ if (!xfer->flags_int.transferring) { DPRINTF("not transferring\n"); + /* end of control transfer, if any */ + xfer->flags_int.control_act = 0; return; } /* only set transfer error if not already set */ @@ -2491,6 +2502,9 @@ usbd_callback_wrapper_sub(struct usb_xfe usb_timeout_t temp; + /* only delay once */ + xfer->flags_int.did_dma_delay = 1; + /* we can not cancel this delay */ xfer->flags_int.can_cancel_immed = 0;