From 2986a7b88b3c8cbee968ea0e67b5723f8034bcb5 Mon Sep 17 00:00:00 2001 From: wangzhi16 Date: Mon, 13 Jan 2025 11:37:04 +0800 Subject: [PATCH] Use small lock to protect usbdev and endpoint in arch ARM. Signed-off-by: wangzhi16 --- arch/arm/src/cxd56xx/cxd56_usbdev.c | 73 ++++++++++------ arch/arm/src/dm320/dm320_usbdev.c | 60 ++++++++----- arch/arm/src/efm32/efm32_usbdev.c | 67 +++++++++------ arch/arm/src/imxrt/imxrt_usbdev.c | 43 +++++----- arch/arm/src/kinetis/kinetis_usbdev.c | 44 +++++----- arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c | 93 +++++++++++++------- arch/arm/src/lpc214x/lpc214x_usbdev.c | 94 ++++++++++++++------- arch/arm/src/lpc31xx/lpc31_usbdev.c | 51 ++++++----- arch/arm/src/rp2040/rp2040_usbdev.c | 40 ++++++--- arch/arm/src/rp23xx/rp23xx_usbdev.c | 38 ++++++--- arch/arm/src/samv7/sam_usbdevhs.c | 48 ++++++----- arch/arm/src/stm32/stm32_usbdev.c | 63 ++++++++------ arch/arm/src/stm32f0l0g0/stm32_usbdev.c | 79 ++++++++++------- arch/arm/src/stm32l4/stm32l4_usbdev.c | 68 ++++++++------- include/nuttx/usb/usbdev.h | 3 + 15 files changed, 532 insertions(+), 332 deletions(-) diff --git a/arch/arm/src/cxd56xx/cxd56_usbdev.c b/arch/arm/src/cxd56xx/cxd56_usbdev.c index 2ec84ba7cecd6..d81db651cbeb2 100644 --- a/arch/arm/src/cxd56xx/cxd56_usbdev.c +++ b/arch/arm/src/cxd56xx/cxd56_usbdev.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ #include #include +#include #include #include #include @@ -784,17 +786,14 @@ 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 +821,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->ep.lock); + + /* Remove the completed request at the head of the endpoint request list */ + + cxd56_reqcomplete_nolock(privep, result); + + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: cxd56_txdmacomplete * @@ -1085,7 +1095,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 +1113,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 +1129,15 @@ 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->ep.lock); + + cxd56_cancelrequests_nolock(privep); + + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: cxd56_epfindbyaddr * @@ -2269,10 +2288,10 @@ 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->ep.lock); cxd56_epstall(&privep->ep, false); - cxd56_cancelrequests(privep); - leave_critical_section(flags); + cxd56_cancelrequests_nolock(privep); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2411,7 +2430,8 @@ static int cxd56_epsubmit(struct usbdev_ep_s *ep, req->result = -EINPROGRESS; req->xfrd = 0; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); + sched_lock(); /* If we are stalled, then drop all requests on the floor, except OUT */ @@ -2515,7 +2535,8 @@ static int cxd56_epsubmit(struct usbdev_ep_s *ep, ret = cxd56_rdrequest(privep); } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); + sched_unlock(); return ret; } @@ -2543,9 +2564,9 @@ 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->ep.lock); + cxd56_cancelrequests_nolock(privep); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2725,12 +2746,12 @@ static struct usbdev_ep_s *cxd56_allocep(struct usbdev_s *dev, continue; } - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.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->usbdev.lock, flags); return &priv->eplist[ndx].ep; } } @@ -2758,9 +2779,9 @@ static void cxd56_freeep(struct usbdev_s *dev, cxd56_freeepbuffer(privep); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&pdev->usbdev.lock); pdev->avail |= 1 << privep->epphy; - leave_critical_section(flags); + spin_unlock_irqrestore(&pdev->usbdev.lock, flags); } /**************************************************************************** @@ -2790,9 +2811,9 @@ static int cxd56_getframe(struct usbdev_s *dev) * because the operation is not atomic. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&dev.lock); ret = getreg32(CXD56_USB_DEV_STATUS) >> 18; - leave_critical_section(flags); + spin_unlock_irqrestore(&dev.lock, flags); return ret; } @@ -2810,9 +2831,9 @@ static int cxd56_wakeup(struct usbdev_s *dev) usbtrace(TRACE_DEVWAKEUP, 0); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&dev.lock); putreg32(getreg32(CXD56_USB_DEV_CONTROL) | 1, CXD56_USB_DEV_CONTROL); - leave_critical_section(flags); + spin_unlock_irqrestore(&dev.lock, flags); return OK; } @@ -3135,7 +3156,7 @@ void arm_usbuninitialize(void) usbdev_unregister(priv->driver); } - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); cxd56_pullup(&priv->usbdev, false); priv->usbdev.speed = USB_SPEED_UNKNOWN; @@ -3152,7 +3173,7 @@ void arm_usbuninitialize(void) irq_detach(CXD56_IRQ_USB_VBUSN); cxd56_usb_clock_disable(); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); /* Clear signal */ @@ -3246,7 +3267,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) CLASS_UNBIND(driver, &g_usbdev.usbdev); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); /* Disable IRQs */ @@ -3266,7 +3287,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) cxd56_usbhwuninit(); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); up_pm_release_freqlock(&g_hv_lock); up_pm_release_wakelock(&g_wake_lock); diff --git a/arch/arm/src/dm320/dm320_usbdev.c b/arch/arm/src/dm320/dm320_usbdev.c index 93f47cc8c8af1..930821e52a6b6 100644 --- a/arch/arm/src/dm320/dm320_usbdev.c +++ b/arch/arm/src/dm320/dm320_usbdev.c @@ -42,6 +42,7 @@ #include #include +#include #include #include "chip.h" @@ -892,7 +893,7 @@ 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; @@ -900,9 +901,7 @@ static void dm320_reqcomplete(struct dm320_ep_s *privep, int16_t result) /* 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 +932,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->ep.lock); + + /* Remove the completed request at the head of the endpoint request list */ + + cxd56_reqcomplete_nolock(privep, result); + + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: dm320_wrrequest * @@ -944,7 +954,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 +1029,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 +1037,18 @@ 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->ep.lock); + + ret = dm320_wrrequest_nolock(privep); + + spin_unlock_irqrestore(&privep->ep.lock, flags); + + return ret; +} + /**************************************************************************** * Name: dm320_rdrequest * @@ -1091,7 +1113,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 +2020,11 @@ 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->ep.lock); dm320_cancelrequests(privep); dm320_epreset(privep->epphy); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2141,7 +2163,7 @@ static int dm320_epsubmit(struct usbdev_ep_s *ep, req->result = -EINPROGRESS; req->xfrd = 0; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); /* Check for NULL packet */ @@ -2179,7 +2201,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 +2223,7 @@ static int dm320_epsubmit(struct usbdev_ep_s *ep, } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return ret; } @@ -2231,9 +2253,9 @@ 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(&privep->ep.lock); dm320_cancelrequests(privep); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2358,10 +2380,10 @@ static int dm320_getframe(struct usbdev_s *dev) * because the operation is not atomic. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&dev->lock); ret = dm320_getreg8(DM320_USB_FRAME2) << 8; ret |= dm320_getreg8(DM320_USB_FRAME1); - leave_critical_section(flags); + spin_unlock_irqrestore(&dev->lock, flags); return ret; } @@ -2378,9 +2400,9 @@ static int dm320_wakeup(struct usbdev_s *dev) irqstate_t flags; usbtrace(TRACE_DEVWAKEUP, 0); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&dev->lock); dm320_putreg8(USB_POWER_RESUME, DM320_USB_POWER); - leave_critical_section(flags); + spin_unlock_irqrestore(&dev->lock, flags); return OK; } @@ -2425,7 +2447,7 @@ static int dm320_pullup(struct usbdev_s *dev, bool enable) usbtrace(TRACE_DEVPULLUP, (uint16_t)enable); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&dev->lock); if (enable) { GIO_SET_OUTPUT(CONFIG_DM320_GIO_USBDPPULLUP); /* Set D+ pullup */ @@ -2435,7 +2457,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(&dev->lock, flags); return OK; } #endif diff --git a/arch/arm/src/efm32/efm32_usbdev.c b/arch/arm/src/efm32/efm32_usbdev.c index e4fd0157a096e..378e62c836b06 100644 --- a/arch/arm/src/efm32/efm32_usbdev.c +++ b/arch/arm/src/efm32/efm32_usbdev.c @@ -43,6 +43,7 @@ #include #include +#include #include #include "chip.h" @@ -4123,7 +4124,7 @@ 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->ep.lock); efm32_enablegonak(privep); /* Disable the required OUT endpoint by setting the EPDIS and SNAK bits @@ -4170,7 +4171,7 @@ static void efm32_epout_disable(struct efm32_ep_s *privep) efm32_req_cancel(privep, -ESHUTDOWN); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); } /**************************************************************************** @@ -4235,7 +4236,7 @@ static void efm32_epin_disable(struct efm32_ep_s *privep) * the DIEPCTLx register. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); regaddr = EFM32_USB_DIEPCTL(privep->epphy); regval = efm32_getreg(regaddr); regval &= ~USB_DIEPCTL_USBACTEP; @@ -4266,7 +4267,7 @@ 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->ep.lock, flags); } /**************************************************************************** @@ -4457,7 +4458,7 @@ static int efm32_ep_submit(struct usbdev_ep_s *ep, /* Disable Interrupts */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); /* If we are stalled, then drop all requests on the floor */ @@ -4502,7 +4503,7 @@ static int efm32_ep_submit(struct usbdev_ep_s *ep, } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return ret; } @@ -4530,7 +4531,7 @@ static int efm32_ep_cancel(struct usbdev_ep_s *ep, usbtrace(TRACE_EPCANCEL, privep->epphy); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); /* FIXME: if the request is the first, then we need to flush the EP * otherwise just remove it from the list @@ -4539,7 +4540,7 @@ static int efm32_ep_cancel(struct usbdev_ep_s *ep, */ efm32_req_cancel(privep, -ESHUTDOWN); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -4749,7 +4750,7 @@ 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->ep.lock); if (resume) { ret = efm32_ep_clrstall(privep); @@ -4759,7 +4760,7 @@ 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->ep.lock, flags); return ret; } @@ -4819,7 +4820,7 @@ 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->usbdev.lock); epavail = priv->epavail[in]; /* A physical address of 0 means that any endpoint will do */ @@ -4866,7 +4867,7 @@ 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->usbdev.lock, flags); return in ? &priv->epin[epno].ep : &priv->epout[epno].ep; } } @@ -4875,7 +4876,7 @@ 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->usbdev.lock, flags); return NULL; } @@ -4900,9 +4901,9 @@ static void efm32_ep_free(struct usbdev_s *dev, { /* Mark the endpoint as available */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); priv->epavail[privep->isin] |= (1 << privep->epphy); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } } @@ -4944,7 +4945,7 @@ static int efm32_wakeup(struct usbdev_s *dev) /* Is wakeup enabled? */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); if (priv->wakeup) { /* Yes... is the core suspended? */ @@ -4970,7 +4971,7 @@ static int efm32_wakeup(struct usbdev_s *dev) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return OK; } @@ -5008,13 +5009,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 +5034,21 @@ 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; + + irqstate_t flags = spin_lock_irqsave(&dev->lock); + ret = efm32_pullup_nolock(dev, enable); + spin_unlock_irqrestore(&dev->lock, flags); + + return ret; +} + /**************************************************************************** * Name: efm32_setaddress * @@ -5657,8 +5668,8 @@ void arm_usbuninitialize(void) /* Disconnect device */ - flags = enter_critical_section(); - efm32_pullup(&priv->usbdev, false); + flags = spin_lock_irqsave(&priv->usbdev.lock); + efm32_pullup_nolock(&priv->usbdev, false); priv->usbdev.speed = USB_SPEED_UNKNOWN; /* Disable and detach IRQs */ @@ -5693,7 +5704,7 @@ void arm_usbuninitialize(void) /* TODO: Turn off USB power and clocking */ priv->devstate = DEVSTATE_DEFAULT; - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -5804,9 +5815,9 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) * canceled while the class driver is still bound. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); efm32_usbreset(priv); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); /* Unbind the class driver */ @@ -5814,17 +5825,17 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) /* Disable USB controller interrupts */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.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->usbdev.lock, flags); return OK; } diff --git a/arch/arm/src/imxrt/imxrt_usbdev.c b/arch/arm/src/imxrt/imxrt_usbdev.c index e4de158199f08..06dd5a41572f9 100644 --- a/arch/arm/src/imxrt/imxrt_usbdev.c +++ b/arch/arm/src/imxrt/imxrt_usbdev.c @@ -42,6 +42,7 @@ #include #include +#include #include #include "chip.h" @@ -2238,7 +2239,7 @@ static int imxrt_epdisable(struct usbdev_ep_s *ep) usbtrace(TRACE_EPDISABLE, privep->epphy); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); /* Disable Endpoint */ @@ -2259,7 +2260,7 @@ static int imxrt_epdisable(struct usbdev_ep_s *ep) imxrt_cancelrequests(privep, -ESHUTDOWN); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2416,7 +2417,7 @@ static int imxrt_epsubmit(struct usbdev_ep_s *ep, /* Disable Interrupts */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); /* If we are stalled, then drop all requests on the floor */ @@ -2443,7 +2444,7 @@ static int imxrt_epsubmit(struct usbdev_ep_s *ep, } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return ret; } @@ -2471,7 +2472,7 @@ static int imxrt_epcancel(struct usbdev_ep_s *ep, usbtrace(TRACE_EPCANCEL, privep->epphy); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); /* FIXME: if the request is the first, then we need to flush the EP * otherwise just remove it from the list @@ -2480,7 +2481,7 @@ static int imxrt_epcancel(struct usbdev_ep_s *ep, */ imxrt_cancelrequests(privep, -ESHUTDOWN); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2499,7 +2500,7 @@ 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->ep.lock); usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, privep->epphy); uint32_t addr = IMXRT_USBDEV_ENDPTCTRL(privep->epphy >> 1); @@ -2523,7 +2524,7 @@ static int imxrt_epstall(struct usbdev_ep_s *ep, bool resume) imxrt_setbits(ctrl_xs, addr); } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2627,7 +2628,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->usbdev.lock); epset &= priv->epavail; if (epset) { @@ -2643,7 +2644,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->usbdev.lock, flags); /* And return the pointer to the standard endpoint * structure @@ -2656,7 +2657,7 @@ static struct usbdev_ep_s *imxrt_allocep(struct usbdev_s *dev, /* Shouldn't get here */ } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } usbtrace(TRACE_DEVERROR(IMXRT_TRACEERR_NOEP), (uint16_t)eplog); @@ -2684,9 +2685,9 @@ static void imxrt_freeep(struct usbdev_s *dev, { /* Mark the endpoint as available */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); priv->epavail |= (1 << privep->epphy); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } } @@ -2734,9 +2735,9 @@ static int imxrt_wakeup(struct usbdev_s *dev) usbtrace(TRACE_DEVWAKEUP, 0); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&dev->lock); imxrt_setbits(USBDEV_PRTSC1_FPR, IMXRT_USBDEV_PORTSC1); - leave_critical_section(flags); + spin_unlock_irqrestore(&dev->lock, flags); return OK; } @@ -2778,7 +2779,7 @@ static int imxrt_pullup(struct usbdev_s *dev, bool enable) { usbtrace(TRACE_DEVPULLUP, (uint16_t)enable); - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&dev->lock); if (enable) { imxrt_setbits(USBDEV_USBCMD_RS, IMXRT_USBDEV_USBCMD); @@ -2795,7 +2796,7 @@ static int imxrt_pullup(struct usbdev_s *dev, bool enable) imxrt_clrbits(USBDEV_USBCMD_RS, IMXRT_USBDEV_USBCMD); } - leave_critical_section(flags); + spin_unlock_irqrestore(&dev->lock, flags); return OK; } @@ -2823,7 +2824,7 @@ void arm_usbinitialize(void) int i; irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); /* Initialize the device state structure */ @@ -2948,7 +2949,7 @@ void arm_usbinitialize(void) irq_attach(IMXRT_IRQ_USBOTG1, imxrt_usbinterrupt, NULL); up_enable_irq(IMXRT_IRQ_USBOTG1); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); /* Reset/Re-initialize the USB hardware */ @@ -2972,7 +2973,7 @@ void arm_usbuninitialize(void) usbdev_unregister(priv->driver); } - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); /* Disconnect device */ @@ -3003,7 +3004,7 @@ void arm_usbuninitialize(void) imxrt_clockoff_usboh3(); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** diff --git a/arch/arm/src/kinetis/kinetis_usbdev.c b/arch/arm/src/kinetis/kinetis_usbdev.c index 1b48acfcb36d3..6beb39584ee6d 100644 --- a/arch/arm/src/kinetis/kinetis_usbdev.c +++ b/arch/arm/src/kinetis/kinetis_usbdev.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,7 @@ #include #include +#include #include "arm_internal.h" #include "kinetis.h" @@ -892,9 +894,9 @@ static void khci_reqcomplete(struct khci_ep_s *privep, int16_t result) * request list. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); privreq = khci_remfirst(&privep->active); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); if (privreq) { @@ -3202,7 +3204,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->usbdev.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 +3246,8 @@ static void khci_resume(struct khci_usbdev_s *priv) CLASS_RESUME(priv->driver, &priv->usbdev); } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); + sched_unlock(); } /**************************************************************************** @@ -3261,7 +3265,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->usbdev.lock); epset &= priv->epavail; if (epset) { @@ -3286,7 +3290,7 @@ khci_epreserve(struct khci_usbdev_s *priv, uint8_t epset) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return privep; } @@ -3297,9 +3301,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->usbdev.lock); priv->epavail |= KHCI_ENDP_BIT(USB_EPNO(privep->ep.eplog)); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -3528,7 +3532,7 @@ static int khci_epdisable(struct usbdev_ep_s *ep) /* Cancel any ongoing activity */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); khci_cancelrequests(privep, -ESHUTDOWN); /* Disable the endpoint */ @@ -3545,7 +3549,7 @@ static int khci_epdisable(struct usbdev_ep_s *ep) *ptr++ = 0; } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -3644,7 +3648,7 @@ 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(&privep->ep.lock); /* Add the new request to the request queue for the OUT endpoint */ @@ -3688,7 +3692,7 @@ static int khci_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return ret; } @@ -3711,9 +3715,9 @@ 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->ep.lock); khci_cancelrequests(privep, -EAGAIN); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -3920,7 +3924,7 @@ 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->ep.lock); /* Special case EP0. When we stall EP0 we have to stall both the IN and * OUT BDTs. @@ -3949,7 +3953,7 @@ 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->ep.lock, flags); return ret; } @@ -4594,7 +4598,7 @@ void arm_usbuninitialize(void) /* Disconnect the device */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); khci_swreset(priv); @@ -4618,7 +4622,7 @@ void arm_usbuninitialize(void) regval &= ~SIM_SCGC4_USBOTG; putreg32(regval, KINETIS_SIM_SCGC4); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -4719,7 +4723,7 @@ 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->usbdev.lock); khci_swreset(priv); kinetis_usbpullup(&priv->usbdev, false); khci_hwreset(priv); @@ -4740,7 +4744,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) khci_hwshutdown(priv); khci_swinitialize(priv); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return OK; } #endif /* CONFIG_USBDEV */ diff --git a/arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c b/arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c index fa433c4acb608..6e64cf64dcca8 100644 --- a/arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c +++ b/arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,7 @@ #include #include +#include #include #include "arm_internal.h" @@ -513,6 +515,8 @@ static struct lpc17_40_dmadesc_s g_usbddesc[CONFIG_LPC17_40_USBDEV_NDMADESCRIPTORS]; #endif +static spinlock_t g_irq_lock = SP_UNLOCKED; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -660,7 +664,7 @@ static uint32_t lpc17_40_usbcmd(uint16_t cmd, uint8_t data) /* Disable interrupt and clear CDFULL and CCEMPTY interrupt status */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_irq_lock); lpc17_40_putreg(USBDEV_INT_CDFULL | USBDEV_INT_CCEMPTY, LPC17_40_USBDEV_INTCLR); @@ -799,7 +803,7 @@ static uint32_t lpc17_40_usbcmd(uint16_t cmd, uint8_t data) /* Restore the interrupt flags */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_irq_lock, flags); return tmp; } @@ -1037,18 +1041,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 +1077,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->ep.lock); + + lpc17_40_reqcomplete_nolock(privep, result); + + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: lpc17_40_wrrequest * @@ -1084,7 +1095,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 +1130,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; } @@ -1187,6 +1198,20 @@ static int lpc17_40_wrrequest(struct lpc17_40_ep_s *privep) return OK; } +static int lpc17_40_wrrequest(struct lpc17_40_ep_s *privep) +{ + int ret; + + irqstate_t flags = spin_lock_irqsave(&privep->ep.lock); + sched_lock(); + ret = lpc17_40_wrrequest_nolock(privep); + spin_unlock_irqrestore(&privep->ep.lock, flags); + sched_unlock(); + + return ret; +} + + /**************************************************************************** * Name: lpc17_40_rdrequest * @@ -1263,7 +1288,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 +2752,7 @@ static int lpc17_40_epdisable(struct usbdev_ep_s *ep) /* Cancel any ongoing activity */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); lpc17_40_cancelrequests(privep); /* Disable endpoint and interrupt */ @@ -2742,7 +2767,7 @@ 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->ep.lock, flags); return OK; } @@ -2931,7 +2956,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(&privep->ep.lock); + sched_lock(); /* If we are stalled, then drop all requests on the floor */ @@ -2977,7 +3003,8 @@ static int lpc17_40_epsubmit(struct usbdev_ep_s *ep, } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); + sched_unlock(); return ret; } @@ -3005,9 +3032,9 @@ static int lpc17_40_epcancel(struct usbdev_ep_s *ep, usbtrace(TRACE_EPCANCEL, privep->epphy); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); lpc17_40_cancelrequests(privep); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -3026,7 +3053,8 @@ 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->ep.lock); + sched_lock(); usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, privep->epphy); lpc17_40_usbcmd(CMD_USBDEV_EPSETSTATUS | privep->epphy, (resume ? 0 : CMD_SETSTAUS_ST)); @@ -3035,10 +3063,11 @@ static int lpc17_40_epstall(struct usbdev_ep_s *ep, bool resume) if (resume) { - lpc17_40_wrrequest(privep); + lpc17_40_wrrequest_nolock(privep); } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); + sched_unlock(); return OK; } @@ -3145,7 +3174,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->usbdev.lock); epset &= priv->epavail; if (epset) { @@ -3161,7 +3190,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->usbdev.lock, flags); /* And return the pointer to the standard endpoint * structure @@ -3174,7 +3203,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->usbdev.lock, flags); } usbtrace(TRACE_DEVERROR(LPC17_40_TRACEERR_NOEP), (uint16_t)eplog); @@ -3202,9 +3231,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->usbdev.lock); priv->epavail |= (3 << (privep->epphy & ~1)); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } } @@ -3248,14 +3277,14 @@ static int lpc17_40_wakeup(struct usbdev_s *dev) usbtrace(TRACE_DEVWAKEUP, (uint16_t)g_usbdev.devstatus); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_usbdev.usbdev.lock); if (DEVSTATUS_CONNECT(g_usbdev.devstatus)) { arg |= CMD_STATUS_CONNECT; } lpc17_40_usbcmd(CMD_USBDEV_SETSTATUS, arg); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_usbdev.usbdev.lock, flags); return OK; } @@ -3333,7 +3362,7 @@ void arm_usbinitialize(void) /* Step 1: Enable power by setting PCUSB in the PCONP register */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); regval = lpc17_40_getreg(LPC17_40_SYSCON_PCONP); regval |= SYSCON_PCONP_PCUSB; lpc17_40_putreg(regval, LPC17_40_SYSCON_PCONP); @@ -3374,7 +3403,7 @@ 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->usbdev.lock, flags); /* Initialize the device state structure */ @@ -3460,11 +3489,11 @@ void arm_usbinitialize(void) * driver */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.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->usbdev.lock, flags); /* Disconnect device */ @@ -3508,7 +3537,7 @@ void arm_usbuninitialize(void) /* Disconnect device */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); lpc17_40_pullup(&priv->usbdev, false); priv->usbdev.speed = USB_SPEED_UNKNOWN; lpc17_40_usbcmd(CMD_USBDEV_CONFIG, 0); @@ -3523,7 +3552,7 @@ 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->usbdev.lock, flags); } /**************************************************************************** diff --git a/arch/arm/src/lpc214x/lpc214x_usbdev.c b/arch/arm/src/lpc214x/lpc214x_usbdev.c index 1496d563cef05..c03a6c33a75e4 100644 --- a/arch/arm/src/lpc214x/lpc214x_usbdev.c +++ b/arch/arm/src/lpc214x/lpc214x_usbdev.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,7 @@ #include #include +#include #include #include "chip.h" @@ -495,6 +497,8 @@ static const struct usbdev_ops_s g_devops = .pullup = lpc214x_pullup, }; +static spinlock_t g_irq_lock = SP_UNLOCKED; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -602,7 +606,7 @@ static uint32_t lpc214x_usbcmd(uint16_t cmd, uint8_t data) /* Disable interrupt and clear CDFULL and CCEMPTY interrupt status */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_irq_lock); lpc214x_putreg(USBDEV_DEVINT_CDFULL | USBDEV_DEVINT_CCEMTY, LPC214X_USBDEV_DEVINTCLR); @@ -736,7 +740,7 @@ static uint32_t lpc214x_usbcmd(uint16_t cmd, uint8_t data) /* Restore the interrupt flags */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_irq_lock, flags); return tmp; } @@ -975,7 +979,7 @@ 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; @@ -983,9 +987,7 @@ static void lpc214x_reqcomplete(struct lpc214x_ep_s *privep, int16_t result) /* 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 +1015,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->ep.lock); + + lpc214x_reqcomplete_nolock(privep, result); + + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: lpc214x_wrrequest * @@ -1021,7 +1032,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 +1067,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; } @@ -1124,6 +1135,18 @@ static int lpc214x_wrrequest(struct lpc214x_ep_s *privep) return OK; } +static int lpc214x_wrrequest_nolock(struct lpc214x_ep_s *privep) +{ + int ret; + + irqstate_t flags = spin_lock_irqsave(&privep->ep.lock); + int ret = lpc214x_wrrequest_nolock(privep); + spin_unlock_irqrestore(&privep->ep.lock, flags); + + return ret; +} + + /**************************************************************************** * Name: lpc214x_rdrequest * @@ -1194,16 +1217,23 @@ 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->ep.lock); + lpc214x_cancelrequests_nolock(privep); + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: lpc214x_epfindbyaddr * @@ -2687,8 +2717,8 @@ 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->ep.lock); + lpc214x_cancelrequests_nolock(privep); /* Disable endpoint and interrupt */ @@ -2702,7 +2732,7 @@ 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->ep.lock, flags); return OK; } @@ -2890,7 +2920,8 @@ static int lpc214x_epsubmit(struct usbdev_ep_s *ep, req->result = -EINPROGRESS; req->xfrd = 0; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); + sched_lock(); /* If we are stalled, then drop all requests on the floor */ @@ -2913,7 +2944,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 +2967,8 @@ static int lpc214x_epsubmit(struct usbdev_ep_s *ep, } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); + sched_unlock(); return ret; } @@ -2964,9 +2996,9 @@ 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->ep.lock); + lpc214x_cancelrequests_nolock(privep); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2985,7 +3017,8 @@ 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->ep.lock); + sched_lock(); usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, privep->epphy); lpc214x_usbcmd(CMD_USB_EP_SETSTATUS | privep->epphy, (resume ? 0 : USBDEV_EPSTALL)); @@ -2994,10 +3027,11 @@ static int lpc214x_epstall(struct usbdev_ep_s *ep, bool resume) if (resume) { - lpc214x_wrrequest(privep); + lpc214x_wrrequest_nolock(privep); } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); + sched_unlock(); return OK; } @@ -3103,7 +3137,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->usbdev.lock); epset &= priv->epavail; if (epset) { @@ -3119,7 +3153,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->usbdev.lock, flags); /* And return the pointer to the standard endpoint * structure @@ -3132,7 +3166,7 @@ static struct usbdev_ep_s *lcp214x_allocep(struct usbdev_s *dev, /* Shouldn't get here */ } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_NOEP), (uint16_t)eplog); @@ -3160,9 +3194,9 @@ static void lpc214x_freeep(struct usbdev_s *dev, { /* Mark the endpoint as available */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); priv->epavail |= (1 << privep->epphy); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } } @@ -3206,14 +3240,14 @@ static int lpc214x_wakeup(struct usbdev_s *dev) usbtrace(TRACE_DEVWAKEUP, (uint16_t)g_usbdev.devstatus); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_usbdev.usbdev.lock); if (DEVSTATUS_CONNECT(g_usbdev.devstatus)) { arg |= USBDEV_DEVSTATUS_CONNECT; } lpc214x_usbcmd(CMD_USB_DEV_SETSTATUS, arg); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_usbdev.usbdev.lock, flags); return OK; } @@ -3416,7 +3450,7 @@ void arm_usbuninitialize(void) /* Disconnect device */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); lpc214x_pullup(&priv->usbdev, false); priv->usbdev.speed = USB_SPEED_UNKNOWN; lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 0); @@ -3431,7 +3465,7 @@ 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->usbdev.lock, flags); } /**************************************************************************** diff --git a/arch/arm/src/lpc31xx/lpc31_usbdev.c b/arch/arm/src/lpc31xx/lpc31_usbdev.c index c65ea484c02b9..080aeb8474679 100644 --- a/arch/arm/src/lpc31xx/lpc31_usbdev.c +++ b/arch/arm/src/lpc31xx/lpc31_usbdev.c @@ -42,6 +42,7 @@ #include #include +#include #include #include "chip.h" @@ -2096,7 +2097,7 @@ static int lpc31_epdisable(struct usbdev_ep_s *ep) usbtrace(TRACE_EPDISABLE, privep->epphy); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); /* Disable Endpoint */ @@ -2113,7 +2114,7 @@ static int lpc31_epdisable(struct usbdev_ep_s *ep) lpc31_cancelrequests(privep, -ESHUTDOWN); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2262,7 +2263,7 @@ static int lpc31_epsubmit(struct usbdev_ep_s *ep, /* Disable Interrupts */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); /* If we are stalled, then drop all requests on the floor */ @@ -2285,7 +2286,7 @@ static int lpc31_epsubmit(struct usbdev_ep_s *ep, } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return ret; } @@ -2313,7 +2314,7 @@ static int lpc31_epcancel(struct usbdev_ep_s *ep, usbtrace(TRACE_EPCANCEL, privep->epphy); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); /* FIXME: if the request is the first, then we need to flush the EP * otherwise just remove it from the list @@ -2322,7 +2323,7 @@ static int lpc31_epcancel(struct usbdev_ep_s *ep, */ lpc31_cancelrequests(privep, -ESHUTDOWN); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2341,7 +2342,7 @@ 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->ep.lock); usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, privep->epphy); uint32_t addr = LPC31_USBDEV_ENDPTCTRL(privep->epphy); @@ -2365,7 +2366,7 @@ static int lpc31_epstall(struct usbdev_ep_s *ep, bool resume) lpc31_setbits (ctrl_xs, addr); } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -2472,7 +2473,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->usbdev.lock); epset &= priv->epavail; if (epset) { @@ -2488,7 +2489,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->usbdev.lock, flags); /* And return the pointer to the standard endpoint * structure @@ -2501,7 +2502,7 @@ static struct usbdev_ep_s *lpc31_allocep(struct usbdev_s *dev, /* Shouldn't get here */ } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } usbtrace(TRACE_DEVERROR(LPC31_TRACEERR_NOEP), (uint16_t)eplog); @@ -2529,9 +2530,9 @@ static void lpc31_freeep(struct usbdev_s *dev, { /* Mark the endpoint as available */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); priv->epavail |= (1 << privep->epphy); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } } @@ -2577,9 +2578,9 @@ static int lpc31_wakeup(struct usbdev_s *dev) usbtrace(TRACE_DEVWAKEUP, 0); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&dev->lock); lpc31_setbits(USBDEV_PRTSC1_FPR, LPC31_USBDEV_PORTSC1); - leave_critical_section(flags); + spin_unlock_irqrestore(&dev->lock, flags); return OK; } @@ -2617,16 +2618,24 @@ 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) +{ + irqstate_t flags = spin_lock_irqsave(&dev->lock); + + lpc31_pullup_nolock(dev, enable); + + spin_unlock_irqrestore(&dev->lock, flags); return OK; } @@ -2793,8 +2802,8 @@ void arm_usbuninitialize(void) /* Disconnect device */ - flags = enter_critical_section(); - lpc31_pullup(&priv->usbdev, false); + flags = spin_lock_irqsave(&priv->usbdev.lock); + lpc31_pullup_nolock(&priv->usbdev, false); priv->usbdev.speed = USB_SPEED_UNKNOWN; /* Disable and detach IRQs */ @@ -2813,7 +2822,7 @@ void arm_usbuninitialize(void) lpc31_disableclock (CLKID_USBOTGAHBCLK); lpc31_disableclock (CLKID_EVENTROUTERPCLK); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** diff --git a/arch/arm/src/rp2040/rp2040_usbdev.c b/arch/arm/src/rp2040/rp2040_usbdev.c index 32a1068bc7954..2e20236a48c97 100644 --- a/arch/arm/src/rp2040/rp2040_usbdev.c +++ b/arch/arm/src/rp2040/rp2040_usbdev.c @@ -584,7 +584,7 @@ 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; @@ -592,9 +592,7 @@ static void rp2040_reqcomplete(struct rp2040_ep_s *privep, int16_t result) /* 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 +620,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->ep.lock); + + rp2040_reqcomplete_nolock(privep, result); + + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: rp2040_txcomplete * @@ -856,16 +863,23 @@ 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->ep.lock); + rp2040_cancelrequests_nolock(privep); + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: rp2040_epfindbyaddr * @@ -1518,7 +1532,7 @@ 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->ep.lock); privep->ep.maxpacket = 64; privep->stalled = false; @@ -1527,9 +1541,9 @@ 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->ep.lock, flags); return OK; } @@ -1622,7 +1636,7 @@ static int rp2040_epsubmit(struct usbdev_ep_s *ep, req->result = -EINPROGRESS; req->xfrd = 0; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); if (privep->stalled && privep->in) { @@ -1667,7 +1681,7 @@ static int rp2040_epsubmit(struct usbdev_ep_s *ep, } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return ret; } @@ -1697,9 +1711,9 @@ 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->ep.lock); + rp2040_cancelrequests_nolock(privep); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } diff --git a/arch/arm/src/rp23xx/rp23xx_usbdev.c b/arch/arm/src/rp23xx/rp23xx_usbdev.c index 48fd0873256b8..5187ba084edeb 100644 --- a/arch/arm/src/rp23xx/rp23xx_usbdev.c +++ b/arch/arm/src/rp23xx/rp23xx_usbdev.c @@ -582,7 +582,7 @@ 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; @@ -590,9 +590,7 @@ static void rp23xx_reqcomplete(struct rp23xx_ep_s *privep, int16_t result) /* 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 +618,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->ep.lock); + rp23xx_reqcomplete_nolock(privep, result); + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: rp23xx_txcomplete * @@ -854,16 +859,23 @@ 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->ep.lock); + rp23xx_cancelrequests_nolock(privep); + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: rp23xx_epfindbyaddr * @@ -1519,7 +1531,7 @@ 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->ep.lock); privep->ep.maxpacket = 64; privep->stalled = false; @@ -1528,9 +1540,9 @@ 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->ep.lock, flags); return OK; } @@ -1623,7 +1635,7 @@ static int rp23xx_epsubmit(struct usbdev_ep_s *ep, req->result = -EINPROGRESS; req->xfrd = 0; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); if (privep->stalled && privep->in) { @@ -1668,7 +1680,7 @@ static int rp23xx_epsubmit(struct usbdev_ep_s *ep, } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return ret; } @@ -1698,9 +1710,9 @@ 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->ep.lock); + rp23xx_cancelrequests_nolock(privep); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } diff --git a/arch/arm/src/samv7/sam_usbdevhs.c b/arch/arm/src/samv7/sam_usbdevhs.c index 0f92a54598381..b765d792b9646 100644 --- a/arch/arm/src/samv7/sam_usbdevhs.c +++ b/arch/arm/src/samv7/sam_usbdevhs.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -58,6 +59,7 @@ #include #include +#include #include #include "arm_internal.h" @@ -1202,9 +1204,9 @@ static void sam_req_complete(struct sam_ep_s *privep, int16_t result) /* Remove the completed request at the head of the endpoint request list */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); privreq = sam_req_dequeue(&privep->reqq); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); if (privreq) { @@ -3531,7 +3533,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->usbdev.lock); epset &= priv->epavail; if (epset) { @@ -3556,7 +3558,7 @@ sam_ep_reserve(struct sam_usbdev_s *priv, uint16_t epset) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return privep; } @@ -3573,9 +3575,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->usbdev.lock); priv->epavail |= SAM_EP_BIT(USB_EPNO(privep->ep.eplog)); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -3898,14 +3900,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->usbdev.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->usbdev.lock, flags); return OK; } @@ -4021,7 +4023,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(&privep->ep.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 +4076,8 @@ static int sam_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); + sched_unlock(); return ret; } @@ -4091,9 +4095,9 @@ 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->ep.lock); sam_req_cancel(privep, -EAGAIN); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -4124,7 +4128,7 @@ 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(&privep->ep.lock); usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, USB_EPNO(ep->eplog)); /* Handle the resume condition */ @@ -4247,7 +4251,7 @@ static int sam_ep_stall(struct usbdev_ep_s *ep, bool resume) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -4391,7 +4395,7 @@ static int sam_wakeup(struct usbdev_s *dev) /* Resume normal operation */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); sam_resume(priv); /* Activate a remote wakeup. @@ -4404,7 +4408,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->usbdev.lock, flags); /* This bit is automatically cleared by hardware at the end of the Upstream * Resume @@ -4451,7 +4455,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->usbdev.lock); if (enable) { /* Un-freeze clocking. @@ -4603,7 +4607,7 @@ static int sam_pullup(struct usbdev_s *dev, bool enable) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return OK; } @@ -5054,7 +5058,7 @@ void arm_usbuninitialize(void) * easier. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); usbtrace(TRACE_DEVUNINIT, 0); /* Disable and detach the USBHS IRQ */ @@ -5072,7 +5076,7 @@ void arm_usbuninitialize(void) sam_hw_shutdown(priv); sam_sw_shutdown(priv); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -5149,7 +5153,7 @@ 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->usbdev.lock); /* Unbind the class driver */ @@ -5173,7 +5177,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) /* Unhook the driver */ priv->driver = NULL; - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return OK; } diff --git a/arch/arm/src/stm32/stm32_usbdev.c b/arch/arm/src/stm32/stm32_usbdev.c index 9cb27c1e62872..79ad20ac6df48 100644 --- a/arch/arm/src/stm32/stm32_usbdev.c +++ b/arch/arm/src/stm32/stm32_usbdev.c @@ -48,6 +48,7 @@ #include #include +#include #include "arm_internal.h" #include "stm32.h" @@ -1215,16 +1216,13 @@ 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 +1251,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->ep.lock); + + stm32_reqcomplete_nolock(privep, result); + + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: tm32_epwrite ****************************************************************************/ @@ -1540,7 +1547,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 +2752,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->usbdev.lock); epset &= priv->epavail; if (epset) { @@ -2770,7 +2777,7 @@ stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return privep; } @@ -2781,9 +2788,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->usbdev.lock); priv->epavail |= STM32_ENDP_BIT(USB_EPNO(privep->ep.eplog)); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -2806,7 +2813,7 @@ static int stm32_epallocpma(struct stm32_usbdev_s *priv) int bufno = ERROR; int bufndx; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); for (bufndx = 2; bufndx < STM32_NBUFFERS; bufndx++) { /* Check if this buffer is available */ @@ -2825,7 +2832,7 @@ static int stm32_epallocpma(struct stm32_usbdev_s *priv) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return bufno; } @@ -2836,9 +2843,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->usbdev.lock); priv->epavail |= STM32_ENDP_BIT(privep->bufno); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -2970,7 +2977,7 @@ static int stm32_epdisable(struct usbdev_ep_s *ep) /* Cancel any ongoing activity */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); stm32_cancelrequests(privep); /* Disable TX; disable RX */ @@ -2979,7 +2986,7 @@ 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->ep.lock, flags); return OK; } @@ -3072,7 +3079,7 @@ 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(&privep->ep.lock); /* If we are stalled, then drop all requests on the floor */ @@ -3145,7 +3152,7 @@ static int stm32_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return ret; } @@ -3167,9 +3174,9 @@ 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->ep.lock); stm32_cancelrequests(privep); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -3199,7 +3206,7 @@ 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->usbdev.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 +3231,7 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume) priv->ep0state = EP0STATE_STALLED; } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return -ENODEV; } @@ -3310,7 +3317,7 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return OK; } @@ -3474,7 +3481,7 @@ static int stm32_wakeup(struct usbdev_s *dev) * by the ESOF interrupt. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); stm32_initresume(priv); priv->rsmstate = RSMSTATE_STARTED; @@ -3486,7 +3493,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->usbdev.lock, flags); return OK; } @@ -3823,7 +3830,7 @@ void arm_usbuninitialize(void) struct stm32_usbdev_s *priv = &g_usbdev; irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); usbtrace(TRACE_DEVUNINIT, 0); /* Disable and detach the USB IRQs */ @@ -3842,7 +3849,7 @@ void arm_usbuninitialize(void) /* Put the hardware in an inactive state */ stm32_hwshutdown(priv); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -3951,7 +3958,7 @@ 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->usbdev.lock); stm32_reset(priv); /* Unbind the class driver */ @@ -3974,7 +3981,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) /* Unhook the driver */ priv->driver = NULL; - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return OK; } diff --git a/arch/arm/src/stm32f0l0g0/stm32_usbdev.c b/arch/arm/src/stm32f0l0g0/stm32_usbdev.c index 9c84c9371e39b..41da1d4c8b81f 100644 --- a/arch/arm/src/stm32f0l0g0/stm32_usbdev.c +++ b/arch/arm/src/stm32f0l0g0/stm32_usbdev.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -48,6 +49,7 @@ #include #include +#include #include "arm_internal.h" #include "hardware/stm32_rcc.h" @@ -479,6 +481,8 @@ static void stm32_hwreset(struct stm32_usbdev_s *priv); static void stm32_hwsetup(struct stm32_usbdev_s *priv); static void stm32_hwshutdown(struct stm32_usbdev_s *priv); +static int usbdev_unregister_nolock(struct usbdevclass_driver_s *driver); + /**************************************************************************** * Private Data ****************************************************************************/ @@ -1161,16 +1165,13 @@ 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 +1200,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->ep.lock); + + stm32_reqcomplete_nolock(privep, result); + + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: tm32_epwrite ****************************************************************************/ @@ -2669,7 +2679,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->usbdev.lock); epset &= priv->epavail; if (epset) { @@ -2694,7 +2704,7 @@ stm32_epreserve(struct stm32_usbdev_s *priv, uint8_t epset) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return privep; } @@ -2705,9 +2715,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->usbdev.lock); priv->epavail |= STM32_ENDP_BIT(USB_EPNO(privep->ep.eplog)); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -2730,7 +2740,7 @@ static int stm32_epallocpma(struct stm32_usbdev_s *priv) int bufno = ERROR; int bufndx; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); for (bufndx = 2; bufndx < STM32_NBUFFERS; bufndx++) { /* Check if this buffer is available */ @@ -2749,7 +2759,7 @@ static int stm32_epallocpma(struct stm32_usbdev_s *priv) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return bufno; } @@ -2760,9 +2770,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(&privep->ep.lock); priv->epavail |= STM32_ENDP_BIT(privep->bufno); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); } /**************************************************************************** @@ -2894,7 +2904,7 @@ static int stm32_epdisable(struct usbdev_ep_s *ep) /* Cancel any ongoing activity */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); stm32_cancelrequests(privep); /* Disable TX; disable RX */ @@ -2903,7 +2913,7 @@ 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->ep.lock, flags); return OK; } @@ -2997,7 +3007,7 @@ 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->usbdev.lock); /* If we are stalled, then drop all requests on the floor */ @@ -3072,7 +3082,7 @@ static int stm32_epsubmit(struct usbdev_ep_s *ep, } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return ret; } @@ -3095,9 +3105,9 @@ 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->ep.lock); stm32_cancelrequests(privep); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -3127,7 +3137,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->usbdev.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 +3163,7 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume) priv->ep0state = EP0STATE_STALLED; } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return -ENODEV; } @@ -3238,7 +3249,8 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); + sched_unlock(); return OK; } @@ -3403,7 +3415,7 @@ static int stm32_wakeup(struct usbdev_s *dev) * by the ESOF interrupt. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); stm32_initresume(priv); priv->rsmstate = RSMSTATE_STARTED; @@ -3415,7 +3427,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->usbdev.lock, flags); return OK; } @@ -3733,7 +3745,7 @@ void arm_usbuninitialize(void) struct stm32_usbdev_s *priv = &g_usbdev; irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); usbtrace(TRACE_DEVUNINIT, 0); /* Disable and detach the USB IRQs */ @@ -3744,13 +3756,13 @@ 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->usbdev.lock, flags); } /**************************************************************************** @@ -3835,7 +3847,7 @@ int usbdev_register(struct usbdevclass_driver_s *driver) * ****************************************************************************/ -int usbdev_unregister(struct usbdevclass_driver_s *driver) +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 @@ -3859,7 +3871,6 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) * canceled while the class driver is still bound. */ - flags = enter_critical_section(); stm32_reset(priv); /* Unbind the class driver */ @@ -3881,8 +3892,18 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) /* Unhook the driver */ priv->driver = NULL; - leave_critical_section(flags); return OK; } +int usbdev_unregister(struct usbdevclass_driver_s *driver) +{ + int ret; + + irqstate_t flags = spin_lock_irqsave(&priv->usbdev.lock); + ret = usbdev_unregister_nolock(driver); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); + + return ret; +} + #endif /* CONFIG_USBDEV && CONFIG_STM32F0L0G0_USB */ diff --git a/arch/arm/src/stm32l4/stm32l4_usbdev.c b/arch/arm/src/stm32l4/stm32l4_usbdev.c index 03776e2ba58ec..88de4a17bb741 100644 --- a/arch/arm/src/stm32l4/stm32l4_usbdev.c +++ b/arch/arm/src/stm32l4/stm32l4_usbdev.c @@ -43,6 +43,7 @@ #include #include +#include #include "arm_internal.h" #include "stm32l4.h" @@ -1215,16 +1216,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 +1252,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->ep.lock); + + stm32l4_reqcomplete_nolock(privep, result); + + spin_unlock_irqrestore(&privep->ep.lock, flags); +} + /**************************************************************************** * Name: tm32_epwrite ****************************************************************************/ @@ -1539,7 +1547,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 +2710,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->usbdev.lock); epset &= priv->epavail; if (epset) { @@ -2727,7 +2735,7 @@ stm32l4_epreserve(struct stm32l4_usbdev_s *priv, uint8_t epset) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return privep; } @@ -2739,9 +2747,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->usbdev.lock); priv->epavail |= STM32L4_ENDP_BIT(USB_EPNO(privep->ep.eplog)); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -2764,7 +2772,7 @@ static int stm32l4_epallocpma(struct stm32l4_usbdev_s *priv) int bufno = ERROR; int bufndx; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); for (bufndx = 2; bufndx < STM32L4_NBUFFERS; bufndx++) { /* Check if this buffer is available */ @@ -2783,7 +2791,7 @@ static int stm32l4_epallocpma(struct stm32l4_usbdev_s *priv) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return bufno; } @@ -2794,9 +2802,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->usbdev.lock); priv->epavail |= STM32L4_ENDP_BIT(privep->bufno); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -2928,7 +2936,7 @@ static int stm32l4_epdisable(struct usbdev_ep_s *ep) /* Cancel any ongoing activity */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->ep.lock); stm32l4_cancelrequests(privep); /* Disable TX; disable RX */ @@ -2937,7 +2945,7 @@ 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->ep.lock, flags); return OK; } @@ -3033,7 +3041,7 @@ 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->usbdev.lock); /* If we are stalled, then drop all requests on the floor */ @@ -3106,7 +3114,7 @@ static int stm32l4_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return ret; } @@ -3129,9 +3137,9 @@ 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->ep.lock); stm32l4_cancelrequests(privep); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->ep.lock, flags); return OK; } @@ -3161,7 +3169,7 @@ 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->usbdev.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 +3194,7 @@ static int stm32l4_epstall(struct usbdev_ep_s *ep, bool resume) priv->ep0state = EP0STATE_STALLED; } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return -ENODEV; } @@ -3272,7 +3280,7 @@ static int stm32l4_epstall(struct usbdev_ep_s *ep, bool resume) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return OK; } @@ -3438,7 +3446,7 @@ static int stm32l4_wakeup(struct usbdev_s *dev) * by the ESOF interrupt. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); stm32l4_initresume(priv); priv->rsmstate = RSMSTATE_STARTED; @@ -3450,7 +3458,7 @@ 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->usbdev.lock, flags); return OK; } @@ -3487,7 +3495,7 @@ static int stm32l4_pullup(struct usbdev_s *dev, bool enable) usbtrace(TRACE_DEVPULLUP, (uint16_t)enable); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&dev->lock); regval = stm32l4_getreg(STM32L4_USB_BCDR); if (enable) { @@ -3507,7 +3515,7 @@ static int stm32l4_pullup(struct usbdev_s *dev, bool enable) } stm32l4_putreg(regval, STM32L4_USB_BCDR); - leave_critical_section(flags); + spin_unlock_irqrestore(&dev->lock, flags); return OK; } @@ -3782,7 +3790,7 @@ void arm_usbuninitialize(void) struct stm32l4_usbdev_s *priv = &g_usbdev; irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->usbdev.lock); usbtrace(TRACE_DEVUNINIT, 0); /* Disable and detach the USB IRQ */ @@ -3804,7 +3812,7 @@ void arm_usbuninitialize(void) stm32l4_pwr_enableusv(false); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); } /**************************************************************************** @@ -3912,7 +3920,7 @@ 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->usbdev.lock); stm32l4_reset(priv); /* Unbind the class driver */ @@ -3934,7 +3942,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) /* Unhook the driver */ priv->driver = NULL; - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->usbdev.lock, flags); return OK; } diff --git a/include/nuttx/usb/usbdev.h b/include/nuttx/usb/usbdev.h index 132e24c432280..2fc4699603700 100644 --- a/include/nuttx/usb/usbdev.h +++ b/include/nuttx/usb/usbdev.h @@ -37,6 +37,7 @@ #include #include #include +#include /**************************************************************************** * Pre-processor Definitions @@ -323,6 +324,7 @@ struct usbdev_ep_s uint16_t maxpacket; /* Maximum packet size for this endpoint */ FAR void *priv; /* For use by class driver */ FAR void *fs; /* USB fs device this ep belongs */ + spinlock_t lock; /* Lock to protect the endpoint */ }; /* struct usbdev_s represents a usb device */ @@ -359,6 +361,7 @@ struct usbdev_s FAR struct usbdev_ep_s *ep0; /* Endpoint zero */ uint8_t speed; /* Current speed of the host connection */ uint8_t dualspeed:1; /* 1:supports high and full speed operation */ + spinlock_t lock; /* Lock to protect the device */ }; /* USB Device Class Implementations *****************************************/