⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iop.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	       &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 + -