usb: gadget: Enable/Disable USB_BAM based on composition

BAM is used only in USB BAM mode. If platform has BAM enabled
by default in peripheral mode then it may slow down DDR access
by USB and also observing throughput degradation for software path
transfers. Since, USB legacy mode doesn't use BAM2BAM mode disable
the same for USB legacy mode and enable USB BAM based on composition.

Change-Id: I564caea896fb6b7b7acef12dc72e1bf179977b3f
Signed-off-by: Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
Signed-off-by: Ajay Agarwal <ajaya@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/platform/msm/usb-bam.txt b/Documentation/devicetree/bindings/platform/msm/usb-bam.txt
index 7d2e31e..9af22e2 100644
--- a/Documentation/devicetree/bindings/platform/msm/usb-bam.txt
+++ b/Documentation/devicetree/bindings/platform/msm/usb-bam.txt
@@ -36,7 +36,6 @@
 - qcom,reset-bam-on-connect: If present then BAM is RESET before connecting
   pipe. This may be required if BAM peripheral is also reset before connect.
 - qcom,reset-bam-on-disconnect: If present then BAM is RESET after disconnecting pipes.
-- qcom,enable-hsusb-bam-on-boot: If present then BAM is enabled at bootup itself.
 
 A number of USB BAM pipe parameters are represented as sub-nodes:
 
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index b4cd640..4c932cb 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -2969,9 +2969,6 @@
 	else
 		usb_bam_data->override_threshold = threshold;
 
-	usb_bam_data->enable_hsusb_bam_on_boot = of_property_read_bool(node,
-		"qcom,enable-hsusb-bam-on-boot");
-
 	for_each_child_of_node(pdev->dev.of_node, node)
 		max_connections++;
 
@@ -3095,48 +3092,42 @@
 	return NULL;
 }
 
-static int usb_bam_init(struct platform_device *pdev)
+static void msm_usb_bam_update_props(struct sps_bam_props *props,
+				struct platform_device *pdev)
 {
-	int ret;
 	struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
 	enum usb_ctrl bam_type = ctx->usb_bam_data->bam_type;
-	struct sps_bam_props props;
 	struct device *dev;
 
-	memset(&props, 0, sizeof(props));
-
-	pr_debug("%s: usb_bam_init - %s\n", __func__,
-		bam_enable_strings[bam_type]);
-
-	props.phys_addr = ctx->io_res->start;
-	props.virt_size = resource_size(ctx->io_res);
-	props.irq = ctx->irq;
-	props.summing_threshold = ctx->usb_bam_data->override_threshold;
-	props.event_threshold = ctx->usb_bam_data->override_threshold;
-	props.num_pipes = ctx->usb_bam_data->usb_bam_num_pipes;
-	props.callback = usb_bam_sps_events;
-	props.user = bam_enable_strings[bam_type];
+	props->phys_addr = ctx->io_res->start;
+	props->virt_addr = NULL;
+	props->virt_size = resource_size(ctx->io_res);
+	props->irq = ctx->irq;
+	props->summing_threshold = ctx->usb_bam_data->override_threshold;
+	props->event_threshold = ctx->usb_bam_data->override_threshold;
+	props->num_pipes = ctx->usb_bam_data->usb_bam_num_pipes;
+	props->callback = usb_bam_sps_events;
+	props->user = bam_enable_strings[bam_type];
 
 	/*
 	* HSUSB and HSIC Cores don't support RESET ACK signal to BAMs
 	* Hence, let BAM to ignore acknowledge from USB while resetting PIPE
 	*/
 	if (ctx->usb_bam_data->ignore_core_reset_ack && bam_type != DWC3_CTRL)
-		props.options = SPS_BAM_NO_EXT_P_RST;
+		props->options = SPS_BAM_NO_EXT_P_RST;
 
 	if (ctx->usb_bam_data->disable_clk_gating)
-		props.options |= SPS_BAM_NO_LOCAL_CLK_GATING;
+		props->options |= SPS_BAM_NO_LOCAL_CLK_GATING;
 
 	/*
-	 * HSUSB BAM is not NDP BAM and it must be enabled early before
+	 * HSUSB BAM is not NDP BAM and it must be enabled before
 	 * starting peripheral controller to avoid switching USB core mode
 	 * from legacy to BAM with ongoing data transfers.
 	 */
-	if (ctx->usb_bam_data->enable_hsusb_bam_on_boot
-					&& bam_type == CI_CTRL) {
-		pr_debug("Register and enable HSUSB BAM\n");
-		props.options |= SPS_BAM_OPT_ENABLE_AT_BOOT;
-		props.options |= SPS_BAM_FORCE_RESET;
+	if (bam_type == CI_CTRL) {
+		log_event_dbg("Register and enable HSUSB BAM\n");
+		props->options |= SPS_BAM_OPT_ENABLE_AT_BOOT;
+		props->options |= SPS_BAM_FORCE_RESET;
 	}
 
 	dev = &ctx->usb_bam_pdev->dev;
@@ -3145,9 +3136,29 @@
 						"qcom,smmu-s1-bypass")) {
 		pr_info("%s: setting SPS_BAM_SMMU_EN flag with (%s)\n",
 						__func__, dev_name(dev));
-		props.options |= SPS_BAM_SMMU_EN;
+		props->options |= SPS_BAM_SMMU_EN;
 	}
+}
 
+static int usb_bam_init(struct platform_device *pdev)
+{
+	int ret;
+	struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
+	enum usb_ctrl bam_type = ctx->usb_bam_data->bam_type;
+	struct sps_bam_props props;
+
+	pr_debug("%s: usb_bam_init - %s\n", __func__,
+		bam_enable_strings[bam_type]);
+
+	/*
+	 * CI USB2 BAM is registered before starting controller
+	 * and only if bam2bam function is present in composition
+	 */
+	if (bam_type == CI_CTRL)
+		return 0;
+
+	memset(&props, 0, sizeof(props));
+	msm_usb_bam_update_props(&props, pdev);
 	ret = sps_register_bam_device(&props, &ctx->h_bam);
 	if (ret < 0) {
 		log_event_err("%s: register bam error %d\n", __func__, ret);
@@ -3428,7 +3439,7 @@
 		return 0;
 
 	usb_bam_data = ctx->usb_bam_data;
-	if ((bam != CI_CTRL) || !usb_bam_data->enable_hsusb_bam_on_boot)
+	if (bam != CI_CTRL)
 		return 0;
 
 	if (!ctx->pipes_enabled_per_bam || info[bam].pipes_suspended)
@@ -3532,18 +3543,44 @@
 {
 	struct msm_usb_bam_data *usb_bam_data;
 	struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam];
+	static bool bam_enabled;
+	int ret;
 
 	if (!ctx->usb_bam_pdev)
 		return 0;
 
 	usb_bam_data = ctx->usb_bam_data;
-	if ((bam != CI_CTRL) || !(bam_enable ||
-					usb_bam_data->enable_hsusb_bam_on_boot))
+	if (bam != CI_CTRL)
 		return 0;
 
-	msm_hw_bam_disable(1);
-	sps_device_reset(ctx->h_bam);
-	msm_hw_bam_disable(0);
+	if (bam_enabled == bam_enable) {
+		log_event_dbg("%s: USB BAM is already %s\n", __func__,
+				bam_enable ? "Registered" : "De-registered");
+		return 0;
+	}
+
+	if (bam_enable) {
+		struct sps_bam_props props;
+
+		memset(&props, 0, sizeof(props));
+		msm_usb_bam_update_props(&props, ctx->usb_bam_pdev);
+		msm_hw_bam_disable(1);
+		ret = sps_register_bam_device(&props, &ctx->h_bam);
+		bam_enabled = true;
+		if (ret < 0) {
+			log_event_err("%s: register bam error %d\n",
+					__func__, ret);
+			return -EFAULT;
+		}
+		log_event_dbg("%s: USB BAM Registered\n", __func__);
+		msm_hw_bam_disable(0);
+	} else {
+		msm_hw_bam_disable(1);
+		sps_device_reset(ctx->h_bam);
+		sps_deregister_bam_device(ctx->h_bam);
+		log_event_dbg("%s: USB BAM De-registered\n", __func__);
+		bam_enabled = false;
+	}
 
 	return 0;
 }
diff --git a/drivers/usb/gadget/function/f_qc_rndis.c b/drivers/usb/gadget/function/f_qc_rndis.c
index 908805a..df26403 100644
--- a/drivers/usb/gadget/function/f_qc_rndis.c
+++ b/drivers/usb/gadget/function/f_qc_rndis.c
@@ -1063,6 +1063,7 @@
 	 * until we're activated via set_alt().
 	 */
 
+	c->cdev->gadget->bam2bam_func_enabled = true;
 	DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n",
 			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -1116,6 +1117,7 @@
 		usb_free_descriptors(f->hs_descriptors);
 	usb_free_descriptors(f->fs_descriptors);
 
+	c->cdev->gadget->bam2bam_func_enabled = false;
 	kfree(rndis->notify_req->buf);
 	usb_ep_free_request(rndis->notify, rndis->notify_req);
 
diff --git a/drivers/usb/gadget/function/f_qdss.c b/drivers/usb/gadget/function/f_qdss.c
index 6ae2693..d1c3741 100644
--- a/drivers/usb/gadget/function/f_qdss.c
+++ b/drivers/usb/gadget/function/f_qdss.c
@@ -478,6 +478,7 @@
 		}
 	}
 
