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
+10
View File
@@ -273,6 +273,16 @@ config CAN_KVASER
if 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 choice
prompt "Kvaser PCI CAN device type" prompt "Kvaser PCI CAN device type"
default CAN_KVASER_CHARDEV if CAN default CAN_KVASER_CHARDEV if CAN
+41 -39
View File
@@ -946,36 +946,37 @@ static void kvaser_chardev_interrupt(FAR struct kvaser_driver_s *priv)
{ {
uint8_t st = 0; uint8_t st = 0;
int i = 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); for (i = 0; i < priv->count; i++)
if (st == 0)
{ {
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]); kvaser_chardev_receive(&priv->sja[i]);
}
/* Transmit interrupt */ /* Transmit interrupt */
if (st & SJA1000_TX_INT_ST) if (st & SJA1000_TX_INT_ST)
{ {
/* Tell the upper half that the transfer is finished. */ /* 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 #ifdef CONFIG_CAN_ERRORS
/* Handle errors */ /* Handle errors */
kvaser_chardev_error(&priv->sja[i], st); kvaser_chardev_error(&priv->sja[i], st);
#endif #endif
}
} }
} }
#endif /* CONFIG_CAN_KVASER_CHARDEV */ #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; FAR struct kvaser_driver_s *priv = arg;
uint8_t st = 0; uint8_t st = 0;
uint8_t i = 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); for (i = 0; i < priv->count; i++)
if (st == 0)
{ {
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]); kvaser_sock_receive(&priv->sja[i]);
}
/* Transmit interrupt */ /* Transmit interrupt */
if (st & SJA1000_TX_INT_ST) if (st & SJA1000_TX_INT_ST)
{ {
NETDEV_TXDONE(&priv->sja[i].dev); NETDEV_TXDONE(&priv->sja[i].dev);
/* There should be space for a new TX in any event. /* There should be space for a new TX in any event.
* Poll the network for new XMIT data. * Poll the network for new XMIT data.
*/ */
net_lock(); net_lock();
devif_poll(&priv->sja[i].dev, kvaser_sock_txpoll); devif_poll(&priv->sja[i].dev, kvaser_sock_txpoll);
net_unlock(); net_unlock();
} }
#ifdef CONFIG_NET_CAN_ERRORS #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
}
} }
} }
#endif /* CONFIG_CAN_KVASER_SOCKET */ #endif /* CONFIG_CAN_KVASER_SOCKET */