[SCSI] 3ware 8000 serialize reset code
The attached patch updates the 3ware 8000 driver: - Free irq handler in __tw_shutdown(). - Turn on RCD bit for caching mode page. - Serialize reset code. Signed-off-by: Adam Radford <linuxraid@amcc.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
6397256b0a
commit
4fe48187da
|
@ -6,7 +6,7 @@
|
||||||
Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
||||||
Brad Strand <linux@3ware.com>
|
Brad Strand <linux@3ware.com>
|
||||||
|
|
||||||
Copyright (C) 1999-2005 3ware Inc.
|
Copyright (C) 1999-2007 3ware Inc.
|
||||||
|
|
||||||
Kernel compatiblity By: Andre Hedrick <andre@suse.com>
|
Kernel compatiblity By: Andre Hedrick <andre@suse.com>
|
||||||
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
|
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
|
||||||
|
@ -191,6 +191,9 @@
|
||||||
before shutting down card.
|
before shutting down card.
|
||||||
Change to new 'change_queue_depth' api.
|
Change to new 'change_queue_depth' api.
|
||||||
Fix 'handled=1' ISR usage, remove bogus IRQ check.
|
Fix 'handled=1' ISR usage, remove bogus IRQ check.
|
||||||
|
1.26.02.002 - Free irq handler in __tw_shutdown().
|
||||||
|
Turn on RCD bit for caching mode page.
|
||||||
|
Serialize reset code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -214,7 +217,7 @@
|
||||||
#include "3w-xxxx.h"
|
#include "3w-xxxx.h"
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
#define TW_DRIVER_VERSION "1.26.02.001"
|
#define TW_DRIVER_VERSION "1.26.02.002"
|
||||||
static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
|
static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
|
||||||
static int tw_device_extension_count = 0;
|
static int tw_device_extension_count = 0;
|
||||||
static int twe_major = -1;
|
static int twe_major = -1;
|
||||||
|
@ -226,7 +229,7 @@ MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION(TW_DRIVER_VERSION);
|
MODULE_VERSION(TW_DRIVER_VERSION);
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset);
|
static int tw_reset_device_extension(TW_Device_Extension *tw_dev);
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
|
|
||||||
|
@ -984,24 +987,12 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
|
||||||
/* Now wait for the command to complete */
|
/* Now wait for the command to complete */
|
||||||
timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
|
timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
|
||||||
|
|
||||||
/* See if we reset while waiting for the ioctl to complete */
|
|
||||||
if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
|
|
||||||
clear_bit(TW_IN_RESET, &tw_dev->flags);
|
|
||||||
retval = -ERESTARTSYS;
|
|
||||||
goto out2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We timed out, and didn't get an interrupt */
|
/* We timed out, and didn't get an interrupt */
|
||||||
if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
|
if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
|
||||||
/* Now we need to reset the board */
|
/* Now we need to reset the board */
|
||||||
printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
|
printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
|
||||||
retval = -EIO;
|
retval = -EIO;
|
||||||
spin_lock_irqsave(tw_dev->host->host_lock, flags);
|
if (tw_reset_device_extension(tw_dev)) {
|
||||||
tw_dev->state[request_id] = TW_S_COMPLETED;
|
|
||||||
tw_state_request_finish(tw_dev, request_id);
|
|
||||||
tw_dev->posted_request_count--;
|
|
||||||
spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
|
|
||||||
if (tw_reset_device_extension(tw_dev, 1)) {
|
|
||||||
printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no);
|
printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no);
|
||||||
}
|
}
|
||||||
goto out2;
|
goto out2;
|
||||||
|
@ -1336,7 +1327,7 @@ static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
|
||||||
} /* End tw_unmap_scsi_data() */
|
} /* End tw_unmap_scsi_data() */
|
||||||
|
|
||||||
/* This function will reset a device extension */
|
/* This function will reset a device extension */
|
||||||
static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset)
|
static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct scsi_cmnd *srb;
|
struct scsi_cmnd *srb;
|
||||||
|
@ -1382,15 +1373,10 @@ static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_rese
|
||||||
printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);
|
printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
|
|
||||||
|
|
||||||
/* Wake up any ioctl that was pending before the reset */
|
TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
|
||||||
if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || (ioctl_reset)) {
|
clear_bit(TW_IN_RESET, &tw_dev->flags);
|
||||||
clear_bit(TW_IN_RESET, &tw_dev->flags);
|
tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
|
||||||
} else {
|
|
||||||
tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
|
|
||||||
wake_up(&tw_dev->ioctl_wqueue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} /* End tw_reset_device_extension() */
|
} /* End tw_reset_device_extension() */
|
||||||
|
@ -1437,14 +1423,18 @@ static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt)
|
||||||
"WARNING: Command (0x%x) timed out, resetting card.\n",
|
"WARNING: Command (0x%x) timed out, resetting card.\n",
|
||||||
SCpnt->cmnd[0]);
|
SCpnt->cmnd[0]);
|
||||||
|
|
||||||
|
/* Make sure we are not issuing an ioctl or resetting from ioctl */
|
||||||
|
mutex_lock(&tw_dev->ioctl_lock);
|
||||||
|
|
||||||
/* Now reset the card and some of the device extension data */
|
/* Now reset the card and some of the device extension data */
|
||||||
if (tw_reset_device_extension(tw_dev, 0)) {
|
if (tw_reset_device_extension(tw_dev)) {
|
||||||
printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
|
printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = SUCCESS;
|
retval = SUCCESS;
|
||||||
out:
|
out:
|
||||||
|
mutex_unlock(&tw_dev->ioctl_lock);
|
||||||
return retval;
|
return retval;
|
||||||
} /* End tw_scsi_eh_reset() */
|
} /* End tw_scsi_eh_reset() */
|
||||||
|
|
||||||
|
@ -1660,9 +1650,9 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques
|
||||||
request_buffer[4] = 0x8; /* caching page */
|
request_buffer[4] = 0x8; /* caching page */
|
||||||
request_buffer[5] = 0xa; /* page length */
|
request_buffer[5] = 0xa; /* page length */
|
||||||
if (*flags & 0x1)
|
if (*flags & 0x1)
|
||||||
request_buffer[6] = 0x4; /* WCE on */
|
request_buffer[6] = 0x5; /* WCE on, RCD on */
|
||||||
else
|
else
|
||||||
request_buffer[6] = 0x0; /* WCE off */
|
request_buffer[6] = 0x1; /* WCE off, RCD on */
|
||||||
tw_transfer_internal(tw_dev, request_id, request_buffer,
|
tw_transfer_internal(tw_dev, request_id, request_buffer,
|
||||||
sizeof(request_buffer));
|
sizeof(request_buffer));
|
||||||
|
|
||||||
|
@ -2012,6 +2002,10 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
|
||||||
int retval = 1;
|
int retval = 1;
|
||||||
TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
|
TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
|
||||||
|
|
||||||
|
/* If we are resetting due to timed out ioctl, report as busy */
|
||||||
|
if (test_bit(TW_IN_RESET, &tw_dev->flags))
|
||||||
|
return SCSI_MLQUEUE_HOST_BUSY;
|
||||||
|
|
||||||
/* Save done function into Scsi_Cmnd struct */
|
/* Save done function into Scsi_Cmnd struct */
|
||||||
SCpnt->scsi_done = done;
|
SCpnt->scsi_done = done;
|
||||||
|
|
||||||
|
@ -2100,6 +2094,10 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance)
|
||||||
|
|
||||||
handled = 1;
|
handled = 1;
|
||||||
|
|
||||||
|
/* If we are resetting, bail */
|
||||||
|
if (test_bit(TW_IN_RESET, &tw_dev->flags))
|
||||||
|
goto tw_interrupt_bail;
|
||||||
|
|
||||||
/* Check controller for errors */
|
/* Check controller for errors */
|
||||||
if (tw_check_bits(status_reg_value)) {
|
if (tw_check_bits(status_reg_value)) {
|
||||||
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
|
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
|
||||||
|
@ -2276,6 +2274,9 @@ static void __tw_shutdown(TW_Device_Extension *tw_dev)
|
||||||
/* Disable interrupts */
|
/* Disable interrupts */
|
||||||
TW_DISABLE_INTERRUPTS(tw_dev);
|
TW_DISABLE_INTERRUPTS(tw_dev);
|
||||||
|
|
||||||
|
/* Free up the IRQ */
|
||||||
|
free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
|
||||||
|
|
||||||
printk(KERN_WARNING "3w-xxxx: Shutting down host %d.\n", tw_dev->host->host_no);
|
printk(KERN_WARNING "3w-xxxx: Shutting down host %d.\n", tw_dev->host->host_no);
|
||||||
|
|
||||||
/* Tell the card we are shutting down */
|
/* Tell the card we are shutting down */
|
||||||
|
@ -2444,9 +2445,6 @@ static void tw_remove(struct pci_dev *pdev)
|
||||||
twe_major = -1;
|
twe_major = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free up the IRQ */
|
|
||||||
free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
|
|
||||||
|
|
||||||
/* Shutdown the card */
|
/* Shutdown the card */
|
||||||
__tw_shutdown(tw_dev);
|
__tw_shutdown(tw_dev);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
||||||
Brad Strand <linux@3ware.com>
|
Brad Strand <linux@3ware.com>
|
||||||
|
|
||||||
Copyright (C) 1999-2005 3ware Inc.
|
Copyright (C) 1999-2007 3ware Inc.
|
||||||
|
|
||||||
Kernel compatiblity By: Andre Hedrick <andre@suse.com>
|
Kernel compatiblity By: Andre Hedrick <andre@suse.com>
|
||||||
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
|
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
|
||||||
|
|
Loading…
Reference in New Issue