From 04df2cceade7defa4b8defed1895bd7221e6cc2b Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 19 Mar 2025 15:51:15 +0200 Subject: [PATCH] arch/mpfs/mpfs_usb.c: Replace big kernel lock with spin lock Remove call to enter_critical_section (big kernel lock) and replace it with a smaller lock to protect the USB clock and its reference counter. Signed-off-by: Ville Juven --- arch/risc-v/src/mpfs/hardware/mpfs_usb.h | 6 ++ arch/risc-v/src/mpfs/mpfs_usb.c | 86 +++++++++++------------- 2 files changed, 44 insertions(+), 48 deletions(-) diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_usb.h b/arch/risc-v/src/mpfs/hardware/mpfs_usb.h index ad13318780e..bb375c85ef6 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_usb.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_usb.h @@ -409,6 +409,7 @@ union wb_u struct mpfs_rqhead_s { + spinlock_t qlock; /* Lock to protect access to the queue */ struct mpfs_req_s *head; /* Requests are added to the head of the list */ struct mpfs_req_s *tail; /* Requests are removed from the tail of the list */ }; @@ -417,6 +418,7 @@ struct mpfs_ep_s { struct usbdev_ep_s ep; /* Standard endpoint structure */ + spinlock_t eplock; /* Lock for endpoint access */ struct mpfs_usbdev_s *dev; /* Reference to private driver data */ struct mpfs_rqhead_s reqq; /* Read/write request queue */ struct mpfs_rqhead_s pendq; /* Write requests pending stall sent */ @@ -447,6 +449,10 @@ struct mpfs_usbdev_s struct usbdevclass_driver_s *driver; + /* Device specific fields */ + + spinlock_t lock; /* Device lock */ + /* USB-specific fields */ struct usb_ctrlreq_s ctrl; /* Last EP0 request */ diff --git a/arch/risc-v/src/mpfs/mpfs_usb.c b/arch/risc-v/src/mpfs/mpfs_usb.c index 58c487f4ea4..fc183784580 100644 --- a/arch/risc-v/src/mpfs/mpfs_usb.c +++ b/arch/risc-v/src/mpfs/mpfs_usb.c @@ -226,11 +226,12 @@ static void mpfs_epset_reset(struct mpfs_usbdev_s *priv, uint16_t epset); * Private Data ****************************************************************************/ -static spinlock_t g_mpfs_modifyreg_lock = SP_UNLOCKED; - static struct mpfs_usbdev_s g_usbd; -static uint8_t g_clkrefs; -static bool g_linkdead; + +static spinlock_t g_mpfs_modifyreg_lock = SP_UNLOCKED; +static spinlock_t g_clklock = SP_UNLOCKED; +static uint8_t g_clkrefs; +static bool g_linkdead; static const struct usbdev_epops_s g_epops = { @@ -438,7 +439,7 @@ static void mpfs_enableclk(void) { /* Handle the counter atomically */ - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&g_clklock); if (g_clkrefs == 0) { @@ -447,7 +448,7 @@ static void mpfs_enableclk(void) } g_clkrefs++; - leave_critical_section(flags); + spin_unlock_irqrestore(&g_clklock, flags); } /**************************************************************************** @@ -468,7 +469,7 @@ static void mpfs_disableclk(void) { /* Handle the counter atomically */ - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&g_clklock); g_clkrefs--; if (g_clkrefs == 0) @@ -477,7 +478,7 @@ static void mpfs_disableclk(void) 0); } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_clklock, flags); } /**************************************************************************** @@ -500,6 +501,7 @@ static void mpfs_disableclk(void) static struct mpfs_req_s *mpfs_req_dequeue(struct mpfs_rqhead_s *queue) { + irqstate_t flags = spin_lock_irqsave(&queue->qlock); struct mpfs_req_s *ret = queue->head; if (ret != NULL) @@ -513,6 +515,7 @@ static struct mpfs_req_s *mpfs_req_dequeue(struct mpfs_rqhead_s *queue) ret->flink = NULL; } + spin_unlock_irqrestore(&queue->qlock, flags); return ret; } @@ -534,6 +537,8 @@ static struct mpfs_req_s *mpfs_req_dequeue(struct mpfs_rqhead_s *queue) static void mpfs_req_enqueue(struct mpfs_rqhead_s *queue, struct mpfs_req_s *req) { + irqstate_t flags = spin_lock_irqsave(&queue->qlock); + req->flink = NULL; if (queue->head == NULL) @@ -546,6 +551,8 @@ static void mpfs_req_enqueue(struct mpfs_rqhead_s *queue, queue->tail->flink = req; queue->tail = req; } + + spin_unlock_irqrestore(&queue->qlock, flags); } /**************************************************************************** @@ -566,14 +573,10 @@ static void mpfs_req_enqueue(struct mpfs_rqhead_s *queue, static void mpfs_req_complete(struct mpfs_ep_s *privep, int16_t result) { struct mpfs_req_s *privreq; - irqstate_t flags; /* Remove the completed request at the head of the endpoint request list */ - flags = enter_critical_section(); privreq = mpfs_req_dequeue(&privep->reqq); - leave_critical_section(flags); - if (privreq) { /* Save the result in the request structure */ @@ -886,7 +889,7 @@ static int mpfs_ep_stall(struct mpfs_ep_s *privep) /* Check that endpoint is enabled and not already in Halt state */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->eplock); if ((privep->epstate != USB_EPSTATE_DISABLED) && (privep->epstate != USB_EPSTATE_STALLED)) { @@ -932,7 +935,7 @@ static int mpfs_ep_stall(struct mpfs_ep_s *privep) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->eplock, flags); return OK; } @@ -989,10 +992,6 @@ static int mpfs_req_write(struct mpfs_usbdev_s *priv, return -ENOENT; } - uinfo("epno=%d req=%p: len=%zu xfrd=%zu inflight=%d\n", - epno, privreq, privreq->req.len, privreq->req.xfrd, - privreq->inflight); - /* Handle any bytes in flight. */ privreq->req.xfrd += privreq->inflight; @@ -1168,9 +1167,6 @@ static int mpfs_req_read(struct mpfs_usbdev_s *priv, return OK; } - uinfo("EP%d: req.len=%zu xfrd=%zu recvsize=%d\n", - epno, privreq->req.len, privreq->req.xfrd, recvsize); - /* Ignore any attempt to receive a zero length packet */ if (privreq->req.len == 0) @@ -1619,8 +1615,6 @@ static void mpfs_ep_reset(struct mpfs_usbdev_s *priv, uint8_t epno) static void mpfs_setdevaddr(struct mpfs_usbdev_s *priv, uint8_t address) { - uinfo("ENTRY address=0x%x\n", address); - DEBUGASSERT(address <= 0x7f); mpfs_putreg8(address, MPFS_USB_FADDR); @@ -1662,14 +1656,14 @@ static int mpfs_ep_disable(struct usbdev_ep_s *ep) /* Reset the endpoint and cancel any ongoing activity */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->eplock); priv = privep->dev; mpfs_ep_reset(priv, epno); /* Revert to the addressed-but-not-configured state */ mpfs_setdevaddr(priv, priv->devaddr); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->eplock, flags); return OK; } @@ -1815,7 +1809,7 @@ static int mpfs_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req) req->xfrd = 0; privreq->inflight = 0; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->eplock); /* 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 @@ -1884,7 +1878,7 @@ static int mpfs_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->eplock, flags); return ret; } @@ -1907,13 +1901,9 @@ static int mpfs_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req) static int mpfs_ep_cancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req) { struct mpfs_ep_s *privep = (struct mpfs_ep_s *)ep; - irqstate_t flags; usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog)); - - flags = enter_critical_section(); mpfs_req_cancel(privep, -EAGAIN); - leave_critical_section(flags); return OK; } @@ -1945,7 +1935,7 @@ static int mpfs_ep_resume(struct mpfs_ep_s *privep) usbtrace(TRACE_EPRESUME, USB_EPNO(privep->ep.eplog)); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->eplock); /* Check if the endpoint is stalled */ @@ -2008,7 +1998,7 @@ static int mpfs_ep_resume(struct mpfs_ep_s *privep) } } - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->eplock, flags); return OK; } @@ -2052,7 +2042,7 @@ static int mpfs_ep_stallresume(struct usbdev_ep_s *ep, bool resume) * requests before sending the stall. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&privep->eplock); epno = USB_EPNO(ep->eplog); if (epno != 0 && USB_ISEPIN(ep->eplog)) { @@ -2068,7 +2058,7 @@ static int mpfs_ep_stallresume(struct usbdev_ep_s *ep, bool resume) */ privep->pending = true; - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->eplock, flags); return OK; } } @@ -2077,8 +2067,8 @@ static int mpfs_ep_stallresume(struct usbdev_ep_s *ep, bool resume) * Stall the endpoint now. */ + spin_unlock_irqrestore(&privep->eplock, flags); ret = mpfs_ep_stall(privep); - leave_critical_section(flags); } return ret; @@ -2111,7 +2101,7 @@ mpfs_ep_reserve(struct mpfs_usbdev_s *priv, uint16_t epset, bool in) irqstate_t flags; int epndx = 0; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->lock); epset &= priv->epavail; if (epset != 0) @@ -2159,7 +2149,7 @@ mpfs_ep_reserve(struct mpfs_usbdev_s *priv, uint16_t epset, bool in) DEBUGASSERT(privep != NULL); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->lock, flags); return privep; } @@ -2249,9 +2239,9 @@ static struct usbdev_ep_s *mpfs_allocep(struct usbdev_s *dev, uint8_t epno, static inline void mpfs_ep_unreserve(struct mpfs_usbdev_s *priv, struct mpfs_ep_s *privep) { - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->lock); priv->epavail |= MPFS_EP_BIT(USB_EPNO(privep->ep.eplog)); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** @@ -2383,13 +2373,13 @@ static int mpfs_wakeup(struct usbdev_s *dev) /* Resume normal operation */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->lock); mpfs_resume(priv); /* Device is always self-powered. Remote wakeup is not supported */ - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->lock, flags); return OK; } @@ -3977,15 +3967,15 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) struct mpfs_usbdev_s *priv = &g_usbd; irqstate_t flags; + /* Unbind the class driver */ + + CLASS_UNBIND(driver, &priv->usbdev); + /* Reset the hardware and cancel all requests. All requests must be * canceled while the class driver is still bound. */ - flags = enter_critical_section(); - - /* Unbind the class driver */ - - CLASS_UNBIND(driver, &priv->usbdev); + flags = spin_lock_irqsave(&priv->lock); mpfs_hw_shutdown(priv); mpfs_sw_shutdown(priv); @@ -3993,7 +3983,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) /* Unhook the driver */ priv->driver = NULL; - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->lock, flags); return OK; }