[PATCH] I2O: second code cleanup of sparse warnings and unneeded syncronization

Changes:
 - Added header "core.h" for i2o_core.ko internal definitions
 - More sparse fixes
 - Changed display of TID's in sysfs attributes from XXX to 0xXXX
 - Use the right functions for accessing I/O and normal memory
 - Removed error handling of SCSI device errors and let the SCSI layer
   take care of it
 - Added new device / removed device handling to SCSI-OSM
 - Make status access volatile
 - Cleaned up activation of I2O controller
 - Removed unnecessary wmb() and rmb() calls
 - Use own struct i2o_io for I/O memory instead of struct i2o_dma

Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index fef53b5..9f1744c 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -40,7 +40,6 @@
  *	Fix the resource management problems.
  */
 
-#define DEBUG 1
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -338,158 +337,43 @@
 			  struct i2o_message *msg)
 {
 	struct scsi_cmnd *cmd;
+	u32 error;
 	struct device *dev;
-	u8 as, ds, st;
 
 	cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
-
-	if (msg->u.head[0] & (1 << 13)) {
-		struct i2o_message __iomem *pmsg;	/* preserved message */
-		u32 pm;
-		int err = DID_ERROR;
-
-		pm = le32_to_cpu(msg->body[3]);
-
-		pmsg = i2o_msg_in_to_virt(c, pm);
-
-		osm_err("IOP fail.\n");
-		osm_err("From %d To %d Cmd %d.\n",
-			(msg->u.head[1] >> 12) & 0xFFF,
-			msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24);
-		osm_err("Failure Code %d.\n", msg->body[0] >> 24);
-		if (msg->body[0] & (1 << 16))
-			osm_err("Format error.\n");
-		if (msg->body[0] & (1 << 17))
-			osm_err("Path error.\n");
-		if (msg->body[0] & (1 << 18))
-			osm_err("Path State.\n");
-		if (msg->body[0] & (1 << 18))
-		{
-			osm_err("Congestion.\n");
-			err = DID_BUS_BUSY;
-		}
-
-		osm_debug("Failing message is %p.\n", pmsg);
-
-		cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt));
-		if (!cmd)
-			return 1;
-
-		cmd->result = err << 16;
-		cmd->scsi_done(cmd);
-
-		/* Now flush the message by making it a NOP */
-		i2o_msg_nop(c, pm);
-
-		return 1;
+	if (unlikely(!cmd)) {
+		osm_err("NULL reply received!\n");
+		return -1;
 	}
 
 	/*
 	 *      Low byte is device status, next is adapter status,
 	 *      (then one byte reserved), then request status.
 	 */
-	ds = (u8) le32_to_cpu(msg->body[0]);
-	as = (u8) (le32_to_cpu(msg->body[0]) >> 8);
-	st = (u8) (le32_to_cpu(msg->body[0]) >> 24);
-
-	/*
-	 *      Is this a control request coming back - eg an abort ?
-	 */
-
-	if (!cmd) {
-		if (st)
-			osm_warn("SCSI abort: %08X", le32_to_cpu(msg->body[0]));
-		osm_info("SCSI abort completed.\n");
-		return -EFAULT;
-	}
+	error = le32_to_cpu(msg->body[0]);
 
 	osm_debug("Completed %ld\n", cmd->serial_number);
 
