From owner-svn-src-all@FreeBSD.ORG Tue Jun 2 17:30:18 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 C76CD1065672; Tue, 2 Jun 2009 17:30:18 +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 9BB298FC08; Tue, 2 Jun 2009 17:30:18 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n52HUItn022203; Tue, 2 Jun 2009 17:30:18 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n52HUIMQ022202; Tue, 2 Jun 2009 17:30:18 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <200906021730.n52HUIMQ022202@svn.freebsd.org> From: Andrew Thompson Date: Tue, 2 Jun 2009 17:30:18 +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: r193316 - 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: Tue, 02 Jun 2009 17:30:19 -0000 Author: thompsa Date: Tue Jun 2 17:30:18 2009 New Revision: 193316 URL: http://svn.freebsd.org/changeset/base/193316 Log: Fix multithread issue where the is_uref variable was not set and cleared properly in the CDEV private data. Submitted by: Hans Petter Selasky Modified: head/sys/dev/usb/usb_dev.c Modified: head/sys/dev/usb/usb_dev.c ============================================================================== --- head/sys/dev/usb/usb_dev.c Tue Jun 2 17:29:15 2009 (r193315) +++ head/sys/dev/usb/usb_dev.c Tue Jun 2 17:30:18 2009 (r193316) @@ -169,21 +169,23 @@ usb2_ref_device(struct usb_cdev_privdata cpd->bus = devclass_get_softc(usb2_devclass_ptr, cpd->bus_index); if (cpd->bus == NULL) { DPRINTFN(2, "no bus at %u\n", cpd->bus_index); + need_uref = 0; goto error; } cpd->udev = cpd->bus->devices[cpd->dev_index]; if (cpd->udev == NULL) { DPRINTFN(2, "no device at %u\n", cpd->dev_index); + need_uref = 0; goto error; } if (cpd->udev->refcount == USB_DEV_REF_MAX) { DPRINTFN(2, "no dev ref\n"); + need_uref = 0; goto error; } if (need_uref) { DPRINTFN(2, "ref udev - needed\n"); cpd->udev->refcount++; - cpd->is_uref = 1; mtx_unlock(&usb2_ref_lock); @@ -194,6 +196,11 @@ usb2_ref_device(struct usb_cdev_privdata sx_xlock(cpd->udev->default_sx + 1); mtx_lock(&usb2_ref_lock); + + /* + * Set "is_uref" after grabbing the default SX lock + */ + cpd->is_uref = 1; } /* check if we are doing an open */ @@ -258,18 +265,18 @@ usb2_ref_device(struct usb_cdev_privdata } mtx_unlock(&usb2_ref_lock); - if (cpd->is_uref) { + if (need_uref) { mtx_lock(&Giant); /* XXX */ } return (0); error: - if (cpd->is_uref) { + if (need_uref) { + cpd->is_uref = 0; sx_unlock(cpd->udev->default_sx + 1); if (--(cpd->udev->refcount) == 0) { usb2_cv_signal(cpd->udev->default_cv + 1); } - cpd->is_uref = 0; } mtx_unlock(&usb2_ref_lock); DPRINTFN(2, "fail\n"); @@ -289,10 +296,14 @@ error: static usb_error_t usb2_usb_ref_device(struct usb_cdev_privdata *cpd) { + uint8_t is_uref; + + is_uref = cpd->is_uref && sx_xlocked(cpd->udev->default_sx + 1); + /* * Check if we already got an USB reference on this location: */ - if (cpd->is_uref) + if (is_uref) return (0); /* success */ /* @@ -313,7 +324,12 @@ usb2_usb_ref_device(struct usb_cdev_priv void usb2_unref_device(struct usb_cdev_privdata *cpd) { - if (cpd->is_uref) { + uint8_t is_uref; + + is_uref = cpd->is_uref && sx_xlocked(cpd->udev->default_sx + 1); + + if (is_uref) { + cpd->is_uref = 0; mtx_unlock(&Giant); /* XXX */ sx_unlock(cpd->udev->default_sx + 1); } @@ -330,11 +346,10 @@ usb2_unref_device(struct usb_cdev_privda } cpd->is_write = 0; } - if (cpd->is_uref) { + if (is_uref) { if (--(cpd->udev->refcount) == 0) { usb2_cv_signal(cpd->udev->default_cv + 1); } - cpd->is_uref = 0; } mtx_unlock(&usb2_ref_lock); }