diff -ur linux/drivers/s390/net/iucv.c new/iucv.c
--- linux/drivers/s390/net/iucv.c	Fri Apr 12 12:38:32 2002
+++ new/iucv.c	Fri Apr 12 12:37:19 2002
@@ -482,7 +482,7 @@
 b2f0(__u32 code, void *parm)
 {
 	iucv_debug("iparml before b2f0 call:");
-	iucv_dumpit(parm, sizeof(iucv_param.param));
+	iucv_dumpit(parm, sizeof(iucv_param));
 
 	asm volatile (
 		"LRA   1,0(%1)\n\t"
@@ -494,7 +494,7 @@
 		);
 
 	iucv_debug("iparml after b2f0 call:");
-	iucv_dumpit(parm, sizeof(iucv_param.param));
+	iucv_dumpit(parm, sizeof(iucv_param));
 
 	return (unsigned long)*((__u8 *)(parm + 3));
 }
@@ -952,6 +952,24 @@
 		EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget));
 	}
 
+	/* In order to establish an IUCV connection, the procedure is:
+	 *
+	 * b2f0(CONNECT)
+	 * take the ippathid from the b2f0 call
+	 * register the handler to the ippathid
+	 * 
+	 * Unfortunately, the ConnectionEstablished message gets sent after the
+	 * b2f0(CONNECT) call but before the register is handled.
+	 *
+	 * In order for this race condition to be eliminated, the IUCV Control
+	 * Interrupts must be disabled for the above procedure.
+	 *
+	 * David Kennedy <dkennedy@linuxcare.com>
+	 */
+
+	/* Enable everything but IUCV Control messages */
+	iucv_setmask(~(IUCVControlInterruptsFlag));
+
 	parm->ipflags1 = (__u8)flags1;
 	b2f0_result = b2f0(CONNECT, parm);
 
@@ -963,6 +981,9 @@
 	add_pathid_result = iucv_add_pathid(parm->ippathid, h);
 	*pathid = parm->ippathid;
 
+	/* Enable everything again */
+	iucv_setmask(~0);
+
 	if (msglim)
 		*msglim = parm->ipmsglim;
 	if (flags1_out)
@@ -1961,6 +1982,7 @@
  *           0x40 - Priority_MessagePendingInterruptsFlag
  *           0x20 - Nonpriority_MessageCompletionInterruptsFlag
  *           0x10 - Priority_MessageCompletionInterruptsFlag
+ *           0x08 - IUCVControlInterruptsFlag
  * Output: NA
  * Return: b2f0_result - return code from CP
 */
@@ -2129,7 +2151,7 @@
 					iucv_sever (int_buf->ippathid,
 						    no_listener);
 					iucv_debug("add_pathid failed, rc = %d",
-						   (int)add_pathid_result);
+						   (int)rc);
 				} else {
 					interrupt = h->interrupt_table;
 					if (interrupt->ConnectionPending) {
@@ -2146,11 +2168,15 @@
 			break;
 			
 		case 0x02:		/*connection complete */
+			iucv_debug("entering");
 			if (h) {
 				if (interrupt->ConnectionComplete)
+				{
+					iucv_debug("calling ConnectionComplete");
 					interrupt->ConnectionComplete(
 						(iucv_ConnectionComplete *)int_buf,
 						h->pgm_data);
+				}
 				else
 					iucv_debug("ConnectionComplete not called");
 			}
diff -ur linux/drivers/s390/net/iucv.h new/iucv.h
--- linux/drivers/s390/net/iucv.h	Thu Apr 11 16:07:32 2002
+++ new/iucv.h	Fri Apr 12 09:47:52 2002
@@ -62,6 +62,8 @@
 #define Priority_MessagePendingInterruptsFlag            0x40
 #define Nonpriority_MessageCompletionInterruptsFlag      0x20
 #define Priority_MessageCompletionInterruptsFlag         0x10
+#define IUCVControlInterruptsFlag                        0x08
+
 /*
  * Mapping of external interrupt buffers should be used with the corresponding
  * interrupt types.                  
@@ -735,6 +737,7 @@
  *           0x40 - Priority_MessagePendingInterruptsFlag            
  *           0x20 - Nonpriority_MessageCompletionInterruptsFlag      
  *           0x10 - Priority_MessageCompletionInterruptsFlag         
+ *           0x08 - IUCVControlInterruptsFlag         
  * Output: NA                                                        
  * Return: Return code from CP IUCV call.                         
 */
diff -ur linux/drivers/s390/net/netiucv.c new/netiucv.c
--- linux/drivers/s390/net/netiucv.c	Fri Apr 12 12:38:41 2002
+++ new/netiucv.c	Fri Apr 12 09:49:36 2002
@@ -443,6 +443,10 @@
 	iucv_connection *conn = (iucv_connection *)pgm_data;
 	iucv_event ev;
 
+#ifdef DEBUG
+	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
+#endif
+
 	ev.conn = conn;
 	ev.data = (void *)eib;
 	fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, &ev);
@@ -806,10 +810,15 @@
 	printk(KERN_DEBUG "%s('%s'): connecting ...\n",
 	       conn->netdev->name, conn->userid);
 #endif
+
+	/* We must set the state before calling iucv_connect because the callback
+	 * handler could be called at any point after the connection request is
+	 * sent. */
+
+	fsm_newstate(fi, CONN_STATE_SETUPWAIT);
 	rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,
 			  conn->userid, iucv_host, 0, NULL, NULL, conn->handle,
 			  conn);
-	fsm_newstate(fi, CONN_STATE_SETUPWAIT);
 	switch (rc) {
 		case 0:
 			return;
