// SPDX-License-Identifier: GPL-2.0 // // mcp251xfd - Microchip MCP251xFD Family CAN controller driver // // Copyright (c) 2019, 2020, 2021, 2023 Pengutronix, // Marc Kleine-Budde <kernel@pengutronix.de> // // Based on: // // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface // // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org> //
/* First shift to full u8. The subtraction works on signed * values, that keeps the difference steady around the u8 * overflow. The right shift acts on len, which is an u8.
*/
BUILD_BUG_ON(sizeof(ring->obj_num) != sizeof(chip_head));
BUILD_BUG_ON(sizeof(ring->obj_num) != sizeof(tail));
BUILD_BUG_ON(sizeof(ring->obj_num) != sizeof(len));
len = (chip_head << shift) - (tail << shift);
*len_p = len >> shift;
/* According to mcp2518fd erratum DS80000789E 6. the FIFOCI * bits of a FIFOSTA register, here the RX FIFO head index * might be corrupted and we might process past the RX FIFO's * head into old CAN frames. * * Compare the timestamp of currently processed CAN frame with * last valid frame received. Abort with -EBADMSG if an old * CAN frame is detected.
*/
timestamp = timecounter_cyc2time(&priv->tc, hw_rx_obj->ts); if (timestamp <= ring->last_valid) {
stats->rx_fifo_errors++;
staticint
mcp251xfd_handle_rxif_ring_uinc(conststruct mcp251xfd_priv *priv, struct mcp251xfd_rx_ring *ring,
u8 len)
{ int offset; int err;
if (!len) return 0;
ring->head += len;
/* Increment the RX FIFO tail pointer 'len' times in a * single SPI message. * * Note: * Calculate offset, so that the SPI transfer ends on * the last message of the uinc_xfer array, which has * "cs_change == 0", to properly deactivate the chip * select.
*/
offset = ARRAY_SIZE(ring->uinc_xfer) - len;
err = spi_sync_transfer(priv->spi,
ring->uinc_xfer + offset, len); if (err) return err;
for (i = 0; i < l; i++) {
err = mcp251xfd_handle_rxif_one(priv, ring,
(void *)hw_rx_obj +
i * ring->obj_size);
/* -EBADMSG means we're affected by mcp2518fd * erratum DS80000789E 6., i.e. the timestamp * in the RX object is older that the last * valid received CAN frame. Don't process any * further and mark processed frames as good.
*/ if (err == -EBADMSG) return mcp251xfd_handle_rxif_ring_uinc(priv, ring, i); elseif (err) return err;
}
err = mcp251xfd_handle_rxif_ring_uinc(priv, ring, l); if (err) return err;
len -= l;
}
return 0;
}
int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv)
{ struct mcp251xfd_rx_ring *ring; int err, n;
mcp251xfd_for_each_rx_ring(priv, ring, n) { /* - if RX IRQ coalescing is active always handle ring 0 * - only handle rings if RX IRQ is active
*/ if ((ring->nr > 0 || !priv->rx_obj_num_coalesce_irq) &&
!(priv->regs_status.rxif & BIT(ring->fifo_nr))) continue;
err = mcp251xfd_handle_rxif_ring(priv, ring); if (err) return err;
}
if (priv->rx_coalesce_usecs_irq)
hrtimer_start(&priv->rx_irq_timer,
ns_to_ktime(priv->rx_coalesce_usecs_irq *
NSEC_PER_USEC),
HRTIMER_MODE_REL);
return 0;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.