patch-2.3.27 linux/drivers/i2o/i2o_core.c

Next file: linux/drivers/i2o/i2o_lan.c
Previous file: linux/drivers/i2o/i2o_config.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
@@ -35,6 +35,7 @@
 
 #include <linux/bitops.h>
 #include <linux/wait.h>
+#include <linux/delay.h>
 #include <linux/timer.h>
 
 #include <asm/io.h>
@@ -927,7 +928,7 @@
 	u32 *p;
 	struct i2o_device *d;
 	char str[22];
-	pi2o_lct lct = c->lct;
+	i2o_lct *lct = c->lct;
 
 	max = lct->table_size;
 	
@@ -1168,6 +1169,9 @@
 
 	/* Wait for a reply */
 	time=jiffies;
+	
+	/* DPT driver claims they need this */
+	mdelay(5);
 
 #ifdef DRIVERDEBUG
 	printk(KERN_INFO "Reset posted, waiting...\n");
@@ -1192,7 +1196,7 @@
 	{
 		/* 
 		 * Once the reset is sent, the IOP goes into the INIT state 
-		 * which is inditerminate.  We need to wait until the IOP 
+		 * which is indeterminate.  We need to wait until the IOP 
 		 * has rebooted before we can let the system talk to 
 		 * it. We read the inbound Free_List until a message is 
 		 * available.  If we can't read one in the given ammount of 
@@ -1230,6 +1234,7 @@
 	u32 m;
 	u32 *msg;
 	u8 *status_block;
+	int i;
 
 #ifdef DRIVERDEBUG
 	printk(KERN_INFO "Getting status block for iop%d\n", c->unit);
@@ -1238,7 +1243,7 @@
 		kfree(c->status_block);
 
 	c->status_block = 
-		(pi2o_status_block)kmalloc(sizeof(i2o_status_block),GFP_KERNEL);
+		(i2o_status_block *)kmalloc(sizeof(i2o_status_block),GFP_KERNEL);
 	if(c->status_block == NULL)
 	{
 #ifdef DRIVERDEBUG
@@ -1248,45 +1253,53 @@
 	}
 
 	status_block = (u8*)c->status_block;
+	
+	for(i=0;i<5;i++)
+	{
+		m=i2o_wait_message(c, "StatusGet");
+		if(m==0xFFFFFFFF)
+			return -ETIMEDOUT;
+		
+		memset(status_block, 0, sizeof(i2o_status_block));
+	
+		msg=(u32 *)(c->mem_offset+m);
 
-	m=i2o_wait_message(c, "StatusGet");
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;
-
-	msg=(u32 *)(c->mem_offset+m);
-
-	msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
-	msg[2]=core_context;
-	msg[3]=0;
-	msg[4]=0;
-	msg[5]=0;
-	msg[6]=virt_to_phys(c->status_block);
-	msg[7]=0;	/* 64bit host FIXME */
-	msg[8]=88;
-
-	i2o_post_message(c,m);
+		__raw_writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]);
+		__raw_writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]);
+		__raw_writel(0, &msg[2]);
+	 	__raw_writel(0, &msg[3]);
+	 	__raw_writel(0, &msg[4]);
+	 	__raw_writel(0, &msg[5]);
+		__raw_writel(virt_to_bus(c->status_block), &msg[6]);
+		__raw_writel(0, &msg[7]);	/* 64bit host FIXME */
+		__raw_writel(sizeof(i2o_status_block), &msg[8]);
+		
+		printk("SB is %d bytes.\n", sizeof(i2o_status_block));
 
-	/* Wait for a reply */
-	time=jiffies;
+		i2o_post_message(c,m);
+		
+		/* DPT work around */
+		mdelay(5);
 
-	while(status_block[87]!=0xFF)
-	{
-		if((jiffies-time)>=5*HZ)
+		/* Wait for a reply */
+		time=jiffies;
+	
+		while((jiffies-time)<=HZ)
 		{
+			if(status_block[87]!=0)
+			{
+				/* Ok the reply has arrived. Fill in the important stuff */
+				c->inbound_size = (status_block[12]|(status_block[13]<<8))*4;
+				return 0;
+			}
+			schedule();
+			barrier();
+		}
 #ifdef DRIVERDEBUG
-			printk(KERN_ERR "IOP get status timeout.\n");
+		printk(KERN_ERR "IOP get status timeout.\n");
 #endif
-			return -ETIMEDOUT;
-		}
-		schedule();
-		barrier();
 	}
-	
-	/* Ok the reply has arrived. Fill in the important stuff */
-	c->inbound_size = (status_block[12]|(status_block[13]<<8))*4;
-
-	return 0;
+	return 0;//-ETIMEDOUT;
 }
 
 
@@ -1354,7 +1367,7 @@
  */
 static void __init i2o_sys_init()
 {
-	struct i2o_controller *iop;
+	struct i2o_controller *iop, *niop;
 	int ret;
 	u32 m;
 
@@ -1362,18 +1375,30 @@
 	printk(KERN_INFO "This may take a few minutes if there are many devices\n");
 
 	/* Get the status for each IOP */
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 	{
+		niop = iop->next;
 #ifdef DRIVERDEBUG
 		printk(KERN_INFO "Getting initial status for iop%d\n", iop->unit);
 #endif
-		i2o_status_get(iop);
+		if(i2o_status_get(iop)<0)
+		{
+			printk("Unable to obtain status of IOP, attempting a reset.\n");
+			i2o_reset_controller(iop);
+			if(i2o_status_get(iop)<0)
+			{
+				printk("IOP not responding.\n");
+				i2o_delete_controller(iop);
+				continue;
+			}
+		}
 
 		if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED)
 		{
 			printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
 					iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 
 		if(iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
@@ -1384,7 +1409,7 @@
 			int msg[256];
 
 #ifdef DRIVERDEBUG
-			printk(KERN_INFO "iop%d already running...trying to reboot",
+			printk(KERN_INFO "iop%d already running...trying to reboot\n",
 					iop->unit);
 #endif
 			i2o_init_outbound_q(iop);
@@ -1396,6 +1421,7 @@
 			{
 				printk(KERN_CRIT "Failed to initialize iop%d\n", iop->unit);
 				i2o_delete_controller(iop);
+				continue;
 			}
 		}
 	}
@@ -1403,9 +1429,11 @@
 	/*
 	 * Now init the outbound queue for each one.
 	 */
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 	{
 		int i;
+		
+		niop = iop->next;
 
 		if((ret=i2o_init_outbound_q(iop)))
 		{
@@ -1413,6 +1441,7 @@
 				"IOP%d initialization failed: Could not initialize outbound q\n",
 				iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 		iop->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
 
@@ -1438,18 +1467,20 @@
 	/*
 	 * OK..parse the HRT
 	 */
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 	{
+		niop = iop->next;
 		if(i2o_hrt_get(iop))
 		{
 			printk(KERN_CRIT "iop%d: Could not get HRT!\n", iop->unit);
 			i2o_delete_controller(iop);
-			break;
+			continue;
 		}
 		if(i2o_parse_hrt(iop))
 		{
 			printk(KERN_CRIT "iop%d: Could not parse HRT!\n", iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 	}
 
@@ -1466,15 +1497,17 @@
 		return;
 	}
 
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 #ifdef DRIVERDEBUG
 	{
+		niop = iop->next;
 		printk(KERN_INFO "Sending system table to iop%d\n", iop->unit);
 #endif
 		if(i2o_systab_send(iop))
 		{
 			printk(KERN_CRIT "iop%d: Error sending system table\n", iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 #ifdef DRIVERDEBUG
 	}
@@ -1483,8 +1516,9 @@
 	/*
 	 * Enable
 	 */
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 	{
+		niop = iop->next;
 #ifdef DRIVERDEBUG
 		printk(KERN_INFO "Enableing iop%d\n", iop->unit);
 #endif
@@ -1492,14 +1526,16 @@
 		{
 			printk(KERN_ERR "Could not enable iop%d\n", iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 	}
 
 	/*
 	 * OK..one last thing and we're ready to go!
 	 */
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 	{
+		niop = iop->next;
 #ifdef DRIVERDEBUG
 		printk(KERN_INFO "Getting LCT for iop%d\n", iop->unit);
 #endif
@@ -1507,6 +1543,7 @@
 		{
 			printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 		else	
 			i2o_parse_lct(iop);
@@ -1667,7 +1704,7 @@
 	msg[4]= 4096;			/* Host page frame size */
 	msg[5]= MSG_FRAME_SIZE<<16|0x80;	/* Outbound msg frame size and Initcode */
 	msg[6]= 0xD0000004;		/* Simple SG LE, EOB */
-	msg[7]= virt_to_phys(workspace);
+	msg[7]= virt_to_bus(workspace);
 	*((u32 *)workspace)=0;
 
 	/*
@@ -1685,7 +1722,6 @@
 		{
 			printk(KERN_ERR "i2o/iop%d: IOP outbound initialise failed.\n",
 						c->unit);
-			kfree(workspace);
 			return -ETIMEDOUT;
 		}
 		schedule();
@@ -2419,7 +2455,7 @@
 	case I2O_CMD_UTIL_DEVICE_RELEASE:
 		printk("UTIL_DEVICE_RELEASE, ");
 		break;
-	case I2O_CMD_UTIL_ACK:
+	case I2O_CMD_UTIL_EVT_ACK:
 		printk("UTIL_EVENT_ACKNOWLEDGE, ");
 		break;
 	case I2O_CMD_UTIL_EVT_REGISTER:

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)