From: Eric Moore 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) drivers/message/fusion/mptbase.c | 386 ++++++++++++++++++++++++++++---------- drivers/message/fusion/mptbase.h | 10 drivers/message/fusion/mptscsih.c | 251 +++++++++++++++++------- drivers/message/fusion/mptscsih.h | 10 4 files changed, 472 insertions(+), 185 deletions(-) diff -puN drivers/message/fusion/mptbase.c~mpt-fusion-update drivers/message/fusion/mptbase.c --- 25/drivers/message/fusion/mptbase.c~mpt-fusion-update 2004-01-06 21:22:08.000000000 -0800 +++ 25-akpm/drivers/message/fusion/mptbase.c 2004-01-06 21:22:08.000000000 -0800 @@ -167,6 +167,7 @@ static int MptDriverClass[MPT_MAX_PRO 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 irqreturn_t mpt_interrupt(int irq 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 int ProcessEventNotification(MPT_ 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 @@ struct _mpt_ioc_proc_list { #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 @@ mpt_reset_deregister(int cb_idx) 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 @@ 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 +1278,7 @@ mpt_verify_adapter(int iocid, MPT_ADAPTE /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * 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 @@ mpt_verify_adapter(int iocid, MPT_ADAPTE * * 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 @@ 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 +1532,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)); @@ -1525,6 +1558,146 @@ mpt_adapter_install(struct pci_dev *pdev /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* + * 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 + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * 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; iiname); + (*(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_register); 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_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), +#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 @@ fusion_init(void) /* 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 @@ fusion_init(void) * 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 @@ fusion_exit(void) 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 @@ fusion_exit(void) mpt_reset_deregister(mpt_base_index); } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ module_init(fusion_init); module_exit(fusion_exit); diff -puN drivers/message/fusion/mptbase.h~mpt-fusion-update drivers/message/fusion/mptbase.h --- 25/drivers/message/fusion/mptbase.h~mpt-fusion-update 2004-01-06 21:22:08.000000000 -0800 +++ 25-akpm/drivers/message/fusion/mptbase.h 2004-01-06 21:22:08.000000000 -0800 @@ -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 @@ 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 */ @@ -649,6 +652,7 @@ typedef struct _MPT_ADAPTER_TRACKER { 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 int mpt_event_register(int cb_id 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 -puN drivers/message/fusion/mptscsih.c~mpt-fusion-update drivers/message/fusion/mptscsih.c --- 25/drivers/message/fusion/mptscsih.c~mpt-fusion-update 2004-01-06 21:22:08.000000000 -0800 +++ 25-akpm/drivers/message/fusion/mptscsih.c 2004-01-06 21:22:08.000000000 -0800 @@ -164,8 +164,8 @@ static u32 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd 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 void mptscsih_fillbuf(char *buffe 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 @@ static struct mptscsih_driver_setup 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 @@ 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 +316,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 +863,13 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F 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 @@ mptscsih_initChainBuffers (MPT_SCSI_HOST } else { mem = (u8 *) hd->ReqToChain; } - memset(mem, 0xFF, sz); - +/* memset(mem, 0xFF, sz); */ + for(ii=0;iiioc->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 @@ mptscsih_initChainBuffers (MPT_SCSI_HOST 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 @@ static char *info_kbuf = NULL; /* 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 @@ mptscsih_detect(Scsi_Host_Template *tpnt 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 @@ mptscsih_detect(Scsi_Host_Template *tpnt 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 @@ mptscsih_detect(Scsi_Host_Template *tpnt 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 @@ mptscsih_detect(Scsi_Host_Template *tpnt } mpt_scsi_hosts++; + + scsi_add_host (sh, &this->pcidev->dev); + scsi_scan_host(sh); + } } /* for each adapter port */ @@ -1657,24 +1709,62 @@ mptscsih_detect(Scsi_Host_Template *tpnt } 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 @@ mptscsih_release(struct Scsi_Host *host) /* 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 @@ mptscsih_release(struct Scsi_Host *host) 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 @@ mptscsih_freeChainBuffers(MPT_SCSI_HOST * 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 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 */ 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 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 * 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 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd */ 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 @@ 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! @@ -2938,7 +3032,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. @@ -3002,7 +3096,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! @@ -3085,7 +3179,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 { @@ -3225,18 +3319,50 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER * */ 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 @@ mptscsih_slave_configure(Scsi_Device *de 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 @@ 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. @@ -4318,6 +4414,8 @@ int mpt_ScsiHost_ErrorReport(IO_Info_t * case WRITE_10: case READ_12: case WRITE_12: + case READ_16: + case WRITE_16: break; default: return 0; @@ -5413,7 +5511,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST 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 @@ 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; @@ -7007,3 +7105,6 @@ mptscsih_setup(char *str) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +module_init(mptscsih_init); +module_exit(mptscsih_exit); diff -puN drivers/message/fusion/mptscsih.h~mpt-fusion-update drivers/message/fusion/mptscsih.h --- 25/drivers/message/fusion/mptscsih.h~mpt-fusion-update 2004-01-06 21:22:08.000000000 -0800 +++ 25-akpm/drivers/message/fusion/mptscsih.h 2004-01-06 21:22:08.000000000 -0800 @@ -160,8 +160,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 +168,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 +177,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 +184,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 *); _