#include <linux/module.h>
#include <linux/i2o.h>
+#include <linux/delay.h>
+
+#define OSM_VERSION "$Rev$"
+#define OSM_DESCRIPTION "I2O subsystem"
/* global I2O controller list */
LIST_HEAD(i2o_controllers);
*/
static struct i2o_dma i2o_systab;
+static int i2o_hrt_get(struct i2o_controller *c);
+
/* Module internal functions from other sources */
extern struct i2o_driver i2o_exec_driver;
extern int i2o_exec_lct_get(struct i2o_controller *);
*/
void i2o_msg_nop(struct i2o_controller *c, u32 m)
{
- struct i2o_message *msg = c->in_queue.virt + m;
+ struct i2o_message __iomem *msg = c->in_queue.virt + m;
writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
* address from the read port (see the i2o spec). If no message is
* available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
*/
-u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message **msg,
+u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message __iomem **msg,
int wait)
{
unsigned long timeout = jiffies + wait * HZ;
*
* Returns context id > 0 on success or 0 on failure.
*/
-u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr)
+u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr)
{
struct i2o_context_list_element *entry;
unsigned long flags;
if (!ptr)
- printk(KERN_ERR "NULL pointer found!\n");
+ printk(KERN_ERR "%s: couldn't add NULL pointer to context list!"
+ "\n", c->name);
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (!entry) {
- printk(KERN_ERR "i2o: Could not allocate memory for context "
- "list element\n");
+ printk(KERN_ERR "%s: Could not allocate memory for context "
+ "list element\n", c->name);
return 0;
}
spin_unlock_irqrestore(&c->context_list_lock, flags);
- pr_debug("Add context to list %p -> %d\n", ptr, context);
+ pr_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context);
return entry->context;
};
*
* Returns context id on succes or 0 on failure.
*/
-u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr)
+u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr)
{
struct i2o_context_list_element *entry;
u32 context = 0;
spin_unlock_irqrestore(&c->context_list_lock, flags);
if (!context)
- printk(KERN_WARNING "i2o: Could not remove nonexistent ptr "
- "%p\n", ptr);
+ printk(KERN_WARNING "%s: Could not remove nonexistent ptr "
+ "%p\n", c->name, ptr);
- pr_debug("remove ptr from context list %d -> %p\n", context, ptr);
+ pr_debug("%s: remove ptr from context list %d -> %p\n", c->name,
+ context, ptr);
return context;
};
spin_unlock_irqrestore(&c->context_list_lock, flags);
if (!ptr)
- printk(KERN_WARNING "i2o: context id %d not found\n", context);
+ printk(KERN_WARNING "%s: context id %d not found\n", c->name,
+ context);
- pr_debug("get ptr from context list %d -> %p\n", context, ptr);
+ pr_debug("%s: get ptr from context list %d -> %p\n", c->name, context,
+ ptr);
return ptr;
};
spin_unlock_irqrestore(&c->context_list_lock, flags);
if (!context)
- printk(KERN_WARNING "i2o: Could not find nonexistent ptr "
- "%p\n", ptr);
+ printk(KERN_WARNING "%s: Could not find nonexistent ptr "
+ "%p\n", c->name, ptr);
- pr_debug("get context id from context list %p -> %d\n", ptr, context);
+ pr_debug("%s: get context id from context list %p -> %d\n", c->name,
+ ptr, context);
return context;
};
*/
static int i2o_iop_quiesce(struct i2o_controller *c)
{
- struct i2o_message *msg;
+ struct i2o_message __iomem *msg;
u32 m;
i2o_status_block *sb = c->status_block.virt;
int rc;
*/
static int i2o_iop_enable(struct i2o_controller *c)
{
- struct i2o_message *msg;
+ struct i2o_message __iomem *msg;
u32 m;
i2o_status_block *sb = c->status_block.virt;
int rc;
*/
static int i2o_iop_clear(struct i2o_controller *c)
{
- struct i2o_message *msg;
+ struct i2o_message __iomem *msg;
u32 m;
int rc;
static int i2o_iop_reset(struct i2o_controller *c)
{
u8 *status = c->status.virt;
- struct i2o_message *msg;
+ struct i2o_message __iomem *msg;
u32 m;
unsigned long timeout;
i2o_status_block *sb = c->status_block.virt;
int rc = 0;
- pr_debug("Resetting controller\n");
+ pr_debug("%s: Resetting controller\n", c->name);
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
if (m == I2O_QUEUE_EMPTY)
return -ETIMEDOUT;
- memset(status, 0, 4);
+ memset(status, 0, 8);
/* Quiesce all IOPs first */
i2o_iop_quiesce_all();
timeout = jiffies + I2O_TIMEOUT_RESET * HZ;
while (!*status) {
if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "IOP reset timeout.\n");
+ printk(KERN_ERR "%s: IOP reset timeout.\n", c->name);
rc = -ETIMEDOUT;
goto exit;
}
+
+ /* Promise bug */
+ if (status[1] || status[4]) {
+ *status = 0;
+ break;
+ }
+
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
while (m == I2O_QUEUE_EMPTY) {
if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "IOP reset timeout.\n");
+ printk(KERN_ERR "%s: IOP reset timeout.\n",
+ c->name);
rc = -ETIMEDOUT;
goto exit;
}
*
* Returns 0 on success or a negative errno code on failure.
*/
-int i2o_iop_init_outbound_queue(struct i2o_controller *c)
+static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
{
u8 *status = c->status.virt;
u32 m;
- struct i2o_message *msg;
+ struct i2o_message __iomem *msg;
ulong timeout;
int i;
/* 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 __iomem *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
*/
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 */
rc = i2o_status_get(c);
if (rc) {
- printk(KERN_INFO "Unable to obtain status of %s, "
+ printk(KERN_INFO "%s: Unable to obtain status, "
"attempting a reset.\n", c->name);
if (i2o_iop_reset(c))
return rc;
}
if (sb->i2o_version > I2OVER15) {
- printk(KERN_ERR "%s: Not running vrs. 1.5. of the I2O "
+ printk(KERN_ERR "%s: Not running version 1.5 of the I2O "
"Specification.\n", c->name);
return -ENODEV;
}
case ADAPTER_STATE_OPERATIONAL:
case ADAPTER_STATE_HOLD:
case ADAPTER_STATE_FAILED:
- pr_debug("already running, trying to reset...\n");
+ pr_debug("%s: already running, trying to reset...\n", c->name);
if (i2o_iop_reset(c))
return -ENODEV;
}
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;
};
/**
*/
static int i2o_iop_systab_set(struct i2o_controller *c)
{
- struct i2o_message *msg;
+ struct i2o_message __iomem *msg;
u32 m;
i2o_status_block *sb = c->status_block.virt;
struct device *dev = &c->pdev->dev;
res->flags = IORESOURCE_MEM;
res->start = 0;
res->end = 0;
- printk("%s: requires private memory resources.\n", c->name);
+ printk(KERN_INFO "%s: requires private memory resources.\n",
+ c->name);
root = pci_find_parent_resource(c->pdev, res);
if (root == NULL)
- printk("Can't find parent resource!\n");
+ printk(KERN_WARNING "%s: Can't find parent resource!\n",
+ c->name);
if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
NULL, NULL) >= 0) {
c->mem_alloc = 1;
sb->current_mem_size = 1 + res->end - res->start;
sb->current_mem_base = res->start;
- printk(KERN_INFO
- "%s: allocated %ld bytes of PCI memory at 0x%08lX.\n",
- c->name, 1 + res->end - res->start, res->start);
+ printk(KERN_INFO "%s: allocated %ld bytes of PCI memory"
+ " at 0x%08lX.\n", c->name,
+ 1 + res->end - res->start, res->start);
}
}
res->flags = IORESOURCE_IO;
res->start = 0;
res->end = 0;
- printk("%s: requires private memory resources.\n", c->name);
+ printk(KERN_INFO "%s: requires private memory resources.\n",
+ c->name);
root = pci_find_parent_resource(c->pdev, res);
if (root == NULL)
- printk("Can't find parent resource!\n");
+ printk(KERN_WARNING "%s: Can't find parent resource!\n",
+ c->name);
if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
NULL, NULL) >= 0) {
c->io_alloc = 1;
sb->current_io_size = 1 + res->end - res->start;
sb->current_mem_base = res->start;
- printk(KERN_INFO
- "%s: allocated %ld bytes of PCI I/O at 0x%08lX.\n",
- c->name, 1 + res->end - res->start, res->start);
+ printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at"
+ " 0x%08lX.\n", c->name,
+ 1 + res->end - res->start, res->start);
}
}
writel(c->unit + 2, &msg->body[0]);
writel(0, &msg->body[1]);
- writel(0x54000000 | i2o_systab.phys, &msg->body[2]);
+ writel(0x54000000 | i2o_systab.len, &msg->body[2]);
writel(i2o_systab.phys, &msg->body[3]);
writel(0x54000000 | sb->current_mem_size, &msg->body[4]);
writel(sb->current_mem_base, &msg->body[5]);
{
struct i2o_device *dev, *tmp;
- pr_debug("Deleting controller %s\n", c->name);
+ pr_debug("%s: deleting controller\n", c->name);
i2o_driver_notify_controller_remove_all(c);
*/
int i2o_status_get(struct i2o_controller *c)
{
- struct i2o_message *msg;
+ struct i2o_message __iomem *msg;
u32 m;
u8 *status_block;
unsigned long timeout;
*
* Returns 0 on success or negativer error code on failure.
*/
-int i2o_hrt_get(struct i2o_controller *c)
+static int i2o_hrt_get(struct i2o_controller *c)
{
int rc;
int i;
struct device *dev = &c->pdev->dev;
for (i = 0; i < I2O_HRT_GET_TRIES; i++) {
- struct i2o_message *msg;
+ struct i2o_message __iomem *msg;
u32 m;
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
c = kmalloc(sizeof(*c), GFP_KERNEL);
if (!c) {
- printk(KERN_ERR "i2o: Insufficient memory to allocate the "
+ printk(KERN_ERR "i2o: Insufficient memory to allocate a I2O "
"controller.\n");
return ERR_PTR(-ENOMEM);
}
memset(c, 0, sizeof(*c));
INIT_LIST_HEAD(&c->devices);
- c->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&c->lock);
init_MUTEX(&c->lct_lock);
c->unit = unit++;
sprintf(c->name, "iop%d", c->unit);
#if BITS_PER_LONG == 64
- c->context_list_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&c->context_list_lock);
atomic_set(&c->context_list_counter, 0);
INIT_LIST_HEAD(&c->context_list);
#endif
"devices\n", c->name);
if ((rc = i2o_iop_activate(c))) {
- printk(KERN_ERR "%s: controller could not activated\n",
+ printk(KERN_ERR "%s: could not activate controller\n",
c->name);
i2o_iop_reset(c);
return rc;
}
- pr_debug("building sys table %s...\n", c->name);
+ pr_debug("%s: building sys table...\n", c->name);
if ((rc = i2o_systab_build())) {
i2o_iop_reset(c);
return rc;
}
- pr_debug("online controller %s...\n", c->name);
+ pr_debug("%s: online controller...\n", c->name);
if ((rc = i2o_iop_online(c))) {
i2o_iop_reset(c);
return rc;
}
- pr_debug("getting LCT %s...\n", c->name);
+ pr_debug("%s: getting LCT...\n", c->name);
if ((rc = i2o_exec_lct_get(c))) {
i2o_iop_reset(c);
int tcntxt, u32 evt_mask)
{
struct i2o_controller *c = dev->iop;
- struct i2o_message *msg;
+ struct i2o_message __iomem *msg;
u32 m;
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
{
int rc = 0;
- printk(KERN_INFO "I2O Core - (C) Copyright 1999 Red Hat Software\n");
+ printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
rc = i2o_device_init();
if (rc)
module_exit(i2o_iop_exit);
MODULE_AUTHOR("Red Hat Software");
-MODULE_DESCRIPTION("I2O Core");
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(OSM_DESCRIPTION);
+MODULE_VERSION(OSM_VERSION);
#if BITS_PER_LONG == 64
EXPORT_SYMBOL(i2o_cntxt_list_add);
EXPORT_SYMBOL(i2o_iop_find_device);
EXPORT_SYMBOL(i2o_event_register);
EXPORT_SYMBOL(i2o_status_get);
-EXPORT_SYMBOL(i2o_hrt_get);
EXPORT_SYMBOL(i2o_controllers);