usb: gadget: u_bam_data: Add support for BAM reset

This change adds the capability for f_qc_rndis, f_qc_ecm and
f_mbim running in BAM-to-BAM mode, to perform USB BAM reset,
upon a peer BAM reset.

The u_bam_data registers a callback from USB BAM driver, to be
notified about peer BAM reset. When the callback is invoked,
USB BAM reset is executed.

Change-Id: Ia7d8f4a5bbef78c83e0ca0891511547001df29a9
CRs-Fixed: 424867
Signed-off-by: Amit Blay <ablay@codeaurora.org>
diff --git a/drivers/usb/gadget/f_qc_ecm.c b/drivers/usb/gadget/f_qc_ecm.c
index 0b41197..b1c5985 100644
--- a/drivers/usb/gadget/f_qc_ecm.c
+++ b/drivers/usb/gadget/f_qc_ecm.c
@@ -324,8 +324,9 @@
 
 static int ecm_qc_bam_disconnect(struct f_ecm_qc *dev)
 {
-	pr_debug("dev:%p. %s Do nothing.\n",
-			 dev, __func__);
+	pr_debug("dev:%p. %s Disconnect BAM.\n", dev, __func__);
+
+	bam_data_disconnect(&ecm_qc_bam_port, 0);
 
 	return 0;
 }
@@ -518,8 +519,12 @@
 
 		if (ecm->port.in_ep->driver_data) {
 			DBG(cdev, "reset ecm\n");
-			gether_qc_disconnect_name(&ecm->port, "ecm0");
+			/* ecm->port is needed for disconnecting the BAM data
+			 * path. Only after the BAM data path is disconnected,
+			 * we can disconnect the port from the network layer.
+			 */
 			ecm_qc_bam_disconnect(ecm);
+			gether_qc_disconnect_name(&ecm->port, "ecm0");
 		}
 
 		if (!ecm->port.in_ep->desc ||
@@ -591,8 +596,8 @@
 	DBG(cdev, "ecm deactivated\n");
 
 	if (ecm->port.in_ep->driver_data) {
-		gether_qc_disconnect_name(&ecm->port, "ecm0");
 		ecm_qc_bam_disconnect(ecm);
+		gether_qc_disconnect_name(&ecm->port, "ecm0");
 	}
 
 	if (ecm->notify->driver_data) {