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

Commit 1520ba63 authored by Pratham Pratap's avatar Pratham Pratap
Browse files

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: default avatarPratham Pratap <prathampratap@codeaurora.org>
parent 4e4a72e7
Loading
Loading
Loading
Loading
+37 −6
Original line number Diff line number Diff line
@@ -500,7 +500,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,
@@ -550,7 +550,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,
@@ -558,7 +558,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 =
@@ -636,7 +636,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__);

@@ -664,6 +664,21 @@ 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:
	usb_gsi_ep_op(d_port->out_ep, NULL,
		GSI_EP_OP_ENDXFER);
free_trb_ep_out:
	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;
}

@@ -911,7 +926,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__);
@@ -1050,7 +1074,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__);