Use small lock to protect usbdev and endpoint in sim.
Signed-off-by: wangzhi16 <wangzhi16@xiaomi.com>
This commit is contained in:
parent
95f11e02c1
commit
4558db18e4
1 changed files with 36 additions and 21 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue