This is an automated email from the ASF dual-hosted git repository.
jerpelea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new a38dc249edf drivers/can/kvaser_pci.c: refactor to use netdev_upperhalf
a38dc249edf is described below
commit a38dc249edfe11e21aba3840222e63fd9d5c2954
Author: p-szafonimateusz <[email protected]>
AuthorDate: Thu Aug 28 12:10:22 2025 +0200
drivers/can/kvaser_pci.c: refactor to use netdev_upperhalf
Refactor kvaser_pci.c to use netdev_upperhalf for SocketCAN interface.
The reason for this change is to simplify the driver code and get rid of
duplicate code that may be shared between other network devices.
Signed-off-by: p-szafonimateusz <[email protected]>
---
drivers/can/kvaser_pci.c | 585 ++++++++++++++++++++---------------------------
1 file changed, 243 insertions(+), 342 deletions(-)
diff --git a/drivers/can/kvaser_pci.c b/drivers/can/kvaser_pci.c
index bf08eee0da3..090325ff263 100644
--- a/drivers/can/kvaser_pci.c
+++ b/drivers/can/kvaser_pci.c
@@ -40,8 +40,7 @@
#endif
#ifdef CONFIG_CAN_KVASER_SOCKET
-# include <nuttx/wqueue.h>
-# include <nuttx/net/netdev.h>
+# include <nuttx/net/netdev_lowerhalf.h>
# include <nuttx/net/can.h>
#endif
@@ -77,22 +76,29 @@
SJA1000_ARB_LOST_INT_ENA | \
SJA1000_BUS_ERR_INT_ENA)
+#define KVASER_INT_ERR_ST (SJA1000_OVERRUN_INT_ST | \
+ SJA1000_ERR_PASSIVE_INT_ST | \
+ SJA1000_ARB_LOST_INT_ST | \
+ SJA1000_BUS_ERR_INT_ST)
+
/* SocketCAN specific */
#ifdef CONFIG_CAN_KVASER_SOCKET
+# define KVASER_TX_QUOTA 1
+# define KVASER_RX_QUOTA 1
-# define KVASER_POOL_SIZE 1
-
-/* Work queue support is required. */
-
-# if !defined(CONFIG_SCHED_WORKQUEUE)
-# error Work queue support is required
+# if CONFIG_IOB_NBUFFERS < (KVASER_RX_QUOTA + KVASER_TX_QUOTA)
+# error CONFIG_IOB_NBUFFERS must be > (KVASER_RX_QUOTA + KVASER_TX_QUOTA)
# endif
-# define KVASER_CANWORK LPWORK
-
#endif /* CONFIG_CAN_KVASER_SOCKET */
+#ifndef CONFIG_NET_CAN_ERRORS
+# define KVASER_SOCK_RXINT (SJA1000_RX_INT_ST)
+#else
+# define KVASER_SOCK_RXINT (SJA1000_RX_INT_ST | KVASER_INT_ERR_ST)
+#endif
+
/*****************************************************************************
* Private Types
*****************************************************************************/
@@ -106,13 +112,9 @@ struct kvaser_sja_s
#endif
#ifdef CONFIG_CAN_KVASER_SOCKET
- struct net_driver_s dev; /* Interface understood by the network */
- struct work_s pollwork; /* For deferring poll work to the work wq */
+ /* This holds the information visible to the NuttX network */
- /* TX/RX pool */
-
- struct can_frame tx_pool[KVASER_POOL_SIZE];
- struct can_frame rx_pool[KVASER_POOL_SIZE];
+ struct netdev_lowerhalf_s dev;
#endif
/* PCI data */
@@ -193,21 +195,22 @@ static void kvaser_chardev_interrupt(FAR struct
kvaser_driver_s *priv);
#ifdef CONFIG_CAN_KVASER_SOCKET
/* SocketCAN methods */
-static int kvaser_sock_ifup(FAR struct net_driver_s *dev);
-static int kvaser_sock_ifdown(FAR struct net_driver_s *dev);
-
-static void kvaser_sock_txavail_work(FAR void *arg);
-static int kvaser_sock_txavail(FAR struct net_driver_s *dev);
+static int kvaser_sock_ifup(FAR struct netdev_lowerhalf_s *dev);
+static int kvaser_sock_ifdown(FAR struct netdev_lowerhalf_s *dev);
+static int kvaser_sock_transmit(FAR struct netdev_lowerhalf_s *dev,
+ FAR netpkt_t *pkt);
+static FAR netpkt_t *kvaser_sock_recv(FAR struct netdev_lowerhalf_s *dev);
# ifdef CONFIG_NETDEV_IOCTL
-static int kvaser_sock_ioctl(FAR struct net_driver_s *dev, int cmd,
+static int kvaser_sock_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd,
unsigned long arg);
# endif
-static int kvaser_sock_txpoll(FAR struct net_driver_s *dev);
-static int kvaser_sock_send(FAR struct kvaser_sja_s *priv);
-static void kvaser_sock_receive(FAR struct kvaser_sja_s *priv);
-static void kvaser_sock_interrupt_work(FAR void *arg);
+# ifdef CONFIG_NET_CAN_ERRORS
+static FAR netpkt_t *kvaser_sock_error(FAR struct netdev_lowerhalf_s *dev);
+# endif
+
+static void kvaser_sock_interrupt(FAR struct kvaser_driver_s *priv);
#endif
/* Interrupts */
@@ -240,6 +243,19 @@ static const struct can_ops_s g_kvaser_can_ops =
};
#endif
+#ifdef CONFIG_CAN_KVASER_SOCKET
+static const struct netdev_ops_s g_kvaser_net_ops =
+{
+ .ifup = kvaser_sock_ifup,
+ .ifdown = kvaser_sock_ifdown,
+ .transmit = kvaser_sock_transmit,
+ .receive = kvaser_sock_recv,
+#ifdef CONFIG_NETDEV_IOCTL
+ .ioctl = kvaser_sock_ioctl,
+#endif
+};
+#endif
+
static const struct pci_device_id_s g_kvaser_id_table[] =
{
{
@@ -997,11 +1013,9 @@ static void kvaser_chardev_interrupt(FAR struct
kvaser_driver_s *priv)
*
*****************************************************************************/
-static int kvaser_sock_ifup(FAR struct net_driver_s *dev)
+static int kvaser_sock_ifup(FAR struct netdev_lowerhalf_s *dev)
{
- FAR struct kvaser_sja_s *priv = (FAR struct kvaser_sja_s *)dev->d_private;
-
- priv->dev.d_buf = (FAR uint8_t *)priv->tx_pool;
+ FAR struct kvaser_sja_s *priv = (FAR struct kvaser_sja_s *)dev;
kvaser_reset(priv);
kvaser_setup(priv);
@@ -1026,9 +1040,9 @@ static int kvaser_sock_ifup(FAR struct net_driver_s *dev)
*
*****************************************************************************/
-static int kvaser_sock_ifdown(FAR struct net_driver_s *dev)
+static int kvaser_sock_ifdown(FAR struct netdev_lowerhalf_s *dev)
{
- FAR struct kvaser_sja_s *priv = (FAR struct kvaser_sja_s *)dev->d_private;
+ FAR struct kvaser_sja_s *priv = (FAR struct kvaser_sja_s *)dev;
kvaser_txint(priv, false);
kvaser_rxint(priv, false);
@@ -1041,180 +1055,32 @@ static int kvaser_sock_ifdown(FAR struct net_driver_s
*dev)
}
/*****************************************************************************
- * Name: kvaser_sock_txavail_work
+ * Name: kvaser_sock_transmit
*
* Description:
- * Perform an out-of-cycle poll on the worker thread.
+ * Start hardware transmission. Called either from the txdone interrupt
+ * handling or from watchdog based polling.
*
* Input Parameters:
- * arg - Reference to the NuttX driver state structure (cast to void*)
+ * priv - Reference to the driver state structure
*
* Returned Value:
- * None
+ * Return OK on success
*
* Assumptions:
- * Called on the higher priority worker thread.
+ * The network is locked.
*
*****************************************************************************/
-static void kvaser_sock_txavail_work(FAR void *arg)
+static int kvaser_sock_transmit(FAR struct netdev_lowerhalf_s *dev,
+ FAR netpkt_t *pkt)
{
- FAR struct kvaser_sja_s *priv = (FAR struct kvaser_sja_s *)arg;
-
- /* Ignore the notification if the interface is not yet up */
-
- net_lock();
- if (IFF_IS_UP(priv->dev.d_flags))
- {
- /* Check if there is room in the hardware to hold another outgoing
- * packet.
- */
-
- if (kvaser_txready(priv))
- {
- /* No, there is space for another transfer. Poll the network for
- * new XMIT data.
- */
-
- devif_poll(&priv->dev, kvaser_sock_txpoll);
- }
- }
-
- net_unlock();
-}
-
-/*****************************************************************************
- * Name: kvaser_sock_txavail
- *
- * Description:
- * Driver callback invoked when new TX data is available. This is a
- * stimulus perform an out-of-cycle poll and, thereby, reduce the TX
- * latency.
- *
- * Input Parameters:
- * dev - Reference to the NuttX driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Called in normal user mode
- *
- *****************************************************************************/
-
-static int kvaser_sock_txavail(FAR struct net_driver_s *dev)
-{
- FAR struct kvaser_sja_s *priv = (FAR struct kvaser_sja_s *)dev->d_private;
-
- /* Is our single work structure available? It may not be if there are
- * pending interrupt actions and we will have to ignore the Tx
- * availability action.
- */
-
- if (work_available(&priv->pollwork))
- {
- /* Schedule to serialize the poll on the worker thread. */
-
- kvaser_sock_txavail_work(priv);
- }
-
- return OK;
-}
-
-# ifdef CONFIG_NETDEV_IOCTL
-/*****************************************************************************
- * Name: kvaser_sock_ioctl
- *
- * Description:
- * PHY ioctl command handler
- *
- * Input Parameters:
- * dev - Reference to the NuttX driver state structure
- * cmd - ioctl command
- * arg - Argument accompanying the command
- *
- * Returned Value:
- * Zero (OK) on success; a negated errno value on failure.
- *
- * Assumptions:
- *
- *****************************************************************************/
-
-static int kvaser_sock_ioctl(FAR struct net_driver_s *dev, int cmd,
- unsigned long arg)
-{
- return -ENOTTY;
-}
-
-# endif /* CONFIG_NETDEV_IOCTL */
-
-/*****************************************************************************
- * Name: kvaser_sock_txpoll
- *
- * Description:
- * The transmitter is available, check if the network has any outgoing
- * packets ready to send. This is a callback from devif_poll().
- * devif_poll() may be called:
- *
- * 1. When the preceding TX packet send is complete,
- * 2. When the preceding TX packet send timesout and the interface is reset
- * 3. During normal TX polling
- *
- * Input Parameters:
- * dev - Reference to the NuttX driver state structure
- *
- * Returned Value:
- * OK on success; a negated errno on failure
- *
- * Assumptions:
- * May or may not be called from an interrupt handler. In either case,
- * global interrupts are disabled, either explicitly or indirectly through
- * interrupt handling logic.
- *
- *****************************************************************************/
-
-static int kvaser_sock_txpoll(FAR struct net_driver_s *dev)
-{
- FAR struct kvaser_sja_s *priv = (FAR struct kvaser_sja_s *)dev->d_private;
-
- /* If the polling resulted in data that should be sent out on the network,
- * the field d_len is set to a value > 0.
- */
-
- if (priv->dev.d_len > 0)
- {
- /* Send the packet */
-
- kvaser_sock_send(priv);
-
- /* Check if there is room in the device to hold another packet. If
- * not, return a non-zero value to terminate the poll.
- */
-
- if (!kvaser_txready(priv))
- {
- return -EBUSY;
- }
- }
-
- /* If zero is returned, the polling will continue until all connections
- * have been examined.
- */
-
- return 0;
-}
-
-/*****************************************************************************
- * Name: kvaser_sock_send
- *****************************************************************************/
-
-static int kvaser_sock_send(FAR struct kvaser_sja_s *priv)
-{
- FAR struct can_frame *frame = (FAR struct can_frame *)priv->dev.d_buf;
- uint8_t regval = 0;
- uint8_t dreg = 0;
- uint8_t fi = 0;
- int i = 0;
+ FAR struct kvaser_sja_s *priv = (FAR struct kvaser_sja_s *)dev;
+ FAR struct can_frame *frame = NULL;
+ uint8_t regval = 0;
+ uint8_t dreg = 0;
+ uint8_t fi = 0;
+ int i = 0;
/* Check TX buffer status */
@@ -1227,13 +1093,17 @@ static int kvaser_sock_send(FAR struct kvaser_sja_s
*priv)
#ifdef CONFIG_CAN_FD
/* Drop CAN FD frames */
- if (priv->dev.d_len != sizeof(struct can_frame))
+ if (netpkt_getdatalen(dev, pkt) != sizeof(struct can_frame))
{
canerr("ERROR: CAN FD frames not supported\n");
return -ENOTSUP;
}
#endif
+ /* Get frame data */
+
+ frame = (FAR struct can_frame *)netpkt_getdata(dev, pkt);
+
/* Set up the DLC */
fi = frame->can_dlc;
@@ -1293,115 +1163,187 @@ static int kvaser_sock_send(FAR struct kvaser_sja_s
*priv)
regval = SJA1000_TX_REQ;
kvaser_putreg_sja(priv, SJA1000_CMD_REG, regval);
+ /* All is done - free packet */
+
+ netpkt_free(dev, pkt, NETPKT_TX);
+
return OK;
}
/*****************************************************************************
- * Name: kvaser_sock_receive
+ * Name: kvaser_sock_recv
+ *
+ * Description:
+ * An interrupt was received indicating the availability of a new RX packet
+ *
+ * Input Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * A pointer to received packet
+ *
+ * Assumptions:
+ * The network is locked.
+ *
*****************************************************************************/
-static void kvaser_sock_receive(FAR struct kvaser_sja_s *priv)
+static FAR netpkt_t *kvaser_sock_recv(FAR struct netdev_lowerhalf_s *dev)
{
- FAR struct can_frame *frame = (FAR struct can_frame *)priv->rx_pool;
- uint8_t dreg = 0;
- int i = 0;
- uint8_t regval;
+ FAR struct kvaser_sja_s *priv = (FAR struct kvaser_sja_s *)dev;
+ FAR struct can_frame *frame = NULL;
+ FAR netpkt_t *pkt = NULL;
+ uint8_t dreg = 0;
+ int i = 0;
+ uint8_t regval;
+ uint8_t st;
+
+ /* Read frame if RXFIFO not empty */
+
+ st = kvaser_getreg_sja(priv, SJA1000_STATUS_REG);
+ if ((st & SJA1000_RX_BUF_ST) == 0)
+ {
+#ifdef CONFIG_NET_CAN_ERRORS
+ /* Check for errors */
- /* Wait until data in RXFIFO */
+ return kvaser_sock_error(dev);
+#else
+ return NULL;
+#endif
+ }
- while (kvaser_getreg_sja(priv, SJA1000_STATUS_REG) & SJA1000_RX_BUF_ST)
+ /* Allocate packet */
+
+ pkt = netpkt_alloc(dev, NETPKT_RX);
+ if (!pkt)
{
- regval = kvaser_getreg_sja(priv, SJA1000_DATA_0_REG);
+ canerr("alloc pkt_new failed\n");
+ return NULL;
+ }
- /* Get the DLC */
+ netpkt_setdatalen(dev, pkt, sizeof(struct can_frame));
+ frame = (FAR struct can_frame *)netpkt_getdata(dev, pkt);
- frame->can_dlc = (regval & SJA1000_FI_DLC_MASK);
+ regval = kvaser_getreg_sja(priv, SJA1000_DATA_0_REG);
- /* Get the CAN identifier. */
+ /* Get the DLC */
- if (!(regval & SJA1000_FI_FF))
- {
- frame->can_id =
- ((kvaser_getreg_sja(priv, SJA1000_DATA_1_REG) << 3) |
- (kvaser_getreg_sja(priv, SJA1000_DATA_2_REG) >> 5));
+ frame->can_dlc = (regval & SJA1000_FI_DLC_MASK);
- dreg = SJA1000_DATA_3_REG;
- }
- else
- {
+ /* Get the CAN identifier. */
+
+ if (!(regval & SJA1000_FI_FF))
+ {
+ frame->can_id =
+ ((kvaser_getreg_sja(priv, SJA1000_DATA_1_REG) << 3) |
+ (kvaser_getreg_sja(priv, SJA1000_DATA_2_REG) >> 5));
+
+ dreg = SJA1000_DATA_3_REG;
+ }
+ else
+ {
#ifdef CONFIG_NET_CAN_EXTID
- frame->can_id =
- ((kvaser_getreg_sja(priv, SJA1000_DATA_1_REG) << 21) |
- (kvaser_getreg_sja(priv, SJA1000_DATA_2_REG) << 13) |
- (kvaser_getreg_sja(priv, SJA1000_DATA_3_REG) << 5) |
- (kvaser_getreg_sja(priv, SJA1000_DATA_4_REG) >> 3));
- frame->can_id |= CAN_EFF_FLAG;
+ frame->can_id =
+ ((kvaser_getreg_sja(priv, SJA1000_DATA_1_REG) << 21) |
+ (kvaser_getreg_sja(priv, SJA1000_DATA_2_REG) << 13) |
+ (kvaser_getreg_sja(priv, SJA1000_DATA_3_REG) << 5) |
+ (kvaser_getreg_sja(priv, SJA1000_DATA_4_REG) >> 3));
+ frame->can_id |= CAN_EFF_FLAG;
- dreg = SJA1000_DATA_5_REG;
+ dreg = SJA1000_DATA_5_REG;
#else
- canerr("ERROR: Received message with extended"
- " identifier. Dropped\n");
+ canerr("ERROR: Received message with extended"
+ " identifier. Dropped\n");
- /* Release RX buffer */
+ /* Release RX buffer */
- kvaser_putreg_sja(priv, SJA1000_CMD_REG, SJA1000_RELEASE_BUF);
+ kvaser_putreg_sja(priv, SJA1000_CMD_REG, SJA1000_RELEASE_BUF);
- continue;
+ netpkt_free(dev, pkt);
+ return NULL;
#endif
- }
-
- /* Extract the RTR bit */
-
- if (regval & SJA1000_FI_RTR)
- {
- frame->can_id |= CAN_RTR_FLAG;
- }
-
- /* Get data */
-
- for (i = 0; i < can_dlc2bytes(frame->can_dlc); i++)
- {
- frame->data[i] = kvaser_getreg_sja(priv, dreg + i);
- }
+ }
- /* Release RX buffer */
+ /* Extract the RTR bit */
- kvaser_putreg_sja(priv, SJA1000_CMD_REG, SJA1000_RELEASE_BUF);
+ if (regval & SJA1000_FI_RTR)
+ {
+ frame->can_id |= CAN_RTR_FLAG;
+ }
- /* Copy the buffer pointer to priv->dev.. Set amount of data
- * in priv->dev.d_len
- */
+ /* Get data */
- priv->dev.d_len = sizeof(struct can_frame);
- priv->dev.d_buf = (FAR uint8_t *)frame;
+ for (i = 0; i < can_dlc2bytes(frame->can_dlc); i++)
+ {
+ frame->data[i] = kvaser_getreg_sja(priv, dreg + i);
+ }
- /* Send to socket interface */
+ /* Release RX buffer */
- NETDEV_RXPACKETS(&priv->dev);
+ kvaser_putreg_sja(priv, SJA1000_CMD_REG, SJA1000_RELEASE_BUF);
- can_input(&priv->dev);
+ return pkt;
+}
- /* 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
- * to. This is OK because devif_poll won't be called unless the
- * queue is not full.
- */
+# ifdef CONFIG_NETDEV_IOCTL
+/*****************************************************************************
+ * Name: kvaser_sock_ioctl
+ *
+ * Description:
+ * PHY ioctl command handler
+ *
+ * Input Parameters:
+ * dev - Reference to the NuttX driver state structure
+ * cmd - ioctl command
+ * arg - Argument accompanying the command
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ *
+ *****************************************************************************/
- priv->dev.d_buf = (FAR uint8_t *)priv->tx_pool;
- }
+static int kvaser_sock_ioctl(FAR struct netdev_lowerhalf_s, int cmd,
+ unsigned long arg)
+{
+ return -ENOTTY;
}
+# endif /* CONFIG_NETDEV_IOCTL */
+
#ifdef CONFIG_NET_CAN_ERRORS
/*****************************************************************************
* Name: kvaser_sock_error
*****************************************************************************/
-static void kvaser_sock_error(FAR struct kvaser_sja_s *priv, uint8_t st)
+static FAR netpkt_t *kvaser_sock_error(FAR struct netdev_lowerhalf_s *dev)
{
- FAR struct can_frame *frame = NULL;
- uint8_t regval;
- uint16_t errbits = 0;
+ FAR struct kvaser_sja_s *priv = (FAR struct kvaser_sja_s *)dev;
+ FAR struct can_frame *frame = NULL;
+ FAR netpkt_t *pkt = NULL;
+ uint8_t regval = 0;
+ uint8_t st = 0;
+ uint16_t errbits = 0;
+
+ /* Check for no errors */
+
+ st = kvaser_getreg_sja(priv, SJA1000_INT_RAW_REG);
+ if ((st & KVASER_INT_ERR_ST) == 0)
+ {
+ return NULL;
+ }
+
+ /* Allocate packet */
+
+ pkt = netpkt_alloc(dev, NETPKT_RX);
+ if (!pkt)
+ {
+ canerr("alloc pkt_new failed\n");
+ return NULL;
+ }
+
+ netpkt_setdatalen(dev, pkt, sizeof(struct can_frame));
+ frame = (FAR struct can_frame *)netpkt_getdata(dev, pkt);
/* Data overrun interrupt */
@@ -1440,55 +1382,26 @@ static void kvaser_sock_error(FAR struct kvaser_sja_s
*priv, uint8_t st)
errbits |= CAN_ERR_BUSERROR;
}
- if (errbits != 0)
- {
- frame = (FAR struct can_frame *)priv->rx_pool;
-
- canerr("ERROR: errbits = %08" PRIx16 "\n", errbits);
-
- /* Copy frame */
-
- frame->can_id = errbits;
- frame->can_dlc = CAN_ERR_DLC;
-
- net_lock();
-
- /* Copy the buffer pointer to priv->dev.. Set amount of data
- * in priv->dev.d_len
- */
-
- priv->dev.d_len = sizeof(struct can_frame);
- priv->dev.d_buf = (FAR uint8_t *)frame;
-
- /* Send to socket interface */
-
- NETDEV_ERRORS(&priv->dev);
+ canerr("ERROR: errbits = %08" PRIx16 "\n", errbits);
- can_input(&priv->dev);
+ /* Copy frame */
- /* 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
- * to. This is OK because devif_poll won't be called unless the
- * queue is not full.
- */
+ frame->can_id = errbits;
+ frame->can_dlc = CAN_ERR_DLC;
- priv->dev.d_buf = (FAR uint8_t *)priv->tx_pool;
- net_unlock();
- }
+ return pkt;
}
#endif
/*****************************************************************************
- * Name: kvaser_sock_interrupt_work
+ * Name: kvaser_sock_interrupt
*****************************************************************************/
-static void kvaser_sock_interrupt_work(FAR void *arg)
+static void kvaser_sock_interrupt(FAR struct kvaser_driver_s *priv)
{
- FAR struct kvaser_driver_s *priv = arg;
- uint8_t st = 0;
- uint8_t i = 0;
- int passes;
+ uint8_t st = 0;
+ uint8_t i = 0;
+ int passes;
for (passes = 0; passes < CONFIG_CAN_KVASER_IRQ_PASSES; passes++)
{
@@ -1500,30 +1413,19 @@ static void kvaser_sock_interrupt_work(FAR void *arg)
continue;
}
- /* Handle RX frames */
+ /* RX ready */
- kvaser_sock_receive(&priv->sja[i]);
+ if (st & KVASER_SOCK_RXINT)
+ {
+ netdev_lower_rxready(&priv->sja[i].dev);
+ }
/* Transmit interrupt */
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.
- */
-
- net_lock();
- devif_poll(&priv->sja[i].dev, kvaser_sock_txpoll);
- net_unlock();
+ netdev_lower_txdone(&priv->sja[i].dev);
}
-
-#ifdef CONFIG_NET_CAN_ERRORS
- /* Handle errors */
-
- kvaser_sock_error(&priv->sja[i], st);
-#endif
}
}
}
@@ -1553,10 +1455,9 @@ static int kvaser_interrupt(int irq, FAR void *context,
FAR void *arg)
#endif
#ifdef CONFIG_CAN_KVASER_SOCKET
- /* Derefer SocketCAN interrupt to work queue */
+ /* Handle SocketCAN interrupt */
- work_queue(KVASER_CANWORK, &priv->irqwork,
- kvaser_sock_interrupt_work, priv, 0);
+ kvaser_sock_interrupt(priv);
#endif
}
@@ -1633,12 +1534,15 @@ static uint8_t kvaser_count_sja(FAR struct
kvaser_driver_s *priv)
static int kvaser_probe(FAR struct pci_device_s *dev)
{
- FAR struct kvaser_driver_s *priv = NULL;
- uint8_t i = 0;
- int ret;
+#ifdef CONFIG_CAN_KVASER_SOCKET
+ FAR struct netdev_lowerhalf_s *netdev = NULL;
+#endif
+ FAR struct kvaser_driver_s *priv = NULL;
+ uint8_t i = 0;
+ int ret;
#ifdef CONFIG_CAN_KVASER_CHARDEV
- uint8_t count;
- char devpath[PATH_MAX];
+ uint8_t count;
+ char devpath[PATH_MAX];
#endif
/* Allocate the interface structure */
@@ -1747,15 +1651,13 @@ static int kvaser_probe(FAR struct pci_device_s *dev)
#endif
#ifdef CONFIG_CAN_KVASER_SOCKET
- /* Initialize the driver structure */
+ netdev = &priv->sja[i].dev;
- priv->sja[i].dev.d_ifup = kvaser_sock_ifup;
- priv->sja[i].dev.d_ifdown = kvaser_sock_ifdown;
- priv->sja[i].dev.d_txavail = kvaser_sock_txavail;
-# ifdef CONFIG_NETDEV_IOCTL
- priv->sja[i].dev.d_ioctl = kvaser_sock_ioctl;
-# endif
- priv->sja[i].dev.d_private = &priv->sja[i];
+ /* Register the network device */
+
+ netdev->quota[NETPKT_TX] = KVASER_TX_QUOTA;
+ netdev->quota[NETPKT_RX] = KVASER_RX_QUOTA;
+ netdev->ops = &g_kvaser_net_ops;
/* Put the interface in the down state. This usually amounts to
* resetting the device and/or calling kvaser_sock_ifdown().
@@ -1763,11 +1665,9 @@ static int kvaser_probe(FAR struct pci_device_s *dev)
kvaser_sock_ifdown(&priv->sja[i].dev);
- /* Register the device with the OS so that socket IOCTLs can be
- * performed
- */
+ /* Register the network interface. */
- ret = netdev_register(&priv->sja[i].dev, NET_LL_CAN);
+ ret = netdev_lower_register(netdev, NET_LL_CAN);
if (ret < 0)
{
pcierr("ERROR: failed to register count=%d, %d\n", i, ret);
@@ -1784,7 +1684,8 @@ errout:
if (priv->sja[i].pcidev)
{
#ifdef CONFIG_CAN_KVASER_SOCKET
- netdev_unregister(&priv->sja[i].dev);
+ netdev = &priv->sja[i].dev;
+ netdev_lower_unregister(netdev);
#endif
#ifdef CONFIG_CAN_KVASER_CHARDEV