drivers/can/kvaser_pci.c: configure number of passes in interrupt handler

Configure number of passes in interrupt handler logic to avoid losing RX frames
in QEMU environment.

Signed-off-by: p-szafonimateusz <p-szafonimateusz@xiaomi.com>
This commit is contained in:
p-szafonimateusz
2025-06-19 14:34:13 +02:00
committed by Donny(董九柱)
parent e2cdb7ef34
commit 4ed174a7e0
2 changed files with 51 additions and 39 deletions

View File

@@ -273,6 +273,16 @@ config CAN_KVASER
if CAN_KVASER
config CAN_KVASER_IRQ_PASSES
int "Kvaser PCI interrupt passes"
default 16
range 1 512
---help---
This option sets how many times the card status will be checked
during one interrupt handler. A value greater than 1 helps avoid
data loss when there is a lot of traffic on the CAN bus.
The downside is that it increases the interrupt service time.
choice
prompt "Kvaser PCI CAN device type"
default CAN_KVASER_CHARDEV if CAN

View File

@@ -946,36 +946,37 @@ static void kvaser_chardev_interrupt(FAR struct kvaser_driver_s *priv)
{
uint8_t st = 0;
int i = 0;
int passes;
for (i = 0; i < priv->count; i++)
for (passes = 0; passes < CONFIG_CAN_KVASER_IRQ_PASSES; passes++)
{
st = kvaser_getreg_sja(&priv->sja[i], SJA1000_INT_RAW_REG);
if (st == 0)
for (i = 0; i < priv->count; i++)
{
continue;
}
st = kvaser_getreg_sja(&priv->sja[i], SJA1000_INT_RAW_REG);
if (st == 0)
{
continue;
}
/* Receive interrupt */
/* Handle RX frames */
if (st & SJA1000_RX_INT_ST)
{
kvaser_chardev_receive(&priv->sja[i]);
}
/* Transmit interrupt */
/* Transmit interrupt */
if (st & SJA1000_TX_INT_ST)
{
/* Tell the upper half that the transfer is finished. */
if (st & SJA1000_TX_INT_ST)
{
/* Tell the upper half that the transfer is finished. */
can_txdone(&priv->sja[i].dev);
}
can_txdone(&priv->sja[i].dev);
}
#ifdef CONFIG_CAN_ERRORS
/* Handle errors */
/* Handle errors */
kvaser_chardev_error(&priv->sja[i], st);
kvaser_chardev_error(&priv->sja[i], st);
#endif
}
}
}
#endif /* CONFIG_CAN_KVASER_CHARDEV */
@@ -1487,42 +1488,43 @@ static void kvaser_sock_interrupt_work(FAR void *arg)
FAR struct kvaser_driver_s *priv = arg;
uint8_t st = 0;
uint8_t i = 0;
int passes;
for (i = 0; i < priv->count; i++)
for (passes = 0; passes < CONFIG_CAN_KVASER_IRQ_PASSES; passes++)
{
st = kvaser_getreg_sja(&priv->sja[i], SJA1000_INT_RAW_REG);
if (st == 0)
for (i = 0; i < priv->count; i++)
{
continue;
}
st = kvaser_getreg_sja(&priv->sja[i], SJA1000_INT_RAW_REG);
if (st == 0)
{
continue;
}
/* Receive interrupt */
/* Handle RX frames */
if (st & SJA1000_RX_INT_ST)
{
kvaser_sock_receive(&priv->sja[i]);
}
/* Transmit interrupt */
/* Transmit interrupt */
if (st & SJA1000_TX_INT_ST)
{
NETDEV_TXDONE(&priv->sja[i].dev);
if (st & SJA1000_TX_INT_ST)
{
NETDEV_TXDONE(&priv->sja[i].dev);
/* There should be space for a new TX in any event.
* Poll the network for new XMIT data.
*/
/* There should be space for a new TX in any event.
* Poll the network for new XMIT data.
*/
net_lock();
devif_poll(&priv->sja[i].dev, kvaser_sock_txpoll);
net_unlock();
}
net_lock();
devif_poll(&priv->sja[i].dev, kvaser_sock_txpoll);
net_unlock();
}
#ifdef CONFIG_NET_CAN_ERRORS
/* Handle errors */
/* Handle errors */
kvaser_sock_error(&priv->sja[i], st);
kvaser_sock_error(&priv->sja[i], st);
#endif
}
}
}
#endif /* CONFIG_CAN_KVASER_SOCKET */