Commit c8f7b073 authored by Mark Haverkamp's avatar Mark Haverkamp Committed by James Bottomley

[SCSI] aacraid: interruptible ioctl

Received from Mark Salyzyn

This patch allows the FSACTL_SEND_LARGE_FIB, FSACTL_SENDFIB and
FSACTL_SEND_RAW_SRB ioctl calls into the aacraid driver to be
interruptible. Only necessary if the adapter and/or the management
software has gone into some sort of misbehavior and the system is being
rebooted, thus permitting the user management software applications to
be killed relatively cleanly. The FIB queue resource is held out of the
free queue until the adapter finally, if ever, completes the command.
Signed-off-by: default avatarMark Haverkamp <markh@osdl.org>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 04846f25
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/delay.h> #include <linux/delay.h> /* ssleep prototype */
#include <linux/kthread.h> #include <linux/kthread.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -140,7 +140,8 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) ...@@ -140,7 +140,8 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
fibptr->hw_fib_pa = hw_fib_pa; fibptr->hw_fib_pa = hw_fib_pa;
fibptr->hw_fib = hw_fib; fibptr->hw_fib = hw_fib;
} }
aac_fib_free(fibptr); if (retval != -EINTR)
aac_fib_free(fibptr);
return retval; return retval;
} }
...@@ -621,7 +622,13 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -621,7 +622,13 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue if(actual_fibsize != fibsize){ // User made a mistake - should not continue
dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n")); dprintk((KERN_DEBUG"aacraid: Bad Size specified in "
"Raw SRB command calculated fibsize=%d "
"user_srbcmd->sg.count=%d aac_srb=%d sgentry=%d "
"issued fibsize=%d\n",
actual_fibsize, user_srbcmd->sg.count,
sizeof(struct aac_srb), sizeof(struct sgentry),
fibsize));
rcode = -EINVAL; rcode = -EINVAL;
goto cleanup; goto cleanup;
} }
...@@ -663,6 +670,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -663,6 +670,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
psg->count = cpu_to_le32(sg_indx+1); psg->count = cpu_to_le32(sg_indx+1);
status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
} }
if (status == -EINTR) {
rcode = -EINTR;
goto cleanup;
}
if (status != 0){ if (status != 0){
dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n")); dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"));
...@@ -696,8 +707,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) ...@@ -696,8 +707,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
for(i=0; i <= sg_indx; i++){ for(i=0; i <= sg_indx; i++){
kfree(sg_list[i]); kfree(sg_list[i]);
} }
aac_fib_complete(srbfib); if (rcode != -EINTR) {
aac_fib_free(srbfib); aac_fib_complete(srbfib);
aac_fib_free(srbfib);
}
return rcode; return rcode;
} }
......
...@@ -464,6 +464,8 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, ...@@ -464,6 +464,8 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr));
if (!dev->queues)
return -ENODEV;
q = &dev->queues->queue[AdapNormCmdQueue]; q = &dev->queues->queue[AdapNormCmdQueue];
if(wait) if(wait)
...@@ -527,8 +529,15 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, ...@@ -527,8 +529,15 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
} }
udelay(5); udelay(5);
} }
} else } else if (down_interruptible(&fibptr->event_wait)) {
down(&fibptr->event_wait); spin_lock_irqsave(&fibptr->event_lock, flags);
if (fibptr->done == 0) {
fibptr->done = 2; /* Tell interrupt we aborted */
spin_unlock_irqrestore(&fibptr->event_lock, flags);
return -EINTR;
}
spin_unlock_irqrestore(&fibptr->event_lock, flags);
}
BUG_ON(fibptr->done == 0); BUG_ON(fibptr->done == 0);
if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){
...@@ -795,7 +804,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) ...@@ -795,7 +804,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
/* Sniff for container changes */ /* Sniff for container changes */
if (!dev) if (!dev || !dev->fsa_dev)
return; return;
container = (u32)-1; container = (u32)-1;
......
...@@ -124,10 +124,15 @@ unsigned int aac_response_normal(struct aac_queue * q) ...@@ -124,10 +124,15 @@ unsigned int aac_response_normal(struct aac_queue * q)
} else { } else {
unsigned long flagv; unsigned long flagv;
spin_lock_irqsave(&fib->event_lock, flagv); spin_lock_irqsave(&fib->event_lock, flagv);
fib->done = 1; if (!fib->done)
fib->done = 1;
up(&fib->event_wait); up(&fib->event_wait);
spin_unlock_irqrestore(&fib->event_lock, flagv); spin_unlock_irqrestore(&fib->event_lock, flagv);
FIB_COUNTER_INCREMENT(aac_config.NormalRecved); FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
if (fib->done == 2) {
aac_fib_complete(fib);
aac_fib_free(fib);
}
} }
consumed++; consumed++;
spin_lock_irqsave(q->lock, flags); spin_lock_irqsave(q->lock, flags);
...@@ -316,7 +321,8 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) ...@@ -316,7 +321,8 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
unsigned long flagv; unsigned long flagv;
dprintk((KERN_INFO "event_wait up\n")); dprintk((KERN_INFO "event_wait up\n"));
spin_lock_irqsave(&fib->event_lock, flagv); spin_lock_irqsave(&fib->event_lock, flagv);
fib->done = 1; if (!fib->done)
fib->done = 1;
up(&fib->event_wait); up(&fib->event_wait);
spin_unlock_irqrestore(&fib->event_lock, flagv); spin_unlock_irqrestore(&fib->event_lock, flagv);
FIB_COUNTER_INCREMENT(aac_config.NormalRecved); FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment