From b1e25b6bf255cecf4d022099857d200cbc681661 Mon Sep 17 00:00:00 2001 From: lyz Date: Mon, 19 Jan 2015 18:55:56 +0800 Subject: [PATCH] usb: dwc_otg: fix issue with race condition of competition between hcd_reinit() and cil_interrupt handler. hcd_reinit() should get core_if->lock before modify this lock, so that can prevent competition between cil_interrupt handler and hcd_reinit(), hcd_reinit() be scheduled while cil_interrupt handler holding core_if->lock, hcd_reinit() modify the lock then previous core_if->lock will never be unlocked. Signed-off-by: lyz --- drivers/usb/dwc_otg_310/dwc_otg_hcd.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc_otg_310/dwc_otg_hcd.c b/drivers/usb/dwc_otg_310/dwc_otg_hcd.c index 451424e84204..7602e4f851f6 100755 --- a/drivers/usb/dwc_otg_310/dwc_otg_hcd.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_hcd.c @@ -966,9 +966,9 @@ static void dwc_otg_hcd_reinit(dwc_otg_hcd_t *hcd) dwc_hc_t *channel; dwc_hc_t *channel_tmp; dwc_irqflags_t flags; + dwc_spinlock_t *temp_lock; hcd->flags.d32 = 0; - hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; hcd->non_periodic_channels = 0; hcd->periodic_channels = 0; @@ -995,7 +995,15 @@ static void dwc_otg_hcd_reinit(dwc_otg_hcd_t *hcd) dwc_otg_core_host_init(hcd->core_if); /* Set core_if's lock pointer to the hcd->lock */ - hcd->core_if->lock = hcd->lock; + /* Should get this lock before modify it */ + if (hcd->core_if->lock) { + DWC_SPINLOCK_IRQSAVE(hcd->core_if->lock, &flags); + temp_lock = hcd->core_if->lock; + hcd->core_if->lock = hcd->lock; + DWC_SPINUNLOCK_IRQRESTORE(temp_lock, flags); + } else { + hcd->core_if->lock = hcd->lock; + } } /** -- 2.34.1