diff options
author | Diego Ismirlian <dismirlian (at) google's mail.com> | 2017-06-05 10:26:17 -0300 |
---|---|---|
committer | Diego Ismirlian <dismirlian (at) google's mail.com> | 2017-06-05 10:26:17 -0300 |
commit | cc347f02ba4c15d150c93bb6b40ede09498c658d (patch) | |
tree | 6addcf6a7172304dcf460edd47a7731e99c1f950 | |
parent | 5ecaf7722b5f1f9d0c41213fc5c129b451302f99 (diff) | |
download | ChibiOS-Contrib-cc347f02ba4c15d150c93bb6b40ede09498c658d.tar.gz ChibiOS-Contrib-cc347f02ba4c15d150c93bb6b40ede09498c658d.tar.bz2 ChibiOS-Contrib-cc347f02ba4c15d150c93bb6b40ede09498c658d.zip |
Fix possible race condition in FTDI driver stop
-rw-r--r-- | os/hal/src/usbh/hal_usbh_ftdi.c | 27 |
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) { |