
From: Markus Lidel <Markus.Lidel@shadowconnect.com>

- added new function i2o_msg_in_to_virt and i2o_msg_out_to_virt, to turn an
  I2O message to a virtual address (original from Alan Cox)

- replaced readl with le32_to_cpu where it is not necessary (original from
  Alan Cox)

Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/message/i2o/exec-osm.c  |   10 +++---
 25-akpm/drivers/message/i2o/i2o_block.c |   27 +++++++++---------
 25-akpm/drivers/message/i2o/i2o_scsi.c  |   18 ++++++------
 25-akpm/drivers/message/i2o/pci.c       |    7 ----
 25-akpm/include/linux/i2o.h             |   46 +++++++++++++++++++++++++++++++-
 5 files changed, 74 insertions(+), 34 deletions(-)

diff -puN drivers/message/i2o/exec-osm.c~i2o-new-functions-to-convert-messages-to-a-virtual-address drivers/message/i2o/exec-osm.c
--- 25/drivers/message/i2o/exec-osm.c~i2o-new-functions-to-convert-messages-to-a-virtual-address	Fri Oct  8 14:32:36 2004
+++ 25-akpm/drivers/message/i2o/exec-osm.c	Fri Oct  8 14:32:36 2004
@@ -322,13 +322,13 @@ static void i2o_exec_lct_modified(struct
 static int i2o_exec_reply(struct i2o_controller *c, u32 m,
 			  struct i2o_message *msg)
 {
-	if (readl(&msg->u.head[0]) & MSG_FAIL) {	// Fail bit is set
+	if (le32_to_cpu(&msg->u.head[0]) & MSG_FAIL) {	// Fail bit is set
 		struct i2o_message *pmsg;	/* preserved message */
 		u32 pm;
 
-		pm = readl(&msg->body[3]);
+		pm = le32_to_cpu(&msg->body[3]);
 
-		pmsg = c->in_queue.virt + pm;
+		pmsg = i2o_msg_in_to_virt(c, pm);
 
 		i2o_report_status(KERN_INFO, "i2o_core", msg);
 
@@ -339,10 +339,10 @@ static int i2o_exec_reply(struct i2o_con
 		return -1;
 	}
 
-	if (readl(&msg->u.s.tcntxt) & 0x80000000)
+	if (le32_to_cpu(&msg->u.s.tcntxt) & 0x80000000)
 		return i2o_msg_post_wait_complete(c, m, msg);
 
-	if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
+	if ((le32_to_cpu(&msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
 		struct work_struct *work;
 
 		pr_debug("%s: LCT notify received\n", c->name);
diff -puN drivers/message/i2o/i2o_block.c~i2o-new-functions-to-convert-messages-to-a-virtual-address drivers/message/i2o/i2o_block.c
--- 25/drivers/message/i2o/i2o_block.c~i2o-new-functions-to-convert-messages-to-a-virtual-address	Fri Oct  8 14:32:36 2004
+++ 25-akpm/drivers/message/i2o/i2o_block.c	Fri Oct  8 14:32:36 2004
@@ -416,7 +416,7 @@ static int i2o_block_reply(struct i2o_co
 	unsigned long flags;
 
 	/* FAILed message */
-	if (unlikely(readl(&msg->u.head[0]) & (1 << 13))) {
+	if (unlikely(le32_to_cpu(&msg->u.head[0]) & (1 << 13))) {
 		struct i2o_message *pmsg;
 		u32 pm;
 
@@ -430,10 +430,10 @@ static int i2o_block_reply(struct i2o_co
 		 * better be on the safe side since no one really follows
 		 * the spec to the book :)
 		 */
-		pm = readl(&msg->body[3]);
-		pmsg = c->in_queue.virt + pm;
+		pm = le32_to_cpu(&msg->body[3]);
+		pmsg = i2o_msg_in_to_virt(c, pm);
 
-		req = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt));
+		req = i2o_cntxt_list_get(c, le32_to_cpu(&pmsg->u.s.tcntxt));
 		if (unlikely(!req)) {
 			printk(KERN_ERR "block-osm: NULL reply received!\n");
 			return -1;
@@ -448,7 +448,7 @@ static int i2o_block_reply(struct i2o_co
 		spin_lock_irqsave(q->queue_lock, flags);
 
 		while (end_that_request_chunk(req, !req->errors,
-					      readl(&pmsg->body[1]))) ;
+					      le32_to_cpu(&pmsg->body[1]))) ;
 		end_that_request_last(req);
 
 		dev->open_queue_depth--;
@@ -463,7 +463,7 @@ static int i2o_block_reply(struct i2o_co
 		return -1;
 	}
 
-	req = i2o_cntxt_list_get(c, readl(&msg->u.s.tcntxt));
+	req = i2o_cntxt_list_get(c, le32_to_cpu(&msg->u.s.tcntxt));
 	if (unlikely(!req)) {
 		printk(KERN_ERR "block-osm: NULL reply received!\n");
 		return -1;
@@ -486,7 +486,7 @@ static int i2o_block_reply(struct i2o_co
 		       "I2O Block: Data transfer to deleted device!\n");
 		spin_lock_irqsave(q->queue_lock, flags);
 		while (end_that_request_chunk
-		       (req, !req->errors, readl(&msg->body[1]))) ;
+		       (req, !req->errors, le32_to_cpu(&msg->body[1]))) ;
 		end_that_request_last(req);
 
 		dev->open_queue_depth--;
@@ -502,7 +502,7 @@ static int i2o_block_reply(struct i2o_co
 	 *      request in the context.
 	 */
 
-	st = readl(&msg->body[0]) >> 24;
+	st = le32_to_cpu(&msg->body[0]) >> 24;
 
 	if (st != 0) {
 		int err;
@@ -523,7 +523,7 @@ static int i2o_block_reply(struct i2o_co
 			"Volume has changed, waiting for acknowledgement"
 		};
 
-		err = readl(&msg->body[0]) & 0xffff;
+		err = le32_to_cpu(&msg->body[0]) & 0xffff;
 
 		/*
 		 *      Device not ready means two things. One is that the
@@ -538,16 +538,17 @@ static int i2o_block_reply(struct i2o_co
 		 */
 
 		printk(KERN_ERR "/dev/%s error: %s", dev->gd->disk_name,
-		       bsa_errors[readl(&msg->body[0]) & 0xffff]);
-		if (readl(&msg->body[0]) & 0x00ff0000)
+		       bsa_errors[le32_to_cpu(&msg->body[0]) & 0xffff]);
+		if (le32_to_cpu(&msg->body[0]) & 0x00ff0000)
 			printk(KERN_ERR " - DDM attempted %d retries",
-			       (readl(&msg->body[0]) >> 16) & 0x00ff);
+			       (le32_to_cpu(&msg->body[0]) >> 16) & 0x00ff);
 		printk(KERN_ERR ".\n");
 		req->errors++;
 	} else
 		req->errors = 0;
 
-	if (!end_that_request_chunk(req, !req->errors, readl(&msg->body[1]))) {
+	if (!end_that_request_chunk
+	    (req, !req->errors, le32_to_cpu(&msg->body[1]))) {
 		add_disk_randomness(req->rq_disk);
 		spin_lock_irqsave(q->queue_lock, flags);
 
diff -puN drivers/message/i2o/i2o_scsi.c~i2o-new-functions-to-convert-messages-to-a-virtual-address drivers/message/i2o/i2o_scsi.c
--- 25/drivers/message/i2o/i2o_scsi.c~i2o-new-functions-to-convert-messages-to-a-virtual-address	Fri Oct  8 14:32:36 2004
+++ 25-akpm/drivers/message/i2o/i2o_scsi.c	Fri Oct  8 14:32:36 2004
@@ -296,15 +296,15 @@ static int i2o_scsi_reply(struct i2o_con
 	struct device *dev;
 	u8 as, ds, st;
 
-	cmd = i2o_cntxt_list_get(c, readl(&msg->u.s.tcntxt));
+	cmd = i2o_cntxt_list_get(c, le32_to_cpu(&msg->u.s.tcntxt));
 
 	if (msg->u.head[0] & (1 << 13)) {
 		struct i2o_message *pmsg;	/* preserved message */
 		u32 pm;
 
-		pm = readl(&msg->body[3]);
+		pm = le32_to_cpu(&msg->body[3]);
 
-		pmsg = c->in_queue.virt + pm;
+		pmsg = i2o_msg_in_to_virt(c, pm);
 
 		printk(KERN_ERR "IOP fail.\n");
 		printk(KERN_ERR "From %d To %d Cmd %d.\n",
@@ -339,9 +339,9 @@ static int i2o_scsi_reply(struct i2o_con
 	 *      Low byte is device status, next is adapter status,
 	 *      (then one byte reserved), then request status.
 	 */
-	ds = (u8) readl(&msg->body[0]);
-	as = (u8) (readl(&msg->body[0]) >> 8);
-	st = (u8) (readl(&msg->body[0]) >> 24);
+	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 ?
@@ -350,7 +350,7 @@ static int i2o_scsi_reply(struct i2o_con
 	if (!cmd) {
 		if (st)
 			printk(KERN_WARNING "SCSI abort: %08X",
-			       readl(&msg->body[0]));
+			       le32_to_cpu(&msg->body[0]));
 		printk(KERN_INFO "SCSI abort completed.\n");
 		return -EFAULT;
 	}
@@ -363,7 +363,7 @@ static int i2o_scsi_reply(struct i2o_con
 
 		switch (st) {
 		case 0x06:
-			count = readl(&msg->body[1]);
+			count = le32_to_cpu(&msg->body[1]);
 			if (count < cmd->underflow) {
 				int i;
 				printk(KERN_ERR "SCSI: underflow 0x%08X 0x%08X"
@@ -378,7 +378,7 @@ static int i2o_scsi_reply(struct i2o_con
 			break;
 
 		default:
-			error = readl(&msg->body[0]);
+			error = le32_to_cpu(&msg->body[0]);
 
 			printk(KERN_ERR "scsi-osm: SCSI error %08x\n", error);
 
diff -puN drivers/message/i2o/pci.c~i2o-new-functions-to-convert-messages-to-a-virtual-address drivers/message/i2o/pci.c
--- 25/drivers/message/i2o/pci.c~i2o-new-functions-to-convert-messages-to-a-virtual-address	Fri Oct  8 14:32:36 2004
+++ 25-akpm/drivers/message/i2o/pci.c	Fri Oct  8 14:32:36 2004
@@ -277,7 +277,6 @@ static irqreturn_t i2o_pci_interrupt(int
 	struct device *dev = &c->pdev->dev;
 	struct i2o_message *m;
 	u32 mv;
-	u32 *msg;
 
 	/*
 	 * Old 960 steppings had a bug in the I2O unit that caused
@@ -298,11 +297,7 @@ static irqreturn_t i2o_pci_interrupt(int
 		 * Because bus_to_virt is deprecated, we have calculate the
 		 * location by ourself!
 		 */
-		m = (struct i2o_message *)(mv -
-					   (unsigned long)c->out_queue.phys +
-					   (unsigned long)c->out_queue.virt);
-
-		msg = (u32 *) m;
+		m = i2o_msg_out_to_virt(c, mv);
 
 		/*
 		 *      Ensure this message is seen coherently but cachably by
diff -puN include/linux/i2o.h~i2o-new-functions-to-convert-messages-to-a-virtual-address include/linux/i2o.h
--- 25/include/linux/i2o.h~i2o-new-functions-to-convert-messages-to-a-virtual-address	Fri Oct  8 14:32:36 2004
+++ 25-akpm/include/linux/i2o.h	Fri Oct  8 14:32:36 2004
@@ -47,7 +47,7 @@ struct i2o_message {
 			u32 function:8;
 			u32 icntxt;	/* initiator context */
 			u32 tcntxt;	/* transaction context */
-		} s;
+		} __attribute((packed)) s;
 		u32 head[4];
 	} u;
 	/* List follows */
@@ -252,6 +252,11 @@ extern int i2o_msg_post_wait_mem(struct 
 extern void i2o_msg_nop(struct i2o_controller *, u32);
 static inline void i2o_flush_reply(struct i2o_controller *, u32);
 
+static inline struct i2o_message *i2o_msg_in_to_virt(struct i2o_controller *,
+						     u32);
+static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller
+						      *, u32);
+
 /* DMA handling functions */
 static inline int i2o_dma_alloc(struct device *, struct i2o_dma *, size_t,
 				unsigned int);
@@ -502,6 +507,45 @@ static inline void i2o_flush_reply(struc
 };
 
 /**
+ *	i2o_out_to_virt - Turn an I2O message to a virtual address
+ *	@c: controller
+ *	@m: message engine value
+ *
+ *	Turn a receive message from an I2O controller bus address into
+ *	a Linux virtual address. The shared page frame is a linear block
+ *	so we simply have to shift the offset. This function does not
+ *	work for sender side messages as they are ioremap objects
+ *	provided by the I2O controller.
+ */
+static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c,
+						      u32 m)
+{
+	if (unlikely
+	    (m < c->out_queue.phys
+	     || m >= c->out_queue.phys + c->out_queue.len))
+		BUG();
+
+	return c->out_queue.virt + (m - c->out_queue.phys);
+};
+
+/**
+ *	i2o_msg_in_to_virt - Turn an I2O message to a virtual address
+ *	@c: controller
+ *	@m: message engine value
+ *
+ *	Turn a send message from an I2O controller bus address into
+ *	a Linux virtual address. The shared page frame is a linear block
+ *	so we simply have to shift the offset. This function does not
+ *	work for receive side messages as they are kmalloc objects
+ *	in a different pool.
+ */
+static inline struct i2o_message *i2o_msg_in_to_virt(struct i2o_controller *c,
+						     u32 m)
+{
+	return c->in_queue.virt + m;
+};
+
+/**
  *	i2o_dma_alloc - Allocate DMA memory
  *	@dev: struct device pointer to the PCI device of the I2O controller
  *	@addr: i2o_dma struct which should get the DMA buffer
_
