patch-2.2.16 linux/drivers/i2o/i2o_config.c

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

diff -urN v2.2.15/linux/drivers/i2o/i2o_config.c linux/drivers/i2o/i2o_config.c
@@ -42,7 +42,8 @@
 static int i2o_cfg_context = -1;
 static void *page_buf;
 static void *i2o_buffer;
-static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t i2o_queue_lock = SPIN_LOCK_UNLOCKED;
+
 struct wait_queue *i2o_wait_queue;
 
 #define MODINC(x,y) (x = x++ % y)
@@ -85,8 +86,19 @@
 {
 	u32 *msg = (u32 *)m;
 
-	if (msg[0] & (1<<13))
+//	if (msg[0] & (1<<13))
+        if (msg[0] & MSG_FAIL) {
+                u32 *preserved_msg = (u32*)(c->mem_offset + msg[7]);
+
 		printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n");
+                /* Release the preserved msg frame by resubmitting it as a NOP */
+
+                preserved_msg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
+                preserved_msg[1] = I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0;
+                preserved_msg[2] = 0;
+                i2o_post_message(c, msg[7]);
+        }
+
         
 	if (msg[4] >> 24)  // RegStatus != SUCCESS
 		i2o_report_status(KERN_INFO,"i2o_config",msg);
@@ -133,7 +145,7 @@
 				(unsigned char *)(msg + 5),
 				inf->event_q[inf->q_in].data_size);
 
-		spin_lock(&i2o_config_lock);
+		spin_lock(&i2o_queue_lock);
 		MODINC(inf->q_in, I2O_EVT_Q_LEN);
 		if(inf->q_len == I2O_EVT_Q_LEN)
 		{
@@ -145,7 +157,7 @@
 			// Keep I2OEVTGET on another CPU from touching this
 			inf->q_len++;
 		}
-		spin_unlock(&i2o_config_lock);
+		spin_unlock(&i2o_queue_lock);
 		
 
 //		printk(KERN_INFO "File %p w/id %d has %d events\n",
@@ -166,6 +178,9 @@
 struct i2o_handler cfg_handler=
 {
 	i2o_cfg_reply,
+	NULL,
+	NULL,
+	NULL,
 	"Configuration",
 	0,
 	0xffffffff	// All classes
@@ -416,7 +431,8 @@
         
 	if (len < 0) {
 		kfree(res);
-		return len; /* -DetailedStatus */
+		//return len; /* -DetailedStatus */
+		return -EAGAIN;
 	}
 
 	put_user(len, kcmd.reslen);
@@ -749,7 +765,7 @@
 
 	/* Device exists? */
 	for(d = iop->devices; d; d = d->next)
-		if(d->lct_data->tid == kdesc.tid)
+		if(d->lct_data.tid == kdesc.tid)
 			break;
 
 	if(!d)
@@ -793,11 +809,12 @@
 
 	memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info));
 	MODINC(p->q_out, I2O_EVT_Q_LEN);
-	spin_lock_irqsave(&i2o_config_lock, flags);
+	spin_lock_irqsave(&i2o_queue_lock, flags);
+	/* FIXME - ought to lock the q_ values here!! */
 	p->q_len--;
 	kget.pending = p->q_len;
 	kget.lost = p->q_lost;
-	spin_unlock_irqrestore(&i2o_config_lock, flags);
+	spin_unlock_irqrestore(&i2o_queue_lock, flags);
 
 	__copy_to_user(uget, &kget, sizeof(struct i2o_evt_get));
 
@@ -823,9 +840,9 @@
 	tmp->q_lost = 0;
 	tmp->next = open_files;
 
-	spin_lock_irqsave(&i2o_config_lock, flags);
+	spin_lock_irqsave(&i2o_queue_lock, flags);
 	open_files = tmp;
-	spin_unlock_irqrestore(&i2o_config_lock, flags);
+	spin_unlock_irqrestore(&i2o_queue_lock, flags);
 	
 	MOD_INC_USE_COUNT;
 	return 0;
@@ -839,7 +856,7 @@
 
 	p1 = p2 = NULL;
 
-	spin_lock_irqsave(&i2o_config_lock, flags);
+	spin_lock_irqsave(&i2o_queue_lock, flags);
 	for(p1 = open_files; p1; )
 	{
 		if(p1->q_id == id)
@@ -858,7 +875,7 @@
 		p2 = p1;
 		p1 = p1->next;
 	}
-	spin_unlock_irqrestore(&i2o_config_lock, flags);
+	spin_unlock_irqrestore(&i2o_queue_lock, flags);
 
 	MOD_DEC_USE_COUNT;
 	return 0;

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