[PATCH] I2O: fix and workaround for Motorola/Freescale controller
- 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@shadowconnect.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
15d8ec7d08
commit
8b3e09e199
3 changed files with 25 additions and 2 deletions
|
@ -60,4 +60,7 @@ extern void i2o_iop_remove(struct i2o_controller *);
|
|||
#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
|
||||
|
|
|
@ -168,6 +168,24 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
|
|||
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;
|
||||
|
|
|
@ -1115,9 +1115,11 @@ static inline struct i2o_message *i2o_msg_get(struct i2o_controller *c)
|
|||
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);
|
||||
if(mmsg->mfa == I2O_QUEUE_EMPTY)
|
||||
return ERR_PTR(-EBUSY);
|
||||
return ERR_PTR(-EFAULT);
|
||||
}
|
||||
|
||||
return &mmsg->msg;
|
||||
|
|
Loading…
Reference in a new issue