usb: dwc_otg: fix issue with race condition of competition
authorlyz <lyz@rock-chips.com>
Mon, 19 Jan 2015 10:55:56 +0000 (18:55 +0800)
committerlyz <lyz@rock-chips.com>
Fri, 23 Jan 2015 09:08:18 +0000 (17:08 +0800)
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 <lyz@rock-chips.com>
drivers/usb/dwc_otg_310/dwc_otg_hcd.c

index 451424e842042205760df4ac55e104bd079d774f..7602e4f851f6552ef65b8e0468f4e76c01f72a16 100755 (executable)
@@ -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;
+       }
 }
 
 /**