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 Original line 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 */
			/* 3072 = 3 max-size Isoc packets */
			buf_size = 3072;
			buf_size = 3072;


		qh->dw_align_buf = dma_alloc_coherent(hsotg->dev, buf_size,
		qh->dw_align_buf = kmalloc(buf_size, GFP_ATOMIC | GFP_DMA);
						      &qh->dw_align_buf_dma,
						      GFP_ATOMIC);
		if (!qh->dw_align_buf)
		if (!qh->dw_align_buf)
			return -ENOMEM;
			return -ENOMEM;
		qh->dw_align_buf_size = buf_size;
		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;
	chan->align_buf = qh->dw_align_buf_dma;
	return 0;
	return 0;
}
}
+38 −15
Original line number Original line 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 */
	/* 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__);
		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,
		       xfer_length);
				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",
	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);
					chan, chnum, qtd, halt_status, NULL);


		/* Non DWORD-aligned buffer case handling */
		/* Non DWORD-aligned buffer case handling */
		if (chan->align_buf && frame_desc->actual_length &&
		if (chan->align_buf && frame_desc->actual_length) {
		    chan->ep_is_in) {
			dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
			dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
				 __func__);
				 __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 +
				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);
					frame_desc->actual_length);
		}
		}
		break;
		break;
@@ -584,12 +594,17 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
					chan, chnum, qtd, halt_status, NULL);
					chan, chnum, qtd, halt_status, NULL);


		/* Non DWORD-aligned buffer case handling */
		/* Non DWORD-aligned buffer case handling */
		if (chan->align_buf && frame_desc->actual_length &&
		if (chan->align_buf && frame_desc->actual_length) {
		    chan->ep_is_in) {
			dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
			dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
				 __func__);
				 __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 +
				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);
					frame_desc->actual_length);
		}
		}


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


	if (chan->align_buf) {
	if (chan->align_buf) {
		dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
		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 +
		memcpy(qtd->urb->buf + frame_desc->offset +
		       qtd->isoc_split_offset, chan->qh->dw_align_buf, len);
		       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 */
	/* Non DWORD-aligned buffer case handling */
	if (chan->align_buf && xfer_length && chan->ep_is_in) {
	if (chan->align_buf && xfer_length && chan->ep_is_in) {
		dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
		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);
					xfer_length);
	}
	}


+6 −4
Original line number Original line 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)
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);
		dwc2_hcd_qh_free_ddma(hsotg, qh);
	else if (qh->dw_align_buf)
	} else {
		dma_free_coherent(hsotg->dev, qh->dw_align_buf_size,
		/* kfree(NULL) is safe */
				  qh->dw_align_buf, qh->dw_align_buf_dma);
		kfree(qh->dw_align_buf);
		qh->dw_align_buf_dma = (dma_addr_t)0;
	}
	kfree(qh);
	kfree(qh);
}
}