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

Commit 23cc3652 authored by Hemant Kumar's avatar Hemant Kumar
Browse files

usb: gadget: Mark usb gsi driver dma memory as cached



With this change usb gsi driver specific context bank is marked as
cached. This is needed to be in sync with IPA context bank used to
map usb iova to PA which is marked as non-cached. Otherwise IPA is
accessing the cached memory of USB transfer ring which resulting
in to SMMU page fault as the contents of the memory is invalid.
IO-Coherency is enabled by default in driver.

Change-Id: I04790e155f8e82425d98a3bc1a9d558fccd88bcb
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
parent 76382194
Loading
Loading
Loading
Loading
+29 −10
Original line number Diff line number Diff line
@@ -338,6 +338,7 @@ struct dwc3_msm {
	enum usb_device_speed override_usb_speed;
	u32			*gsi_reg;
	int			gsi_reg_offset_cnt;
	bool			gsi_io_coherency_disabled;

	struct notifier_block	dpdm_nb;
	struct regulator	*dpdm_reg;
@@ -1121,20 +1122,27 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
{
	int i = 0;
	size_t len;
	unsigned long dma_attr;
	dma_addr_t buffer_addr;
	struct dwc3_ep *dep = to_dwc3_ep(ep);
	struct dwc3		*dwc = dep->dwc;
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
	struct dwc3_trb *trb;
	int num_trbs = (dep->direction) ? (2 * (req->num_bufs) + 2)
					: (req->num_bufs + 2);
	struct scatterlist *sg;
	struct sg_table *sgt;

	if (mdwc->gsi_io_coherency_disabled)
		dma_attr = DMA_ATTR_FORCE_NON_COHERENT;
	else
		dma_attr = DMA_ATTR_FORCE_COHERENT;

	/* Allocate TRB buffers */

	len = req->buf_len * req->num_bufs;
	req->buf_base_addr = dma_zalloc_coherent(dwc->sysdev, len, &req->dma,
					GFP_KERNEL);
	req->buf_base_addr = dma_alloc_attrs(dwc->sysdev, len, &req->dma,
					GFP_KERNEL, dma_attr);
	if (!req->buf_base_addr) {
		dev_err(dwc->dev, "%s: buf_base_addr allocate failed %s\n",
				dep->name);
@@ -1148,9 +1156,9 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)

	/* Allocate and configgure TRBs */

	dep->trb_pool = dma_zalloc_coherent(dwc->sysdev,
	dep->trb_pool = dma_alloc_attrs(dwc->sysdev,
				num_trbs * sizeof(struct dwc3_trb),
				&dep->trb_pool_dma, GFP_KERNEL);
				&dep->trb_pool_dma, GFP_KERNEL, dma_attr);

	if (!dep->trb_pool) {
		dev_err(dep->dwc->dev, "failed to alloc trb dma pool for %s\n",
@@ -1254,7 +1262,8 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
	return 0;

free_trb_buffer:
	dma_free_coherent(dwc->sysdev, len, req->buf_base_addr, req->dma);
	dma_free_attrs(dwc->sysdev, len, req->buf_base_addr, req->dma,
			dma_attr);
	req->buf_base_addr = NULL;
	sg_free_table(&req->sgt_data_buff);
	return -ENOMEM;
@@ -1270,24 +1279,30 @@ static void gsi_free_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
{
	struct dwc3_ep *dep = to_dwc3_ep(ep);
	struct dwc3 *dwc = dep->dwc;
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
	unsigned long dma_attr;

	if (dep->endpoint.ep_type == EP_TYPE_NORMAL)
		return;

	if (mdwc->gsi_io_coherency_disabled)
		dma_attr = DMA_ATTR_FORCE_NON_COHERENT;
	else
		dma_attr = DMA_ATTR_FORCE_COHERENT;

	/*  Free TRBs and TRB pool for EP */
	if (dep->trb_pool_dma) {
		dma_free_coherent(dwc->sysdev,
		dma_free_attrs(dwc->sysdev,
			dep->num_trbs * sizeof(struct dwc3_trb),
			dep->trb_pool,
			dep->trb_pool_dma);
			dep->trb_pool, dep->trb_pool_dma, dma_attr);
		dep->trb_pool = NULL;
		dep->trb_pool_dma = 0;
	}
	sg_free_table(&req->sgt_trb_xfer_ring);

	/* free TRB buffers */
	dma_free_coherent(dwc->sysdev, req->buf_len * req->num_bufs,
		req->buf_base_addr, req->dma);
	dma_free_attrs(dwc->sysdev, req->buf_len * req->num_bufs,
		req->buf_base_addr, req->dma, dma_attr);
	req->buf_base_addr = NULL;
	sg_free_table(&req->sgt_data_buff);
}
@@ -3616,6 +3631,10 @@ static int dwc3_msm_probe(struct platform_device *pdev)

	mdwc->use_pdc_interrupts = of_property_read_bool(node,
				"qcom,use-pdc-interrupts");

	mdwc->gsi_io_coherency_disabled = of_property_read_bool(node,
				"qcom,gsi-disable-io-coherency");

	dwc3_set_notifier(&dwc3_msm_notify_event);

	if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {