summaryrefslogtreecommitdiff
path: root/drivers/message/fusion
diff options
context:
space:
mode:
authorJames Bottomley <jejb@mulgrave.(none)>2004-01-25 23:56:31 -0600
committerJames Bottomley <jejb@mulgrave.(none)>2004-01-25 23:56:31 -0600
commit4195d656cf74dd2ef1a5dbec8a77cbb877e39638 (patch)
tree3dd13938ebd6606d955b8555c1384ccab79736ec /drivers/message/fusion
parent0450c68d1bcb8a3d73e56010ce8a4266057ecc6b (diff)
Fusion update to 3.00.02
From: Moore, Eric Dean <Emoore@lsil.com> Here is list of fix's. * added new PCI API support * added ACPI support * added CONFIG_LBA, READ16, WRITE16 support * underun fix * chain buffer free list not being init properly * reduce task management (abort=2sec,reset bus=5sec, timeout=10sec) * Hot plug fix's requested from Christoph Hellwig, and several others from the linux-scsi@ list.
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r--drivers/message/fusion/mptbase.c417
-rw-r--r--drivers/message/fusion/mptbase.h19
-rw-r--r--drivers/message/fusion/mptscsih.c956
-rw-r--r--drivers/message/fusion/mptscsih.h24
4 files changed, 878 insertions, 538 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index e17b29d19568..bbe05a8ea605 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -167,6 +167,7 @@ static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
/* Reset handler lookup table */
static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
+static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
static int FusionInitCalled = 0;
static int mpt_base_index = -1;
@@ -183,7 +184,6 @@ static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
-static int mpt_adapter_install(struct pci_dev *pdev);
static void mpt_detect_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
static void mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup);
static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
@@ -232,8 +232,12 @@ static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *
static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
-int fusion_init(void);
-static void fusion_exit(void);
+/* module entry point */
+static int __devinit mptbase_probe (struct pci_dev *, const struct pci_device_id *);
+static void __devexit mptbase_remove(struct pci_dev *);
+static void mptbase_shutdown(struct device * );
+static int __init fusion_init (void);
+static void __exit fusion_exit (void);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -260,6 +264,30 @@ struct _mpt_ioc_proc_list {
#endif
+/****************************************************************************
+ * Supported hardware
+ */
+
+static struct pci_device_id mptbase_pci_table[] = {
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
+ PCI_ANY_ID, PCI_ANY_ID },
+ {0} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
+
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* 20000207 -sralston
* GRRRRR... IOSpace (port i/o) register access (for the 909) is back!
@@ -518,7 +546,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
* @mf: Pointer to original MPT request frame
* @reply: Pointer to MPT reply frame (NULL if TurboReply)
*
- * Returns 1 indicating original alloc'd request frame ptr
+ * Returns 1 indicating original alloc'd request frame ptr
* should be freed, or 0 if it shouldn't.
*/
static int
@@ -805,6 +833,34 @@ mpt_reset_deregister(int cb_idx)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
+ * mpt_device_driver_register - Register device driver hooks
+ */
+int
+mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
+{
+ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+ return -1;
+
+ MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
+ return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mpt_device_driver_deregister - DeRegister device driver hooks
+ */
+void
+mpt_device_driver_deregister(int cb_idx)
+{
+ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+ return;
+
+ MptDeviceDriverHandlers[cb_idx] = NULL;
+}
+
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
* mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
* allocated per MPT adapter.
* @handle: Handle of registered MPT protocol driver
@@ -1142,88 +1198,6 @@ mpt_adapter_find_next(MPT_ADAPTER *prev)
return next;
}
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * mpt_pci_scan - Scan PCI devices for MPT adapters.
- *
- * Returns count of MPT adapters found, keying off of PCI vendor and
- * device_id's.
- */
-static int __init
-mpt_pci_scan(void)
-{
- struct pci_dev *pdev = NULL;
- struct pci_dev *pdev2;
- int found = 0;
- int count = 0;
- int r;
-
- dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n"));
-
- /*
- * NOTE: The 929, 929X, 1030 and 1035 will appear as 2 separate PCI devices,
- * one for each channel.
- */
- while ((pdev = pci_find_device(PCI_VENDOR_ID_LSI_LOGIC, PCI_ANY_ID, pdev)) != NULL) {
- pdev2 = NULL;
- if ((pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC909) &&
- (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929) &&
- (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919) &&
- (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929X) &&
- (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919X) &&
- (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) &&
- (pdev->device != MPI_MANUFACTPAGE_DEVID_1030_53C1035) &&
- 1) {
- dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device));
- continue;
- }
-
- /* GRRRRR
- * dual function devices (929, 929X, 1030, 1035) may be presented in Func 1,0 order,
- * but we'd really really rather have them in Func 0,1 order.
- * Do some kind of look ahead here...
- */
- if (pdev->devfn & 1) {
- pdev2 = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev);
- if (pdev2 && (pdev2->vendor == 0x1000) &&
- (PCI_SLOT(pdev2->devfn) == PCI_SLOT(pdev->devfn)) &&
- (pdev2->device == pdev->device) &&
- (pdev2->bus->number == pdev->bus->number) &&
- !(pdev2->devfn & 1)) {
- dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",
- pdev2->bus->number, pdev2->devfn, pdev2->class, pdev2->device));
- found++;
- if ((r = mpt_adapter_install(pdev2)) == 0)
- count++;
- } else {
- pdev2 = NULL;
- }
- }
-
- dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",
- pdev->bus->number, pdev->devfn, pdev->class, pdev->device));
- found++;
- if ((r = mpt_adapter_install(pdev)) == 0)
- count++;
-
- if (pdev2)
- pdev = pdev2;
- }
-
- printk(KERN_INFO MYNAM ": %d MPT adapter%s found, %d installed.\n",
- found, (found==1) ? "" : "s", count);
-
- if (!found || !count) {
- fusion_exit();
- return -ENODEV;
- }
-
-#ifdef CONFIG_PROC_FS
- (void) procmpt_create();
-#endif
-
- return count;
-}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
@@ -1253,7 +1227,7 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mpt_adapter_install - Install a PCI intelligent MPT adapter.
+ * mptbase_probe - Install a PCI intelligent MPT adapter.
* @pdev: Pointer to pci_dev structure
*
* This routine performs all the steps necessary to bring the IOC of
@@ -1268,8 +1242,8 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
*
* TODO: Add support for polled controllers
*/
-static int __init
-mpt_adapter_install(struct pci_dev *pdev)
+static int __devinit
+mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
MPT_ADAPTER *ioc;
u8 *mem;
@@ -1292,6 +1266,13 @@ mpt_adapter_install(struct pci_dev *pdev)
return r;
}
+ if (!pci_set_consistent_dma_mask(pdev, mask))
+ dprintk((KERN_INFO MYNAM
+ ": Using 64 bit consistent mask\n"));
+ else
+ dprintk((KERN_INFO MYNAM
+ ": Not using 64 bit consistent mask\n"));
+
ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
if (ioc == NULL) {
printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
@@ -1500,6 +1481,7 @@ mpt_adapter_install(struct pci_dev *pdev)
ioc->pci_irq = pdev->irq;
pci_set_master(pdev); /* ?? */
+ pci_set_drvdata(pdev, ioc);
#ifndef __sparc__
dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
@@ -1520,11 +1502,209 @@ mpt_adapter_install(struct pci_dev *pdev)
ioc->name, r);
}
- return r;
+ if(r != 0 )
+ return r;
+
+
+ /* call per device driver probe entry point */
+ for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
+ if(MptDeviceDriverHandlers[ii] &&
+ MptDeviceDriverHandlers[ii]->probe) {
+ MptDeviceDriverHandlers[ii]->probe(pdev,id);
+ }
+ }
+
+ return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
+ * mptbase_remove - Remove a PCI intelligent MPT adapter.
+ * @pdev: Pointer to pci_dev structure
+ *
+ */
+
+static void __devexit
+mptbase_remove(struct pci_dev *pdev)
+{
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ int ii;
+
+ /* call per device driver remove entry point */
+ for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
+ if(MptDeviceDriverHandlers[ii] &&
+ MptDeviceDriverHandlers[ii]->remove) {
+ MptDeviceDriverHandlers[ii]->remove(pdev);
+ }
+ }
+
+ /* Disable interrupts! */
+ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+
+ ioc->active = 0;
+
+ /* Clear any lingering interrupt */
+ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
+ CHIPREG_READ32(&ioc->chip->IntStatus);
+
+ Q_DEL_ITEM(ioc);
+ mpt_adapter_dispose(ioc);
+
+ mptscsih_sync_irq(ioc->irq);
+ pci_set_drvdata(pdev, NULL);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptbase_shutdown -
+ *
+ */
+static void
+mptbase_shutdown(struct device * dev)
+{
+ int ii;
+
+ /* call per device driver shutdown entry point */
+ for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
+ if(MptDeviceDriverHandlers[ii] &&
+ MptDeviceDriverHandlers[ii]->shutdown) {
+ MptDeviceDriverHandlers[ii]->shutdown(dev);
+ }
+ }
+
+}
+
+
+/**************************************************************************
+ * Power Management
+ */
+#ifdef CONFIG_PM
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptbase_suspend - Fusion MPT base driver suspend routine.
+ *
+ *
+ */
+static int
+mptbase_suspend(struct pci_dev *pdev, u32 state)
+{
+ u32 device_state;
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ int ii;
+
+ switch(state)
+ {
+ case 1: /* S1 */
+ device_state=1; /* D1 */;
+ break;
+ case 3: /* S3 */
+ case 4: /* S4 */
+ device_state=3; /* D3 */;
+ break;
+ default:
+ return -EAGAIN /*FIXME*/;
+ break;
+ }
+
+ printk(MYIOC_s_INFO_FMT
+ "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
+ ioc->name, pdev, pci_name(pdev), device_state);
+
+ /* call per device driver suspend entry point */
+ for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
+ if(MptDeviceDriverHandlers[ii] &&
+ MptDeviceDriverHandlers[ii]->suspend) {
+ MptDeviceDriverHandlers[ii]->suspend(pdev, state);
+ }
+ }
+
+ pci_save_state(pdev, ioc->PciState);
+
+ /* put ioc into READY_STATE */
+ if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
+ printk(MYIOC_s_ERR_FMT
+ "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
+ }
+
+ /* disable interrupts */
+ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+ ioc->active = 0;
+
+ /* Clear any lingering interrupt */
+ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, device_state);
+
+ return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptbase_resume - Fusion MPT base driver resume routine.
+ *
+ *
+ */
+static int
+mptbase_resume(struct pci_dev *pdev)
+{
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ u32 device_state = pdev->current_state;
+ int recovery_state;
+ int ii;
+
+ printk(MYIOC_s_INFO_FMT
+ "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
+ ioc->name, pdev, pci_name(pdev), device_state);
+
+ pci_set_power_state(pdev, 0);
+ pci_restore_state(pdev, ioc->PciState);
+ pci_enable_device(pdev);
+
+ /* enable interrupts */
+ CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ ioc->active = 1;
+
+ /* F/W not running */
+ if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
+ /* enable domain validation flags */
+ for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+ ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
+ }
+ }
+
+ printk(MYIOC_s_INFO_FMT
+ "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
+ ioc->name,
+ (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
+ CHIPREG_READ32(&ioc->chip->Doorbell));
+
+ /* bring ioc to operational state */
+ if ((recovery_state = mpt_do_ioc_recovery(ioc,
+ MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
+ printk(MYIOC_s_INFO_FMT
+ "pci-resume: Cannot recover, error:[%x]\n",
+ ioc->name, recovery_state);
+ } else {
+ printk(MYIOC_s_INFO_FMT
+ "pci-resume: success\n", ioc->name);
+ }
+
+ /* call per device driver resume entry point */
+ for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
+ if(MptDeviceDriverHandlers[ii] &&
+ MptDeviceDriverHandlers[ii]->resume) {
+ MptDeviceDriverHandlers[ii]->resume(pdev);
+ }
+ }
+
+ return 0;
+}
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
* mpt_do_ioc_recovery - Initialize or recover MPT adapter.
* @ioc: Pointer to MPT adapter structure
* @reason: Event word / reason
@@ -5851,6 +6031,8 @@ EXPORT_SYMBOL(mpt_event_register);
EXPORT_SYMBOL(mpt_event_deregister);
EXPORT_SYMBOL(mpt_reset_register);
EXPORT_SYMBOL(mpt_reset_deregister);
+EXPORT_SYMBOL(mpt_device_driver_register);
+EXPORT_SYMBOL(mpt_device_driver_deregister);
EXPORT_SYMBOL(mpt_get_msg_frame);
EXPORT_SYMBOL(mpt_put_msg_frame);
EXPORT_SYMBOL(mpt_free_msg_frame);
@@ -5877,16 +6059,32 @@ EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
EXPORT_SYMBOL(mpt_ASCQ_TableSz);
EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
+
+static struct pci_driver mptbase_driver = {
+ .name = "mptbase",
+ .id_table = mptbase_pci_table,
+ .probe = mptbase_probe,
+ .remove = __devexit_p(mptbase_remove),
+ .driver = {
+ .shutdown = mptbase_shutdown,
+ },
+#ifdef CONFIG_PM
+ .suspend = mptbase_suspend,
+ .resume = mptbase_resume,
+#endif
+};
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* fusion_init - Fusion MPT base driver initialization routine.
*
* Returns 0 for success, non-zero for failure.
*/
-int __init
+static int __init
fusion_init(void)
{
int i;
+ int r;
if (FusionInitCalled++) {
dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
@@ -5920,10 +6118,15 @@ fusion_init(void)
/* FIXME! */
}
- if ((i = mpt_pci_scan()) < 0)
- return i;
+ r = pci_module_init(&mptbase_driver);
+ if(r)
+ return(r);
- return 0;
+#ifdef CONFIG_PROC_FS
+ (void) procmpt_create();
+#endif
+
+ return r;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5933,13 +6136,12 @@ fusion_init(void)
* This routine frees all resources associated with each MPT adapter
* and removes all %MPT_PROCFS_MPTBASEDIR entries.
*/
-static void
+static void __exit
fusion_exit(void)
{
- MPT_ADAPTER *this;
- struct pci_dev *pdev = NULL;
dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
+ pci_unregister_driver(&mptbase_driver);
/* Whups? 20010120 -sralston
* Moved this *above* removal of all MptAdapters!
@@ -5948,30 +6150,9 @@ fusion_exit(void)
(void) procmpt_destroy();
#endif
- while (! Q_IS_EMPTY(&MptAdapters)) {
- this = MptAdapters.head;
-
- /* Disable interrupts! */
- CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
-
- this->active = 0;
-
- pdev = (struct pci_dev *)this->pcidev;
- mptscsih_sync_irq(pdev->irq);
-
- /* Clear any lingering interrupt */
- CHIPREG_WRITE32(&this->chip->IntStatus, 0);
-
- CHIPREG_READ32(&this->chip->IntStatus);
-
- Q_DEL_ITEM(this);
- mpt_adapter_dispose(this);
- }
-
mpt_reset_deregister(mpt_base_index);
}
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
module_init(fusion_init);
module_exit(fusion_exit);
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index c41eb0a6f5ba..94f898527afc 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -80,8 +80,8 @@
#define COPYRIGHT "Copyright (c) 1999-2003 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "2.05.00.06"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.05.00.06"
+#define MPT_LINUX_VERSION_COMMON "3.00.02"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.00.02"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -180,6 +180,16 @@ typedef enum {
MPTUNKNOWN_DRIVER
} MPT_DRIVER_CLASS;
+struct mpt_pci_driver{
+ int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);
+ void (*remove) (struct pci_dev *dev);
+ int (*suspend) (struct pci_dev *dev, u32 state);
+#ifdef CONFIG_PM
+ int (*resume) (struct pci_dev *dev);
+ void (*shutdown) (struct device * dev);
+#endif
+};
+
/*
* MPT adapter / port / bus / device info structures...
*/
@@ -629,6 +639,9 @@ typedef struct _MPT_ADAPTER
FCPortPage0_t fc_port_page0[2];
LANPage0_t lan_cnfg_page0;
LANPage1_t lan_cnfg_page1;
+#ifdef CONFIG_PM
+ u32 PciState[64]; /* save PCI state to this area */
+#endif
u8 FirstWhoInit;
u8 upload_fw; /* If set, do a fw upload */
u8 reload_fw; /* Force a FW Reload on next reset */
@@ -1001,6 +1014,8 @@ extern int mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc);
extern void mpt_event_deregister(int cb_idx);
extern int mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func);
extern void mpt_reset_deregister(int cb_idx);
+extern int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx);
+extern void mpt_device_driver_deregister(int cb_idx);
extern int mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable);
extern void mpt_deregister_ascqops_strings(void);
extern MPT_FRAME_HDR *mpt_get_msg_frame(int handle, int iocid);
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 1e957312e470..585fc68e09c2 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -75,7 +75,8 @@
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
#include <linux/reboot.h> /* notifier code */
#include "../../scsi/scsi.h"
-#include "../../scsi/hosts.h"
+#include <scsi/scsi_host.h>
+
#include "mptbase.h"
#include "mptscsih.h"
@@ -164,8 +165,8 @@ static u32 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc);
static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
static void post_pendingQ_commands(MPT_SCSI_HOST *hd);
-static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, int sleepFlag);
-static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, int sleepFlag);
+static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
+static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
@@ -184,7 +185,7 @@ static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
static struct mpt_work_struct mptscsih_rstTask;
-#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
static void mptscsih_domainValidation(void *hd);
static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
@@ -194,14 +195,19 @@ static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
#endif
static int mptscsih_setup(char *str);
-static int mptscsih_halt(struct notifier_block *nb, ulong event, void *buf);
-/*
- * Reboot Notification
- */
-static struct notifier_block mptscsih_notifier = {
- mptscsih_halt, NULL, 0
-};
+/* module entry point */
+static int __init mptscsih_init (void);
+static void __exit mptscsih_exit (void);
+
+static int __devinit mptscsih_probe (struct pci_dev *, const struct pci_device_id *);
+static void __devexit mptscsih_remove(struct pci_dev *);
+static void mptscsih_shutdown(struct device *);
+#ifdef CONFIG_PM
+static int mptscsih_suspend(struct pci_dev *pdev, u32 state);
+static int mptscsih_resume(struct pci_dev *pdev);
+#endif
+
/*
* Private data...
@@ -216,7 +222,7 @@ static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
#define SNS_LEN(scp) sizeof((scp)->sense_buffer)
-#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/*
* Domain Validation task structure
*/
@@ -238,6 +244,32 @@ static struct mptscsih_driver_setup
driver_setup = MPTSCSIH_DRIVER_SETUP;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/* see mptscsih.h */
+
+static struct scsi_host_template driver_template = {
+ .proc_name = "mptscsih",
+ .proc_info = x_scsi_proc_info,
+ .name = "MPT SCSI Host",
+ .info = x_scsi_info,
+ .queuecommand = x_scsi_queuecommand,
+ .slave_alloc = x_scsi_slave_alloc,
+ .slave_configure = x_scsi_slave_configure,
+ .slave_destroy = x_scsi_slave_destroy,
+ .eh_abort_handler = x_scsi_abort,
+ .eh_device_reset_handler = x_scsi_dev_reset,
+ .eh_bus_reset_handler = x_scsi_bus_reset,
+ .eh_host_reset_handler = x_scsi_host_reset,
+ .bios_param = x_scsi_bios_param,
+ .can_queue = MPT_SCSI_CAN_QUEUE,
+ .this_id = -1,
+ .sg_tablesize = MPT_SCSI_SG_DEPTH,
+ .max_sectors = MPT_SCSI_MAX_SECTORS,
+ .cmd_per_lun = MPT_SCSI_CMD_PER_LUN,
+ .use_clustering = ENABLE_CLUSTERING,
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Private inline routines...
*/
@@ -264,12 +296,14 @@ static inline int
mptscsih_io_direction(Scsi_Cmnd *cmd)
{
switch (cmd->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
+ case WRITE_6:
+ case WRITE_10:
+ case WRITE_16:
return SCSI_DATA_WRITE;
break;
- case READ_6:
- case READ_10:
+ case READ_6:
+ case READ_10:
+ case READ_16:
return SCSI_DATA_READ;
break;
}
@@ -280,6 +314,7 @@ mptscsih_io_direction(Scsi_Cmnd *cmd)
switch (cmd->cmnd[0]) {
/* _DATA_OUT commands */
case WRITE_6: case WRITE_10: case WRITE_12:
+ case WRITE_16:
case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER:
case WRITE_VERIFY: case WRITE_VERIFY_12:
case COMPARE: case COPY: case COPY_VERIFY:
@@ -826,6 +861,13 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
sc->resid = sc->request_bufflen - xfer_cnt;
dprintk((KERN_NOTICE " SET sc->resid=%02xh\n", sc->resid));
+ if(sc->underflow > xfer_cnt) {
+ printk(MYIOC_s_INFO_FMT
+ "SCSI data underrun: underflow=%02x, xfercnt=%02x\n",
+ ioc->name, sc->underflow, xfer_cnt);
+ sc->result = DID_SOFT_ERROR << 16;
+ }
+
/* Report Queue Full
*/
if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
@@ -1235,7 +1277,6 @@ mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
for(ii=0;ii<hd->ioc->req_depth;ii++)
hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
-
/* ChainToChain size must equal the total number
* of chain buffers to be allocated.
* index = chain_idx
@@ -1277,7 +1318,6 @@ mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
mem = (u8 *) hd->ChainToChain;
}
memset(mem, 0xFF, sz);
-
sz = num_chain * hd->ioc->req_sz;
if (hd->ChainBuffer == NULL) {
/* Allocate free chain buffer pool
@@ -1353,28 +1393,25 @@ mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIOReque
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int BeenHereDoneThat = 0;
static char *info_kbuf = NULL;
-/* SCSI host fops start here... */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mptscsih_detect - Register MPT adapter(s) as SCSI host(s) with
- * linux scsi mid-layer.
- * @tpnt: Pointer to Scsi_Host_Template structure
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptscsih_probe - Installs scsi devices per bus.
+ * @pdev: Pointer to pci_dev structure
*
- * (linux Scsi_Host_Template.detect routine)
+ * Returns 0 for success, non-zero for failure.
*
- * Returns number of SCSI host adapters that were successfully
- * registered with the linux scsi mid-layer via the scsi_register()
- * API call.
*/
-int
-mptscsih_detect(Scsi_Host_Template *tpnt)
+
+static int __devinit
+mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct Scsi_Host *sh = NULL;
MPT_SCSI_HOST *hd = NULL;
- MPT_ADAPTER *this;
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ int portnum;
MPT_DONE_Q *freedoneQ;
unsigned long flags;
int sz, ii;
@@ -1382,325 +1419,312 @@ mptscsih_detect(Scsi_Host_Template *tpnt)
int scale;
u8 *mem;
- if (! BeenHereDoneThat++) {
- show_mptmod_ver(my_NAME, my_VERSION);
-
- ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
- ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
- ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
+ for (portnum=0; portnum < ioc->facts.NumberOfPorts; portnum++) {
- if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
- dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n"));
- } else {
- /* FIXME! */
+ /* 20010215 -sralston
+ * Added sanity check on SCSI Initiator-mode enabled
+ * for this MPT adapter.
+ */
+ if (!(ioc->pfacts[portnum].ProtocolFlags &
+ MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
+ printk(MYIOC_s_WARN_FMT
+ "Skipping because SCSI Initiator mode is NOT enabled!\n",
+ ioc->name);
+ continue;
}
- if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
- dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
- } else {
- /* FIXME! */
+ /* 20010202 -sralston
+ * Added sanity check on readiness of the MPT adapter.
+ */
+ if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
+ printk(MYIOC_s_WARN_FMT
+ "Skipping because it's not operational!\n",
+ ioc->name);
+ continue;
}
- }
- dprintk((KERN_INFO MYNAM ": mpt_scsih_detect()\n"));
-#ifdef MODULE
- /* Evaluate the command line arguments, if any */
- if (mptscsih)
- mptscsih_setup(mptscsih);
-#endif
-
- this = mpt_adapter_find_first();
- while (this != NULL) {
- int portnum;
- for (portnum=0; portnum < this->facts.NumberOfPorts; portnum++) {
+ sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST));
+ if (sh != NULL) {
+ spin_lock_irqsave(&ioc->FreeQlock, flags);
- /* 20010215 -sralston
- * Added sanity check on SCSI Initiator-mode enabled
- * for this MPT adapter.
+ /* Attach the SCSI Host to the IOC structure
*/
- if (!(this->pfacts[portnum].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
- printk(MYIOC_s_WARN_FMT "Skipping because SCSI Initiator mode is NOT enabled!\n",
- this->name);
- continue;
- }
-
- /* 20010202 -sralston
- * Added sanity check on readiness of the MPT adapter.
+ ioc->sh = sh;
+
+ sh->io_port = 0;
+ sh->n_io_port = 0;
+ sh->irq = 0;
+
+ /* set 16 byte cdb's */
+ sh->max_cmd_len = 16;
+
+ /* Yikes! This is important!
+ * Otherwise, by default, linux
+ * only scans target IDs 0-7!
+ * pfactsN->MaxDevices unreliable
+ * (not supported in early
+ * versions of the FW).
+ * max_id = 1 + actual max id,
+ * max_lun = 1 + actual last lun,
+ * see hosts.h :o(
*/
- if (this->last_state != MPI_IOC_STATE_OPERATIONAL) {
- printk(MYIOC_s_WARN_FMT "Skipping because it's not operational!\n",
- this->name);
- continue;
+ if ((int)ioc->chip_type > (int)FC929) {
+ sh->max_id = MPT_MAX_SCSI_DEVICES;
+ } else {
+ /* For FC, increase the queue depth
+ * from MPT_SCSI_CAN_QUEUE (31)
+ * to MPT_FC_CAN_QUEUE (63).
+ */
+ sh->can_queue = MPT_FC_CAN_QUEUE;
+ sh->max_id =
+ MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
}
- tpnt->proc_info = mptscsih_proc_info;
- sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));
- if (sh != NULL) {
- spin_lock_irqsave(&this->FreeQlock, flags);
- sh->io_port = 0;
- sh->n_io_port = 0;
- sh->irq = 0;
-
- /* Yikes! This is important!
- * Otherwise, by default, linux
- * only scans target IDs 0-7!
- * pfactsN->MaxDevices unreliable
- * (not supported in early
- * versions of the FW).
- * max_id = 1 + actual max id,
- * max_lun = 1 + actual last lun,
- * see hosts.h :o(
- */
- if ((int)this->chip_type > (int)FC929)
- sh->max_id = MPT_MAX_SCSI_DEVICES;
- else {
- /* For FC, increase the queue depth
- * from MPT_SCSI_CAN_QUEUE (31)
- * to MPT_FC_CAN_QUEUE (63).
- */
- sh->can_queue = MPT_FC_CAN_QUEUE;
- sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
- }
- sh->max_lun = MPT_LAST_LUN + 1;
+ sh->max_lun = MPT_LAST_LUN + 1;
+ sh->max_sectors = MPT_SCSI_MAX_SECTORS;
+ sh->this_id = ioc->pfacts[portnum].PortSCSIID;
- sh->max_sectors = MPT_SCSI_MAX_SECTORS;
- sh->this_id = this->pfacts[portnum].PortSCSIID;
+ /* Required entry.
+ */
+ sh->unique_id = ioc->id;
+
+ /* Verify that we won't exceed the maximum
+ * number of chain buffers
+ * We can optimize: ZZ = req_sz/sizeof(SGE)
+ * For 32bit SGE's:
+ * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
+ * + (req_sz - 64)/sizeof(SGE)
+ * A slightly different algorithm is required for
+ * 64bit SGEs.
+ */
+ scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
+ if (sizeof(dma_addr_t) == sizeof(u64)) {
+ numSGE = (scale - 1) *
+ (ioc->facts.MaxChainDepth-1) + scale +
+ (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
+ sizeof(u32));
+ } else {
+ numSGE = 1 + (scale - 1) *
+ (ioc->facts.MaxChainDepth-1) + scale +
+ (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
+ sizeof(u32));
+ }
- /* Required entry.
- */
- sh->unique_id = this->id;
-
- /* Verify that we won't exceed the maximum
- * number of chain buffers
- * We can optimize: ZZ = req_sz/sizeof(SGE)
- * For 32bit SGE's:
- * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
- * + (req_sz - 64)/sizeof(SGE)
- * A slightly different algorithm is required for
- * 64bit SGEs.
- */
- scale = this->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
- if (sizeof(dma_addr_t) == sizeof(u64)) {
- numSGE = (scale - 1) * (this->facts.MaxChainDepth-1) + scale +
- (this->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
- } else {
- numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale +
- (this->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
- }
+ if (numSGE < sh->sg_tablesize) {
+ /* Reset this value */
+ dprintk((MYIOC_s_INFO_FMT
+ "Resetting sg_tablesize to %d from %d\n",
+ ioc->name, numSGE, sh->sg_tablesize));
+ sh->sg_tablesize = numSGE;
+ }
- if (numSGE < sh->sg_tablesize) {
- /* Reset this value */
- dprintk((MYIOC_s_INFO_FMT
- "Resetting sg_tablesize to %d from %d\n",
- this->name, numSGE, sh->sg_tablesize));
- sh->sg_tablesize = numSGE;
- }
+ /* Set the pci device pointer in Scsi_Host structure.
+ */
+ scsi_set_device(sh, &ioc->pcidev->dev);
- /* Set the pci device pointer in Scsi_Host structure.
- */
- scsi_set_device(sh, &this->pcidev->dev);
+ spin_unlock_irqrestore(&ioc->FreeQlock, flags);
- spin_unlock_irqrestore(&this->FreeQlock, flags);
+ hd = (MPT_SCSI_HOST *) sh->hostdata;
+ hd->ioc = ioc;
+ hd->max_sge = sh->sg_tablesize;
- hd = (MPT_SCSI_HOST *) sh->hostdata;
- hd->ioc = this;
- hd->max_sge = sh->sg_tablesize;
+ if ((int)ioc->chip_type > (int)FC929)
+ hd->is_spi = 1;
- if ((int)this->chip_type > (int)FC929)
- hd->is_spi = 1;
+ if (DmpService && (ioc->chip_type == FC919 ||
+ ioc->chip_type == FC929)) {
+ hd->is_multipath = 1;
+ }
+ hd->port = 0; /* FIXME! */
- if (DmpService &&
- (this->chip_type == FC919 || this->chip_type == FC929))
- hd->is_multipath = 1;
+ /* SCSI needs Scsi_Cmnd lookup table!
+ * (with size equal to req_depth*PtrSz!)
+ */
+ sz = hd->ioc->req_depth * sizeof(void *);
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL)
+ goto mptscsih_probe_failed;
- hd->port = 0; /* FIXME! */
+ memset(mem, 0, sz);
+ hd->ScsiLookup = (struct scsi_cmnd **) mem;
- /* SCSI needs Scsi_Cmnd lookup table!
- * (with size equal to req_depth*PtrSz!)
- */
- sz = hd->ioc->req_depth * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL)
- goto done;
+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+ ioc->name, hd->ScsiLookup, sz));
- memset(mem, 0, sz);
- hd->ScsiLookup = (struct scsi_cmnd **) mem;
+ if (mptscsih_initChainBuffers(hd, 1) < 0)
+ goto mptscsih_probe_failed;
- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
- this->name, hd->ScsiLookup, sz));
+ /* Allocate memory for free and doneQ's
+ */
+ sz = sh->can_queue * sizeof(MPT_DONE_Q);
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL)
+ goto mptscsih_probe_failed;
- if (mptscsih_initChainBuffers(hd, 1) < 0)
- goto done;
+ memset(mem, 0xFF, sz);
+ hd->memQ = mem;
- /* Allocate memory for free and doneQ's
- */
- sz = sh->can_queue * sizeof(MPT_DONE_Q);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL)
- goto done;
+ /* Initialize the free, done and pending Qs.
+ */
+ Q_INIT(&hd->freeQ, MPT_DONE_Q);
+ Q_INIT(&hd->doneQ, MPT_DONE_Q);
+ Q_INIT(&hd->pendingQ, MPT_DONE_Q);
+ spin_lock_init(&hd->freedoneQlock);
+
+ mem = hd->memQ;
+ for (ii=0; ii < sh->can_queue; ii++) {
+ freedoneQ = (MPT_DONE_Q *) mem;
+ Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
+ mem += sizeof(MPT_DONE_Q);
+ }
- memset(mem, 0xFF, sz);
- hd->memQ = mem;
+ /* Initialize this Scsi_Host
+ * internal task Q.
+ */
+ Q_INIT(&hd->taskQ, MPT_FRAME_HDR);
+ hd->taskQcnt = 0;
- /* Initialize the free, done and pending Qs.
- */
- Q_INIT(&hd->freeQ, MPT_DONE_Q);
- Q_INIT(&hd->doneQ, MPT_DONE_Q);
- Q_INIT(&hd->pendingQ, MPT_DONE_Q);
- spin_lock_init(&hd->freedoneQlock);
-
- mem = hd->memQ;
- for (ii=0; ii < sh->can_queue; ii++) {
- freedoneQ = (MPT_DONE_Q *) mem;
- Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
- mem += sizeof(MPT_DONE_Q);
- }
+ /* Allocate memory for the device structures.
+ * A non-Null pointer at an offset
+ * indicates a device exists.
+ * max_id = 1 + maximum id (hosts.h)
+ */
+ sz = sh->max_id * sizeof(void *);
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL)
+ goto mptscsih_probe_failed;
- /* Initialize this Scsi_Host
- * internal task Q.
- */
- Q_INIT(&hd->taskQ, MPT_FRAME_HDR);
- hd->taskQcnt = 0;
+ memset(mem, 0, sz);
+ hd->Targets = (VirtDevice **) mem;
- /* Allocate memory for the device structures.
- * A non-Null pointer at an offset
- * indicates a device exists.
- * max_id = 1 + maximum id (hosts.h)
- */
- sz = sh->max_id * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL)
- goto done;
+ dprintk((KERN_INFO
+ " Targets @ %p, sz=%d\n", hd->Targets, sz));
- memset(mem, 0, sz);
- hd->Targets = (VirtDevice **) mem;
- dprintk((KERN_INFO " Targets @ %p, sz=%d\n", hd->Targets, sz));
+ /* Clear the TM flags
+ */
+ hd->tmPending = 0;
+ hd->tmState = TM_STATE_NONE;
+ hd->resetPending = 0;
+ hd->abortSCpnt = NULL;
+ hd->tmPtr = NULL;
+ hd->numTMrequests = 0;
+ /* Clear the pointer used to store
+ * single-threaded commands, i.e., those
+ * issued during a bus scan, dv and
+ * configuration pages.
+ */
+ hd->cmdPtr = NULL;
- /* Clear the TM flags
- */
- hd->tmPending = 0;
- hd->tmState = TM_STATE_NONE;
- hd->resetPending = 0;
- hd->abortSCpnt = NULL;
- hd->tmPtr = NULL;
- hd->numTMrequests = 0;
+ /* Initialize this SCSI Hosts' timers
+ * To use, set the timer expires field
+ * and add_timer
+ */
+ init_timer(&hd->timer);
+ hd->timer.data = (unsigned long) hd;
+ hd->timer.function = mptscsih_timer_expired;
- /* Clear the pointer used to store
- * single-threaded commands, i.e., those
- * issued during a bus scan, dv and
- * configuration pages.
- */
- hd->cmdPtr = NULL;
+ init_timer(&hd->TMtimer);
+ hd->TMtimer.data = (unsigned long) hd;
+ hd->TMtimer.function = mptscsih_taskmgmt_timeout;
+ hd->qtag_tick = jiffies;
- /* Attach the SCSI Host to the IOC structure
- */
- this->sh = sh;
+ /* Moved Earlier Pam D */
+ /* ioc->sh = sh; */
- /* Initialize this SCSI Hosts' timers
- * To use, set the timer expires field
- * and add_timer
+ if (hd->is_spi) {
+ /* Update with the driver setup
+ * values.
*/
- init_timer(&hd->timer);
- hd->timer.data = (unsigned long) hd;
- hd->timer.function = mptscsih_timer_expired;
-
- init_timer(&hd->TMtimer);
- hd->TMtimer.data = (unsigned long) hd;
- hd->TMtimer.function = mptscsih_taskmgmt_timeout;
- hd->qtag_tick = jiffies;
-
- /* Moved Earlier Pam D */
- /* this->sh = sh; */
+ if (hd->ioc->spi_data.maxBusWidth >
+ driver_setup.max_width) {
+ hd->ioc->spi_data.maxBusWidth =
+ driver_setup.max_width;
+ }
- if (hd->is_spi) {
- /* Update with the driver setup
- * values.
- */
- if (hd->ioc->spi_data.maxBusWidth > driver_setup.max_width)
- hd->ioc->spi_data.maxBusWidth = driver_setup.max_width;
- if (hd->ioc->spi_data.minSyncFactor < driver_setup.min_sync_fac)
- hd->ioc->spi_data.minSyncFactor = driver_setup.min_sync_fac;
+ if (hd->ioc->spi_data.minSyncFactor <
+ driver_setup.min_sync_fac) {
+ hd->ioc->spi_data.minSyncFactor =
+ driver_setup.min_sync_fac;
+ }
- if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC)
- hd->ioc->spi_data.maxSyncOffset = 0;
+ if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) {
+ hd->ioc->spi_data.maxSyncOffset = 0;
+ }
- hd->negoNvram = 0;
-#ifdef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
- hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
+ hd->negoNvram = 0;
+#ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+ hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
#endif
- if (driver_setup.dv == 0)
- hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
-
- hd->ioc->spi_data.forceDv = 0;
- for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
- hd->ioc->spi_data.dvStatus[ii] = MPT_SCSICFG_NEGOTIATE;
-
- if (hd->negoNvram == 0) {
- for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
- hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_NOT_DONE;
- }
+ if (driver_setup.dv == 0) {
+ hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
+ }
- ddvprintk((MYIOC_s_INFO_FMT
- "dv %x width %x factor %x \n",
- hd->ioc->name, driver_setup.dv,
- driver_setup.max_width,
- driver_setup.min_sync_fac));
+ hd->ioc->spi_data.forceDv = 0;
+ for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+ hd->ioc->spi_data.dvStatus[ii] =
+ MPT_SCSICFG_NEGOTIATE;
+ }
+ if (hd->negoNvram == 0) {
+ for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+ hd->ioc->spi_data.dvStatus[ii] |=
+ MPT_SCSICFG_DV_NOT_DONE;
}
- mpt_scsi_hosts++;
+ ddvprintk((MYIOC_s_INFO_FMT
+ "dv %x width %x factor %x \n",
+ hd->ioc->name, driver_setup.dv,
+ driver_setup.max_width,
+ driver_setup.min_sync_fac));
+
}
- } /* for each adapter port */
+ mpt_scsi_hosts++;
- this = mpt_adapter_find_next(this);
- }
+ if(scsi_add_host (sh, &ioc->pcidev->dev)) {
+ dprintk((KERN_ERR MYNAM,
+ "scsi_add_host failed\n"));
+ goto mptscsih_probe_failed;
+ }
-done:
- if (mpt_scsi_hosts > 0)
- register_reboot_notifier(&mptscsih_notifier);
- else {
- mpt_reset_deregister(ScsiDoneCtx);
- dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n"));
+ scsi_scan_host(sh);
+ return 0;
- mpt_event_deregister(ScsiDoneCtx);
- dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n"));
+ } /* scsi_host_alloc */
- mpt_deregister(ScsiScanDvCtx);
- mpt_deregister(ScsiTaskCtx);
- mpt_deregister(ScsiDoneCtx);
+ } /* for each adapter port */
- if (info_kbuf != NULL)
- kfree(info_kbuf);
- }
+mptscsih_probe_failed:
+
+ mptscsih_remove(pdev);
+ return -ENODEV;
- return mpt_scsi_hosts;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mptscsih_release - Unregister SCSI host from linux scsi mid-layer
- * @host: Pointer to Scsi_Host structure
+/*
+ * mptscsih_remove - Removed scsi devices
+ * @pdev: Pointer to pci_dev structure
*
- * (linux Scsi_Host_Template.release routine)
- * This routine releases all resources associated with the SCSI host
- * adapter.
*
- * Returns 0 for success.
*/
-int
-mptscsih_release(struct Scsi_Host *host)
+static void __devexit
+mptscsih_remove(struct pci_dev *pdev)
{
- MPT_SCSI_HOST *hd;
- int count;
- unsigned long flags;
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ struct Scsi_Host *host = ioc->sh;
+ MPT_SCSI_HOST *hd;
+ int count;
+ unsigned long flags;
+
+ if(!host)
+ return;
- hd = (MPT_SCSI_HOST *) host->hostdata;
+ scsi_remove_host(host);
-#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/* Check DV thread active */
count = 10 * HZ;
spin_lock_irqsave(&dvtaskQ_lock, flags);
@@ -1721,8 +1745,7 @@ mptscsih_release(struct Scsi_Host *host)
#endif
#endif
- unregister_reboot_notifier(&mptscsih_notifier);
-
+ hd = (MPT_SCSI_HOST *)host->hostdata;
if (hd != NULL) {
int sz1, sz2, sz3, sztarget=0;
int szr2chain = 0;
@@ -1730,9 +1753,7 @@ mptscsih_release(struct Scsi_Host *host)
int szchain = 0;
int szQ = 0;
- /* Synchronize disk caches
- */
- (void) mptscsih_synchronize_cache(hd, 0);
+ mptscsih_shutdown(&pdev->dev);
sz1 = sz2 = sz3 = 0;
@@ -1796,72 +1817,203 @@ mptscsih_release(struct Scsi_Host *host)
hd->Targets = NULL;
}
- dprintk((MYIOC_s_INFO_FMT "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n",
- hd->ioc->name, sz1, szchain, sz3, sztarget));
+ dprintk((MYIOC_s_INFO_FMT
+ "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n",
+ hd->ioc->name, sz1, szchain, sz3, sztarget));
dprintk(("Free'd done and free Q (%d) memory\n", szQ));
+
+ /* NULL the Scsi_Host pointer
+ */
+ hd->ioc->sh = NULL;
}
- /* NULL the Scsi_Host pointer
+
+ scsi_host_put(host);
+
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptscsih_shutdown - reboot notifier
+ *
+ */
+static void
+mptscsih_shutdown(struct device * dev)
+{
+ MPT_ADAPTER *ioc = pci_get_drvdata(to_pci_dev(dev));
+ struct Scsi_Host *host = ioc->sh;
+ MPT_SCSI_HOST *hd;
+
+ if(!host)
+ return;
+
+ hd = (MPT_SCSI_HOST *)host->hostdata;
+
+ /* Flush the cache of this adapter
*/
- hd->ioc->sh = NULL;
- scsi_unregister(host);
+ if(hd != NULL)
+ mptscsih_synchronize_cache(hd, 0);
- if (mpt_scsi_hosts) {
- if (--mpt_scsi_hosts == 0) {
- mpt_reset_deregister(ScsiDoneCtx);
- dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n"));
+}
- mpt_event_deregister(ScsiDoneCtx);
- dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n"));
+#ifdef CONFIG_PM
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptscsih_suspend - Fusion MPT scsie driver suspend routine.
+ *
+ *
+ */
+static int
+mptscsih_suspend(struct pci_dev *pdev, u32 state)
+{
+ mptscsih_shutdown(&pdev->dev);
+ return 0;
+}
- mpt_deregister(ScsiScanDvCtx);
- mpt_deregister(ScsiTaskCtx);
- mpt_deregister(ScsiDoneCtx);
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptscsih_resume - Fusion MPT scsi driver resume routine.
+ *
+ *
+ */
+static int
+mptscsih_resume(struct pci_dev *pdev)
+{
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ struct Scsi_Host *host = ioc->sh;
+ MPT_SCSI_HOST *hd;
- if (info_kbuf != NULL)
- kfree(info_kbuf);
- }
- }
+ if(!host)
+ return 0;
+ hd = (MPT_SCSI_HOST *)host->hostdata;
+ if(!hd)
+ return 0;
+
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+ {
+ unsigned long lflags;
+ spin_lock_irqsave(&dvtaskQ_lock, lflags);
+ if (!dvtaskQ_active) {
+ dvtaskQ_active = 1;
+ spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
+ MPT_INIT_WORK(&mptscsih_dvTask,
+ mptscsih_domainValidation, (void *) hd);
+ SCHEDULE_TASK(&mptscsih_dvTask);
+ } else {
+ spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
+ }
+ }
+#endif
return 0;
}
+#endif
+
+static struct mpt_pci_driver mptscsih_driver = {
+ .probe = mptscsih_probe,
+ .remove = __devexit_p(mptscsih_remove),
+ .shutdown = mptscsih_shutdown,
+#ifdef CONFIG_PM
+ .suspend = mptscsih_suspend,
+ .resume = mptscsih_resume,
+#endif
+};
+
+
+/* SCSI host fops start here... */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mptscsih_halt - Process the reboot notification
- * @nb: Pointer to a struct notifier_block (ignored)
- * @event: event (SYS_HALT, SYS_RESTART, SYS_POWER_OFF)
- * @buf: Pointer to a data buffer (ignored)
- *
- * This routine called if a system shutdown or reboot is to occur.
+ * mptscsih_init - Register MPT adapter(s) as SCSI host(s) with
+ * linux scsi mid-layer.
*
- * Return NOTIFY_DONE if this is something other than a reboot message.
- * NOTIFY_OK if this is a reboot message.
+ * Returns 0 for success, non-zero for failure.
*/
static int
-mptscsih_halt(struct notifier_block *nb, ulong event, void *buf)
+__init mptscsih_init(void)
{
- MPT_ADAPTER *ioc = NULL;
- MPT_SCSI_HOST *hd = NULL;
+ MPT_ADAPTER *ioc;
- /* Ignore all messages other than reboot message
- */
- if ((event != SYS_RESTART) && (event != SYS_HALT)
- && (event != SYS_POWER_OFF))
- return (NOTIFY_DONE);
+ show_mptmod_ver(my_NAME, my_VERSION);
- for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
- /* Flush the cache of this adapter
- */
- if (ioc->sh) {
- hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
- if (hd) {
- mptscsih_synchronize_cache(hd, 0);
- }
+ ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
+ ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
+ ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
+
+ if(mpt_device_driver_register(&mptscsih_driver,
+ MPTSCSIH_DRIVER) != 0 ) {
+ dprintk((KERN_INFO MYNAM
+ ": failed to register dd callbacks\n"));
+ }
+
+ if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
+ dprintk((KERN_INFO MYNAM
+ ": Registered for IOC event notifications\n"));
+ }
+
+ if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
+ dprintk((KERN_INFO MYNAM
+ ": Registered for IOC reset notifications\n"));
+ }
+
+#ifdef MODULE
+ /* Evaluate the command line arguments, if any */
+ if (mptscsih)
+ mptscsih_setup(mptscsih);
+#endif
+
+ /* probing for devices */
+ for(ioc = mpt_adapter_find_first(); ioc != NULL;
+ ioc = mpt_adapter_find_next(ioc)) {
+ if(mptscsih_probe(ioc->pcidev, ioc->pcidev->driver->id_table)) {
+ dprintk((KERN_INFO MYNAM ": probe failed\n"));
+ return -ENODEV;
}
}
- unregister_reboot_notifier(&mptscsih_notifier);
- return NOTIFY_OK;
+ if (mpt_scsi_hosts > 0)
+ return 0;
+
+ mptscsih_exit();
+ return -ENODEV;
+
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptscsih_exit - Unregisters MPT adapter(s)
+ *
+ */
+static void
+__exit mptscsih_exit(void)
+{
+ MPT_ADAPTER *ioc;
+
+ /* removing devices */
+ for(ioc = mpt_adapter_find_first(); ioc != NULL;
+ ioc = mpt_adapter_find_next(ioc)) {
+ if ((ioc->last_state != MPI_IOC_STATE_OPERATIONAL) ||
+ (ioc->sh == NULL))
+ continue;
+ mptscsih_remove(ioc->pcidev);
+ }
+
+ mpt_reset_deregister(ScsiDoneCtx);
+ dprintk((KERN_INFO MYNAM
+ ": Deregistered for IOC reset notifications\n"));
+
+ mpt_event_deregister(ScsiDoneCtx);
+ dprintk((KERN_INFO MYNAM
+ ": Deregistered for IOC event notifications\n"));
+
+ mpt_device_driver_deregister(MPTSCSIH_DRIVER);
+ mpt_deregister(ScsiScanDvCtx);
+ mpt_deregister(ScsiTaskCtx);
+ mpt_deregister(ScsiDoneCtx);
+
+ if (info_kbuf != NULL)
+ kfree(info_kbuf);
+
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2436,7 +2588,7 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
hd->ioc->spi_data.dvStatus[target] = dvStatus;
}
-#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
(hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
unsigned long lflags;
@@ -2608,7 +2760,7 @@ mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
* Returns 0 for SUCCESS or -1 if FAILED.
*/
static int
-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, int sleepFlag)
+mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
{
MPT_ADAPTER *ioc = NULL;
int rc = -1;
@@ -2664,7 +2816,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort,
*/
if (hd->hard_resets < -1)
hd->hard_resets++;
- rc = mptscsih_IssueTaskMgmt(hd, type, target, lun, ctx2abort, sleepFlag);
+ rc = mptscsih_IssueTaskMgmt(hd, type, target, lun, ctx2abort, timeout, sleepFlag);
if (rc) {
printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
} else {
@@ -2710,7 +2862,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort,
* else other non-zero value returned.
*/
static int
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, int sleepFlag)
+mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
{
MPT_FRAME_HDR *mf;
SCSITaskMgmt_t *pScsiTm;
@@ -2760,7 +2912,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2ab
*/
hd->tmPtr = mf;
hd->numTMrequests++;
- hd->TMtimer.expires = jiffies + HZ*20; /* 20 seconds */
+ hd->TMtimer.expires = jiffies + timeout;
add_timer(&hd->TMtimer);
if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
@@ -2870,7 +3022,8 @@ mptscsih_abort(Scsi_Cmnd * SCpnt)
spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
- SCpnt->device->id, SCpnt->device->lun, ctx2abort, CAN_SLEEP)
+ SCpnt->device->id, SCpnt->device->lun,
+ ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP)
< 0) {
/* The TM request failed and the subsequent FW-reload failed!
@@ -2940,7 +3093,7 @@ mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
}
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
- SCpnt->device->id, 0, 0, CAN_SLEEP)
+ SCpnt->device->id, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
< 0){
/* The TM request failed and the subsequent FW-reload failed!
* Fatal error case.
@@ -3004,7 +3157,7 @@ mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
/* We are now ready to execute the task management request. */
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
- 0, 0, 0, CAN_SLEEP)
+ 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
< 0){
/* The TM request failed and the subsequent FW-reload failed!
@@ -3087,7 +3240,7 @@ static int
mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
{
unsigned long flags;
- int loop_count = 60 * 4; /* Wait 60 seconds */
+ int loop_count = 10 * 4; /* Wait 10 seconds */
int status = FAILED;
do {
@@ -3227,18 +3380,50 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
*/
int
mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
- sector_t capacity, int *ip)
+ sector_t capacity, int geom[])
{
- int size;
+ int heads;
+ int sectors;
+ sector_t cylinders;
+#ifdef CONFIG_LBD
+ ulong dummy;
+#endif
- size = capacity;
- ip[0] = 64; /* heads */
- ip[1] = 32; /* sectors */
- if ((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */
- ip[0] = 255; /* heads */
- ip[1] = 63; /* sectors */
- ip[2] = size / (255 * 63); /* cylinders */
+ heads = 64;
+ sectors = 32;
+#ifdef CONFIG_LBD
+ dummy = heads * sectors;
+ cylinders = capacity;
+ sector_div(cylinders,dummy);
+#else
+ cylinders = (ulong)capacity / (heads * sectors);
+#endif
+
+ /*
+ * Handle extended translation size for logical drives
+ * > 1Gb
+ */
+ if ((ulong)capacity >= 0x200000) {
+ heads = 255;
+ sectors = 63;
+#ifdef CONFIG_LBD
+ dummy = heads * sectors;
+ cylinders = capacity;
+ sector_div(cylinders,dummy);
+#else
+ cylinders = (ulong)capacity / (heads * sectors);
+#endif
}
+
+ /* return result */
+ geom[0] = heads;
+ geom[1] = sectors;
+ geom[2] = cylinders;
+
+ dprintk((KERN_NOTICE
+ ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
+ sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
+
return 0;
}
@@ -3368,7 +3553,7 @@ mptscsih_slave_configure(Scsi_Device *device)
vdev->raidVolume = 0;
if (hd->is_spi && (hd->ioc->spi_data.isRaid & (1 << (device->id)))) {
vdev->raidVolume = 1;
- ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
+ ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", device->id));
}
mptscsih_target_settings(hd, vdev, device);
@@ -3650,36 +3835,6 @@ SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc)
return -1;
}
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-/* see mptscsih.h */
-
-#ifdef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS
-static Scsi_Host_Template driver_template = {
- .proc_name = "mptscsih",
- .proc_info = x_scsi_proc_info,
- .name = "MPT SCSI Host",
- .detect = x_scsi_detect,
- .release = x_scsi_release,
- .info = x_scsi_info,
- .queuecommand = x_scsi_queuecommand,
- .slave_alloc = x_scsi_slave_alloc,
- .slave_configure = x_scsi_slave_configure,
- .slave_destroy = x_scsi_slave_destroy,
- .eh_abort_handler = x_scsi_abort,
- .eh_device_reset_handler = x_scsi_dev_reset,
- .eh_bus_reset_handler = x_scsi_bus_reset,
- .eh_host_reset_handler = x_scsi_host_reset,
- .bios_param = x_scsi_bios_param,
- .can_queue = MPT_SCSI_CAN_QUEUE,
- .this_id = -1,
- .sg_tablesize = MPT_SCSI_SG_DEPTH,
- .max_sectors = MPT_SCSI_MAX_SECTORS,
- .cmd_per_lun = MPT_SCSI_CMD_PER_LUN,
- .use_clustering = ENABLE_CLUSTERING,
-};
-#include "../../scsi/scsi_module.c"
-#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* Search the pendingQ for a command with specific index.
@@ -3958,7 +4113,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
break;
case MPI_EVENT_INTEGRATED_RAID: /* 0B */
-#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/* negoNvram set to 0 if DV enabled and to USE_NVRAM if
* if DV disabled. Need to check for target mode.
*/
@@ -3972,7 +4127,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
int numPDisk;
u8 reason;
u8 physDiskNum;
-
+
reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
/* New or replaced disk.
@@ -4320,6 +4475,8 @@ int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
case WRITE_10:
case READ_12:
case WRITE_12:
+ case READ_16:
+ case WRITE_16:
break;
default:
return 0;
@@ -4618,7 +4775,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
//negoFlags = MPT_TARGET_NO_NEGO_SYNC;
}
-#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/* Force to async and narrow if DV has not been executed
* for this ID
*/
@@ -5000,7 +5157,7 @@ static void mptscsih_timer_expired(unsigned long data)
return;
}
-#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* mptscsih_do_raid - Format and Issue a RAID volume request message.
* @hd: Pointer to scsi host structure
@@ -5071,7 +5228,7 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
return 0;
}
-#endif /* ~MPTSCSIH_DISABLE_DOMAIN_VALIDATION */
+#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
@@ -5383,7 +5540,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
if (ioc->spi_data.sdp1length > 0) {
pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
-
+
if (pcfg1Data != NULL) {
doConfig = 1;
header1.PageVersion = ioc->spi_data.sdp1version;
@@ -5415,7 +5572,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
flags = hd->ioc->spi_data.noQas;
if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
data = hd->ioc->spi_data.nvram[id];
-
+
if (data & MPT_NVRAM_WIDE_DISABLE)
flags |= MPT_TARGET_NO_NEGO_WIDE;
@@ -5424,7 +5581,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
flags |= MPT_TARGET_NO_NEGO_SYNC;
}
}
-
+
/* Force to async, narrow */
mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
&configuration, flags);
@@ -5467,7 +5624,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
return 0;
}
-#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_domainValidation - Top level handler for domain validation.
@@ -5520,7 +5677,7 @@ mptscsih_domainValidation(void *arg)
/* DV only to SCSI adapters */
if ((int)ioc->chip_type <= (int)FC929)
continue;
-
+
/* Make sure everything looks ok */
if (ioc->sh == NULL)
continue;
@@ -6914,7 +7071,7 @@ mptscsih_fillbuf(char *buffer, int size, int index, int width)
break;
}
}
-#endif /* ~MPTSCSIH_DISABLE_DOMAIN_VALIDATION */
+#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* Commandline Parsing routines and defines.
@@ -7009,3 +7166,6 @@ mptscsih_setup(char *str)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+module_init(mptscsih_init);
+module_exit(mptscsih_exit);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 04dd95c59c60..1f791b735738 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -98,13 +98,14 @@
#define MPT_SCSI_SG_DEPTH 40
#endif
-/* To disable domain validation, uncomment the
+/* To disable domain validation, comment the
* following line. No effect for FC devices.
* For SCSI devices, driver will negotiate to
* NVRAM settings (if available) or to maximum adapter
* capabilities.
*/
-/* #define MPTSCSIH_DISABLE_DOMAIN_VALIDATION */
+
+#define MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/* SCSI driver setup structure. Settings can be overridden
@@ -138,15 +139,6 @@ struct mptscsih_driver_setup
*/
/*
- * Conditionalizing with "#ifdef MODULE/#endif" around:
- * static Scsi_Host_Template driver_template = XX;
- * #include <../../scsi/scsi_module.c>
- * lines was REMOVED @ lk-2.4.0-test9
- * Issue discovered 20001213 by: sshirron
- */
-#define MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS 1
-
-/*
* tq_scheduler disappeared @ lk-2.4.0-test12
* (right when <linux/sched.h> newly defined TQ_ACTIVE)
* tq_struct reworked in 2.5.41. Include workqueue.h.
@@ -160,8 +152,6 @@ struct mptscsih_driver_setup
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#define x_scsi_detect mptscsih_detect
-#define x_scsi_release mptscsih_release
#define x_scsi_info mptscsih_info
#define x_scsi_queuecommand mptscsih_qcmd
#define x_scsi_abort mptscsih_abort
@@ -170,9 +160,6 @@ struct mptscsih_driver_setup
#define x_scsi_host_reset mptscsih_host_reset
#define x_scsi_bios_param mptscsih_bios_param
-#define x_scsi_taskmgmt_bh mptscsih_taskmgmt_bh
-#define x_scsi_old_abort mptscsih_old_abort
-#define x_scsi_old_reset mptscsih_old_reset
#define x_scsi_slave_alloc mptscsih_slave_alloc
#define x_scsi_slave_configure mptscsih_slave_configure
#define x_scsi_slave_destroy mptscsih_slave_destroy
@@ -182,8 +169,6 @@ struct mptscsih_driver_setup
/*
* MPT SCSI Host / Initiator decls...
*/
-extern int x_scsi_detect(Scsi_Host_Template *);
-extern int x_scsi_release(struct Scsi_Host *host);
extern const char *x_scsi_info(struct Scsi_Host *);
extern int x_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
extern int x_scsi_abort(Scsi_Cmnd *);
@@ -191,8 +176,7 @@ extern int x_scsi_bus_reset(Scsi_Cmnd *);
extern int x_scsi_dev_reset(Scsi_Cmnd *);
extern int x_scsi_host_reset(Scsi_Cmnd *);
extern int x_scsi_bios_param(struct scsi_device * sdev, struct block_device *bdev,
- sector_t capacity, int *ip);
-extern void x_scsi_taskmgmt_bh(void *);
+ sector_t capacity, int geom[]);
extern int x_scsi_slave_alloc(Scsi_Device *);
extern int x_scsi_slave_configure(Scsi_Device *);
extern void x_scsi_slave_destroy(Scsi_Device *);