diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c index 71c2a0fa8e2c1..06009d44c7967 100644 --- a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c @@ -701,6 +701,12 @@ static void mpfs_receive_work(void *arg) mpfs_can_retrieve_rx_frame(priv, cf, ffw); + /* Lock the network; we have to protect the dev.d_len, dev.d_buf + * and dev.d_iob from the devif_poll path + */ + + net_lock(); + /* Copy the buffer pointer to priv->dev.. Set amount of data * in priv->dev.d_len */ @@ -714,6 +720,8 @@ static void mpfs_receive_work(void *arg) NETDEV_RXPACKETS(&priv->dev); can_input(&priv->dev); + net_unlock(); + /* Point the packet buffer back to the next Tx buffer that will be * used during the next write. If the write queue is full, then * this will point at an active buffer, which must not be written diff --git a/net/can/can_callback.c b/net/can/can_callback.c index ac5de920937f5..2804b67d1ba67 100644 --- a/net/can/can_callback.c +++ b/net/can/can_callback.c @@ -62,11 +62,12 @@ can_data_event(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn, uint16_t flags) { int buflen = dev->d_len; + uint16_t recvlen; + uint16_t ret; + #ifdef CONFIG_NET_TIMESTAMP buflen -= sizeof(struct timeval); #endif - uint16_t recvlen; - uint16_t ret; ret = (flags & ~CAN_NEWDATA); @@ -136,19 +137,6 @@ uint16_t can_callback(FAR struct net_driver_s *dev, if ((flags & CAN_NEWDATA) != 0) { - if (dev->d_iob->io_flink != NULL || - dev->d_iob->io_pktlen == 0 || - dev->d_iob->io_offset <= 0) - { - if (dev->d_iob->io_flink == NULL) - { - iob_free(dev->d_iob); - } - - netdev_iob_clear(dev); - return flags; - } - #ifdef CONFIG_NET_TIMESTAMP /* TIMESTAMP sockopt is activated, * create timestamp and copy to iob @@ -230,11 +218,16 @@ uint16_t can_datahandler(FAR struct net_driver_s *dev, can_readahead_signal(conn); #endif ret = iob->io_pktlen; - } - /* Device buffer must be enqueue or freed, clear the handle */ + /* Device buffer has been enqueued, clear the handle */ - netdev_iob_clear(dev); + netdev_iob_clear(dev); + } + else + { + nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret); + netdev_iob_release(dev); + } return ret; } diff --git a/net/can/can_recvmsg.c b/net/can/can_recvmsg.c index b6a486b28463d..4ce63b69ee751 100644 --- a/net/can/can_recvmsg.c +++ b/net/can/can_recvmsg.c @@ -233,22 +233,9 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) pstate->pr_recvlen = -1; - if ((iob = iob_peek_queue(&conn->readahead)) != NULL && + if ((iob = iob_remove_queue(&conn->readahead)) != NULL && pstate->pr_buflen > 0) { - if (iob->io_flink != NULL || - iob->io_pktlen == 0 || - iob->io_offset <= 0) - { - if (iob->io_pktlen == 0 || iob->io_offset <= 0) - { - iob_free(iob); - } - - iob_remove_queue(&conn->readahead); - return 0; - } - DEBUGASSERT(iob->io_pktlen > 0); #ifdef CONFIG_NET_CANPROTO_OPTIONS @@ -259,17 +246,7 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) if (can_recv_filter(conn, can_id) == 0) { - FAR struct iob_s *tmp; - - /* Remove the I/O buffer chain from the head of the read-ahead - * buffer queue. - */ - - tmp = iob_remove_queue(&conn->readahead); - DEBUGASSERT(tmp == iob); - UNUSED(tmp); - - /* And free the I/O buffer chain */ + /* Free the I/O buffer chain */ iob_free_chain(iob); return 0; @@ -290,27 +267,14 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) recvlen = iob_copyout(pstate->pr_buffer, iob, pstate->pr_buflen, 0); - /* If we took all of the data from the I/O buffer chain is empty, then - * release it. If there is still data available in the I/O buffer - * chain, then just trim the data that we have taken from the - * beginning of the I/O buffer chain. - */ - - /* No trimming needed since one CAN/CANFD frame can perfectly - * fit in one iob - */ - - FAR struct iob_s *tmp; - - /* Remove the I/O buffer chain from the head of the read-ahead - * buffer queue. + /* We should have taken all of the data from the I/O buffer chain, + * so release it. There is no trimming needed, since One CAN/CANFD + * frame can always fit in one IOB. */ - tmp = iob_remove_queue(&conn->readahead); - DEBUGASSERT(tmp == iob); - UNUSED(tmp); + static_assert(sizeof(struct can_frame) <= CONFIG_IOB_BUFSIZE); - /* And free the I/O buffer chain */ + /* Free the I/O buffer chain */ iob_free_chain(iob);