Fix another corner case in the upper half CAN driver

This commit is contained in:
Gregory Nutt 2015-11-10 07:41:40 -06:00
parent d6cc75dc64
commit 1ed69cd535
1 changed files with 26 additions and 17 deletions

View File

@ -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;