diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2013-09-10 11:38:40 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2013-09-10 11:38:40 -0600 |
commit | 669c2200146850f70228b5a1323156c506f8e224 (patch) | |
tree | 1548ad36f83852e0c11eb94fc5d131927664cc91 | |
parent | 2a9410a2ae8ce12d6c0bbf768d6d8d82281d97c9 (diff) | |
download | nuttx-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/ChangeLog | 4 | ||||
-rw-r--r-- | nuttx/configs/sama5d3x-ek/README.txt | 97 | ||||
-rw-r--r-- | nuttx/drivers/usbhost/usbhost_storage.c | 54 |
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; } |