From: "Moore, Eric" Signed-off-by: Andrew Morton --- drivers/message/fusion/mptbase.c | 173 +++++++++++++++++++++++++++- drivers/message/fusion/mptbase.h | 2 drivers/message/fusion/mptscsih.c | 72 ++++++++++- drivers/message/fusion/mptscsih.h | 2 drivers/message/fusion/mptspi.c | 10 + 5 files changed, 244 insertions(+), 15 deletions(-) diff -puN drivers/message/fusion/mptbase.c~fusion-update drivers/message/fusion/mptbase.c --- devel/drivers/message/fusion/mptbase.c~fusion-update 2006-01-22 22:00:38.000000000 -0800 +++ devel-akpm/drivers/message/fusion/mptbase.c 2006-01-22 22:00:38.000000000 -0800 @@ -81,6 +81,10 @@ MODULE_LICENSE("GPL"); /* * cmd line parameters */ +static int mpt_msi_enable = 0; +module_param(mpt_msi_enable, int, 0); +MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)"); + #ifdef MFCNT static int mfcounter = 0; #define PRINT_MF_COUNT 20000 @@ -1444,6 +1448,12 @@ mpt_attach(struct pci_dev *pdev, const s ioc->pci_irq = -1; if (pdev->irq) { + + if (mpt_msi_enable && pci_enable_msi(pdev)) + printk(MYIOC_s_INFO_FMT + "PCI-MSI enabled for this hotplug controller\n", + ioc->name); + r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); if (r < 0) { @@ -1483,6 +1493,8 @@ mpt_attach(struct pci_dev *pdev, const s list_del(&ioc->list); free_irq(ioc->pci_irq, ioc); + if (mpt_msi_enable == 1) + pci_disable_msi(pdev); iounmap(mem); kfree(ioc); pci_set_drvdata(pdev, NULL); @@ -2136,6 +2148,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) if (ioc->pci_irq != -1) { free_irq(ioc->pci_irq, ioc); + if (mpt_msi_enable == 1) + pci_disable_msi(ioc->pcidev); ioc->pci_irq = -1; } @@ -2770,13 +2784,16 @@ SendPortEnable(MPT_ADAPTER *ioc, int por /* RAID FW may take a long time to enable */ - if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) - > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) { - rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, - reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag); + if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) + > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) || + (ioc->bus_type == SAS)) { + rc = mpt_handshake_req_reply_wait(ioc, req_sz, + (u32*)&port_enable, reply_sz, (u16*)&reply_buf, + 300 /*seconds*/, sleepFlag); } else { - rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, - reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag); + rc = mpt_handshake_req_reply_wait(ioc, req_sz, + (u32*)&port_enable, reply_sz, (u16*)&reply_buf, + 30 /*seconds*/, sleepFlag); } return rc; } @@ -4387,6 +4404,138 @@ mptbase_sas_persist_operation(MPT_ADAPTE } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +static void +mptbase_raid_process_event_data(MPT_ADAPTER *ioc, + MpiEventDataRaid_t * pRaidEventData) +{ + int volume; + int reason; + int disk; + int status; + int flags; + int state; + + volume = pRaidEventData->VolumeID; + reason = pRaidEventData->ReasonCode; + disk = pRaidEventData->PhysDiskNum; + status = le32_to_cpu(pRaidEventData->SettingsStatus); + flags = (status >> 0) & 0xff; + state = (status >> 8) & 0xff; + + if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { + return; + } + + if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED && + reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) || + (reason == MPI_EVENT_RAID_RC_SMART_DATA)) { + printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n", + ioc->name, disk); + } else { + printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n", + ioc->name, volume); + } + + switch(reason) { + case MPI_EVENT_RAID_RC_VOLUME_CREATED: + printk(MYIOC_s_INFO_FMT " volume has been created\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_VOLUME_DELETED: + + printk(MYIOC_s_INFO_FMT " volume has been deleted\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED: + printk(MYIOC_s_INFO_FMT " volume settings have been changed\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: + printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n", + ioc->name, + state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL + ? "optimal" + : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED + ? "degraded" + : state == MPI_RAIDVOL0_STATUS_STATE_FAILED + ? "failed" + : "state unknown", + flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED + ? ", enabled" : "", + flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED + ? ", quiesced" : "", + flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS + ? ", resync in progress" : "" ); + break; + + case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED: + printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n", + ioc->name, disk); + break; + + case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: + printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: + printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED: + printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: + printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n", + ioc->name, + state == MPI_PHYSDISK0_STATUS_ONLINE + ? "online" + : state == MPI_PHYSDISK0_STATUS_MISSING + ? "missing" + : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE + ? "not compatible" + : state == MPI_PHYSDISK0_STATUS_FAILED + ? "failed" + : state == MPI_PHYSDISK0_STATUS_INITIALIZING + ? "initializing" + : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED + ? "offline requested" + : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED + ? "failed requested" + : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE + ? "offline" + : "state unknown", + flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC + ? ", out of sync" : "", + flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED + ? ", quiesced" : "" ); + break; + + case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED: + printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n", + ioc->name, disk); + break; + + case MPI_EVENT_RAID_RC_SMART_DATA: + printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n", + ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ); + break; + + case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED: + printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n", + ioc->name, disk); + break; + } +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * GetIoUnitPage2 - Retrieve BIOS version and boot order information. * @ioc: Pointer to MPT_ADAPTER structure @@ -4598,6 +4747,14 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf; MpiDeviceInfo_t *pdevice = NULL; + /* + * Save "Set to Avoid SCSI Bus Resets" flag + */ + ioc->spi_data.bus_reset = + (le32_to_cpu(pPP2->PortFlags) & + MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ? + 0 : 1 ; + /* Save the Port Page 2 data * (reformat into a 32bit quantity) */ @@ -5967,6 +6124,10 @@ ProcessEventNotification(MPT_ADAPTER *io } } break; + case MPI_EVENT_INTEGRATED_RAID: + mptbase_raid_process_event_data(ioc, + (MpiEventDataRaid_t *)pEventReply->Data); + break; default: break; } diff -puN drivers/message/fusion/mptbase.h~fusion-update drivers/message/fusion/mptbase.h --- devel/drivers/message/fusion/mptbase.h~fusion-update 2006-01-22 22:00:38.000000000 -0800 +++ devel-akpm/drivers/message/fusion/mptbase.h 2006-01-22 22:00:38.000000000 -0800 @@ -123,7 +123,7 @@ #define MPT_MAX_FRAME_SIZE 128 #define MPT_DEFAULT_FRAME_SIZE 128 -#define MPT_REPLY_FRAME_SIZE 0x40 /* Must be a multiple of 8 */ +#define MPT_REPLY_FRAME_SIZE 0x50 /* Must be a multiple of 8 */ #define MPT_SG_REQ_128_SCALE 1 #define MPT_SG_REQ_96_SCALE 2 diff -puN drivers/message/fusion/mptscsih.c~fusion-update drivers/message/fusion/mptscsih.c --- devel/drivers/message/fusion/mptscsih.c~fusion-update 2006-01-22 22:00:38.000000000 -0800 +++ devel-akpm/drivers/message/fusion/mptscsih.c 2006-01-22 22:00:38.000000000 -0800 @@ -144,7 +144,8 @@ static int mptscsih_tm_pending_wait(MPT_ static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); -static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); +int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, + u8 target, u8 lun, int ctx2abort, ulong timeout); static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); @@ -730,6 +731,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F break; + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ + sc->resid=0; case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ if (scsi_status == MPI_SCSI_STATUS_BUSY) @@ -789,7 +792,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */ case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */ case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */ - case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ default: @@ -1530,7 +1532,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i * * Returns 0 for SUCCESS or -1 if FAILED. */ -static int +int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) { MPT_ADAPTER *ioc; @@ -1721,6 +1723,20 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd return retval; } +static int +mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) +{ + switch (ioc->bus_type) { + case FC: + return 40; + case SAS: + return 10; + case SPI: + default: + return 5; + } +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant @@ -1790,9 +1806,10 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) hd->abortSCpnt = SCpnt; vdev = SCpnt->device->hostdata; + /* set timeout in seconds */ retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, vdev->bus_id, vdev->target_id, vdev->lun, - ctx2abort, 2 /* 2 second timeout */); + ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", hd->ioc->name, @@ -1843,7 +1860,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SC vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, vdev->bus_id, vdev->target_id, - 0, 0, 5 /* 5 second timeout */); + 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", hd->ioc->name, @@ -1893,7 +1910,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SC vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - vdev->bus_id, 0, 0, 0, 5 /* 5 second timeout */); + vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", hd->ioc->name, @@ -2016,6 +2033,42 @@ mptscsih_tm_wait_for_completion(MPT_SCSI } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +static void +mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) +{ + char *desc; + + switch (response_code) { + case MPI_SCSITASKMGMT_RSP_TM_COMPLETE: + desc = "The task completed."; + break; + case MPI_SCSITASKMGMT_RSP_INVALID_FRAME: + desc = "The IOC received an invalid frame status."; + break; + case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: + desc = "The task type is not supported."; + break; + case MPI_SCSITASKMGMT_RSP_TM_FAILED: + desc = "The requested task failed."; + break; + case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED: + desc = "The task completed successfully."; + break; + case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN: + desc = "The LUN request is invalid."; + break; + case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: + desc = "The task is in the IOC queue and has not been sent to target."; + break; + default: + desc = "unknown"; + break; + } + printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n", + ioc->name, response_code, desc); +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver * @ioc: Pointer to MPT_ADAPTER structure @@ -2064,6 +2117,11 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER * /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */ tmType = pScsiTmReq->TaskType; + if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && + pScsiTmReply->ResponseCode) + mptscsih_taskmgmt_response_code(ioc, + pScsiTmReply->ResponseCode); + dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n", ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); @@ -5620,5 +5678,5 @@ EXPORT_SYMBOL(mptscsih_event_process); EXPORT_SYMBOL(mptscsih_ioc_reset); EXPORT_SYMBOL(mptscsih_change_queue_depth); EXPORT_SYMBOL(mptscsih_timer_expired); - +EXPORT_SYMBOL(mptscsih_TMHandler); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff -puN drivers/message/fusion/mptscsih.h~fusion-update drivers/message/fusion/mptscsih.h --- devel/drivers/message/fusion/mptscsih.h~fusion-update 2006-01-22 22:00:38.000000000 -0800 +++ devel-akpm/drivers/message/fusion/mptscsih.h 2006-01-22 22:00:38.000000000 -0800 @@ -106,5 +106,7 @@ extern int mptscsih_taskmgmt_complete(MP extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); +extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, + u8 target, u8 lun, int ctx2abort, ulong timeout); extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern void mptscsih_timer_expired(unsigned long data); diff -puN drivers/message/fusion/mptspi.c~fusion-update drivers/message/fusion/mptspi.c --- devel/drivers/message/fusion/mptspi.c~fusion-update 2006-01-22 22:00:38.000000000 -0800 +++ devel-akpm/drivers/message/fusion/mptspi.c 2006-01-22 22:00:38.000000000 -0800 @@ -384,6 +384,14 @@ mptspi_probe(struct pci_dev *pdev, const goto out_mptspi_probe; } + /* + * issue internal bus reset + */ + if (ioc->spi_data.bus_reset) + mptscsih_TMHandler(hd, + MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, + 0, 0, 0, 0, 5); + scsi_scan_host(sh); return 0; @@ -445,7 +453,7 @@ static void __exit mptspi_exit(void) { pci_unregister_driver(&mptspi_driver); - + mpt_reset_deregister(mptspiDoneCtx); dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n")); _