hidg: support boot protocol
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg / dwc_otg_hcd_queue.c
index 76326dd69a3488d3fa7b414ca2e942f0ef0330b2..a0b9357626584c2d4af78a6a60524ea78ab42ee9 100755 (executable)
@@ -86,21 +86,30 @@ 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 */
-       local_irq_save (flags);
        for (pos = _qh->qtd_list.next;
             pos != &_qh->qtd_list;
             pos = _qh->qtd_list.next)
        {
                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;
        }
-       local_irq_restore (flags);
-
+    
        kfree (_qh);
+       _qh = NULL;
+       local_irq_restore(flags);
        return;
 }
 
@@ -136,15 +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->speed == USB_SPEED_LOW) || 
             (_urb->dev->speed == USB_SPEED_FULL)) &&
            (_urb->dev->tt) && (_urb->dev->tt->hub)&&
@@ -163,10 +168,15 @@ void dwc_otg_hcd_qh_init(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, struct urb *_ur
 
                /** @todo Account for split transfers in the bus time. */
                int bytecount = dwc_hb_mult(_qh->maxp) * dwc_max_packet(_qh->maxp);
+               /*
+                * The results from usb_calc_bus_time are in nanosecs,
+                * so divide the result by 1000 to convert to
+                * microsecs expected by this driver
+                */
                _qh->usecs = usb_calc_bus_time(_urb->dev->speed,
                                               usb_pipein(_urb->pipe),
                                               (_qh->ep_type == USB_ENDPOINT_XFER_ISOC),
-                                              bytecount);
+                                              bytecount) / 1000;
 
                /* Start in a slightly future (micro)frame. */
                _qh->sched_frame = dwc_frame_num_inc(_hcd->frame_number,
@@ -237,6 +247,7 @@ static int periodic_channel_available(dwc_otg_hcd_t *_hcd)
         * non-periodic transactions.
         */
        int status;
+#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188)
        int num_channels;
 
        num_channels = _hcd->core_if->core_params->host_channels;
@@ -250,7 +261,9 @@ static int periodic_channel_available(dwc_otg_hcd_t *_hcd)
                           _hcd->non_periodic_channels);
                status = -ENOSPC;
        }
-
+#else
+       status = 0;
+#endif
        return status;
 }
 
@@ -361,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++;
@@ -392,10 +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;
+       unsigned long flags;
        int status = 0;
 
-       //local_irq_save(flags);
+       local_irq_save(flags);
 
        if (!list_empty(&_qh->qh_list_entry)) {
                /* QH already in a schedule. */
@@ -411,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;
 }
@@ -499,6 +513,7 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, int sched
                if (!list_empty(&_qh->qtd_list)) {
                        /* Add back to inactive non-periodic schedule. */
                        dwc_otg_hcd_qh_add(_hcd, _qh);
+               return;
                }
        } else {
                uint16_t frame_number = dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(_hcd));
@@ -545,11 +560,13 @@ 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;
                        }
                }
        }
@@ -622,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.
@@ -643,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;
 }