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;