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

Commit 3861555c authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: f_gsi: Ignore supsend/resume events if data interface is not selected"

parents 1e8e848d 1e270c3e
Loading
Loading
Loading
Loading
+33 −52
Original line number Diff line number Diff line
@@ -650,25 +650,6 @@ static void ipa_disconnect_work_handler(struct gsi_data_port *d_port)

	if (gsi->d_port.out_ep)
		usb_gsi_ep_op(gsi->d_port.out_ep, NULL, GSI_EP_OP_FREE_TRBS);

	/*
	 * Unconfig the gsi eps after freeing the trbs. If done in
	 * gsi_disable() then since gsi_disable() is called in interrupt context
	 * and the usb_gsi_ep_op() for GSI_EP_OP_FREE_TRBS which is called from
	 * ipa_disconnect_work_handler() a worker thread, can get delayed. So
	 * when gsi_disable() unconfigures the eps, usb_gsi_ep_op() will not be
	 * executed which leads to a memory leak.
	 * Also if this is done in gsi_unbind() then again this is executed in
	 * interrupt context and ipa_disconnect_work_handler() is a worker
	 * thread which can get delayed.
	 */
	if (gadget_is_dwc3(d_port->gadget)) {
		if (gsi->d_port.in_ep)
			msm_ep_unconfig(gsi->d_port.in_ep);
		if (gsi->d_port.out_ep)
			msm_ep_unconfig(gsi->d_port.out_ep);
	}

}

static int ipa_suspend_work_handler(struct gsi_data_port *d_port)
@@ -2023,20 +2004,6 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
				goto notify_ep_disable;
			}

			if (gsi->d_port.in_ep &&
				msm_ep_config(gsi->d_port.in_ep)) {
				log_event_err("%s: in ep config failed",
							__func__);
				goto notify_ep_disable;
			}

			if (gsi->d_port.out_ep &&
				msm_ep_config(gsi->d_port.out_ep)) {
				log_event_err("%s: out ep config failed",
							__func__);
				goto in_ep_unconfig;
			}

			/* Configure EPs for GSI */
			if (gsi->d_port.in_ep) {
				if (gsi->prot_id == IPA_USB_DIAG)
@@ -2061,7 +2028,7 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
				gsi_rndis_open(gsi);
				net = gsi_rndis_get_netdev("rndis0");
				if (IS_ERR(net))
					goto out_ep_unconfig;
					goto notify_ep_disable;

				log_event_dbg("RNDIS RX/TX early activation");
				gsi->d_port.cdc_filter = 0;
@@ -2088,16 +2055,12 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
			(gsi->d_port.out_ep &&
			!gsi->d_port.out_ep->driver_data))) {
				ipa_disconnect_handler(&gsi->d_port);
			if (gsi->data_interface_up) {
				if ((gsi->d_port.in_ep &&
					msm_ep_unconfig(gsi->d_port.in_ep)) ||
					(gsi->d_port.out_ep &&
					msm_ep_unconfig(gsi->d_port.out_ep))) {
					log_event_err("ep_unconfig failed");
					goto notify_ep_disable;
				}
			}
				post_event(&gsi->d_port, EVT_DISCONNECTED);
				queue_work(gsi->d_port.ipa_usb_wq,
						&gsi->d_port.usb_ipa_w);
				log_event_dbg("%s: Disconnecting\n", __func__);
			}

		gsi->data_interface_up = alt;
		log_event_dbg("DATA_INTERFACE id = %d, status = %d",
				gsi->data_id, gsi->data_interface_up);
@@ -2107,12 +2070,6 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)

	return 0;

out_ep_unconfig:
	if (gsi->d_port.out_ep)
		msm_ep_unconfig(gsi->d_port.out_ep);
in_ep_unconfig:
	if (gsi->d_port.in_ep)
		msm_ep_unconfig(gsi->d_port.in_ep);
notify_ep_disable:
	if (gsi->c_port.notify && gsi->c_port.notify->driver_data)
		usb_ep_disable(gsi->c_port.notify);
