Use small lock to protect usbdev and endpoint in arch ARM.

Signed-off-by: wangzhi16 <wangzhi16@xiaomi.com>
This commit is contained in:
wangzhi16
2025-01-20 10:05:04 +08:00
committed by Xiang Xiao
parent 4857ea211f
commit e177ff9c0c
14 changed files with 969 additions and 419 deletions
+69 -27
View File
@@ -40,6 +40,7 @@
#include <debug.h>
#include <fcntl.h>
#include <stdio.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -49,6 +50,7 @@
#include <nuttx/fs/procfs.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <nuttx/signal.h>
#include <arch/chip/usbdev.h>
#include <arch/chip/pm.h>
@@ -383,6 +385,10 @@ struct cxd56_usbdev_s
int signo;
pid_t pid;
/* spinlock */
spinlock_t lock;
};
/* For maintaining tables of endpoint info */
@@ -784,17 +790,15 @@ static inline void cxd56_abortrequest(struct cxd56_ep_s *privep,
*
****************************************************************************/
static void cxd56_reqcomplete(struct cxd56_ep_s *privep, int16_t result)
static void cxd56_reqcomplete_nolock(struct cxd56_ep_s *privep,
int16_t result)
{
struct cxd56_req_s *privreq;
int stalled = privep->stalled;
irqstate_t flags;
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
privreq = cxd56_rqdequeue(privep);
leave_critical_section(flags);
if (privreq)
{
@@ -822,6 +826,17 @@ static void cxd56_reqcomplete(struct cxd56_ep_s *privep, int16_t result)
}
}
static void cxd56_reqcomplete(struct cxd56_ep_s *privep, int16_t result)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
/* Remove the completed request at the head of the endpoint request list */
cxd56_reqcomplete_nolock(privep, result);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
* Name: cxd56_txdmacomplete
*
@@ -1085,7 +1100,7 @@ static void cxd56_stopoutep(struct cxd56_ep_s *privep)
*
****************************************************************************/
static void cxd56_cancelrequests(struct cxd56_ep_s *privep)
static void cxd56_cancelrequests_nolock(struct cxd56_ep_s *privep)
{
if (privep->epphy > 0)
{
@@ -1103,7 +1118,7 @@ static void cxd56_cancelrequests(struct cxd56_ep_s *privep)
{
usbtrace(TRACE_COMPLETE(privep->epphy),
(cxd56_rqpeek(privep))->req.xfrd);
cxd56_reqcomplete(privep, -ESHUTDOWN);
cxd56_reqcomplete_nolock(privep, -ESHUTDOWN);
}
if (privep->epphy > 0)
@@ -1119,6 +1134,17 @@ static void cxd56_cancelrequests(struct cxd56_ep_s *privep)
}
}
static void cxd56_cancelrequests(struct cxd56_ep_s *privep)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
cxd56_cancelrequests_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
}
/****************************************************************************
* Name: cxd56_epfindbyaddr
*
@@ -2269,10 +2295,12 @@ static int cxd56_epdisable(struct usbdev_ep_s *ep)
/* Cancel any ongoing activity and reset the endpoint */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
cxd56_epstall(&privep->ep, false);
cxd56_cancelrequests(privep);
leave_critical_section(flags);
cxd56_cancelrequests_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2411,7 +2439,8 @@ static int cxd56_epsubmit(struct usbdev_ep_s *ep,
req->result = -EINPROGRESS;
req->xfrd = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* If we are stalled, then drop all requests on the floor, except OUT */
@@ -2442,7 +2471,7 @@ static int cxd56_epsubmit(struct usbdev_ep_s *ep,
*/
usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
cxd56_reqcomplete(privep, OK);
cxd56_reqcomplete_nolock(privep, OK);
}
if (priv->ctrl.req == USB_REQ_SETCONFIGURATION)
@@ -2515,7 +2544,8 @@ static int cxd56_epsubmit(struct usbdev_ep_s *ep,
ret = cxd56_rdrequest(privep);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -2543,9 +2573,11 @@ static int cxd56_epcancel(struct usbdev_ep_s *ep,
usbtrace(TRACE_EPCANCEL, privep->epphy);
flags = enter_critical_section();
cxd56_cancelrequests(privep);
leave_critical_section(flags);
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
cxd56_cancelrequests_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2725,12 +2757,12 @@ static struct usbdev_ep_s *cxd56_allocep(struct usbdev_s *dev,
continue;
}
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
priv->avail &= ~(1 << ndx);
mask = getreg32(CXD56_USB_DEV_EP_INTR_MASK);
mask &= ~(1 << ndx << (in ? 0 : 16));
putreg32(mask, CXD56_USB_DEV_EP_INTR_MASK);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return &priv->eplist[ndx].ep;
}
}
@@ -2758,9 +2790,9 @@ static void cxd56_freeep(struct usbdev_s *dev,
cxd56_freeepbuffer(privep);
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
pdev->avail |= 1 << privep->epphy;
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
@@ -2773,6 +2805,7 @@ static void cxd56_freeep(struct usbdev_s *dev,
static int cxd56_getframe(struct usbdev_s *dev)
{
struct cxd56_usbdev_s *priv = (struct cxd56_usbdev_s *)dev;
irqstate_t flags;
int ret = 0;
@@ -2790,9 +2823,9 @@ static int cxd56_getframe(struct usbdev_s *dev)
* because the operation is not atomic.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
ret = getreg32(CXD56_USB_DEV_STATUS) >> 18;
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}
@@ -2806,13 +2839,14 @@ static int cxd56_getframe(struct usbdev_s *dev)
static int cxd56_wakeup(struct usbdev_s *dev)
{
struct cxd56_usbdev_s *priv = (struct cxd56_usbdev_s *)dev;
irqstate_t flags;
usbtrace(TRACE_DEVWAKEUP, 0);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
putreg32(getreg32(CXD56_USB_DEV_CONTROL) | 1, CXD56_USB_DEV_CONTROL);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
@@ -3076,6 +3110,10 @@ void arm_usbinitialize(void)
cxd56_usb_clock_enable();
/* Initialize driver lock */
spin_lock_init(&g_usbdev.lock);
if (irq_attach(CXD56_IRQ_USB_SYS, cxd56_sysinterrupt, &g_usbdev) != 0)
{
usbtrace(TRACE_DEVERROR(CXD56_TRACEERR_ATTACHIRQREG), 0);
@@ -3135,7 +3173,8 @@ void arm_usbuninitialize(void)
usbdev_unregister(priv->driver);
}
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
cxd56_pullup(&priv->usbdev, false);
priv->usbdev.speed = USB_SPEED_UNKNOWN;
@@ -3152,7 +3191,8 @@ void arm_usbuninitialize(void)
irq_detach(CXD56_IRQ_USB_VBUSN);
cxd56_usb_clock_disable();
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
/* Clear signal */
@@ -3246,7 +3286,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
CLASS_UNBIND(driver, &g_usbdev.usbdev);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* Disable IRQs */
@@ -3266,7 +3307,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
cxd56_usbhwuninit();
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
up_pm_release_freqlock(&g_hv_lock);
up_pm_release_wakelock(&g_wake_lock);
+62 -20
View File
@@ -34,6 +34,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -42,6 +43,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include "chip.h"
@@ -233,6 +235,10 @@ struct dm320_usbdev_s
/* The endpoint list */
struct dm320_ep_s eplist[DM320_NENDPOINTS];
/* Spinlock */
spinlock_t lock;
};
/* For maintaining tables of endpoint info */
@@ -892,17 +898,15 @@ static inline void dm320_abortrequest(struct dm320_ep_s *privep,
*
****************************************************************************/
static void dm320_reqcomplete(struct dm320_ep_s *privep, int16_t result)
static void dm320_reqcomplete_nolock(struct dm320_ep_s *privep,
int16_t result)
{
struct dm320_req_s *privreq;
int stalled = privep->stalled;
irqstate_t flags;
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
privreq = dm320_rqdequeue(privep);
leave_critical_section(flags);
if (privreq)
{
@@ -933,6 +937,17 @@ static void dm320_reqcomplete(struct dm320_ep_s *privep, int16_t result)
}
}
static void dm320_reqcomplete(struct dm320_ep_s *privep, int16_t result)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
/* Remove the completed request at the head of the endpoint request list */
cxd56_reqcomplete_nolock(privep, result);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
* Name: dm320_wrrequest
*
@@ -944,7 +959,7 @@ static void dm320_reqcomplete(struct dm320_ep_s *privep, int16_t result)
*
****************************************************************************/
static int dm320_wrrequest(struct dm320_ep_s *privep)
static int dm320_wrrequest_nolock(struct dm320_ep_s *privep)
{
struct dm320_req_s *privreq;
uint8_t *buf;
@@ -1019,7 +1034,7 @@ static int dm320_wrrequest(struct dm320_ep_s *privep)
{
usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
privep->txnullpkt = 0;
dm320_reqcomplete(privep, OK);
dm320_reqcomplete_nolock(privep, OK);
return OK;
}
}
@@ -1027,6 +1042,20 @@ static int dm320_wrrequest(struct dm320_ep_s *privep)
return OK; /* Won't get here */
}
static int dm320_wrrequest(struct dm320_ep_s *privep)
{
int ret;
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
ret = dm320_wrrequest_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return ret;
}
/****************************************************************************
* Name: dm320_rdrequest
*
@@ -1091,7 +1120,7 @@ static void dm320_cancelrequests(struct dm320_ep_s *privep)
{
usbtrace(TRACE_COMPLETE(privep->epphy),
(dm320_rqpeek(privep))->req.xfrd);
dm320_reqcomplete(privep, -ESHUTDOWN);
dm320_reqcomplete_nolock(privep, -ESHUTDOWN);
}
}
@@ -1998,11 +2027,13 @@ static int dm320_epdisable(struct usbdev_ep_s *ep)
/* Cancel any ongoing activity and reset the endpoint */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
dm320_cancelrequests(privep);
dm320_epreset(privep->epphy);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2141,7 +2172,8 @@ static int dm320_epsubmit(struct usbdev_ep_s *ep,
req->result = -EINPROGRESS;
req->xfrd = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* Check for NULL packet */
@@ -2179,7 +2211,7 @@ static int dm320_epsubmit(struct usbdev_ep_s *ep,
dm320_rqenqueue(privep, privreq);
usbtrace(TRACE_INREQQUEUED(privep->epphy), privreq->req.len);
ret = dm320_wrrequest(privep);
ret = dm320_wrrequest_nolock(privep);
}
/* Handle OUT (host-to-device) requests */
@@ -2201,7 +2233,8 @@ static int dm320_epsubmit(struct usbdev_ep_s *ep,
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -2231,9 +2264,11 @@ static int dm320_epcancel(struct usbdev_ep_s *ep,
usbtrace(TRACE_EPCANCEL, privep->epphy);
priv = privep->dev;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
dm320_cancelrequests(privep);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -2341,6 +2376,7 @@ static void dm320_freeep(struct usbdev_s *dev,
static int dm320_getframe(struct usbdev_s *dev)
{
struct dm320_usbdev_s *priv = (struct dm320_usbdev_s *)dev;
irqstate_t flags;
int ret;
@@ -2358,10 +2394,10 @@ static int dm320_getframe(struct usbdev_s *dev)
* because the operation is not atomic.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
ret = dm320_getreg8(DM320_USB_FRAME2) << 8;
ret |= dm320_getreg8(DM320_USB_FRAME1);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}
@@ -2375,12 +2411,13 @@ static int dm320_getframe(struct usbdev_s *dev)
static int dm320_wakeup(struct usbdev_s *dev)
{
struct dm320_usbdev_s *priv = (struct dm320_usbdev_s *)dev;
irqstate_t flags;
usbtrace(TRACE_DEVWAKEUP, 0);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
dm320_putreg8(USB_POWER_RESUME, DM320_USB_POWER);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
@@ -2421,11 +2458,12 @@ static int dm320_selfpowered(struct usbdev_s *dev, bool selfpowered)
#ifdef CONFIG_DM320_GIO_USBDPPULLUP
static int dm320_pullup(struct usbdev_s *dev, bool enable)
{
struct dm320_usbdev_s *priv = (struct dm320_usbdev_s *)dev;
irqstate_t flags;
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
if (enable)
{
GIO_SET_OUTPUT(CONFIG_DM320_GIO_USBDPPULLUP); /* Set D+ pullup */
@@ -2435,7 +2473,7 @@ static int dm320_pullup(struct usbdev_s *dev, bool enable)
GIO_CLEAR_OUTPUT(CONFIG_DM320_GIO_USBDPPULLUP); /* Clear D+ pullup */
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
#endif
@@ -2463,6 +2501,10 @@ void arm_usbinitialize(void)
usbtrace(TRACE_DEVINIT, 0);
/* Initialize dev lock */
spin_lock_init(&priv->lock);
/* Initialize the device state structure */
memset(priv, 0, sizeof(struct dm320_usbdev_s));
+72 -28
View File
@@ -35,6 +35,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -43,6 +44,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include "chip.h"
@@ -455,6 +457,10 @@ struct efm32_usbdev_s
struct efm32_ep_s epin[EFM32_NENDPOINTS];
struct efm32_ep_s epout[EFM32_NENDPOINTS];
/* Spinlock */
spinlock_t lock;
};
/****************************************************************************
@@ -4123,7 +4129,8 @@ static void efm32_epout_disable(struct efm32_ep_s *privep)
* Global OUT NAK mode in the core.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
efm32_enablegonak(privep);
/* Disable the required OUT endpoint by setting the EPDIS and SNAK bits
@@ -4170,7 +4177,8 @@ static void efm32_epout_disable(struct efm32_ep_s *privep)
efm32_req_cancel(privep, -ESHUTDOWN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
}
/****************************************************************************
@@ -4235,7 +4243,8 @@ static void efm32_epin_disable(struct efm32_ep_s *privep)
* the DIEPCTLx register.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
regaddr = EFM32_USB_DIEPCTL(privep->epphy);
regval = efm32_getreg(regaddr);
regval &= ~USB_DIEPCTL_USBACTEP;
@@ -4266,7 +4275,8 @@ static void efm32_epin_disable(struct efm32_ep_s *privep)
/* Cancel any queued write requests */
efm32_req_cancel(privep, -ESHUTDOWN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
}
/****************************************************************************
@@ -4457,7 +4467,8 @@ static int efm32_ep_submit(struct usbdev_ep_s *ep,
/* Disable Interrupts */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* If we are stalled, then drop all requests on the floor */
@@ -4502,7 +4513,8 @@ static int efm32_ep_submit(struct usbdev_ep_s *ep,
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -4530,7 +4542,8 @@ static int efm32_ep_cancel(struct usbdev_ep_s *ep,
usbtrace(TRACE_EPCANCEL, privep->epphy);
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
/* FIXME: if the request is the first, then we need to flush the EP
* otherwise just remove it from the list
@@ -4539,7 +4552,8 @@ static int efm32_ep_cancel(struct usbdev_ep_s *ep,
*/
efm32_req_cancel(privep, -ESHUTDOWN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -4749,7 +4763,8 @@ static int efm32_ep_stall(struct usbdev_ep_s *ep, bool resume)
/* Set or clear the stall condition as requested */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
if (resume)
{
ret = efm32_ep_clrstall(privep);
@@ -4759,7 +4774,8 @@ static int efm32_ep_stall(struct usbdev_ep_s *ep, bool resume)
ret = efm32_ep_setstall(privep);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return ret;
}
@@ -4819,7 +4835,8 @@ static struct usbdev_ep_s *efm32_ep_alloc(struct usbdev_s *dev,
/* Get the set of available endpoints depending on the direction */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
epavail = priv->epavail[in];
/* A physical address of 0 means that any endpoint will do */
@@ -4866,7 +4883,8 @@ static struct usbdev_ep_s *efm32_ep_alloc(struct usbdev_s *dev,
/* And return the pointer to the standard endpoint structure */
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return in ? &priv->epin[epno].ep : &priv->epout[epno].ep;
}
}
@@ -4875,7 +4893,8 @@ static struct usbdev_ep_s *efm32_ep_alloc(struct usbdev_s *dev,
}
usbtrace(TRACE_DEVERROR(EFM32_TRACEERR_NOEP), (uint16_t)eplog);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return NULL;
}
@@ -4900,9 +4919,9 @@ static void efm32_ep_free(struct usbdev_s *dev,
{
/* Mark the endpoint as available */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
priv->epavail[privep->isin] |= (1 << privep->epphy);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
}
@@ -4944,7 +4963,8 @@ static int efm32_wakeup(struct usbdev_s *dev)
/* Is wakeup enabled? */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
if (priv->wakeup)
{
/* Yes... is the core suspended? */
@@ -4970,7 +4990,8 @@ static int efm32_wakeup(struct usbdev_s *dev)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -5008,13 +5029,12 @@ static int efm32_selfpowered(struct usbdev_s *dev, bool selfpowered)
*
****************************************************************************/
static int efm32_pullup(struct usbdev_s *dev, bool enable)
static int efm32_pullup_nolock(struct usbdev_s *dev, bool enable)
{
uint32_t regval;
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
irqstate_t flags = enter_critical_section();
regval = efm32_getreg(EFM32_USB_DCTL);
if (enable)
{
@@ -5034,10 +5054,24 @@ static int efm32_pullup(struct usbdev_s *dev, bool enable)
}
efm32_putreg(regval, EFM32_USB_DCTL);
leave_critical_section(flags);
return OK;
}
static int efm32_pullup(struct usbdev_s *dev, bool enable)
{
uint32_t ret;
struct efm32_usbdev_s *priv = (struct efm32_usbdev_s *)dev;
irqstate_t flags = spin_lock_irqsave(&priv->lock);
sched_lock();
ret = efm32_pullup_nolock(dev, enable);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
/****************************************************************************
* Name: efm32_setaddress
*
@@ -5585,6 +5619,10 @@ void arm_usbinitialize(void)
* 10. Start initializing the USB core ...
*/
/* Initialize driver lock */
spin_lock_init(&priv->lock);
/* Uninitialize the hardware so that we know that we are starting from a
* known state.
*/
@@ -5657,8 +5695,9 @@ void arm_usbuninitialize(void)
/* Disconnect device */
flags = enter_critical_section();
efm32_pullup(&priv->usbdev, false);
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
efm32_pullup_nolock(&priv->usbdev, false);
priv->usbdev.speed = USB_SPEED_UNKNOWN;
/* Disable and detach IRQs */
@@ -5693,7 +5732,8 @@ void arm_usbuninitialize(void)
/* TODO: Turn off USB power and clocking */
priv->devstate = DEVSTATE_DEFAULT;
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
@@ -5804,9 +5844,11 @@ 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);
sched_lock();
efm32_usbreset(priv);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
/* Unbind the class driver */
@@ -5814,17 +5856,19 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
/* Disable USB controller interrupts */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
up_disable_irq(EFM32_IRQ_USB);
/* Disconnect device */
efm32_pullup(&priv->usbdev, false);
efm32_pullup_nolock(&priv->usbdev, false);
/* Unhook the driver */
priv->driver = NULL;
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
+51 -26
View File
@@ -34,6 +34,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -42,6 +43,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include "chip.h"
@@ -388,6 +390,10 @@ struct imxrt_usbdev_s
/* The endpoint list */
struct imxrt_ep_s eplist[IMXRT_NPHYSENDPOINTS];
/* Spinlock */
spinlock_t lock;
};
#define EP0STATE_IDLE 0 /* Idle State, leave on receiving a setup packet or epsubmit */
@@ -2238,7 +2244,8 @@ static int imxrt_epdisable(struct usbdev_ep_s *ep)
usbtrace(TRACE_EPDISABLE, privep->epphy);
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
/* Disable Endpoint */
@@ -2259,7 +2266,8 @@ static int imxrt_epdisable(struct usbdev_ep_s *ep)
imxrt_cancelrequests(privep, -ESHUTDOWN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2416,7 +2424,8 @@ static int imxrt_epsubmit(struct usbdev_ep_s *ep,
/* Disable Interrupts */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* If we are stalled, then drop all requests on the floor */
@@ -2443,7 +2452,8 @@ static int imxrt_epsubmit(struct usbdev_ep_s *ep,
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -2471,7 +2481,8 @@ static int imxrt_epcancel(struct usbdev_ep_s *ep,
usbtrace(TRACE_EPCANCEL, privep->epphy);
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
/* FIXME: if the request is the first, then we need to flush the EP
* otherwise just remove it from the list
@@ -2480,7 +2491,8 @@ static int imxrt_epcancel(struct usbdev_ep_s *ep,
*/
imxrt_cancelrequests(privep, -ESHUTDOWN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2499,7 +2511,8 @@ static int imxrt_epstall(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, privep->epphy);
uint32_t addr = IMXRT_USBDEV_ENDPTCTRL(privep->epphy >> 1);
@@ -2523,7 +2536,8 @@ static int imxrt_epstall(struct usbdev_ep_s *ep, bool resume)
imxrt_setbits(ctrl_xs, addr);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2627,7 +2641,7 @@ static struct usbdev_ep_s *imxrt_allocep(struct usbdev_s *dev,
{
/* Yes.. now see if any of the request endpoints are available */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
@@ -2643,7 +2657,7 @@ static struct usbdev_ep_s *imxrt_allocep(struct usbdev_s *dev,
/* Mark endpoint no longer available */
priv->epavail &= ~bit;
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
/* And return the pointer to the standard endpoint
* structure
@@ -2656,7 +2670,7 @@ static struct usbdev_ep_s *imxrt_allocep(struct usbdev_s *dev,
/* Shouldn't get here */
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
usbtrace(TRACE_DEVERROR(IMXRT_TRACEERR_NOEP), (uint16_t)eplog);
@@ -2684,9 +2698,9 @@ static void imxrt_freeep(struct usbdev_s *dev,
{
/* Mark the endpoint as available */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= (1 << privep->epphy);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
}
@@ -2730,13 +2744,14 @@ static int imxrt_getframe(struct usbdev_s *dev)
static int imxrt_wakeup(struct usbdev_s *dev)
{
struct imxrt_usbdev_s *priv = (struct imxrt_usbdev_s *)dev;
irqstate_t flags;
usbtrace(TRACE_DEVWAKEUP, 0);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
imxrt_setbits(USBDEV_PRTSC1_FPR, IMXRT_USBDEV_PORTSC1);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
@@ -2774,11 +2789,10 @@ static int imxrt_selfpowered(struct usbdev_s *dev, bool selfpowered)
*
****************************************************************************/
static int imxrt_pullup(struct usbdev_s *dev, bool enable)
static int imxrt_pullup_nolock(struct usbdev_s *dev, bool enable)
{
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
irqstate_t flags = enter_critical_section();
if (enable)
{
imxrt_setbits(USBDEV_USBCMD_RS, IMXRT_USBDEV_USBCMD);
@@ -2795,10 +2809,23 @@ static int imxrt_pullup(struct usbdev_s *dev, bool enable)
imxrt_clrbits(USBDEV_USBCMD_RS, IMXRT_USBDEV_USBCMD);
}
leave_critical_section(flags);
return OK;
}
static int imxrt_pullup(struct usbdev_s *dev, bool enable)
{
struct imxrt_usbdev_s *priv = (struct imxrt_usbdev_s *)dev;
int ret;
irqstate_t flags = spin_lock_irqsave(&priv->lock);
sched_lock();
ret = imxrt_pullup_nolock(dev, enable);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -2821,9 +2848,6 @@ void arm_usbinitialize(void)
{
struct imxrt_usbdev_s *priv = &g_usbdev;
int i;
irqstate_t flags;
flags = enter_critical_section();
/* Initialize the device state structure */
@@ -2831,6 +2855,7 @@ void arm_usbinitialize(void)
priv->usbdev.ops = &g_devops;
priv->usbdev.ep0 = &priv->eplist[IMXRT_EP0_IN].ep;
priv->epavail = IMXRT_EPALLSET & ~IMXRT_EPCTRLSET;
spin_lock_init(&priv->lock);
/* Initialize the endpoint list */
@@ -2948,8 +2973,6 @@ void arm_usbinitialize(void)
irq_attach(IMXRT_IRQ_USBOTG1, imxrt_usbinterrupt, NULL);
up_enable_irq(IMXRT_IRQ_USBOTG1);
leave_critical_section(flags);
/* Reset/Re-initialize the USB hardware */
imxrt_usbreset(priv);
@@ -2972,11 +2995,12 @@ void arm_usbuninitialize(void)
usbdev_unregister(priv->driver);
}
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* Disconnect device */
imxrt_pullup(&priv->usbdev, false);
imxrt_pullup_nolock(&priv->usbdev, false);
priv->usbdev.speed = USB_SPEED_UNKNOWN;
/* Disable and detach IRQs */
@@ -3003,7 +3027,8 @@ void arm_usbuninitialize(void)
imxrt_clockoff_usboh3();
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
+44 -20
View File
@@ -48,6 +48,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
@@ -57,6 +58,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include "arm_internal.h"
#include "kinetis.h"
@@ -502,6 +504,10 @@ struct khci_usbdev_s
/* The endpoint list */
struct khci_ep_s eplist[KHCI_NENDPOINTS];
/* Spinlock */
spinlock_t lock;
};
/****************************************************************************
@@ -892,9 +898,9 @@ static void khci_reqcomplete(struct khci_ep_s *privep, int16_t result)
* request list.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
privreq = khci_remfirst(&privep->active);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
if (privreq)
{
@@ -3202,7 +3208,8 @@ static void khci_resume(struct khci_usbdev_s *priv)
irqstate_t flags;
uint32_t regval;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* This function is called when the USB resume interrupt occurs.
* If using clock switching, this is the place to call out to
@@ -3243,7 +3250,8 @@ static void khci_resume(struct khci_usbdev_s *priv)
CLASS_RESUME(priv->driver, &priv->usbdev);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
@@ -3261,7 +3269,7 @@ khci_epreserve(struct khci_usbdev_s *priv, uint8_t epset)
irqstate_t flags;
int epndx = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
@@ -3286,7 +3294,7 @@ khci_epreserve(struct khci_usbdev_s *priv, uint8_t epset)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return privep;
}
@@ -3297,9 +3305,9 @@ khci_epreserve(struct khci_usbdev_s *priv, uint8_t epset)
static inline void
khci_epunreserve(struct khci_usbdev_s *priv, struct khci_ep_s *privep)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= KHCI_ENDP_BIT(USB_EPNO(privep->ep.eplog));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************
@@ -3528,7 +3536,8 @@ static int khci_epdisable(struct usbdev_ep_s *ep)
/* Cancel any ongoing activity */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
khci_cancelrequests(privep, -ESHUTDOWN);
/* Disable the endpoint */
@@ -3545,7 +3554,8 @@ static int khci_epdisable(struct usbdev_ep_s *ep)
*ptr++ = 0;
}
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -3644,7 +3654,8 @@ static int khci_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
#ifndef CONFIG_USBDEV_NOWRITEAHEAD
privreq->inflight[1] = 0;
#endif
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* Add the new request to the request queue for the OUT endpoint */
@@ -3688,7 +3699,8 @@ static int khci_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -3711,9 +3723,11 @@ static int khci_epcancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog));
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
khci_cancelrequests(privep, -EAGAIN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -3920,7 +3934,8 @@ static int khci_epstall(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();
/* Special case EP0. When we stall EP0 we have to stall both the IN and
* OUT BDTs.
@@ -3949,7 +3964,8 @@ static int khci_epstall(struct usbdev_ep_s *ep, bool resume)
ret = khci_epbdtstall(ep, resume, USB_ISEPIN(ep->eplog));
}
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return ret;
}
@@ -4516,6 +4532,10 @@ void arm_usbinitialize(void)
usbtrace(TRACE_DEVINIT, 0);
/* Initialize driver lock */
spin_lock_init(&priv->lock);
/* Initialize the driver state structure */
khci_swinitialize(priv);
@@ -4594,7 +4614,8 @@ void arm_usbuninitialize(void)
/* Disconnect the device */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
khci_swreset(priv);
@@ -4618,7 +4639,8 @@ void arm_usbuninitialize(void)
regval &= ~SIM_SCGC4_USBOTG;
putreg32(regval, KINETIS_SIM_SCGC4);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
@@ -4719,7 +4741,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
* the hardware back into its initial, unconnected state.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
khci_swreset(priv);
kinetis_usbpullup(&priv->usbdev, false);
khci_hwreset(priv);
@@ -4740,7 +4763,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
khci_hwshutdown(priv);
khci_swinitialize(priv);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
#endif /* CONFIG_USBDEV */
+111 -43
View File
@@ -34,6 +34,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -42,6 +43,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include "arm_internal.h"
@@ -353,6 +355,10 @@ struct lpc17_40_usbdev_s
/* The endpoint list */
struct lpc17_40_ep_s eplist[LPC17_40_NPHYSENDPOINTS];
/* Spinlock */
spinlock_t lock;
};
/****************************************************************************
@@ -651,16 +657,12 @@ static void lpc17_40_putreg(uint32_t val, uint32_t addr)
*
****************************************************************************/
static uint32_t lpc17_40_usbcmd(uint16_t cmd, uint8_t data)
static uint32_t lpc17_40_usbcmd_nolock(uint16_t cmd, uint8_t data)
{
irqstate_t flags;
uint32_t cmd32;
uint32_t data32;
uint32_t tmp = 0;
/* Disable interrupt and clear CDFULL and CCEMPTY interrupt status */
flags = enter_critical_section();
lpc17_40_putreg(USBDEV_INT_CDFULL | USBDEV_INT_CCEMPTY,
LPC17_40_USBDEV_INTCLR);
@@ -797,9 +799,22 @@ static uint32_t lpc17_40_usbcmd(uint16_t cmd, uint8_t data)
break;
}
/* Restore the interrupt flags */
return tmp;
}
static uint32_t lpc17_40_usbcmd(uint16_t cmd, uint8_t data)
{
irqstate_t flags;
uint32_t tmp;
/* Disable interrupt and clear CDFULL and CCEMPTY interrupt status */
flags = spin_lock_irqsave(&g_usbdev.lock);
sched_lock();
tmp = lpc17_40_usbcmd_nolock(cmd, data);
spin_unlock_irqrestore(&g_usbdev.lock, flags);
sched_unlock();
leave_critical_section(flags);
return tmp;
}
@@ -1037,18 +1052,15 @@ static inline void lpc17_40_abortrequest(struct lpc17_40_ep_s *privep,
*
****************************************************************************/
static void lpc17_40_reqcomplete(struct lpc17_40_ep_s *privep,
int16_t result)
static void lpc17_40_reqcomplete_nolock(struct lpc17_40_ep_s *privep,
int16_t result)
{
struct lpc17_40_req_s *privreq;
int stalled = privep->stalled;
irqstate_t flags;
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
privreq = lpc17_40_rqdequeue(privep);
leave_critical_section(flags);
if (privreq)
{
@@ -1076,6 +1088,16 @@ static void lpc17_40_reqcomplete(struct lpc17_40_ep_s *privep,
}
}
static void lpc17_40_reqcomplete(struct lpc17_40_ep_s *privep,
int16_t result)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
lpc17_40_reqcomplete_nolock(privep, result);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
* Name: lpc17_40_wrrequest
*
@@ -1084,7 +1106,7 @@ static void lpc17_40_reqcomplete(struct lpc17_40_ep_s *privep,
*
****************************************************************************/
static int lpc17_40_wrrequest(struct lpc17_40_ep_s *privep)
static int lpc17_40_wrrequest_nolock(struct lpc17_40_ep_s *privep)
{
struct lpc17_40_req_s *privreq;
uint8_t *buf;
@@ -1119,7 +1141,7 @@ static int lpc17_40_wrrequest(struct lpc17_40_ep_s *privep)
/* In any event, the request is complete */
lpc17_40_reqcomplete(privep, OK);
lpc17_40_reqcomplete_nolock(privep, OK);
return OK;
}
@@ -1181,12 +1203,25 @@ static int lpc17_40_wrrequest(struct lpc17_40_ep_s *privep)
{
usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
privep->txnullpkt = 0;
lpc17_40_reqcomplete(privep, OK);
lpc17_40_reqcomplete_nolock(privep, OK);
}
return OK;
}
static int lpc17_40_wrrequest(struct lpc17_40_ep_s *privep)
{
int ret;
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
ret = lpc17_40_wrrequest_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return ret;
}
/****************************************************************************
* Name: lpc17_40_rdrequest
*
@@ -1263,7 +1298,7 @@ static void lpc17_40_cancelrequests(struct lpc17_40_ep_s *privep)
{
usbtrace(TRACE_COMPLETE(privep->epphy),
(lpc17_40_rqpeek(privep))->req.xfrd);
lpc17_40_reqcomplete(privep, -ESHUTDOWN);
lpc17_40_reqcomplete_nolock(privep, -ESHUTDOWN);
}
}
@@ -2727,7 +2762,8 @@ static int lpc17_40_epdisable(struct usbdev_ep_s *ep)
/* Cancel any ongoing activity */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
lpc17_40_cancelrequests(privep);
/* Disable endpoint and interrupt */
@@ -2742,7 +2778,8 @@ static int lpc17_40_epdisable(struct usbdev_ep_s *ep)
regval &= ~mask;
lpc17_40_putreg(regval, LPC17_40_USBDEV_EPINTEN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2931,7 +2968,8 @@ static int lpc17_40_epsubmit(struct usbdev_ep_s *ep,
req->result = -EINPROGRESS;
req->xfrd = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* If we are stalled, then drop all requests on the floor */
@@ -2977,7 +3015,8 @@ static int lpc17_40_epsubmit(struct usbdev_ep_s *ep,
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -3005,9 +3044,11 @@ static int lpc17_40_epcancel(struct usbdev_ep_s *ep,
usbtrace(TRACE_EPCANCEL, privep->epphy);
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
lpc17_40_cancelrequests(privep);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -3026,19 +3067,21 @@ static int lpc17_40_epstall(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, privep->epphy);
lpc17_40_usbcmd(CMD_USBDEV_EPSETSTATUS | privep->epphy,
(resume ? 0 : CMD_SETSTAUS_ST));
lpc17_40_usbcmd_nolock(CMD_USBDEV_EPSETSTATUS | privep->epphy,
(resume ? 0 : CMD_SETSTAUS_ST));
/* If the endpoint of was resumed, then restart any queue write requests */
if (resume)
{
lpc17_40_wrrequest(privep);
lpc17_40_wrrequest_nolock(privep);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -3145,7 +3188,7 @@ static struct usbdev_ep_s *lpc17_40_allocep(struct usbdev_s *dev,
{
/* Yes.. now see if any of the request endpoints are available */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
@@ -3161,7 +3204,7 @@ static struct usbdev_ep_s *lpc17_40_allocep(struct usbdev_s *dev,
/* Mark the IN/OUT endpoint no longer available */
priv->epavail &= ~(3 << (epndx & ~1));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
/* And return the pointer to the standard endpoint
* structure
@@ -3174,7 +3217,7 @@ static struct usbdev_ep_s *lpc17_40_allocep(struct usbdev_s *dev,
/* Shouldn't get here */
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
usbtrace(TRACE_DEVERROR(LPC17_40_TRACEERR_NOEP), (uint16_t)eplog);
@@ -3202,9 +3245,9 @@ static void lpc17_40_freeep(struct usbdev_s *dev,
{
/* Mark the IN/OUT endpoint as available */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= (3 << (privep->epphy & ~1));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
}
@@ -3243,19 +3286,22 @@ static int lpc17_40_getframe(struct usbdev_s *dev)
static int lpc17_40_wakeup(struct usbdev_s *dev)
{
struct lpc17_40_usbdev_s *priv = (struct lpc17_40_usbdev_s *)dev;
uint8_t arg = CMD_STATUS_SUSPEND;
irqstate_t flags;
usbtrace(TRACE_DEVWAKEUP, (uint16_t)g_usbdev.devstatus);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
if (DEVSTATUS_CONNECT(g_usbdev.devstatus))
{
arg |= CMD_STATUS_CONNECT;
}
lpc17_40_usbcmd(CMD_USBDEV_SETSTATUS, arg);
leave_critical_section(flags);
lpc17_40_usbcmd_nolock(CMD_USBDEV_SETSTATUS, arg);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -3293,6 +3339,20 @@ static int lpc17_40_selfpowered(struct usbdev_s *dev, bool selfpowered)
*
****************************************************************************/
static int lpc17_40_pullup_nolock(struct usbdev_s *dev, bool enable)
{
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
/* The CMD_STATUS_CONNECT bit in the CMD_USBDEV_SETSTATUS command
* controls the LPC17xx/LPC40xx SoftConnect_N output pin that is used for
* SoftConnect.
*/
lpc17_40_usbcmd_nolock(CMD_USBDEV_SETSTATUS,
(enable ? CMD_STATUS_CONNECT : 0));
return OK;
}
static int lpc17_40_pullup(struct usbdev_s *dev, bool enable)
{
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
@@ -3331,9 +3391,14 @@ void arm_usbinitialize(void)
usbtrace(TRACE_DEVINIT, 0);
/* Initialize driver lock */
spin_lock_init(&priv->lock);
/* Step 1: Enable power by setting PCUSB in the PCONP register */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
regval = lpc17_40_getreg(LPC17_40_SYSCON_PCONP);
regval |= SYSCON_PCONP_PCUSB;
lpc17_40_putreg(regval, LPC17_40_SYSCON_PCONP);
@@ -3374,7 +3439,8 @@ void arm_usbinitialize(void)
regval = lpc17_40_getreg(LPC17_40_SYSCON_USBINTST);
regval &= ~SYSCON_USBINTST_ENINTS;
lpc17_40_putreg(regval, LPC17_40_SYSCON_USBINTST);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
/* Initialize the device state structure */
@@ -3460,11 +3526,11 @@ void arm_usbinitialize(void)
* driver
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
regval = lpc17_40_getreg(LPC17_40_SYSCON_USBINTST);
regval |= SYSCON_USBINTST_ENINTS;
lpc17_40_putreg(regval, LPC17_40_SYSCON_USBINTST);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
/* Disconnect device */
@@ -3508,10 +3574,11 @@ void arm_usbuninitialize(void)
/* Disconnect device */
flags = enter_critical_section();
lpc17_40_pullup(&priv->usbdev, false);
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
lpc17_40_pullup_nolock(&priv->usbdev, false);
priv->usbdev.speed = USB_SPEED_UNKNOWN;
lpc17_40_usbcmd(CMD_USBDEV_CONFIG, 0);
lpc17_40_usbcmd_nolock(CMD_USBDEV_CONFIG, 0);
/* Disable and detach IRQs */
@@ -3523,7 +3590,8 @@ void arm_usbuninitialize(void)
regval = lpc17_40_getreg(LPC17_40_SYSCON_PCONP);
regval &= ~SYSCON_PCONP_PCUSB;
lpc17_40_putreg(regval, LPC17_40_SYSCON_PCONP);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
+119 -40
View File
@@ -34,6 +34,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -42,6 +43,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include "chip.h"
@@ -361,6 +363,10 @@ struct lpc214x_usbdev_s
/* The endpoint list */
struct lpc214x_ep_s eplist[LPC214X_NPHYSENDPOINTS];
/* Spinlock */
spinlock_t lock;
};
/****************************************************************************
@@ -595,14 +601,10 @@ static void lpc214x_putreg(uint32_t val, uint32_t addr)
*
****************************************************************************/
static uint32_t lpc214x_usbcmd(uint16_t cmd, uint8_t data)
static uint32_t lpc214x_usbcmd_nolock(uint16_t cmd, uint8_t data)
{
irqstate_t flags;
uint32_t tmp = 0;
/* Disable interrupt and clear CDFULL and CCEMPTY interrupt status */
flags = enter_critical_section();
lpc214x_putreg(USBDEV_DEVINT_CDFULL | USBDEV_DEVINT_CCEMTY,
LPC214X_USBDEV_DEVINTCLR);
@@ -734,9 +736,26 @@ static uint32_t lpc214x_usbcmd(uint16_t cmd, uint8_t data)
break;
}
return tmp;
}
static uint32_t lpc214x_usbcmd(uint16_t cmd, uint8_t data)
{
irqstate_t flags;
uint32_t tmp = 0;
/* Disable interrupt and clear CDFULL and CCEMPTY interrupt status */
flags = spin_lock_irqsave(&g_usbdev.lock);
sched_lock();
tmp = lpc214x_usbcmd_nolock(cmd, data);
/* Restore the interrupt flags */
leave_critical_section(flags);
spin_unlock_irqrestore(&g_usbdev.lock, flags);
sched_unlock();
return tmp;
}
@@ -975,17 +994,15 @@ static inline void lpc214x_abortrequest(struct lpc214x_ep_s *privep,
*
****************************************************************************/
static void lpc214x_reqcomplete(struct lpc214x_ep_s *privep, int16_t result)
static void lpc214x_reqcomplete_nolock(struct lpc214x_ep_s *privep,
int16_t result)
{
struct lpc214x_req_s *privreq;
int stalled = privep->stalled;
irqstate_t flags;
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
privreq = lpc214x_rqdequeue(privep);
leave_critical_section(flags);
if (privreq)
{
@@ -1013,6 +1030,15 @@ static void lpc214x_reqcomplete(struct lpc214x_ep_s *privep, int16_t result)
}
}
static void lpc214x_reqcomplete(struct lpc214x_ep_s *privep, int16_t result)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
lpc214x_reqcomplete_nolock(privep, result);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
* Name: lpc214x_wrrequest
*
@@ -1021,7 +1047,7 @@ static void lpc214x_reqcomplete(struct lpc214x_ep_s *privep, int16_t result)
*
****************************************************************************/
static int lpc214x_wrrequest(struct lpc214x_ep_s *privep)
static int lpc214x_wrrequest_nolock(struct lpc214x_ep_s *privep)
{
struct lpc214x_req_s *privreq;
uint8_t *buf;
@@ -1056,7 +1082,7 @@ static int lpc214x_wrrequest(struct lpc214x_ep_s *privep)
/* In any event, the request is complete */
lpc214x_reqcomplete(privep, OK);
lpc214x_reqcomplete_nolock(privep, OK);
return OK;
}
@@ -1118,12 +1144,25 @@ static int lpc214x_wrrequest(struct lpc214x_ep_s *privep)
{
usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
privep->txnullpkt = 0;
lpc214x_reqcomplete(privep, OK);
lpc214x_reqcomplete_nolock(privep, OK);
}
return OK;
}
static int lpc214x_wrrequest(struct lpc214x_ep_s *privep)
{
int ret;
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
ret = lpc214x_wrrequest_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return ret;
}
/****************************************************************************
* Name: lpc214x_rdrequest
*
@@ -1194,16 +1233,25 @@ static int lpc214x_rdrequest(struct lpc214x_ep_s *privep)
*
****************************************************************************/
static void lpc214x_cancelrequests(struct lpc214x_ep_s *privep)
static void lpc214x_cancelrequests_nolock(struct lpc214x_ep_s *privep)
{
while (!lpc214x_rqempty(privep))
{
usbtrace(TRACE_COMPLETE(privep->epphy),
(lpc214x_rqpeek(privep))->req.xfrd);
lpc214x_reqcomplete(privep, -ESHUTDOWN);
lpc214x_reqcomplete_nolock(privep, -ESHUTDOWN);
}
}
static void lpc214x_cancelrequests(struct lpc214x_ep_s *privep)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
lpc214x_cancelrequests_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
}
/****************************************************************************
* Name: lpc214x_epfindbyaddr
*
@@ -2687,8 +2735,9 @@ static int lpc214x_epdisable(struct usbdev_ep_s *ep)
/* Cancel any ongoing activity */
flags = enter_critical_section();
lpc214x_cancelrequests(privep);
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
lpc214x_cancelrequests_nolock(privep);
/* Disable endpoint and interrupt */
@@ -2702,7 +2751,8 @@ static int lpc214x_epdisable(struct usbdev_ep_s *ep)
reg &= ~mask;
lpc214x_putreg(reg, LPC214X_USBDEV_EPINTEN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2890,7 +2940,8 @@ static int lpc214x_epsubmit(struct usbdev_ep_s *ep,
req->result = -EINPROGRESS;
req->xfrd = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* If we are stalled, then drop all requests on the floor */
@@ -2913,7 +2964,7 @@ static int lpc214x_epsubmit(struct usbdev_ep_s *ep,
if (privep->txbusy == 0)
{
ret = lpc214x_wrrequest(privep);
ret = lpc214x_wrrequest_nolock(privep);
}
}
@@ -2936,7 +2987,8 @@ static int lpc214x_epsubmit(struct usbdev_ep_s *ep,
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -2964,9 +3016,11 @@ static int lpc214x_epcancel(struct usbdev_ep_s *ep,
usbtrace(TRACE_EPCANCEL, privep->epphy);
flags = enter_critical_section();
lpc214x_cancelrequests(privep);
leave_critical_section(flags);
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
lpc214x_cancelrequests_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2985,19 +3039,21 @@ static int lpc214x_epstall(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, privep->epphy);
lpc214x_usbcmd(CMD_USB_EP_SETSTATUS | privep->epphy,
lpc214x_usbcmd_nolock(CMD_USB_EP_SETSTATUS | privep->epphy,
(resume ? 0 : USBDEV_EPSTALL));
/* If the endpoint of was resumed, then restart any queue write requests */
if (resume)
{
lpc214x_wrrequest(privep);
lpc214x_wrrequest_nolock(privep);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -3103,7 +3159,7 @@ static struct usbdev_ep_s *lcp214x_allocep(struct usbdev_s *dev,
{
/* Yes.. now see if any of the request endpoints are available */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
@@ -3119,7 +3175,7 @@ static struct usbdev_ep_s *lcp214x_allocep(struct usbdev_s *dev,
/* Mark the IN/OUT endpoint no longer available */
priv->epavail &= ~(3 << (bit & ~1));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
/* And return the pointer to the standard endpoint
* structure
@@ -3132,7 +3188,7 @@ static struct usbdev_ep_s *lcp214x_allocep(struct usbdev_s *dev,
/* Shouldn't get here */
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_NOEP), (uint16_t)eplog);
@@ -3160,9 +3216,9 @@ static void lpc214x_freeep(struct usbdev_s *dev,
{
/* Mark the endpoint as available */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= (1 << privep->epphy);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
}
@@ -3201,19 +3257,22 @@ static int lpc214x_getframe(struct usbdev_s *dev)
static int lpc214x_wakeup(struct usbdev_s *dev)
{
struct lpc214x_usbdev_s *priv = (struct lpc214x_usbdev_s *)dev;
uint8_t arg = USBDEV_DEVSTATUS_SUSPEND;
irqstate_t flags;
usbtrace(TRACE_DEVWAKEUP, (uint16_t)g_usbdev.devstatus);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
if (DEVSTATUS_CONNECT(g_usbdev.devstatus))
{
arg |= USBDEV_DEVSTATUS_CONNECT;
}
lpc214x_usbcmd(CMD_USB_DEV_SETSTATUS, arg);
leave_critical_section(flags);
lpc214x_usbcmd_nolock(CMD_USB_DEV_SETSTATUS, arg);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -3251,6 +3310,20 @@ static int lpc214x_selfpowered(struct usbdev_s *dev, bool selfpowered)
*
****************************************************************************/
static int lpc214x_pullup_nolock(struct usbdev_s *dev, bool enable)
{
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
/* The USBDEV_DEVSTATUS_CONNECT bit in the CMD_USB_DEV_SETSTATUS command
* controls the LPC214x SoftConnect_N output pin that is used for
* SoftConnect.
*/
lpc214x_usbcmd_nolock(CMD_USB_DEV_SETSTATUS,
(enable ? USBDEV_DEVSTATUS_CONNECT : 0));
return OK;
}
static int lpc214x_pullup(struct usbdev_s *dev, bool enable)
{
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
@@ -3292,6 +3365,10 @@ void arm_usbinitialize(void)
usbtrace(TRACE_DEVINIT, 0);
/* Initialize driver lock */
spin_lock_init(&priv->lock);
/* Disable USB interrupts */
lpc214x_putreg(0, LPC214X_USBDEV_INTST);
@@ -3416,10 +3493,11 @@ void arm_usbuninitialize(void)
/* Disconnect device */
flags = enter_critical_section();
lpc214x_pullup(&priv->usbdev, false);
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
lpc214x_pullup_nolock(&priv->usbdev, false);
priv->usbdev.speed = USB_SPEED_UNKNOWN;
lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 0);
lpc214x_usbcmd_nolock(CMD_USB_DEV_CONFIG, 0);
/* Disable and detach IRQs */
@@ -3431,7 +3509,8 @@ void arm_usbuninitialize(void)
reg = lpc214x_getreg(LPC214X_PCON_PCONP);
reg &= ~LPC214X_PCONP_PCUSB;
lpc214x_putreg(reg, LPC214X_PCON_PCONP);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
+55 -22
View File
@@ -34,6 +34,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -42,6 +43,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include "chip.h"
@@ -319,7 +321,11 @@ struct lpc31_usbdev_s
/* The endpoint list */
struct lpc31_ep_s eplist[LPC31_NPHYSENDPOINTS];
struct lpc31_ep_s eplist[LPC31_NPHYSENDPOINTS];
/* Spinlock */
spinlock_t lock;
};
#define EP0STATE_IDLE 0 /* Idle State, leave on receiving a setup packet or epsubmit */
@@ -2096,7 +2102,8 @@ static int lpc31_epdisable(struct usbdev_ep_s *ep)
usbtrace(TRACE_EPDISABLE, privep->epphy);
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
/* Disable Endpoint */
@@ -2113,7 +2120,8 @@ static int lpc31_epdisable(struct usbdev_ep_s *ep)
lpc31_cancelrequests(privep, -ESHUTDOWN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2262,7 +2270,8 @@ static int lpc31_epsubmit(struct usbdev_ep_s *ep,
/* Disable Interrupts */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
/* If we are stalled, then drop all requests on the floor */
@@ -2285,7 +2294,8 @@ static int lpc31_epsubmit(struct usbdev_ep_s *ep,
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return ret;
}
@@ -2313,7 +2323,8 @@ static int lpc31_epcancel(struct usbdev_ep_s *ep,
usbtrace(TRACE_EPCANCEL, privep->epphy);
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
/* FIXME: if the request is the first, then we need to flush the EP
* otherwise just remove it from the list
@@ -2322,7 +2333,8 @@ static int lpc31_epcancel(struct usbdev_ep_s *ep,
*/
lpc31_cancelrequests(privep, -ESHUTDOWN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2341,7 +2353,8 @@ static int lpc31_epstall(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, privep->epphy);
uint32_t addr = LPC31_USBDEV_ENDPTCTRL(privep->epphy);
@@ -2365,7 +2378,8 @@ static int lpc31_epstall(struct usbdev_ep_s *ep, bool resume)
lpc31_setbits (ctrl_xs, addr);
}
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2472,7 +2486,7 @@ static struct usbdev_ep_s *lpc31_allocep(struct usbdev_s *dev,
* now see if any of the request endpoints are available
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
@@ -2488,7 +2502,7 @@ static struct usbdev_ep_s *lpc31_allocep(struct usbdev_s *dev,
/* Mark the IN/OUT endpoint no longer available */
priv->epavail &= ~(3 << (bit & ~1));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
/* And return the pointer to the standard endpoint
* structure
@@ -2501,7 +2515,7 @@ static struct usbdev_ep_s *lpc31_allocep(struct usbdev_s *dev,
/* Shouldn't get here */
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
usbtrace(TRACE_DEVERROR(LPC31_TRACEERR_NOEP), (uint16_t)eplog);
@@ -2529,9 +2543,9 @@ static void lpc31_freeep(struct usbdev_s *dev,
{
/* Mark the endpoint as available */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= (1 << privep->epphy);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
}
@@ -2573,13 +2587,14 @@ static int lpc31_getframe(struct usbdev_s *dev)
static int lpc31_wakeup(struct usbdev_s *dev)
{
struct lpc31_usbdev_s *priv = (struct lpc31_usbdev_s *)dev;
irqstate_t flags;
usbtrace(TRACE_DEVWAKEUP, 0);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
lpc31_setbits(USBDEV_PRTSC1_FPR, LPC31_USBDEV_PORTSC1);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
@@ -2617,19 +2632,31 @@ static int lpc31_selfpowered(struct usbdev_s *dev, bool selfpowered)
*
****************************************************************************/
static int lpc31_pullup(struct usbdev_s *dev, bool enable)
static int lpc31_pullup_nolock(struct usbdev_s *dev, bool enable)
{
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
irqstate_t flags = enter_critical_section();
if (enable)
lpc31_setbits (USBDEV_USBCMD_RS, LPC31_USBDEV_USBCMD);
else
lpc31_clrbits (USBDEV_USBCMD_RS, LPC31_USBDEV_USBCMD);
leave_critical_section(flags);
return OK;
}
static int lpc31_pullup(struct usbdev_s *dev, bool enable)
{
struct lpc31_usbdev_s *priv = (struct lpc31_usbdev_s *)dev;
int ret;
irqstate_t flags = spin_lock_irqsave(&priv->lock);
sched_lock();
ret = lpc31_pullup_nolock(dev, enable);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -2656,6 +2683,10 @@ void arm_usbinitialize(void)
usbtrace(TRACE_DEVINIT, 0);
/* Initialize driver lock */
spin_lock_init(&priv->lock);
/* Disable USB interrupts */
lpc31_putreg(0, LPC31_USBDEV_USBINTR);
@@ -2793,8 +2824,9 @@ void arm_usbuninitialize(void)
/* Disconnect device */
flags = enter_critical_section();
lpc31_pullup(&priv->usbdev, false);
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
lpc31_pullup_nolock(&priv->usbdev, false);
priv->usbdev.speed = USB_SPEED_UNKNOWN;
/* Disable and detach IRQs */
@@ -2813,7 +2845,8 @@ void arm_usbuninitialize(void)
lpc31_disableclock (CLKID_USBOTGAHBCLK);
lpc31_disableclock (CLKID_EVENTROUTERPCLK);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
+43 -14
View File
@@ -34,6 +34,7 @@
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/spinlock.h>
@@ -584,17 +585,15 @@ static void rp2040_abortrequest(struct rp2040_ep_s *privep,
*
****************************************************************************/
static void rp2040_reqcomplete(struct rp2040_ep_s *privep, int16_t result)
static void rp2040_reqcomplete_nolock(struct rp2040_ep_s *privep,
int16_t result)
{
struct rp2040_req_s *privreq;
int stalled = privep->stalled;
irqstate_t flags;
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
privreq = rp2040_rqdequeue(privep);
leave_critical_section(flags);
if (privreq)
{
@@ -622,6 +621,15 @@ static void rp2040_reqcomplete(struct rp2040_ep_s *privep, int16_t result)
}
}
static void rp2040_reqcomplete(struct rp2040_ep_s *privep, int16_t result)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
rp2040_reqcomplete_nolock(privep, result);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
* Name: rp2040_txcomplete
*
@@ -856,16 +864,25 @@ static void rp2040_handle_zlp(struct rp2040_usbdev_s *priv)
*
****************************************************************************/
static void rp2040_cancelrequests(struct rp2040_ep_s *privep)
static void rp2040_cancelrequests_nolock(struct rp2040_ep_s *privep)
{
while (!rp2040_rqempty(privep))
{
usbtrace(TRACE_COMPLETE(privep->epphy),
(rp2040_rqpeek(privep))->req.xfrd);
rp2040_reqcomplete(privep, -ESHUTDOWN);
rp2040_reqcomplete_nolock(privep, -ESHUTDOWN);
}
}
static void rp2040_cancelrequests(struct rp2040_ep_s *privep)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
rp2040_cancelrequests_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
}
/****************************************************************************
* Name: rp2040_epfindbyaddr
*
@@ -1518,7 +1535,8 @@ static int rp2040_epdisable(struct usbdev_ep_s *ep)
usbtrace(TRACE_EPDISABLE, privep->epphy);
uinfo("EP%d\n", privep->epphy);
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
privep->ep.maxpacket = 64;
privep->stalled = false;
@@ -1527,9 +1545,10 @@ static int rp2040_epdisable(struct usbdev_ep_s *ep)
/* Cancel all queued requests */
rp2040_cancelrequests(privep);
rp2040_cancelrequests_nolock(privep);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -1622,7 +1641,8 @@ static int rp2040_epsubmit(struct usbdev_ep_s *ep,
req->result = -EINPROGRESS;
req->xfrd = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
if (privep->stalled && privep->in)
{
@@ -1667,7 +1687,8 @@ static int rp2040_epsubmit(struct usbdev_ep_s *ep,
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return ret;
}
@@ -1697,9 +1718,11 @@ static int rp2040_epcancel(struct usbdev_ep_s *ep,
/* Remove request from req_queue */
flags = enter_critical_section();
rp2040_cancelrequests(privep);
leave_critical_section(flags);
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
rp2040_cancelrequests_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -1742,8 +1765,10 @@ static int rp2040_epstall_exec(struct usbdev_ep_s *ep)
int ret;
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
ret = rp2040_epstall_exec_nolock(ep);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -1762,6 +1787,7 @@ static int rp2040_epstall(struct usbdev_ep_s *ep, bool resume)
irqstate_t flags;
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
if (resume)
{
@@ -1803,6 +1829,7 @@ static int rp2040_epstall(struct usbdev_ep_s *ep, bool resume)
}
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -2153,6 +2180,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
usbtrace(TRACE_DEVUNREGISTER, 0);
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* Unbind the class driver */
@@ -2171,6 +2199,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
priv->driver = NULL;
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
+51 -24
View File
@@ -34,6 +34,7 @@
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/spinlock.h>
@@ -514,9 +515,9 @@ static int rp23xx_epwrite(struct rp23xx_ep_s *privep, uint8_t *buf,
/* Start the transfer */
flags = spin_lock_irqsave(&g_usbdev.lock);
flags = spin_lock_irqsave(&privep->dev->lock);
rp23xx_update_buffer_control(privep, 0, val);
spin_unlock_irqrestore(&g_usbdev.lock, flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
return nbytes;
}
@@ -543,9 +544,9 @@ static int rp23xx_epread(struct rp23xx_ep_s *privep, uint16_t nbytes)
/* Start the transfer */
flags = spin_lock_irqsave(&g_usbdev.lock);
flags = spin_lock_irqsave(&privep->dev->lock);
rp23xx_update_buffer_control(privep, 0, val);
spin_unlock_irqrestore(&g_usbdev.lock, flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
return OK;
}
@@ -582,17 +583,15 @@ static void rp23xx_abortrequest(struct rp23xx_ep_s *privep,
*
****************************************************************************/
static void rp23xx_reqcomplete(struct rp23xx_ep_s *privep, int16_t result)
static void rp23xx_reqcomplete_nolock(struct rp23xx_ep_s *privep,
int16_t result)
{
struct rp23xx_req_s *privreq;
int stalled = privep->stalled;
irqstate_t flags;
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
privreq = rp23xx_rqdequeue(privep);
leave_critical_section(flags);
if (privreq)
{
@@ -620,6 +619,13 @@ static void rp23xx_reqcomplete(struct rp23xx_ep_s *privep, int16_t result)
}
}
static void rp23xx_reqcomplete(struct rp23xx_ep_s *privep, int16_t result)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
rp23xx_reqcomplete_nolock(privep, result);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
* Name: rp23xx_txcomplete
*
@@ -854,16 +860,25 @@ static void rp23xx_handle_zlp(struct rp23xx_usbdev_s *priv)
*
****************************************************************************/
static void rp23xx_cancelrequests(struct rp23xx_ep_s *privep)
static void rp23xx_cancelrequests_nolock(struct rp23xx_ep_s *privep)
{
while (!rp23xx_rqempty(privep))
{
usbtrace(TRACE_COMPLETE(privep->epphy),
(rp23xx_rqpeek(privep))->req.xfrd);
rp23xx_reqcomplete(privep, -ESHUTDOWN);
rp23xx_reqcomplete_nolock(privep, -ESHUTDOWN);
}
}
static void rp23xx_cancelrequests(struct rp23xx_ep_s *privep)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
rp23xx_cancelrequests_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
}
/****************************************************************************
* Name: rp23xx_epfindbyaddr
*
@@ -1330,9 +1345,11 @@ static bool rp23xx_usbintr_buffstat(struct rp23xx_usbdev_s *priv)
}
else if (privep->pending_stall)
{
flags = spin_lock_irqsave(&g_usbdev.lock);
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
rp23xx_epstall_exec(&privep->ep);
spin_unlock_irqrestore(&g_usbdev.lock, flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
}
else
@@ -1519,7 +1536,8 @@ static int rp23xx_epdisable(struct usbdev_ep_s *ep)
usbtrace(TRACE_EPDISABLE, privep->epphy);
uinfo("EP%d\n", privep->epphy);
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
privep->ep.maxpacket = 64;
privep->stalled = false;
@@ -1528,9 +1546,10 @@ static int rp23xx_epdisable(struct usbdev_ep_s *ep)
/* Cancel all queued requests */
rp23xx_cancelrequests(privep);
rp23xx_cancelrequests_nolock(privep);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -1623,7 +1642,8 @@ static int rp23xx_epsubmit(struct usbdev_ep_s *ep,
req->result = -EINPROGRESS;
req->xfrd = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
if (privep->stalled && privep->in)
{
@@ -1668,7 +1688,8 @@ static int rp23xx_epsubmit(struct usbdev_ep_s *ep,
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return ret;
}
@@ -1698,9 +1719,11 @@ static int rp23xx_epcancel(struct usbdev_ep_s *ep,
/* Remove request from req_queue */
flags = enter_critical_section();
rp23xx_cancelrequests(privep);
leave_critical_section(flags);
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
rp23xx_cancelrequests_nolock(privep);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -1749,7 +1772,8 @@ static int rp23xx_epstall(struct usbdev_ep_s *ep, bool resume)
struct rp23xx_usbdev_s *priv = privep->dev;
irqstate_t flags;
flags = spin_lock_irqsave(&g_usbdev.lock);
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
if (resume)
{
@@ -1790,7 +1814,8 @@ static int rp23xx_epstall(struct usbdev_ep_s *ep, bool resume)
priv->zlp_stat = RP23XX_ZLP_NONE;
}
spin_unlock_irqrestore(&g_usbdev.lock, flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -2140,7 +2165,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
usbtrace(TRACE_DEVUNREGISTER, 0);
flags = spin_lock_irqsave(&g_usbdev.lock);
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* Unbind the class driver */
@@ -2158,7 +2184,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
priv->driver = NULL;
spin_unlock_irqrestore(&g_usbdev.lock, flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
+52 -26
View File
@@ -50,6 +50,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -58,6 +59,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include "arm_internal.h"
@@ -428,6 +430,10 @@ struct sam_usbdev_s
*/
uint8_t ep0out[SAM_EP0_MAXPACKET];
/* Spinlock */
spinlock_t lock;
};
/****************************************************************************
@@ -1195,16 +1201,13 @@ sam_req_abort(struct sam_ep_s *privep, struct sam_req_s *privreq,
*
****************************************************************************/
static void sam_req_complete(struct sam_ep_s *privep, int16_t result)
static void sam_req_complete_nolock(struct sam_ep_s *privep, int16_t result)
{
struct sam_req_s *privreq;
irqstate_t flags;
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
privreq = sam_req_dequeue(&privep->reqq);
leave_critical_section(flags);
if (privreq)
{
@@ -1235,6 +1238,15 @@ static void sam_req_complete(struct sam_ep_s *privep, int16_t result)
}
}
static void sam_req_complete(struct sam_ep_s *privep, int16_t result)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
sam_req_complete_nolock(privep, result);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
*
* Name: sam_ep_fifocon
@@ -1789,7 +1801,7 @@ static void sam_req_cancel(struct sam_ep_s *privep, int16_t result)
{
usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)),
(sam_rqpeek(&privep->reqq))->req.xfrd);
sam_req_complete(privep, result);
sam_req_complete_nolock(privep, result);
}
}
@@ -3531,7 +3543,7 @@ sam_ep_reserve(struct sam_usbdev_s *priv, uint16_t epset)
irqstate_t flags;
int epndx = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
@@ -3556,7 +3568,7 @@ sam_ep_reserve(struct sam_usbdev_s *priv, uint16_t epset)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return privep;
}
@@ -3573,9 +3585,9 @@ sam_ep_reserve(struct sam_usbdev_s *priv, uint16_t epset)
static inline void
sam_ep_unreserve(struct sam_usbdev_s *priv, struct sam_ep_s *privep)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= SAM_EP_BIT(USB_EPNO(privep->ep.eplog));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************
@@ -3898,14 +3910,14 @@ static int sam_ep_disable(struct usbdev_ep_s *ep)
/* Reset the endpoint and cancel any ongoing activity */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
priv = privep->dev;
sam_ep_reset(priv, epno);
/* Revert to the addressed-but-not-configured state */
priv->devstate = USBHS_DEVSTATE_ADDRESSED;
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
@@ -4021,7 +4033,8 @@ static int sam_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
req->result = -EINPROGRESS;
req->xfrd = 0;
privreq->inflight = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* Handle IN (device-to-host) requests. NOTE: If the class device is
* using the bi-directional EP0, then we assume that they intend the EP0
@@ -4073,7 +4086,8 @@ static int sam_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -4091,9 +4105,11 @@ static int sam_ep_cancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
DEBUGASSERT(ep != NULL && req != NULL);
usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog));
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
sam_req_cancel(privep, -EAGAIN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -4124,7 +4140,8 @@ static int sam_ep_stall(struct usbdev_ep_s *ep, bool resume)
/* STALL or RESUME the endpoint */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, USB_EPNO(ep->eplog));
/* Handle the resume condition */
@@ -4208,7 +4225,7 @@ static int sam_ep_stall(struct usbdev_ep_s *ep, bool resume)
else if (privep->epstate == USBHS_EPSTATE_RECEIVING)
{
sam_req_complete(privep, -EPERM);
sam_req_complete_nolock(privep, -EPERM);
}
/* Put endpoint into stalled state */
@@ -4247,7 +4264,8 @@ static int sam_ep_stall(struct usbdev_ep_s *ep, bool resume)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -4391,7 +4409,7 @@ static int sam_wakeup(struct usbdev_s *dev)
/* Resume normal operation */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sam_resume(priv);
/* Activate a remote wakeup.
@@ -4404,7 +4422,7 @@ static int sam_wakeup(struct usbdev_s *dev)
regval = sam_getreg(SAM_USBHS_DEVCTRL);
regval |= USBHS_DEVCTRL_RMWKUP;
sam_putreg(regval, SAM_USBHS_DEVCTRL);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
/* This bit is automatically cleared by hardware at the end of the Upstream
* Resume
@@ -4451,7 +4469,7 @@ static int sam_pullup(struct usbdev_s *dev, bool enable)
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
if (enable)
{
/* Un-freeze clocking.
@@ -4603,7 +4621,7 @@ static int sam_pullup(struct usbdev_s *dev, bool enable)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
@@ -4996,6 +5014,10 @@ void arm_usbinitialize(void)
usbtrace(TRACE_DEVINIT, 0);
/* Initialize driver lock */
spin_lock_init(&priv->lock);
/* Software initialization */
sam_sw_setup(priv);
@@ -5054,7 +5076,8 @@ void arm_usbuninitialize(void)
* easier.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
usbtrace(TRACE_DEVUNINIT, 0);
/* Disable and detach the USBHS IRQ */
@@ -5072,7 +5095,8 @@ void arm_usbuninitialize(void)
sam_hw_shutdown(priv);
sam_sw_shutdown(priv);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
@@ -5149,7 +5173,8 @@ 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);
sched_lock();
/* Unbind the class driver */
@@ -5173,7 +5198,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
/* Unhook the driver */
priv->driver = NULL;
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
+60 -28
View File
@@ -40,6 +40,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -48,6 +49,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include "arm_internal.h"
#include "stm32.h"
@@ -357,6 +359,10 @@ struct stm32_usbdev_s
/* The endpoint list */
struct stm32_ep_s eplist[STM32_NENDPOINTS];
/* Spinlock */
spinlock_t lock;
};
/****************************************************************************
@@ -1215,16 +1221,14 @@ stm32_abortrequest(struct stm32_ep_s *privep,
* Name: stm32_reqcomplete
****************************************************************************/
static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result)
static void stm32_reqcomplete_nolock(struct stm32_ep_s *privep,
int16_t result)
{
struct stm32_req_s *privreq;
irqstate_t flags;
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
privreq = stm32_rqdequeue(privep);
leave_critical_section(flags);
if (privreq)
{
@@ -1253,6 +1257,15 @@ static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result)
}
}
static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
stm32_reqcomplete_nolock(privep, result);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
* Name: tm32_epwrite
****************************************************************************/
@@ -1540,7 +1553,7 @@ static void stm32_cancelrequests(struct stm32_ep_s *privep)
{
usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)),
(stm32_rqpeek(privep))->req.xfrd);
stm32_reqcomplete(privep, -ESHUTDOWN);
stm32_reqcomplete_nolock(privep, -ESHUTDOWN);
}
}
@@ -2745,7 +2758,7 @@ stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset)
irqstate_t flags;
int epndx = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
@@ -2770,7 +2783,7 @@ stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return privep;
}
@@ -2781,9 +2794,9 @@ stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset)
static inline void
stm32_epunreserve(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= STM32_ENDP_BIT(USB_EPNO(privep->ep.eplog));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************
@@ -2806,7 +2819,7 @@ static int stm32_epallocpma(struct stm32_usbdev_s *priv)
int bufno = ERROR;
int bufndx;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
for (bufndx = 2; bufndx < STM32_NBUFFERS; bufndx++)
{
/* Check if this buffer is available */
@@ -2825,7 +2838,7 @@ static int stm32_epallocpma(struct stm32_usbdev_s *priv)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return bufno;
}
@@ -2836,9 +2849,9 @@ static int stm32_epallocpma(struct stm32_usbdev_s *priv)
static inline void
stm32_epfreepma(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= STM32_ENDP_BIT(privep->bufno);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************
@@ -2970,7 +2983,8 @@ static int stm32_epdisable(struct usbdev_ep_s *ep)
/* Cancel any ongoing activity */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
stm32_cancelrequests(privep);
/* Disable TX; disable RX */
@@ -2979,7 +2993,8 @@ static int stm32_epdisable(struct usbdev_ep_s *ep)
stm32_seteprxstatus(epno, USB_EPR_STATRX_DIS);
stm32_seteptxstatus(epno, USB_EPR_STATTX_DIS);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -3072,7 +3087,8 @@ static int stm32_epsubmit(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 we are stalled, then drop all requests on the floor */
@@ -3145,7 +3161,8 @@ static int stm32_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -3167,9 +3184,11 @@ static int stm32_epcancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
#endif
usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog));
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
stm32_cancelrequests(privep);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -3199,7 +3218,8 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume)
/* STALL or RESUME the endpoint */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, USB_EPNO(ep->eplog));
/* Get status of the endpoint; stall the request if the endpoint is
@@ -3224,7 +3244,8 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume)
priv->ep0state = EP0STATE_STALLED;
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return -ENODEV;
}
@@ -3310,7 +3331,8 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -3474,7 +3496,8 @@ static int stm32_wakeup(struct usbdev_s *dev)
* by the ESOF interrupt.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
stm32_initresume(priv);
priv->rsmstate = RSMSTATE_STARTED;
@@ -3486,7 +3509,8 @@ static int stm32_wakeup(struct usbdev_s *dev)
stm32_setimask(priv, USB_CNTR_ESOFM, USB_CNTR_WKUPM | USB_CNTR_SUSPM);
stm32_putreg(~USB_ISTR_ESOF, STM32_USB_ISTR);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -3748,6 +3772,10 @@ void arm_usbinitialize(void)
usbtrace(TRACE_DEVINIT, 0);
stm32_checksetup();
/* Initialize driver lock */
spin_lock_init(&priv->lock);
/* Configure USB GPIO alternate function pins */
#ifdef CONFIG_STM32_STM32F30XX
@@ -3823,7 +3851,8 @@ void arm_usbuninitialize(void)
struct stm32_usbdev_s *priv = &g_usbdev;
irqstate_t flags;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
usbtrace(TRACE_DEVUNINIT, 0);
/* Disable and detach the USB IRQs */
@@ -3842,7 +3871,8 @@ void arm_usbuninitialize(void)
/* Put the hardware in an inactive state */
stm32_hwshutdown(priv);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
@@ -3951,7 +3981,8 @@ 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);
sched_lock();
stm32_reset(priv);
/* Unbind the class driver */
@@ -3974,7 +4005,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
/* Unhook the driver */
priv->driver = NULL;
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
+116 -70
View File
@@ -40,6 +40,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -48,6 +49,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include "arm_internal.h"
#include "hardware/stm32_rcc.h"
@@ -342,6 +344,10 @@ struct stm32_usbdev_s
/* The endpoint list */
struct stm32_ep_s eplist[STM32_NENDPOINTS];
/* Spinlock */
spinlock_t lock;
};
/****************************************************************************
@@ -1161,16 +1167,14 @@ stm32_abortrequest(struct stm32_ep_s *privep,
* Name: stm32_reqcomplete
****************************************************************************/
static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result)
static void stm32_reqcomplete_nolock(struct stm32_ep_s *privep,
int16_t result)
{
struct stm32_req_s *privreq;
irqstate_t flags;
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
privreq = stm32_rqdequeue(privep);
leave_critical_section(flags);
if (privreq)
{
@@ -1199,6 +1203,15 @@ static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result)
}
}
static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result)
{
irqstate_t flags = spin_lock_irqsave(&privep->dev->lock);
stm32_reqcomplete_nolock(privep, result);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
* Name: tm32_epwrite
****************************************************************************/
@@ -2669,7 +2682,7 @@ stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset)
irqstate_t flags;
int epndx = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
@@ -2694,7 +2707,7 @@ stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return privep;
}
@@ -2705,9 +2718,9 @@ stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset)
static inline void
stm32_epunreserve(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= STM32_ENDP_BIT(USB_EPNO(privep->ep.eplog));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************
@@ -2730,7 +2743,7 @@ static int stm32_epallocpma(struct stm32_usbdev_s *priv)
int bufno = ERROR;
int bufndx;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
for (bufndx = 2; bufndx < STM32_NBUFFERS; bufndx++)
{
/* Check if this buffer is available */
@@ -2749,7 +2762,7 @@ static int stm32_epallocpma(struct stm32_usbdev_s *priv)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return bufno;
}
@@ -2760,9 +2773,9 @@ static int stm32_epallocpma(struct stm32_usbdev_s *priv)
static inline void
stm32_epfreepma(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= STM32_ENDP_BIT(privep->bufno);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************
@@ -2894,7 +2907,8 @@ static int stm32_epdisable(struct usbdev_ep_s *ep)
/* Cancel any ongoing activity */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
stm32_cancelrequests(privep);
/* Disable TX; disable RX */
@@ -2903,7 +2917,8 @@ static int stm32_epdisable(struct usbdev_ep_s *ep)
stm32_seteprxstatus(epno, USB_EPR_STATRX_DIS);
stm32_seteptxstatus(epno, USB_EPR_STATTX_DIS);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -2997,7 +3012,8 @@ static int stm32_epsubmit(struct usbdev_ep_s *ep,
epno = USB_EPNO(ep->eplog);
req->result = -EINPROGRESS;
req->xfrd = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
/* If we are stalled, then drop all requests on the floor */
@@ -3072,7 +3088,8 @@ static int stm32_epsubmit(struct usbdev_ep_s *ep,
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -3095,9 +3112,11 @@ static int stm32_epcancel(struct usbdev_ep_s *ep,
#endif
usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog));
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
stm32_cancelrequests(privep);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -3127,7 +3146,8 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume)
/* STALL or RESUME the endpoint */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, USB_EPNO(ep->eplog));
/* Get status of the endpoint; stall the request if the endpoint is
@@ -3152,7 +3172,8 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume)
priv->ep0state = EP0STATE_STALLED;
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return -ENODEV;
}
@@ -3238,7 +3259,8 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -3403,7 +3425,7 @@ static int stm32_wakeup(struct usbdev_s *dev)
* by the ESOF interrupt.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
stm32_initresume(priv);
priv->rsmstate = RSMSTATE_STARTED;
@@ -3415,7 +3437,7 @@ static int stm32_wakeup(struct usbdev_s *dev)
stm32_setimask(priv, USB_CNTR_ESOFM, USB_CNTR_WKUPM | USB_CNTR_SUSPM);
stm32_putreg(~USB_ISTR_ESOF, STM32_USB_ISTR);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
@@ -3649,6 +3671,61 @@ static void stm32_hwshutdown(struct stm32_usbdev_s *priv)
stm32_putreg(USB_CNTR_FRES | USB_CNTR_PDWN, STM32_USB_CNTR);
}
/****************************************************************************
* Name: usbdev_unregister_nolock
*
* Description:
* The version of the public function usbdev_unregister without spin lock.
*
****************************************************************************/
static int usbdev_unregister_nolock(struct usbdevclass_driver_s *driver)
{
/* For now there is only one USB controller, but we will always refer to
* it using a pointer to make any future ports to multiple USB controllers
* easier.
*/
struct stm32_usbdev_s *priv = &g_usbdev;
usbtrace(TRACE_DEVUNREGISTER, 0);
#ifdef CONFIG_DEBUG_USB
if (driver != priv->driver)
{
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
return -EINVAL;
}
#endif
/* Reset the hardware and cancel all requests. All requests must be
* canceled while the class driver is still bound.
*/
stm32_reset(priv);
/* Unbind the class driver */
CLASS_UNBIND(driver, &priv->usbdev);
/* Disable USB controller interrupts (but keep them attached) */
up_disable_irq(STM32_IRQ_USB);
/* Put the hardware in an inactive state. Then bring the hardware back up
* in the reset state (this is probably not necessary, the stm32_reset()
* call above was probably sufficient).
*/
stm32_hwshutdown(priv);
stm32_hwsetup(priv);
/* Unhook the driver */
priv->driver = NULL;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -3677,6 +3754,10 @@ void arm_usbinitialize(void)
usbtrace(TRACE_DEVINIT, 0);
/* Initialize driver lock */
spin_lock_init(&priv->lock);
/* Configure USB GPIO alternate function pins */
stm32_configgpio(GPIO_USB_DM);
@@ -3733,7 +3814,8 @@ void arm_usbuninitialize(void)
struct stm32_usbdev_s *priv = &g_usbdev;
irqstate_t flags;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
usbtrace(TRACE_DEVUNINIT, 0);
/* Disable and detach the USB IRQs */
@@ -3744,13 +3826,14 @@ void arm_usbuninitialize(void)
if (priv->driver)
{
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DRIVERREGISTERED), 0);
usbdev_unregister(priv->driver);
usbdev_unregister_nolock(priv->driver);
}
/* Put the hardware in an inactive state */
stm32_hwshutdown(priv);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
@@ -3837,52 +3920,15 @@ int usbdev_register(struct usbdevclass_driver_s *driver)
int usbdev_unregister(struct usbdevclass_driver_s *driver)
{
/* For now there is only one USB controller, but we will always refer to
* it using a pointer to make any future ports to multiple USB controllers
* easier.
*/
int ret;
struct stm32_usbdev_s *priv = &g_usbdev;
irqstate_t flags;
irqstate_t flags = spin_lock_irqsave(&g_usbdev.lock);
sched_lock();
ret = usbdev_unregister_nolock(driver);
spin_unlock_irqrestore(&g_usbdev.lock, flags);
sched_unlock();
usbtrace(TRACE_DEVUNREGISTER, 0);
#ifdef CONFIG_DEBUG_USB
if (driver != priv->driver)
{
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0);
return -EINVAL;
}
#endif
/* Reset the hardware and cancel all requests. All requests must be
* canceled while the class driver is still bound.
*/
flags = enter_critical_section();
stm32_reset(priv);
/* Unbind the class driver */
CLASS_UNBIND(driver, &priv->usbdev);
/* Disable USB controller interrupts (but keep them attached) */
up_disable_irq(STM32_IRQ_USB);
/* Put the hardware in an inactive state. Then bring the hardware back up
* in the reset state (this is probably not necessary, the stm32_reset()
* call above was probably sufficient).
*/
stm32_hwshutdown(priv);
stm32_hwsetup(priv);
/* Unhook the driver */
priv->driver = NULL;
leave_critical_section(flags);
return OK;
return ret;
}
#endif /* CONFIG_USBDEV && CONFIG_STM32F0L0G0_USB */
+64 -31
View File
@@ -35,6 +35,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
@@ -43,6 +44,7 @@
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/irq.h>
#include <nuttx/spinlock.h>
#include "arm_internal.h"
#include "stm32l4.h"
@@ -342,7 +344,11 @@ struct stm32l4_usbdev_s
/* The endpoint list */
struct stm32l4_ep_s eplist[STM32L4_NENDPOINTS];
struct stm32l4_ep_s eplist[STM32L4_NENDPOINTS];
/* Spinlock */
spinlock_t lock;
};
/****************************************************************************
@@ -1215,16 +1221,14 @@ stm32l4_abortrequest(struct stm32l4_ep_s *privep,
* Name: stm32l4_reqcomplete
****************************************************************************/
static void stm32l4_reqcomplete(struct stm32l4_ep_s *privep, int16_t result)
static void stm32l4_reqcomplete_nolock(struct stm32l4_ep_s *privep,
int16_t result)
{
struct stm32l4_req_s *privreq;
irqstate_t flags;
/* Remove the completed request at the head of the endpoint request list */
flags = enter_critical_section();
privreq = stm32l4_rqdequeue(privep);
leave_critical_section(flags);
if (privreq)
{
@@ -1253,6 +1257,15 @@ static void stm32l4_reqcomplete(struct stm32l4_ep_s *privep, int16_t result)
}
}
static void stm32l4_reqcomplete(struct stm32l4_ep_s *privep, int16_t result)
{
flags = spin_lock_irqsave(&privep->dev->lock);
stm32l4_reqcomplete_nolock(privep, result);
spin_unlock_irqrestore(&privep->dev->lock, flags);
}
/****************************************************************************
* Name: tm32_epwrite
****************************************************************************/
@@ -1539,7 +1552,7 @@ static void stm32l4_cancelrequests(struct stm32l4_ep_s *privep)
{
usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)),
(stm32l4_rqpeek(privep))->req.xfrd);
stm32l4_reqcomplete(privep, -ESHUTDOWN);
stm32l4_reqcomplete_nolock(privep, -ESHUTDOWN);
}
}
@@ -2702,7 +2715,7 @@ stm32l4_epreserve(struct stm32l4_usbdev_s *priv, uint8_t epset)
irqstate_t flags;
int epndx = 0;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
@@ -2727,7 +2740,7 @@ stm32l4_epreserve(struct stm32l4_usbdev_s *priv, uint8_t epset)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return privep;
}
@@ -2739,9 +2752,9 @@ static inline void
stm32l4_epunreserve(struct stm32l4_usbdev_s *priv,
struct stm32l4_ep_s *privep)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= STM32L4_ENDP_BIT(USB_EPNO(privep->ep.eplog));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************
@@ -2764,7 +2777,7 @@ static int stm32l4_epallocpma(struct stm32l4_usbdev_s *priv)
int bufno = ERROR;
int bufndx;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
for (bufndx = 2; bufndx < STM32L4_NBUFFERS; bufndx++)
{
/* Check if this buffer is available */
@@ -2783,7 +2796,7 @@ static int stm32l4_epallocpma(struct stm32l4_usbdev_s *priv)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return bufno;
}
@@ -2794,9 +2807,9 @@ static int stm32l4_epallocpma(struct stm32l4_usbdev_s *priv)
static inline void
stm32l4_epfreepma(struct stm32l4_usbdev_s *priv, struct stm32l4_ep_s *privep)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= STM32L4_ENDP_BIT(privep->bufno);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************
@@ -2928,7 +2941,8 @@ static int stm32l4_epdisable(struct usbdev_ep_s *ep)
/* Cancel any ongoing activity */
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
stm32l4_cancelrequests(privep);
/* Disable TX; disable RX */
@@ -2937,7 +2951,8 @@ static int stm32l4_epdisable(struct usbdev_ep_s *ep)
stm32l4_seteprxstatus(epno, USB_EPR_STATRX_DIS);
stm32l4_seteptxstatus(epno, USB_EPR_STATTX_DIS);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -3033,7 +3048,8 @@ static int stm32l4_epsubmit(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 we are stalled, then drop all requests on the floor */
@@ -3106,7 +3122,8 @@ static int stm32l4_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}
@@ -3129,9 +3146,11 @@ static int stm32l4_epcancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog));
flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
stm32l4_cancelrequests(privep);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}
@@ -3161,7 +3180,8 @@ static int stm32l4_epstall(struct usbdev_ep_s *ep, bool resume)
/* STALL or RESUME the endpoint */
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, USB_EPNO(ep->eplog));
/* Get status of the endpoint; stall the request if the endpoint is
@@ -3186,7 +3206,8 @@ static int stm32l4_epstall(struct usbdev_ep_s *ep, bool resume)
priv->ep0state = EP0STATE_STALLED;
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return -ENODEV;
}
@@ -3272,7 +3293,8 @@ static int stm32l4_epstall(struct usbdev_ep_s *ep, bool resume)
}
}
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -3438,7 +3460,8 @@ static int stm32l4_wakeup(struct usbdev_s *dev)
* by the ESOF interrupt.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
stm32l4_initresume(priv);
priv->rsmstate = RSMSTATE_STARTED;
@@ -3450,7 +3473,8 @@ static int stm32l4_wakeup(struct usbdev_s *dev)
stm32l4_setimask(priv, USB_CNTR_ESOFM, USB_CNTR_WKUPM | USB_CNTR_SUSPM);
stm32l4_putreg(~USB_ISTR_ESOF, STM32L4_USB_ISTR);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}
@@ -3482,12 +3506,13 @@ static int stm32l4_selfpowered(struct usbdev_s *dev, bool selfpowered)
static int stm32l4_pullup(struct usbdev_s *dev, bool enable)
{
struct stm32l4_usbdev_s *priv = (struct stm32l4_usbdev_s *)dev;
uint32_t regval;
irqstate_t flags;
usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
regval = stm32l4_getreg(STM32L4_USB_BCDR);
if (enable)
{
@@ -3507,7 +3532,7 @@ static int stm32l4_pullup(struct usbdev_s *dev, bool enable)
}
stm32l4_putreg(regval, STM32L4_USB_BCDR);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
}
@@ -3743,6 +3768,10 @@ void arm_usbinitialize(void)
usbtrace(TRACE_DEVINIT, 0);
stm32l4_checksetup();
/* Initialize driver lock */
spin_lock_init(&priv->lock);
/* Enable Vbus monitoring in the Power control */
stm32l4_pwr_enableusv(true);
@@ -3782,7 +3811,8 @@ void arm_usbuninitialize(void)
struct stm32l4_usbdev_s *priv = &g_usbdev;
irqstate_t flags;
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
usbtrace(TRACE_DEVUNINIT, 0);
/* Disable and detach the USB IRQ */
@@ -3804,7 +3834,8 @@ void arm_usbuninitialize(void)
stm32l4_pwr_enableusv(false);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}
/****************************************************************************
@@ -3912,7 +3943,8 @@ 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);
sched_lock();
stm32l4_reset(priv);
/* Unbind the class driver */
@@ -3934,7 +3966,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
/* Unhook the driver */
priv->driver = NULL;
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}