Use small lock to protect usbdev and endpoint in sim.

Signed-off-by: wangzhi16 <wangzhi16@xiaomi.com>
This commit is contained in:
wangzhi16 2025-01-15 15:55:33 +08:00 committed by Xiang Xiao
parent 95f11e02c1
commit 4558db18e4

View file

@ -36,9 +36,11 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
#include <nuttx/spinlock.h>
#include <nuttx/usb/usb.h>
#include <nuttx/usb/usbdev.h>
#include <nuttx/usb/usbdev_trace.h>
@ -156,6 +158,7 @@ struct sim_usbdev_s
uint8_t selfpowered:1; /* 1: Device is self powered */
uint16_t epavail; /* Bitset of available endpoints */
struct sim_ep_s eps[SIM_USB_EPNUM];
spinlock_t lock; /* Spinlock */
};
struct sim_req_s
@ -347,9 +350,9 @@ static void sim_reqcomplete(struct sim_ep_s *privep, int16_t result)
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
privreq = sim_rqdequeue(&privep->reqq);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
if (privreq)
{
@ -640,7 +643,8 @@ static int sim_ep_disable(struct usbdev_ep_s *ep)
/* Cancel any ongoing activity */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
/* Disable TX; disable RX */
@ -648,7 +652,8 @@ static int sim_ep_disable(struct usbdev_ep_s *ep)
privep->epstate = SIM_EPSTATE_DISABLED;
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@ -703,14 +708,16 @@ static int sim_ep_stall(struct usbdev_ep_s *ep, bool resume)
/* STALL or RESUME the endpoint */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, epno);
ret = host_usbdev_epstall(epno, resume);
privep->epstate = SIM_EPSTATE_STALLED;
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return ret;
}
@ -738,12 +745,14 @@ static int sim_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
epno = USB_EPNO(ep->eplog);
req->result = -EINPROGRESS;
req->xfrd = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
if (privep->epstate == SIM_EPSTATE_STALLED)
{
sim_reqabort(privep, privreq, -EBUSY);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return -EPERM;
}
@ -778,7 +787,8 @@ static int sim_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
sim_rqenqueue(&privep->reqq, privreq);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@ -788,13 +798,14 @@ static int sim_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
static int sim_ep_cancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
{
struct sim_ep_s *privep = (struct sim_ep_s *)ep;
irqstate_t flags;
usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog));
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
host_usbdev_epcancel(USB_EPNO(ep->eplog));
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
return OK;
}
@ -818,7 +829,7 @@ static struct sim_ep_s *sim_ep_reserve(struct sim_usbdev_s *priv,
irqstate_t flags;
int epndx = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
@ -843,7 +854,7 @@ static struct sim_ep_s *sim_ep_reserve(struct sim_usbdev_s *priv,
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return privep;
}
@ -860,9 +871,9 @@ static struct sim_ep_s *sim_ep_reserve(struct sim_usbdev_s *priv,
static void sim_ep_unreserve(struct sim_usbdev_s *priv,
struct sim_ep_s *privep)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= SIM_EP_BIT(USB_EPNO(privep->ep.eplog));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************
@ -1004,13 +1015,14 @@ static int sim_usbdev_selfpowered(struct usbdev_s *dev, bool selfpowered)
static int sim_usbdev_pullup(struct usbdev_s *dev, bool enable)
{
struct sim_usbdev_s *priv = (struct sim_usbdev_s *)dev;
irqstate_t flags;
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
host_usbdev_pullup(enable);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
@ -1059,6 +1071,9 @@ static void sim_usbdev_devinit(struct sim_usbdev_s *dev)
void sim_usbdev_initialize(void)
{
/* Initialize driver lock */
spin_lock_init(&g_sim_usbdev.lock);
}
/****************************************************************************
@ -1132,9 +1147,9 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
* canceled while the class driver is still bound.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
CLASS_DISCONNECT(driver, &priv->usbdev);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
/* Unbind the class driver */
@ -1142,7 +1157,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
/* Disable USB controller interrupts */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
/* Disconnect device */
@ -1152,7 +1167,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
/* Unhook the driver */
priv->driver = NULL;
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}