usb: f_gsi: Avoid gsi ep operations if run/stop is cleared

The GSI operations for GSI_EP_OP_PREPARE_TRBS and GSI_EP_OP_STARTXFER
should not proceed if run/stop is cleared. Since ipa_work_handler runs
in worqueue context there might be a race between run/stop STARTXFER
and ENDXFER which can lead to SMMU fault. This change add checks to
avoid gsi ep operations when run/stop is cleared.

Change-Id: I9f64dee7020aec9cccfde8d247c0b53d9cc1f234
Signed-off-by: Pratham Pratap <prathampratap@codeaurora.org>
This commit is contained in:
Pratham Pratap 2019-12-05 20:13:14 +05:30
parent 1520ba63d5
commit 42a80370a9
2 changed files with 35 additions and 3 deletions
drivers/usb
dwc3
gadget/function

View file

@ -1504,6 +1504,11 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep,
switch (op) {
case GSI_EP_OP_PREPARE_TRBS:
if (!dwc->pullups_connected) {
dbg_log_string("No Pullup\n");
return -ESHUTDOWN;
}
request = (struct usb_gsi_request *)op_data;
ret = gsi_prepare_trbs(ep, request);
break;
@ -1512,12 +1517,22 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep,
gsi_free_trbs(ep, request);
break;
case GSI_EP_OP_CONFIG:
if (!dwc->pullups_connected) {
dbg_log_string("No Pullup\n");
return -ESHUTDOWN;
}
request = (struct usb_gsi_request *)op_data;
spin_lock_irqsave(&dwc->lock, flags);
gsi_configure_ep(ep, request);
spin_unlock_irqrestore(&dwc->lock, flags);
break;
case GSI_EP_OP_STARTXFER:
if (!dwc->pullups_connected) {
dbg_log_string("No Pullup\n");
return -ESHUTDOWN;
}
spin_lock_irqsave(&dwc->lock, flags);
ret = gsi_startxfer_for_ep(ep);
spin_unlock_irqrestore(&dwc->lock, flags);
@ -1530,6 +1545,11 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep,
gsi_store_ringbase_dbl_info(ep, request);
break;
case GSI_EP_OP_ENABLE_GSI:
if (!dwc->pullups_connected) {
dbg_log_string("No Pullup\n");
return -ESHUTDOWN;
}
gsi_enable(ep);
break;
case GSI_EP_OP_GET_CH_INFO:
@ -1537,6 +1557,11 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep,
gsi_get_channel_info(ep, ch_info);
break;
case GSI_EP_OP_RING_DB:
if (!dwc->pullups_connected) {
dbg_log_string("No Pullup\n");
return -ESHUTDOWN;
}
request = (struct usb_gsi_request *)op_data;
gsi_ring_db(ep, request);
break;

View file

@ -841,8 +841,10 @@ static int gsi_ep_enable(struct f_gsi *gsi)
return ret;
log_event_dbg("%s: Enable IN ep", __func__);
usb_gsi_ep_op(gsi->d_port.in_ep,
&gsi->d_port.in_request, GSI_EP_OP_CONFIG);
ret = usb_gsi_ep_op(gsi->d_port.in_ep,
&gsi->d_port.in_request, GSI_EP_OP_CONFIG);
if (ret)
return ret;
}
if (gsi->d_port.out_ep && !gsi->d_port.out_ep->desc) {
@ -852,8 +854,13 @@ static int gsi_ep_enable(struct f_gsi *gsi)
return ret;
log_event_dbg("%s: Enable OUT ep", __func__);
usb_gsi_ep_op(gsi->d_port.out_ep,
ret = usb_gsi_ep_op(gsi->d_port.out_ep,
&gsi->d_port.out_request, GSI_EP_OP_CONFIG);
if (ret) {
usb_gsi_ep_op(gsi->d_port.in_ep,
&gsi->d_port.in_request, GSI_EP_OP_DISABLE);
return ret;
}
}
return 0;