diff options
Diffstat (limited to 'drivers/usb/dwc2/hcd_queue.c')
-rw-r--r-- | drivers/usb/dwc2/hcd_queue.c | 67 |
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 | */ |
194 | static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, | 194 | struct 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 | */ |
230 | void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | 230 | void 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 | */ |
776 | int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, | 777 | int 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 | |||
807 | fail: | 796 | fail: |
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 | } |