usb: f_gsi: Don't enable IPA data path if connect channel fails

ipa_connect_channels can return failure if gsi prepare trbs fail or
start xfer fails. But currently driver is not checking for the failure
and goes ahead to enable IPA data path. This leads the controller to
access faulty addresses which cause kernel panic. Fix this by checking
the failure returned from ipa_connect_channels. Also cleanup the error
handling path.

Change-Id: Ia1e8e17381e12231d8d78224ba3b07081f143212
Signed-off-by: Pratham Pratap <prathampratap@codeaurora.org>
This commit is contained in:
Pratham Pratap 2019-06-11 19:26:35 +05:30 • committed by Jack Pham
commit 9490c68a6f

View file

@ -496,7 +496,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
if (ret) {
log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n",
__func__, ret);
return ret;
goto free_trb_ep_in;
}
d_port->in_xfer_rsc_index = usb_gsi_ep_op(d_port->in_ep, NULL,
@ -546,7 +546,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
if (ret) {
log_event_err("%s: GSI_EP_OP_PREPARE_TRBS failed: %d\n",
__func__, ret);
return ret;
goto end_xfer_ep_in;
}
ret = usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
@ -554,7 +554,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
if (ret) {
log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n",
__func__, ret);
return ret;
goto free_trb_ep_out;
}
d_port->out_xfer_rsc_index =
@ -632,7 +632,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
conn_params);
if (ret) {
log_event_err("%s: IPA connect failed %d", __func__, ret);
return ret;
goto end_xfer_ep_out;
}
log_event_dbg("%s: xdci_connect done", __func__);
@ -660,6 +660,23 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
d_port->out_request.db_reg_phs_addr_msb =
ipa_out_channel_out_params.db_reg_phs_addr_msb;
}
return ret;
end_xfer_ep_out:
if (d_port->out_ep)
usb_gsi_ep_op(d_port->out_ep, NULL,
GSI_EP_OP_ENDXFER);
free_trb_ep_out:
if (d_port->out_ep)
usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
GSI_EP_OP_FREE_TRBS);
end_xfer_ep_in:
usb_gsi_ep_op(d_port->in_ep, NULL,
GSI_EP_OP_ENDXFER);
free_trb_ep_in:
usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
GSI_EP_OP_FREE_TRBS);
return ret;
}
@ -907,7 +924,16 @@ static void ipa_work_handler(struct work_struct *w)
break;
}
ipa_connect_channels(d_port);
ret = ipa_connect_channels(d_port);
if (ret) {
log_event_err("%s: ipa_connect_channels failed\n",
__func__);
ipa_data_path_disable(d_port);
usb_gadget_autopm_put_async(d_port->gadget);
d_port->sm_state = STATE_INITIALIZED;
break;
}
d_port->sm_state = STATE_WAIT_FOR_IPA_RDY;
log_event_dbg("%s: ST_INIT_EVT_SET_ALT",
__func__);
@ -1046,7 +1072,14 @@ static void ipa_work_handler(struct work_struct *w)
log_event_dbg("%s: get = %d", __func__,
atomic_read(&gad_dev->power.usage_count));
ipa_connect_channels(d_port);
ret = ipa_connect_channels(d_port);
if (ret) {
log_event_err("%s: ipa_connect_channels failed\n",
__func__);
usb_gadget_autopm_put_async(d_port->gadget);
break;
}
ipa_data_path_enable(d_port);
d_port->sm_state = STATE_CONNECTED;
log_event_dbg("%s: ST_HOST_NRDY_EVT_HRDY_", __func__);