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

Commit 1ccf343c authored by Azhar Shaikh's avatar Azhar Shaikh
Browse files

usb: gadget: f_gsi: Fix setting of ep_type for GSI endpoints



Currently endpoint type is set as EP_TYPE_GSI in
gsi_update_function_bind_params() called from gsi_bind(). In
multi-config compositions, the endpoint type is over-written
with EP_TYPE_GSI, even for functions which do not support gsi.
Due to this over-writing, in case of diag compositions on cable
disconnect, the pending read requests were not flushed and hence
reference count of diag_context gets messed up. On next cable
connect the pending read request completes, decreases the reference
count of diag_context to 0 which eventually frees diag_context.
And then on next diag read, it tries to acquire a lock on freed
diag_context, which causes a crash.
Hence move the setting of the endpoint type in gsi_configure_ep()
called from gsi_set_alt(), so that it is set only for gsi endpoints.
Also set the endpoint type back to EP_TYPE_NORMAL in gsi_free_trbs()
so that for next composition switch which can be a non-gsi supported
the endpoint type is reset.
Also protect the freeing of dma_trb_pool with NULL check for non-gsi
endpoints.

CRs-fixed: 950978
Change-Id: I0a1b486786f37bd727eb8c988dd2115b7ac43d70
Signed-off-by: default avatarAzhar Shaikh <azhars@codeaurora.org>
parent 4d150bc9
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1088,6 +1088,11 @@ static void gsi_free_trbs(struct usb_ep *ep)
		dep->trb_pool = NULL;
		dep->trb_pool_dma = 0;
		dep->trb_dma_pool = NULL;
		/*
		 * Reset the ep_type to NORMAL, for next compostion
		 * switch which may be non-gsi.
		 */
		dep->endpoint.ep_type = EP_TYPE_NORMAL;
	}
}
/*
@@ -1108,6 +1113,9 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)

	memset(&params, 0x00, sizeof(params));

	/* Set the ep_type as GSI */
	dep->endpoint.ep_type = EP_TYPE_GSI;

	/* Configure GSI EP */
	params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc))
		| DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc));
+7 −4
Original line number Diff line number Diff line
@@ -408,12 +408,15 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep)
	if (dep->endpoint.ep_type == EP_TYPE_GSI)
		return;

	dma_free_coherent(dwc->dev, sizeof(struct dwc3_trb) * DWC3_TRB_NUM,
			dep->trb_pool, dep->trb_pool_dma);
	if (dep->trb_pool && dep->trb_pool_dma) {
		dma_free_coherent(dwc->dev,
			sizeof(struct dwc3_trb) * DWC3_TRB_NUM, dep->trb_pool,
			dep->trb_pool_dma);

		dep->trb_pool = NULL;
		dep->trb_pool_dma = 0;
	}
}

static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep)
{
+0 −2
Original line number Diff line number Diff line
@@ -2265,7 +2265,6 @@ skip_string_id_alloc:
		ep = usb_ep_autoconfig(cdev->gadget, info->fs_in_desc);
		if (!ep)
			goto fail;
		ep->ep_type = EP_TYPE_GSI;
		gsi->d_port.in_ep = ep;
		ep->driver_data = cdev;	/* claim */
	}
@@ -2274,7 +2273,6 @@ skip_string_id_alloc:
		ep = usb_ep_autoconfig(cdev->gadget, info->fs_out_desc);
		if (!ep)
			goto fail;
		ep->ep_type = EP_TYPE_GSI;
		gsi->d_port.out_ep = ep;
		ep->driver_data = cdev;	/* claim */
	}