usb: gsmd: Handle SMD Closing Delay Retry

Add a retry to handle the case where the SMD port is
closed and a re-open is attempted before the SMD port
close event has been processed by the remote processor.

CRs-Fixed: 327710
Change-Id: I112dc3ff3712d2a8900e4e02bcd296b50dfe0b24
Signed-off-by: Eric Holmberg <eholmber@codeaurora.org>
diff --git a/drivers/usb/gadget/u_smd.c b/drivers/usb/gadget/u_smd.c
index 93a96be..95adf5d 100644
--- a/drivers/usb/gadget/u_smd.c
+++ b/drivers/usb/gadget/u_smd.c
@@ -71,7 +71,7 @@
 	struct gserial		*port_usb;
 
 	struct smd_port_info	*pi;
-	struct work_struct	connect_work;
+	struct delayed_work	connect_work;
 
 	/* At present, smd does not notify
 	 * control bit change info from modem
@@ -562,7 +562,7 @@
 	struct smd_port_info *pi;
 	int ret;
 
-	port = container_of(w, struct gsmd_port, connect_work);
+	port = container_of(w, struct gsmd_port, connect_work.work);
 	pi = port->pi;
 
 	pr_debug("%s: port:%p port#%d\n", __func__, port, port->port_num);
@@ -573,9 +573,16 @@
 	ret = smd_named_open_on_edge(pi->name, SMD_APPS_MODEM,
 				&pi->ch, port, gsmd_notify);
 	if (ret) {
-		pr_err("%s: unable to open smd port:%s err:%d\n",
-				__func__, pi->name, ret);
-		return;
+		if (ret == -EAGAIN) {
+			/* port not ready  - retry */
+			pr_debug("%s: SMD port not ready - rescheduling:%s err:%d\n",
+					__func__, pi->name, ret);
+			queue_delayed_work(gsmd_wq, &port->connect_work,
+				msecs_to_jiffies(250));
+		} else {
+			pr_err("%s: unable to open smd port:%s err:%d\n",
+					__func__, pi->name, ret);
+		}
 	}
 }
 
@@ -672,7 +679,7 @@
 	}
 	gser->out->driver_data = port;
 
-	queue_work(gsmd_wq, &port->connect_work);
+	queue_delayed_work(gsmd_wq, &port->connect_work, msecs_to_jiffies(0));
 
 	return 0;
 }
@@ -743,7 +750,8 @@
 			set_bit(CH_READY, &pi->flags);
 			spin_lock_irqsave(&port->port_lock, flags);
 			if (port->port_usb)
-				queue_work(gsmd_wq, &port->connect_work);
+				queue_delayed_work(gsmd_wq, &port->connect_work,
+					msecs_to_jiffies(0));
 			spin_unlock_irqrestore(&port->port_lock, flags);
 			break;
 		}
@@ -805,7 +813,7 @@
 	INIT_LIST_HEAD(&port->write_pool);
 	INIT_WORK(&port->pull, gsmd_tx_pull);
 
-	INIT_WORK(&port->connect_work, gsmd_connect_work);
+	INIT_DELAYED_WORK(&port->connect_work, gsmd_connect_work);
 
 	smd_ports[portno].port = port;
 	pdrv = &smd_ports[portno].pdrv;