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

📄 iop.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	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){	volatile u8 *status = c->status.virt;	u32 m;	struct i2o_message __iomem *msg;	ulong timeout;	int i;	osm_debug("%s: Initializing Outbound Queue...\n", c->name);	memset(c->status.virt, 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 | SGL_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(0x00000000, &msg->u.s.tcntxt);	writel(PAGE_SIZE, &msg->body[0]);	/* Outbound msg frame size in words and Initcode */	writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);	writel(0xd0000004, &msg->body[2]);	writel(i2o_dma_low(c->status.phys), &msg->body[3]);	writel(i2o_dma_high(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)) {			osm_warn("%s: Timeout Initializing\n", c->name);			return -ETIMEDOUT;		}		schedule_timeout_uninterruptible(1);	}	m = c->out_queue.phys;	/* Post frames */	for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) {		i2o_flush_reply(c, m);		udelay(1);	/* Promise */		m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32);	}	return 0;}/** *	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){	volatile 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;	osm_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(c->status_block.virt, 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_dma_low(c->status.phys), &msg->body[2]);	writel(i2o_dma_high(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))			break;		schedule_timeout_uninterruptible(1);	}	switch (*status) {	case I2O_CMD_REJECTED:		osm_warn("%s: IOP reset rejected\n", c->name);		rc = -EPERM;		break;	case 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.		 */		osm_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)) {				osm_err("%s: IOP reset timeout.\n", c->name);				rc = -ETIMEDOUT;				goto exit;			}			schedule_timeout_uninterruptible(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;		/* verify if controller is in state RESET */		i2o_status_get(c);		if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET))			osm_warn("%s: reset completed, but adapter not in RESET"				 " state.\n", c->name);		else			osm_debug("%s: reset completed.\n", c->name);		break;	default:		osm_err("%s: IOP reset timeout.\n", c->name);		rc = -ETIMEDOUT;		break;	}      exit:	/* Enable all IOPs */	i2o_iop_enable_all();	return rc;};/** *	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){	i2o_status_block *sb = c->status_block.virt;	int rc;	int state;	/* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */	/* In READY state, Get status */	rc = i2o_status_get(c);	if (rc) {		osm_info("%s: Unable to obtain status, attempting a reset.\n",			 c->name);		rc = i2o_iop_reset(c);		if (rc)			return rc;	}	if (sb->i2o_version > I2OVER15) {		osm_err("%s: Not running version 1.5 of the I2O Specification."			"\n", c->name);		return -ENODEV;	}	switch (sb->iop_state) {	case ADAPTER_STATE_FAULTED:		osm_err("%s: hardware fault\n", c->name);		return -EFAULT;	case ADAPTER_STATE_READY:	case ADAPTER_STATE_OPERATIONAL:	case ADAPTER_STATE_HOLD:	case ADAPTER_STATE_FAILED:		osm_debug("%s: already running, trying to reset...\n", c->name);		rc = i2o_iop_reset(c);		if (rc)			return rc;	}	/* preserve state */	state = sb->iop_state;	rc = i2o_iop_init_outbound_queue(c);	if (rc)		return rc;	/* if adapter was not in RESET state clear now */	if (state != ADAPTER_STATE_RESET)		i2o_iop_clear(c);	i2o_status_get(c);	if (sb->iop_state != ADAPTER_STATE_HOLD) {		osm_err("%s: failed to bring IOP into HOLD state\n", c->name);		return -EIO;	}	return i2o_hrt_get(c);};/** *	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;		osm_info("%s: requires private memory resources.\n", c->name);		root = pci_find_parent_resource(c->pdev, res);		if (root == NULL)			osm_warn("%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;			osm_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;		osm_info("%s: requires private memory resources.\n", c->name);		root = pci_find_parent_resource(c->pdev, res);		if (root == NULL)			osm_warn("%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;			osm_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)		osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name,			-rc);	else		osm_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 */	osm_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;	osm_debug("%s: deleting controller\n", c->name);	i2o_driver_notify_controller_remove_all(c);	list_del(&c->list);	list_for_each_entry_safe(dev, tmp, &c->devices, list)	    i2o_device_remove(dev);	class_device_unregister(c->classdev);	device_del(&c->device);	/* Ask the IOP to switch to RESET state */	i2o_iop_reset(c);	put_device(&c->device);}/** *	i2o_systab_build - Build system table * *	The system table contains information about all the IOPs in the system *	(duh) and is used by the Executives on the IOPs to establish peer2peer *	connections. We're not supporting peer2peer at the moment, but this *	will be needed down the road for things like lan2lan forwarding. * *	Returns 0 on success or negative error code on failure. */static int i2o_systab_build(void){	struct i2o_controller *c, *tmp;	int num_controllers = 0;	u32 change_ind = 0;	int count = 0;	struct i2o_sys_tbl *systab = i2o_systab.virt;	list_for_each_entry_safe(c, tmp, &i2o_controllers, list)	    num_controllers++;	if (systab) {		change_ind = systab->change_ind;		kfree(i2o_systab.virt);	}	/* Header + IOPs */	i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers *	    sizeof(struct i2o_sys_tbl_entry);	systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -