Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b3e09e1 authored by Markus Lidel's avatar Markus Lidel Committed by Linus Torvalds
Browse files

[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: default avatarMarkus Lidel <Markus.Lidel@shadowconnect.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 15d8ec7d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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
+18 −0
Original line number Diff line number Diff line
@@ -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;
+4 −2
Original line number Diff line number Diff line
@@ -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;