From b8e7c7ca38dd571814cacc412ed3cb1b80bc7d2f Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Mon, 29 May 2017 14:52:40 +0530 Subject: [PATCH] usb: gsi: Don't disable endpoints as part of flow control Currently GSI endpoints are disabled when host enables flow control for RNDIS function. When these endpoints are enabled again as part of flow control disable, no transactions are observed on these endpoints. Fix this by not disabling the endpoints as part of flow control enable but just stop the active transfers on these endpoints. Change-Id: I391a7048188b2a63e2df993fcebf7a6e78eaef14 Signed-off-by: Sriharsha Allenki --- drivers/usb/gadget/function/f_gsi.c | 60 ++++++++++++++++------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 67f7e75a9219..ff61879767b3 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -49,6 +49,7 @@ static struct gsi_inst_status { /* Deregister misc device and free instance structures */ static void gsi_inst_clean(struct gsi_opts *opts); +static void gsi_rndis_ipa_reset_trigger(struct gsi_data_port *d_port); static void ipa_disconnect_handler(struct gsi_data_port *d_port); static int gsi_ctrl_send_notification(struct f_gsi *gsi); static int gsi_alloc_trb_buffer(struct f_gsi *gsi); @@ -501,14 +502,11 @@ static void ipa_disconnect_handler(struct gsi_data_port *d_port) */ usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); - gsi->in_ep_desc_backup = gsi->d_port.in_ep->desc; usb_gsi_ep_op(gsi->d_port.in_ep, NULL, GSI_EP_OP_DISABLE); } - if (gsi->d_port.out_ep) { - gsi->out_ep_desc_backup = gsi->d_port.out_ep->desc; + if (gsi->d_port.out_ep) usb_gsi_ep_op(gsi->d_port.out_ep, NULL, GSI_EP_OP_DISABLE); - } gsi->d_port.net_ready_trigger = false; } @@ -617,6 +615,7 @@ static void ipa_work_handler(struct work_struct *w) struct usb_gadget *gadget = gsi->gadget; struct device *dev; struct device *gad_dev; + bool block_db; event = read_event(d_port); @@ -679,28 +678,6 @@ static void ipa_work_handler(struct work_struct *w) break; } - /* - * Update desc and reconfigure USB GSI OUT and IN - * endpoint for RNDIS Adaptor enable case. - */ - if (d_port->out_ep && !d_port->out_ep->desc && - gsi->out_ep_desc_backup) { - d_port->out_ep->desc = gsi->out_ep_desc_backup; - d_port->out_ep->ep_intr_num = 1; - log_event_dbg("%s: OUT ep_op_config", __func__); - usb_gsi_ep_op(d_port->out_ep, - &d_port->out_request, GSI_EP_OP_CONFIG); - } - - if (d_port->in_ep && !d_port->in_ep->desc && - gsi->in_ep_desc_backup) { - d_port->in_ep->desc = gsi->in_ep_desc_backup; - d_port->in_ep->ep_intr_num = 2; - log_event_dbg("%s: IN ep_op_config", __func__); - usb_gsi_ep_op(d_port->in_ep, - &d_port->in_request, GSI_EP_OP_CONFIG); - } - ipa_connect_channels(d_port); ipa_data_path_enable(d_port); d_port->sm_state = STATE_CONNECTED; @@ -762,7 +739,15 @@ static void ipa_work_handler(struct work_struct *w) if (event == EVT_HOST_NRDY) { log_event_dbg("%s: ST_CON_HOST_NRDY\n", __func__); - ipa_disconnect_handler(d_port); + block_db = true; + /* stop USB ringing doorbell to GSI(OUT_EP) */ + usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, + GSI_EP_OP_SET_CLR_BLOCK_DBL); + gsi_rndis_ipa_reset_trigger(d_port); + usb_gsi_ep_op(d_port->in_ep, NULL, + GSI_EP_OP_ENDXFER); + usb_gsi_ep_op(d_port->out_ep, NULL, + GSI_EP_OP_ENDXFER); } ipa_disconnect_work_handler(d_port); @@ -1471,6 +1456,27 @@ static void gsi_rndis_open(struct f_gsi *rndis) rndis_signal_connect(rndis->params); } +static void gsi_rndis_ipa_reset_trigger(struct gsi_data_port *d_port) +{ + struct f_gsi *rndis = d_port_to_gsi(d_port); + unsigned long flags; + + if (!rndis) { + log_event_err("%s: gsi prot ctx is %pK", __func__, rndis); + return; + } + + spin_lock_irqsave(&rndis->d_port.lock, flags); + if (!rndis) { + log_event_err("%s: No RNDIS instance", __func__); + spin_unlock_irqrestore(&rndis->d_port.lock, flags); + return; + } + + rndis->d_port.net_ready_trigger = false; + spin_unlock_irqrestore(&rndis->d_port.lock, flags); +} + void gsi_rndis_flow_ctrl_enable(bool enable, struct rndis_params *param) { struct f_gsi *rndis = param->v;