linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* PATCH: bring i2o_scsi further into line with 2.5
@ 2002-10-09 18:23 Alan Cox
  0 siblings, 0 replies; only message in thread
From: Alan Cox @ 2002-10-09 18:23 UTC (permalink / raw)
  To: torvalds, linux-kernel

diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.41/drivers/message/i2o/i2o_scsi.c linux.2.5.41-ac2/drivers/message/i2o/i2o_scsi.c
--- linux.2.5.41/drivers/message/i2o/i2o_scsi.c	2002-10-02 21:32:55.000000000 +0100
+++ linux.2.5.41-ac2/drivers/message/i2o/i2o_scsi.c	2002-10-09 18:44:32.000000000 +0100
@@ -1,13 +1,19 @@
 /* 
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2, or (at your option) any
- *  later version.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open non patent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
  *
  *  Complications for I2O scsi
  *
@@ -56,7 +62,7 @@
 #include "../../scsi/sd.h"
 #include "i2o_scsi.h"
 
-#define VERSION_STRING        "Version 0.0.1"
+#define VERSION_STRING        "Version 0.1.1"
 
 #define dprintk(x)
 
@@ -77,6 +83,7 @@
 static u32 *retry[32];
 static struct i2o_controller *retry_ctrl[32];
 static struct timer_list retry_timer;
+static spinlock_t retry_lock;
 static int retry_ct = 0;
 
 static atomic_t queue_depth;
@@ -108,7 +115,10 @@
 static int sg_chain_tag = 0;
 static int sg_max_frags = SG_MAX_FRAGS;
 
-/*
+/**
+ *	i2o_retry_run		-	retry on timeout
+ *	@f: unused
+ *
  *	Retry congested frames. This actually needs pushing down into
  *	i2o core. We should only bother the OSM with this when we can't
  *	queue and retry the frame. Or perhaps we should call the OSM
@@ -121,24 +131,26 @@
 	int i;
 	unsigned long flags;
 	
-	save_flags(flags);
-	cli();
-
+	spin_lock_irqsave(&retry_lock, flags);
 	for(i=0;i<retry_ct;i++)
 		i2o_post_message(retry_ctrl[i], virt_to_bus(retry[i]));
 	retry_ct=0;
-	
-	restore_flags(flags);
+	spin_unlock_irqrestore(&retry_lock, flags);
 }
 
+/**
+ *	flush_pending		-	empty the retry queue
+ *
+ *	Turn each of the pending commands into a NOP and post it back
+ *	to the controller to clear it.
+ */
+ 
 static void flush_pending(void)
 {
 	int i;
 	unsigned long flags;
 	
-	save_flags(flags);
-	cli();
-
+	spin_lock_irqsave(&retry_lock, flags);
 	for(i=0;i<retry_ct;i++)
 	{
 		retry[i][0]&=~0xFFFFFF;
@@ -146,16 +158,30 @@
 		i2o_post_message(retry_ctrl[i],virt_to_bus(retry[i]));
 	}
 	retry_ct=0;
-	
-	restore_flags(flags);
+	spin_unlock_irqrestore(&retry_lock, flags);
 }
 
