patch-2.4.5 linux/drivers/i2o/i2o_core.c
Next file: linux/drivers/i2o/i2o_lan.c
Previous file: linux/drivers/i2o/i2o_config.c
Back to the patch index
Back to the overall index
- Lines: 897
- Date:
Tue May 1 16:10:37 2001
- Orig file:
v2.4.4/linux/drivers/i2o/i2o_core.c
- Orig date:
Fri Feb 9 11:30:23 2001
diff -u --recursive --new-file v2.4.4/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
@@ -1,5 +1,5 @@
-/*
- * Core I2O structure managment
+/*
+ * Core I2O structure management
*
* (C) Copyright 1999 Red Hat Software
*
@@ -49,7 +49,7 @@
#include "i2o_lan.h"
-// #define DRIVERDEBUG
+//#define DRIVERDEBUG
#ifdef DRIVERDEBUG
#define dprintk(s, args...) printk(s, ## args)
@@ -147,10 +147,12 @@
*/
struct i2o_post_wait_data
{
- int status;
- u32 id;
- wait_queue_head_t *wq;
- struct i2o_post_wait_data *next;
+ int *status; /* Pointer to status block on caller stack */
+ int *complete; /* Pointer to completion flag on caller stack */
+ u32 id; /* Unique identifier */
+ wait_queue_head_t *wq; /* Wake up for caller (NULL for dead) */
+ struct i2o_post_wait_data *next; /* Chain */
+ void *mem[2]; /* Memory blocks to recover on failure path */
};
static struct i2o_post_wait_data *post_wait_queue = NULL;
static u32 post_wait_id = 0; // Unique ID for each post_wait
@@ -169,10 +171,10 @@
I2O_CLASS_EXECUTIVE
};
-
/*
- * Used when queing a reply to be handled later
+ * Used when queueing a reply to be handled later
*/
+
struct reply_info
{
struct i2o_controller *iop;
@@ -199,10 +201,12 @@
static spinlock_t i2o_evt_lock = SPIN_LOCK_UNLOCKED;
/*
- * Semaphore used to syncrhonize event handling thread with
+ * Semaphore used to synchronize event handling thread with
* interrupt handler.
*/
-DECLARE_MUTEX(evt_sem);
+
+static DECLARE_MUTEX(evt_sem);
+static DECLARE_MUTEX_LOCKED(evt_dead);
DECLARE_WAIT_QUEUE_HEAD(evt_wait);
static struct notifier_block i2o_reboot_notifier =
@@ -212,6 +216,12 @@
0
};
+/*
+ * Config options
+ */
+
+static int verbose = 0;
+MODULE_PARM(verbose, "i");
/*
* I2O Core reply handler
@@ -252,7 +262,7 @@
if(msg[2]&0x80000000) // Post wait message
{
if (msg[4] >> 24)
- status = -(msg[4] & 0xFFFF);
+ status = (msg[4] & 0xFFFF);
else
status = I2O_POST_WAIT_OK;
@@ -369,6 +379,9 @@
d->controller=c;
d->owner=NULL;
d->next=c->devices;
+ d->prev=NULL;
+ if (c->devices != NULL)
+ c->devices->prev=d;
c->devices=d;
*d->dev_name = 0;
@@ -696,7 +709,7 @@
{
down(&i2o_configuration_lock);
if (d->owner) {
- printk(KERN_INFO "Device claim called, but dev allready owned by %s!",
+ printk(KERN_INFO "Device claim called, but dev already owned by %s!",
h->name);
up(&i2o_configuration_lock);
return -EBUSY;
@@ -721,37 +734,59 @@
* Drop a claim by an OSM on a given I2O device. The handler is cleared
* and 0 is returned on success.
*
+ * AC - some devices seem to want to refuse an unclaim until they have
+ * finished internal processing. It makes sense since you don't want a
+ * new device to go reconfiguring the entire system until you are done.
+ * Thus we are prepared to wait briefly.
*/
int i2o_release_device(struct i2o_device *d, struct i2o_handler *h)
{
int err = 0;
+ int tries;
down(&i2o_configuration_lock);
if (d->owner != h) {
- printk(KERN_INFO "Claim release called, but not owned by %s!",
+ printk(KERN_INFO "Claim release called, but not owned by %s!\n",
h->name);
up(&i2o_configuration_lock);
return -ENOENT;
}
- d->owner = NULL;
-
- if(i2o_issue_claim(I2O_CMD_UTIL_RELEASE, d->controller, d->lct_data.tid,
- I2O_CLAIM_PRIMARY))
+ for(tries=0;tries<10;tries++)
{
- err = -ENXIO;
- d->owner = h;
- }
+ d->owner = NULL;
+ /*
+ * If the controller takes a nonblocking approach to
+ * releases we have to sleep/poll for a few times.
+ */
+
+ if((err=i2o_issue_claim(I2O_CMD_UTIL_RELEASE, d->controller, d->lct_data.tid, I2O_CLAIM_PRIMARY)) )
+ {
+ err = -ENXIO;
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ);
+ }
+ else
+ {
+ err=0;
+ break;
+ }
+ }
up(&i2o_configuration_lock);
return err;
}
-/*
- * Called by OSMs to let the core know that they want to be
- * notified if the given device is deleted from the system.
+/**
+ * i2o_device_notify_on - Enable deletion notifiers
+ * @d: device for notification
+ * @h: handler to install
+ *
+ * Called by OSMs to let the core know that they want to be
+ * notified if the given device is deleted from the system.
*/
+
int i2o_device_notify_on(struct i2o_device *d, struct i2o_handler *h)
{
int i;
@@ -773,7 +808,11 @@
return 0;
}
-/*
+/**
+ * i2o_device_notify_off - Remove deletion notifiers
+ * @d: device for notification
+ * @h: handler to remove
+ *
* Called by OSMs to let the core know that they no longer
* are interested in the fate of the given device.
*/
@@ -794,9 +833,18 @@
return -ENOENT;
}
-/*
- * Event registration API
+/**
+ * i2o_event_register - register interest in an event
+ * @c: Controller to register interest with
+ * @tid: I2O task id
+ * @init_context: initiator context to use with this notifier
+ * @tr_context: transaction context to use with this notifier
+ * @evt_mask: mask of events
+ *
+ * Create and posts an event registration message to the task. No reply
+ * is waited for, or expected. Errors in posting will be reported.
*/
+
int i2o_event_register(struct i2o_controller *c, u32 tid,
u32 init_context, u32 tr_context, u32 evt_mask)
{
@@ -814,11 +862,13 @@
}
/*
- * Event ack API
+ * i2o_event_ack - acknowledge an event
+ * @c: controller
+ * @msg: pointer to the UTIL_EVENT_REGISTER reply we received
*
- * We just take a pointer to the original UTIL_EVENT_REGISTER reply
- * message and change the function code since that's what spec
- * describes an EventAck message looking like.
+ * We just take a pointer to the original UTIL_EVENT_REGISTER reply
+ * message and change the function code since that's what spec
+ * describes an EventAck message looking like.
*/
int i2o_event_ack(struct i2o_controller *c, u32 *msg)
@@ -850,12 +900,12 @@
while(1)
{
- down_interruptible(&evt_sem);
- if(signal_pending(current))
+ if(down_interruptible(&evt_sem))
{
dprintk(KERN_INFO "I2O event thread dead\n");
+ printk("exiting...");
evt_running = 0;
- return 0;
+ up_and_exit(&evt_dead, 0);
}
/*
@@ -922,6 +972,10 @@
kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
int i;
+ if (d == NULL) {
+ printk(KERN_EMERG "i2oevtd: out of memory\n");
+ break;
+ }
memcpy(&d->lct_data, &msg[5], sizeof(i2o_lct_entry));
d->next = NULL;
@@ -974,7 +1028,11 @@
printk(KERN_WARNING "%s: Warning notification received!"
"Check configuration for errors!\n", c->name);
break;
-
+
+ case I2O_EVT_IND_EVT_MASK_MODIFIED:
+ /* Well I guess that was us hey .. */
+ break;
+
default:
printk(KERN_WARNING "%s: No handler for event (0x%08x)\n", c->name, msg[4]);
break;
@@ -1124,12 +1182,6 @@
m=(struct i2o_message *)bus_to_virt(mv);
msg=(u32*)m;
- /*
- * Temporary Debugging
- */
- if(m->function==0x15)
- printk(KERN_ERR "%s: UTFR!\n", c->name);
-
i=i2o_handlers[m->initiator_context&(MAX_I2O_MODULES-1)];
if(i && i->reply)
i->reply(i,c,m);
@@ -1219,9 +1271,9 @@
/**
- * i2o_wait_message
+ * i2o_wait_message - obtain an i2o message from the IOP
* @c: controller
- * @why: explanation
+ * @why: explanation
*
* This function waits up to 5 seconds for a message slot to be
* available. If no message is available it prints an error message
@@ -1266,9 +1318,11 @@
char str[22];
int ret;
int unit = d->lct_data.tid;
-
- printk(KERN_INFO "Target ID %d.\n", unit);
+ if(verbose==0)
+ return;
+
+ printk(KERN_INFO "Target ID %d.\n", unit);
if((ret=i2o_query_scalar(c, unit, 0xF100, 3, buf, 16))>=0)
{
buf[16]=0;
@@ -1279,13 +1333,11 @@
buf[16]=0;
printk(KERN_INFO " Device: %s\n", buf);
}
-#if 0
if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16)>=0)
{
buf[16]=0;
printk(KERN_INFO " Description: %s\n", buf);
}
-#endif
if((ret=i2o_query_scalar(c, unit, 0xF100, 6, buf, 8))>=0)
{
buf[8]=0;
@@ -1581,7 +1633,7 @@
/**
- * i2o_reset_controller
+ * i2o_reset_controller - reset an IOP
* @c: controller to reset
*
* Reset the IOP into INIT state and wait until IOP gets into RESET state.
@@ -1601,7 +1653,10 @@
/* Quiesce all IOPs first */
for (iop = i2o_controller_chain; iop; iop = iop->next)
- i2o_quiesce_controller(iop);
+ {
+ if(iop->type != I2O_TYPE_PCI || !iop->bus.pci.dpt)
+ i2o_quiesce_controller(iop);
+ }
m=i2o_wait_message(c, "AdapterReset");
if(m==0xFFFFFFFF)
@@ -1628,19 +1683,19 @@
/* Wait for a reply */
time=jiffies;
- while(status[0]==0)
+ while(*status==0)
{
if((jiffies-time)>=20*HZ)
{
printk(KERN_ERR "IOP reset timeout.\n");
- kfree(status);
+ // Better to leak this for safety: kfree(status);
return -ETIMEDOUT;
}
schedule();
barrier();
}
- if (status[0]==I2O_CMD_IN_PROGRESS)
+ if (*status==I2O_CMD_IN_PROGRESS)
{
/*
* Once the reset is sent, the IOP goes into the INIT state
@@ -1799,7 +1854,7 @@
u32 msg[6];
int ret, size = sizeof(i2o_hrt);
- /* Read first just the header to figure out the real size */
+ /* First read just the header to figure out the real size */
do {
if (c->hrt == NULL) {
@@ -1816,7 +1871,18 @@
msg[4]= (0xD0000000 | size); /* Simple transaction */
msg[5]= virt_to_bus(c->hrt); /* Dump it here */
- if ((ret = i2o_post_wait(c, msg, sizeof(msg), 20))) {
+ ret = i2o_post_wait_mem(c, msg, sizeof(msg), 20, c->hrt, NULL);
+
+ if(ret == -ETIMEDOUT)
+ {
+ /* The HRT block we used is in limbo somewhere. When the iop wakes up
+ we will recover it */
+ c->hrt = NULL;
+ return ret;
+ }
+
+ if(ret<0)
+ {
printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n",
c->name, -ret);
return ret;
@@ -1845,14 +1911,15 @@
static int i2o_systab_send(struct i2o_controller *iop)
{
u32 msg[12];
- u32 privmem[2];
- u32 privio[2];
int ret;
+ u32 *privbuf = kmalloc(16, GFP_KERNEL);
+ if(privbuf == NULL)
+ return -ENOMEM;
- privmem[0] = iop->status_block->current_mem_base;
- privmem[1] = iop->status_block->current_mem_size;
- privio[0] = iop->status_block->current_io_base;
- privio[1] = iop->status_block->current_io_size;
+ privbuf[0] = iop->status_block->current_mem_base;
+ privbuf[1] = iop->status_block->current_mem_size;
+ privbuf[2] = iop->status_block->current_io_base;
+ privbuf[3] = iop->status_block->current_io_size;
msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
@@ -1864,20 +1931,33 @@
* Provide three SGL-elements:
* System table (SysTab), Private memory space declaration and
* Private i/o space declaration
+ *
+ * FIXME: provide these for controllers needing them
*/
msg[6] = 0x54000000 | sys_tbl_len;
msg[7] = virt_to_bus(sys_tbl);
msg[8] = 0x54000000 | 0;
- msg[9] = virt_to_bus(privmem);
+ msg[9] = virt_to_bus(privbuf);
msg[10] = 0xD4000000 | 0;
- msg[11] = virt_to_bus(privio);
+ msg[11] = virt_to_bus(privbuf+8);
- if ((ret=i2o_post_wait(iop, msg, sizeof(msg), 120)))
- printk(KERN_INFO "%s: Unable to set SysTab (status=%#x).\n",
+ ret=i2o_post_wait_mem(iop, msg, sizeof(msg), 120, privbuf, NULL);
+
+ if(ret==-ETIMEDOUT)
+ {
+ printk(KERN_ERR "%s: SysTab setup timed out.\n", iop->name);
+ }
+ else if(ret<0)
+ {
+ printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n",
iop->name, -ret);
+ kfree(privbuf);
+ }
else
+ {
dprintk(KERN_INFO "%s: SysTab set.\n", iop->name);
-
+ kfree(privbuf);
+ }
i2o_status_get(iop); // Entered READY state
return ret;
@@ -2162,7 +2242,16 @@
msg[6] = 0xD0000000|size;
msg[7] = virt_to_bus(c->lct);
- if ((ret=i2o_post_wait(c, msg, sizeof(msg), 120))) {
+ ret=i2o_post_wait_mem(c, msg, sizeof(msg), 120, c->lct, NULL);
+
+ if(ret == -ETIMEDOUT)
+ {
+ c->lct = NULL;
+ return ret;
+ }
+
+ if(ret<0)
+ {
printk(KERN_ERR "%s: LCT Get failed (status=%#x.\n",
c->name, -ret);
return ret;
@@ -2206,8 +2295,11 @@
/*
* Bring a controller online into OPERATIONAL state.
*/
+
int i2o_online_controller(struct i2o_controller *iop)
{
+ u32 v;
+
if (i2o_systab_send(iop) < 0)
return -1;
@@ -2223,6 +2315,15 @@
if (i2o_lct_get(iop) < 0)
return -1;
+ /* Check battery status */
+
+ iop->battery = 0;
+ if(i2o_query_scalar(iop, ADAPTER_TID, 0x0000, 4, &v, 4)>=0)
+ {
+ if(v&16)
+ iop->battery = 1;
+ }
+
return 0;
}
@@ -2346,83 +2447,134 @@
return 0;
}
-/*
- * This core API allows an OSM to post a message and then be told whether
- * or not the system received a successful reply. It is useful when
- * the OSM does not want to know the exact 3
+/**
+ * i2o_post_wait_mem - I2O query/reply with DMA buffers
+ * @c: controller
+ * @msg: message to send
+ * @len: length of message
+ * @timeout: time in seconds to wait
+ * @mem1: attached memory buffer 1
+ * @mem2: attached memory buffer 2
+ *
+ * This core 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 buffers attached to the request. If -ETIMEDOUT is returned then
+ * the memory buffers must not be freed. Instead the event completion will
+ * free them for you. In all other cases the buffers are your problem.
+ *
+ * Pass NULL for unneeded buffers.
*/
-int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
+
+int i2o_post_wait_mem(struct i2o_controller *c, u32 *msg, int len, int timeout, void *mem1, void *mem2)
{
DECLARE_WAIT_QUEUE_HEAD(wq_i2o_post);
- int status = 0;
+ int complete = 0;
+ int status;
int flags = 0;
- struct i2o_post_wait_data *p1, *p2;
struct i2o_post_wait_data *wait_data =
kmalloc(sizeof(struct i2o_post_wait_data), GFP_KERNEL);
if(!wait_data)
return -ENOMEM;
+ /*
+ * Create a new notification object
+ */
+ wait_data->status = &status;
+ wait_data->complete = &complete;
+ wait_data->mem[0] = mem1;
+ wait_data->mem[1] = mem2;
/*
- * The spin locking is needed to keep anyone from playing
- * with the queue pointers and id while we do the same
+ * Queue the event with its unique id
*/
spin_lock_irqsave(&post_wait_lock, flags);
+
wait_data->next = post_wait_queue;
post_wait_queue = wait_data;
wait_data->id = (++post_wait_id) & 0x7fff;
- spin_unlock_irqrestore(&post_wait_lock, flags);
-
wait_data->wq = &wq_i2o_post;
- wait_data->status = -ETIMEDOUT;
+ spin_unlock_irqrestore(&post_wait_lock, flags);
+
+ /*
+ * Fill in the message id
+ */
+
msg[2] = 0x80000000|(u32)core_context|((u32)wait_data->id<<16);
+ /*
+ * 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. From the point post_this returns
+ * the wait_data may have been deleted.
+ */
if ((status = i2o_post_this(c, msg, len))==0) {
- interruptible_sleep_on_timeout(&wq_i2o_post, HZ * timeout);
- status = wait_data->status;
+ sleep_on_timeout(&wq_i2o_post, HZ * timeout);
}
-
-#ifdef DRIVERDEBUG
- if(status == -ETIMEDOUT)
- printk(KERN_INFO "%s: POST WAIT TIMEOUT\n",c->name);
-#endif
-
- /*
- * Remove the entry from the queue.
- * Since i2o_post_wait() may have been called again by
- * a different thread while we were waiting for this
- * instance to complete, we're not guaranteed that
- * this entry is at the head of the queue anymore, so
- * we need to search for it, find it, and delete it.
- */
- p2 = NULL;
+ else
+ return -EIO;
+
+ if(signal_pending(current))
+ status = -EINTR;
+
spin_lock_irqsave(&post_wait_lock, flags);
- for(p1 = post_wait_queue; p1; p2 = p1, p1 = p1->next) {
- if(p1 == wait_data) {
- if(p2)
- p2->next = p1->next;
- else
- post_wait_queue = p1->next;
-
- break;
+ barrier(); /* Be sure we see complete as it is locked */
+ if(!complete)
+ {
+ /*
+ * Mark the entry dead. We cannot remove it. This is important.
+ * When it does terminate (which it must do if the controller hasnt
+ * died..) then it will otherwise scribble on stuff.
+ * !complete lets us safely check if the entry is still
+ * allocated and thus we can write into it
+ */
+ wait_data->wq = NULL;
+ status = -ETIMEDOUT;
+ }
+ else
+ {
+ /* Debugging check - remove me soon */
+ if(status == -ETIMEDOUT)
+ {
+ printk("TIMEDOUT BUG!\n");
+ status = -EIO;
}
}
+ /* And the wait_data is not leaked either! */
spin_unlock_irqrestore(&post_wait_lock, flags);
-
- kfree(wait_data);
-
return status;
}
+/**
+ * i2o_post_wait - I2O query/reply
+ * @c: controller
+ * @msg: message to send
+ * @len: length of message
+ * @timeout: time in seconds to wait
+ *
+ * This core API allows an OSM to post a message and then be told whether
+ * or not the system received a successful reply.
+ */
+
+int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
+{
+ return i2o_post_wait_mem(c, msg, len, timeout, NULL, NULL);
+}
+
/*
* i2o_post_wait is completed and we want to wake up the
* sleeping proccess. Called by core's reply handler.
*/
+
static void i2o_post_wait_complete(u32 context, int status)
{
- struct i2o_post_wait_data *p1 = NULL;
-
+ struct i2o_post_wait_data **p1, *q;
+ unsigned long flags;
+
/*
* We need to search through the post_wait
* queue to see if the given message is still
@@ -2435,18 +2587,49 @@
* Lock needed to keep anyone from moving queue pointers
* around while we're looking through them.
*/
- spin_lock(&post_wait_lock);
- for(p1 = post_wait_queue; p1; p1 = p1->next) {
- if(p1->id == ((context >> 16) & 0x7fff)) {
- p1->status = status;
- wake_up_interruptible(p1->wq);
+
+ spin_lock_irqsave(&post_wait_lock, flags);
+
+ for(p1 = &post_wait_queue; *p1!=NULL; p1 = &((*p1)->next))
+ {
+ q = (*p1);
+ if(q->id == ((context >> 16) & 0x7fff)) {
+ /*
+ * Delete it
+ */
+
+ *p1 = q->next;
+
+ /*
+ * Live or dead ?
+ */
+
+ if(q->wq)
+ {
+ /* Live entry - wakeup and set status */
+ *q->status = status;
+ *q->complete = 1;
+ wake_up(q->wq);
+ }
+ else
+ {
+ /*
+ * Free resources. Caller is dead
+ */
+ if(q->mem[0])
+ kfree(q->mem[0]);
+ if(q->mem[1])
+ kfree(q->mem[1]);
+ printk(KERN_WARNING "i2o_post_wait event completed after timeout.\n");
+ }
+ kfree(q);
spin_unlock(&post_wait_lock);
return;
}
}
spin_unlock(&post_wait_lock);
- printk(KERN_DEBUG "i2o_post_wait reply after timeout!\n");
+ printk(KERN_DEBUG "i2o_post_wait: Bogus reply!\n");
}
/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
@@ -2461,25 +2644,52 @@
void *oplist, int oplen, void *reslist, int reslen)
{
u32 msg[9];
- u8 *res = (u8 *)reslist;
u32 *res32 = (u32*)reslist;
u32 *restmp = (u32*)reslist;
int len = 0;
int i = 0;
int wait_status;
-
+ u32 *opmem, *resmem;
+
+ /* Get DMAable memory */
+ opmem = kmalloc(oplen, GFP_KERNEL);
+ if(opmem == NULL)
+ return -ENOMEM;
+ memcpy(opmem, oplist, oplen);
+
+ resmem = kmalloc(reslen, GFP_KERNEL);
+ if(resmem == NULL)
+ {
+ kfree(opmem);
+ return -ENOMEM;
+ }
+
msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
msg[1] = cmd << 24 | HOST_TID << 12 | tid;
msg[3] = 0;
msg[4] = 0;
msg[5] = 0x54000000 | oplen; /* OperationList */
- msg[6] = virt_to_bus(oplist);
+ msg[6] = virt_to_bus(opmem);
msg[7] = 0xD0000000 | reslen; /* ResultList */
- msg[8] = virt_to_bus(reslist);
+ msg[8] = virt_to_bus(resmem);
- if((wait_status = i2o_post_wait(iop, msg, sizeof(msg), 10)))
- return wait_status; /* -DetailedStatus */
+ wait_status = i2o_post_wait_mem(iop, msg, sizeof(msg), 10, opmem, resmem);
+
+ /*
+ * This only looks like a memory leak - don't "fix" it.
+ */
+ if(wait_status == -ETIMEDOUT)
+ return wait_status;
+ /* Query failed */
+ if(wait_status != 0)
+ {
+ kfree(resmem);
+ kfree(opmem);
+ return wait_status;
+ }
+
+ memcpy(reslist, resmem, reslen);
/*
* Calculate number of bytes of Result LIST
* We need to loop through each Result BLOCK and grab the length
@@ -2500,13 +2710,13 @@
* If this is the only request,than we return an error
*/
if((res32[0]&0x0000FFFF) == 1)
- return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
+ {
+ return -((res32[1] >> 16) & 0xFF); /* -BlockStatus */
+ }
}
-
len += restmp[0] & 0x0000FFFF; /* Length of res BLOCK */
restmp += restmp[0] & 0x0000FFFF; /* Skip to next BLOCK */
}
-
return (len << 2); /* bytes used by result list */
}
@@ -2526,10 +2736,10 @@
size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid,
opblk, sizeof(opblk), resblk, sizeof(resblk));
- if (size < 0)
- return size;
-
memcpy(buf, resblk+8, buflen); /* cut off header */
+
+ if(size>buflen)
+ return buflen;
return size;
}
@@ -2570,6 +2780,8 @@
opblk, 12+buflen, resblk, sizeof(resblk));
kfree(opblk);
+ if(size>buflen)
+ return buflen;
return size;
}
@@ -2614,6 +2826,8 @@
opblk, 10+ibuflen, resblk, reslen);
kfree(opblk);
+ if(size>reslen)
+ return reslen;
return size;
}
@@ -2662,6 +2876,8 @@
opblk, 10+buflen, resblk, sizeof(resblk));
kfree(opblk);
+ if(size>buflen)
+ return buflen;
return size;
}
@@ -3113,8 +3329,6 @@
}
-#ifdef MODULE
-
EXPORT_SYMBOL(i2o_controller_chain);
EXPORT_SYMBOL(i2o_num_controllers);
EXPORT_SYMBOL(i2o_find_controller);
@@ -3131,6 +3345,7 @@
EXPORT_SYMBOL(i2o_post_this);
EXPORT_SYMBOL(i2o_post_wait);
+EXPORT_SYMBOL(i2o_post_wait_mem);
EXPORT_SYMBOL(i2o_query_scalar);
EXPORT_SYMBOL(i2o_set_scalar);
@@ -3147,6 +3362,8 @@
EXPORT_SYMBOL(i2o_get_class_name);
+#ifdef MODULE
+
MODULE_AUTHOR("Red Hat Software");
MODULE_DESCRIPTION("I2O Core");
@@ -3206,17 +3423,13 @@
* If this is shutdown time, the thread has already been killed
*/
if(evt_running) {
+ printk("Terminating i2o threads...");
stat = kill_proc(evt_pid, SIGTERM, 1);
if(!stat) {
- int count = 10 * 100;
- while(evt_running && count--) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- }
-
- if(!count)
- printk(KERN_ERR "i2o: Event thread still running!\n");
+ printk("waiting...");
+ down(&evt_dead);
}
+ printk("done.\n");
}
#ifdef CONFIG_I2O_PCI_MODULE
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)