aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2/hcd_queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/dwc2/hcd_queue.c')
-rw-r--r--drivers/usb/dwc2/hcd_queue.c67
1 files changed, 19 insertions, 48 deletions
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index bb97838bc6c0..3ad63d392e13 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -191,7 +191,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
191 * 191 *
192 * Return: Pointer to the newly allocated QH, or NULL on error 192 * Return: Pointer to the newly allocated QH, or NULL on error
193 */ 193 */
194static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, 194struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
195 struct dwc2_hcd_urb *urb, 195 struct dwc2_hcd_urb *urb,
196 gfp_t mem_flags) 196 gfp_t mem_flags)
197{ 197{
@@ -229,11 +229,13 @@ static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
229 */ 229 */
230void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) 230void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
231{ 231{
232 if (hsotg->core_params->dma_desc_enable > 0) 232 if (hsotg->core_params->dma_desc_enable > 0) {
233 dwc2_hcd_qh_free_ddma(hsotg, qh); 233 dwc2_hcd_qh_free_ddma(hsotg, qh);
234 else if (qh->dw_align_buf) 234 } else {
235 dma_free_coherent(hsotg->dev, qh->dw_align_buf_size, 235 /* kfree(NULL) is safe */
236 qh->dw_align_buf, qh->dw_align_buf_dma); 236 kfree(qh->dw_align_buf);
237 qh->dw_align_buf_dma = (dma_addr_t)0;
238 }
237 kfree(qh); 239 kfree(qh);
238} 240}
239 241
@@ -761,67 +763,36 @@ void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb)
761 763
762/** 764/**
763 * dwc2_hcd_qtd_add() - Adds a QTD to the QTD-list of a QH 765 * dwc2_hcd_qtd_add() - Adds a QTD to the QTD-list of a QH
766 * Caller must hold driver lock.
764 * 767 *
765 * @hsotg: The DWC HCD structure 768 * @hsotg: The DWC HCD structure
766 * @qtd: The QTD to add 769 * @qtd: The QTD to add
767 * @qh: Out parameter to return queue head 770 * @qh: Queue head to add qtd to
768 * @atomic_alloc: Flag to do atomic alloc if needed
769 * 771 *
770 * Return: 0 if successful, negative error code otherwise 772 * Return: 0 if successful, negative error code otherwise
771 * 773 *
772 * Finds the correct QH to place the QTD into. If it does not find a QH, it 774 * If the QH to which the QTD is added is not currently scheduled, it is placed
773 * will create a new QH. If the QH to which the QTD is added is not currently 775 * into the proper schedule based on its EP type.
774 * scheduled, it is placed into the proper schedule based on its EP type.
775 */ 776 */
776int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, 777int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
777 struct dwc2_qh **qh, gfp_t mem_flags) 778 struct dwc2_qh *qh)
778{ 779{
779 struct dwc2_hcd_urb *urb = qtd->urb;
780 unsigned long flags;
781 int allocated = 0;
782 int retval; 780 int retval;
783 781
784 /* 782 if (unlikely(!qh)) {
785 * Get the QH which holds the QTD-list to insert to. Create QH if it 783 dev_err(hsotg->dev, "%s: Invalid QH\n", __func__);
786 * doesn't exist. 784 retval = -EINVAL;
787 */ 785 goto fail;
788 if (*qh == NULL) {
789 *qh = dwc2_hcd_qh_create(hsotg, urb, mem_flags);
790 if (*qh == NULL)
791 return -ENOMEM;
792 allocated = 1;
793 } 786 }
794 787
795 spin_lock_irqsave(&hsotg->lock, flags); 788 retval = dwc2_hcd_qh_add(hsotg, qh);
796
797 retval = dwc2_hcd_qh_add(hsotg, *qh);
798 if (retval) 789 if (retval)
799 goto fail; 790 goto fail;
800 791
801 qtd->qh = *qh; 792 qtd->qh = qh;
802 list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list); 793 list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list);
803 spin_unlock_irqrestore(&hsotg->lock, flags);
804 794
805 return 0; 795 return 0;
806
807fail: 796fail:
808 if (allocated) {
809 struct dwc2_qtd *qtd2, *qtd2_tmp;
810 struct dwc2_qh *qh_tmp = *qh;
811
812 *qh = NULL;
813 dwc2_hcd_qh_unlink(hsotg, qh_tmp);
814
815 /* Free each QTD in the QH's QTD list */
816 list_for_each_entry_safe(qtd2, qtd2_tmp, &qh_tmp->qtd_list,
817 qtd_list_entry)
818 dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh_tmp);
819
820 spin_unlock_irqrestore(&hsotg->lock, flags);
821 dwc2_hcd_qh_free(hsotg, qh_tmp);
822 } else {
823 spin_unlock_irqrestore(&hsotg->lock, flags);
824 }
825
826 return retval; 797 return retval;
827} 798}