[PATCH] 2.6.1-rc2 - MPT Fusion driver 3.00.00 update

From: Eric Moore
Date: Tue Jan 06 2004 - 19:12:00 EST


Here's an driver update for mpt fusion driver version 3.00.00.

If you find this inline patch malformed,
please kindly download this patch from this URL:

ftp://ftp.lsil.com/HostAdapterDrivers/linux/Fusion-MPT/2.6-patches/

3.00.00 changes
* 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)



diff -uarN linux-2.6.1-rc2-reference/drivers/message/fusion/mptbase.c linux-2.6.1-rc2/drivers/message/fusion/mptbase.c
--- linux-2.6.1-rc2-reference/drivers/message/fusion/mptbase.c 2004-01-06 14:17:58.000000000 -0700
+++ linux-2.6.1-rc2/drivers/message/fusion/mptbase.c 2004-01-06 15:01:27.803311992 -0700
@@ -167,6 +167,7 @@
static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
/* Reset handler lookup table */
static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
+static MPT_DVHANDLER MptDvHandler[MPT_MAX_PROTOCOL_DRIVERS];

static int FusionInitCalled = 0;
static int mpt_base_index = -1;
@@ -183,7 +184,6 @@
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,11 @@
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 int __init fusion_init (void);
+static void __exit fusion_exit (void);

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -260,6 +263,80 @@

#endif

+/****************************************************************************
+ * Supported hardware
+ */
+#define DEVT_INDEX_MPT 0x0000 /* Fusion MPT Interface */
+
+static struct pci_device_id mptbase_pci_table[] = {
+ {
+ .vendor = PCI_VENDOR_ID_LSI_LOGIC,
+ .device = PCI_DEVICE_ID_LSI_FC909,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = PCI_CLASS_SERIAL_FIBER << 8,
+ .class_mask = 0xFFFF00,
+ .driver_data = DEVT_INDEX_MPT
+ },
+ {
+ .vendor = PCI_VENDOR_ID_LSI_LOGIC,
+ .device = PCI_DEVICE_ID_LSI_FC929,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = PCI_CLASS_SERIAL_FIBER << 8,
+ .class_mask = 0xFFFF00,
+ .driver_data = DEVT_INDEX_MPT
+ },
+ {
+ .vendor = PCI_VENDOR_ID_LSI_LOGIC,
+ .device = PCI_DEVICE_ID_LSI_FC919,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = PCI_CLASS_SERIAL_FIBER << 8,
+ .class_mask = 0xFFFF00,
+ .driver_data = DEVT_INDEX_MPT
+ },
+ {
+ .vendor = PCI_VENDOR_ID_LSI_LOGIC,
+ .device = PCI_DEVICE_ID_LSI_FC929X,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = PCI_CLASS_SERIAL_FIBER << 8,
+ .class_mask = 0xFFFF00,
+ .driver_data = DEVT_INDEX_MPT
+ },
+ {
+ .vendor = PCI_VENDOR_ID_LSI_LOGIC,
+ .device = PCI_DEVICE_ID_LSI_FC919X,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = PCI_CLASS_SERIAL_FIBER << 8,
+ .class_mask = 0xFFFF00,
+ .driver_data = DEVT_INDEX_MPT
+ },
+ {
+ .vendor = PCI_VENDOR_ID_LSI_LOGIC,
+ .device = PCI_DEVICE_ID_LSI_53C1030,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = PCI_CLASS_STORAGE_SCSI << 8,
+ .class_mask = 0xFFFF00,
+ .driver_data = DEVT_INDEX_MPT
+ },
+ {
+ .vendor = PCI_VENDOR_ID_LSI_LOGIC,
+ .device = PCI_DEVICE_ID_LSI_1030_53C1035,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = PCI_CLASS_STORAGE_SCSI << 8,
+ .class_mask = 0xFFFF00,
+ .driver_data = DEVT_INDEX_MPT
+ },
+ {0} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
+
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* 20000207 -sralston
* GRRRRR... IOSpace (port i/o) register access (for the 909) is back!
@@ -803,6 +880,36 @@
MptResetHandlers[cb_idx] = NULL;
}

+
+#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mpt_dv_register - Register protocol-specific domain validation handler.
+ */
+int mpt_dv_register(MPT_DVHANDLER dv_cbfunc, int cb_idx)
+{
+ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+ return -1;
+
+ MptDvHandler[cb_idx] = dv_cbfunc;
+ return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mpt_dv_deregister - Deregister protocol-specific domain validation handler.
+ */
+void
+mpt_dv_deregister(int cb_idx)
+{
+ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+ return;
+
+ MptDvHandler[cb_idx] = NULL;
+}
+#endif
+
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
@@ -1142,88 +1249,6 @@
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 +1278,7 @@

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * 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 +1293,8 @@
*
* 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 +1317,13 @@
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 +1532,7 @@
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));
@@ -1525,6 +1558,146 @@

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
+ * mptbase_remove - Remove a PCI intelligent MPT adapter.
+ * @pdev: Pointer to pci_dev structure
+ *
+ */
+
+static void
+__devexit mptbase_remove(struct pci_dev *pdev)
+{
+ mptscsih_sync_irq(pdev->irq);
+ pci_set_drvdata(pdev, NULL);
+}
+
+
+/**************************************************************************
+ * Power Management
+ */
+#ifdef CONFIG_PM
+#include <acpi/acpi_drivers.h>
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * 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);
+
+ switch(state)
+ {
+ case ACPI_STATE_S1:
+ device_state=ACPI_STATE_D1;
+ break;
+ case ACPI_STATE_S3:
+ case ACPI_STATE_S4:
+ device_state=ACPI_STATE_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);
+
+ 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 do_domain_validation_flag=0;
+ int recovery_state;
+
+ 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, ACPI_STATE_D0);
+ 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)) {
+ do_domain_validation_flag=1;
+ }
+
+ 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);
+ }
+
+#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+ if(do_domain_validation_flag) {
+ int ii;
+
+ for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+ ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
+ }
+
+ for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
+ if(MptDvHandler[ii]) {
+ printk(MYIOC_s_INFO_FMT
+ "pci-resume: domain validation\n",ioc->name);
+ (*(MptDvHandler[ii]))(NULL);
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
* mpt_do_ioc_recovery - Initialize or recover MPT adapter.
* @ioc: Pointer to MPT adapter structure
* @reason: Event word / reason
@@ -5851,6 +6024,8 @@
EXPORT_SYMBOL(mpt_event_deregister);
EXPORT_SYMBOL(mpt_reset_register);
EXPORT_SYMBOL(mpt_reset_deregister);
+EXPORT_SYMBOL(mpt_dv_register);
+EXPORT_SYMBOL(mpt_dv_deregister);
EXPORT_SYMBOL(mpt_get_msg_frame);
EXPORT_SYMBOL(mpt_put_msg_frame);
EXPORT_SYMBOL(mpt_free_msg_frame);
@@ -5877,16 +6052,29 @@
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),
+#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
-fusion_init(void)
+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 +6108,13 @@
/* FIXME! */
}

- if ((i = mpt_pci_scan()) < 0)
- return i;
+ r = pci_module_init(&mptbase_driver);

- return 0;
+#ifdef CONFIG_PROC_FS
+ (void) procmpt_create();
+#endif
+
+ return r;
}

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5934,13 +6125,14 @@
* and removes all %MPT_PROCFS_MPTBASEDIR entries.
*/
static void
-fusion_exit(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!
*/
@@ -5956,9 +6148,6 @@

this->active = 0;

- pdev = (struct pci_dev *)this->pcidev;
- mptscsih_sync_irq(pdev->irq);
-
/* Clear any lingering interrupt */
CHIPREG_WRITE32(&this->chip->IntStatus, 0);

@@ -5971,7 +6160,6 @@
mpt_reset_deregister(mpt_base_index);
}

-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

module_init(fusion_init);
module_exit(fusion_exit);
diff -uarN linux-2.6.1-rc2-reference/drivers/message/fusion/mptbase.h linux-2.6.1-rc2/drivers/message/fusion/mptbase.h
--- linux-2.6.1-rc2-reference/drivers/message/fusion/mptbase.h 2004-01-06 14:17:58.000000000 -0700
+++ linux-2.6.1-rc2/drivers/message/fusion/mptbase.h 2003-12-19 10:01:51.000000000 -0700
@@ -80,8 +80,8 @@
#define COPYRIGHT "Copyright (c) 1999-2003 " MODULEAUTHOR
#endif

-#define MPT_LINUX_VERSION_COMMON "2.05.00.05"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.05.00.05"
+#define MPT_LINUX_VERSION_COMMON "3.00.00"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.00.00"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"

#define show_mptmod_ver(s,ver) \
@@ -629,6 +629,9 @@
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 */
@@ -649,6 +652,7 @@
typedef int (*MPT_CALLBACK)(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
typedef int (*MPT_EVHANDLER)(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply);
typedef int (*MPT_RESETHANDLER)(MPT_ADAPTER *ioc, int reset_phase);
+typedef void (*MPT_DVHANDLER)(void *arg);
/* reset_phase defs */
#define MPT_IOC_PRE_RESET 0
#define MPT_IOC_POST_RESET 1
@@ -1001,6 +1005,8 @@
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_dv_register(MPT_DVHANDLER dv_cbfunc, int cb_idx);
+extern void mpt_dv_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 -uarN linux-2.6.1-rc2-reference/drivers/message/fusion/mptscsih.c linux-2.6.1-rc2/drivers/message/fusion/mptscsih.c
--- linux-2.6.1-rc2-reference/drivers/message/fusion/mptscsih.c 2004-01-06 14:17:58.000000000 -0700
+++ linux-2.6.1-rc2/drivers/message/fusion/mptscsih.c 2004-01-06 14:25:16.000000000 -0700
@@ -164,8 +164,8 @@
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);
@@ -196,6 +196,12 @@
static int mptscsih_setup(char *str);
static int mptscsih_halt(struct notifier_block *nb, ulong event, void *buf);

+/* module entry point */
+static int __init mptscsih_init (void);
+static void __exit mptscsih_exit (void);
+int mptscsih_release(struct Scsi_Host *host);
+
+
/*
* Reboot Notification
*/
@@ -238,6 +244,34 @@
driver_setup = MPTSCSIH_DRIVER_SETUP;

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/* 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",
+ .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,
+};
+#endif
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Private inline routines...
*/
@@ -264,12 +298,14 @@
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 +316,7 @@
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 +863,13 @@
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)
@@ -1231,8 +1275,9 @@
} else {
mem = (u8 *) hd->ReqToChain;
}
- memset(mem, 0xFF, sz);
-
+/* memset(mem, 0xFF, sz); */
+ 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.
@@ -1275,7 +1320,6 @@
mem = (u8 *) hd->ChainToChain;
}
memset(mem, 0xFF, sz);
-
sz = num_chain * hd->ioc->req_sz;
if (hd->ChainBuffer == NULL) {
/* Allocate free chain buffer pool
@@ -1357,18 +1401,13 @@
/* SCSI host fops start here... */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mptscsih_detect - Register MPT adapter(s) as SCSI host(s) with
+ * mptscsih_init - Register MPT adapter(s) as SCSI host(s) with
* linux scsi mid-layer.
- * @tpnt: Pointer to Scsi_Host_Template structure
*
- * (linux Scsi_Host_Template.detect routine)
- *
- * Returns number of SCSI host adapters that were successfully
- * registered with the linux scsi mid-layer via the scsi_register()
- * API call.
+ * Returns 0 for success, non-zero for failure.
*/
-int
-mptscsih_detect(Scsi_Host_Template *tpnt)
+static int
+__init mptscsih_init(void)
{
struct Scsi_Host *sh = NULL;
MPT_SCSI_HOST *hd = NULL;
@@ -1387,6 +1426,12 @@
ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);

+#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+ if(mpt_dv_register(mptscsih_domainValidation, MPTSCSIH_DRIVER) != 0 ) {
+ dprintk((KERN_INFO MYNAM
+ ": failed to register dv callback\n"));
+ }
+#endif
if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n"));
} else {
@@ -1431,14 +1476,17 @@
continue;
}

- tpnt->proc_info = mptscsih_proc_info;
- sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));
+ sh = scsi_host_alloc(&driver_template, 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;

+ /* set 16 byte cdb's
+ */
+ sh->max_cmd_len = 16;
+
/* Yikes! This is important!
* Otherwise, by default, linux
* only scans target IDs 0-7!
@@ -1634,7 +1682,7 @@
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;
@@ -1649,6 +1697,10 @@
}

mpt_scsi_hosts++;
+
+ scsi_add_host (sh, &this->pcidev->dev);
+ scsi_scan_host(sh);
+
}

} /* for each adapter port */
@@ -1657,24 +1709,62 @@
}

done:
- if (mpt_scsi_hosts > 0)
+ if (mpt_scsi_hosts > 0) {
register_reboot_notifier(&mptscsih_notifier);
- else {
+ return 0;
+ } else {
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"));

+#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+ mpt_dv_deregister(MPTSCSIH_DRIVER);
+#endif
mpt_deregister(ScsiScanDvCtx);
mpt_deregister(ScsiTaskCtx);
mpt_deregister(ScsiDoneCtx);

if (info_kbuf != NULL)
kfree(info_kbuf);
+
+ return -EBUSY;
}

- return mpt_scsi_hosts;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptscsih_exit - Unregisters MPT adapter(s)
+ *
+ */
+static void
+__exit mptscsih_exit(void)
+{
+ MPT_ADAPTER *this;
+ struct Scsi_Host *sh = NULL;
+
+ this = mpt_adapter_find_first();
+ while (this != NULL) {
+
+ if (this->last_state != MPI_IOC_STATE_OPERATIONAL) {
+ this = mpt_adapter_find_next(this);
+ continue;
+ }
+
+ sh = this->sh;
+ if( sh == NULL ) {
+ continue;
+ }
+
+ scsi_remove_host(sh);
+ mptscsih_release(sh);
+ scsi_host_put(sh);
+ this->sh = NULL;
+ this = mpt_adapter_find_next(this);
+ }
}

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1801,7 +1891,6 @@
/* NULL the Scsi_Host pointer
*/
hd->ioc->sh = NULL;
- scsi_unregister(host);

if (mpt_scsi_hosts) {
if (--mpt_scsi_hosts == 0) {
@@ -1811,6 +1900,10 @@
mpt_event_deregister(ScsiDoneCtx);
dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n"));

+#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+ mpt_dv_deregister(MPTSCSIH_DRIVER);
+#endif
+
mpt_deregister(ScsiScanDvCtx);
mpt_deregister(ScsiTaskCtx);
mpt_deregister(ScsiDoneCtx);
@@ -2606,7 +2699,7 @@
* 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;
@@ -2662,7 +2755,7 @@
*/
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 {
@@ -2708,7 +2801,7 @@
* 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;
@@ -2758,7 +2851,7 @@
*/
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,
@@ -2868,7 +2961,8 @@

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!
@@ -2938,7 +3032,7 @@
}

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.
@@ -3002,7 +3096,7 @@

/* 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!
@@ -3085,7 +3179,7 @@
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 {
@@ -3225,18 +3319,50 @@
*/
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;
+ do_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;
+ do_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;
}

@@ -3366,7 +3492,7 @@
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);
@@ -3648,36 +3774,6 @@
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.
@@ -4318,6 +4414,8 @@
case WRITE_10:
case READ_12:
case WRITE_12:
+ case READ_16:
+ case WRITE_16:
break;
default:
return 0;
@@ -5413,7 +5511,7 @@
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;

@@ -5518,7 +5616,7 @@
/* DV only to SCSI adapters */
if ((int)ioc->chip_type <= (int)FC929)
continue;
- +
/* Make sure everything looks ok */
if (ioc->sh == NULL)
continue;
@@ -7007,3 +7105,6 @@

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

+
+module_init(mptscsih_init);
+module_exit(mptscsih_exit);
diff -uarN linux-2.6.1-rc2-reference/drivers/message/fusion/mptscsih.h linux-2.6.1-rc2/drivers/message/fusion/mptscsih.h
--- linux-2.6.1-rc2-reference/drivers/message/fusion/mptscsih.h 2004-01-06 14:17:58.000000000 -0700
+++ linux-2.6.1-rc2/drivers/message/fusion/mptscsih.h 2003-12-16 12:18:46.000000000 -0700
@@ -160,8 +160,6 @@

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

-#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 +168,6 @@
#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 +177,6 @@
/*
* 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 +184,7 @@
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 *);


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/