# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.524.9.8 -> 1.524.9.9
#	drivers/usb/serial/ipaq.c	1.14    -> 1.15   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/08/01	ganesh@vxindia.veritas.com	1.524.9.9
# [PATCH] bugfix for drivers/usb/serial/ipaq.c
# 
# Buggy error handling fixed. Retry the "kickstart" packet much harder -
# this greatly reduces instances of connection failures.
# --------------------------------------------
#
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	Fri Aug  2 11:15:34 2002
+++ b/drivers/usb/serial/ipaq.c	Fri Aug  2 11:15:34 2002
@@ -9,6 +9,10 @@
  *	the Free Software Foundation; either version 2 of the License, or
  *	(at your option) any later version.
  *
+ * (26/7/2002) ganesh
+ * 	Fixed up broken error handling in ipaq_open. Retry the "kickstart"
+ * 	packet much harder - this drastically reduces connection failures.
+ *
  * (30/4/2002) ganesh
  * 	Added support for the Casio EM500. Completely untested. Thanks
  * 	to info from Nathan <wfilardo@fuse.net>
@@ -54,6 +58,8 @@
 #include "usb-serial.h"
 #include "ipaq.h"
 
+#define KP_RETRIES	100
+
 /*
  * Version Information
  */
@@ -118,6 +124,7 @@
 	struct ipaq_private	*priv;
 	struct ipaq_packet	*pkt;
 	int			i, result = 0;
+	int			retries = KP_RETRIES;
 
 	if (port_paranoia_check(port, __FUNCTION__)) {
 		return -ENODEV;
@@ -192,31 +199,35 @@
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result) {
 		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+		goto error;
 	}
 
 	/*
-	 * Send out two control messages observed in win98 sniffs. Not sure what
-	 * they do.
+	 * Send out control message observed in win98 sniffs. Not sure what
+	 * it does, but from empirical observations, it seems that the device
+	 * will start the chat sequence once one of these messages gets
+	 * through. Since this has a reasonably high failure rate, we retry
+	 * several times.
 	 */
 
-	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
-			0x1, 0, NULL, 0, 5 * HZ);
-	if (result < 0) {
-		err(__FUNCTION__ " - failed doing control urb, error %d", result);
-	}
-	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
-			0x1, 0, NULL, 0, 5 * HZ);
-	if (result < 0) {
-		err(__FUNCTION__ " - failed doing control urb, error %d", result);
+	while (retries--) {
+		result = usb_control_msg(serial->dev,
+				usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
+				0x1, 0, NULL, 0, HZ / 10 + 1);
+		if (result == 0) {
+			return 0;
+		}
 	}
-	
-	return result;
+	err(__FUNCTION__ " - failed doing control urb, error %d", result);
+	goto error;
 
 enomem:
+	result = -ENOMEM;
+	err(__FUNCTION__ " - Out of memory");
+error:
 	ipaq_destroy_lists(port);
 	kfree(priv);
-	err(__FUNCTION__ " - Out of memory");
-	return -ENOMEM;
+	return result;
 }