can: Add more critical section to fix the race condition.

since routines called by IRQ need to be protected in SMP too.

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2024-04-06 14:45:25 +08:00 committed by Lup Yuen Lee
parent 4324970980
commit ccddaa78c9

View File

@ -300,6 +300,8 @@ static int can_close(FAR struct file *filep)
return ret;
}
flags = enter_critical_section(); /* Disable interrupts */
list_for_every(&dev->cd_readers, node)
{
if (((FAR struct can_reader_s *)node) ==
@ -341,11 +343,10 @@ static int can_close(FAR struct file *filep)
/* Free the IRQ and disable the CAN device */
flags = enter_critical_section(); /* Disable interrupts */
dev_shutdown(dev); /* Disable the CAN */
leave_critical_section(flags);
dev_shutdown(dev); /* Disable the CAN */
errout:
leave_critical_section(flags);
nxmutex_unlock(&dev->cd_closelock);
return ret;
}
@ -719,15 +720,10 @@ static inline ssize_t can_rtrread(FAR struct file *filep,
{
FAR struct can_dev_s *dev = filep->f_inode->i_private;
FAR struct can_rtrwait_s *wait = NULL;
irqstate_t flags;
int i;
int sval;
int ret = -ENOMEM;
/* Disable interrupts through this operation */
flags = enter_critical_section();
/* Find an available slot in the pending RTR list */
for (i = 0; i < CONFIG_CAN_NPENDINGRTR; i++)
@ -801,7 +797,6 @@ static inline ssize_t can_rtrread(FAR struct file *filep,
}
}
leave_critical_section(flags);
return ret;
}
@ -815,9 +810,14 @@ static int can_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
FAR struct can_dev_s *dev = inode->i_private;
FAR struct can_reader_s *reader = filep->f_priv;
int ret = OK;
irqstate_t flags;
caninfo("cmd: %d arg: %ld\n", cmd, arg);
/* Disable interrupts through this operation */
flags = enter_critical_section();
/* Handle built-in ioctl commands */
switch (cmd)
@ -913,6 +913,7 @@ static int can_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
break;
}
leave_critical_section(flags);
return ret;
}
@ -1120,6 +1121,7 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
{
FAR struct can_rxfifo_s *fifo;
FAR struct list_node *node;
irqstate_t flags;
int nexttail;
int ret = -ENOMEM;
int i;
@ -1127,6 +1129,8 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
caninfo("ID: %" PRId32 " DLC: %d\n", (uint32_t)hdr->ch_id, hdr->ch_dlc);
flags = enter_critical_section();
/* Check if adding this new message would over-run the drivers ability to
* enqueue read data.
*/
@ -1256,6 +1260,7 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
poll_notify(dev->cd_fds, CONFIG_CAN_NPOLLWAITERS, POLLIN);
}
leave_critical_section(flags);
return ret;
}
@ -1332,10 +1337,13 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
int can_txdone(FAR struct can_dev_s *dev)
{
int ret = -ENOENT;
irqstate_t flags;
caninfo("xmit head: %d queue: %d tail: %d\n",
dev->cd_xmit.tx_head, dev->cd_xmit.tx_queue, dev->cd_xmit.tx_tail);
flags = enter_critical_section();
/* Verify that the xmit FIFO is not empty */
if (dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail)
@ -1379,6 +1387,7 @@ int can_txdone(FAR struct can_dev_s *dev)
}
}
leave_critical_section(flags);
return ret;
}
@ -1443,11 +1452,14 @@ int can_txdone(FAR struct can_dev_s *dev)
int can_txready(FAR struct can_dev_s *dev)
{
int ret = -ENOENT;
irqstate_t flags;
caninfo("xmit head: %d queue: %d tail: %d waiters: %d\n",
dev->cd_xmit.tx_head, dev->cd_xmit.tx_queue, dev->cd_xmit.tx_tail,
dev->cd_ntxwaiters);
flags = enter_critical_section();
/* Verify that the xmit FIFO is not empty. This is safe because interrupts
* are always disabled when calling into can_xmit(); this cannot collide
* with ongoing activity from can_write().
@ -1495,6 +1507,7 @@ int can_txready(FAR struct can_dev_s *dev)
#endif
}
leave_critical_section(flags);
return ret;
}
#endif /* CONFIG_CAN_TXREADY */