2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-23 12:43:55 +08:00

[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: Mark Haverkamp <markh@osdl.org>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
Mark Haverkamp 2006-08-03 08:02:24 -07:00 committed by James Bottomley
parent 04846f2592
commit c8f7b073e0
3 changed files with 38 additions and 10 deletions
drivers/scsi/aacraid

View File

@ -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 @@ cleanup:
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)
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)
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 @@ cleanup:
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;
} }

View File

@ -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,
} }
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)
/* Sniff for container changes */ /* Sniff for container changes */
if (!dev) if (!dev || !dev->fsa_dev)
return; return;
container = (u32)-1; container = (u32)-1;

View File

@ -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)
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);