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

Commit e0a427ed authored by Mayank Rana's avatar Mayank Rana
Browse files

dwc3: Use dma_alloc_coherent() API instead of DMA pool for GSI TRB ring



USB GSI wrapper has requirement as TRB ring base address must be aligned
to ring length rounded to power of 2. To support USB SMMU stage S1
functionality, if DMA pool APIs are used then multiple IOVA address may
fall within same page. When IPA driver is trying to map shared IOVA
address, Linux SMMU driver fails to map second IOVA address as it sees
as already mapped. Hence to fix this issue, use dma_alloc_coherent() API
which allows IOVA address mapping (due to page functionality) as well
provided IOVA buffer would be page aligned as it uses alloc_pages()
instead of pool based memory.

Change-Id: I21dc4109dea42fd0d8fb8a99aaec0dc52d32693e
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent e7325167
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -568,7 +568,6 @@ struct dwc3_ep_events {
 * @started_list: list of started requests on this endpoint
 * @lock: spinlock for endpoint request queue traversal
 * @regs: pointer to first endpoint register
 * @trb_dma_pool: dma pool used to get aligned trb memory pool
 * @trb_pool: array of transaction buffers
 * @trb_pool_dma: dma address of @trb_pool
 * @num_trbs: num of trbs in the trb dma pool
@@ -600,7 +599,6 @@ struct dwc3_ep {
	spinlock_t		lock;
	void __iomem		*regs;

	struct dma_pool		*trb_dma_pool;
	struct dwc3_trb		*trb_pool;
	dma_addr_t		trb_pool_dma;
	u32			num_trbs;
+11 −18
Original line number Diff line number Diff line
@@ -1052,25 +1052,17 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
	int num_trbs = (dep->direction) ? (2 * (req->num_bufs) + 2)
					: (req->num_bufs + 2);

	dep->trb_dma_pool = dma_pool_create(ep->name, dwc->sysdev,
	dep->trb_pool = dma_zalloc_coherent(dwc->sysdev,
				num_trbs * sizeof(struct dwc3_trb),
					num_trbs * sizeof(struct dwc3_trb), 0);
	if (!dep->trb_dma_pool) {
		dev_err(dep->dwc->dev, "failed to alloc trb dma pool for %s\n",
				dep->name);
		return -ENOMEM;
	}
				&dep->trb_pool_dma, GFP_KERNEL);

	dep->num_trbs = num_trbs;

	dep->trb_pool = dma_pool_alloc(dep->trb_dma_pool,
					   GFP_KERNEL, &dep->trb_pool_dma);
	if (!dep->trb_pool) {
		dev_err(dep->dwc->dev, "failed to allocate trb pool for %s\n",
		dev_err(dep->dwc->dev, "failed to alloc trb dma pool for %s\n",
				dep->name);
		return -ENOMEM;
	}

	dep->num_trbs = num_trbs;
	/* IN direction */
	if (dep->direction) {
		for (i = 0; i < num_trbs ; i++) {
@@ -1160,18 +1152,19 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
static void gsi_free_trbs(struct usb_ep *ep)
{
	struct dwc3_ep *dep = to_dwc3_ep(ep);
	struct dwc3 *dwc = dep->dwc;

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

	/*  Free TRBs and TRB pool for EP */
	if (dep->trb_dma_pool) {
		dma_pool_free(dep->trb_dma_pool, dep->trb_pool,
	if (dep->trb_pool_dma) {
		dma_free_coherent(dwc->sysdev,
			dep->num_trbs * sizeof(struct dwc3_trb),
			dep->trb_pool,
			dep->trb_pool_dma);
		dma_pool_destroy(dep->trb_dma_pool);
		dep->trb_pool = NULL;
		dep->trb_pool_dma = 0;
		dep->trb_dma_pool = NULL;
	}
}
/*