Commit 32777000 authored by Markus Lidel's avatar Markus Lidel Committed by Linus Torvalds

[PATCH] i2o: added support for Promise controllers

- added support for Promise I2O controllers, which need a different
  initialization sequence (original from Alan Cox)
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 f21a3a38
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2o.h> #include <linux/i2o.h>
#include <linux/delay.h>
/* global I2O controller list */ /* global I2O controller list */
LIST_HEAD(i2o_controllers); LIST_HEAD(i2o_controllers);
...@@ -470,7 +471,7 @@ static int i2o_iop_reset(struct i2o_controller *c) ...@@ -470,7 +471,7 @@ static int i2o_iop_reset(struct i2o_controller *c)
if (m == I2O_QUEUE_EMPTY) if (m == I2O_QUEUE_EMPTY)
return -ETIMEDOUT; return -ETIMEDOUT;
memset(status, 0, 4); memset(status, 0, 8);
/* Quiesce all IOPs first */ /* Quiesce all IOPs first */
i2o_iop_quiesce_all(); i2o_iop_quiesce_all();
...@@ -495,6 +496,13 @@ static int i2o_iop_reset(struct i2o_controller *c) ...@@ -495,6 +496,13 @@ static int i2o_iop_reset(struct i2o_controller *c)
rc = -ETIMEDOUT; rc = -ETIMEDOUT;
goto exit; goto exit;
} }
/* Promise bug */
if (status[1] || status[4]) {
*status = 0;
break;
}
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1); schedule_timeout(1);
...@@ -605,12 +613,30 @@ int i2o_iop_init_outbound_queue(struct i2o_controller *c) ...@@ -605,12 +613,30 @@ int i2o_iop_init_outbound_queue(struct i2o_controller *c)
/* Post frames */ /* Post frames */
for (i = 0; i < NMBR_MSG_FRAMES; i++) { for (i = 0; i < NMBR_MSG_FRAMES; i++) {
i2o_flush_reply(c, m); i2o_flush_reply(c, m);
udelay(1); /* Promise */
m += MSG_FRAME_SIZE * 4; m += MSG_FRAME_SIZE * 4;
} }
return 0; return 0;
} }
/**
* i2o_iop_send_nop - send a core NOP message
* @c: controller
*
* Send a no-operation message with a reply set to cause no
* action either. Needed for bringing up promise controllers.
*/
static int i2o_iop_send_nop(struct i2o_controller *c)
{
struct i2o_message *msg;
u32 m = i2o_msg_get_wait(c, &msg, HZ);
if (m == I2O_QUEUE_EMPTY)
return -ETIMEDOUT;
i2o_msg_nop(c, m);
return 0;
}
/** /**
* i2o_iop_activate - Bring controller up to HOLD * i2o_iop_activate - Bring controller up to HOLD
* @c: controller * @c: controller
...@@ -622,8 +648,27 @@ int i2o_iop_init_outbound_queue(struct i2o_controller *c) ...@@ -622,8 +648,27 @@ int i2o_iop_init_outbound_queue(struct i2o_controller *c)
*/ */
static int i2o_iop_activate(struct i2o_controller *c) static int i2o_iop_activate(struct i2o_controller *c)
{ {
struct pci_dev *i960 = NULL;
i2o_status_block *sb = c->status_block.virt; i2o_status_block *sb = c->status_block.virt;
int rc; int rc;
if (c->promise) {
/* Beat up the hardware first of all */
i960 =
pci_find_slot(c->pdev->bus->number,
PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
if (i960)
pci_write_config_word(i960, 0x42, 0);
/* Follow this sequence precisely or the controller
ceases to perform useful functions until reboot */
if ((rc = i2o_iop_send_nop(c)))
return rc;
if ((rc = i2o_iop_reset(c)))
return rc;
}
/* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */ /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */
/* In READY state, Get status */ /* In READY state, Get status */
...@@ -659,13 +704,22 @@ static int i2o_iop_activate(struct i2o_controller *c) ...@@ -659,13 +704,22 @@ static int i2o_iop_activate(struct i2o_controller *c)
if (rc) if (rc)
return rc; return rc;
if (c->promise) {
if ((rc = i2o_iop_send_nop(c)))
return rc;
if ((rc = i2o_status_get(c)))
return rc;
if (i960)
pci_write_config_word(i960, 0x42, 0x3FF);
}
/* In HOLD state */ /* In HOLD state */
rc = i2o_hrt_get(c); rc = i2o_hrt_get(c);
if (rc)
return rc;
return 0; return rc;
}; };
/** /**
......
...@@ -231,7 +231,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) ...@@ -231,7 +231,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
} }
#endif #endif
if (i2o_dma_alloc(dev, &c->status, 4, GFP_KERNEL)) { if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
i2o_pci_free(c); i2o_pci_free(c);
return -ENOMEM; return -ENOMEM;
} }
...@@ -277,7 +277,6 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) ...@@ -277,7 +277,6 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
struct device *dev = &c->pdev->dev; struct device *dev = &c->pdev->dev;
struct i2o_message *m; struct i2o_message *m;
u32 mv; u32 mv;
u32 *msg;
/* /*
* Old 960 steppings had a bug in the I2O unit that caused * Old 960 steppings had a bug in the I2O unit that caused
...@@ -298,11 +297,7 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) ...@@ -298,11 +297,7 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
* Because bus_to_virt is deprecated, we have calculate the * Because bus_to_virt is deprecated, we have calculate the
* location by ourself! * location by ourself!
*/ */
m = (struct i2o_message *)(mv - m = i2o_msg_out_to_virt(c, mv);
(unsigned long)c->out_queue.phys +
(unsigned long)c->out_queue.virt);
msg = (u32 *) m;
/* /*
* Ensure this message is seen coherently but cachably by * Ensure this message is seen coherently but cachably by
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment