From 8f4621b9e5f7f2728fccfe0fba281d8ed7e8bdb2 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Wed, 13 Mar 2019 17:48:33 -0700 Subject: [PATCH] usb: f_gsi: Add error checking for PREPARE_TRBS and STARTXFER ops The GSI operations for GSI_EP_OP_PREPARE_TRBS and GSI_EP_OP_STARTXFER should not proceed if the endpoint is disabled and should return an error code (-ESHUTDOWN). Add error checking in f_gsi when calling these ops. This is to catch cases where the endpoint is not enabled (i.e. GSI_EP_OP_CONFIG was not called or GSI_EP_OP_DISABLE was called) prior to ipa_connect_channels(), and helps to avoid the situation in which STARTXFER is called on a disabled endpoint and later GSI_EP_OP_FREE_TRBS is called which causes the HW to incorrectly access stale DMA addresses the next time STARTXFER is called. Change-Id: I45f70524b87ec6303e135e385accd8e68e2b5a01 Signed-off-by: Jack Pham --- drivers/usb/gadget/function/f_gsi.c | 34 ++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index f6be9b01c6db..24d9bdec1f5c 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -483,10 +483,22 @@ static int ipa_connect_channels(struct gsi_data_port *d_port) log_event_dbg("IN: num_bufs:=%zu, buf_len=%zu\n", d_port->in_request.num_bufs, d_port->in_request.buf_len); - usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, - GSI_EP_OP_PREPARE_TRBS); - usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, + ret = usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, + GSI_EP_OP_PREPARE_TRBS); + if (ret) { + log_event_err("%s: GSI_EP_OP_PREPARE_TRBS failed: %d\n", + __func__, ret); + return ret; + } + + ret = usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_STARTXFER); + if (ret) { + log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n", + __func__, ret); + return ret; + } + d_port->in_xfer_rsc_index = usb_gsi_ep_op(d_port->in_ep, NULL, GSI_EP_OP_GET_XFER_IDX); @@ -529,10 +541,22 @@ static int ipa_connect_channels(struct gsi_data_port *d_port) log_event_dbg("OUT: num_bufs:=%zu, buf_len=%zu\n", d_port->out_request.num_bufs, d_port->out_request.buf_len); - usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, + ret = usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, GSI_EP_OP_PREPARE_TRBS); - usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, + if (ret) { + log_event_err("%s: GSI_EP_OP_PREPARE_TRBS failed: %d\n", + __func__, ret); + return ret; + } + + ret = usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, GSI_EP_OP_STARTXFER); + if (ret) { + log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n", + __func__, ret); + return ret; + } + d_port->out_xfer_rsc_index = usb_gsi_ep_op(d_port->out_ep, NULL, GSI_EP_OP_GET_XFER_IDX);