summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-09-10 11:38:40 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-09-10 11:38:40 -0600
commit669c2200146850f70228b5a1323156c506f8e224 (patch)
tree1548ad36f83852e0c11eb94fc5d131927664cc91
parent2a9410a2ae8ce12d6c0bbf768d6d8d82281d97c9 (diff)
downloadnuttx-669c2200146850f70228b5a1323156c506f8e224.tar.gz
nuttx-669c2200146850f70228b5a1323156c506f8e224.tar.bz2
nuttx-669c2200146850f70228b5a1323156c506f8e224.zip
Fix a reference counting error in the USB host mass storage class
-rw-r--r--nuttx/ChangeLog4
-rw-r--r--nuttx/configs/sama5d3x-ek/README.txt97
-rw-r--r--nuttx/drivers/usbhost/usbhost_storage.c54
3 files changed, 117 insertions, 38 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 9be16a33a..8aa5efa1a 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -5526,4 +5526,8 @@
transfer errors while attempt to initialize, don't bother with
the startup retries; abort immediately so that the device will
be reset and we can try again (2013-9-9).
+ * drivers/usbhost/usbhost_storagge: Correct a reference counting
+ error: When an MSC device transfer fails while waiting for
+ UnitTestReady (see 2013-9-9), the reference count was not being
+ decremented. The end result is a memory leak (2013-9-10).
diff --git a/nuttx/configs/sama5d3x-ek/README.txt b/nuttx/configs/sama5d3x-ek/README.txt
index 0716476d0..7e9a58040 100644
--- a/nuttx/configs/sama5d3x-ek/README.txt
+++ b/nuttx/configs/sama5d3x-ek/README.txt
@@ -1039,6 +1039,7 @@ Configurations
7. The USB high-speed EHCI and the low-/full- OHCI host drivers are supported
in this configuration.
+
Here are the relevant configuration options that enable EHCI support:
System Type -> ATSAMA5 Peripheral Support
@@ -1064,24 +1065,64 @@ Configurations
Application Configuration -> NSH Library
CONFIG_NSH_ARCHINIT=y : NSH board-initialization
+ Example Usage:
+
+ NuttShell (NSH) NuttX-6.29
+ nsh> ls /dev
+ /dev:
+ console
+ mtdblock0
+ null
+ ttyS0
+
+ Here a USB FLASH stick is inserted. Nothing visible happens in the
+ the shell. But a new device will appear:
+
+ nsh> ls /dev
+ /dev:
+ console
+ mtdblock0
+ null
+ sda
+ ttyS0
+ nsh> mount -t vfat /dev/sda /mnt/sda
+ nsh> ls -l /mnt/sda
+ /mnt/sda:
+ -rw-rw-rw- 8788 viminfo
+ drw-rw-rw- 0 .Trash-1000/
+ -rw-rw-rw- 3378 zmodem.patch
+ -rw-rw-rw- 1503 sz-1.log
+ -rw-rw-rw- 613 .bashrc
+
The following features are *not* enabled in the demo configuration but
might be of some use to you:
- 8. Debugging USB Device. There is normal console debug output available
- that can be enabled with CONFIG_DEBUG + CONFIG_DEBUG_USB. However,
- USB device operation is very time critical and enabling this debug
- output WILL interfere with the operation of the UDPHS. USB device
- tracing is a less invasive way to get debug information: If tracing
- is enabled, the USB device will save encoded trace output in in-memory
- buffer; if the USB monitor is also enabled, that trace buffer will be
- periodically emptied and dumped to the system logging device (the
- serial console in this configuration):
+ 8. Debugging USB. There is normal console debug output available that
+ can be enabled with CONFIG_DEBUG + CONFIG_DEBUG_USB. However, USB
+ operation is very time critical and enabling this debug output WILL
+ interfere with some operation. USB tracing is a less invasive way
+ to get debug information: If tracing is enabled, the USB driver(s)
+ will save encoded trace output in in-memory buffers; if the USB
+ monitor is also enabled, those trace buffers will be periodically
+ emptied and dumped to the system logging device (the serial console
+ in this configuration):
+
+ Either or both USB device or host controller driver tracing can
+ be enabled:
Device Drivers -> "USB Device Driver Support:
- CONFIG_USBDEV_TRACE=y : Enable USB trace feature
+ CONFIG_USBDEV_TRACE=y : Enable USB device trace feature
CONFIG_USBDEV_TRACE_NRECORDS=256 : Buffer 256 records in memory
CONFIG_USBDEV_TRACE_STRINGS=y : (optional)
+ Device Drivers -> "USB Host Driver Support:
+ CONFIG_USBHOST_TRACE=y : Enable USB host trace feature
+ CONFIG_USBHOST_TRACE_NRECORDS=256 : Buffer 256 records in memory
+ CONFIG_USBHOST_TRACE_VERBOSE=y : Buffer everything
+
+ These settings will configure the USB monitor thread which will dump the
+ buffered USB debug data once every second:
+
Application Configuration -> NSH LIbrary:
CONFIG_NSH_USBDEV_TRACE=n : No builtin tracing from NSH
CONFIG_NSH_ARCHINIT=y : Automatically start the USB monitor
@@ -1459,6 +1500,41 @@ Configurations
Application Configuration -> NSH Library
CONFIG_NSH_ARCHINIT=y : NSH board-initialization
+ Debugging USB Host. There is normal console debug output available
+ that can be enabled with CONFIG_DEBUG + CONFIG_DEBUG_USB. However,
+ USB host operation is very time critical and enabling this debug
+ output might interfere with the operation of the UDPHS. USB host
+ tracing is a less invasive way to get debug information: If tracing
+ is enabled, the USB host will save encoded trace output in in-memory
+ buffer; if the USB monitor is also enabled, that trace buffer will be
+ periodically emptied and dumped to the system logging device (the
+ serial console in this configuration):
+
+ Device Drivers -> "USB Host Driver Support:
+ CONFIG_USBHOST_TRACE=y : Enable USB host trace feature
+ CONFIG_USBHOST_TRACE_NRECORDS=256 : Buffer 256 records in memory
+ CONFIG_USBHOST_TRACE_VERBOSE=y : Buffer everything
+
+ Application Configuration -> NSH LIbrary:
+ CONFIG_NSH_USBDEV_TRACE=n : No builtin tracing from NSH
+ CONFIG_NSH_ARCHINIT=y : Automatically start the USB monitor
+
+ Application Configuration -> System NSH Add-Ons:
+ CONFIG_SYSTEM_USBMONITOR=y : Enable the USB monitor daemon
+ CONFIG_SYSTEM_USBMONITOR_STACKSIZE=2048 : USB monitor daemon stack size
+ CONFIG_SYSTEM_USBMONITOR_PRIORITY=50 : USB monitor daemon priority
+ CONFIG_SYSTEM_USBMONITOR_INTERVAL=1 : Dump trace data every second
+ CONFIG_SYSTEM_USBMONITOR_TRACEINIT=y : Enable TRACE output
+ CONFIG_SYSTEM_USBMONITOR_TRACECLASS=y
+ CONFIG_SYSTEM_USBMONITOR_TRACETRANSFERS=y
+ CONFIG_SYSTEM_USBMONITOR_TRACECONTROLLER=y
+ CONFIG_SYSTEM_USBMONITOR_TRACEINTERRUPTS=y
+
+ NOTE: If USB debug output is also enabled, both outpus will appear
+ on the serial console. However, the debug output will be
+ asynchronous with the trace output and, hence, difficult to
+ interpret.
+
12. Support the USB high-speed USB device driver (UDPHS) can be enabled
by changing the NuttX configuration file as follows:
@@ -1503,6 +1579,7 @@ Configurations
Device Drivers -> "USB Device Driver Support:
CONFIG_USBDEV_TRACE=y : Enable USB trace feature
CONFIG_USBDEV_TRACE_NRECORDS=256 : Buffer 256 records in memory
+ CONFIG_USBDEV_TRACE_STRINGS=y : (optional)
Application Configuration -> NSH LIbrary:
CONFIG_NSH_USBDEV_TRACE=n : No builtin tracing from NSH
diff --git a/nuttx/drivers/usbhost/usbhost_storage.c b/nuttx/drivers/usbhost/usbhost_storage.c
index c6126131f..e0d662286 100644
--- a/nuttx/drivers/usbhost/usbhost_storage.c
+++ b/nuttx/drivers/usbhost/usbhost_storage.c
@@ -1322,45 +1322,43 @@ static inline int usbhost_initvolume(FAR struct usbhost_state_s *priv)
ret = register_blockdriver(devname, &g_bops, 0, priv);
}
- /* Check if we successfully initialized. We now have to be concerned
- * about asynchronous modification of crefs because the block
+ /* Decrement the reference count. We incremented the reference count
+ * above so that usbhost_destroy() could not be called. We now have to
+ * be concerned about asynchronous modification of crefs because the block
* driver has been registerd.
*/
- if (ret == OK)
- {
- usbhost_takesem(&priv->exclsem);
- DEBUGASSERT(priv->crefs >= 2);
-
- /* Decrement the reference count */
-
- priv->crefs--;
+ usbhost_takesem(&priv->exclsem);
+ DEBUGASSERT(priv->crefs >= 2);
- /* Handle a corner case where (1) open() has been called so the
- * reference count was > 2, but the device has been disconnected.
- * In this case, the class instance needs to persist until close()
- * is called.
- */
+ /* Decrement the reference count */
- if (priv->crefs <= 1 && priv->disconnected)
- {
- /* The will cause the enumeration logic to disconnect
- * the class driver.
- */
+ priv->crefs--;
- ret = -ENODEV;
- }
+ /* Check if we successfully initialized. If so, handle a corner case
+ * where (1) open() has been called so the reference count was > 2, but
+ * the device has been disconnected. In this case, the class instance
+ * needs to persist until close()
+ * is called.
+ */
- /* Release the semaphore... there is a race condition here.
- * Decrementing the reference count and releasing the semaphore
- * allows usbhost_destroy() to execute (on the worker thread);
- * the class driver instance could get destoryed before we are
- * ready to handle it!
+ if (ret == OK && priv->crefs <= 1 && priv->disconnected)
+ {
+ /* The will cause the enumeration logic to disconnect the class
+ * driver.
*/
- usbhost_givesem(&priv->exclsem);
+ ret = -ENODEV;
}
+ /* Release the semaphore... there is a race condition here.
+ * Decrementing the reference count and releasing the semaphore
+ * allows usbhost_destroy() to execute (on the worker thread);
+ * the class driver instance could get destroyed before we are
+ * ready to handle it!
+ */
+
+ usbhost_givesem(&priv->exclsem);
return ret;
}