hidg: support boot protocol
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg / dwc_otg_hcd_queue.c
index 4c62f491e667b0d69364b1651a9b70ef947dfbbf..a0b9357626584c2d4af78a6a60524ea78ab42ee9 100755 (executable)
@@ -87,6 +87,10 @@ void dwc_otg_hcd_qh_free (dwc_otg_qh_t *_qh)
        dwc_otg_qtd_t *qtd;
        struct list_head *pos;
 
+       unsigned long flags;
+
+       local_irq_save(flags);
+       
        /* Free each QTD in the QTD list */
        for (pos = _qh->qtd_list.next;
             pos != &_qh->qtd_list;
@@ -94,10 +98,18 @@ void dwc_otg_hcd_qh_free (dwc_otg_qh_t *_qh)
        {
                list_del (pos);
                qtd = dwc_list_to_qtd (pos);
+               if(qtd->urb)
+               {
+                   qtd->urb->hcpriv =NULL;
+               qtd->urb->ep->hcpriv = NULL;
+           }
                dwc_otg_hcd_qtd_free (qtd);
+               qtd=NULL;
        }
-
+    
        kfree (_qh);
+       _qh = NULL;
+       local_irq_restore(flags);
        return;
 }
 
@@ -133,17 +145,11 @@ void dwc_otg_hcd_qh_init(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, struct urb *_ur
        _qh->maxp = usb_maxpacket(_urb->dev, _urb->pipe, !(usb_pipein(_urb->pipe)));
        INIT_LIST_HEAD(&_qh->qtd_list);
        INIT_LIST_HEAD(&_qh->qh_list_entry);
-       _qh->channel = NULL;
 
        /* FS/LS Enpoint on HS Hub 
         * NOT virtual root hub */
        _qh->do_split = 0;
 
-       /* yk@rk 20100625
-        * _urb->dev->tt->hub may be null
-        */
-       if((_urb->dev->tt)&&(!_urb->dev->tt->hub))
-               DWC_PRINT("%s tt->hub null!\n",__func__);
        if (((_urb->dev->speed == USB_SPEED_LOW) || 
             (_urb->dev->speed == USB_SPEED_FULL)) &&
            (_urb->dev->tt) && (_urb->dev->tt->hub)&&
@@ -241,7 +247,7 @@ static int periodic_channel_available(dwc_otg_hcd_t *_hcd)
         * non-periodic transactions.
         */
        int status;
-#if 0
+#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188)
        int num_channels;
 
        num_channels = _hcd->core_if->core_params->host_channels;
@@ -368,6 +374,7 @@ static int schedule_periodic(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
 
        /* Always start in the inactive schedule. */
        list_add_tail(&_qh->qh_list_entry, &_hcd->periodic_sched_inactive);
+       _qh->qh_state = QH_INACTIVE;
 
        /* Reserve the periodic channel. */
        _hcd->periodic_channels++;
@@ -399,12 +406,10 @@ static int schedule_periodic(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
  */
 int dwc_otg_hcd_qh_add (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
 {
+       unsigned long flags;
        int status = 0;
 
-       if (!spin_is_locked(&_hcd->global_lock))        {
-               //pr_err("%s don't have hcd->global_lock\n", __func__);
-               //BUG();
-       }
+       local_irq_save(flags);
 
        if (!list_empty(&_qh->qh_list_entry)) {
                /* QH already in a schedule. */
@@ -420,7 +425,7 @@ int dwc_otg_hcd_qh_add (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
        }
 
  done:
-       //local_irq_restore(flags);
+       local_irq_restore(flags);
 
        return status;
 }
@@ -463,10 +468,9 @@ static void deschedule_periodic(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
  * @param[in] _qh QH to remove from schedule. */
 void dwc_otg_hcd_qh_remove (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
 {
-       if (!spin_is_locked(&_hcd->global_lock))        {
-               //pr_err("%s don't have hcd->global_lock\n", __func__);
-               //BUG();
-       }
+       unsigned long flags;
+
+       local_irq_save(flags);
 
        if (list_empty(&_qh->qh_list_entry)) {
                /* QH is not in a schedule. */
@@ -483,7 +487,7 @@ void dwc_otg_hcd_qh_remove (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
        }
 
  done:
-       ;
+       local_irq_restore(flags);
 }
 
 /**
@@ -501,10 +505,9 @@ void dwc_otg_hcd_qh_remove (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
  */
 void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, int sched_next_periodic_split)
 {
-       if (!spin_is_locked(&_hcd->global_lock))        {
-               //pr_err("%s don't have hcd->global_lock\n", __func__);
-               //BUG();
-       }
+       unsigned long flags;
+       local_irq_save(flags);
+
        if (dwc_qh_is_non_per(_qh)) {
                dwc_otg_hcd_qh_remove(_hcd, _qh);
                if (!list_empty(&_qh->qtd_list)) {
@@ -557,16 +560,18 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, int sched
                         * appropriate queue.
                         */
                        if (_qh->sched_frame == frame_number) {
-                               list_move(&_qh->qh_list_entry,
-                                         &_hcd->periodic_sched_ready);
+                               //list_move_tail(&_qh->qh_list_entry,
+                               //        &_hcd->periodic_sched_ready);
+                   _qh->qh_state = QH_READY;
                        } else {
-                               list_move(&_qh->qh_list_entry,
-                                         &_hcd->periodic_sched_inactive);
+                               //list_move_tail(&_qh->qh_list_entry,
+                               //        &_hcd->periodic_sched_inactive);
+                   _qh->qh_state = QH_INACTIVE;
                        }
                }
        }
 
-
+       local_irq_restore(flags);
 }
 
 /** 
@@ -634,13 +639,11 @@ int dwc_otg_hcd_qtd_add (dwc_otg_qtd_t *_qtd,
 {
        struct usb_host_endpoint *ep;
        dwc_otg_qh_t *qh;
-       //unsigned long flags;
+       unsigned long flags;
        int retval = 0;
 
        struct urb *urb = _qtd->urb;
 
-       //local_irq_save(flags);
-
        /*
         * Get the QH which holds the QTD-list to insert to. Create QH if it
         * doesn't exist.
@@ -655,14 +658,15 @@ int dwc_otg_hcd_qtd_add (dwc_otg_qtd_t *_qtd,
                }
                ep->hcpriv = qh;
        }
-       
+    spin_lock_irqsave(&_dwc_otg_hcd->global_lock, flags);
        retval = dwc_otg_hcd_qh_add(_dwc_otg_hcd, qh);
        if (retval == 0) {
                list_add_tail(&_qtd->qtd_list_entry, &qh->qtd_list);
        }
 
+    spin_unlock_irqrestore(&_dwc_otg_hcd->global_lock, flags);
+
  done:
-       //local_irq_restore(flags);
        return retval;
 }