Skip to content
Snippets Groups Projects
Commit 1ed69cd5 authored by Gregory Nutt's avatar Gregory Nutt
Browse files

Fix another corner case in the upper half CAN driver

parent d6cc75dc
No related branches found
No related tags found
No related merge requests found
......@@ -1044,6 +1044,12 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
* Returned Value:
* OK on success; a negated errno on failure.
*
* Assumptions:
* Interrupts are disabled. This is required by can_xmit() which is called
* by this function. Interrupts are explicitly disabled when called
* through can_write(). Interrupts are expected be disabled when called
* from the CAN interrupt handler.
*
****************************************************************************/
int can_txdone(FAR struct can_dev_s *dev)
......@@ -1143,6 +1149,10 @@ int can_txdone(FAR struct can_dev_s *dev)
* Returned Value:
* OK on success; a negated errno on failure.
*
* Assumptions:
* Interrupts are disabled. This is required by can_xmit() which is called
* by this function.
*
****************************************************************************/
#ifdef CONFIG_CAN_TXREADY
......@@ -1154,26 +1164,20 @@ int can_txready(FAR struct can_dev_s *dev)
dev->cd_xmit.tx_head, dev->cd_xmit.tx_queue, dev->cd_xmit.tx_tail,
dev->cd_ntxwaiters);
/* Are there any threads waiting for space in the xmit FIFO? */
/* Verify that the xmit FIFO is not empty. This is safe because interrupts
* are always disabled when calling into can_xmit(); this cannot collide
* with ongoing activity from can_write().
*/
if (dev->cd_ntxwaiters > 0)
if (dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail)
{
/* Verify that the xmit FIFO is not empty.
*
* REVISIT: This probably should be an assertion since we should only
* be waiting for space in the xmit FIFO if the xmit FIFO is full.
/* Send the next message in the S/W FIFO. In the case where the
* H/W TX FIFO is not empty, this should add one more CAN message
* to the H/W TX FIFO and can_txdone() should be called, making
* space in the S/W FIFO
*/
if (dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail)
{
/* Send the next message in the S/W FIFO. In the case where the
* H/W TX FIFO is not empty, this should add one more CAN message
* to the H/W TX FIFO and can_txdone() should be called, making
* space in the S/W FIFO
*/
(void)can_xmit(dev);
}
(void)can_xmit(dev);
/* Inform one waiter that new xmit space is available in the S/W FIFO.
* NOTE that is can_txdone() is, indeed, called twice that the tx_sem
......@@ -1181,7 +1185,12 @@ int can_txready(FAR struct can_dev_s *dev)
* harmful.
*/
ret = sem_post(&dev->cd_xmit.tx_sem);
/* Are there any threads waiting for space in the xmit FIFO? */
if (dev->cd_ntxwaiters > 0)
{
ret = sem_post(&dev->cd_xmit.tx_sem);
}
}
return ret;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment