📄 iop.c
字号:
&msg->u.head[1]); if ((rc = i2o_msg_post_wait(c, m, 30))) printk(KERN_INFO "%s: Unable to clear (status=%#x).\n", c->name, -rc); else pr_debug("%s: Cleared.\n", c->name); /* Enable all IOPs */ i2o_iop_enable_all(); i2o_status_get(c); return rc;}/** * i2o_iop_reset - reset an I2O controller * @c: controller to reset * * Reset the IOP into INIT state and wait until IOP gets into RESET state. * Terminate all external operations, clear IOP's inbound and outbound * queues, terminate all DDMs, and reload the IOP's operating environment * and all local DDMs. The IOP rebuilds its LCT. */static int i2o_iop_reset(struct i2o_controller *c){ u8 *status = c->status.virt; struct i2o_message __iomem *msg; u32 m; unsigned long timeout; i2o_status_block *sb = c->status_block.virt; int rc = 0; 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, 8); /* Quiesce all IOPs first */ i2o_iop_quiesce_all(); writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); writel(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); writel(i2o_exec_driver.context, &msg->u.s.icntxt); writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context writel(0, &msg->body[0]); writel(0, &msg->body[1]); writel(i2o_ptr_low((void *)c->status.phys), &msg->body[2]); writel(i2o_ptr_high((void *)c->status.phys), &msg->body[3]); i2o_msg_post(c, m); /* Wait for a reply */ timeout = jiffies + I2O_TIMEOUT_RESET * HZ; while (!*status) { if (time_after(jiffies, timeout)) { 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); rmb(); } if (*status == I2O_CMD_IN_PROGRESS) { /* * Once the reset is sent, the IOP goes into the INIT state * which is indeterminate. We need to wait until the IOP * has rebooted before we can let the system talk to * it. We read the inbound Free_List until a message is * available. If we can't read one in the given ammount of * time, we assume the IOP could not reboot properly. */ pr_debug("%s: Reset in progress, waiting for reboot...\n", c->name); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); while (m == I2O_QUEUE_EMPTY) { if (time_after(jiffies, timeout)) { printk(KERN_ERR "%s: IOP reset timeout.\n", c->name); rc = -ETIMEDOUT; goto exit; } set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); } i2o_msg_nop(c, m); } /* from here all quiesce commands are safe */ c->no_quiesce = 0; /* If IopReset was rejected or didn't perform reset, try IopClear */ i2o_status_get(c); if (*status == I2O_CMD_REJECTED || sb->iop_state != ADAPTER_STATE_RESET) { printk(KERN_WARNING "%s: Reset rejected, trying to clear\n", c->name); i2o_iop_clear(c); } else pr_debug("%s: Reset completed.\n", c->name); exit: /* Enable all IOPs */ i2o_iop_enable_all(); return rc;};/** * i2o_iop_init_outbound_queue - setup the outbound message queue * @c: I2O controller * * Clear and (re)initialize IOP's outbound queue and post the message * frames to the IOP. * * Returns 0 on success or a negative errno code on failure. */static int i2o_iop_init_outbound_queue(struct i2o_controller *c){ u8 *status = c->status.virt; u32 m; struct i2o_message __iomem *msg; ulong timeout; int i; pr_debug("%s: Initializing Outbound Queue...\n", c->name); memset(status, 0, 4); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); if (m == I2O_QUEUE_EMPTY) return -ETIMEDOUT; writel(EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6, &msg->u.head[0]); writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); writel(i2o_exec_driver.context, &msg->u.s.icntxt); writel(0x0106, &msg->u.s.tcntxt); /* FIXME: why 0x0106, maybe in Spec? */ writel(PAGE_SIZE, &msg->body[0]); writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); /* Outbound msg frame size in words and Initcode */ writel(0xd0000004, &msg->body[2]); writel(i2o_ptr_low((void *)c->status.phys), &msg->body[3]); writel(i2o_ptr_high((void *)c->status.phys), &msg->body[4]); i2o_msg_post(c, m); timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; while (*status <= I2O_CMD_IN_PROGRESS) { if (time_after(jiffies, timeout)) { printk(KERN_WARNING "%s: Timeout Initializing\n", c->name); return -ETIMEDOUT; } set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); rmb(); } m = c->out_queue.phys; /* 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 * * This function brings an I2O controller into HOLD state. The adapter * is reset if necessary and then the queues and resource table are read. * * Returns 0 on success or negative error code on failure. */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 "%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 version 1.5 of the I2O " "Specification.\n", c->name); return -ENODEV; } switch (sb->iop_state) { case ADAPTER_STATE_FAULTED: printk(KERN_CRIT "%s: hardware fault\n", c->name); return -ENODEV; case ADAPTER_STATE_READY: case ADAPTER_STATE_OPERATIONAL: case ADAPTER_STATE_HOLD: case ADAPTER_STATE_FAILED: pr_debug("%s: already running, trying to reset...\n", c->name); if (i2o_iop_reset(c)) return -ENODEV; } rc = i2o_iop_init_outbound_queue(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); return rc;};/** * i2o_iop_systab_set - Set the I2O System Table of the specified IOP * @c: I2O controller to which the system table should be send * * Before the systab could be set i2o_systab_build() must be called. * * Returns 0 on success or negative error code on failure. */static int i2o_iop_systab_set(struct i2o_controller *c){ struct i2o_message __iomem *msg; u32 m; i2o_status_block *sb = c->status_block.virt; struct device *dev = &c->pdev->dev; struct resource *root; int rc; if (sb->current_mem_size < sb->desired_mem_size) { struct resource *res = &c->mem_resource; res->name = c->pdev->bus->name; res->flags = IORESOURCE_MEM; res->start = 0; res->end = 0; printk(KERN_INFO "%s: requires private memory resources.\n", c->name); root = pci_find_parent_resource(c->pdev, res); if (root == NULL) 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); } } if (sb->current_io_size < sb->desired_io_size) { struct resource *res = &c->io_resource; res->name = c->pdev->bus->name; res->flags = IORESOURCE_IO; res->start = 0; res->end = 0; printk(KERN_INFO "%s: requires private memory resources.\n", c->name); root = pci_find_parent_resource(c->pdev, res); if (root == NULL) 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); } } m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); if (m == I2O_QUEUE_EMPTY) return -ETIMEDOUT; i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len, PCI_DMA_TODEVICE); if (!i2o_systab.phys) { i2o_msg_nop(c, m); return -ENOMEM; } writel(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6, &msg->u.head[0]); writel(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); /* * Provide three SGL-elements: * System table (SysTab), Private memory space declaration and * Private i/o space declaration * * FIXME: is this still true? * Nasty one here. We can't use dma_alloc_coherent to send the * same table to everyone. We have to go remap it for them all */ writel(c->unit + 2, &msg->body[0]); writel(0, &msg->body[1]); 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]); writel(0xd4000000 | sb->current_io_size, &msg->body[6]); writel(sb->current_io_base, &msg->body[6]); rc = i2o_msg_post_wait(c, m, 120); dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len, PCI_DMA_TODEVICE); if (rc < 0) printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n", c->name, -rc); else pr_debug("%s: SysTab set.\n", c->name); i2o_status_get(c); // Entered READY state return rc;}/** * i2o_iop_online - Bring a controller online into OPERATIONAL state. * @c: I2O controller * * Send the system table and enable the I2O controller. * * Returns 0 on success or negativer error code on failure. */static int i2o_iop_online(struct i2o_controller *c){ int rc; rc = i2o_iop_systab_set(c); if (rc) return rc; /* In READY state */ pr_debug("%s: Attempting to enable...\n", c->name); rc = i2o_iop_enable(c); if (rc) return rc; return 0;};/** * i2o_iop_remove - Remove the I2O controller from the I2O core * @c: I2O controller * * Remove the I2O controller from the I2O core. If devices are attached to * the controller remove these also and finally reset the controller. */void i2o_iop_remove(struct i2o_controller *c){ struct i2o_device *dev, *tmp; pr_debug("%s: deleting controller\n", c->name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -