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:
parent
04846f2592
commit
c8f7b073e0
drivers/scsi/aacraid
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user