+/**
+ *	i2o_scsi_reply		-	scsi message reply processor
+ *	@h: our i2o handler
+ *	@c: controller issuing the reply
+ *	@msg: the message from the controller (mapped)
+ *
+ *	Process reply messages (interrupts in normal scsi controller think).
+ *	We can get a variety of messages to process. The normal path is
+ *	scsi command completions. We must also deal with IOP failures,
+ *	the reply to a bus reset and the reply to a LUN query.
+ *
+ *	Locks: the queue lock is taken to call the completion handler
+ */
+
 static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
 {
 	Scsi_Cmnd *current_command;
 	spinlock_t *lock;
 	u32 *m = (u32 *)msg;
 	u8 as,ds,st;
+	unsigned long flags;
 
 	if(m[0] & (1<<13))
 	{
@@ -177,6 +203,9 @@
 		m=(u32 *)bus_to_virt(m[7]);
 		printk("Failing message is %p.\n", m);
 		
+		/* This isnt a fast path .. */
+		spin_lock_irqsave(&retry_lock, flags);
+		
 		if((m[4]&(1<<18)) && retry_ct < 32)
 		{
 			retry_ctrl[retry_ct]=c;
@@ -186,18 +215,20 @@
 				retry_timer.expires=jiffies+1;
 				add_timer(&retry_timer);
 			}
+			spin_unlock_irqrestore(&retry_lock, flags);
 		}
 		else
 		{
+			spin_unlock_irqrestore(&retry_lock, flags);
 			/* Create a scsi error for this */
 			current_command = (Scsi_Cmnd *)m[3];
-			lock = &current_command->host->host_lock;
+			lock = current_command->host->host_lock;
 			printk("Aborted %ld\n", current_command->serial_number);
 
-			spin_lock_irq(lock);
+			spin_lock_irqsave(lock, flags);
 			current_command->result = DID_ERROR << 16;
 			current_command->scsi_done(current_command);
-			spin_unlock_irq(lock);
+			spin_unlock_irqrestore(lock, flags);
 			
 			/* Now flush the message by making it a NOP */
 			m[0]&=0x00FFFFFF;
@@ -214,14 +245,14 @@
 	 *	Low byte is device status, next is adapter status,
 	 *	(then one byte reserved), then request status.
 	 */
-	ds=(u8)m[4]; 
-	as=(u8)(m[4]>>8);
-	st=(u8)(m[4]>>24);
+	ds=(u8)le32_to_cpu(m[4]);
+	as=(u8)le32_to_cpu(m[4]>>8);
+	st=(u8)le32_to_cpu(m[4]>>24);
 	
 	dprintk(("i2o got a scsi reply %08X: ", m[0]));
 	dprintk(("m[2]=%08X: ", m[2]));
 	dprintk(("m[4]=%08X\n", m[4]));
-
+ 
 	if(m[2]&0x80000000)
 	{
 		if(m[2]&0x40000000)
@@ -230,10 +261,13 @@
 			lun_done=1;
 			return;
 		}
-		printk(KERN_ERR "i2o_scsi: bus reset reply.\n");
+		printk(KERN_INFO "i2o_scsi: bus reset completed.\n");
 		return;
 	}
-	
+	/*
+ 	 *	FIXME: 64bit breakage
+	 */
+
 	current_command = (Scsi_Cmnd *)m[3];
 	
 	/*
@@ -254,11 +288,11 @@
 	
 	if(st == 0x06)
 	{
-		if(m[5] < current_command->underflow)
+		if(le32_to_cpu(m[5]) < current_command->underflow)
 		{
 			int i;
 			printk(KERN_ERR "SCSI: underflow 0x%08X 0x%08X\n",
-				m[5], current_command->underflow);
+				le32_to_cpu(m[5]), current_command->underflow);
 			printk("Cmd: ");
 			for(i=0;i<15;i++)
 				printk("%02X ", current_command->cmnd[i]);
@@ -286,10 +320,10 @@
 		 *	It worked maybe ?
 		 */		
 		current_command->result = DID_OK << 16 | ds;
-	lock = &current_command->host->host_lock;
-	spin_lock(lock);
+	lock = current_command->host->host_lock;
+	spin_lock_irqsave(lock, flags);
 	current_command->scsi_done(current_command);
-	spin_unlock(lock);
+	spin_unlock_irqrestore(lock, flags);
 	return;
 }
 
@@ -304,6 +338,18 @@
 	I2O_CLASS_SCSI_PERIPHERAL
 };
 
+/**
+ *	i2o_find_lun		-	report the lun of an i2o device
+ *	@c: i2o controller owning the device
+ *	@d: i2o disk device
+ *	@target: filled in with target id
+ *	@lun: filled in with target lun
+ *
+ *	Query an I2O device to find out its SCSI lun and target numbering. We
+ *	don't currently handle some of the fancy SCSI-3 stuff although our
+ *	querying is sufficient to do so.
+ */
+ 
 static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *target, int *lun)
 {
 	u8 reply[8];
@@ -322,7 +368,20 @@
 	return 0;
 }
 
-void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_Host *shpnt)
+/**
+ *	i2o_scsi_init		-	initialize an i2o device for scsi
+ *	@c: i2o controller owning the device
+ *	@d: scsi controller
+ *	@shpnt: scsi device we wish it to become
+ *
+ *	Enumerate the scsi peripheral/fibre channel peripheral class
+ *	devices that are children of the controller. From that we build
+ *	a translation map for the command queue code. Since I2O works on
+ *	its own tid's we effectively have to think backwards to get what
+ *	the midlayer wants
+ */
+ 
+static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_Host *shpnt)
 {
 	struct i2o_device *unit;
 	struct i2o_scsi_host *h =(struct i2o_scsi_host *)shpnt->hostdata;
@@ -382,14 +441,24 @@
 	}		
 }
 
-int i2o_scsi_detect(Scsi_Host_Template * tpnt)
+/**
+ *	i2o_scsi_detect		-	probe for I2O scsi devices
+ *	@tpnt: scsi layer template
+ *
+ *	I2O is a little odd here. The I2O core already knows what the
+ *	devices are. It also knows them by disk and tape as well as
+ *	by controller. We register each I2O scsi class object as a
+ *	scsi controller and then let the enumeration fake up the rest
+ */
+ 
+static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
 {
 	unsigned long flags;
 	struct Scsi_Host *shpnt = NULL;
 	int i;
 	int count;
 
-	printk("i2o_scsi.c: %s\n", VERSION_STRING);
+	printk(KERN_INFO "i2o_scsi.c: %s\n", VERSION_STRING);
 
 	if(i2o_install_handler(&i2o_scsi_handler)<0)
 	{
@@ -400,14 +469,14 @@
 	
 	if((sg_chain_pool = kmalloc(SG_CHAIN_POOL_SZ, GFP_KERNEL)) == NULL)
 	{
-		printk("i2o_scsi: Unable to alloc %d byte SG chain buffer pool.\n", SG_CHAIN_POOL_SZ);
-		printk("i2o_scsi: SG chaining DISABLED!\n");
+		printk(KERN_INFO "i2o_scsi: Unable to alloc %d byte SG chain buffer pool.\n", SG_CHAIN_POOL_SZ);
+		printk(KERN_INFO "i2o_scsi: SG chaining DISABLED!\n");
 		sg_max_frags = 11;
 	}
 	else
 	{
-		printk("  chain_pool: %d bytes @ %p\n", SG_CHAIN_POOL_SZ, sg_chain_pool);
-		printk("  (%d byte buffers X %d can_queue X %d i2o controllers)\n",
+		printk(KERN_INFO "  chain_pool: %d bytes @ %p\n", SG_CHAIN_POOL_SZ, sg_chain_pool);
+		printk(KERN_INFO "  (%d byte buffers X %d can_queue X %d i2o controllers)\n",
 				SG_CHAIN_BUF_SZ, I2O_SCSI_CAN_QUEUE, i2o_num_controllers);
 		sg_max_frags = SG_MAX_FRAGS;    // 64
 	}
@@ -447,14 +516,11 @@
 			shpnt = scsi_register(tpnt, sizeof(struct i2o_scsi_host));
 			if(shpnt==NULL)
 				continue;
-			save_flags(flags);
-			cli();
 			shpnt->unique_id = (u32)d;
 			shpnt->io_port = 0;
 			shpnt->n_io_port = 0;
 			shpnt->irq = 0;
 			shpnt->this_id = /* Good question */15;
-			restore_flags(flags);
 			i2o_scsi_init(c, d, shpnt);
 			count++;
 		}
@@ -476,7 +542,7 @@
 	return count;
 }
 
-int i2o_scsi_release(struct Scsi_Host *host)
+static int i2o_scsi_release(struct Scsi_Host *host)
 {
 	if(--i2o_scsi_hosts==0)
 	{
@@ -493,45 +559,28 @@
 }
 
 
-const char *i2o_scsi_info(struct Scsi_Host *SChost)
+static const char *i2o_scsi_info(struct Scsi_Host *SChost)
 {
 	struct i2o_scsi_host *hostdata;
-
 	hostdata = (struct i2o_scsi_host *)SChost->hostdata;
-
 	return(&hostdata->controller->name[0]);
 }
 
-
-/*
- * From the wd93 driver:
- * Returns true if there will be a DATA_OUT phase with this command, 
- * false otherwise.
- * (Thanks to Joerg Dorchain for the research and suggestion.)
- *
- */
-static int is_dir_out(Scsi_Cmnd *cmd)
-{
-	switch (cmd->cmnd[0]) 
-	{
-     		case WRITE_6:           case WRITE_10:          case WRITE_12:
-      		case WRITE_LONG:        case WRITE_SAME:        case WRITE_BUFFER:
-      		case WRITE_VERIFY:      case WRITE_VERIFY_12:      
-      		case COMPARE:           case COPY:              case COPY_VERIFY:
-      		case SEARCH_EQUAL:      case SEARCH_HIGH:       case SEARCH_LOW:
-      		case SEARCH_EQUAL_12:   case SEARCH_HIGH_12:    case SEARCH_LOW_12:      
-      		case FORMAT_UNIT:       case REASSIGN_BLOCKS:   case RESERVE:
-      		case MODE_SELECT:       case MODE_SELECT_10:    case LOG_SELECT:
-      		case SEND_DIAGNOSTIC:   case CHANGE_DEFINITION: case UPDATE_BLOCK:
-      		case SET_WINDOW:        case MEDIUM_SCAN:       case SEND_VOLUME_TAG:
-      		case 0xea:
-        		return 1;
-		default:
-        		return 0;
-	}
-}
-
-int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
+/**
+ *	i2o_scsi_queuecommand	-	queue a SCSI command
+ *	@SCpnt: scsi command pointer
+ *	@done: callback for completion
+ *
+ *	Issue a scsi comamnd asynchronously. Return 0 on success or 1 if
+ *	we hit an error (normally message queue congestion). The only 
+ *	minor complication here is that I2O deals with the device addressing
+ *	so we have to map the bus/dev/lun back to an I2O handle as well
+ *	as faking absent devices ourself. 
+ *
+ *	Locks: takes the controller lock on error path only
+ */
+ 
+static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 {
 	int i;
 	int tid;
@@ -547,6 +596,7 @@
 	u32 len;
 	u32 reqlen;
 	u32 tag;
+	unsigned long flags;
 	
 	static int max_qd = 1;
 	
@@ -582,24 +632,23 @@
 	if(tid == -1)
 	{
 		SCpnt->result = DID_NO_CONNECT << 16;
+		spin_lock_irqsave(host->host_lock, flags);
 		done(SCpnt);
+		spin_unlock_irqrestore(host->host_lock, flags);
 		return 0;
 	}
 	
 	dprintk(("Real scsi messages.\n"));
 
-	
 	/*
-	 *	Obtain an I2O message. Right now we _have_ to obtain one
-	 *	until the scsi layer stuff is cleaned up.
+	 *	Obtain an I2O message. If there are none free then 
+	 *	throw it back to the scsi layer
 	 */	
 	 
-	do
-	{
-		mb();
-		m = I2O_POST_READ32(c);
-	}
-	while(m==0xFFFFFFFF);
+	m = le32_to_cpu(I2O_POST_READ32(c));
+	if(m==0xFFFFFFFF)
+		return 1;
+
 	msg = (u32 *)(c->mem_offset + m);
 	
 	/*
@@ -609,28 +658,33 @@
 	len = SCpnt->request_bufflen;
 	direction = 0x00000000;			// SGL IN  (osm<--iop)
 	
-	/*
-	 *	The scsi layer should be handling this stuff
-	 */
-	
-	scsidir = 0x00000000;			// DATA NO XFER
-	if(len)
+	if(SCpnt->sc_data_direction == SCSI_DATA_NONE)
+		scsidir = 0x00000000;			// DATA NO XFER
+	else if(SCpnt->sc_data_direction == SCSI_DATA_WRITE)
 	{
-		if(is_dir_out(SCpnt))
-		{
-			direction=0x04000000;	// SGL OUT  (osm-->iop)
-			scsidir  =0x80000000;	// DATA OUT (iop-->dev)
-		}
-		else
-		{
-			scsidir  =0x40000000;	// DATA IN  (iop<--dev)
-		}
+		direction=0x04000000;	// SGL OUT  (osm-->iop)
+		scsidir  =0x80000000;	// DATA OUT (iop-->dev)
+	}
+	else if(SCpnt->sc_data_direction == SCSI_DATA_READ)
+	{
+		scsidir  =0x40000000;	// DATA IN  (iop<--dev)
+	}
+	else
+	{
+		/* Unknown - kill the command */
+		SCpnt->result = DID_NO_CONNECT << 16;
+		
+		/* We must lock the request queue while completing */
+		spin_lock_irqsave(host->host_lock, flags);
+		done(SCpnt);
+		spin_unlock_irqrestore(host->host_lock, flags);
+		return 0;
 	}
 	
-	__raw_writel(I2O_CMD_SCSI_EXEC<<24|HOST_TID<<12|tid, &msg[1]);
-	__raw_writel(scsi_context, &msg[2]);	/* So the I2O layer passes to us */
+	i2o_raw_writel(I2O_CMD_SCSI_EXEC<<24|HOST_TID<<12|tid, &msg[1]);
+	i2o_raw_writel(scsi_context, &msg[2]);	/* So the I2O layer passes to us */
 	/* Sorry 64bit folks. FIXME */
-	__raw_writel((u32)SCpnt, &msg[3]);	/* We want the SCSI control block back */
+	i2o_raw_writel((u32)SCpnt, &msg[3]);	/* We want the SCSI control block back */
 
 	/* LSI_920_PCI_QUIRK
 	 *
@@ -673,7 +727,7 @@
 	}
 
 	/* Direction, disconnect ok, tag, CDBLen */
-	__raw_writel(scsidir|0x20000000|SCpnt->cmd_len|tag, &msg[4]);
+	i2o_raw_writel(scsidir|0x20000000|SCpnt->cmd_len|tag, &msg[4]);
 
 	mptr=msg+5;
 
@@ -708,8 +762,8 @@
 			/*
 			 *	Need to chain!
 			 */
-			__raw_writel(direction|0xB0000000|(SCpnt->use_sg*2*4), mptr++);
-			__raw_writel(virt_to_bus(sg_chain_pool + sg_chain_tag), mptr);
+			i2o_raw_writel(direction|0xB0000000|(SCpnt->use_sg*2*4), mptr++);
+			i2o_raw_writel(virt_to_bus(sg_chain_pool + sg_chain_tag), mptr);
 			mptr = (u32*)(sg_chain_pool + sg_chain_tag);
 			if (SCpnt->use_sg > max_sg_len)
 			{
@@ -723,7 +777,7 @@
 			{
 				*mptr++=direction|0x10000000|sg->length;
 				len+=sg->length;
-				*mptr++=virt_to_bus(sg->address);
+				*mptr++=virt_to_bus(page_address(sg->page)+sg->offset);
 				sg++;
 			}
 			mptr[-2]=direction|0xD0000000|(sg-1)->length;
@@ -732,22 +786,22 @@
 		{		
 			for(i = 0 ; i < SCpnt->use_sg; i++)
 			{
-				__raw_writel(direction|0x10000000|sg->length, mptr++);
+				i2o_raw_writel(direction|0x10000000|sg->length, mptr++);
 				len+=sg->length;
-				__raw_writel(virt_to_bus(sg->address), mptr++);
+				i2o_raw_writel(virt_to_bus(page_address(sg->page) + sg->offset), mptr++);
 				sg++;
 			}
 
 			/* Make this an end of list. Again evade the 920 bug and
 			   unwanted PCI read traffic */
 		
-			__raw_writel(direction|0xD0000000|(sg-1)->length, &mptr[-2]);
+			i2o_raw_writel(direction|0xD0000000|(sg-1)->length, &mptr[-2]);
 		}
 		
 		if(!chain)
 			reqlen = mptr - msg;
 		
-		__raw_writel(len, lenptr);
+		i2o_raw_writel(len, lenptr);
 		
 		if(len != SCpnt->underflow)
 			printk("Cmd len %08X Cmd underflow %08X\n",
@@ -757,15 +811,15 @@
 	{
 		dprintk(("non sg for %p, %d\n", SCpnt->request_buffer,
 				SCpnt->request_bufflen));
-		__raw_writel(len = SCpnt->request_bufflen, lenptr);
+		i2o_raw_writel(len = SCpnt->request_bufflen, lenptr);
 		if(len == 0)
 		{
 			reqlen = 9;
 		}
 		else
 		{
-			__raw_writel(0xD0000000|direction|SCpnt->request_bufflen, mptr++);
-			__raw_writel(virt_to_bus(SCpnt->request_buffer), mptr++);
+			i2o_raw_writel(0xD0000000|direction|SCpnt->request_bufflen, mptr++);
+			i2o_raw_writel(virt_to_bus(SCpnt->request_buffer), mptr++);
 		}
 	}
 	
@@ -773,7 +827,7 @@
 	 *	Stick the headers on 
 	 */
 
-	__raw_writel(reqlen<<16 | SGL_OFFSET_10, msg);
+	i2o_raw_writel(reqlen<<16 | SGL_OFFSET_10, msg);
 	
 	/* Queue the message */
 	i2o_post_message(c,m);
@@ -792,12 +846,26 @@
 	return 0;
 }
 
+/**
+ *	internal_done	-	legacy scsi glue
+ *	@SCPnt: command
+ *
+ *	Completion function for a synchronous command
+ */
+
 static void internal_done(Scsi_Cmnd * SCpnt)
 {
 	SCpnt->SCp.Status++;
 }
 
-int i2o_scsi_command(Scsi_Cmnd * SCpnt)
+/**
+ *	i2o_scsi_command	-	issue a scsi command and wait
+ *	@SCPnt: command
+ *
+ *	Issue a SCSI command and wait for it to complete.
+ */
+ 
+static int i2o_scsi_command(Scsi_Cmnd * SCpnt)
 {
 	i2o_scsi_queuecommand(SCpnt, internal_done);
 	SCpnt->SCp.Status = 0;
@@ -806,65 +874,90 @@
 	return SCpnt->result;
 }
 
+/**
+ *	i2o_scsi_abort	-	abort a running command
+ *	@SCpnt: command to abort
+ *
+ *	Ask the I2O controller to abort a command. This is an asynchrnous
+ *	process and oru callback handler will see the command complete
+ *	with an aborted message if it succeeds. 
+ *
+ *	Locks: no locks are held or needed
+ */
+ 
 int i2o_scsi_abort(Scsi_Cmnd * SCpnt)
 {
 	struct i2o_controller *c;
 	struct Scsi_Host *host;
 	struct i2o_scsi_host *hostdata;
-	u32 *msg;
+	unsigned long msg;
 	u32 m;
 	int tid;
 	
-	printk("i2o_scsi: Aborting command block.\n");
+	printk(KERN_WARNING "i2o_scsi: Aborting command block.\n");
 	
 	host = SCpnt->host;
 	hostdata = (struct i2o_scsi_host *)host->hostdata;
 	tid = hostdata->task[SCpnt->target][SCpnt->lun];
 	if(tid==-1)
 	{
-		printk(KERN_ERR "impossible command to abort.\n");
-		return SCSI_ABORT_NOT_RUNNING;
+		printk(KERN_ERR "i2o_scsi: Impossible command to abort!\n");
+		return FAILED;
 	}
 	c = hostdata->controller;
 	
 	/*
 	 *	Obtain an I2O message. Right now we _have_ to obtain one
 	 *	until the scsi layer stuff is cleaned up.
+	 *
+	 *	FIXME: we are in error context so we could sleep retry
+	 * 	a bit and then bail in the improved scsi layer.
 	 */	
 	 
 	do
 	{
 		mb();
-		m = I2O_POST_READ32(c);
+		m = le32_to_cpu(I2O_POST_READ32(c));
 	}
 	while(m==0xFFFFFFFF);
-	msg = (u32 *)(c->mem_offset + m);
+	msg = c->mem_offset + m;
 	
-	__raw_writel(FIVE_WORD_MSG_SIZE, &msg[0]);
-	__raw_writel(I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|tid, &msg[1]);
-	__raw_writel(scsi_context, &msg[2]);
-	__raw_writel(0, &msg[3]);	/* Not needed for an abort */
-	__raw_writel((u32)SCpnt, &msg[4]);	
+	i2o_raw_writel(FIVE_WORD_MSG_SIZE, msg);
+	i2o_raw_writel(I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|tid, msg+4);
+	i2o_raw_writel(scsi_context, msg+8);
+	i2o_raw_writel(0, msg+12);	/* Not needed for an abort */
+	i2o_raw_writel((u32)SCpnt, msg+16);	
 	wmb();
 	i2o_post_message(c,m);
 	wmb();
-	return SCSI_ABORT_PENDING;
+	return SUCCESS;
 }
 
-int i2o_scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
+/**
+ *	i2o_scsi_bus_reset		-	Issue a SCSI reset
+ *	@SCpnt: the command that caused the reset
+ *
+ *	Perform a SCSI bus reset operation. In I2O this is just a message
+ *	we pass. I2O can do clever multi-initiator and shared reset stuff
+ *	but we don't support this.
+ *
+ *	Locks: called with no lock held, requires no locks.
+ */
+ 
+static int i2o_scsi_bus_reset(Scsi_Cmnd * SCpnt)
 {
 	int tid;
 	struct i2o_controller *c;
 	struct Scsi_Host *host;
 	struct i2o_scsi_host *hostdata;
 	u32 m;
-	u32 *msg;
+	unsigned long msg;
 
 	/*
 	 *	Find the TID for the bus
 	 */
 
-	printk("i2o_scsi: Attempting to reset the bus.\n");
+	printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n");
 	
 	host = SCpnt->host;
 	hostdata = (struct i2o_scsi_host *)host->hostdata;
@@ -877,7 +970,7 @@
 	 *	possibly ?
 	 */
 	 
-	m = I2O_POST_READ32(c);
+	m = le32_to_cpu(I2O_POST_READ32(c));
 	
 	/*
 	 *	No free messages, try again next time - no big deal
@@ -886,23 +979,55 @@
 	if(m == 0xFFFFFFFF)
 		return SCSI_RESET_PUNT;
 	
-	msg = (u32 *)(c->mem_offset + m);
-	__raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]);
-	__raw_writel(I2O_CMD_SCSI_BUSRESET<<24|HOST_TID<<12|tid, &msg[1]);
-	__raw_writel(scsi_context|0x80000000, &msg[2]);
+	msg = c->mem_offset + m;
+	i2o_raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, msg);
+	i2o_raw_writel(I2O_CMD_SCSI_BUSRESET<<24|HOST_TID<<12|tid, msg+4);
+	i2o_raw_writel(scsi_context|0x80000000, msg+8);
 	/* We use the top bit to split controller and unit transactions */
 	/* Now store unit,tid so we can tie the completion back to a specific device */
-	__raw_writel(c->unit << 16 | tid, &msg[3]);
+	__raw_writel(c->unit << 16 | tid, msg+12);
 	wmb();
 	i2o_post_message(c,m);
-	return SCSI_RESET_PENDING;
+	return SUCCESS;
 }
 
-/*
- *	This is anyones guess quite frankly.
+/**
+ *	i2o_scsi_host_reset	-	host reset callback
+ *	@SCpnt: command causing the reset
+ *
+ *	An I2O controller can be many things at once. While we can
+ *	reset a controller the potential mess from doing so is vast, and
+ *	it's better to simply hold on and pray
+ */
+ 
+static int i2o_scsi_host_reset(Scsi_Cmnd * SCpnt)
+{
+	return FAILED;
+}
+
+/**
+ *	i2o_scsi_device_reset	-	device reset callback
+ *	@SCpnt: command causing the reset
+ *
+ *	I2O does not (AFAIK) support doing a device reset
+ */
+ 
+static int i2o_scsi_device_reset(Scsi_Cmnd * SCpnt)
+{
+	return FAILED;
+}
+
+/**
+ *	i2o_scsi_bios_param	-	Invent disk geometry
+ *	@disk: device 
+ *	@dev: block layer device
+ *	@ip: geometry array
+ *
+ *	This is anyones guess quite frankly. We use the same rules everyone 
+ *	else appears to and hope. It seems to work.
  */
  
-int i2o_scsi_bios_param(Disk * disk, struct block_device *dev, int *ip)
+static int i2o_scsi_bios_param(Disk * disk, struct block_device *dev, int *ip)
 {
 	int size;
 
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.41/drivers/message/i2o/i2o_scsi.h linux.2.5.41-ac2/drivers/message/i2o/i2o_scsi.h
--- linux.2.5.41/drivers/message/i2o/i2o_scsi.h	2002-10-02 21:32:55.000000000 +0100
+++ linux.2.5.41-ac2/drivers/message/i2o/i2o_scsi.h	2002-10-09 18:39:58.000000000 +0100
@@ -1,12 +1,6 @@
 #ifndef _I2O_SCSI_H
 #define _I2O_SCSI_H
 
-#if !defined(LINUX_VERSION_CODE)
-#include <linux/version.h>
-#endif
-
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 
@@ -14,34 +8,37 @@
 #define I2O_SCSI_CAN_QUEUE 4
 #define I2O_SCSI_CMD_PER_LUN 6
 
-extern int i2o_scsi_detect(Scsi_Host_Template *);
-extern const char *i2o_scsi_info(struct Scsi_Host *);
-extern int i2o_scsi_command(Scsi_Cmnd *);
-extern int i2o_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int i2o_scsi_abort(Scsi_Cmnd *);
-extern int i2o_scsi_reset(Scsi_Cmnd *, unsigned int);
-extern int i2o_scsi_bios_param(Disk *, struct block_device *, int *);
-extern void i2o_scsi_setup(char *str, int *ints);
-extern int i2o_scsi_release(struct Scsi_Host *host);
-
-#define I2OSCSI {                                          \
-		  next: NULL,				    \
-                  proc_name:         "i2o_scsi",   \
-                  name:              "I2O SCSI Layer", 	    \
-                  detect:            i2o_scsi_detect,       \
-                  release:	     i2o_scsi_release,	    \
-                  info:              i2o_scsi_info,         \
-                  command:           i2o_scsi_command,      \
-                  queuecommand:      i2o_scsi_queuecommand, \
-                  abort:             i2o_scsi_abort,        \
-                  reset:             i2o_scsi_reset,        \
-                  bios_param:        i2o_scsi_bios_param,   \
-                  can_queue:         I2O_SCSI_CAN_QUEUE,    \
-                  this_id:           I2O_SCSI_ID,           \
-                  sg_tablesize:      8,                     \
-                  cmd_per_lun:       I2O_SCSI_CMD_PER_LUN,  \
-                  unchecked_isa_dma: 0,                     \
-                  use_clustering:    ENABLE_CLUSTERING     \
+static int i2o_scsi_detect(Scsi_Host_Template *);
+static const char *i2o_scsi_info(struct Scsi_Host *);
+static int i2o_scsi_command(Scsi_Cmnd *);
+static int i2o_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+static int i2o_scsi_abort(Scsi_Cmnd *);
+static int i2o_scsi_bus_reset(Scsi_Cmnd *);
+static int i2o_scsi_host_reset(Scsi_Cmnd *);
+static int i2o_scsi_device_reset(Scsi_Cmnd *);
+static int i2o_scsi_bios_param(Disk *, struct block_device *, int *);
+static int i2o_scsi_release(struct Scsi_Host *host);
+
+#define I2OSCSI {                                       		\
+		  next: NULL,						\
+                  proc_name:         		"i2o_scsi",   		\
+                  name:              		"I2O SCSI Layer", 	\
+                  detect:            		i2o_scsi_detect,	\
+                  release:	     		i2o_scsi_release,	\
+                  info:              		i2o_scsi_info,		\
+                  command:           		i2o_scsi_command,	\
+                  queuecommand:      		i2o_scsi_queuecommand,	\
+                  eh_abort_handler:             i2o_scsi_abort,		\
+                  eh_bus_reset_handler:         i2o_scsi_bus_reset,	\
+                  eh_device_reset_handler:      i2o_scsi_device_reset,	\
+                  eh_host_reset_handler:	i2o_scsi_host_reset,	\
+  		  bios_param:        i2o_scsi_bios_param,   		\
+                  can_queue:         I2O_SCSI_CAN_QUEUE,    		\
+                  this_id:           I2O_SCSI_ID,           		\
+                  sg_tablesize:      8,                     		\
+                  cmd_per_lun:       I2O_SCSI_CMD_PER_LUN,  		\
+                  unchecked_isa_dma: 0,                     		\
+                  use_clustering:    ENABLE_CLUSTERING     		\
                   }
 
 #endif

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-10-09 18:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-10-09 18:23 PATCH: bring i2o_scsi further into line with 2.5 Alan Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).