From 32777000901aa5144703f7276b8664cbea847f8f Mon Sep 17 00:00:00 2001 From: Markus Lidel Date: Mon, 18 Oct 2004 18:18:07 -0700 Subject: [PATCH] [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: Markus Lidel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/iop.c | 62 ++++++++++++++++++++++++++++++++++++--- drivers/message/i2o/pci.c | 9 ++---- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 5b5a5bfa9b49b..46fa7dfd6eb12 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -27,6 +27,7 @@ #include #include +#include /* global I2O controller list */ LIST_HEAD(i2o_controllers); @@ -470,7 +471,7 @@ static int i2o_iop_reset(struct i2o_controller *c) if (m == I2O_QUEUE_EMPTY) return -ETIMEDOUT; - memset(status, 0, 4); + memset(status, 0, 8); /* Quiesce all IOPs first */ i2o_iop_quiesce_all(); @@ -495,6 +496,13 @@ static int i2o_iop_reset(struct i2o_controller *c) rc = -ETIMEDOUT; goto exit; } + + /* Promise bug */ + if (status[1] || status[4]) { + *status = 0; + break; + } + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); @@ -605,12 +613,30 @@ int i2o_iop_init_outbound_queue(struct i2o_controller *c) /* Post frames */ for (i = 0; i < NMBR_MSG_FRAMES; i++) { i2o_flush_reply(c, m); + udelay(1); /* Promise */ m += MSG_FRAME_SIZE * 4; } 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 * @c: controller @@ -622,8 +648,27 @@ int i2o_iop_init_outbound_queue(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; 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 READY state, Get status */ @@ -659,13 +704,22 @@ static int i2o_iop_activate(struct i2o_controller *c) if (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 */ rc = i2o_hrt_get(c); - if (rc) - return rc; - return 0; + return rc; }; /** diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 2d85609b84d3f..f98849abbe2a1 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -231,7 +231,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) } #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); return -ENOMEM; } @@ -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 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 irq, void *dev_id, struct pt_regs *r) * 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 -- 2.53.0