Loading drivers/usb/gadget/function/f_gsi.c +19 −8 Original line number Original line Diff line number Diff line Loading @@ -618,6 +618,25 @@ static void ipa_disconnect_work_handler(struct gsi_data_port *d_port) if (gsi->d_port.out_ep) if (gsi->d_port.out_ep) usb_gsi_ep_op(gsi->d_port.out_ep, NULL, GSI_EP_OP_FREE_TRBS); 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) static int ipa_suspend_work_handler(struct gsi_data_port *d_port) Loading Loading @@ -2015,7 +2034,6 @@ fail: static void gsi_disable(struct usb_function *f) static void gsi_disable(struct usb_function *f) { { struct f_gsi *gsi = func_to_gsi(f); struct f_gsi *gsi = func_to_gsi(f); struct usb_composite_dev *cdev = f->config->cdev; atomic_set(&gsi->connected, 0); atomic_set(&gsi->connected, 0); Loading @@ -2042,13 +2060,6 @@ static void gsi_disable(struct usb_function *f) return; return; } } if (gadget_is_dwc3(cdev->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); } gsi->data_interface_up = false; gsi->data_interface_up = false; pr_debug("%s deactivated\n", gsi->function.name); pr_debug("%s deactivated\n", gsi->function.name); Loading Loading
drivers/usb/gadget/function/f_gsi.c +19 −8 Original line number Original line Diff line number Diff line Loading @@ -618,6 +618,25 @@ static void ipa_disconnect_work_handler(struct gsi_data_port *d_port) if (gsi->d_port.out_ep) if (gsi->d_port.out_ep) usb_gsi_ep_op(gsi->d_port.out_ep, NULL, GSI_EP_OP_FREE_TRBS); 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) static int ipa_suspend_work_handler(struct gsi_data_port *d_port) Loading Loading @@ -2015,7 +2034,6 @@ fail: static void gsi_disable(struct usb_function *f) static void gsi_disable(struct usb_function *f) { { struct f_gsi *gsi = func_to_gsi(f); struct f_gsi *gsi = func_to_gsi(f); struct usb_composite_dev *cdev = f->config->cdev; atomic_set(&gsi->connected, 0); atomic_set(&gsi->connected, 0); Loading @@ -2042,13 +2060,6 @@ static void gsi_disable(struct usb_function *f) return; return; } } if (gadget_is_dwc3(cdev->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); } gsi->data_interface_up = false; gsi->data_interface_up = false; pr_debug("%s deactivated\n", gsi->function.name); pr_debug("%s deactivated\n", gsi->function.name); Loading