+	c->cdev->gadget->bam2bam_func_enabled = true;
 	return 0;
 fail:
 	clear_eps(f);
@@ -494,7 +495,7 @@
 	pr_debug("qdss_unbind\n");
 
 	flush_workqueue(qdss->wq);
-
+	c->cdev->gadget->bam2bam_func_enabled = false;
 	clear_eps(f);
 	clear_desc(gadget, f);
 }
diff --git a/drivers/usb/gadget/function/f_rmnet.c b/drivers/usb/gadget/function/f_rmnet.c
index ffc6897..bdb9762 100644
--- a/drivers/usb/gadget/function/f_rmnet.c
+++ b/drivers/usb/gadget/function/f_rmnet.c
@@ -480,6 +480,8 @@
 
 	if (dev->notify_req)
 		frmnet_free_req(dev->notify, dev->notify_req);
+
+	c->cdev->gadget->bam2bam_func_enabled = false;
 }
 
 static void frmnet_purge_responses(struct f_rmnet *dev)
@@ -1116,6 +1118,9 @@
 		return dev->ifc_id;
 	}
 
+	if (dev->xport_type == BAM2BAM_IPA)
+		c->cdev->gadget->bam2bam_func_enabled = true;
+
 	info.data_str_idx = 0;
 	if (dev->qti_port_type == QTI_PORT_RMNET) {
 		info.string_defs = rmnet_string_defs;
diff --git a/include/linux/usb_bam.h b/include/linux/usb_bam.h
index fc0647a..3811e34 100644
--- a/include/linux/usb_bam.h
+++ b/include/linux/usb_bam.h
@@ -216,7 +216,6 @@
  *		can work at in bam2bam mode when connected to HS host.
  * @max_mbps_superspeed: Maximum Mbits per seconds that the USB core
  *		can work at in bam2bam mode when connected to SS host.
- * @enable_hsusb_bam_on_boot: Enable HSUSB BAM (non-NDP) on bootup itself
  */
 struct msm_usb_bam_data {
 	u8 max_connections;
@@ -229,7 +228,6 @@
 	u32 override_threshold;
 	u32 max_mbps_highspeed;
 	u32 max_mbps_superspeed;
-	bool enable_hsusb_bam_on_boot;
 	enum usb_ctrl bam_type;
 };