-	if (st) {
-		u32 count, error;
-		/* An error has occurred */
+	cmd->result = error & 0xff;
+	/*
+	 * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let
+	 * the SCSI layer handle the error
+	 */
+	if (cmd->result)
+		memcpy(cmd->sense_buffer, &msg->body[3],
+		       min(sizeof(cmd->sense_buffer), (size_t) 40));
 
-		switch (st) {
-		case 0x06:
-			count = le32_to_cpu(msg->body[1]);
-			if (count < cmd->underflow) {
-				int i;
-
-				osm_err("SCSI underflow 0x%08X 0x%08X\n", count,
-					cmd->underflow);
-				osm_debug("Cmd: ");
-				for (i = 0; i < 15; i++)
-					pr_debug("%02X ", cmd->cmnd[i]);
-				pr_debug(".\n");
-				cmd->result = (DID_ERROR << 16);
-			}
-			break;
-
-		default:
-			error = le32_to_cpu(msg->body[0]);
-
-			osm_err("SCSI error %08x\n", error);
-
-			if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) {
-				int i;
-				u32 len = sizeof(cmd->sense_buffer);
-				len = (len > 40) ? 40 : len;
-				// Copy over the sense data
-				memcpy(cmd->sense_buffer, (void *)&msg->body[3],
-				       len);
-				for (i = 0; i <= len; i++)
-					osm_info("%02x\n",
-						 cmd->sense_buffer[i]);
-				if (cmd->sense_buffer[0] == 0x70
-				    && cmd->sense_buffer[2] == DATA_PROTECT) {
-					/* This is to handle an array failed */
-					cmd->result = (DID_TIME_OUT << 16);
-					printk(KERN_WARNING "%s: SCSI Data "
-					       "Protect-Device (%d,%d,%d) "
-					       "hba_status=0x%x, dev_status="
-					       "0x%x, cmd=0x%x\n", c->name,
-					       (u32) cmd->device->channel,
-					       (u32) cmd->device->id,
-					       (u32) cmd->device->lun,
-					       (error >> 8) & 0xff,
-					       error & 0xff, cmd->cmnd[0]);
-				} else
-					cmd->result = (DID_ERROR << 16);
-
-				break;
-			}
-
-			switch (as) {
-			case 0x0E:
-				/* SCSI Reset */
-				cmd->result = DID_RESET << 16;
-				break;
-
-			case 0x0F:
-				cmd->result = DID_PARITY << 16;
-				break;
-
-			default:
-				cmd->result = DID_ERROR << 16;
-				break;
-			}
-
-			break;
-		}
-
-		cmd->scsi_done(cmd);
-		return 1;
-	}
-
-	cmd->result = DID_OK << 16 | ds;
+	/* only output error code if AdapterStatus is not HBA_SUCCESS */
+	if ((error >> 8) & 0xff)
+		osm_err("SCSI error %08x\n", error);
 
 	dev = &c->pdev->dev;
 	if (cmd->use_sg)
-		dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer,
-			     cmd->use_sg, cmd->sc_data_direction);
-	else if (cmd->request_bufflen)
-		dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr),
-				 cmd->request_bufflen, cmd->sc_data_direction);
+		dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg,
+			     cmd->sc_data_direction);
+	else if (cmd->SCp.dma_handle)
+		dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen,
+				 cmd->sc_data_direction);
 
 	cmd->scsi_done(cmd);
 
@@ -497,6 +381,48 @@
 };
 
 /**
+ *	i2o_scsi_notify_device_add - Retrieve notifications of added devices
+ *	@i2o_dev: the I2O device which was added
+ *
+ *	If a I2O device is added we catch the notification, because I2O classes
+ *	other then SCSI peripheral will not be received through
+ *	i2o_scsi_probe().
+ */
+static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev)
+{
+	switch (i2o_dev->lct_data.class_id) {
+	case I2O_CLASS_EXECUTIVE:
+	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+		i2o_scsi_probe(&i2o_dev->device);
+		break;
+
+	default:
+		break;
+	}
+};
+
+/**
+ *	i2o_scsi_notify_device_remove - Retrieve notifications of removed
+ *				        devices
+ *	@i2o_dev: the I2O device which was removed
+ *
+ *	If a I2O device is removed, we catch the notification to remove the
+ *	corresponding SCSI device.
+ */
+static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev)
+{
+	switch (i2o_dev->lct_data.class_id) {
+	case I2O_CLASS_EXECUTIVE:
+	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+		i2o_scsi_remove(&i2o_dev->device);
+		break;
+
+	default:
+		break;
+	}
+};
+
+/**
  *	i2o_scsi_notify_controller_add - Retrieve notifications of added
  *					 controllers
  *	@c: the controller which was added
@@ -554,6 +480,8 @@
 	.name = OSM_NAME,
 	.reply = i2o_scsi_reply,
 	.classes = i2o_scsi_class_id,
+	.notify_device_add = i2o_scsi_notify_device_add,
+	.notify_device_remove = i2o_scsi_notify_device_remove,
 	.notify_controller_add = i2o_scsi_notify_controller_add,
 	.notify_controller_remove = i2o_scsi_notify_controller_remove,
 	.driver = {
@@ -712,7 +640,7 @@
 	 */
 
 	/* Attach tags to the devices */
-	/*
+	/* FIXME: implement
 	   if(SCpnt->device->tagged_supported) {
 	   if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
 	   scsi_flags |= 0x01000000;