/** Free each QTD in the QH's QTD-list then free the QH. QH should already be * removed from a list. QTD list should already be empty if called from URB * Dequeue. * * @param[in] hcd HCD instance. * @param[in] qh The QH to free. */ void dwc_otg_hcd_qh_free (dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) { dwc_otg_qtd_t *qtd; struct list_head *pos; unsigned long flags; /* Free each QTD in the QTD list */ SPIN_LOCK_IRQSAVE(&hcd->lock, 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); dwc_otg_hcd_qtd_free (qtd); } SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags) if (qh->dw_align_buf) { dma_free_coherent((dwc_otg_hcd_to_hcd(hcd))->self.controller, hcd->core_if->core_params->max_transfer_size, qh->dw_align_buf, qh->dw_align_buf_dma); } kfree (qh); return; }
/** Free each QTD in the QH's QTD-list then free the QH. QH should already be * removed from a list. QTD list should already be empty if called from URB * Dequeue. * * @param[in] hcd HCD instance. * @param[in] qh The QH to free. */ void dwc_otg_hcd_qh_free (dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) { dwc_otg_qtd_t *qtd; struct list_head *pos; //unsigned long flags; /* Free each QTD in the QTD list */ #ifdef CONFIG_SMP //the spinlock is locked before this function get called, //but in case the lock is needed, the check function is preserved //but in non-SMP mode, all spinlock is lockable. //don't do the test in non-SMP mode if(spin_trylock(&hcd->lock)) { printk("%s: It is not supposed to be lockable!!\n",__func__); BUG(); } #endif // SPIN_LOCK_IRQSAVE(&hcd->lock, 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); dwc_otg_hcd_qtd_free (qtd); } // SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags) kfree (qh); return; }
/** Free each QTD in the QH's QTD-list then free the QH. QH should already be * removed from a list. QTD list should already be empty if called from URB * Dequeue. * * @param[in] _qh The QH to free. */ 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; 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; } kfree (_qh); _qh = NULL; local_irq_restore(flags); return; }
/** Free each QTD in the QH's QTD-list then free the QH. QH should already be * removed from a list. QTD list should already be empty if called from URB * Dequeue. * * @param[in] _qh The QH to free. */ void dwc_otg_hcd_qh_free(dwc_otg_qh_t * _qh) { dwc_otg_qtd_t * qtd; struct list_head *pos; unsigned long 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); dwc_otg_hcd_qtd_free(qtd); } local_irq_restore(flags); kfree(_qh); return; }