From 07789a18fd58bc05ba779e3838ba042bea545fce Mon Sep 17 00:00:00 2001 From: James Bottomley <jejb@mulgrave.(none)> Date: Sat, 24 Apr 2004 22:44:44 -0500 Subject: [PATCH] MPT Fusion add back FC909 support From: "Moore, Eric Dean" <Emoore@lsil.com> --- drivers/message/fusion/mptbase.c | 157 ++++++++++++++++++++++++++++++ drivers/message/fusion/mptbase.h | 4 +- drivers/message/fusion/mptctl.c | 78 ++++++++++----- drivers/message/fusion/mptctl.h | 31 ++++++ drivers/message/fusion/mptscsih.c | 33 +++++-- 5 files changed, 265 insertions(+), 38 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 2797d881d780..fba96eb6d224 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -223,6 +223,7 @@ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); +static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); @@ -263,6 +264,8 @@ struct _mpt_ioc_proc_list { */ 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, @@ -389,6 +392,12 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) else mpt_sp_log_info(ioc, log_info); } + if (ioc_stat & MPI_IOCSTATUS_MASK) { + if ((int)ioc->chip_type <= (int)FC929) + ; + else + mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); + } } else { /* * Process turbo (context) reply... @@ -1350,6 +1359,10 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) } ioc->chip_type = FCUNK; + if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) { + ioc->chip_type = FC909; + ioc->prod_name = "LSIFC909"; + } if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { ioc->chip_type = FC929; ioc->prod_name = "LSIFC929"; @@ -6086,11 +6099,155 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) case 0x00080000: desc = "Outbound DMA Overrun"; break; + + case 0x00090000: + desc = "Task Management"; + break; + + case 0x000A0000: + desc = "Device Problem"; + break; + + case 0x000B0000: + desc = "Invalid Phase Change"; + break; + + case 0x000C0000: + desc = "Untagged Table Size"; + break; + } printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc); } +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC. + * @ioc: Pointer to MPT_ADAPTER structure + * @ioc_status: U32 IOCStatus word from IOC + * @mf: Pointer to MPT request frame + * + * Refer to lsi/mpi.h. + */ +static void +mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) +{ + u32 status = ioc_status & MPI_IOCSTATUS_MASK; + char *desc = ""; + + switch (status) { + case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ + desc = "Invalid Function"; + break; + + case MPI_IOCSTATUS_BUSY: /* 0x0002 */ + desc = "Busy"; + break; + + case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */ + desc = "Invalid SGL"; + break; + + case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */ + desc = "Internal Error"; + break; + + case MPI_IOCSTATUS_RESERVED: /* 0x0005 */ + desc = "Reserved"; + break; + + case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */ + desc = "Insufficient Resources"; + break; + + case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */ + desc = "Invalid Field"; + break; + + case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */ + desc = "Invalid State"; + break; + + case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */ + case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */ + case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */ + case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */ + case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */ + case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */ + /* No message for Config IOCStatus values */ + break; + + case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ + /* No message for recovered error + desc = "SCSI Recovered Error"; + */ + break; + + case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ + desc = "SCSI Invalid Bus"; + break; + + case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ + desc = "SCSI Invalid TargetID"; + break; + + case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ + { + SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; + U8 cdb = pScsiReq->CDB[0]; + if (cdb != 0x12) { /* Inquiry is issued for device scanning */ + desc = "SCSI Device Not There"; + } + break; + } + + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ + desc = "SCSI Data Overrun"; + break; + + case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ + /* This error is checked in scsi_io_done(). Skip. + desc = "SCSI Data Underrun"; + */ + break; + + case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ + desc = "SCSI I/O Data Error"; + break; + + case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ + desc = "SCSI Protocol Error"; + break; + + case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ + desc = "SCSI Task Terminated"; + break; + + case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ + desc = "SCSI Residual Mismatch"; + break; + + case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ + desc = "SCSI Task Management Failed"; + break; + + case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ + desc = "SCSI IOC Terminated"; + break; + + case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ + desc = "SCSI Ext Terminated"; + break; + + default: + desc = "Others"; + break; + } + if (desc != "") + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index dbadc822409e..bcb0aedfc9c9 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -81,8 +81,8 @@ #define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.01.03" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.03" +#define MPT_LINUX_VERSION_COMMON "3.01.05" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.05" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 40379f916763..434ceb1cae5c 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1199,7 +1199,7 @@ static int mptctl_getiocinfo (unsigned long arg, unsigned int data_size) { struct mpt_ioctl_iocinfo *uarg = (struct mpt_ioctl_iocinfo *) arg; - struct mpt_ioctl_iocinfo karg; + struct mpt_ioctl_iocinfo *karg; MPT_ADAPTER *ioc; struct pci_dev *pdev; struct Scsi_Host *sh; @@ -1219,34 +1219,46 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) */ if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev0)) cim_rev = 0; - else if (data_size == sizeof(struct mpt_ioctl_iocinfo)) + else if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev1)) cim_rev = 1; + else if (data_size == sizeof(struct mpt_ioctl_iocinfo)) + cim_rev = 2; else if (data_size == (sizeof(struct mpt_ioctl_iocinfo_rev0)+12)) cim_rev = 0; /* obsolete */ else return -EFAULT; - - if (copy_from_user(&karg, uarg, data_size)) { + + karg = kmalloc(data_size, GFP_KERNEL); + if (karg == NULL) { + printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n", + __FILE__, __LINE__); + return -ENOMEM; + } + + if (copy_from_user(karg, uarg, data_size)) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to read in mpt_ioctl_iocinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); + kfree(karg); return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || + if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { dctlprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); + kfree(karg); return -ENODEV; } /* Verify the data transfer size is correct. * Ignore the port setting. */ - if (karg.hdr.maxDataSize != data_size) { + if (karg->hdr.maxDataSize != data_size) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Structure size mismatch. Command not completed.\n", __FILE__, __LINE__); + kfree(karg); return -EFAULT; } @@ -1254,29 +1266,37 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) * program */ if ((int)ioc->chip_type <= (int) FC929) - karg.adapterType = MPT_IOCTL_INTERFACE_FC; + karg->adapterType = MPT_IOCTL_INTERFACE_FC; else - karg.adapterType = MPT_IOCTL_INTERFACE_SCSI; + karg->adapterType = MPT_IOCTL_INTERFACE_SCSI; - port = karg.hdr.port; + port = karg->hdr.port; - karg.port = port; + karg->port = port; pdev = (struct pci_dev *) ioc->pcidev; - karg.pciId = pdev->device; + karg->pciId = pdev->device; pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); - karg.hwRev = revision; + karg->hwRev = revision; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - karg.subSystemDevice = pdev->subsystem_device; - karg.subSystemVendor = pdev->subsystem_vendor; + karg->subSystemDevice = pdev->subsystem_device; + karg->subSystemVendor = pdev->subsystem_vendor; #endif if (cim_rev == 1) { /* Get the PCI bus, device, and function numbers for the IOC */ - karg.pciInfo.u.bits.busNumber = pdev->bus->number; - karg.pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); - karg.pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); + karg->pciInfo.u.bits.busNumber = pdev->bus->number; + karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); + karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); + } else if (cim_rev == 2) { + /* Get the PCI bus, device, function and segment ID numbers + for the IOC */ + karg->pciInfo.u.bits.busNumber = pdev->bus->number; + karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); + karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); + karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); + karg->pciInfo.segmentID = pci_domain_nr(pdev->bus); } /* Get number of devices @@ -1297,31 +1317,33 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) } } } - karg.numDevices = numDevices; + karg->numDevices = numDevices; /* Set the BIOS and FW Version */ - karg.FWVersion = ioc->facts.FWVersion.Word; - karg.BIOSVersion = ioc->biosVersion; + karg->FWVersion = ioc->facts.FWVersion.Word; + karg->BIOSVersion = ioc->biosVersion; /* Set the Version Strings. */ - strncpy (karg.driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH); - karg.driverVersion[MPT_IOCTL_VERSION_LENGTH-1]='\0'; + strncpy (karg->driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH); + karg->driverVersion[MPT_IOCTL_VERSION_LENGTH-1]='\0'; - karg.busChangeEvent = 0; - karg.hostId = ioc->pfacts[port].PortSCSIID; - karg.rsvd[0] = karg.rsvd[1] = 0; + karg->busChangeEvent = 0; + karg->hostId = ioc->pfacts[port].PortSCSIID; + karg->rsvd[0] = karg->rsvd[1] = 0; /* Copy the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, &karg, data_size)) { + if (copy_to_user((char *)arg, karg, data_size)) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to write out mpt_ioctl_iocinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); + kfree(karg); return -EFAULT; } + kfree(karg); return 0; } @@ -2909,6 +2931,8 @@ int __init mptctl_init(void) if (++where && err) goto out_fail; err = register_ioctl32_conversion(MPTIOCINFO1, compat_mptctl_ioctl); if (++where && err) goto out_fail; + err = register_ioctl32_conversion(MPTIOCINFO2, compat_mptctl_ioctl); + if (++where && err) goto out_fail; err = register_ioctl32_conversion(MPTTARGETINFO, compat_mptctl_ioctl); if (++where && err) goto out_fail; err = register_ioctl32_conversion(MPTTEST, compat_mptctl_ioctl); @@ -2968,6 +2992,7 @@ int __init mptctl_init(void) " (%d:err=%d)\n", where, err); unregister_ioctl32_conversion(MPTIOCINFO); unregister_ioctl32_conversion(MPTIOCINFO1); + unregister_ioctl32_conversion(MPTIOCINFO2); unregister_ioctl32_conversion(MPTTARGETINFO); unregister_ioctl32_conversion(MPTTEST); unregister_ioctl32_conversion(MPTEVENTQUERY); @@ -3018,6 +3043,7 @@ void mptctl_exit(void) #ifdef CONFIG_COMPAT unregister_ioctl32_conversion(MPTIOCINFO); unregister_ioctl32_conversion(MPTIOCINFO1); + unregister_ioctl32_conversion(MPTIOCINFO2); unregister_ioctl32_conversion(MPTTARGETINFO); unregister_ioctl32_conversion(MPTTEST); unregister_ioctl32_conversion(MPTEVENTQUERY); diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h index e751165f5261..47ffd977d1aa 100644 --- a/drivers/message/fusion/mptctl.h +++ b/drivers/message/fusion/mptctl.h @@ -91,6 +91,7 @@ #define MPTIOCINFO _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo) #define MPTIOCINFO1 _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo_rev0) +#define MPTIOCINFO2 _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo_rev1) #define MPTTARGETINFO _IOWR(MPT_MAGIC_NUMBER,18,struct mpt_ioctl_targetinfo) #define MPTTEST _IOWR(MPT_MAGIC_NUMBER,19,struct mpt_ioctl_test) #define MPTEVENTQUERY _IOWR(MPT_MAGIC_NUMBER,21,struct mpt_ioctl_eventquery) @@ -165,6 +166,18 @@ struct mpt_ioctl_pci_info { } u; }; +struct mpt_ioctl_pci_info2 { + union { + struct { + unsigned int deviceNumber : 5; + unsigned int functionNumber : 3; + unsigned int busNumber : 24; + } bits; + unsigned int asUlong; + } u; + int segmentID; +}; + /* * Adapter Information Page * Read only. @@ -175,6 +188,24 @@ struct mpt_ioctl_pci_info { #define MPT_IOCTL_VERSION_LENGTH (32) struct mpt_ioctl_iocinfo { + mpt_ioctl_header hdr; + int adapterType; /* SCSI or FCP */ + int port; /* port number */ + int pciId; /* PCI Id. */ + int hwRev; /* hardware revision */ + int subSystemDevice; /* PCI subsystem Device ID */ + int subSystemVendor; /* PCI subsystem Vendor ID */ + int numDevices; /* number of devices */ + int FWVersion; /* FW Version (integer) */ + int BIOSVersion; /* BIOS Version (integer) */ + char driverVersion[MPT_IOCTL_VERSION_LENGTH]; /* Driver Version (string) */ + char busChangeEvent; + char hostId; + char rsvd[2]; + struct mpt_ioctl_pci_info2 pciInfo; /* Added Rev 2 */ +}; + +struct mpt_ioctl_iocinfo_rev1 { mpt_ioctl_header hdr; int adapterType; /* SCSI or FCP */ int port; /* port number */ diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index a0cef8c98a6b..0f126e033d60 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -805,6 +805,14 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) copy_sense_data(sc, hd, mf, pScsiReply); + + /* + * Look for + dump FCP ResponseInfo[]! + */ + if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) { + printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n", + le32_to_cpu(pScsiReply->ResponseInfo)); + } switch(status) { case MPI_IOCSTATUS_BUSY: /* 0x0002 */ @@ -1106,16 +1114,21 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) * Do OS callback * Free driver resources (chain, msg buffers) */ - if (SCpnt->use_sg) { - pci_unmap_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, - SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); - } else if (SCpnt->request_bufflen) { - scPrivate *my_priv; - - my_priv = (scPrivate *) &SCpnt->SCp; - pci_unmap_single(hd->ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1, - SCpnt->request_bufflen, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + if (scsi_device_online(SCpnt->device)) { + if (SCpnt->use_sg) { + pci_unmap_sg(hd->ioc->pcidev, + (struct scatterlist *) SCpnt->request_buffer, + SCpnt->use_sg, + scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + } else if (SCpnt->request_bufflen) { + scPrivate *my_priv; + + my_priv = (scPrivate *) &SCpnt->SCp; + pci_unmap_single(hd->ioc->pcidev, + (dma_addr_t)(ulong)my_priv->p1, + SCpnt->request_bufflen, + scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + } } SCpnt->result = DID_RESET << 16; SCpnt->host_scribble = NULL; -- 2.30.9