Commit 07789a18 authored by James Bottomley's avatar James Bottomley

MPT Fusion add back FC909 support

From: "Moore, Eric Dean" <Emoore@lsil.com>
parent 7ce42ae1
......@@ -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
......
......@@ -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) \
......
......@@ -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);
......
......@@ -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 */
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment