drivers/can/ctucanfd_pci.c: refactor to use netdev_uperhalf

refactor ctucanfd_pci.c to use netdev_uperhalf for SocketCAN interface

Signed-off-by: p-szafonimateusz <p-szafonimateusz@xiaomi.com>
This commit is contained in:
p-szafonimateusz 2025-08-28 14:09:54 +02:00 committed by Xiang Xiao
parent 9014af9ae7
commit f84d34a57b

View file

@ -40,8 +40,7 @@
#endif
#ifdef CONFIG_CAN_CTUCANFD_SOCKET
# include <nuttx/wqueue.h>
# include <nuttx/net/netdev.h>
# include <nuttx/net/netdev_lowerhalf.h>
# include <nuttx/net/can.h>
#endif
@ -76,19 +75,19 @@
/* SocketCAN specific */
#ifdef CONFIG_CAN_CTUCANFD_SOCKET
# define CTUCANFD_POOL_SIZE 1
/* Work queue support is required. */
# if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
# define CTUCANFD_TX_QUOTA 1
# define CTUCANFD_RX_QUOTA 1
# if CONFIG_IOB_NBUFFERS < (CTUCANFD_RX_QUOTA + CTUCANFD_TX_QUOTA)
# error CONFIG_IOB_NBUFFERS must be > (CTUCANFD_RX_QUOTA + CTUCANFD_TX_QUOTA)
# endif
# define CTUCANFD_CANWORK LPWORK
#endif /* CONFIG_CAN_CTUCANFD_SOCKET */
#ifndef CONFIG_NET_CAN_ERRORS
# define CTUCANFD_SOCK_RXINT (CTUCANFD_INT_RBNEI)
#else
# define CTUCANFD_SOCK_RXINT (CTUCANFD_INT_RBNEI | CTUCANFD_INT_ERR)
#endif
/*****************************************************************************
* Private Types
*****************************************************************************/
@ -102,18 +101,9 @@ struct ctucanfd_can_s
#endif
#ifdef CONFIG_CAN_CTUCANFD_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 */
# ifdef CONFIG_NET_CAN_CANFD
struct canfd_frame tx_pool[CTUCANFD_POOL_SIZE];
struct canfd_frame rx_pool[CTUCANFD_POOL_SIZE];
# else
struct can_frame tx_pool[CTUCANFD_POOL_SIZE];
struct can_frame rx_pool[CTUCANFD_POOL_SIZE];
# endif
struct netdev_lowerhalf_s dev;
#endif
FAR struct pci_device_s *pcidev;
@ -135,12 +125,6 @@ struct ctucanfd_driver_s
FAR struct pci_device_s *pcidev;
int irq;
uintptr_t base;
#ifdef CONFIG_CAN_CTUCANFD_SOCKET
/* For deferring interrupt work to the wq */
struct work_s irqwork;
#endif
};
/*****************************************************************************
@ -162,9 +146,9 @@ static void ctucanfd_shutdown(FAR struct ctucanfd_can_s *priv);
static void ctucanfd_setup(FAR struct ctucanfd_can_s *priv);
static void ctucanfd_rxint(FAR struct ctucanfd_can_s *priv, bool enable);
static void ctucanfd_txint(FAR struct ctucanfd_can_s *priv, bool enable);
static bool ctucanfd_txready(FAR struct ctucanfd_can_s *priv);
#ifdef CONFIG_CAN_CTUCANFD_CHARDEV
/* CAN character device methods */
static void ctucanfd_chrdev_reset(FAR struct can_dev_s *dev);
@ -187,21 +171,22 @@ static void ctucanfd_chardev_interrupt(FAR struct ctucanfd_driver_s *priv);
#ifdef CONFIG_CAN_CTUCANFD_SOCKET
/* SocketCAN methods */
static int ctucanfd_sock_ifup(FAR struct net_driver_s *dev);
static int ctucanfd_sock_ifdown(FAR struct net_driver_s *dev);
static void ctucanfd_sock_txavail_work(FAR void *arg);
static int ctucanfd_sock_txavail(FAR struct net_driver_s *dev);
static int ctucanfd_sock_ifup(FAR struct netdev_lowerhalf_s *dev);
static int ctucanfd_sock_ifdown(FAR struct netdev_lowerhalf_s *dev);
static int ctucanfd_sock_transmit(FAR struct netdev_lowerhalf_s *dev,
FAR netpkt_t *pkt);
static FAR netpkt_t *ctucanfd_sock_recv(FAR struct netdev_lowerhalf_s *dev);
# ifdef CONFIG_NETDEV_IOCTL
static int ctucanfd_sock_ioctl(FAR struct net_driver_s *dev, int cmd,
static int ctucanfd_sock_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd,
unsigned long arg);
# endif
static int ctucanfd_sock_txpoll(FAR struct net_driver_s *dev);
static int ctucanfd_sock_send(FAR struct ctucanfd_can_s *priv);
static void ctucanfd_sock_receive(FAR struct ctucanfd_can_s *priv);
static void ctucanfd_sock_interrupt_work(FAR void *arg);
# ifdef CONFIG_NET_CAN_ERRORS
static FAR netpkt_t *ctucanfd_sock_error(FAR struct netdev_lowerhalf_s *dev);
# endif
static void ctucanfd_sock_interrupt(FAR struct ctucanfd_driver_s *priv);
#endif
/* Interrupts */
@ -234,6 +219,19 @@ static const struct can_ops_s g_ctucanfd_can_ops =
};
#endif
#ifdef CONFIG_CAN_CTUCANFD_SOCKET
static const struct netdev_ops_s g_ctucanfd_net_ops =
{
.ifup = ctucanfd_sock_ifup,
.ifdown = ctucanfd_sock_ifdown,
.transmit = ctucanfd_sock_transmit,
.receive = ctucanfd_sock_recv,
#ifdef CONFIG_NETDEV_IOCTL
.ioctl = ctucanfd_sock_ioctl,
#endif
};
#endif
static const struct pci_device_id_s g_ctucanfd_id_table[] =
{
{
@ -385,28 +383,6 @@ static void ctucanfd_txint(FAR struct ctucanfd_can_s *priv, bool enable)
}
}
/*****************************************************************************
* Name: ctucanfd_txready
*****************************************************************************/
static bool ctucanfd_txready(FAR struct ctucanfd_can_s *priv)
{
uint32_t regval;
int i;
regval = ctucanfd_getreg(priv, CTUCANFD_TXSTAT);
for (i = 0; i < priv->txbufcnt; i++)
{
if (CTUCANFD_TXSTAT_GET(regval, i) == CTUCANFD_TXSTAT_ETY)
{
return true;
}
}
return false;
}
#ifdef CONFIG_CAN_CTUCANFD_CHARDEV
/*****************************************************************************
* Name: ctucanfd_chrdev_reset
@ -689,8 +665,20 @@ static int ctucanfd_chrdev_send(FAR struct can_dev_s *dev,
static bool ctucanfd_chrdev_txready(FAR struct can_dev_s *dev)
{
FAR struct ctucanfd_can_s *priv = (FAR struct ctucanfd_can_s *)dev;
uint32_t regval;
int i;
return ctucanfd_txready(priv);
regval = ctucanfd_getreg(priv, CTUCANFD_TXSTAT);
for (i = 0; i < priv->txbufcnt; i++)
{
if (CTUCANFD_TXSTAT_GET(regval, i) == CTUCANFD_TXSTAT_ETY)
{
return true;
}
}
return false;
}
/*****************************************************************************
@ -998,12 +986,9 @@ static void ctucanfd_chardev_interrupt(FAR struct ctucanfd_driver_s *priv)
*
*****************************************************************************/
static int ctucanfd_sock_ifup(FAR struct net_driver_s *dev)
static int ctucanfd_sock_ifup(FAR struct netdev_lowerhalf_s *dev)
{
FAR struct ctucanfd_can_s *priv =
(FAR struct ctucanfd_can_s *)dev->d_private;
priv->dev.d_buf = (FAR uint8_t *)priv->tx_pool;
FAR struct ctucanfd_can_s *priv = (FAR struct ctucanfd_can_s *)dev;
ctucanfd_reset(priv);
ctucanfd_setup(priv);
@ -1028,10 +1013,9 @@ static int ctucanfd_sock_ifup(FAR struct net_driver_s *dev)
*
*****************************************************************************/
static int ctucanfd_sock_ifdown(FAR struct net_driver_s *dev)
static int ctucanfd_sock_ifdown(FAR struct netdev_lowerhalf_s *dev)
{
FAR struct ctucanfd_can_s *priv =
(FAR struct ctucanfd_can_s *)dev->d_private;
FAR struct ctucanfd_can_s *priv = (FAR struct ctucanfd_can_s *)dev;
ctucanfd_txint(priv, false);
ctucanfd_rxint(priv, false);
@ -1043,88 +1027,6 @@ static int ctucanfd_sock_ifdown(FAR struct net_driver_s *dev)
return OK;
}
/*****************************************************************************
* Name: ctucanfd_sock_txavail_work
*
* Description:
* Perform an out-of-cycle poll on the worker thread.
*
* Input Parameters:
* arg - Reference to the NuttX driver state structure (cast to void*)
*
* Returned Value:
* None
*
* Assumptions:
* Called on the higher priority worker thread.
*
*****************************************************************************/
static void ctucanfd_sock_txavail_work(FAR void *arg)
{
FAR struct ctucanfd_can_s *priv = (FAR struct ctucanfd_can_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 (ctucanfd_txready(priv))
{
/* No, there is space for another transfer. Poll the network for
* new XMIT data.
*/
devif_poll(&priv->dev, ctucanfd_sock_txpoll);
}
}
net_unlock();
}
/*****************************************************************************
* Name: ctucanfd_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 ctucanfd_sock_txavail(FAR struct net_driver_s *dev)
{
FAR struct ctucanfd_can_s *priv =
(FAR struct ctucanfd_can_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. */
ctucanfd_sock_txavail_work(priv);
}
return OK;
}
# ifdef CONFIG_NETDEV_IOCTL
/*****************************************************************************
* Name: ctucanfd_sock_ioctl
@ -1144,8 +1046,8 @@ static int ctucanfd_sock_txavail(FAR struct net_driver_s *dev)
*
*****************************************************************************/
static int ctucanfd_sock_ioctl(FAR struct net_driver_s *dev, int cmd,
unsigned long arg)
static int ctucanfd_sock_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd,
unsigned long arg)
{
return -ENOTTY;
}
@ -1153,74 +1055,19 @@ static int ctucanfd_sock_ioctl(FAR struct net_driver_s *dev, int cmd,
# endif /* CONFIG_NETDEV_IOCTL */
/*****************************************************************************
* Name: ctucanfd_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.
*
* Name: ctucanfd_sock_transmit
*****************************************************************************/
static int ctucanfd_sock_txpoll(FAR struct net_driver_s *dev)
static int ctucanfd_sock_transmit(FAR struct netdev_lowerhalf_s *dev,
FAR netpkt_t *pkt)
{
FAR struct ctucanfd_can_s *priv =
(FAR struct ctucanfd_can_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 */
ctucanfd_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 (!ctucanfd_txready(priv))
{
return -EBUSY;
}
}
/* If zero is returned, the polling will continue until all connections
* have been examined.
*/
return 0;
}
/*****************************************************************************
* Name: ctucanfd_sock_send
*****************************************************************************/
static int ctucanfd_sock_send(FAR struct ctucanfd_can_s *priv)
{
union ctucanfd_frame_fmt_u fmt;
union ctucanfd_frame_id_u id;
uint32_t regval;
uint32_t offset;
int txidx;
int i;
FAR struct ctucanfd_can_s *priv = (FAR struct ctucanfd_can_s *)dev;
union ctucanfd_frame_fmt_u fmt;
union ctucanfd_frame_id_u id;
uint32_t regval;
uint32_t offset;
int txidx;
int i;
/* Get TX empty buffer */
@ -1250,10 +1097,10 @@ static int ctucanfd_sock_send(FAR struct ctucanfd_can_s *priv)
/* CAN 2.0 or CAN FD */
if (priv->dev.d_len == sizeof(struct can_frame))
if (netpkt_getdatalen(dev, pkt) == sizeof(struct can_frame))
{
FAR struct can_frame *frame = frame =
(FAR struct can_frame *)priv->dev.d_buf;
(FAR struct can_frame *)netpkt_getdata(dev, pkt);
/* Set up the DLC */
@ -1293,7 +1140,7 @@ static int ctucanfd_sock_send(FAR struct ctucanfd_can_s *priv)
else /* CAN FD frame */
{
FAR struct canfd_frame *frame =
(FAR struct canfd_frame *)priv->dev.d_buf;
(FAR struct canfd_frame *)netpkt_getdata(dev, pkt);
/* CAN FD frame */
@ -1342,203 +1189,188 @@ static int ctucanfd_sock_send(FAR struct ctucanfd_can_s *priv)
regval = CTUCANFD_TXCMD_TXCR + (1 << (CTUCANFD_TXCMD_TXB_SHIFT + txidx));
ctucanfd_putreg(priv, CTUCANFD_TXINFOCMD, regval);
/* All is done - free packet */
netpkt_free(dev, pkt, NETPKT_TX);
return OK;
}
/*****************************************************************************
* Name: ctucanfd_sock_receive
* Name: ctucanfd_sock_recv
*****************************************************************************/
static void ctucanfd_sock_receive(FAR struct ctucanfd_can_s *priv)
static FAR netpkt_t *ctucanfd_sock_recv(FAR struct netdev_lowerhalf_s *dev)
{
FAR struct ctucanfd_can_s *priv = (FAR struct ctucanfd_can_s *)dev;
FAR netpkt_t *pkt = NULL;
FAR struct ctucanfd_frame_s *rxframe;
uint32_t buff[sizeof(struct ctucanfd_frame_s) / 4];
int i = 0;
uint16_t frc = 0;
uint32_t regval = 0;
uint8_t bytes;
/* Get frame count */
/* Read frame if RX buffer not empty */
regval = ctucanfd_getreg(priv, CTUCANFD_RXSETSTAT);
frc = (regval & CTUCANFD_RXSTAT_RXFRC_MASK) >> CTUCANFD_RXSTAT_RXFRC_SHIFT;
/* Read frames */
while (frc-- > 0)
if ((regval & CTUCANFD_RXSTAT_RXE) != 0)
{
/* We use a pointer to buffer to avoid an unaligned pointer
* compiler errors
*/
/* Re-enable RX interrupts if no more messages to read */
rxframe = (struct ctucanfd_frame_s *)&buff;
ctucanfd_rxint(priv, true);
/* RX buffer in automatic mode */
#ifdef CONFIG_NET_CAN_ERRORS
/* Check for errors */
buff[0] = ctucanfd_getreg(priv, CTUCANFD_RXDATA);
return ctucanfd_sock_error(dev);
#else
return NULL;
#endif
}
/* Read the rest of data */
/* Allocate packet */
for (i = 0; i < rxframe->fmt.rwcnt; i++)
{
buff[i + 1] = ctucanfd_getreg(priv, CTUCANFD_RXDATA);
}
pkt = netpkt_alloc(dev, NETPKT_RX);
if (!pkt)
{
canerr("alloc pkt_new failed\n");
return NULL;
}
/* CAN 2.0 or CAN FD */
/* We use a pointer to buffer to avoid an unaligned pointer
* compiler errors
*/
rxframe = (struct ctucanfd_frame_s *)&buff;
/* RX buffer in automatic mode */
buff[0] = ctucanfd_getreg(priv, CTUCANFD_RXDATA);
/* Read the rest of data */
for (i = 0; i < rxframe->fmt.rwcnt; i++)
{
buff[i + 1] = ctucanfd_getreg(priv, CTUCANFD_RXDATA);
}
/* CAN 2.0 or CAN FD */
#ifdef CONFIG_NET_CAN_CANFD
if (rxframe->fmt.fdf)
{
struct canfd_frame *frame = (struct canfd_frame *)priv->rx_pool;
if (rxframe->fmt.fdf)
{
struct canfd_frame *frame;
/* Get the DLC */
netpkt_setdatalen(dev, pkt, sizeof(struct canfd_frame));
frame = (FAR struct canfd_frame *)netpkt_getdata(dev, pkt);
frame->len = can_dlc2bytes(rxframe->fmt.dlc);
/* Get the DLC */
frame->len = can_dlc2bytes(rxframe->fmt.dlc);
#ifdef CONFIG_NET_CAN_EXTID
/* Get the CAN identifier. */
/* Get the CAN identifier. */
if (rxframe->fmt.ide)
{
frame->can_id = rxframe->id.id_ext;
frame->can_id |= CAN_EFF_FLAG;
}
else
{
frame->can_id = rxframe->id.id;
}
#else
if (rxframe->fmt.ide)
{
canerr("ERROR: Received message with extended"
" identifier. Dropped\n");
continue;
}
frame->can_id = rxframe->id.id;
#endif
/* Extract the RTR bit */
if (rxframe->fmt.rtr)
{
frame->can_id |= CAN_RTR_FLAG;
}
/* Get CANFD flags */
frame->flags = 0;
if (rxframe->fmt.esi_rsv)
{
frame->flags |= CANFD_ESI;
}
if (rxframe->fmt.brs)
{
frame->flags |= CANFD_BRS;
}
/* Get data */
bytes = can_dlc2bytes(rxframe->fmt.dlc);
for (i = 0; i < bytes; i++)
{
frame->data[i] = rxframe->data[i];
}
/* Copy the buffer pointer to priv->dev.. Set amount of data
* in priv->dev.d_len
*/
priv->dev.d_len = sizeof(struct canfd_frame);
priv->dev.d_buf = (FAR uint8_t *)frame;
/* Send to socket interface */
NETDEV_RXPACKETS(&priv->dev);
can_input(&priv->dev);
/* 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.
*/
priv->dev.d_buf = (FAR uint8_t *)priv->tx_pool;
if (rxframe->fmt.ide)
{
frame->can_id = rxframe->id.id_ext;
frame->can_id |= CAN_EFF_FLAG;
}
else
#endif
{
FAR struct can_frame *frame =
(FAR struct can_frame *)priv->rx_pool;
/* Get the DLC */
frame->can_dlc = rxframe->fmt.dlc;
#ifdef CONFIG_NET_CAN_EXTID
/* Get the CAN identifier. */
if (rxframe->fmt.ide)
{
frame->can_id = rxframe->id.id_ext;
frame->can_id |= CAN_EFF_FLAG;
}
else
{
frame->can_id = rxframe->id.id;
}
#else
if (rxframe->fmt.ide)
{
canerr("ERROR: Received message with extended"
" identifier. Dropped\n");
continue;
}
frame->can_id = rxframe->id.id;
}
#else
if (rxframe->fmt.ide)
{
canerr("ERROR: Received message with extended"
" identifier. Dropped\n");
continue;
}
frame->can_id = rxframe->id.id;
#endif
/* Extract the RTR bit */
/* Extract the RTR bit */
if (rxframe->fmt.rtr)
{
frame->can_id |= CAN_RTR_FLAG;
}
if (rxframe->fmt.rtr)
{
frame->can_id |= CAN_RTR_FLAG;
}
/* Get data */
/* Get CANFD flags */
for (i = 0; i < rxframe->fmt.dlc; i++)
{
frame->data[i] = rxframe->data[i];
}
frame->flags = 0;
/* Copy the buffer pointer to priv->dev.. Set amount of data
* in priv->dev.d_len
*/
if (rxframe->fmt.esi_rsv)
{
frame->flags |= CANFD_ESI;
}
priv->dev.d_len = sizeof(struct can_frame);
priv->dev.d_buf = (FAR uint8_t *)frame;
if (rxframe->fmt.brs)
{
frame->flags |= CANFD_BRS;
}
/* Send to socket interface */
/* Get data */
NETDEV_RXPACKETS(&priv->dev);
can_input(&priv->dev);
/* 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.
*/
priv->dev.d_buf = (FAR uint8_t *)priv->tx_pool;
bytes = can_dlc2bytes(rxframe->fmt.dlc);
for (i = 0; i < bytes; i++)
{
frame->data[i] = rxframe->data[i];
}
}
else
#endif
{
FAR struct can_frame *frame;
netpkt_setdatalen(dev, pkt, sizeof(struct can_frame));
frame = (FAR struct can_frame *)netpkt_getdata(dev, pkt);
/* Get the DLC */
frame->can_dlc = rxframe->fmt.dlc;
#ifdef CONFIG_NET_CAN_EXTID
/* Get the CAN identifier. */
if (rxframe->fmt.ide)
{
frame->can_id = rxframe->id.id_ext;
frame->can_id |= CAN_EFF_FLAG;
}
else
{
frame->can_id = rxframe->id.id;
}
#else
if (rxframe->fmt.ide)
{
canerr("ERROR: Received message with extended"
" identifier. Dropped\n");
continue;
}
frame->can_id = rxframe->id.id;
#endif
/* Extract the RTR bit */
if (rxframe->fmt.rtr)
{
frame->can_id |= CAN_RTR_FLAG;
}
/* Get data */
for (i = 0; i < rxframe->fmt.dlc; i++)
{
frame->data[i] = rxframe->data[i];
}
}
return pkt;
}
#ifdef CONFIG_NET_CAN_ERRORS
@ -1546,11 +1378,31 @@ static void ctucanfd_sock_receive(FAR struct ctucanfd_can_s *priv)
* Name: ctucanfd_sock_error
*****************************************************************************/
static void ctucanfd_sock_error(FAR struct ctucanfd_can_s *priv,
uint32_t stat)
static FAR netpkt_t *ctucanfd_sock_error(FAR struct netdev_lowerhalf_s *dev)
{
FAR struct can_frame *frame = NULL;
uint16_t errbits = 0;
FAR struct ctucanfd_can_s *priv = (FAR struct ctucanfd_can_s *) dev;
FAR struct can_frame *frame = NULL;
FAR netpkt_t *pkt = NULL;
uint16_t errbits = 0;
uint32_t stat = 0;
stat = ctucanfd_getreg(priv, CTUCANFD_INTSTAT);
if ((stat & CTUCANFD_INT_ERR) == 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 */
@ -1580,56 +1432,27 @@ static void ctucanfd_sock_error(FAR struct ctucanfd_can_s *priv,
errbits |= CAN_ERR_BUSERROR;
}
if (errbits != 0)
{
frame = (FAR struct can_frame *)priv->rx_pool;
canerr("ERROR: errbits = %08" PRIx16 "\n", errbits);
canerr("ERROR: errbits = %08" PRIx16 "\n", errbits);
/* Copy frame */
/* Copy frame */
frame->can_id = errbits;
frame->can_dlc = CAN_ERR_DLC;
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);
can_input(&priv->dev);
/* 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.
*/
priv->dev.d_buf = (FAR uint8_t *)priv->tx_pool;
net_unlock();
}
return pkt;
}
#endif
/*****************************************************************************
* Name: ctucanfd_sock_interrupt_work
* Name: ctucanfd_sock_interrupt
*****************************************************************************/
static void ctucanfd_sock_interrupt_work(FAR void *arg)
static void ctucanfd_sock_interrupt(FAR struct ctucanfd_driver_s *priv)
{
FAR struct ctucanfd_driver_s *priv = arg;
uint32_t stat = 0;
uint32_t regval = 0;
int i = 0;
int txidx = 0;
uint32_t stat = 0;
uint32_t regval = 0;
int i = 0;
int txidx = 0;
for (i = 0; i < priv->count; i++)
{
@ -1639,11 +1462,11 @@ static void ctucanfd_sock_interrupt_work(FAR void *arg)
continue;
}
/* RX buffer not empty interrupt */
/* RX ready */
if (stat & CTUCANFD_INT_RBNEI)
if (stat & CTUCANFD_SOCK_RXINT)
{
ctucanfd_sock_receive(&priv->devs[i]);
netdev_lower_rxready(&priv->devs[i].dev);
}
/* Transmit interrupt */
@ -1657,15 +1480,7 @@ static void ctucanfd_sock_interrupt_work(FAR void *arg)
if (CTUCANFD_TXSTAT_GET(regval, txidx) ==
CTUCANFD_TXSTAT_TOK)
{
NETDEV_TXDONE(&priv->devs[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->devs[i].dev, ctucanfd_sock_txpoll);
net_unlock();
netdev_lower_txdone(&priv->devs[i].dev);
/* Mark buffer as empty */
@ -1676,22 +1491,14 @@ static void ctucanfd_sock_interrupt_work(FAR void *arg)
}
}
#ifdef CONFIG_NET_CAN_ERRORS
/* Handle errors */
if (stat & CTUCANFD_INT_ERR)
{
ctucanfd_sock_error(&priv->devs[i], stat);
}
#endif
/* Clear interrupts */
ctucanfd_putreg(&priv->devs[i], CTUCANFD_INTSTAT, stat);
/* Re-enable RX/TX interrupts */
/* Re-enable TX interrupts.
* NOTE: RX interrupts are re-enabled in ctucanfd_sock_recv.
*/
ctucanfd_rxint(&priv->devs[i], true);
ctucanfd_txint(&priv->devs[i], true);
}
}
@ -1744,10 +1551,9 @@ static int ctucanfd_interrupt(int irq, FAR void *context, FAR void *arg)
#endif
#ifdef CONFIG_CAN_CTUCANFD_SOCKET
/* Derefer SocketCAN interrupt to work queue */
/* Handle SocketCAN interrupt */
work_queue(CTUCANFD_CANWORK, &priv->irqwork,
ctucanfd_sock_interrupt_work, priv, 0);
ctucanfd_sock_interrupt(priv);
#endif
return OK;
@ -1806,12 +1612,15 @@ static uint8_t ctucanfd_ctucanfd_probe(FAR struct ctucanfd_driver_s *priv)
static int ctucanfd_probe(FAR struct pci_device_s *dev)
{
FAR struct ctucanfd_driver_s *priv = NULL;
uint8_t i = 0;
int ret;
#ifdef CONFIG_CAN_CTUCANFD_SOCKET
FAR struct netdev_lowerhalf_s *netdev = NULL;
#endif
FAR struct ctucanfd_driver_s *priv = NULL;
uint8_t i = 0;
int ret;
#ifdef CONFIG_CAN_CTUCANFD_CHARDEV
uint8_t count;
char devpath[PATH_MAX];
uint8_t count;
char devpath[PATH_MAX];
#endif
/* Allocate the interface structure */
@ -1918,15 +1727,13 @@ static int ctucanfd_probe(FAR struct pci_device_s *dev)
#endif
#ifdef CONFIG_CAN_CTUCANFD_SOCKET
/* Initialize the driver structure */
netdev = &priv->devs[i].dev;
priv->devs[i].dev.d_ifup = ctucanfd_sock_ifup;
priv->devs[i].dev.d_ifdown = ctucanfd_sock_ifdown;
priv->devs[i].dev.d_txavail = ctucanfd_sock_txavail;
# ifdef CONFIG_NETDEV_IOCTL
priv->devs[i].dev.d_ioctl = ctucanfd_sock_ioctl;
# endif
priv->devs[i].dev.d_private = &priv->devs[i];
/* Register the network device */
netdev->quota[NETPKT_TX] = CTUCANFD_TX_QUOTA;
netdev->quota[NETPKT_RX] = CTUCANFD_RX_QUOTA;
netdev->ops = &g_ctucanfd_net_ops;
/* Put the interface in the down state. This usually amounts to
* resetting the device and/or calling ctucanfd_sock_ifdown().
@ -1934,11 +1741,9 @@ static int ctucanfd_probe(FAR struct pci_device_s *dev)
ctucanfd_sock_ifdown(&priv->devs[i].dev);
/* Register the device with the OS so that socket IOCTLs can be
* performed
*/
/* Register the network interface. */
ret = netdev_register(&priv->devs[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);
@ -1955,7 +1760,8 @@ errout:
if (priv->devs[i].pcidev)
{
#ifdef CONFIG_CAN_CTUCANFD_SOCKET
netdev_unregister(&priv->devs[i].dev);
netdev = &priv->devs[i].dev;
netdev_lower_unregister(netdev);
#endif
#ifdef CONFIG_CAN_CTUCANFD_CHARDEV