This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 5571ec8fa29b902cc616aadd2727ad63d176d103 Author: yangsong8 <[email protected]> AuthorDate: Fri Jun 20 21:21:02 2025 +0800 drivers/usbhost: use small lock to protect usbhost msc replace critical_section with spinlock Signed-off-by: yangsong8 <[email protected]> --- drivers/usbhost/usbhost_storage.c | 52 +++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/drivers/usbhost/usbhost_storage.c b/drivers/usbhost/usbhost_storage.c index f4de798c78a..08fd719a4ec 100644 --- a/drivers/usbhost/usbhost_storage.c +++ b/drivers/usbhost/usbhost_storage.c @@ -25,6 +25,7 @@ ****************************************************************************/ #include <nuttx/config.h> +#include <nuttx/spinlock.h> #include <inttypes.h> #include <stdio.h> @@ -120,6 +121,7 @@ struct usbhost_state_s int16_t crefs; /* Reference count on the driver instance */ uint16_t blocksize; /* Block size of USB mass storage device */ uint32_t nblocks; /* Number of blocks on the USB mass storage device */ + spinlock_t spinlock; /* Used to protect critical section */ mutex_t lock; /* Used to maintain mutual exclusive access */ struct work_s work; /* For interacting with the worker thread */ FAR uint8_t *tbuffer; /* The allocated transfer buffer */ @@ -298,6 +300,8 @@ static FAR struct usbhost_freestate_s *g_freelist; static uint32_t g_devinuse; +static spinlock_t g_lock = SP_UNLOCKED; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -331,14 +335,14 @@ static inline FAR struct usbhost_state_s *usbhost_allocclass(void) * our pre-allocated class instances from the free list. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_lock); entry = g_freelist; if (entry) { g_freelist = entry->flink; } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_lock, flags); uinfo("Allocated: %p\n", entry); return (FAR struct usbhost_state_s *)entry; } @@ -387,10 +391,10 @@ static inline void usbhost_freeclass(FAR struct usbhost_state_s *usbclass) /* Just put the pre-allocated class structure back on the freelist */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_lock); entry->flink = g_freelist; g_freelist = entry; - leave_critical_section(flags); + spin_unlock_irqrestore(&g_lock, flags); } #else static inline void usbhost_freeclass(FAR struct usbhost_state_s *usbclass) @@ -420,7 +424,7 @@ static int usbhost_allocdevno(FAR struct usbhost_state_s *priv) irqstate_t flags; int devno; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_lock); for (devno = 0; devno < 26; devno++) { uint32_t bitno = 1 << devno; @@ -428,12 +432,12 @@ static int usbhost_allocdevno(FAR struct usbhost_state_s *priv) { g_devinuse |= bitno; priv->sdchar = 'a' + devno; - leave_critical_section(flags); + spin_unlock_irqrestore(&g_lock, flags); return OK; } } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_lock, flags); return -EMFILE; } @@ -443,9 +447,9 @@ static void usbhost_freedevno(FAR struct usbhost_state_s *priv) if (devno >= 0 && devno < 26) { - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&g_lock); g_devinuse &= ~(1 << devno); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_lock, flags); } } @@ -1703,6 +1707,7 @@ static FAR struct usbhost_class_s * */ nxmutex_init(&priv->lock); + spin_lock_init(&priv->spinlock); /* NOTE: We do not yet know the geometry of the USB mass storage * device. @@ -1825,7 +1830,7 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass) * device is no longer available. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); priv->disconnected = true; /* Now check the number of references on the class instance. If it is one, @@ -1834,7 +1839,6 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass) * block driver. */ - uinfo("crefs: %d\n", priv->crefs); if (priv->crefs == 1) { /* Destroy the class instance. If we are executing from an interrupt @@ -1842,6 +1846,7 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass) * Otherwise, destroy the instance now. */ + spin_unlock_irqrestore(&priv->spinlock, flags); if (up_interrupt_context()) { /* Destroy the instance on the worker thread. */ @@ -1857,9 +1862,11 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass) usbhost_destroy(priv); } + + return OK; } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return OK; } @@ -1894,7 +1901,7 @@ static int usbhost_open(FAR struct inode *inode) * disconnect events. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); if (priv->disconnected) { /* No... the block driver is no longer bound to the class. That means @@ -1912,7 +1919,7 @@ static int usbhost_open(FAR struct inode *inode) ret = OK; } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); nxmutex_unlock(&priv->lock); return ret; @@ -1939,20 +1946,13 @@ static int usbhost_close(FAR struct inode *inode) DEBUGASSERT(priv->crefs > 1); nxmutex_lock(&priv->lock); - priv->crefs--; - - /* Release the semaphore. The following operations when crefs == 1 are - * safe because we know that there is no outstanding open references to - * the block driver. - */ - - nxmutex_unlock(&priv->lock); /* We need to disable interrupts momentarily to assure that there are * no asynchronous disconnect events. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); + priv->crefs--; /* Check if the USB mass storage device is still connected. If the * storage device is not connected and the reference count just @@ -1965,10 +1965,14 @@ static int usbhost_close(FAR struct inode *inode) /* Destroy the class instance */ DEBUGASSERT(priv->crefs == 1); + spin_unlock_irqrestore(&priv->spinlock, flags); + nxmutex_unlock(&priv->lock); usbhost_destroy(priv); + return OK; } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); + nxmutex_unlock(&priv->lock); return OK; }