@@ -2163,6 +2120,11 @@ static void gsi_suspend(struct usb_function *f)
	struct f_gsi *gsi = func_to_gsi(f);
	bool remote_wakeup_allowed;

	if (!gsi->data_interface_up) {
		log_event_dbg("%s: Data interface not up\n", __func__);
		return;
	}

	/* Check if function is already suspended in gsi_func_suspend() */
	if (f->func_is_suspended) {
		log_event_dbg("%s: func already suspended, return\n", __func__);
@@ -2216,6 +2178,11 @@ static void gsi_resume(struct usb_function *f)

	log_event_dbg("%s", __func__);

	if (!gsi->data_interface_up) {
		log_event_dbg("%s: Data interface not up\n", __func__);
		return;
	}

	/*
	 * If the function is in USB3 Function Suspend state, resume is
	 * canceled. In this case resume is done by a Function Resume request.
@@ -2358,18 +2325,22 @@ skip_string_id_alloc:

	/* allocate instance-specific endpoints */
	if (info->fs_in_desc) {
		ep = usb_ep_autoconfig(cdev->gadget, info->fs_in_desc);
		ep = usb_ep_autoconfig_by_name
			(cdev->gadget, info->fs_in_desc, info->in_epname);
		if (!ep)
			goto fail;
		gsi->d_port.in_ep = ep;
		msm_ep_config(gsi->d_port.in_ep);
		ep->driver_data = cdev;	/* claim */
	}

	if (info->fs_out_desc) {
		ep = usb_ep_autoconfig(cdev->gadget, info->fs_out_desc);
		ep = usb_ep_autoconfig_by_name
			(cdev->gadget, info->fs_out_desc, info->out_epname);
		if (!ep)
			goto fail;
		gsi->d_port.out_ep = ep;
		msm_ep_config(gsi->d_port.out_ep);
		ep->driver_data = cdev;	/* claim */
	}

@@ -2566,6 +2537,8 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
		info.fs_desc_hdr = gsi_eth_fs_function;
		info.hs_desc_hdr = gsi_eth_hs_function;
		info.ss_desc_hdr = gsi_eth_ss_function;
		info.in_epname = "gsi-epin";
		info.out_epname = "gsi-epout";
		info.in_req_buf_len = GSI_IN_BUFF_SIZE;
		gsi->d_port.in_aggr_size = GSI_IN_RNDIS_AGGR_SIZE;
		info.in_req_num_buf = num_in_bufs;
@@ -2632,6 +2605,8 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
		info.fs_desc_hdr = mbim_gsi_fs_function;
		info.hs_desc_hdr = mbim_gsi_hs_function;
		info.ss_desc_hdr = mbim_gsi_ss_function;
		info.in_epname = "gsi-epin";
		info.out_epname = "gsi-epout";
		gsi->d_port.in_aggr_size = GSI_IN_MBIM_AGGR_SIZE;
		info.in_req_buf_len = GSI_IN_BUFF_SIZE;
		info.in_req_num_buf = num_in_bufs;
@@ -2671,6 +2646,8 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
		info.fs_desc_hdr = rmnet_gsi_fs_function;
		info.hs_desc_hdr = rmnet_gsi_hs_function;
		info.ss_desc_hdr = rmnet_gsi_ss_function;
		info.in_epname = "gsi-epin";
		info.out_epname = "gsi-epout";
		gsi->d_port.in_aggr_size = GSI_IN_RMNET_AGGR_SIZE;
		info.in_req_buf_len = GSI_IN_BUFF_SIZE;
		info.in_req_num_buf = num_in_bufs;
@@ -2701,6 +2678,8 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
		info.fs_desc_hdr = ecm_gsi_fs_function;
		info.hs_desc_hdr = ecm_gsi_hs_function;
		info.ss_desc_hdr = ecm_gsi_ss_function;
		info.in_epname = "gsi-epin";
		info.out_epname = "gsi-epout";
		gsi->d_port.in_aggr_size = GSI_IN_ECM_AGGR_SIZE;
		info.in_req_buf_len = GSI_IN_BUFF_SIZE;
		info.in_req_num_buf = num_in_bufs;
@@ -2736,6 +2715,8 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
		info.fs_desc_hdr = qdss_gsi_hs_data_only_desc;
		info.hs_desc_hdr = qdss_gsi_hs_data_only_desc;
		info.ss_desc_hdr = qdss_gsi_ss_data_only_desc;
		info.in_epname = "gsi-epin";
		info.out_epname = "";
		info.in_req_buf_len = 16384;
		info.in_req_num_buf = num_in_bufs;
		info.notify_buf_len = sizeof(struct usb_cdc_notification);
+3 −0
Original line number Diff line number Diff line
@@ -121,6 +121,9 @@ struct gsi_function_bind_info {
	struct usb_descriptor_header **fs_desc_hdr;
	struct usb_descriptor_header **hs_desc_hdr;
	struct usb_descriptor_header **ss_desc_hdr;
	const char *in_epname;
	const char *out_epname;

	u32 in_req_buf_len;
	u32 in_req_num_buf;
	u32 out_req_buf_len;