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

📄 exec-osm.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	Executive OSM * * 	Copyright (C) 1999-2002	Red Hat Software * *	Written by Alan Cox, Building Number Three Ltd * *	This program is free software; you can redistribute it and/or modify it *	under the terms of the GNU General Public License as published by the *	Free Software Foundation; either version 2 of the License, or (at your *	option) any later version. * *	A lot of the I2O message side code from this is taken from the Red *	Creek RCPCI45 adapter driver by Red Creek Communications * *	Fixes/additions: *		Philipp Rumpf *		Juha Siev鋘en <Juha.Sievanen@cs.Helsinki.FI> *		Auvo H鋕kinen <Auvo.Hakkinen@cs.Helsinki.FI> *		Deepak Saxena <deepak@plexity.net> *		Boji T Kannanthanam <boji.t.kannanthanam@intel.com> *		Alan Cox <alan@redhat.com>: *			Ported to Linux 2.5. *		Markus Lidel <Markus.Lidel@shadowconnect.com>: *			Minor fixes for 2.6. *		Markus Lidel <Markus.Lidel@shadowconnect.com>: *			Support for sysfs included. */#include <linux/module.h>#include <linux/i2o.h>#include <linux/delay.h>#include <linux/workqueue.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/sched.h>   /* wait_event_interruptible_timeout() needs this */#include <asm/param.h>		/* HZ */#include "core.h"#define OSM_NAME "exec-osm"struct i2o_driver i2o_exec_driver;static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind);/* global wait list for POST WAIT */static LIST_HEAD(i2o_exec_wait_list);/* Wait struct needed for POST WAIT */struct i2o_exec_wait {	wait_queue_head_t *wq;	/* Pointer to Wait queue */	struct i2o_dma dma;	/* DMA buffers to free on failure */	u32 tcntxt;		/* transaction context from reply */	int complete;		/* 1 if reply received otherwise 0 */	u32 m;			/* message id */	struct i2o_message *msg;	/* pointer to the reply message */	struct list_head list;	/* node in global wait list */};/* Exec OSM class handling definition */static struct i2o_class_id i2o_exec_class_id[] = {	{I2O_CLASS_EXECUTIVE},	{I2O_CLASS_END}};/** *	i2o_exec_wait_alloc - Allocate a i2o_exec_wait struct an initialize it * *	Allocate the i2o_exec_wait struct and initialize the wait. * *	Returns i2o_exec_wait pointer on success or negative error code on *	failure. */static struct i2o_exec_wait *i2o_exec_wait_alloc(void){	struct i2o_exec_wait *wait;	wait = kmalloc(sizeof(*wait), GFP_KERNEL);	if (!wait)		return ERR_PTR(-ENOMEM);	memset(wait, 0, sizeof(*wait));	INIT_LIST_HEAD(&wait->list);	return wait;};/** *	i2o_exec_wait_free - Free a i2o_exec_wait struct *	@i2o_exec_wait: I2O wait data which should be cleaned up */static void i2o_exec_wait_free(struct i2o_exec_wait *wait){	kfree(wait);};/** * 	i2o_msg_post_wait_mem - Post and wait a message with DMA buffers *	@c: controller *	@m: message to post *	@timeout: time in seconds to wait *	@dma: i2o_dma struct of the DMA buffer to free on failure * * 	This API allows an OSM to post a message and then be told whether or *	not the system received a successful reply. If the message times out *	then the value '-ETIMEDOUT' is returned. This is a special case. In *	this situation the message may (should) complete at an indefinite time *	in the future. When it completes it will use the memory buffer *	attached to the request. If -ETIMEDOUT is returned then the memory *	buffer must not be freed. Instead the event completion will free them *	for you. In all other cases the buffer are your problem. * *	Returns 0 on success, negative error code on timeout or positive error *	code from reply. */int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long			  timeout, struct i2o_dma *dma){	DECLARE_WAIT_QUEUE_HEAD(wq);	struct i2o_exec_wait *wait;	static u32 tcntxt = 0x80000000;	struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);	int rc = 0;	wait = i2o_exec_wait_alloc();	if (!wait)		return -ENOMEM;	if (tcntxt == 0xffffffff)		tcntxt = 0x80000000;	if (dma)		wait->dma = *dma;	/*	 * Fill in the message initiator context and transaction context.	 * We will only use transaction contexts >= 0x80000000 for POST WAIT,	 * so we could find a POST WAIT reply easier in the reply handler.	 */	writel(i2o_exec_driver.context, &msg->u.s.icntxt);	wait->tcntxt = tcntxt++;	writel(wait->tcntxt, &msg->u.s.tcntxt);	/*	 * Post the message to the controller. At some point later it will	 * return. If we time out before it returns then complete will be zero.	 */	i2o_msg_post(c, m);	if (!wait->complete) {		wait->wq = &wq;		/*		 * we add elements add the head, because if a entry in the list		 * will never be removed, we have to iterate over it every time		 */		list_add(&wait->list, &i2o_exec_wait_list);		wait_event_interruptible_timeout(wq, wait->complete,						 timeout * HZ);		wait->wq = NULL;	}	barrier();	if (wait->complete) {		rc = le32_to_cpu(wait->msg->body[0]) >> 24;		i2o_flush_reply(c, wait->m);		i2o_exec_wait_free(wait);	} else {		/*		 * We cannot remove it now. This is important. When it does		 * terminate (which it must do if the controller has not		 * died...) then it will otherwise scribble on stuff.		 *		 * FIXME: try abort message		 */		if (dma)			dma->virt = NULL;		rc = -ETIMEDOUT;	}	return rc;};/** *	i2o_msg_post_wait_complete - Reply to a i2o_msg_post request from IOP *	@c: I2O controller which answers *	@m: message id *	@msg: pointer to the I2O reply message *	@context: transaction context of request * *	This function is called in interrupt context only. If the reply reached *	before the timeout, the i2o_exec_wait struct is filled with the message *	and the task will be waked up. The task is now responsible for returning *	the message m back to the controller! If the message reaches us after *	the timeout clean up the i2o_exec_wait struct (including allocated *	DMA buffer). * *	Return 0 on success and if the message m should not be given back to the *	I2O controller, or >0 on success and if the message should be given back *	afterwords. Returns negative error code on failure. In this case the *	message must also be given back to the controller. */static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,				      struct i2o_message *msg, u32 context){	struct i2o_exec_wait *wait, *tmp;	unsigned long flags;	static spinlock_t lock = SPIN_LOCK_UNLOCKED;	int rc = 1;	/*	 * We need to search through the i2o_exec_wait_list to see if the given	 * message is still outstanding. If not, it means that the IOP took	 * longer to respond to the message than we had allowed and timer has	 * already expired. Not much we can do about that except log it for	 * debug purposes, increase timeout, and recompile.	 */	spin_lock_irqsave(&lock, flags);	list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {		if (wait->tcntxt == context) {			list_del(&wait->list);			spin_unlock_irqrestore(&lock, flags);			wait->m = m;			wait->msg = msg;			wait->complete = 1;			barrier();			if (wait->wq) {				wake_up_interruptible(wait->wq);				rc = 0;			} else {				struct device *dev;				dev = &c->pdev->dev;				pr_debug("%s: timedout reply received!\n",					 c->name);				i2o_dma_free(dev, &wait->dma);				i2o_exec_wait_free(wait);				rc = -1;			}			return rc;		}	}	spin_unlock_irqrestore(&lock, flags);	osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,		 context);	return -1;};/** *	i2o_exec_show_vendor_id - Displays Vendor ID of controller *	@d: device of which the Vendor ID should be displayed *	@buf: buffer into which the Vendor ID should be printed * *	Returns number of bytes printed into buffer. */static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf){	struct i2o_device *dev = to_i2o_device(d);	u16 id;	if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {		sprintf(buf, "0x%04x", id);		return strlen(buf) + 1;	}	return 0;};/** *	i2o_exec_show_product_id - Displays Product ID of controller *	@d: device of which the Product ID should be displayed *	@buf: buffer into which the Product ID should be printed *

⌨️ 快捷键说明

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