diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index ab3a3a12c56f..afea9e7038b1 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -2038,16 +2038,32 @@ static void gsi_rndis_command_complete(struct usb_ep *ep, struct usb_request *req) { struct f_gsi *gsi = req->context; - rndis_init_msg_type *buf; int status; + u32 MsgType; + + if (!req->buf || !gsi->params) + return; + + MsgType = get_unaligned_le32((__le32 *)req->buf); + + /* intercept halt message to perform flow control */ + if (MsgType == RNDIS_MSG_HALT) { + log_event_dbg("RNDIS_MSG_HALT, state:%d\n", + gsi->params->state); + if (gsi->params->state == RNDIS_DATA_INITIALIZED) + gsi_rndis_flow_ctrl_enable(true, gsi->params); + gsi->params->state = RNDIS_UNINITIALIZED; + return; + } status = rndis_msg_parser(gsi->params, (u8 *) req->buf); if (status < 0) log_event_err("RNDIS command error %d, %d/%d", status, req->actual, req->length); - buf = (rndis_init_msg_type *)req->buf; - if (le32_to_cpu(buf->MessageType) == RNDIS_MSG_INIT) { + if (MsgType == RNDIS_MSG_INIT) { + rndis_init_msg_type *buf = (rndis_init_msg_type *)req->buf; + log_event_dbg("RNDIS host major:%d minor:%d version\n", le32_to_cpu(buf->MajorVersion), le32_to_cpu(buf->MinorVersion)); @@ -2056,6 +2072,13 @@ static void gsi_rndis_command_complete(struct usb_ep *ep, gsi->d_port.in_aggr_size = le32_to_cpu(buf->MaxTransferSize); log_event_dbg("RNDIS host DL MaxTransferSize:%d\n", le32_to_cpu(buf->MaxTransferSize)); + } else if (MsgType == RNDIS_MSG_SET) { + rndis_set_msg_type *buf = (rndis_set_msg_type *)req->buf; + + if (le32_to_cpu(buf->OID) == + RNDIS_OID_GEN_CURRENT_PACKET_FILTER) + gsi_rndis_flow_ctrl_enable(!(*gsi->params->filter), + gsi->params); } } @@ -2573,8 +2596,11 @@ static void gsi_resume(struct usb_function *f) */ if (gsi->prot_id == IPA_USB_RNDIS && !usb_gsi_remote_wakeup_allowed(f) && - gsi->host_supports_flow_control) - rndis_flow_control(gsi->params, false); + gsi->host_supports_flow_control && gsi->params) { + if (gsi->params->state != RNDIS_DATA_INITIALIZED) + gsi_rndis_flow_ctrl_enable(false, gsi->params); + gsi->params->state = RNDIS_DATA_INITIALIZED; + } post_event(&gsi->d_port, EVT_RESUMED); queue_delayed_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w, 0); @@ -2859,8 +2885,7 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f) info.out_req_num_buf = GSI_NUM_OUT_BUFFERS; info.notify_buf_len = sizeof(struct usb_cdc_notification); - params = rndis_register(gsi_rndis_response_available, gsi, - gsi_rndis_flow_ctrl_enable); + params = rndis_register(gsi_rndis_response_available, gsi); if (IS_ERR(params)) goto fail; diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c index d5373bc70324..51779e2bc195 100644 --- a/drivers/usb/gadget/function/f_rndis.c +++ b/drivers/usb/gadget/function/f_rndis.c @@ -1030,7 +1030,7 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi) rndis->port.func.disable = rndis_disable; rndis->port.func.free_func = rndis_free; - params = rndis_register(rndis_response_available, rndis, NULL); + params = rndis_register(rndis_response_available, rndis); if (IS_ERR(params)) { kfree(rndis); return ERR_CAST(params); diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 9b70ac789dcf..d568a44589b7 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -814,16 +814,10 @@ int rndis_msg_parser(struct rndis_params *params, u8 *buf) case RNDIS_MSG_HALT: pr_debug("%s: RNDIS_MSG_HALT\n", __func__); - if (params->state == RNDIS_DATA_INITIALIZED) { - if (params->flow_ctrl_enable) { - params->flow_ctrl_enable(true, params); - } else { - if (params->dev) { - netif_carrier_off(params->dev); - netif_stop_queue(params->dev); - } - } - params->state = RNDIS_UNINITIALIZED; + params->state = RNDIS_UNINITIALIZED; + if (params->dev) { + netif_carrier_off(params->dev); + netif_stop_queue(params->dev); } return 0; @@ -878,8 +872,7 @@ static inline void rndis_put_nr(int nr) ida_simple_remove(&rndis_ida, nr); } -struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v, - void (*flow_ctrl_enable)(bool enable, struct rndis_params *params)) +struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v) { struct rndis_params *params; int i; @@ -923,7 +916,6 @@ struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v, params->state = RNDIS_UNINITIALIZED; params->media_state = RNDIS_MEDIA_STATE_DISCONNECTED; params->resp_avail = resp_avail; - params->flow_ctrl_enable = flow_ctrl_enable; params->v = v; INIT_LIST_HEAD(¶ms->resp_queue); pr_debug("%s: configNr = %d\n", __func__, i); @@ -1007,49 +999,6 @@ void rndis_set_max_pkt_xfer(struct rndis_params *params, u8 max_pkt_per_xfer) params->max_pkt_per_xfer = max_pkt_per_xfer; } -/** - * rndis_flow_control: enable/disable flow control with USB RNDIS interface - * params - RNDIS network parameter - * enable_flow_control - true: perform flow control, false: disable flow control - * - * In hw accelerated mode, this function triggers functionality to start/stop - * endless transfers, otherwise it enables/disables RNDIS network interface. - */ -void rndis_flow_control(struct rndis_params *params, bool enable_flow_control) -{ - if (!params) { - pr_err("%s: failed, params NULL\n", __func__); - return; - } - - pr_debug("%s(): params->state:%x\n", __func__, params->state); - - if (enable_flow_control) { - if (params->state == RNDIS_DATA_INITIALIZED) { - if (params->flow_ctrl_enable) { - params->flow_ctrl_enable(enable_flow_control, - params); - } else { - netif_carrier_off(params->dev); - netif_stop_queue(params->dev); - } - } - params->state = RNDIS_INITIALIZED; - } else { - if (params->state != RNDIS_DATA_INITIALIZED) { - if (params->flow_ctrl_enable) { - params->flow_ctrl_enable(enable_flow_control, - params); - } else { - netif_carrier_on(params->dev); - if (netif_running(params->dev)) - netif_wake_queue(params->dev); - } - } - params->state = RNDIS_DATA_INITIALIZED; - } -} - void rndis_add_hdr(struct sk_buff *skb) { struct rndis_packet_msg_type *header; diff --git a/drivers/usb/gadget/function/rndis.h b/drivers/usb/gadget/function/rndis.h index 81bf58622c19..4bd6dc918a38 100644 --- a/drivers/usb/gadget/function/rndis.h +++ b/drivers/usb/gadget/function/rndis.h @@ -173,17 +173,13 @@ typedef struct rndis_params { u8 max_pkt_per_xfer; const char *vendorDescr; void (*resp_avail)(void *v); - void (*flow_ctrl_enable)(bool enable, - struct rndis_params *params); - void *v; struct list_head resp_queue; } rndis_params; /* RNDIS Message parser and other useless functions */ int rndis_msg_parser(struct rndis_params *params, u8 *buf); -struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v, - void (*flow_ctrl_enable)(bool enable, struct rndis_params *params)); +struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v); void rndis_deregister(struct rndis_params *params); int rndis_set_param_dev(struct rndis_params *params, struct net_device *dev, u16 *cdc_filter); @@ -203,6 +199,5 @@ int rndis_signal_connect(struct rndis_params *params); int rndis_signal_disconnect(struct rndis_params *params); int rndis_state(struct rndis_params *params); extern void rndis_set_host_mac(struct rndis_params *params, const u8 *addr); -void rndis_flow_control(struct rndis_params *params, bool enable_flow_control); #endif /* _LINUX_RNDIS_H */