Spirit network driver: TX timeout was never being cancelled! Also reviewed and cleaned up all error handling logic

This commit is contained in:
Gregory Nutt 2017-08-06 15:40:37 -06:00
parent 3c6981534f
commit bbf1ad4ea6
2 changed files with 56 additions and 25 deletions

View File

@ -1104,9 +1104,14 @@ static void spirit_interrupt_work(FAR void *arg)
if (irqstatus.IRQ_TX_DATA_SENT != 0) if (irqstatus.IRQ_TX_DATA_SENT != 0)
{ {
wlinfo("Data sent\n");
/* Disable the TX timeout */
wd_cancel(priv->txtimeout);
/* Put the Spirit back in the receiving state */ /* Put the Spirit back in the receiving state */
wlinfo("Data sent\n");
DEBUGVERIFY(spirit_management_rxstrobe(spirit)); DEBUGVERIFY(spirit_management_rxstrobe(spirit));
DEBUGVERIFY(spirit_command(spirit, CMD_RX)); DEBUGVERIFY(spirit_command(spirit, CMD_RX));
@ -1215,8 +1220,14 @@ static void spirit_interrupt_work(FAR void *arg)
if ((offset + count) > CONFIG_IOB_BUFSIZE) if ((offset + count) > CONFIG_IOB_BUFSIZE)
{ {
wlwarn("WARNING: Packet too large... dropping\n"); wlwarn("WARNING: Packet too large... dropping\n");
/* Flush the RX FIFO and revert the receiving state */
DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO)); DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO));
priv->state = DRIVER_STATE_IDLE; priv->state = DRIVER_STATE_IDLE;
/* Update error statistics */
NETDEV_RXDROPPED(&priv->radio.r_dev); NETDEV_RXDROPPED(&priv->radio.r_dev);
} }
else else
@ -1234,13 +1245,14 @@ static void spirit_interrupt_work(FAR void *arg)
{ {
wlerr("ERROR: Failed to allocate IOB... dropping\n"); wlerr("ERROR: Failed to allocate IOB... dropping\n");
/* Flush the RX FIFO and revert the receiving state */
DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO)); DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO));
priv->state = DRIVER_STATE_IDLE; priv->state = DRIVER_STATE_IDLE;
/* Update error statistics */
NETDEV_RXDROPPED(&priv->radio.r_dev); NETDEV_RXDROPPED(&priv->radio.r_dev);
/* Send any pending packets */
spirit_schedule_transmit_work(priv);
} }
else else
{ {
@ -1252,6 +1264,8 @@ static void spirit_interrupt_work(FAR void *arg)
iob->io_pktlen = iob->io_len; iob->io_pktlen = iob->io_len;
iob->io_flink = NULL; iob->io_flink = NULL;
/* Flush the RX FIFO and revert the receiving state */
DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO)); DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO));
priv->state = DRIVER_STATE_IDLE; priv->state = DRIVER_STATE_IDLE;
@ -1312,12 +1326,12 @@ static void spirit_interrupt_work(FAR void *arg)
spirit_schedule_receive_work(priv); spirit_schedule_receive_work(priv);
} }
} }
}
/* Send any pending packets */ /* Schedule to send any pending packets */
spirit_schedule_transmit_work(priv); spirit_schedule_transmit_work(priv);
} }
}
#ifdef CONFIG_SPIRIT_FIFOS #ifdef CONFIG_SPIRIT_FIFOS
/* The IRQ_RX_FIFO_ALMOST_FULL notifies an nearly full RX fifo. /* The IRQ_RX_FIFO_ALMOST_FULL notifies an nearly full RX fifo.
@ -1360,10 +1374,18 @@ static void spirit_interrupt_work(FAR void *arg)
if ((offset + count) > CONFIG_IOB_BUFSIZE) if ((offset + count) > CONFIG_IOB_BUFSIZE)
{ {
wlwarn("WARNING: Packet too large... dropping\n"); wlwarn("WARNING: Packet too large... dropping\n");
/* Flush the RX FIFO and revert the receiving state */
DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO)); DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO));
priv->state = DRIVER_STATE_IDLE; priv->state = DRIVER_STATE_IDLE;
/* Update statistics */
NETDEV_RXDROPPED(&priv->radio.r_dev); NETDEV_RXDROPPED(&priv->radio.r_dev);
/* Free the IOB */
priv->rxbuffer = NULL; priv->rxbuffer = NULL;
iob_free(iob); iob_free(iob);
} }
@ -1391,9 +1413,26 @@ static void spirit_interrupt_work(FAR void *arg)
wlinfo(" CRC error=%u RX timeout=%u\n", wlinfo(" CRC error=%u RX timeout=%u\n",
irqstatus.IRQ_CRC_ERROR, irqstatus.IRQ_RX_TIMEOUT); irqstatus.IRQ_CRC_ERROR, irqstatus.IRQ_RX_TIMEOUT);
/* Flush the RX FIFO and revert the receiving state */
DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO)); DEBUGVERIFY(spirit_command(spirit, CMD_FLUSHRXFIFO));
priv->state = DRIVER_STATE_IDLE; priv->state = DRIVER_STATE_IDLE;
NETDEV_RXDROPPED(&priv->radio.r_dev);
/* Statistics are not updated. Nor should they be updated for the
* case of packets that failed the address filter. RX timeouts are not
* enabled. CRC timeouts would depend on if the packet was destined
* for us or not. So, we do nothing.
*/
#ifdef CONFIG_SPIRIT_FIFOS
/* Discard any RX buffer that might have been allocated */
if (priv->rxbuffer != NULL)
{
iob_free(priv->rxbuffer);
priv->rxbuffer = NULL;
}
#endif
} }
/* Check the Spirit status. If it is READY, the setup the RX state */ /* Check the Spirit status. If it is READY, the setup the RX state */
@ -1429,19 +1468,11 @@ static int spirit_interrupt(int irq, FAR void *context, FAR void *arg)
DEBUGASSERT(priv != NULL); DEBUGASSERT(priv != NULL);
/* TODO: Determine if a TX transfer just completed . /* We cannot do SPI transfers from the interrupt handler because
* If a TX transfer just completed, then cancel the TX timeout so * semaphores are probably used to lock the SPI bus. SPI drivers may also
* there will be no race condition between any subsequent timeout * use interrupts and DMA. In these cases, we will defer processing to
* expiration and the deferred interrupt processing. * the HP worker thread. This is also much kinder in the use of system
*/ * resources and is, therefore, probably a good thing to do in any event.
//wd_cancel(priv->txtimeout);
/* In complex environments, we cannot do SPI transfers from the interrupt
* handler because semaphores are probably used to lock the SPI bus. In
* this case, we will defer processing to the worker thread. This is also
* much kinder in the use of system resources and is, therefore, probably
* a good thing to do in any event.
*/ */
return work_queue(HPWORK, &priv->irqwork, spirit_interrupt_work, return work_queue(HPWORK, &priv->irqwork, spirit_interrupt_work,

View File

@ -33,7 +33,7 @@
# #
############################################################################ ############################################################################
# Socket address families # PF_INET/PF_INET6 socket address families
ifeq ($(CONFIG_NET_IPv4),y) ifeq ($(CONFIG_NET_IPv4),y)
SOCK_CSRCS += inet_sockif.c inet_recvfrom.c inet_connect.c inet_close.c SOCK_CSRCS += inet_sockif.c inet_recvfrom.c inet_connect.c inet_close.c
@ -61,7 +61,7 @@ ifneq ($(CONFIG_NET_TCP_NO_STACK),y)
SOCK_CSRCS += inet_monitor.c SOCK_CSRCS += inet_monitor.c
endif endif
# Include socket build support # Include inet build support
DEPPATH += --dep-path inet DEPPATH += --dep-path inet
VPATH += :inet VPATH += :inet