[PATCH 2/2] I2O: fix and workaround for Motorola/Freescale controller

From: Markus Lidel
Date: Mon Jan 23 2006 - 18:28:37 EST


Changes:
--------
- This controller violates the I2O spec for the I/O registers. The patch
contains a workaround which moves the registers to the proper location.
(originally author: Matthew Starzewski)
- If a message frame is beyond the mapped address range a error is
returned.

Signed-off-by: Markus Lidel <Markus.Lidel@xxxxxxxxxxxxxxxxx> --- a/drivers/message/i2o/pci.c 2006-01-23 23:41:42.031509195 +0100
+++ b/drivers/message/i2o/pci.c 2006-01-23 01:03:51.236440918 +0100
@@ -163,6 +168,24 @@
c->in_port = c->base.virt + I2O_IN_PORT;
c->out_port = c->base.virt + I2O_OUT_PORT;

+ /* Motorola/Freescale chip does not follow spec */
+ if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) {
+ /* Check if CPU is enabled */
+ if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) {
+ printk(KERN_INFO "%s: MPC82XX needs CPU running to "
+ "service I2O.\n", c->name);
+ i2o_pci_free(c);
+ return -ENODEV;
+ } else {
+ c->irq_status += I2O_MOTOROLA_PORT_OFFSET;
+ c->irq_mask += I2O_MOTOROLA_PORT_OFFSET;
+ c->in_port += I2O_MOTOROLA_PORT_OFFSET;
+ c->out_port += I2O_MOTOROLA_PORT_OFFSET;
+ printk(KERN_INFO "%s: MPC82XX workarounds activated.\n",
+ c->name);
+ }
+ }
+
if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
i2o_pci_free(c);
return -ENOMEM;
--- a/include/linux/i2o.h 2006-01-23 23:42:06.360729954 +0100
+++ b/include/linux/i2o.h 2006-01-23 00:58:44.288144650 +0100
@@ -1115,9 +1115,11 @@
return ERR_PTR(-ENOMEM);

mmsg->mfa = readl(c->in_port);
- if (mmsg->mfa == I2O_QUEUE_EMPTY) {
+ if (unlikely(mmsg->mfa >= c->in_queue.len)) {
mempool_free(mmsg, c->in_msg.mempool);
- return ERR_PTR(-EBUSY);
+ if(mmsg->mfa == I2O_QUEUE_EMPTY)
+ return ERR_PTR(-EBUSY);
+ return ERR_PTR(-EFAULT);
}

return &mmsg->msg;
--- a/drivers/message/i2o/core.h 2006-01-23 23:41:41.995507388 +0100
+++ b/drivers/message/i2o/core.h 2006-01-23 01:04:57.811975471 +0100
@@ -60,4 +60,7 @@
#define I2O_IN_PORT 0x40
#define I2O_OUT_PORT 0x44

+/* Motorola/Freescale specific register offset */
+#define I2O_MOTOROLA_PORT_OFFSET 0x10400
+
#define I2O_IRQ_OUTBOUND_POST 0x00000008