mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 20:08:15 +08:00
drivers/usbdev/cdcacm.c: Use small lock to protect cdcacm
Use spin lock to replace enter_critical_section Signed-off-by: yangsong8 <yangsong8@xiaomi.com>
This commit is contained in:
+57
-43
@@ -106,6 +106,7 @@ struct cdcacm_dev_s
|
|||||||
#endif
|
#endif
|
||||||
bool rxenabled; /* true: UART RX "interrupts" enabled */
|
bool rxenabled; /* true: UART RX "interrupts" enabled */
|
||||||
bool ispolling;
|
bool ispolling;
|
||||||
|
spinlock_t lock;
|
||||||
|
|
||||||
struct cdc_linecoding_s linecoding; /* Buffered line status */
|
struct cdc_linecoding_s linecoding; /* Buffered line status */
|
||||||
cdcacm_callback_t callback; /* Serial event callback function */
|
cdcacm_callback_t callback; /* Serial event callback function */
|
||||||
@@ -360,6 +361,7 @@ static ssize_t cdcuart_sendbuf(FAR struct uart_dev_s *dev,
|
|||||||
FAR struct usbdev_ep_s *ep = priv->epbulkin;
|
FAR struct usbdev_ep_s *ep = priv->epbulkin;
|
||||||
FAR struct cdcacm_wrreq_s *wrcontainer;
|
FAR struct cdcacm_wrreq_s *wrcontainer;
|
||||||
FAR struct usbdev_req_s *req;
|
FAR struct usbdev_req_s *req;
|
||||||
|
irqstate_t flags;
|
||||||
size_t reqlen;
|
size_t reqlen;
|
||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -370,9 +372,11 @@ static ssize_t cdcuart_sendbuf(FAR struct uart_dev_s *dev,
|
|||||||
|
|
||||||
/* Peek at the request in the container at the head of the list */
|
/* Peek at the request in the container at the head of the list */
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
wrcontainer = (FAR struct cdcacm_wrreq_s *)sq_remfirst(&priv->txfree);
|
wrcontainer = (FAR struct cdcacm_wrreq_s *)sq_remfirst(&priv->txfree);
|
||||||
req = wrcontainer->req;
|
req = wrcontainer->req;
|
||||||
priv->nwrq--;
|
priv->nwrq--;
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* Fill the request with serial TX data */
|
/* Fill the request with serial TX data */
|
||||||
|
|
||||||
@@ -415,11 +419,10 @@ static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv)
|
|||||||
FAR struct uart_dev_s *dev = &priv->serdev;
|
FAR struct uart_dev_s *dev = &priv->serdev;
|
||||||
FAR struct cdcacm_wrreq_s *wrcontainer;
|
FAR struct cdcacm_wrreq_s *wrcontainer;
|
||||||
FAR struct usbdev_req_s *req;
|
FAR struct usbdev_req_s *req;
|
||||||
|
irqstate_t flags;
|
||||||
int ret;
|
int ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
irqstate_t flags;
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FEATURES
|
#ifdef CONFIG_DEBUG_FEATURES
|
||||||
if (priv == NULL)
|
if (priv == NULL)
|
||||||
{
|
{
|
||||||
@@ -428,7 +431,6 @@ static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
flags = enter_critical_section();
|
|
||||||
if (priv->ispolling)
|
if (priv->ispolling)
|
||||||
{
|
{
|
||||||
goto out;
|
goto out;
|
||||||
@@ -454,17 +456,22 @@ static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv)
|
|||||||
{
|
{
|
||||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_SUBMITFAIL),
|
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_SUBMITFAIL),
|
||||||
(uint16_t)-ret);
|
(uint16_t)-ret);
|
||||||
|
flags = spin_lock_irqsave_nopreempt(&priv->lock);
|
||||||
dev->xmit.head = 0;
|
dev->xmit.head = 0;
|
||||||
dev->xmit.tail = 0;
|
dev->xmit.tail = 0;
|
||||||
uart_datasent(dev);
|
uart_datasent(dev);
|
||||||
|
spin_unlock_irqrestore_nopreempt(&priv->lock, flags);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
priv->wrcontainer = NULL;
|
priv->wrcontainer = NULL;
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sq_empty(&priv->txfree))
|
if (!sq_empty(&priv->txfree))
|
||||||
{
|
{
|
||||||
|
flags = spin_lock_irqsave_nopreempt(&priv->lock);
|
||||||
priv->wrcontainer = (FAR struct cdcacm_wrreq_s *)
|
priv->wrcontainer = (FAR struct cdcacm_wrreq_s *)
|
||||||
sq_remfirst(&priv->txfree);
|
sq_remfirst(&priv->txfree);
|
||||||
dev->xmit.buffer = (FAR char *)priv->wrcontainer->req->buf;
|
dev->xmit.buffer = (FAR char *)priv->wrcontainer->req->buf;
|
||||||
@@ -472,6 +479,7 @@ static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv)
|
|||||||
dev->xmit.head = 0;
|
dev->xmit.head = 0;
|
||||||
dev->xmit.tail = 0;
|
dev->xmit.tail = 0;
|
||||||
uart_datasent(dev);
|
uart_datasent(dev);
|
||||||
|
spin_unlock_irqrestore_nopreempt(&priv->lock, flags);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (!sq_empty(&priv->txfree))
|
if (!sq_empty(&priv->txfree))
|
||||||
@@ -481,7 +489,6 @@ static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
out:
|
out:
|
||||||
leave_critical_section(flags);
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +620,7 @@ static int cdcacm_release_rxpending(FAR struct cdcacm_dev_s *priv)
|
|||||||
* must be disabled throughout the following.
|
* must be disabled throughout the following.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave_nopreempt(&priv->lock);
|
||||||
|
|
||||||
if (priv->ispolling)
|
if (priv->ispolling)
|
||||||
{
|
{
|
||||||
@@ -674,7 +681,7 @@ static int cdcacm_release_rxpending(FAR struct cdcacm_dev_s *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore_nopreempt(&priv->lock, flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -739,24 +746,26 @@ static int cdcacm_serialstate(FAR struct cdcacm_dev_s *priv)
|
|||||||
|
|
||||||
usbtrace(CDCACM_CLASSAPI_FLOWCONTROL, (uint16_t)priv->serialstate);
|
usbtrace(CDCACM_CLASSAPI_FLOWCONTROL, (uint16_t)priv->serialstate);
|
||||||
|
|
||||||
flags = enter_critical_section();
|
|
||||||
|
|
||||||
/* Use our interrupt IN endpoint for the transfer */
|
/* Use our interrupt IN endpoint for the transfer */
|
||||||
|
|
||||||
ep = priv->epintin;
|
ep = priv->epintin;
|
||||||
|
|
||||||
/* Remove the next container from the request list */
|
/* Remove the next container from the request list */
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
|
|
||||||
wrcontainer = (FAR struct cdcacm_wrreq_s *)sq_remfirst(&priv->txfree);
|
wrcontainer = (FAR struct cdcacm_wrreq_s *)sq_remfirst(&priv->txfree);
|
||||||
if (wrcontainer == NULL)
|
if (wrcontainer == NULL)
|
||||||
{
|
{
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
goto errout_with_flags;
|
goto errout_with_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decrement the count of write requests */
|
/* Decrement the count of write requests */
|
||||||
|
|
||||||
priv->nwrq--;
|
priv->nwrq--;
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* Format the SerialState notification */
|
/* Format the SerialState notification */
|
||||||
|
|
||||||
@@ -796,7 +805,6 @@ errout_with_flags:
|
|||||||
|
|
||||||
priv->serialstate &= CDC_UART_CONSISTENT;
|
priv->serialstate &= CDC_UART_CONSISTENT;
|
||||||
|
|
||||||
leave_critical_section(flags);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1049,7 +1057,6 @@ static void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep,
|
|||||||
|
|
||||||
/* Process the received data unless this is some unusual condition */
|
/* Process the received data unless this is some unusual condition */
|
||||||
|
|
||||||
flags = enter_critical_section();
|
|
||||||
switch (req->result)
|
switch (req->result)
|
||||||
{
|
{
|
||||||
case 0: /* Normal completion */
|
case 0: /* Normal completion */
|
||||||
@@ -1058,8 +1065,10 @@ static void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep,
|
|||||||
|
|
||||||
/* Place the incoming packet at the end of pending RX packet list. */
|
/* Place the incoming packet at the end of pending RX packet list. */
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
rdcontainer->offset = 0;
|
rdcontainer->offset = 0;
|
||||||
sq_addlast((FAR sq_entry_t *)rdcontainer, &priv->rxpending);
|
sq_addlast((FAR sq_entry_t *)rdcontainer, &priv->rxpending);
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* Then process all pending RX packet starting at the head of the
|
/* Then process all pending RX packet starting at the head of the
|
||||||
* list
|
* list
|
||||||
@@ -1072,10 +1081,13 @@ static void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep,
|
|||||||
case -ESHUTDOWN: /* Disconnection */
|
case -ESHUTDOWN: /* Disconnection */
|
||||||
{
|
{
|
||||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSHUTDOWN), 0);
|
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSHUTDOWN), 0);
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
if (priv->nrdq != 0)
|
if (priv->nrdq != 0)
|
||||||
{
|
{
|
||||||
priv->nrdq--;
|
priv->nrdq--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1087,8 +1099,6 @@ static void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -1124,10 +1134,10 @@ static void cdcacm_wrcomplete(FAR struct usbdev_ep_s *ep,
|
|||||||
|
|
||||||
/* Return the write request to the free list */
|
/* Return the write request to the free list */
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
sq_addlast((FAR sq_entry_t *)wrcontainer, &priv->txfree);
|
sq_addlast((FAR sq_entry_t *)wrcontainer, &priv->txfree);
|
||||||
priv->nwrq++;
|
priv->nwrq++;
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* Send the next packet unless this was some unusual termination
|
/* Send the next packet unless this was some unusual termination
|
||||||
* condition
|
* condition
|
||||||
@@ -1369,18 +1379,20 @@ static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
|
|||||||
wrcontainer->req->priv = wrcontainer;
|
wrcontainer->req->priv = wrcontainer;
|
||||||
wrcontainer->req->callback = cdcacm_wrcomplete;
|
wrcontainer->req->callback = cdcacm_wrcomplete;
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
sq_addlast((FAR sq_entry_t *)wrcontainer, &priv->txfree);
|
sq_addlast((FAR sq_entry_t *)wrcontainer, &priv->txfree);
|
||||||
priv->nwrq++; /* Count of write requests available */
|
priv->nwrq++; /* Count of write requests available */
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CDCACM_DISABLE_TXBUF
|
#ifdef CONFIG_CDCACM_DISABLE_TXBUF
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
priv->wrcontainer = (FAR struct cdcacm_wrreq_s *)
|
priv->wrcontainer = (FAR struct cdcacm_wrreq_s *)
|
||||||
sq_remfirst(&priv->txfree);
|
sq_remfirst(&priv->txfree);
|
||||||
priv->serdev.xmit.buffer = (FAR char *)priv->wrcontainer->req->buf;
|
priv->serdev.xmit.buffer = (FAR char *)priv->wrcontainer->req->buf;
|
||||||
priv->serdev.xmit.size = reqlen + 1;
|
priv->serdev.xmit.size = reqlen + 1;
|
||||||
priv->nwrq--;
|
priv->nwrq--;
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Report if we are selfpowered (unless we are part of a
|
/* Report if we are selfpowered (unless we are part of a
|
||||||
@@ -1484,7 +1496,7 @@ static void cdcacm_unbind(FAR struct usbdevclass_driver_s *driver,
|
|||||||
* of them)
|
* of them)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
|
|
||||||
#ifdef CONFIG_CDCACM_DISABLE_TXBUF
|
#ifdef CONFIG_CDCACM_DISABLE_TXBUF
|
||||||
DEBUGASSERT(priv->nwrq >= CONFIG_CDCACM_NWRREQS - 1);
|
DEBUGASSERT(priv->nwrq >= CONFIG_CDCACM_NWRREQS - 1);
|
||||||
@@ -1503,7 +1515,7 @@ static void cdcacm_unbind(FAR struct usbdevclass_driver_s *driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEBUGASSERT(priv->nwrq == 0);
|
DEBUGASSERT(priv->nwrq == 0);
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
#ifdef CONFIG_CDCACM_HAVE_EPINTIN
|
#ifdef CONFIG_CDCACM_HAVE_EPINTIN
|
||||||
/* Free the interrupt IN endpoint */
|
/* Free the interrupt IN endpoint */
|
||||||
@@ -1982,7 +1994,6 @@ static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
|
|||||||
* connection.
|
* connection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
|
||||||
#ifdef CONFIG_SERIAL_REMOVABLE
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
uart_connected(&priv->serdev, false);
|
uart_connected(&priv->serdev, false);
|
||||||
#endif
|
#endif
|
||||||
@@ -1993,9 +2004,10 @@ static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
|
|||||||
|
|
||||||
/* Clear out all outgoing data in the circular buffer */
|
/* Clear out all outgoing data in the circular buffer */
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
priv->serdev.xmit.head = 0;
|
priv->serdev.xmit.head = 0;
|
||||||
priv->serdev.xmit.tail = 0;
|
priv->serdev.xmit.tail = 0;
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* Perform the soft connect function so that we will we can be
|
/* Perform the soft connect function so that we will we can be
|
||||||
* re-enumerated (unless we are part of a composite device)
|
* re-enumerated (unless we are part of a composite device)
|
||||||
@@ -2205,7 +2217,7 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
FAR sq_entry_t *entry;
|
FAR sq_entry_t *entry;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
irqstate_t flags = enter_critical_section();
|
irqstate_t flags = spin_lock_irqsave(&priv->lock);
|
||||||
|
|
||||||
/* Determine the number of bytes available in the RX buffer */
|
/* Determine the number of bytes available in the RX buffer */
|
||||||
|
|
||||||
@@ -2217,7 +2229,7 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
count += rdcontainer->req->xfrd;
|
count += rdcontainer->req->xfrd;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
*(FAR int *)((uintptr_t)arg) = count;
|
*(FAR int *)((uintptr_t)arg) = count;
|
||||||
}
|
}
|
||||||
@@ -2236,7 +2248,7 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
int count;
|
int count;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
irqstate_t flags = enter_critical_section();
|
irqstate_t flags = spin_lock_irqsave(&priv->lock);
|
||||||
|
|
||||||
/* Determine the number of bytes waiting in the TX buffer */
|
/* Determine the number of bytes waiting in the TX buffer */
|
||||||
|
|
||||||
@@ -2261,7 +2273,7 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
*(FAR int *)((uintptr_t)arg) = count;
|
*(FAR int *)((uintptr_t)arg) = count;
|
||||||
}
|
}
|
||||||
@@ -2274,7 +2286,7 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
FAR sq_entry_t *entry;
|
FAR sq_entry_t *entry;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
irqstate_t flags = enter_critical_section();
|
irqstate_t flags = spin_lock_irqsave(&priv->lock);
|
||||||
|
|
||||||
/* Determine the number of bytes free in the TX buffer */
|
/* Determine the number of bytes free in the TX buffer */
|
||||||
|
|
||||||
@@ -2288,7 +2300,7 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
count += serdev->xmit.size - 1;
|
count += serdev->xmit.size - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
*(FAR int *)((uintptr_t)arg) = count;
|
*(FAR int *)((uintptr_t)arg) = count;
|
||||||
}
|
}
|
||||||
@@ -2307,7 +2319,7 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
FAR struct cdcacm_rdreq_s *rdcontainer;
|
FAR struct cdcacm_rdreq_s *rdcontainer;
|
||||||
ret = OK;
|
ret = OK;
|
||||||
|
|
||||||
irqstate_t flags = enter_critical_section();
|
irqstate_t flags = spin_lock_irqsave(&priv->lock);
|
||||||
|
|
||||||
if (priv->rdcontainer)
|
if (priv->rdcontainer)
|
||||||
{
|
{
|
||||||
@@ -2326,19 +2338,20 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
serdev->recv.head = 0;
|
serdev->recv.head = 0;
|
||||||
serdev->recv.tail = 0;
|
serdev->recv.tail = 0;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
/* De-activate RX flow control. */
|
/* De-activate RX flow control. */
|
||||||
|
|
||||||
uart_rxflowcontrol(serdev, 0, false);
|
uart_rxflowcontrol(serdev, 0, false);
|
||||||
#endif
|
#endif
|
||||||
leave_critical_section(flags);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_CDCACM_DISABLE_TXBUF
|
#ifdef CONFIG_CDCACM_DISABLE_TXBUF
|
||||||
if (arg == TCOFLUSH || arg == TCIOFLUSH)
|
if (arg == TCOFLUSH || arg == TCIOFLUSH)
|
||||||
{
|
{
|
||||||
irqstate_t flags = enter_critical_section();
|
irqstate_t flags = spin_lock_irqsave_nopreempt(&priv->lock);
|
||||||
ret = OK;
|
ret = OK;
|
||||||
|
|
||||||
if (priv->wrcontainer)
|
if (priv->wrcontainer)
|
||||||
@@ -2367,7 +2380,7 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore_nopreempt(&priv->lock, flags);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -2635,13 +2648,13 @@ static void cdcuart_rxint(FAR struct uart_dev_s *dev, bool enable)
|
|||||||
* in the following.
|
* in the following.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
|
||||||
if (enable)
|
if (enable)
|
||||||
{
|
{
|
||||||
/* RX "interrupts" are enabled. Is this a transition from disabled
|
/* RX "interrupts" are enabled. Is this a transition from disabled
|
||||||
* to enabled state?
|
* to enabled state?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
if (!priv->rxenabled)
|
if (!priv->rxenabled)
|
||||||
{
|
{
|
||||||
/* Yes.. RX "interrupts are no longer disabled */
|
/* Yes.. RX "interrupts are no longer disabled */
|
||||||
@@ -2649,6 +2662,8 @@ static void cdcuart_rxint(FAR struct uart_dev_s *dev, bool enable)
|
|||||||
priv->rxenabled = true;
|
priv->rxenabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* During the time that RX interrupts was disabled, incoming
|
/* During the time that RX interrupts was disabled, incoming
|
||||||
* packets were queued in priv->rxpending. We must now process
|
* packets were queued in priv->rxpending. We must now process
|
||||||
* all of them (unless flow control is enabled)
|
* all of them (unless flow control is enabled)
|
||||||
@@ -2666,10 +2681,10 @@ static void cdcuart_rxint(FAR struct uart_dev_s *dev, bool enable)
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
priv->rxenabled = false;
|
priv->rxenabled = false;
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -2897,11 +2912,11 @@ static bool cdcuart_txempty(FAR struct uart_dev_s *dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
|
|
||||||
if (dev->disconnected)
|
if (dev->disconnected)
|
||||||
{
|
{
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2913,6 +2928,8 @@ static bool cdcuart_txempty(FAR struct uart_dev_s *dev)
|
|||||||
* txfree, then there is no longer any TX data in flight.
|
* txfree, then there is no longer any TX data in flight.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
|
|
||||||
#ifdef CONFIG_CDCACM_DISABLE_TXBUF
|
#ifdef CONFIG_CDCACM_DISABLE_TXBUF
|
||||||
/* dev->xmit.buffer always take one req, so just compare
|
/* dev->xmit.buffer always take one req, so just compare
|
||||||
* CONFIG_CDCACM_NWRREQS - 1.
|
* CONFIG_CDCACM_NWRREQS - 1.
|
||||||
@@ -2922,7 +2939,7 @@ static bool cdcuart_txempty(FAR struct uart_dev_s *dev)
|
|||||||
#else
|
#else
|
||||||
empty = priv->nwrq >= CONFIG_CDCACM_NWRREQS;
|
empty = priv->nwrq >= CONFIG_CDCACM_NWRREQS;
|
||||||
#endif
|
#endif
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
@@ -2966,6 +2983,7 @@ static void cdcuart_dmasend(FAR struct uart_dev_s *dev)
|
|||||||
FAR struct usbdev_ep_s *ep = priv->epbulkin;
|
FAR struct usbdev_ep_s *ep = priv->epbulkin;
|
||||||
FAR struct cdcacm_wrreq_s *wrcontainer;
|
FAR struct cdcacm_wrreq_s *wrcontainer;
|
||||||
FAR struct usbdev_req_s *req;
|
FAR struct usbdev_req_s *req;
|
||||||
|
irqstate_t flags;
|
||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
size_t reqlen;
|
size_t reqlen;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -2976,9 +2994,11 @@ static void cdcuart_dmasend(FAR struct uart_dev_s *dev)
|
|||||||
|
|
||||||
/* Peek at the request in the container at the head of the list */
|
/* Peek at the request in the container at the head of the list */
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&priv->lock);
|
||||||
wrcontainer = (FAR struct cdcacm_wrreq_s *)sq_remfirst(&priv->txfree);
|
wrcontainer = (FAR struct cdcacm_wrreq_s *)sq_remfirst(&priv->txfree);
|
||||||
req = wrcontainer->req;
|
req = wrcontainer->req;
|
||||||
priv->nwrq--;
|
priv->nwrq--;
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* Fill the request with serial TX data */
|
/* Fill the request with serial TX data */
|
||||||
|
|
||||||
@@ -3145,15 +3165,11 @@ ssize_t cdcacm_write(FAR const char *buffer, size_t buflen)
|
|||||||
|
|
||||||
while (len < buflen)
|
while (len < buflen)
|
||||||
{
|
{
|
||||||
irqstate_t flags;
|
|
||||||
|
|
||||||
if (!priv || !(priv->ctrlline & CDC_DTE_PRESENT))
|
if (!priv || !(priv->ctrlline & CDC_DTE_PRESENT))
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = enter_critical_section();
|
|
||||||
|
|
||||||
if (cdcuart_txready(&priv->serdev))
|
if (cdcuart_txready(&priv->serdev))
|
||||||
{
|
{
|
||||||
ssize_t ret = cdcuart_sendbuf(&priv->serdev,
|
ssize_t ret = cdcuart_sendbuf(&priv->serdev,
|
||||||
@@ -3161,14 +3177,11 @@ ssize_t cdcacm_write(FAR const char *buffer, size_t buflen)
|
|||||||
buflen - len);
|
buflen - len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
leave_critical_section(flags);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
len += ret;
|
len += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return buflen;
|
return buflen;
|
||||||
@@ -3241,6 +3254,7 @@ int cdcacm_classobject(int minor, FAR struct usbdev_devinfo_s *devinfo,
|
|||||||
memset(priv, 0, sizeof(struct cdcacm_dev_s));
|
memset(priv, 0, sizeof(struct cdcacm_dev_s));
|
||||||
sq_init(&priv->txfree);
|
sq_init(&priv->txfree);
|
||||||
sq_init(&priv->rxpending);
|
sq_init(&priv->rxpending);
|
||||||
|
spin_lock_init(&priv->lock);
|
||||||
|
|
||||||
priv->minor = minor;
|
priv->minor = minor;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user