Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use small lock to protect usbdev and endpoint in mips. #15548

Merged
merged 1 commit into from
Jan 15, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 42 additions & 20 deletions arch/mips/src/pic32mx/pic32mx_usbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sched.h>

#include <nuttx/arch.h>
#include <nuttx/spinlock.h>
#include <nuttx/wdog.h>
#include <nuttx/kmalloc.h>
#include <nuttx/usb/usb.h>
Expand Down Expand Up @@ -407,6 +409,10 @@ struct pic32mx_usbdev_s
/* The endpoint list */

struct pic32mx_ep_s eplist[PIC32MX_NENDPOINTS];

/* Spinlock */

spinlock_t lock;
};

/****************************************************************************
Expand Down Expand Up @@ -797,9 +803,9 @@ static void pic32mx_reqcomplete(struct pic32mx_ep_s *privep, int16_t result)
* request list.
*/

flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
privreq = pic32mx_remfirst(&privep->active);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);

if (privreq)
{
Expand Down Expand Up @@ -3003,7 +3009,7 @@ static void pic32mx_resume(struct pic32mx_usbdev_s *priv)
irqstate_t flags;
uint16_t regval;

flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);

/* Start RESUME signaling */

Expand Down Expand Up @@ -3051,7 +3057,7 @@ static void pic32mx_resume(struct pic32mx_usbdev_s *priv)
CLASS_RESUME(priv->driver, &priv->usbdev);
}

leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}

/****************************************************************************
Expand All @@ -3069,7 +3075,7 @@ pic32mx_epreserve(struct pic32mx_usbdev_s *priv, uint8_t epset)
irqstate_t flags;
int epndx = 0;

flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
epset &= priv->epavail;
if (epset)
{
Expand All @@ -3094,7 +3100,7 @@ pic32mx_epreserve(struct pic32mx_usbdev_s *priv, uint8_t epset)
}
}

leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
return privep;
}

Expand All @@ -3106,9 +3112,9 @@ static inline void
pic32mx_epunreserve(struct pic32mx_usbdev_s *priv,
struct pic32mx_ep_s *privep)
{
irqstate_t flags = enter_critical_section();
irqstate_t flags = spin_lock_irqsave(&priv->lock);
priv->epavail |= PIC32MX_ENDP_BIT(USB_EPNO(privep->ep.eplog));
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
}

/****************************************************************************
Expand Down Expand Up @@ -3328,7 +3334,8 @@ static int pic32mx_epdisable(struct usbdev_ep_s *ep)

/* Cancel any ongoing activity */

flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
pic32mx_cancelrequests(privep, -ESHUTDOWN);

/* Disable the endpoint */
Expand All @@ -3345,7 +3352,8 @@ static int pic32mx_epdisable(struct usbdev_ep_s *ep)
*ptr++ = 0;
}

leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}

Expand Down Expand Up @@ -3445,7 +3453,8 @@ static int pic32mx_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
#ifndef CONFIG_USBDEV_NOWRITEAHEAD
privreq->inflight[1] = 0;
#endif
flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();

/* Add the new request to the request queue for the OUT endpoint */

Expand Down Expand Up @@ -3489,7 +3498,8 @@ static int pic32mx_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
}
}

leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return ret;
}

Expand All @@ -3512,9 +3522,11 @@ static int pic32mx_epcancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req)

usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog));

flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();
pic32mx_cancelrequests(privep, -EAGAIN);
leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return OK;
}

Expand Down Expand Up @@ -3705,7 +3717,8 @@ static int pic32mx_epstall(struct usbdev_ep_s *ep, bool resume)

/* STALL or RESUME the endpoint */

flags = enter_critical_section();
flags = spin_lock_irqsave(&privep->dev->lock);
sched_lock();

/* Special case EP0. When we stall EP0 we have to stall both the IN and
* OUT BDTs.
Expand Down Expand Up @@ -3734,7 +3747,8 @@ static int pic32mx_epstall(struct usbdev_ep_s *ep, bool resume)
ret = pic32mx_epbdtstall(ep, resume, USB_ISEPIN(ep->eplog));
}

leave_critical_section(flags);
spin_unlock_irqrestore(&privep->dev->lock, flags);
sched_unlock();
return ret;
}

Expand Down Expand Up @@ -4336,6 +4350,10 @@ void mips_usbinitialize(void)

usbtrace(TRACE_DEVINIT, 0);

/* Initialize driver lock */

spin_lock_init(&priv->lock);

/* Initialize the driver state structure */

pic32mx_stateinit(priv);
Expand Down Expand Up @@ -4383,7 +4401,8 @@ void mips_usbuninitialize(void)
struct pic32mx_usbdev_s *priv = &g_usbdev;
irqstate_t flags;

flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
usbtrace(TRACE_DEVUNINIT, 0);

/* Disable and detach the USB IRQs */
Expand All @@ -4400,7 +4419,8 @@ void mips_usbuninitialize(void)
/* Put the hardware in an inactive state */

pic32mx_hwshutdown(priv);
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
}

/****************************************************************************
Expand Down Expand Up @@ -4504,7 +4524,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
* the hardware back into its initial, unconnected state.
*/

flags = enter_critical_section();
flags = spin_lock_irqsave(&priv->lock);
sched_lock();
pic32mx_swreset(priv);
pic32mx_hwreset(priv);

Expand All @@ -4527,7 +4548,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
/* Unhook the driver */

priv->driver = NULL;
leave_critical_section(flags);
spin_unlock_irqrestore(&priv->lock, flags);
sched_unlock();
return OK;
}

Expand Down
Loading