This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new c3bae60  drivers/can: optimize can driver reader side
c3bae60 is described below

commit c3bae60c57db5f8033a9017efc2dd5f8d65bfa86
Author: Petro Karashchenko <petro.karashche...@gmail.com>
AuthorDate: Fri Mar 11 16:46:20 2022 +0100

    drivers/can: optimize can driver reader side
    
    Signed-off-by: Petro Karashchenko <petro.karashche...@gmail.com>
---
 arch/arm/src/lpc43xx/lpc43_can.c |  2 +-
 drivers/can/can.c                | 96 ++++++++++++++++++++++------------------
 include/nuttx/can/can.h          |  6 ++-
 3 files changed, 60 insertions(+), 44 deletions(-)

diff --git a/arch/arm/src/lpc43xx/lpc43_can.c b/arch/arm/src/lpc43xx/lpc43_can.c
index f41c0b6..249384f 100644
--- a/arch/arm/src/lpc43xx/lpc43_can.c
+++ b/arch/arm/src/lpc43xx/lpc43_can.c
@@ -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,
diff --git a/drivers/can/can.c b/drivers/can/can.c
index 07b8c90..cca1ce8 100644
--- a/drivers/can/can.c
+++ b/drivers/can/can.c
@@ -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 */
 
+      ret = -EMFILE;
+      goto errout;
+    }
+  else
+    {
       flags = enter_critical_section();
-      ret = dev_setup(dev);
-      if (ret >= 0)
+
+      if (dev->cd_crefs == 0)
         {
-          /* Mark the FIFOs empty */
+          ret = dev_setup(dev);
+          if (ret == OK)
+            {
+              /* Mark the FIFOs empty */
 
-          dev->cd_xmit.tx_head  = 0;
-          dev->cd_xmit.tx_queue = 0;
-          dev->cd_xmit.tx_tail  = 0;
+              dev->cd_xmit.tx_head  = 0;
+              dev->cd_xmit.tx_queue = 0;
+              dev->cd_xmit.tx_tail  = 0;
 
-          /* Finally, Enable the CAN RX interrupt */
+              /* Finally, Enable the CAN RX interrupt */
 
-          dev_rxint(dev, true);
+              dev_rxint(dev, true);
+            }
         }
 
-      list_add_head(&dev->cd_readers,
-                    (FAR struct list_node *)init_can_reader(filep));
-
-      leave_critical_section(flags);
-    }
-  else
-    {
-      tmp = list_length(&dev->cd_readers);
-      caninfo("ocount: %d\n", tmp);
-
-      if (tmp >= 255)
+      if (ret == OK)
         {
-          /* Limit to no more than 255 opens */
+          dev->cd_crefs++;
 
-          ret = -EMFILE;
-          goto errout;
-        }
+          /* Update the reader list only if driver was open for reading */
 
-      flags = enter_critical_section();
-      list_add_head(&dev->cd_readers,
-                    (FAR struct list_node *)init_can_reader(filep));
+          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
     }
diff --git a/include/nuttx/can/can.h b/include/nuttx/can/can.h
index 0f7db30..0b5d282 100644
--- a/include/nuttx/can/can.h
+++ b/include/nuttx/can/can.h
@@ -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 */

Reply via email to