1c8eda8
diff -aurp open-iscsi-2.0-872-rc1-bnx2i/usr/initiator.c open-iscsi-2.0-872-rc1-bnx2i.work/usr/initiator.c
1c8eda8
--- open-iscsi-2.0-872-rc1-bnx2i/usr/initiator.c	2010-05-18 17:58:00.000000000 -0500
1c8eda8
+++ open-iscsi-2.0-872-rc1-bnx2i.work/usr/initiator.c	2010-05-18 21:40:44.000000000 -0500
1c8eda8
@@ -1096,6 +1096,18 @@ static void iscsi_login_timedout(void *d
1c8eda8
 	}
1c8eda8
 }
1c8eda8
 
1c8eda8
+static void iscsi_uio_poll_login_timedout(void *data)
1c8eda8
+{
1c8eda8
+	struct queue_task *qtask = data;
1c8eda8
+	struct iscsi_conn *conn = qtask->conn;
1c8eda8
+	iscsi_session_t *session = conn->session;
1c8eda8
+
1c8eda8
+	log_debug(3, "timeout waiting for UIO ...\n");
1c8eda8
+	mgmt_ipc_write_rsp(qtask, MGMT_IPC_ERR_TRANS_TIMEOUT);
1c8eda8
+	conn_delete_timers(conn);
1c8eda8
+	__session_destroy(session);
1c8eda8
+}
1c8eda8
+
1c8eda8
 static void iscsi_login_redirect(iscsi_conn_t *conn)
1c8eda8
 {
1c8eda8
 	iscsi_session_t *session = conn->session;
1c8eda8
@@ -2049,6 +2061,52 @@ cleanup:
1c8eda8
 	session_conn_shutdown(conn, qtask, err);
1c8eda8
 }
1c8eda8
 
1c8eda8
+static void session_conn_uio_poll(void *data)
1c8eda8
+{
1c8eda8
+	struct iscsi_conn_context *conn_context = data;
1c8eda8
+	iscsi_conn_t *conn = conn_context->conn;
1c8eda8
+	struct iscsi_session *session = conn->session;
1c8eda8
+	queue_task_t *qtask = conn_context->data;
1c8eda8
+	int rc;
1c8eda8
+
1c8eda8
+	log_debug(4, "retrying uio poll");
1c8eda8
+	rc = __set_net_config(session->t, session, &conn->session->nrec.iface);
1c8eda8
+	if (rc != 0) {
1c8eda8
+		if (rc == -EAGAIN) {
1c8eda8
+			conn_context->data = qtask;
1c8eda8
+			iscsi_sched_conn_context(conn_context, conn, 2,
1c8eda8
+						 EV_UIO_POLL);
1c8eda8
+			return;
1c8eda8
+		} else {
1c8eda8
+			log_error("session_conn_uio_poll() "
1c8eda8
+				  "connection failure [0x%x]", rc);
1c8eda8
+			actor_delete(&conn->login_timer);
1c8eda8
+			iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_INTERNAL);
1c8eda8
+			iscsi_conn_context_put(conn_context);
1c8eda8
+			return;
1c8eda8
+		}
1c8eda8
+	}
1c8eda8
+	iscsi_conn_context_put(conn_context);
1c8eda8
+
1c8eda8
+	actor_delete(&conn->login_timer);
1c8eda8
+	log_debug(4, "UIO ready trying connect");
1c8eda8
+
1c8eda8
+	/*  uIP is ready try to connect */
1c8eda8
+	if (gettimeofday(&conn->initial_connect_time, NULL))
1c8eda8
+		log_error("Could not get initial connect time. If "
1c8eda8
+			  "login errors iscsid may give up the initial "
1c8eda8
+			  "login early. You should manually login.");
1c8eda8
+
1c8eda8
+        conn->state = STATE_XPT_WAIT;
1c8eda8
+        if (iscsi_conn_connect(conn, qtask)) {
1c8eda8
+		int delay = ISCSI_CONN_ERR_REOPEN_DELAY;
1c8eda8
+		log_debug(4, "Waiting %u seconds before trying to reconnect.\n",
1c8eda8
+			  delay);
1c8eda8
+		queue_delayed_reopen(qtask, delay);
1c8eda8
+        }
1c8eda8
+}
1c8eda8
+
1c8eda8
+
1c8eda8
 void iscsi_sched_conn_context(struct iscsi_conn_context *conn_context,
1c8eda8
 			      struct iscsi_conn *conn, unsigned long tmo,
1c8eda8
 			      int event)
1c8eda8
@@ -2085,6 +2143,11 @@ void iscsi_sched_conn_context(struct isc
1c8eda8
 			  conn_context);
1c8eda8
 		actor_schedule(&conn_context->actor);
1c8eda8
 		break;
1c8eda8
+	case EV_UIO_POLL:
1c8eda8
+		actor_new(&conn_context->actor, session_conn_uio_poll,
1c8eda8
+			  conn_context);
1c8eda8
+		actor_schedule(&conn_context->actor);
1c8eda8
+		break;
1c8eda8
 	case EV_CONN_LOGOUT_TIMER:
1c8eda8
 		actor_timer(&conn_context->actor, tmo * 1000,
1c8eda8
 			    iscsi_logout_timedout, conn_context);
1c8eda8
@@ -2150,8 +2213,10 @@ static int session_is_running(node_rec_t
1c8eda8
 }
1c8eda8
 
1c8eda8
 static int iface_set_param(struct iscsi_transport *t, struct iface_rec *iface,
1c8eda8
-			   struct iscsi_session *session)
1c8eda8
+			   queue_task_t *qtask)
1c8eda8
 {
1c8eda8
+	struct iscsi_conn *conn = qtask->conn;
1c8eda8
+	struct iscsi_session *session = conn->session;
1c8eda8
 	int rc = 0;
1c8eda8
 
1c8eda8
 	log_debug(3, "setting iface %s, dev %s, set ip %s, hw %s, "
1c8eda8
@@ -2170,6 +2235,29 @@ static int iface_set_param(struct iscsi_
1c8eda8
 	}
1c8eda8
 
1c8eda8
 	rc = __set_net_config(t, session, iface);
1c8eda8
+	if (rc == -EAGAIN && t->template->set_net_config) {
1c8eda8
+		struct iscsi_conn_context *conn_context;
1c8eda8
+
1c8eda8
+		conn_context = iscsi_conn_context_get(conn, 0);
1c8eda8
+		if (!conn_context) {
1c8eda8
+			/* while reopening the recv pool should be full */
1c8eda8
+			log_error("BUG: __session_conn_reopen could "
1c8eda8
+				  "not get conn context for recv.");
1c8eda8
+			return ENOMEM;
1c8eda8
+		}
1c8eda8
+		conn_context->data = qtask;
1c8eda8
+		conn->state = STATE_XPT_WAIT;
1c8eda8
+
1c8eda8
+		iscsi_sched_conn_context(conn_context, conn, 0, EV_UIO_POLL);
1c8eda8
+
1c8eda8
+		log_debug(3, "Setting login UIO poll timer "
1c8eda8
+			     "%p timeout %d", &conn->login_timer,
1c8eda8
+			  conn->login_timeout);
1c8eda8
+		actor_timer(&conn->login_timer, conn->login_timeout * 1000,
1c8eda8
+	 		    iscsi_uio_poll_login_timedout, qtask);
1c8eda8
+
1c8eda8
+		return EAGAIN;
1c8eda8
+	}
1c8eda8
 	if (rc != 0)
1c8eda8
 		return rc;
1c8eda8
 
1c8eda8
@@ -2203,6 +2291,7 @@ session_login_task(node_rec_t *rec, queu
1c8eda8
 	iscsi_session_t *session;
1c8eda8
 	iscsi_conn_t *conn;
1c8eda8
 	struct iscsi_transport *t;
1c8eda8
+	int rc;
1c8eda8
 
1c8eda8
 	if (session_is_running(rec))
1c8eda8
 		return MGMT_IPC_ERR_EXISTS;
1c8eda8
@@ -2276,7 +2365,16 @@ session_login_task(node_rec_t *rec, queu
1c8eda8
 	conn = &session->conn[0];
1c8eda8
 	qtask->conn = conn;
1c8eda8
 
1c8eda8
-	if (iface_set_param(t, &rec->iface, session)) {
1c8eda8
+	rc =  iface_set_param(t, &rec->iface, qtask);
1c8eda8
+	if (rc == EAGAIN)  {
1c8eda8
+		/*
1c8eda8
+		 * Cannot block iscsid, so caller is going to internally
1c8eda8
+		 * retry the operation.
1c8eda8
+		 */
1c8eda8
+		qtask->rsp.command = MGMT_IPC_SESSION_LOGIN;
1c8eda8
+		qtask->rsp.err = MGMT_IPC_OK;
1c8eda8
+		return MGMT_IPC_OK;
1c8eda8
+	} else if (rc) {
1c8eda8
 		__session_destroy(session);
1c8eda8
 		return MGMT_IPC_ERR_LOGIN_FAILURE;
1c8eda8
 	}
1c8eda8
Only in open-iscsi-2.0-872-rc1-bnx2i.work/usr/: initiator.c.orig
1c8eda8
diff -aurp open-iscsi-2.0-872-rc1-bnx2i/usr/initiator.h open-iscsi-2.0-872-rc1-bnx2i.work/usr/initiator.h
1c8eda8
--- open-iscsi-2.0-872-rc1-bnx2i/usr/initiator.h	2010-05-18 17:58:00.000000000 -0500
1c8eda8
+++ open-iscsi-2.0-872-rc1-bnx2i.work/usr/initiator.h	2010-05-18 18:13:12.000000000 -0500
1c8eda8
@@ -88,6 +88,7 @@ typedef enum iscsi_event_e {
1c8eda8
 	EV_CONN_ERROR,
1c8eda8
 	EV_CONN_LOGOUT_TIMER,
1c8eda8
 	EV_CONN_STOP,
1c8eda8
+	EV_UIO_POLL,
1c8eda8
 } iscsi_event_e;
1c8eda8
 
1c8eda8
 struct queue_task;
1c8eda8
diff -aurp open-iscsi-2.0-872-rc1-bnx2i/usr/iscsid_req.c open-iscsi-2.0-872-rc1-bnx2i.work/usr/iscsid_req.c
1c8eda8
--- open-iscsi-2.0-872-rc1-bnx2i/usr/iscsid_req.c	2010-05-18 17:58:00.000000000 -0500
1c8eda8
+++ open-iscsi-2.0-872-rc1-bnx2i.work/usr/iscsid_req.c	2010-05-18 21:16:21.000000000 -0500
1c8eda8
@@ -217,6 +217,8 @@ int uip_broadcast(void *buf, size_t buf_
1c8eda8
 		return err;
1c8eda8
 	}
1c8eda8
 
1c8eda8
+	log_debug(3, "connected to uIP daemon");
1c8eda8
+
1c8eda8
 	/*  Send the data to uIP */
1c8eda8
 	if ((err = write(fd, buf, buf_len)) != buf_len) {
1c8eda8
 		log_error("got write error (%d/%d), daemon died?",
1c8eda8
@@ -225,6 +227,8 @@ int uip_broadcast(void *buf, size_t buf_
1c8eda8
 		return -EIO;
1c8eda8
 	}
1c8eda8
 
1c8eda8
+	log_debug(3, "send iface config to uIP daemon");
1c8eda8
+
1c8eda8
 	/*  Set the socket to a non-blocking read, this way if there are
1c8eda8
 	 *  problems waiting for uIP, iscsid can bailout early */
1c8eda8
 	flags = fcntl(fd, F_GETFL, 0);
1c8eda8
@@ -243,8 +247,10 @@ int uip_broadcast(void *buf, size_t buf_
1c8eda8
 		/*  Wait for the response */
1c8eda8
 		err = read(fd, &rsp, sizeof(rsp));
1c8eda8
 		if (err == sizeof(rsp)) {
1c8eda8
-			log_debug(3, "Broadcasted to uIP with length: %ld\n",
1c8eda8
-				  buf_len);
1c8eda8
+			log_debug(3, "Broadcasted to uIP with length: %ld "
1c8eda8
+				     "cmd: 0x%x rsp: 0x%x\n", buf_len,
1c8eda8
+				     rsp.command, rsp.err);
1c8eda8
+			err = 0;
1c8eda8
 			break;
1c8eda8
 		} else if((err == -1) && (errno == EAGAIN)) {
1c8eda8
 			usleep(250000);
1c8eda8
@@ -256,12 +262,17 @@ int uip_broadcast(void *buf, size_t buf_
1c8eda8
 		}
1c8eda8
 	}
1c8eda8
 
1c8eda8
-	if(count == MAX_UIP_BROADCAST_READ_TRIES)
1c8eda8
-		log_error("Could not broadcast to uIP");
1c8eda8
+	if (count == MAX_UIP_BROADCAST_READ_TRIES) {
1c8eda8
+		log_error("Could not broadcast to uIP after %d tries",
1c8eda8
+			  count);
1c8eda8
+		err = -EAGAIN;
1c8eda8
+	} else if (rsp.err != ISCISD_UIP_MGMT_IPC_DEVICE_UP) {
1c8eda8
+		log_debug(3, "Device is not ready\n");
1c8eda8
+		err = -EAGAIN;
1c8eda8
+	}
1c8eda8
 
1c8eda8
 	close(fd);
1c8eda8
-
1c8eda8
-	return 0;
1c8eda8
+	return err;
1c8eda8
 }
1c8eda8
 
1c8eda8
 void iscsid_handle_error(mgmt_ipc_err_e err)
1c8eda8
Only in open-iscsi-2.0-872-rc1-bnx2i.work/usr/: iscsid_req.c.orig
1c8eda8
diff -aurp open-iscsi-2.0-872-rc1-bnx2i/usr/uip_mgmt_ipc.h open-iscsi-2.0-872-rc1-bnx2i.work/usr/uip_mgmt_ipc.h
1c8eda8
--- open-iscsi-2.0-872-rc1-bnx2i/usr/uip_mgmt_ipc.h	2010-05-18 17:58:00.000000000 -0500
1c8eda8
+++ open-iscsi-2.0-872-rc1-bnx2i.work/usr/uip_mgmt_ipc.h	2010-05-18 18:13:12.000000000 -0500
1c8eda8
@@ -55,6 +55,8 @@ typedef enum iscsid_uip_mgmt_ipc_err {
1c8eda8
         ISCISD_UIP_MGMT_IPC_ERR                    = 1,
1c8eda8
         ISCISD_UIP_MGMT_IPC_ERR_NOT_FOUND          = 2,
1c8eda8
         ISCISD_UIP_MGMT_IPC_ERR_NOMEM              = 3,
1c8eda8
+	ISCISD_UIP_MGMT_IPC_DEVICE_UP              = 4,
1c8eda8
+	ISCISD_UIP_MGMT_IPC_DEVICE_INITIALIZING    = 5,
1c8eda8
 } iscsid_uip_mgmt_ipc_err_e;
1c8eda8
 
1c8eda8
 /* IPC Response */