drivers/can: optimize can driver reader side
Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
This commit is contained in:
parent
e2114378b9
commit
c3bae60c57
@ -184,7 +184,7 @@ static int can_bittiming(struct up_dev_s *priv);
|
||||
static const struct can_ops_s g_canops =
|
||||
{
|
||||
.co_reset = can_reset,
|
||||
.co_setup = can_setup,
|
||||
.co_setup = can_setup,
|
||||
.co_shutdown = can_shutdown,
|
||||
.co_rxint = can_rxint,
|
||||
.co_txint = can_txint,
|
||||
|
@ -392,7 +392,6 @@ static int can_open(FAR struct file *filep)
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct can_dev_s *dev = inode->i_private;
|
||||
irqstate_t flags;
|
||||
int tmp;
|
||||
int ret;
|
||||
|
||||
/* If the port is the middle of closing, wait until the close is finished */
|
||||
@ -407,46 +406,48 @@ static int can_open(FAR struct file *filep)
|
||||
* for this device, then perform hardware initialization.
|
||||
*/
|
||||
|
||||
if (list_is_empty(&dev->cd_readers))
|
||||
caninfo("ocount: %u\n", dev->cd_crefs);
|
||||
|
||||
if (dev->cd_crefs >= 255)
|
||||
{
|
||||
caninfo("ocount: %d\n", 0);
|
||||
/* Limit to no more than 255 opens */
|
||||
|
||||
flags = enter_critical_section();
|
||||
ret = dev_setup(dev);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Mark the FIFOs empty */
|
||||
|
||||
dev->cd_xmit.tx_head = 0;
|
||||
dev->cd_xmit.tx_queue = 0;
|
||||
dev->cd_xmit.tx_tail = 0;
|
||||
|
||||
/* Finally, Enable the CAN RX interrupt */
|
||||
|
||||
dev_rxint(dev, true);
|
||||
}
|
||||
|
||||
list_add_head(&dev->cd_readers,
|
||||
(FAR struct list_node *)init_can_reader(filep));
|
||||
|
||||
leave_critical_section(flags);
|
||||
ret = -EMFILE;
|
||||
goto errout;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = list_length(&dev->cd_readers);
|
||||
caninfo("ocount: %d\n", tmp);
|
||||
flags = enter_critical_section();
|
||||
|
||||
if (tmp >= 255)
|
||||
if (dev->cd_crefs == 0)
|
||||
{
|
||||
/* Limit to no more than 255 opens */
|
||||
ret = dev_setup(dev);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Mark the FIFOs empty */
|
||||
|
||||
ret = -EMFILE;
|
||||
goto errout;
|
||||
dev->cd_xmit.tx_head = 0;
|
||||
dev->cd_xmit.tx_queue = 0;
|
||||
dev->cd_xmit.tx_tail = 0;
|
||||
|
||||
/* Finally, Enable the CAN RX interrupt */
|
||||
|
||||
dev_rxint(dev, true);
|
||||
}
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
list_add_head(&dev->cd_readers,
|
||||
(FAR struct list_node *)init_can_reader(filep));
|
||||
if (ret == OK)
|
||||
{
|
||||
dev->cd_crefs++;
|
||||
|
||||
/* Update the reader list only if driver was open for reading */
|
||||
|
||||
if ((filep->f_oflags & O_RDOK) != 0)
|
||||
{
|
||||
list_add_head(&dev->cd_readers,
|
||||
(FAR struct list_node *)init_can_reader(filep));
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
@ -475,7 +476,7 @@ static int can_close(FAR struct file *filep)
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_DEBUG_CAN_INFO
|
||||
caninfo("ocount: %d\n", list_length(&dev->cd_readers));
|
||||
caninfo("ocount: %u\n", dev->cd_crefs);
|
||||
#endif
|
||||
|
||||
ret = can_takesem(&dev->cd_closesem);
|
||||
@ -496,10 +497,11 @@ static int can_close(FAR struct file *filep)
|
||||
}
|
||||
|
||||
filep->f_priv = NULL;
|
||||
dev->cd_crefs--;
|
||||
|
||||
/* Uninitialize the driver if there are no more readers */
|
||||
/* De-initialize the driver if there are no more readers */
|
||||
|
||||
if (!list_is_empty(&dev->cd_readers))
|
||||
if (dev->cd_crefs > 0)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
@ -544,7 +546,7 @@ errout:
|
||||
static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct can_reader_s *reader = NULL;
|
||||
FAR struct can_reader_s *reader;
|
||||
FAR struct can_rxfifo_s *fifo;
|
||||
size_t nread;
|
||||
irqstate_t flags;
|
||||
@ -563,11 +565,25 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
|
||||
|
||||
if (buflen >= CAN_MSGLEN(0))
|
||||
{
|
||||
DEBUGASSERT(filep->f_priv != NULL);
|
||||
reader = (FAR struct can_reader_s *)filep->f_priv;
|
||||
|
||||
fifo = &reader->fifo;
|
||||
|
||||
/* Interrupts must be disabled while accessing the cd_recv FIFO */
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
#ifdef CONFIG_CAN_ERRORS
|
||||
|
||||
/* Check for reader fifo overflow */
|
||||
|
||||
if (fifo->rx_overflow)
|
||||
{
|
||||
dev->cd_error |= CAN_ERROR5_RXOVERFLOW;
|
||||
fifo->rx_overflow = false;
|
||||
}
|
||||
|
||||
/* Check for internal errors */
|
||||
|
||||
if (dev->cd_error != 0)
|
||||
@ -604,12 +620,7 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
|
||||
}
|
||||
#endif /* CONFIG_CAN_ERRORS */
|
||||
|
||||
DEBUGASSERT(filep->f_priv != NULL);
|
||||
reader = (FAR struct can_reader_s *)filep->f_priv;
|
||||
|
||||
fifo = &reader->fifo;
|
||||
|
||||
if (filep->f_oflags & O_NONBLOCK)
|
||||
if ((filep->f_oflags & O_NONBLOCK) != 0)
|
||||
{
|
||||
ret = nxsem_trywait(&fifo->rx_sem);
|
||||
}
|
||||
@ -1229,12 +1240,13 @@ int can_register(FAR const char *path, FAR struct can_dev_s *dev)
|
||||
|
||||
/* Initialize the CAN device structure */
|
||||
|
||||
list_initialize(&dev->cd_readers);
|
||||
dev->cd_ntxwaiters = 0;
|
||||
dev->cd_crefs = 0;
|
||||
dev->cd_npendrtr = 0;
|
||||
dev->cd_ntxwaiters = 0;
|
||||
#ifdef CONFIG_CAN_ERRORS
|
||||
dev->cd_error = 0;
|
||||
#endif
|
||||
list_initialize(&dev->cd_readers);
|
||||
|
||||
/* Initialize semaphores */
|
||||
|
||||
@ -1427,7 +1439,7 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
|
||||
{
|
||||
/* Report rx overflow error */
|
||||
|
||||
dev->cd_error |= CAN_ERROR5_RXOVERFLOW;
|
||||
fifo->rx_overflow = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -498,6 +498,9 @@ struct can_rxfifo_s
|
||||
|
||||
sem_t rx_sem;
|
||||
|
||||
#ifdef CONFIG_CAN_ERRORS
|
||||
bool rx_overflow; /* Indicates the RX FIFO overflow event */
|
||||
#endif
|
||||
uint8_t rx_head; /* Index to the head [IN] in the circular buffer */
|
||||
uint8_t rx_tail; /* Index to the tail [OUT] in the circular buffer */
|
||||
/* Circular buffer of CAN messages */
|
||||
@ -606,12 +609,13 @@ struct can_reader_s
|
||||
|
||||
struct can_dev_s
|
||||
{
|
||||
uint8_t cd_crefs; /* References counts on number of opens */
|
||||
uint8_t cd_npendrtr; /* Number of pending RTR messages */
|
||||
volatile uint8_t cd_ntxwaiters; /* Number of threads waiting to enqueue a message */
|
||||
struct list_node cd_readers; /* List of readers */
|
||||
#ifdef CONFIG_CAN_ERRORS
|
||||
uint8_t cd_error; /* Flags to indicate internal device errors */
|
||||
#endif
|
||||
struct list_node cd_readers; /* List of readers */
|
||||
sem_t cd_closesem; /* Locks out new opens while close is in progress */
|
||||
sem_t cd_pollsem; /* Manages exclusive access to cd_fds[] */
|
||||
struct can_txfifo_s cd_xmit; /* Describes transmit FIFO */
|
||||
|
Loading…
Reference in New Issue
Block a user