Loading drivers/usb/gadget/function/f_gsi.c +33 −52 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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) Loading @@ -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; Loading @@ -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); Loading @@ -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); Loading Loading @@ -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__); Loading Loading @@ -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. Loading Loading @@ -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 */ } Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading drivers/usb/gadget/function/f_gsi.h +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
drivers/usb/gadget/function/f_gsi.c +33 −52 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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) Loading @@ -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; Loading @@ -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); Loading @@ -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); Loading Loading @@ -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__); Loading Loading @@ -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. Loading Loading @@ -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 */ } Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading
drivers/usb/gadget/function/f_gsi.h +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading