diff --git a/drivers/net/ethernet/msm/rndis_ipa.c b/drivers/net/ethernet/msm/rndis_ipa.c index eab8360b4312e9d90b33453d0c9b4a6429d80c54..d327006f71b51e4d07b2a8ef98b3b7c6dddf0caf 100644 --- a/drivers/net/ethernet/msm/rndis_ipa.c +++ b/drivers/net/ethernet/msm/rndis_ipa.c @@ -302,8 +302,8 @@ static void rndis_ipa_dump_skb(struct sk_buff *skb); static int rndis_ipa_debugfs_init(struct rndis_ipa_dev *rndis_ipa_ctx); static void rndis_ipa_debugfs_destroy(struct rndis_ipa_dev *rndis_ipa_ctx); static int rndis_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, - u32 ipa_to_usb_hdl, u32 max_transfer_size, - u32 max_packet_number, u32 mtu, + u32 ipa_to_usb_hdl, u32 max_xfer_size_bytes_to_dev, + u32 max_xfer_size_bytes_to_host, u32 mtu, bool deaggr_enable); static int rndis_ipa_set_device_ethernet_addr(u8 *dev_ethaddr, u8 device_ethaddr[]); @@ -698,8 +698,9 @@ EXPORT_SYMBOL(rndis_ipa_init); */ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl, - u32 max_transfer_byte_size, - u32 max_packet_number, + u32 max_xfer_size_bytes_to_dev, + u32 max_packet_number_to_dev, + u32 max_xfer_size_bytes_to_host, void *private) { struct rndis_ipa_dev *rndis_ipa_ctx = private; @@ -712,8 +713,11 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, RNDIS_IPA_DEBUG("usb_to_ipa_hdl=%d, ipa_to_usb_hdl=%d, private=0x%p\n", usb_to_ipa_hdl, ipa_to_usb_hdl, private); - RNDIS_IPA_DEBUG("max_xfer_sz=%d, max_pkt_num=%d\n", - max_transfer_byte_size, max_packet_number); + RNDIS_IPA_DEBUG("max_xfer_sz_to_dev=%d, max_pkt_num_to_dev=%d\n", + max_xfer_size_bytes_to_dev, + max_packet_number_to_dev); + RNDIS_IPA_DEBUG("max_xfer_sz_to_host=%d\n", + max_xfer_size_bytes_to_host); next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_CONNECT); @@ -734,10 +738,14 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, } rndis_ipa_ctx->ipa_to_usb_hdl = ipa_to_usb_hdl; rndis_ipa_ctx->usb_to_ipa_hdl = usb_to_ipa_hdl; + if (max_packet_number_to_dev > 1) + rndis_ipa_ctx->deaggregation_enable = true; + else + rndis_ipa_ctx->deaggregation_enable = false; result = rndis_ipa_ep_registers_cfg(usb_to_ipa_hdl, ipa_to_usb_hdl, - max_transfer_byte_size, - max_packet_number, + max_xfer_size_bytes_to_dev, + max_xfer_size_bytes_to_host, rndis_ipa_ctx->net->mtu, rndis_ipa_ctx->deaggregation_enable); if (result) { @@ -1876,12 +1884,10 @@ static bool rm_enabled(struct rndis_ipa_dev *rndis_ipa_ctx) * the USB to IPA end-point * @ipa_to_usb_hdl: handle received from ipa_connect which represents * the IPA to USB end-point - * @max_transfer_byte_size: the maximum size, in bytes, that the device + * @max_xfer_size_bytes_to_dev: the maximum size, in bytes, that the device * expects to receive from the host. supplied on REMOTE_NDIS_INITIALIZE_CMPLT. - * @max_packet_number: The maximum number of - * concatenated REMOTE_NDIS_PACKET_MSG messages that the device can handle - * in a single bus transfer to it. - * This value MUST be at least 1. + * @max_xfer_size_bytes_to_host: the maximum size, in bytes, that the host + * expects to receive from the device. supplied on REMOTE_NDIS_INITIALIZE_MSG. * @mtu: the netdev MTU size, in bytes * * USB to IPA pipe: @@ -1897,8 +1903,8 @@ static bool rm_enabled(struct rndis_ipa_dev *rndis_ipa_ctx) */ static int rndis_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl, - u32 max_transfer_byte_size, - u32 max_packet_number, + u32 max_xfer_size_bytes_to_dev, + u32 max_xfer_size_bytes_to_host, u32 mtu, bool deaggr_enable) { @@ -1913,7 +1919,7 @@ static int rndis_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, RNDIS_IPA_DEBUG("deaggregation disabled\n"); } - usb_to_ipa_ep_cfg->deaggr.max_packet_len = max_transfer_byte_size; + usb_to_ipa_ep_cfg->deaggr.max_packet_len = max_xfer_size_bytes_to_dev; result = ipa_cfg_ep(usb_to_ipa_hdl, usb_to_ipa_ep_cfg); if (result) { pr_err("failed to configure USB to IPA point\n"); @@ -1921,9 +1927,9 @@ static int rndis_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, } RNDIS_IPA_DEBUG("IPA<-USB end-point configured\n"); - ipa_to_usb_ep_cfg.aggr.aggr_pkt_limit = max_packet_number; + ipa_to_usb_ep_cfg.aggr.aggr_pkt_limit = 0; ipa_to_usb_ep_cfg.aggr.aggr_byte_limit = - (max_transfer_byte_size - mtu)/1024; + (max_xfer_size_bytes_to_host - mtu)/1024; result = ipa_cfg_ep(ipa_to_usb_hdl, &ipa_to_usb_ep_cfg); if (result) { pr_err("failed to configure IPA to USB end-point\n"); @@ -2676,8 +2682,10 @@ static int rndis_ipa_setup_loopback(bool enable, retval = rndis_ipa_pipe_connect_notify( rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_drv_ep_hdl, rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_drv_ep_hdl, + BAM_DMA_DATA_FIFO_SIZE, + 15, BAM_DMA_DATA_FIFO_SIZE - rndis_ipa_ctx->net->mtu, - 15, rndis_ipa_ctx); + rndis_ipa_ctx); if (retval) { RNDIS_IPA_ERROR("connect notify fail"); return -ENODEV; diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c index 7bdbfed79e2db7e679c1eb4a427d904e311f0457..7f9a90f3e7a72e384e3023453428efb240dbf4fa 100644 --- a/drivers/usb/gadget/f_qc_rndis.c +++ b/drivers/usb/gadget/f_qc_rndis.c @@ -85,7 +85,7 @@ struct f_rndis_qc { u8 ctrl_id, data_id; u8 ethaddr[ETH_ALEN]; u32 vendorID; - u8 max_pkt_per_xfer; + u8 ul_max_pkt_per_xfer; u8 pkt_alignment_factor; u32 max_pkt_size; const char *manufacturer; @@ -587,6 +587,7 @@ static void rndis_qc_command_complete(struct usb_ep *ep, struct f_rndis_qc *rndis = req->context; int status; rndis_init_msg_type *buf; + u32 ul_max_xfer_size, dl_max_xfer_size; /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ status = rndis_msg_parser(rndis->config, (u8 *) req->buf); @@ -597,9 +598,10 @@ static void rndis_qc_command_complete(struct usb_ep *ep, buf = (rndis_init_msg_type *)req->buf; if (buf->MessageType == RNDIS_MSG_INIT) { - rndis->max_pkt_size = buf->MaxTransferSize; - pr_debug("MaxTransferSize: %d\n", buf->MaxTransferSize); - u_bam_data_set_max_xfer_size(rndis->max_pkt_size); + ul_max_xfer_size = rndis_get_ul_max_xfer_size(rndis->config); + u_bam_data_set_ul_max_xfer_size(ul_max_xfer_size); + dl_max_xfer_size = rndis_get_dl_max_xfer_size(rndis->config); + u_bam_data_set_dl_max_xfer_size(dl_max_xfer_size); } } @@ -968,8 +970,8 @@ rndis_qc_bind(struct usb_configuration *c, struct usb_function *f) goto fail; pr_debug("%s(): max_pkt_per_xfer:%d\n", __func__, - rndis->max_pkt_per_xfer); - rndis_set_max_pkt_xfer(rndis->config, rndis->max_pkt_per_xfer); + rndis->ul_max_pkt_per_xfer); + rndis_set_max_pkt_xfer(rndis->config, rndis->ul_max_pkt_per_xfer); /* In case of aggregated packets QC device will request * aliment to 4 (2^2). @@ -1178,10 +1180,10 @@ rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], rndis->manufacturer = manufacturer; /* if max_pkt_per_xfer was not configured set to default value */ - rndis->max_pkt_per_xfer = + rndis->ul_max_pkt_per_xfer = max_pkt_per_xfer ? max_pkt_per_xfer : DEFAULT_MAX_PKT_PER_XFER; - u_bam_data_set_max_pkt_num(rndis->max_pkt_per_xfer); + u_bam_data_set_ul_max_pkt_num(rndis->ul_max_pkt_per_xfer); /* * Check no RNDIS aggregation, and alignment if not mentioned, @@ -1193,7 +1195,7 @@ rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], * those values will always override default values. */ if ((rndis->pkt_alignment_factor == 0) && - (rndis->max_pkt_per_xfer == 1)) + (rndis->ul_max_pkt_per_xfer == 1)) rndis->pkt_alignment_factor = 0; else rndis->pkt_alignment_factor = pkt_alignment_factor ? @@ -1288,14 +1290,14 @@ static long rndis_qc_ioctl(struct file *fp, unsigned cmd, unsigned long arg) switch (cmd) { case RNDIS_QC_GET_MAX_PKT_PER_XFER: ret = copy_to_user((void __user *)arg, - &rndis->max_pkt_per_xfer, - sizeof(rndis->max_pkt_per_xfer)); + &rndis->ul_max_pkt_per_xfer, + sizeof(rndis->ul_max_pkt_per_xfer)); if (ret) { pr_err("copying to user space failed\n"); ret = -EFAULT; } - pr_info("Sent max packets per xfer %d\n", - rndis->max_pkt_per_xfer); + pr_info("Sent UL max packets per xfer %d\n", + rndis->ul_max_pkt_per_xfer); break; case RNDIS_QC_GET_MAX_PKT_SIZE: ret = copy_to_user((void __user *)arg, diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 4880d1c2df4f1a94129bcc06a11ba7530c294cfd..d6d4aa3b5ef9f08b0dc2ae47aad8e8f7210c5e02 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -615,6 +615,7 @@ static int rndis_init_response(int configNr, rndis_init_msg_type *buf) resp->AFListOffset = cpu_to_le32(0); resp->AFListSize = cpu_to_le32(0); + params->ul_max_xfer_size = le32_to_cpu(resp->MaxTransferSize); params->resp_avail(params->v); return 0; } @@ -820,7 +821,7 @@ void rndis_set_host_mac(int configNr, const u8 *addr) */ int rndis_msg_parser(u8 configNr, u8 *buf) { - u32 MsgType, MsgLength; + u32 MsgType, MsgLength, major, minor, max_transfer_size; __le32 *tmp; struct rndis_params *params; @@ -845,6 +846,19 @@ int rndis_msg_parser(u8 configNr, u8 *buf) case RNDIS_MSG_INIT: pr_debug("%s: RNDIS_MSG_INIT\n", __func__); + tmp++; /* to get RequestID */ + major = get_unaligned_le32(tmp++); + minor = get_unaligned_le32(tmp++); + max_transfer_size = get_unaligned_le32(tmp++); + + params->host_rndis_major_ver = major; + params->host_rndis_minor_ver = minor; + params->dl_max_xfer_size = max_transfer_size; + + pr_debug("%s(): RNDIS Host Major:%d Minor:%d version\n", + __func__, major, minor); + pr_debug("%s(): UL Max Transfer size:%x\n", __func__, + max_transfer_size); params->state = RNDIS_INITIALIZED; return rndis_init_response(configNr, (rndis_init_msg_type *)buf); @@ -967,6 +981,17 @@ int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed) return 0; } +u32 rndis_get_dl_max_xfer_size(u8 configNr) +{ + pr_debug("%s:\n", __func__); + return rndis_per_dev_params[configNr].dl_max_xfer_size; +} + +u32 rndis_get_ul_max_xfer_size(u8 configNr) +{ + pr_debug("%s:\n", __func__); + return rndis_per_dev_params[configNr].ul_max_xfer_size; +} void rndis_set_max_pkt_xfer(u8 configNr, u8 max_pkt_per_xfer) { diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index 92b9c0db31ae24e56a93a8909957935976739807..f0133803aa511fcd9ad550078127dd7b01590e20 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h @@ -196,6 +196,10 @@ typedef struct rndis_params void *v; struct list_head resp_queue; spinlock_t lock; + u32 host_rndis_major_ver; + u32 host_rndis_minor_ver; + u32 ul_max_xfer_size; + u32 dl_max_xfer_size; } rndis_params; /* RNDIS Message parser and other useless functions */ @@ -208,6 +212,8 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr); int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); void rndis_set_max_pkt_xfer(u8 configNr, u8 max_pkt_per_xfer); +u32 rndis_get_ul_max_xfer_size(u8 configNr); +u32 rndis_get_dl_max_xfer_size(u8 configNr); void rndis_add_hdr (struct sk_buff *skb); int rndis_rm_hdr(struct gether *port, struct sk_buff *skb, struct sk_buff_head *list); diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c index efb5b9bff3dfc345155d9f5e0f3425e27f18fd31..8fc2c561cb7390da3738600277375de64e2e1009 100644 --- a/drivers/usb/gadget/u_bam_data.c +++ b/drivers/usb/gadget/u_bam_data.c @@ -58,8 +58,12 @@ module_param(bam_data_mux_rx_req_size, uint, S_IRUGO | S_IWUSR); #define MSM_VENDOR_ID BIT(16) struct rndis_data_ch_info { - u32 max_transfer_size; - u32 max_packets_number; + /* this provides downlink (device->host i.e host) side configuration*/ + u32 dl_max_transfer_size; + /* this provides uplink (host->device i.e device) side configuration */ + u32 ul_max_transfer_size; + u32 ul_max_packets_number; + bool ul_aggregation_enable; u32 prod_clnt_hdl; u32 cons_clnt_hdl; void *priv; @@ -992,11 +996,19 @@ static void bam2bam_data_connect_work(struct work_struct *w) d->ipa_params.cons_clnt_hdl; rndis_data.priv = d->ipa_params.priv; + pr_debug("ul_max_transfer_size:%d\n", + rndis_data.ul_max_transfer_size); + pr_debug("ul_max_packets_number:%d\n", + rndis_data.ul_max_packets_number); + pr_debug("dl_max_transfer_size:%d\n", + rndis_data.dl_max_transfer_size); + ret = rndis_ipa_pipe_connect_notify( rndis_data.cons_clnt_hdl, rndis_data.prod_clnt_hdl, - rndis_data.max_transfer_size, - rndis_data.max_packets_number, + rndis_data.ul_max_transfer_size, + rndis_data.ul_max_packets_number, + rndis_data.dl_max_transfer_size, rndis_data.priv); if (ret) { pr_err("%s: failed to connect IPA: err:%d\n", @@ -1650,17 +1662,18 @@ static void bam2bam_data_resume_work(struct work_struct *w) } } -void u_bam_data_set_max_xfer_size(u32 max_transfer_size) +void u_bam_data_set_dl_max_xfer_size(u32 max_transfer_size) { + if (!max_transfer_size) { pr_err("%s: invalid parameters\n", __func__); return; } - - rndis_data.max_transfer_size = max_transfer_size; + rndis_data.dl_max_transfer_size = max_transfer_size; + pr_debug("%s(): dl_max_xfer_size:%d\n", __func__, max_transfer_size); } -void u_bam_data_set_max_pkt_num(u32 max_packets_number) +void u_bam_data_set_ul_max_pkt_num(u8 max_packets_number) { if (!max_packets_number) { @@ -1668,5 +1681,25 @@ void u_bam_data_set_max_pkt_num(u32 max_packets_number) return; } - rndis_data.max_packets_number = max_packets_number; + rndis_data.ul_max_packets_number = max_packets_number; + + if (max_packets_number > 1) + rndis_data.ul_aggregation_enable = true; + else + rndis_data.ul_aggregation_enable = false; + + pr_debug("%s(): ul_aggregation enable:%d\n", __func__, + rndis_data.ul_aggregation_enable); + pr_debug("%s(): ul_max_packets_number:%d\n", __func__, + max_packets_number); +} + +void u_bam_data_set_ul_max_xfer_size(u32 max_transfer_size) +{ + if (!max_transfer_size) { + pr_err("%s: invalid parameters\n", __func__); + return; + } + rndis_data.ul_max_transfer_size = max_transfer_size; + pr_debug("%s(): ul_max_xfer_size:%d\n", __func__, max_transfer_size); } diff --git a/drivers/usb/gadget/u_bam_data.h b/drivers/usb/gadget/u_bam_data.h index 81784a33f5a12af9745c763f3ba718f65bb107b6..9d0d8a9ce2220c17eb0d94c3ebf66258ff367817 100644 --- a/drivers/usb/gadget/u_bam_data.h +++ b/drivers/usb/gadget/u_bam_data.h @@ -47,9 +47,11 @@ void bam_data_suspend(u8 port_num); void bam_data_resume(u8 port_num); -void u_bam_data_set_max_xfer_size(u32 max_transfer_size); +void u_bam_data_set_dl_max_xfer_size(u32 dl_max_transfer_size); -void u_bam_data_set_max_pkt_num(u32 max_packets_number); +void u_bam_data_set_ul_max_pkt_num(u8 ul_max_packets_number); + +void u_bam_data_set_ul_max_xfer_size(u32 ul_max_xfer_size); void u_bam_data_start_rndis_ipa(void); diff --git a/include/linux/rndis_ipa.h b/include/linux/rndis_ipa.h index eeae1d38fe30f6c58559a792a20514448d3c1b2a..14cce939d48515ac86678c3b62e8532f12d91a5b 100644 --- a/include/linux/rndis_ipa.h +++ b/include/linux/rndis_ipa.h @@ -62,8 +62,9 @@ int rndis_ipa_init(struct ipa_usb_init_params *params); int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl, - u32 max_transfer_size, - u32 max_packet_number, + u32 max_xfer_size_bytes_to_dev, + u32 max_packet_number_to_dev, + u32 max_xfer_size_bytes_to_host, void *private); int rndis_ipa_pipe_disconnect_notify(void *private); @@ -79,8 +80,9 @@ int rndis_ipa_init(struct ipa_usb_init_params *params) int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl, - u32 max_transfer_size, - u32 max_packet_number, + u32 max_xfer_size_bytes_to_dev, + u32 max_packet_number_to_dev, + u32 max_xfer_size_bytes_to_host, void *private) { return 0;