Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db62b9a8 authored by Gregory Herrero's avatar Gregory Herrero Committed by Felipe Balbi
Browse files

usb: dwc2: host: don't use dma_alloc_coherent with irqs disabled



Align buffer must be allocated using kmalloc since irqs are disabled.
Coherency is handled through dma_map_single which can be used with irqs
disabled.

Reviewed-by: default avatarJulius Werner <jwerner@chromium.org>
Acked-by: default avatarJohn Youn <johnyoun@synopsys.com>
Signed-off-by: default avatarGregory Herrero <gregory.herrero@intel.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 33ad261a
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -719,9 +719,7 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
			/* 3072 = 3 max-size Isoc packets */
			buf_size = 3072;

		qh->dw_align_buf = dma_alloc_coherent(hsotg->dev, buf_size,
						      &qh->dw_align_buf_dma,
						      GFP_ATOMIC);
		qh->dw_align_buf = kmalloc(buf_size, GFP_ATOMIC | GFP_DMA);
		if (!qh->dw_align_buf)
			return -ENOMEM;
		qh->dw_align_buf_size = buf_size;
@@ -746,6 +744,15 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
		}
	}

	qh->dw_align_buf_dma = dma_map_single(hsotg->dev,
			qh->dw_align_buf, qh->dw_align_buf_size,
			chan->ep_is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
	if (dma_mapping_error(hsotg->dev, qh->dw_align_buf_dma)) {
		dev_err(hsotg->dev, "can't map align_buf\n");
		chan->align_buf = (dma_addr_t)NULL;
		return -EINVAL;
	}

	chan->align_buf = qh->dw_align_buf_dma;
	return 0;
}
+38 −15
Original line number Diff line number Diff line
@@ -466,10 +466,15 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg,
	}

	/* Non DWORD-aligned buffer case handling */
	if (chan->align_buf && xfer_length && chan->ep_is_in) {
	if (chan->align_buf && xfer_length) {
		dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
		memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf,
		       xfer_length);
		dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
				chan->qh->dw_align_buf_size,
				chan->ep_is_in ?
				DMA_FROM_DEVICE : DMA_TO_DEVICE);
		if (chan->ep_is_in)
			memcpy(urb->buf + urb->actual_length,
					chan->qh->dw_align_buf, xfer_length);
	}

	dev_vdbg(hsotg->dev, "urb->actual_length=%d xfer_length=%d\n",
@@ -555,12 +560,17 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
					chan, chnum, qtd, halt_status, NULL);

		/* Non DWORD-aligned buffer case handling */
		if (chan->align_buf && frame_desc->actual_length &&
		    chan->ep_is_in) {
		if (chan->align_buf && frame_desc->actual_length) {
			dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
				 __func__);
			dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
					chan->qh->dw_align_buf_size,
					chan->ep_is_in ?
					DMA_FROM_DEVICE : DMA_TO_DEVICE);
			if (chan->ep_is_in)
				memcpy(urb->buf + frame_desc->offset +
			       qtd->isoc_split_offset, chan->qh->dw_align_buf,
					qtd->isoc_split_offset,
					chan->qh->dw_align_buf,
					frame_desc->actual_length);
		}
		break;
@@ -584,12 +594,17 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
					chan, chnum, qtd, halt_status, NULL);

		/* Non DWORD-aligned buffer case handling */
		if (chan->align_buf && frame_desc->actual_length &&
		    chan->ep_is_in) {
		if (chan->align_buf && frame_desc->actual_length) {
			dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
				 __func__);
			dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
					chan->qh->dw_align_buf_size,
					chan->ep_is_in ?
					DMA_FROM_DEVICE : DMA_TO_DEVICE);
			if (chan->ep_is_in)
				memcpy(urb->buf + frame_desc->offset +
			       qtd->isoc_split_offset, chan->qh->dw_align_buf,
					qtd->isoc_split_offset,
					chan->qh->dw_align_buf,
					frame_desc->actual_length);
		}

@@ -926,6 +941,8 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg,

	if (chan->align_buf) {
		dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
		dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
				chan->qh->dw_align_buf_size, DMA_FROM_DEVICE);
		memcpy(qtd->urb->buf + frame_desc->offset +
		       qtd->isoc_split_offset, chan->qh->dw_align_buf, len);
	}
@@ -1155,7 +1172,13 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg,
	/* Non DWORD-aligned buffer case handling */
	if (chan->align_buf && xfer_length && chan->ep_is_in) {
		dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
		memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf,
		dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
				chan->qh->dw_align_buf_size,
				chan->ep_is_in ?
				DMA_FROM_DEVICE : DMA_TO_DEVICE);
		if (chan->ep_is_in)
			memcpy(urb->buf + urb->actual_length,
					chan->qh->dw_align_buf,
					xfer_length);
	}

+6 −4
Original line number Diff line number Diff line
@@ -229,11 +229,13 @@ static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
 */
void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{
	if (hsotg->core_params->dma_desc_enable > 0)
	if (hsotg->core_params->dma_desc_enable > 0) {
		dwc2_hcd_qh_free_ddma(hsotg, qh);
	else if (qh->dw_align_buf)
		dma_free_coherent(hsotg->dev, qh->dw_align_buf_size,
				  qh->dw_align_buf, qh->dw_align_buf_dma);
	} else {
		/* kfree(NULL) is safe */
		kfree(qh->dw_align_buf);
		qh->dw_align_buf_dma = (dma_addr_t)0;
	}
	kfree(qh);
}