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:
parent
4324970980
commit
ccddaa78c9
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user