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

View File

@ -1044,6 +1044,12 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
* Returned Value: * Returned Value:
* OK on success; a negated errno on failure. * 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) int can_txdone(FAR struct can_dev_s *dev)
@ -1143,6 +1149,10 @@ int can_txdone(FAR struct can_dev_s *dev)
* Returned Value: * Returned Value:
* OK on success; a negated errno on failure. * 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 #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_xmit.tx_head, dev->cd_xmit.tx_queue, dev->cd_xmit.tx_tail,
dev->cd_ntxwaiters); 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. /* 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
* REVISIT: This probably should be an assertion since we should only * to the H/W TX FIFO and can_txdone() should be called, making
* be waiting for space in the xmit FIFO if the xmit FIFO is full. * space in the S/W FIFO
*/ */
if (dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail) (void)can_xmit(dev);
{
/* 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);
}
/* Inform one waiter that new xmit space is available in the S/W FIFO. /* 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 * 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. * 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; return ret;