aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/src/usbh
diff options
context:
space:
mode:
authorDiego Ismirlian <dismirlian (at) google's mail.com>2017-06-05 10:26:17 -0300
committerDiego Ismirlian <dismirlian (at) google's mail.com>2017-06-05 10:26:17 -0300
commitcc347f02ba4c15d150c93bb6b40ede09498c658d (patch)
tree6addcf6a7172304dcf460edd47a7731e99c1f950 /os/hal/src/usbh
parent5ecaf7722b5f1f9d0c41213fc5c129b451302f99 (diff)
downloadChibiOS-Contrib-cc347f02ba4c15d150c93bb6b40ede09498c658d.tar.gz
ChibiOS-Contrib-cc347f02ba4c15d150c93bb6b40ede09498c658d.tar.bz2
ChibiOS-Contrib-cc347f02ba4c15d150c93bb6b40ede09498c658d.zip
Fix possible race condition in FTDI driver stop
Diffstat (limited to 'os/hal/src/usbh')
-rw-r--r--os/hal/src/usbh/hal_usbh_ftdi.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/os/hal/src/usbh/hal_usbh_ftdi.c b/os/hal/src/usbh/hal_usbh_ftdi.c
index 12ed0f9..cce899c 100644
--- a/os/hal/src/usbh/hal_usbh_ftdi.c
+++ b/os/hal/src/usbh/hal_usbh_ftdi.c
@@ -209,7 +209,7 @@ alloc_ok:
}
-static void _stop(USBHFTDIPortDriver *ftdipp);
+static void _stopS(USBHFTDIPortDriver *ftdipp);
static void _ftdi_unload(usbh_baseclassdriver_t *drv) {
osalDbgCheck(drv != NULL);
USBHFTDIDriver *const ftdip = (USBHFTDIDriver *)drv;
@@ -217,7 +217,10 @@ static void _ftdi_unload(usbh_baseclassdriver_t *drv) {
osalMutexLock(&ftdip->mtx);
while (ftdipp) {
- _stop(ftdipp);
+ osalSysLock();
+ _stopS(ftdipp);
+ osalOsRescheduleS();
+ osalSysUnlock();
ftdipp = ftdipp->next;
}
@@ -624,29 +627,27 @@ static const struct FTDIPortDriverVMT async_channel_vmt = {
};
-static void _stop(USBHFTDIPortDriver *ftdipp) {
- osalSysLock();
+static void _stopS(USBHFTDIPortDriver *ftdipp) {
+ if (ftdipp->state != USBHFTDIP_STATE_READY)
+ return;
chVTResetI(&ftdipp->vt);
usbhEPCloseS(&ftdipp->epin);
usbhEPCloseS(&ftdipp->epout);
chThdDequeueAllI(&ftdipp->iq_waiting, Q_RESET);
chThdDequeueAllI(&ftdipp->oq_waiting, Q_RESET);
- osalOsRescheduleS();
ftdipp->state = USBHFTDIP_STATE_ACTIVE;
- osalSysUnlock();
}
void usbhftdipStop(USBHFTDIPortDriver *ftdipp) {
osalDbgCheck((ftdipp->state == USBHFTDIP_STATE_ACTIVE)
|| (ftdipp->state == USBHFTDIP_STATE_READY));
- if (ftdipp->state == USBHFTDIP_STATE_ACTIVE) {
- return;
- }
-
- osalMutexLock(&ftdipp->ftdip->mtx);
- _stop(ftdipp);
- osalMutexUnlock(&ftdipp->ftdip->mtx);
+ osalSysLock();
+ chMtxLockS(&ftdipp->ftdip->mtx);
+ _stopS(ftdipp);
+ chMtxUnlockS(&ftdipp->ftdip->mtx);
+ osalOsRescheduleS();
+ osalSysUnlock();
}
void usbhftdipStart(USBHFTDIPortDriver *ftdipp, const USBHFTDIPortConfig *config) {