Commit bf6ca902 authored by Pamela Delaney's avatar Pamela Delaney Committed by Linus Torvalds

[PATCH] Fusion Driver 2.05.00.03 against 2.5.62bk3

Please accept this large patch against 2.5.62bk4 to update the
Fusion-MPT driver from 2.03.01.01 to 2.05.00.03.

This version contains full 2.5 kernel support (add, configuration &
removal of disks, new module hooks), performance enhancements, removal
of obsolete code that is 2.4 (or earlier) specific and removal of blank
spaces at end of lines.  Tested overnight on 2.5.62bk3 and ran some
tests against bk4 this morning on both machines.  Things appear to be
fine - have not tested the two failure conditions today.

The driver has been tested on two different platforms:

- P4 4-processor
   o boot controller
   o built into kernel
   o disk add, configure, remove
   o bus, target reset
   o device offline cases
   o cross channel I/O stress tests w/ Fibre and SCSI

 - Athlon uniprocessor, IDE boot
   o Ran a test that repeatedly loads the driver, mounts disks, runs a
     short I/O test (20mins) then unload the driver components in a
     different order

Failures:
   o Unable to boot if boot controller is built as a module - pivot_root
     fails (Happens if IDE or SCSI boot)

   o Problems when formatting large SCSI disks.  On P4 w/ 2.5.60, there
     were no difficulties formatting a 36GB disk.  On Athlon, mkfs.ext2
     would never send a write command to the driver (verified w/ SCSI
     trace and driver debug).  Reads completed successfully.  mkfs.ext2
     would not exit and is shown as a running process.

     Smaller partitions were formatted correctly.  W/ 2.5.62 failures on
     P4 and Athlon.

     Same error with other drivers. 100% reproducible.
parent 3d34f2f7
......@@ -91,6 +91,7 @@
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
int __init isense_init(void)
......
......@@ -270,6 +270,13 @@ static __inline__ int __get_order(unsigned long size)
#define mptscsih_sync_irq(_irq) synchronize_irq()
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,58)
#define mpt_inc_use_count()
#define mpt_dec_use_count()
#else
#define mpt_inc_use_count() MOD_INC_USE_COUNT
#define mpt_dec_use_count() MOD_DEC_USE_COUNT
#endif
/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......
......@@ -184,7 +184,7 @@ typedef struct _MSG_SCSI_IO_RAID_PT_REPLY
/****************************************************************************/
/* Mailbox request structure */
/* Mailbox reqeust structure */
/****************************************************************************/
typedef struct _MSG_MAILBOX_REQUEST
......
......@@ -49,7 +49,7 @@
* (mailto:sjralston1@netscape.net)
* (mailto:Pam.Delaney@lsil.com)
*
* $Id: mptbase.c,v 1.125 2002/12/03 21:26:32 pdelaney Exp $
* $Id: mptbase.c,v 1.126 2002/12/16 15:28:45 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
......@@ -123,8 +123,10 @@ MODULE_LICENSE("GPL");
/*
* cmd line parameters
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,59)
MODULE_PARM(PortIo, "0-1i");
MODULE_PARM_DESC(PortIo, "[0]=Use mmap, 1=Use port io");
#endif
static int PortIo = 0;
#ifdef MFCNT
......@@ -580,8 +582,6 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
ioc->name, mf, reply));
DBG_DUMP_REPLY_FRAME(reply)
pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
if (pCfg) {
......@@ -686,7 +686,7 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
MptEvHandlers[i] = NULL;
last_drv_idx = i;
if (cbfunc != mpt_base_reply) {
MOD_INC_USE_COUNT;
mpt_inc_use_count();
}
break;
}
......@@ -706,7 +706,7 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
void
mpt_deregister(int cb_idx)
{
if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
MptCallbacks[cb_idx] = NULL;
MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
MptEvHandlers[cb_idx] = NULL;
......@@ -716,7 +716,7 @@ mpt_deregister(int cb_idx)
isense_idx++;
if (cb_idx != mpt_base_index) {
MOD_DEC_USE_COUNT;
mpt_dec_use_count();
}
}
}
......@@ -2107,9 +2107,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
* Loop here waiting for IOC to come READY.
*/
ii = 0;
cntdn = HZ * 15;
if (sleepFlag != CAN_SLEEP)
cntdn *= 10; /* 1500 iterations @ 1msec per */
cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
......@@ -2483,9 +2481,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
* LoopInit and TargetDiscovery!
*/
count = 0;
cntdn = HZ * 60; /* chg'd from 30 to 60 seconds */
if (sleepFlag != CAN_SLEEP)
cntdn *= 10; /* scale for 1msec delays */
cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
state = mpt_GetIocState(ioc, 1);
while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
if (sleepFlag == CAN_SLEEP) {
......@@ -3478,10 +3474,8 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
/* FW ACK'd request, wait for READY state
*/
cntdn = HZ * 15;
count = 0;
if (sleepFlag != CAN_SLEEP)
cntdn *= 10; /* 1500 iterations @ 1msec per */
cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
cntdn--;
......@@ -3640,9 +3634,6 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
}
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
#ifdef MFCNT
ioc->mfcnt = 0;
#endif
if (ioc->sense_buf_pool == NULL) {
sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
......@@ -3822,10 +3813,12 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
static int
WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
{
int cntdn = HZ * howlong;
int cntdn;
int count = 0;
u32 intstat;
cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
if (sleepFlag == CAN_SLEEP) {
while (--cntdn) {
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
......@@ -3836,7 +3829,6 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
count++;
}
} else {
cntdn *= 10; /* convert to msec */
while (--cntdn) {
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
......@@ -3844,7 +3836,6 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
mdelay (1);
count++;
}
count /= 10;
}
if (cntdn) {
......@@ -3873,10 +3864,11 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
static int
WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
{
int cntdn = HZ * howlong;
int cntdn;
int count = 0;
u32 intstat;
cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
if (sleepFlag == CAN_SLEEP) {
while (--cntdn) {
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
......@@ -3887,7 +3879,6 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
count++;
}
} else {
cntdn *= 10; /* convert to msec */
while (--cntdn) {
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
......@@ -3895,7 +3886,6 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
mdelay(1);
count++;
}
count /= 10;
}
if (cntdn) {
......@@ -4953,7 +4943,6 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
/* Search the configQ for internal commands.
* Flush the Q, and wake up all suspended threads.
*/
#if 1
spin_lock_irqsave(&ioc->FreeQlock, flags);
if (! Q_IS_EMPTY(&ioc->configQ)){
pCfg = (CONFIGPARMS *)ioc->configQ.head;
......@@ -4970,23 +4959,6 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
} while (pCfg != (CONFIGPARMS *)&ioc->configQ);
}
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
#else
while (1) {
spin_lock_irqsave(&ioc->FreeQlock, flags);
if (! Q_IS_EMPTY(&ioc->configQ)){
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
break;
}
pCfg = (CONFIGPARMS *)ioc->configQ.head;
Q_DEL_ITEM(&pCfg->linkage);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
pCfg->status = MPT_CONFIG_ERROR;
pCfg->wait_done = 1;
wake_up(&mpt_waitq);
}
#endif
}
return 1; /* currently means nothing really */
......@@ -5845,7 +5817,7 @@ mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTa
isense_idx = last_drv_idx;
r = 1;
}
MOD_INC_USE_COUNT;
mpt_inc_use_count();
return r;
}
......@@ -5864,7 +5836,7 @@ mpt_deregister_ascqops_strings(void)
mpt_ScsiOpcodesPtr = NULL;
printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
isense_idx = -1;
MOD_DEC_USE_COUNT;
mpt_dec_use_count();
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......
......@@ -13,7 +13,7 @@
* (mailto:sjralston1@netscape.net)
* (mailto:Pam.Delaney@lsil.com)
*
* $Id: mptbase.h,v 1.141 2002/12/03 21:26:32 pdelaney Exp $
* $Id: mptbase.h,v 1.144 2003/01/28 21:31:56 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
......@@ -80,8 +80,8 @@
#define COPYRIGHT "Copyright (c) 1999-2002 " MODULEAUTHOR
#endif
#define MPT_LINUX_VERSION_COMMON "2.03.01.01"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.03.01.01"
#define MPT_LINUX_VERSION_COMMON "2.05.00.03"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.05.00.03"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
......@@ -383,12 +383,9 @@ typedef struct _VirtDevice {
u8 maxWidth; /* 0 if narrow, 1 if wide*/
u8 negoFlags; /* bit field, 0 if WDTR/SDTR/QAS allowed */
u8 raidVolume; /* set, if RAID Volume */
#ifdef ABORT_FIX
u8 numAborts;
#else
u8 rsvd;
#endif
u16 rsvd1raid;
u8 type; /* byte 0 of Inquiry data */
u8 cflags; /* controller flags */
u8 rsvd1raid;
int npaths;
u16 fc_phys_lun;
u16 fc_xlat_lun;
......@@ -400,11 +397,8 @@ typedef struct _VirtDevice {
ScsiCmndTracker WaitQ;
ScsiCmndTracker SentQ;
ScsiCmndTracker DoneQ;
u32 num_luns;
//--- LUN split here?
#ifdef MPT_SAVE_AUTOSENSE
u8 sense[SCSI_STD_SENSE_BYTES]; /* 18 */
u8 rsvd2[2]; /* alignment */
#endif
u32 luns; /* Max LUNs is 32 */
u8 inq_data[SCSI_STD_INQUIRY_BYTES]; /* 36 */
u8 pad0[4];
......@@ -428,13 +422,15 @@ typedef struct _VirtDevice {
* Fibre Channel (SCSI) target device and associated defines...
*/
#define MPT_TARGET_DEFAULT_DV_STATUS 0
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,55)
#define MPT_TARGET_FLAGS_CONFIGURED 0x02
#define MPT_TARGET_FLAGS_Q_YES 0x08
#else
#define MPT_TARGET_FLAGS_VALID_NEGO 0x01
#define MPT_TARGET_FLAGS_VALID_INQUIRY 0x02
#ifdef MPT_SAVE_AUTOSENSE
#define MPT_TARGET_FLAGS_VALID_SENSE 0x04
#endif
#define MPT_TARGET_FLAGS_Q_YES 0x08
#define MPT_TARGET_FLAGS_VALID_56 0x10
#endif
#define MPT_TARGET_NO_NEGO_WIDE 0x01
#define MPT_TARGET_NO_NEGO_SYNC 0x02
......@@ -603,7 +599,7 @@ typedef struct _MPT_ADAPTER
dma_addr_t sense_buf_pool_dma;
u32 sense_buf_low_dma;
int mtrr_reg;
struct pci_dev *pcidev;
struct pci_dev *pcidev; /* struct pci_dev pointer */
u8 *memmap; /* mmap address */
struct Scsi_Host *sh; /* Scsi Host pointer */
ScsiCfgData spi_data; /* Scsi config. data */
......@@ -764,6 +760,13 @@ typedef struct _mpt_sge {
#define dcprintk(x)
#endif
#if defined(MPT_DEBUG_SCSI) || defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME)
#define dsprintk(x) printk x
#else
#define dsprintk(x)
#endif
#define MPT_INDEX_2_MFPTR(ioc,idx) \
(MPT_FRAME_HDR*)( (u8*)(ioc)->req_frames + (ioc)->req_sz * (idx) )
......@@ -1050,7 +1053,7 @@ extern int mpt_ASCQ_TableSz;
#define offsetof(t, m) ((size_t) (&((t *)0)->m))
#endif
#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__)
#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__)
#define CAST_U32_TO_PTR(x) ((void *)(u64)x)
#define CAST_PTR_TO_U32(x) ((u32)(u64)x)
#else
......
......@@ -102,6 +102,9 @@
#define my_VERSION MPT_LINUX_VERSION_COMMON
#define MYNAM "mptctl"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,62)
EXPORT_NO_SYMBOLS;
#endif
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
......@@ -135,7 +138,7 @@ static int mptctl_eventreport (unsigned long arg);
static int mptctl_replace_fw (unsigned long arg);
static int mptctl_do_reset(unsigned long arg);
static int mptctl_hp_hostinfo(unsigned long arg);
static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
static int mptctl_hp_targetinfo(unsigned long arg);
/*
......@@ -658,25 +661,19 @@ mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
dctlprintk((MYIOC_s_INFO_FMT ": mptctl_ioctl()\n", iocp->name));
switch(cmd) {
case MPTFWDOWNLOAD:
if (cmd == MPTFWDOWNLOAD)
ret = mptctl_fw_download(arg);
break;
case MPTCOMMAND:
else if (cmd == MPTCOMMAND)
ret = mptctl_mpt_command(arg);
break;
case MPTHARDRESET:
else if (cmd == MPTHARDRESET)
ret = mptctl_do_reset(arg);
break;
case HP_GETHOSTINFO:
ret = mptctl_hp_hostinfo(arg);
break;
case HP_GETTARGETINFO:
else if ((cmd & ~IOCSIZE_MASK) == (HP_GETHOSTINFO & ~IOCSIZE_MASK))
ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd));
else if (cmd == HP_GETTARGETINFO)
ret = mptctl_hp_targetinfo(arg);
break;
default:
else
ret = -EINVAL;
}
up(&mptctl_syscall_sem_ioc[iocp->id]);
......@@ -873,7 +870,7 @@ mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen)
* 96 8
* 64 4
*/
maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t))
maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t))
/ (sizeof(dma_addr_t) + sizeof(u32));
if (numfrags > maxfrags) {
ret = -EMLINK;
......@@ -1227,10 +1224,16 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
u8 revision;
dctlprintk((": mptctl_getiocinfo called.\n"));
if (data_size == sizeof(struct mpt_ioctl_iocinfo))
cim_rev = 1;
else if (data_size == (sizeof(struct mpt_ioctl_iocinfo) - sizeof(struct mpt_ioctl_pci_info)))
/* Add of PCI INFO results in unaligned access for
* IA64 and Sparc. Reset long to int. Return no PCI
* data for obsolete format.
*/
if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev0))
cim_rev = 0;
else if (data_size == sizeof(struct mpt_ioctl_iocinfo))
cim_rev = 1;
else if (data_size == (sizeof(struct mpt_ioctl_iocinfo_rev0)+12))
cim_rev = 0; /* obsolete */
else
return -EFAULT;
......@@ -1414,7 +1417,7 @@ mptctl_gettargetinfo (unsigned long arg)
/* Get number of devices
*/
if ( (sh = ioc->sh) != NULL) {
if ((sh = ioc->sh) != NULL) {
max_id = sh->max_id - 1;
hd = (MPT_SCSI_HOST *) sh->hostdata;
......@@ -1437,9 +1440,8 @@ mptctl_gettargetinfo (unsigned long arg)
pdata++;
if (maxWordsLeft <= 0) {
if (maxWordsLeft <= 0)
break;
}
}
}
}
......@@ -1712,7 +1714,7 @@ mptctl_replace_fw (unsigned long arg)
/* Allocate memory for the new FW image
*/
newFwSize = karg.newImageSize;
fwmem = mpt_alloc_fw_memory(ioc, newFwSize, &num_frags, &alloc_sz);
fwmem = mpt_alloc_fw_memory(ioc, newFwSize, &num_frags, &alloc_sz);
if (fwmem == NULL)
return -ENOMEM;
......@@ -1732,7 +1734,7 @@ mptctl_replace_fw (unsigned long arg)
}
/* Free the old FW image
/* Free the old FW image
*/
if (ioc->cached_fw) {
mpt_free_fw_memory(ioc, 0);
......@@ -1905,6 +1907,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
case MPI_FUNCTION_FW_UPLOAD:
case MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
case MPI_FUNCTION_FW_DOWNLOAD:
case MPI_FUNCTION_FC_PRIMITIVE_SEND:
break;
case MPI_FUNCTION_SCSI_IO_REQUEST:
......@@ -2032,7 +2035,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
break;
case MPI_FUNCTION_SCSI_TASK_MGMT:
{
{
MPT_SCSI_HOST *hd = NULL;
if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) {
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
......@@ -2065,7 +2068,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
}
if ((pInit->Flags != 0) || (pInit->MaxDevices != ioc->facts.MaxDevices) ||
(pInit->MaxBuses != ioc->facts.MaxBuses) ||
(pInit->MaxBuses != ioc->facts.MaxBuses) ||
(pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) ||
(pInit->HostMfaHighAddr != high_addr) ||
(pInit->SenseBufferHighAddr != sense_high)) {
......@@ -2097,7 +2100,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
MPI_FUNCTION_FC_LINK_SRVC_BUF_POST
MPI_FUNCTION_FC_LINK_SRVC_RSP
MPI_FUNCTION_FC_ABORT
MPI_FUNCTION_FC_PRIMITIVE_SEND
MPI_FUNCTION_LAN_SEND
MPI_FUNCTION_LAN_RECEIVE
MPI_FUNCTION_LAN_RESET
......@@ -2395,7 +2397,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
* -ENOMEM if memory allocation error
*/
static int
mptctl_hp_hostinfo(unsigned long arg)
mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
{
hp_host_info_t *uarg = (hp_host_info_t *) arg;
MPT_ADAPTER *ioc;
......@@ -2406,9 +2408,18 @@ mptctl_hp_hostinfo(unsigned long arg)
CONFIGPARMS cfg;
ConfigPageHeader_t hdr;
int iocnum;
int rc;
int rc, cim_rev;
dctlprintk((": mptctl_hp_hostinfo called.\n"));
/* Reset long to int. Should affect IA64 and SPARC only
*/
if (data_size == sizeof(hp_host_info_t))
cim_rev = 1;
else if (data_size == (sizeof(hp_host_info_t) + 12))
cim_rev = 0; /* obsolete */
else
return -EFAULT;
if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) {
printk(KERN_ERR "%s@%d::mptctl_hp_host_info - "
"Unable to read in hp_host_info struct @ %p\n",
......@@ -2438,7 +2449,7 @@ mptctl_hp_hostinfo(unsigned long arg)
karg.bus = pdev->bus->number;
/* Save the SCSI host no. if
* SCSI driver loaded
* SCSI driver loaded
*/
if (ioc->sh != NULL)
karg.host_no = ioc->sh->host_no;
......@@ -2526,7 +2537,7 @@ mptctl_hp_hostinfo(unsigned long arg)
if (ioc->sh != NULL) {
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
if (hd) {
if (hd && (cim_rev == 1)) {
karg.hard_resets = hd->hard_resets;
karg.soft_resets = hd->soft_resets;
karg.timeouts = hd->timeouts;
......@@ -2620,7 +2631,7 @@ mptctl_hp_targetinfo(unsigned long arg)
if ((rc = mpt_config(ioc, &cfg)) == 0) {
np = le32_to_cpu(pg0_alloc->NegotiatedParameters);
karg.negotiated_width = np & MPI_SCSIDEVPAGE0_NP_WIDE ?
karg.negotiated_width = np & MPI_SCSIDEVPAGE0_NP_WIDE ?
HP_BUS_WIDTH_16 : HP_BUS_WIDTH_8;
if (np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) {
......@@ -2699,7 +2710,7 @@ mptctl_hp_targetinfo(unsigned long arg)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,51)
#define owner_THIS_MODULE owner: THIS_MODULE,
#define owner_THIS_MODULE .owner = THIS_MODULE,
#else
#define owner_THIS_MODULE
#endif
......@@ -2885,6 +2896,8 @@ int __init mptctl_init(void)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) /*{*/
err = register_ioctl32_conversion(MPTIOCINFO, NULL);
if (++where && err) goto out_fail;
err = register_ioctl32_conversion(MPTIOCINFO1, NULL);
if (++where && err) goto out_fail;
err = register_ioctl32_conversion(MPTTARGETINFO, NULL);
if (++where && err) goto out_fail;
err = register_ioctl32_conversion(MPTTEST, NULL);
......@@ -2945,6 +2958,7 @@ int __init mptctl_init(void)
printk(KERN_ERR MYNAM ": ERROR: Failed to register ioctl32_conversion!"
" (%d:err=%d)\n", where, err);
unregister_ioctl32_conversion(MPTIOCINFO);
unregister_ioctl32_conversion(MPTIOCINFO1);
unregister_ioctl32_conversion(MPTTARGETINFO);
unregister_ioctl32_conversion(MPTTEST);
unregister_ioctl32_conversion(MPTEVENTQUERY);
......
......@@ -90,6 +90,7 @@
#endif /*}*/
#define MPTIOCINFO _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo)
#define MPTIOCINFO1 _IOWR(MPT_MAGIC_NUMBER,17,struct mpt_ioctl_iocinfo_rev0)
#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)
......@@ -99,7 +100,7 @@
#define MPTFWREPLACE _IOWR(MPT_MAGIC_NUMBER,25,struct mpt_ioctl_replace_fw)
/*
* SPARC PLATFORM REMARK:
* SPARC PLATFORM REMARKS:
* IOCTL data structures that contain pointers
* will have different sizes in the driver and applications
* (as the app. will not use 8-byte pointers).
......@@ -107,6 +108,8 @@
* The driver will convert data from
* mpt_fw_xfer32 (mpt_ioctl_command32) to mpt_fw_xfer (mpt_ioctl_command)
* internally.
*
* If data structures change size, must handle as in IOCGETINFO.
*/
struct mpt_fw_xfer {
unsigned int iocnum; /* IOC unit number */
......@@ -154,11 +157,11 @@ struct mpt_ioctl_diag_reset {
struct mpt_ioctl_pci_info {
union {
struct {
unsigned long deviceNumber : 5;
unsigned long functionNumber : 3;
unsigned long busNumber : 24;
unsigned int deviceNumber : 5;
unsigned int functionNumber : 3;
unsigned int busNumber : 24;
} bits;
unsigned long asUlong;
unsigned int asUlong;
} u;
};
......@@ -189,6 +192,27 @@ struct mpt_ioctl_iocinfo {
struct mpt_ioctl_pci_info pciInfo; /* Added Rev 1 */
};
/* Original structure, must always accept these
* IOCTLs. 4 byte pads can occur based on arch with
* above structure. Wish to re-align, but cannot.
*/
struct mpt_ioctl_iocinfo_rev0 {
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];
};
/*
* Device Information Page
* Report the number of, and ids of, all targets
......@@ -330,7 +354,7 @@ typedef struct _hp_header {
unsigned int lun;
} hp_header_t;
/*
/*
* Header:
* iocnum required (input)
* host ignored
......@@ -353,12 +377,12 @@ typedef struct _hp_host_info {
u32 bus_phys_width;
u32 base_io_addr;
u32 rsvd;
unsigned long hard_resets; /* driver initiated resets */
unsigned long soft_resets; /* ioc, external resets */
unsigned long timeouts; /* num timeouts */
unsigned int hard_resets; /* driver initiated resets */
unsigned int soft_resets; /* ioc, external resets */
unsigned int timeouts; /* num timeouts */
} hp_host_info_t;
/*
/*
* Header:
* iocnum required (input)
* host required
......
......@@ -154,7 +154,7 @@ static int mpt_lan_open(struct net_device *dev);
static int mpt_lan_reset(struct net_device *dev);
static int mpt_lan_close(struct net_device *dev);
static void mpt_lan_post_receive_buckets(void *dev_id);
static void mpt_lan_wake_post_buckets_task(struct net_device *dev,
static void mpt_lan_wake_post_buckets_task(struct net_device *dev,
int priority);
static int mpt_lan_receive_post_turbo(struct net_device *dev, u32 tmsg);
static int mpt_lan_receive_post_reply(struct net_device *dev,
......@@ -868,7 +868,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static inline void
mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority)
/*
/*
* @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue
*/
{
......@@ -878,8 +878,6 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority)
if (priority) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41)
schedule_work(&priv->post_buckets_task);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,40)
schedule_task(&priv->post_buckets_task);
#else
queue_task(&priv->post_buckets_task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
......@@ -887,8 +885,6 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority)
} else {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41)
schedule_delayed_work(&priv->post_buckets_task, 1);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,40)
schedule_task(&priv->post_buckets_task);
#else
queue_task(&priv->post_buckets_task, &tq_timer);
#endif
......@@ -1191,7 +1187,7 @@ mpt_lan_receive_post_reply(struct net_device *dev,
remaining, atomic_read(&priv->buckets_out));
if ((remaining < priv->bucketthresh) &&
((atomic_read(&priv->buckets_out) - remaining) >
((atomic_read(&priv->buckets_out) - remaining) >
MPT_LAN_BUCKETS_REMAIN_MISMATCH_THRESH)) {
printk (KERN_WARNING MYNAM " Mismatch between driver's "
......@@ -1525,7 +1521,7 @@ mpt_lan_init (void)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
void __init mpt_lan_exit(void)
static void mpt_lan_exit(void)
{
int i;
......@@ -1534,10 +1530,11 @@ void __init mpt_lan_exit(void)
for (i = 0; mpt_landev[i] != NULL; i++) {
struct net_device *dev = mpt_landev[i];
printk (KERN_INFO MYNAM ": %s/%s: Fusion MPT LAN device unregistered\n",
printk (KERN_INFO ": %s/%s: Fusion MPT LAN device unregistered\n",
IOC_AND_NETDEV_NAMES_s_s(dev));
unregister_fcdev(dev);
mpt_landev[i] = (struct net_device *) 0xdeadbeef; /* Debug */
//mpt_landev[i] = (struct net_device *) 0xdeadbeef; /* Debug */
mpt_landev[i] = NULL;
}
if (LanCtx >= 0) {
......@@ -1550,9 +1547,10 @@ void __init mpt_lan_exit(void)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,59)
MODULE_PARM(tx_max_out_p, "i");
MODULE_PARM(max_buckets_out, "i"); // Debug stuff. FIXME!
#endif
module_init(mpt_lan_init);
module_exit(mpt_lan_exit);
......
......@@ -21,11 +21,7 @@
#include <linux/miscdevice.h>
#include <linux/spinlock.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)
#include <linux/tqueue.h>
#else
#include <linux/workqueue.h>
#endif
#include <linux/delay.h>
// #include <linux/trdevice.h>
......
......@@ -78,9 +78,6 @@
#include <linux/reboot.h> /* notifier code */
#include "../../scsi/scsi.h"
#include "../../scsi/hosts.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45)
#include "../../scsi/sd.h"
#endif
#include "mptbase.h"
#include "mptscsih.h"
......@@ -98,7 +95,6 @@ MODULE_LICENSE("GPL");
/* Set string for command line args from insmod */
#ifdef MODULE
char *mptscsih = 0;
MODULE_PARM(mptscsih, "s");
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......@@ -165,11 +161,7 @@ static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
static void mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
static int mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
static void copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
#ifndef MPT_SCSI_USE_NEW_EH
static void search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd);
#else
static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
#endif
static u32 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc);
static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
static void post_pendingQ_commands(MPT_SCSI_HOST *hd);
......@@ -180,11 +172,7 @@ static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun,
static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
static VirtDevice *mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
#ifdef MPT_SAVE_AUTOSENSE
static void clear_sense_flag(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
#endif
static void mptscsih_target_settings(MPT_SCSI_HOST *hd, VirtDevice *target, Scsi_Device *sdev);
static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
......@@ -225,30 +213,8 @@ static int ScsiDoneCtx = -1;
static int ScsiTaskCtx = -1;
static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,28)
static struct proc_dir_entry proc_mpt_scsihost =
{
.low_ino = PROC_SCSI_MPT,
.namelen = 8,
.name = "mptscsih",
.mode = S_IFDIR | S_IRUGO | S_IXUGO,
.nlink = 2,
};
#endif
#define SNS_LEN(scp) sizeof((scp)->sense_buffer)
#ifndef MPT_SCSI_USE_NEW_EH
/*
* Stuff to handle single-threading SCSI TaskMgmt
* (abort/reset) requests...
*/
static spinlock_t mytaskQ_lock = SPIN_LOCK_UNLOCKED;
static int mytaskQ_bh_active = 0;
static struct mpt_work_struct mptscsih_ptaskfoo;
static atomic_t mpt_taskQdepth;
#endif
#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
/*
* Domain Validation task structure
......@@ -307,10 +273,9 @@ mptscsih_io_direction(Scsi_Cmnd *cmd)
break;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN)
return cmd->sc_data_direction;
#endif
switch (cmd->cmnd[0]) {
/* _DATA_OUT commands */
case WRITE_6: case WRITE_10: case WRITE_12:
......@@ -722,9 +687,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
MPT_SCSI_HOST *hd;
SCSIIORequest_t *pScsiReq;
SCSIIOReply_t *pScsiReply;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
unsigned long flags;
#endif
u16 req_idx;
hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
......@@ -739,16 +701,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
sc = hd->ScsiLookup[req_idx];
if (sc == NULL) {
MPIHeader_t *hdr = (MPIHeader_t *)mf;
atomic_dec(&queue_depth);
/* writeSDP1 will use the ScsiDoneCtx
* There is no processing for the reply.
* Just return to the calling function.
/* Remark: writeSDP1 will use the ScsiDoneCtx
* If a SCSI I/O cmd, device disabled by OS and
* completion done. Cannot touch sc struct. Just free mem.
*/
if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n", ioc->name);
atomic_dec(&queue_depth);
mptscsih_freeChainBuffers(hd, req_idx);
return 1;
......@@ -765,25 +722,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
if (pScsiReply == NULL) {
/* special context reply handling */
/* If regular Inquiry cmd - save inquiry data
*/
if (pScsiReq->CDB[0] == INQUIRY && !(pScsiReq->CDB[1] & 0x3)) {
int dlen;
dlen = le32_to_cpu(pScsiReq->DataLength);
if (dlen >= SCSI_STD_INQUIRY_BYTES) {
mptscsih_initTarget(hd,
hd->port,
sc->device->id,
pScsiReq->LUN[1],
sc->buffer,
dlen);
}
}
#ifdef MPT_SAVE_AUTOSENSE
clear_sense_flag(hd, pScsiReq);
#endif
;
} else {
u32 xfer_cnt;
u16 status;
......@@ -792,10 +731,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
scsi_state = pScsiReply->SCSIState;
dprintk((KERN_NOTICE " Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
dsprintk((KERN_NOTICE " Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
mf, mr, sc));
dprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh"
dsprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh"
", SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
status, scsi_state, pScsiReply->SCSIStatus,
le32_to_cpu(pScsiReply->IOCLogInfo)));
......@@ -835,9 +774,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
break;
case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
#ifndef MPT_SCSI_USE_NEW_EH
search_taskQ_for_cmd(sc, hd);
#endif
case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
/* Linux handles an unsolicited DID_RESET better
* than an unsolicited DID_ABORT.
*/
......@@ -848,18 +786,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
mptscsih_no_negotiate(hd, sc->device->id);
break;
case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
#ifndef MPT_SCSI_USE_NEW_EH
search_taskQ_for_cmd(sc, hd);
#endif
sc->result = DID_RESET << 16;
/* GEM Workaround. */
if (hd->is_spi)
mptscsih_no_negotiate(hd, sc->device->id);
break;
case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
/*
......@@ -871,9 +797,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
* precedence!
*/
sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
#ifdef MPT_SAVE_AUTOSENSE
clear_sense_flag(hd, pScsiReq);
#endif
if (scsi_state == 0) {
;
} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
......@@ -897,38 +820,19 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
sc->underflow));
dprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
sc->resid = sc->request_bufflen - xfer_cnt;
dprintk((KERN_NOTICE " SET sc->resid=%02xh\n", sc->resid));
#endif
/* Report Queue Full
*/
if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
/* If regular Inquiry cmd and some data was transferred,
* save inquiry data
*/
if ( pScsiReq->CDB[0] == INQUIRY
&& !(pScsiReq->CDB[1] & 0x3)
&& xfer_cnt >= SCSI_STD_INQUIRY_BYTES
) {
mptscsih_initTarget(hd,
hd->port,
sc->device->id,
pScsiReq->LUN[1],
sc->buffer,
xfer_cnt);
}
break;
case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
#ifdef MPT_SAVE_AUTOSENSE
clear_sense_flag(hd, pScsiReq);
#endif
if (scsi_state == 0) {
;
} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
......@@ -941,26 +845,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
#ifndef MPT_SCSI_USE_NEW_EH
/* ADDED 20011120 -sralston
* Scsi mid-layer (old_eh) doesn't seem to like it
* when RAID returns SCSIStatus=02 (CHECK CONDITION),
* SenseKey=01 (RECOVERED ERROR), ASC/ASCQ=95/01.
* Seems to be * treating this as a IO error:-(
*
* So just lie about it altogether here.
*
* NOTE: It still gets reported to syslog via
* mpt_ScsiHost_ErrorReport from copy_sense_data
* call far above.
*/
if ( pScsiReply->SCSIStatus == STS_CHECK_CONDITION
&& SD_Sense_Key(sc->sense_buffer) == SK_RECOVERED_ERROR
) {
sc->result = 0;
}
#endif
}
else if (scsi_state &
(MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
......@@ -989,22 +873,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
* Reservation Conflict, Busy,
* Command Terminated, CHECK
*/
/* If regular Inquiry cmd - save inquiry data
*/
xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
if ( sc->result == (DID_OK << 16)
&& pScsiReq->CDB[0] == INQUIRY
&& !(pScsiReq->CDB[1] & 0x3)
&& xfer_cnt >= SCSI_STD_INQUIRY_BYTES
) {
mptscsih_initTarget(hd,
hd->port,
sc->device->id,
pScsiReq->LUN[1],
sc->buffer,
xfer_cnt);
}
break;
case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
......@@ -1052,178 +920,15 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
hd->ScsiLookup[req_idx] = NULL;
#ifndef MPT_SCSI_USE_NEW_EH
sc->host_scribble = NULL;
#endif
MPT_HOST_LOCK(flags);
MPT_HOST_LOCK(flags);
sc->scsi_done(sc); /* Issue the command callback */
MPT_HOST_UNLOCK(flags);
MPT_HOST_UNLOCK(flags);
/* Free Chain buffers */
mptscsih_freeChainBuffers(hd, req_idx);
return 1;
}
#ifndef MPT_SCSI_USE_NEW_EH /* { */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* search_taskQ - Search SCSI task mgmt request queue for specific
* request type.
* @remove: (Boolean) Should request be removed if found?
* @sc: Pointer to Scsi_Cmnd structure
* @task_type: Task type to search for
*
* Returns pointer to MPT request frame if found, or %NULL if request
* was not found.
*/
static MPT_FRAME_HDR *
search_taskQ(int remove, Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, u8 task_type)
{
MPT_FRAME_HDR *mf = NULL;
unsigned long flags;
int count = 0;
int list_sz;
dprintk((KERN_INFO MYNAM ": search_taskQ(%d,sc=%p,%d) called\n",
remove, sc, task_type));
spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
list_sz = hd->taskQcnt;
if (! Q_IS_EMPTY(&hd->taskQ)) {
mf = hd->taskQ.head;
do {
count++;
if (mf->u.frame.linkage.argp1 == sc &&
mf->u.frame.linkage.arg1 == task_type) {
if (remove) {
Q_DEL_ITEM(&mf->u.frame.linkage);
hd->taskQcnt--;
atomic_dec(&mpt_taskQdepth);
/* Don't save mf into nextmf because
* exit after command has been deleted.
*/
/* Place the MF back on the FreeQ */
Q_ADD_TAIL(&hd->ioc->FreeQ,
&mf->u.frame.linkage,
MPT_FRAME_HDR);
#ifdef MFCNT
hd->ioc->mfcnt--;
#endif
}
break;
}
} while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&hd->taskQ);
if (mf == (MPT_FRAME_HDR*)&hd->taskQ) {
mf = NULL;
}
}
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
if (list_sz) {
dprintk((KERN_INFO " Results=%p (%sFOUND%s)!\n",
mf,
mf ? "" : "NOT_",
(mf && remove) ? "+REMOVED" : "" ));
dprintk((KERN_INFO " (searched thru %d of %d items on taskQ)\n",
count,
list_sz ));
}
return mf;
}
/*
* clean_taskQ - Clean the SCSI task mgmt request for
* this SCSI host instance.
* @hd: MPT_SCSI_HOST pointer
*
* Returns: None.
*/
static void
clean_taskQ(MPT_SCSI_HOST *hd)
{
MPT_FRAME_HDR *mf = NULL;
MPT_FRAME_HDR *nextmf = NULL;
MPT_ADAPTER *ioc = hd->ioc;
unsigned long flags;
dprintk((KERN_INFO MYNAM ": clean_taskQ called\n"));
spin_lock_irqsave(&ioc->FreeQlock, flags);
if (! Q_IS_EMPTY(&hd->taskQ)) {
mf = hd->taskQ.head;
do {
Q_DEL_ITEM(&mf->u.frame.linkage);
hd->taskQcnt--;
atomic_dec(&mpt_taskQdepth);
nextmf = mf->u.frame.linkage.forw;
/* Place the MF back on the FreeQ */
Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage,
MPT_FRAME_HDR);
#ifdef MFCNT
hd->ioc->mfcnt--;
#endif
} while ((mf = nextmf) != (MPT_FRAME_HDR*)&hd->taskQ);
}
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
return;
}
/*
* search_taskQ_for_cmd - Search the SCSI task mgmt request queue for
* the specified command. If found, delete
* @hd: MPT_SCSI_HOST pointer
*
* Returns: None.
*/
static void
search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd)
{
MPT_FRAME_HDR *mf = NULL;
unsigned long flags;
int count = 0;
dprintk((KERN_INFO MYNAM ": search_taskQ_for_cmd(sc=%p) called\n", sc));
spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
if (! Q_IS_EMPTY(&hd->taskQ)) {
mf = hd->taskQ.head;
do {
count++;
if (mf->u.frame.linkage.argp1 == sc) {
Q_DEL_ITEM(&mf->u.frame.linkage);
hd->taskQcnt--;
atomic_dec(&mpt_taskQdepth);
dprintk((KERN_INFO MYNAM
": Cmd %p found! Deleting.\n", sc));
/* Don't save mf into nextmf because
* exit after command has been deleted.
*/
/* Place the MF back on the FreeQ */
Q_ADD_TAIL(&hd->ioc->FreeQ,
&mf->u.frame.linkage,
MPT_FRAME_HDR);
#ifdef MFCNT
hd->ioc->mfcnt--;
#endif
break;
}
} while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&hd->taskQ);
}
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
return;
}
#endif /* } MPT_SCSI_USE_NEW_EH */
/*
* Flush all commands on the doneQ.
* Lock Q when deleting/adding members
......@@ -1323,24 +1028,13 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
int ii;
int max = hd->ioc->req_depth;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
unsigned long flags;
#endif
dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
for (ii= 0; ii < max; ii++) {
if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
/* Command found.
*/
#ifndef MPT_SCSI_USE_NEW_EH
/* Search taskQ, if found, delete.
*/
search_taskQ_for_cmd(SCpnt, hd);
#endif
/* Search pendingQ, if found,
*
* Search pendingQ, if found,
* delete from Q. If found, do not decrement
* queue_depth, command never posted.
*/
......@@ -1387,6 +1081,57 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
return;
}
/*
* mptscsih_search_running_cmds - Delete any commands associated
* with the specified target and lun. Function called only
* when a lun is disable by mid-layer.
* Do NOT access the referenced Scsi_Cmnd structure or
* members. Will cause either a paging or NULL ptr error.
* @hd: Pointer to a SCSI HOST structure
* @target: target id
* @lun: lun
*
* Returns: None.
*
* Called from slave_destroy.
*/
static void
mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
{
SCSIIORequest_t *mf = NULL;
int ii;
int max = hd->ioc->req_depth;
dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d numIos %d\n",
target, lun, max, atomic_read(&queue_depth)));
for (ii=0; ii < max; ii++) {
if (hd->ScsiLookup[ii] != NULL) {
mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
continue;
/* If cmd pended, do not decrement queue_depth, command never posted.
*/
if (mptscsih_search_pendingQ(hd, ii) == NULL)
atomic_dec(&queue_depth);
/* Cleanup
*/
hd->ScsiLookup[ii] = NULL;
mptscsih_freeChainBuffers(hd, ii);
mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, (MPT_FRAME_HDR *)mf);
}
}
return;
}
#ifdef DROP_TEST
/* mptscsih_flush_drop_test - Free resources and do callback if
* DROP_TEST enabled.
......@@ -1639,10 +1384,6 @@ mptscsih_detect(Scsi_Host_Template *tpnt)
ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
#ifndef MPT_SCSI_USE_NEW_EH
spin_lock_init(&mytaskQ_lock);
#endif
if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n"));
} else {
......@@ -1662,9 +1403,6 @@ mptscsih_detect(Scsi_Host_Template *tpnt)
if (mptscsih)
mptscsih_setup(mptscsih);
#endif
#ifndef MPT_SCSI_USE_NEW_EH
atomic_set(&mpt_taskQdepth, 0);
#endif
this = mpt_adapter_find_first();
while (this != NULL) {
......@@ -1690,9 +1428,6 @@ mptscsih_detect(Scsi_Host_Template *tpnt)
continue;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
tpnt->proc_dir = &proc_mpt_scsihost;
#endif
tpnt->proc_info = mptscsih_proc_info;
sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));
if (sh != NULL) {
......@@ -1723,20 +1458,10 @@ mptscsih_detect(Scsi_Host_Template *tpnt)
}
sh->max_lun = MPT_LAST_LUN + 1;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
sh->max_sectors = MPT_SCSI_MAX_SECTORS;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) || defined CONFIG_HIGHIO
sh->highmem_io = 1;
#endif
sh->this_id = this->pfacts[portnum].PortSCSIID;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
/* OS entry to allow host drivers to force
* a queue depth on a per device basis.
*/
sh->select_queue_depths = mptscsih_select_queue_depths;
#endif
/* Required entry.
*/
sh->unique_id = this->id;
......@@ -1852,9 +1577,7 @@ mptscsih_detect(Scsi_Host_Template *tpnt)
/* Clear the TM flags
*/
hd->tmPending = 0;
#ifdef MPT_SCSI_USE_NEW_EH
hd->tmState = TM_STATE_NONE;
#endif
hd->resetPending = 0;
hd->abortSCpnt = NULL;
hd->tmPtr = NULL;
......@@ -1973,32 +1696,6 @@ mptscsih_release(struct Scsi_Host *host)
hd = (MPT_SCSI_HOST *) host->hostdata;
#ifndef MPT_SCSI_USE_NEW_EH
#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
spin_lock_irqsave(&dvtaskQ_lock, flags);
dvtaskQ_release = 1;
spin_unlock_irqrestore(&dvtaskQ_lock, flags);
#endif
count = 10 * HZ;
spin_lock_irqsave(&mytaskQ_lock, flags);
if (mytaskQ_bh_active) {
spin_unlock_irqrestore(&mytaskQ_lock, flags);
dprintk((KERN_INFO MYNAM ": Info: Zapping TaskMgmt thread!\n"));
clean_taskQ(hd);
while(mytaskQ_bh_active && --count) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
}
} else {
spin_unlock_irqrestore(&mytaskQ_lock, flags);
}
if (!count)
printk(KERN_ERR MYNAM ": ERROR - TaskMgmt thread still active!\n");
#endif
#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
/* Check DV thread active */
count = 10 * HZ;
......@@ -2266,7 +1963,7 @@ static void mptscsih_exec_user_cmd(MPT_ADAPTER *ioc, struct mptscsih_usrcmd *uc)
dma_addr_t cfg_dma_addr = -1;
ConfigPageHeader_t header;
dprintk(("exec_user_command: ioc %p cmd %ld target=%ld\n",
dprintk(("exec_user_command: ioc %p cmd %ld target=%ld\n",
ioc, uc->cmd, uc->target));
switch (uc->cmd) {
......@@ -2329,7 +2026,7 @@ static void mptscsih_exec_user_cmd(MPT_ADAPTER *ioc, struct mptscsih_usrcmd *uc)
printk(" %dMB/sec\n", speed);
} else
} else
printk(" Asynchronous.\n");
} else {
printk("failed\n" );
......@@ -2487,18 +2184,7 @@ int mptscsih_proc_info(char *buffer, char **start, off_t offset,
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static int max_qd = 1;
#if 0
static int index_log[128];
static int index_ent = 0;
static __inline__ void ADD_INDEX_LOG(int req_ent)
{
int i = index_ent++;
index_log[i & (128 - 1)] = req_ent;
}
#else
#define ADD_INDEX_LOG(req_ent) do { } while(0)
#endif
#ifdef DROP_TEST
#define DROP_IOC 1 /* IOC to force failures */
......@@ -2567,7 +2253,6 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
u32 datalen;
u32 scsictl;
u32 scsidir;
u32 qtag;
u32 cmd_len;
int my_idx;
int ii;
......@@ -2586,44 +2271,6 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
#ifdef MPT_SAVE_AUTOSENSE
/* 20000617 -sralston
* GRRRRR... Shouldn't have to do this but...
* Do explicit check for REQUEST_SENSE and cached SenseData.
* If yes, return cached SenseData.
*/
if (SCpnt->cmnd[0] == REQUEST_SENSE) {
u8 *dest = NULL;
int sz;
if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_SENSE)) {
pTarget->tflags &= ~MPT_TARGET_FLAGS_VALID_SENSE; //sjr-moved-here
if (!SCpnt->use_sg) {
dest = SCpnt->request_buffer;
} else {
struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
if (sg)
dest = (u8 *)(ulong)sg_dma_address(sg);
}
if (dest) {
sz = MIN (SCSI_STD_SENSE_BYTES, SCpnt->request_bufflen);
memcpy(dest, pTarget->sense, sz);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
SCpnt->resid = SCpnt->request_bufflen - sz;
#endif
SCpnt->result = 0;
SCpnt->scsi_done(SCpnt);
//sjr-moved-up//pTarget->tflags &= ~MPT_TARGET_FLAGS_VALID_SENSE;
return 0;
}
}
}
#endif
if (hd->resetPending) {
/* Prevent new commands from being issued
* while reloading the FW.
......@@ -2673,22 +2320,13 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
/* Default to untagged. Once a target structure has been allocated,
* use the Inquiry data to determine if device supports tagged.
*/
qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
&& (SCpnt->device->tagged_supported)) {
/*
* Some drives are too stupid to handle fairness issues
* with tagged queueing. We throw in the odd ordered
* tag to stop them starving themselves.
*/
if ((jiffies - hd->qtag_tick) > (5*HZ)) {
qtag = MPI_SCSIIO_CONTROL_ORDEREDQ;
hd->qtag_tick = jiffies;
}
else
qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
if ( pTarget
&& (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
&& (SCpnt->device->tagged_supported)) {
scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
} else {
scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
}
scsictl = scsidir | qtag;
/* Use the above information to set up the message frame
*/
......@@ -3044,10 +2682,6 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort,
}
dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
#ifndef MPT_SCSI_USE_NEW_EH
dtmprintk((MYIOC_s_INFO_FMT "TMHandler: _bh_handler state (%d) taskQ count (%d)\n",
ioc->name, mytaskQ_bh_active, hd->taskQcnt));
#endif
return rc;
}
......@@ -3139,7 +2773,6 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2ab
return retval;
}
#ifdef MPT_SCSI_USE_NEW_EH /* { */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
......@@ -3449,484 +3082,46 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
return status;
}
#else /* MPT_SCSI old EH stuff... */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_old_abort - Abort linux Scsi_Cmnd routine
* @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
* mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
* @ioc: Pointer to MPT_ADAPTER structure
* @mf: Pointer to SCSI task mgmt request frame
* @mr: Pointer to SCSI task mgmt reply frame
*
* (linux Scsi_Host_Template.abort routine)
* This routine is called from mptbase.c::mpt_interrupt() at the completion
* of any SCSI task management request.
* This routine is registered with the MPT (base) driver at driver
* load/init time via the mpt_register() API call.
*
* Returns SCSI_ABORT_{SUCCESS,BUSY,PENDING}.
* Returns 1 indicating alloc'd request frame ptr should be freed.
*/
int
mptscsih_old_abort(Scsi_Cmnd *SCpnt)
static int
mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
{
MPT_SCSI_HOST *hd;
MPT_FRAME_HDR *mf;
struct mpt_work_struct *ptaskfoo;
SCSITaskMgmtReply_t *pScsiTmReply;
SCSITaskMgmt_t *pScsiTmReq;
MPT_SCSI_HOST *hd = NULL;
unsigned long flags;
int scpnt_idx;
printk(KERN_WARNING MYNAM ": OldAbort scheduling ABORT SCSI IO (sc=%p)\n", (void *) SCpnt);
printk(KERN_WARNING " IOs outstanding = %d\n", atomic_read(&queue_depth));
u8 tmType = 0;
if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
printk(KERN_WARNING " WARNING - OldAbort, NULL hostdata ptr!!\n");
SCpnt->result = DID_ERROR << 16;
SCpnt->scsi_done(SCpnt);
return SCSI_ABORT_NOT_RUNNING;
}
if (hd->timeouts < -1)
hd->timeouts++;
if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
/* Cmd not found in ScsiLookup.
* If found in doneQ, delete from Q.
* Do OS callback.
*/
search_doneQ_for_cmd(hd, SCpnt);
SCpnt->result = DID_RESET << 16;
SCpnt->scsi_done(SCpnt);
return SCSI_ABORT_SUCCESS;
} else {
/* If this command is pended, then timeout/hang occurred
* during DV. Force bus reset by posting command to F/W
* and then following up with the reset request.
*/
if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
post_pendingQ_commands(hd);
}
}
/*
* Check to see if there's already an ABORT queued for this guy.
*/
mf = search_taskQ(0, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
if (mf != NULL) {
dtmprintk((MYIOC_s_INFO_FMT "OldAbort:Abort Task PENDING cmd (%p) taskQ depth (%d)\n",
hd->ioc->name, SCpnt, hd->taskQcnt));
return SCSI_ABORT_PENDING;
}
// SJR - CHECKME - Can we avoid this here?
// (mpt_HardResetHandler has this check...)
/* If IOC is reloading FW, return PENDING.
*/
spin_lock_irqsave(&hd->ioc->diagLock, flags);
if (hd->ioc->diagPending) {
spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
return SCSI_ABORT_PENDING;
}
spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
/* If there are no message frames what should we do?
*/
if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
printk((KERN_WARNING " WARNING - OldAbort, no msg frames!!\n"));
/* We are out of message frames!
* Call the reset handler to do a FW reload.
*/
printk((KERN_WARNING " Reloading Firmware!!\n"));
if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
}
return SCSI_ABORT_PENDING;
}
/*
* Add ourselves to (end of) taskQ .
* Check to see if our _bh is running. If NOT, schedule it.
*/
spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
Q_ADD_TAIL(&hd->taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
hd->taskQcnt++;
atomic_inc(&mpt_taskQdepth);
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
spin_lock_irqsave(&mytaskQ_lock, flags);
/* Save the original SCpnt mf pointer
*/
SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx);
/* For the time being, force bus reset on any abort
* requests for the 1030/1035 FW.
*/
if (hd->is_spi)
mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
else
mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
mf->u.frame.linkage.argp1 = SCpnt;
mf->u.frame.linkage.argp2 = (void *) hd;
dtmprintk((MYIOC_s_INFO_FMT "OldAbort:_bh_handler state (%d) taskQ count (%d)\n",
hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt));
if (! mytaskQ_bh_active) {
mytaskQ_bh_active = 1;
spin_unlock_irqrestore(&mytaskQ_lock, flags);
/*
* Oh how cute, no alloc/free/mgmt needed if we use
* (bottom/unused portion of) MPT request frame.
*/
ptaskfoo = (struct mpt_work_struct *) &mptscsih_ptaskfoo;
MPT_INIT_WORK(&mptscsih_ptaskfoo, mptscsih_taskmgmt_bh, (void *) SCpnt);
SCHEDULE_TASK(ptaskfoo);
} else {
spin_unlock_irqrestore(&mytaskQ_lock, flags);
}
return SCSI_ABORT_PENDING;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_old_reset - Perform a SCSI BUS_RESET!
* @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
* @reset_flags: (not used?)
*
* (linux Scsi_Host_Template.reset routine)
*
* Returns SCSI_RESET_{SUCCESS,PUNT,PENDING}.
*/
int
mptscsih_old_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
{
MPT_SCSI_HOST *hd;
MPT_FRAME_HDR *mf;
struct mpt_work_struct *ptaskfoo;
unsigned long flags;
int scpnt_idx;
printk(KERN_WARNING MYNAM ": OldReset scheduling BUS_RESET (sc=%p)\n", (void *) SCpnt);
printk(KERN_WARNING " IOs outstanding = %d\n", atomic_read(&queue_depth));
if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
SCpnt->result = DID_RESET << 16;
SCpnt->scsi_done(SCpnt);
return SCSI_RESET_SUCCESS;
}
if (hd->timeouts < -1)
hd->timeouts++;
if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
/* Cmd not found in ScsiLookup.
* If found in doneQ, delete from Q.
* Do OS callback.
*/
search_doneQ_for_cmd(hd, SCpnt);
SCpnt->result = DID_RESET << 16;
SCpnt->scsi_done(SCpnt);
return SCSI_RESET_SUCCESS;
} else {
/* If this command is pended, then timeout/hang occurred
* during DV. Force bus reset by posting command to F/W
* and then following up with the reset request.
*/
if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
post_pendingQ_commands(hd);
}
}
/*
* Check to see if there's an ABORT_TASK queued for this guy.
* If so, delete.
*/
search_taskQ(1, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
/*
* Check to see if there's already a BUS_RESET queued for this guy.
*/
mf = search_taskQ(0, SCpnt, hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS);
if (mf != NULL) {
dtmprintk((MYIOC_s_INFO_FMT "OldReset:Reset Task PENDING cmd (%p) taskQ depth (%d)\n",
hd->ioc->name, SCpnt, hd->taskQcnt));
return SCSI_RESET_PENDING;
}
// SJR - CHECKME - Can we avoid this here?
// (mpt_HardResetHandler has this check...)
/* If IOC is reloading FW, return PENDING.
*/
spin_lock_irqsave(&hd->ioc->diagLock, flags);
if (hd->ioc->diagPending) {
spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
return SCSI_RESET_PENDING;
}
spin_unlock_irqrestore(&hd->ioc->diagLock, flags);
if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
/* We are out of message frames!
* Call the reset handler to do a FW reload.
*/
printk((KERN_WARNING " Reloading Firmware!!\n"));
if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
}
return SCSI_RESET_PENDING;
}
/*
* Add ourselves to (end of) taskQ.
* Check to see if our _bh is running. If NOT, schedule it.
*/
spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
Q_ADD_TAIL(&hd->taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
hd->taskQcnt++;
atomic_inc(&mpt_taskQdepth);
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
dtmprintk((MYIOC_s_INFO_FMT "OldReset: _bh_handler state (%d) taskQ count (%d)\n",
hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt));
spin_lock_irqsave(&mytaskQ_lock, flags);
/* Save the original SCpnt mf pointer
*/
SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx);
mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
mf->u.frame.linkage.argp1 = SCpnt;
mf->u.frame.linkage.argp2 = (void *) hd;
if (! mytaskQ_bh_active) {
mytaskQ_bh_active = 1;
spin_unlock_irqrestore(&mytaskQ_lock, flags);
/*
* Oh how cute, no alloc/free/mgmt needed if we use
* (bottom/unused portion of) MPT request frame.
*/
ptaskfoo = (struct mpt_work_struct *) &mptscsih_ptaskfoo;
MPT_INIT_WORK(&mptscsih_ptaskfoo, mptscsih_taskmgmt_bh, (void *) SCpnt);
SCHEDULE_TASK(ptaskfoo);
} else {
spin_unlock_irqrestore(&mytaskQ_lock, flags);
}
return SCSI_RESET_PENDING;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptscsih_taskmgmt_bh - SCSI task mgmt bottom half handler
* @sc: (unused)
*
* This routine (thread) is active whenever there are any outstanding
* SCSI task management requests for a SCSI host adapter.
* IMPORTANT! This routine is scheduled therefore should never be
* running in ISR context. i.e., it's safe to sleep here.
*/
void
mptscsih_taskmgmt_bh(void *sc)
{
MPT_ADAPTER *ioc;
Scsi_Cmnd *SCpnt;
MPT_FRAME_HDR *mf = NULL;
MPT_SCSI_HOST *hd;
u32 ctx2abort = 0;
unsigned long flags;
int scpnt_idx;
int did;
u8 task_type;
spin_lock_irqsave(&mytaskQ_lock, flags);
mytaskQ_bh_active = 1;
spin_unlock_irqrestore(&mytaskQ_lock, flags);
do {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/4);
did = 0;
for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
if (ioc->sh) {
hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
if (hd == NULL) {
printk(KERN_ERR MYNAM
": ERROR - TaskMgmt NULL SCSI Host!"
"(ioc=%p, sh=%p hd=%p)\n",
(void *) ioc, (void *) ioc->sh, (void *) hd);
continue;
}
spin_lock_irqsave(&ioc->FreeQlock, flags);
if (Q_IS_EMPTY(&hd->taskQ)) {
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
continue;
}
/* If we ever find a non-empty queue,
* keep the handler alive
*/
did++;
/* tmPending is SMP lock-protected */
if (hd->tmPending || hd->tmPtr) {
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
continue;
}
hd->tmPending = 1;
/* Process this request
*/
mf = hd->taskQ.head;
Q_DEL_ITEM(&mf->u.frame.linkage);
hd->taskQcnt--;
atomic_dec(&mpt_taskQdepth);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
SCpnt = (Scsi_Cmnd*)mf->u.frame.linkage.argp1;
if (SCpnt == NULL) {
printk(KERN_ERR MYNAM ": ERROR - TaskMgmt has NULL SCpnt! (mf=%p:sc=%p)\n",
(void *) mf, (void *) SCpnt);
mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->tmPending = 0;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
continue;
}
/* Get the ScsiLookup index pointer
* from the SC pointer.
*/
if (!SCpnt->host_scribble || ((MPT_SCSI_HOST *)SCpnt->host->hostdata != hd)) {
/* The command associated with the
* abort/reset request must have
* completed and this is a stale
* request. We are done.
* Free the current MF and continue.
*/
mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->tmPending = 0;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
continue;
}
scpnt_idx = MFPTR_2_MPT_INDEX(hd->ioc, SCpnt->host_scribble);
if (scpnt_idx != SCPNT_TO_LOOKUP_IDX(SCpnt)) {
/* Error! this should never happen!!
*/
mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->tmPending = 0;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
continue;
}
task_type = mf->u.frame.linkage.arg1;
ctx2abort = 0;
if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
MPT_FRAME_HDR *SCpntMf;
/*
* Most important! Set TaskMsgContext to SCpnt's MsgContext!
* (the IO to be ABORT'd)
*
* NOTE: Since we do not byteswap MsgContext, we do not
* swap it here either. It is an opaque cookie to
* the controller, so it does not matter. -DaveM
*/
SCpntMf = (MPT_FRAME_HDR *) SCpnt->host_scribble;
ctx2abort = SCpntMf->u.frame.hwhdr.msgctxu.MsgContext;
hd->abortSCpnt = SCpnt;
printk(KERN_WARNING MYNAM ": Attempting ABORT SCSI IO! (mf=%p:sc=%p)\n",
(void *) mf, (void *) SCpnt);
}
/* The TM handler will allocate a new mf,
* so free the current mf.
*/
mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
mf = NULL;
if (mptscsih_TMHandler(hd, task_type, SCpnt->target, SCpnt->lun, ctx2abort, NO_SLEEP) < 0) {
/* The TM request failed and the subsequent FW-reload failed!
* Fatal error case.
*/
printk(KERN_WARNING MYNAM
": WARNING[1] - IOC error processing TaskMgmt request (sc=%p)\n", (void *) SCpnt);
if (hd->ScsiLookup[scpnt_idx] != NULL) {
atomic_dec(&queue_depth);
SCpnt->result = DID_SOFT_ERROR << 16;
MPT_HOST_LOCK(flags);
SCpnt->scsi_done(SCpnt);
MPT_HOST_UNLOCK(flags);
mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
}
spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->tmPending = 0;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
hd->abortSCpnt = NULL;
}
}
}
if (atomic_read(&mpt_taskQdepth) > 0)
did++;
} while ( did );
spin_lock_irqsave(&mytaskQ_lock, flags);
mytaskQ_bh_active = 0;
spin_unlock_irqrestore(&mytaskQ_lock, flags);
return;
}
#endif /* } */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
* @ioc: Pointer to MPT_ADAPTER structure
* @mf: Pointer to SCSI task mgmt request frame
* @mr: Pointer to SCSI task mgmt reply frame
*
* This routine is called from mptbase.c::mpt_interrupt() at the completion
* of any SCSI task management request.
* This routine is registered with the MPT (base) driver at driver
* load/init time via the mpt_register() API call.
*
* Returns 1 indicating alloc'd request frame ptr should be freed.
*/
static int
mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
{
SCSITaskMgmtReply_t *pScsiTmReply;
SCSITaskMgmt_t *pScsiTmReq;
MPT_SCSI_HOST *hd = NULL;
unsigned long flags;
u8 tmType = 0;
dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n",
ioc->name, mf, mr));
if (ioc->sh) {
/* Depending on the thread, a timer is activated for
* the TM request. Delete this timer on completion of TM.
* Decrement count of outstanding TM requests.
*/
hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
if (hd->tmPtr) {
del_timer(&hd->TMtimer);
}
dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n",
ioc->name, hd->taskQcnt));
} else {
dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
ioc->name));
return 1;
dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n",
ioc->name, mf, mr));
if (ioc->sh) {
/* Depending on the thread, a timer is activated for
* the TM request. Delete this timer on completion of TM.
* Decrement count of outstanding TM requests.
*/
hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
if (hd->tmPtr) {
del_timer(&hd->TMtimer);
}
dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n",
ioc->name, hd->taskQcnt));
} else {
dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
ioc->name));
return 1;
}
if (mr == NULL) {
......@@ -3977,19 +3172,6 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
} else {
dtmprintk((KERN_INFO " SCSI TaskMgmt SUCCESS!\n"));
#ifndef MPT_SCSI_USE_NEW_EH
if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
/* clean taskQ - remove tasks associated with
* completed commands.
*/
clean_taskQ(hd);
} else if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
/* If taskQ contains another request
* for this SCpnt, delete this request.
*/
search_taskQ_for_cmd(hd->abortSCpnt, hd);
}
#endif
hd->numTMrequests--;
hd->abortSCpnt = NULL;
flush_doneQ(hd);
......@@ -4005,21 +3187,11 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
mptscsih_flush_drop_test(hd);
#endif
#ifndef MPT_SCSI_USE_NEW_EH
/*
* Signal to _bh thread that we finished.
* This IOC can now process another TM command.
*/
dtmprintk((MYIOC_s_INFO_FMT "taskmgmt_complete: (=%p) done! Num Failed(%d) Task Count (%d)\n",
ioc->name, mf, hd->numTMrequests, hd->taskQcnt));
#endif
hd->tmPtr = NULL;
spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->tmPending = 0;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
#ifdef MPT_SCSI_USE_NEW_EH
hd->tmState = TM_STATE_NONE;
#endif
return 1;
}
......@@ -4029,19 +3201,9 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
* This is anyones guess quite frankly.
*/
int
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)
mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
sector_t capacity, int *ip)
{
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28)
mptscsih_bios_param(Disk * disk, struct block_device *bdev, int *ip)
{
sector_t capacity = disk->capacity;
#else
mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip)
{
unsigned capacity = disk->capacity;
#endif
int size;
size = capacity;
......@@ -4056,87 +3218,307 @@ mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* OS entry point to allow host driver to alloc memory
* for each scsi device. Called once per device the bus scan.
* Return non-zero if allocation fails.
* Init memory once per id (not LUN).
*/
int
mptscsih_slave_alloc(Scsi_Device *device)
{
struct Scsi_Host *host = device->host;
MPT_SCSI_HOST *hd;
VirtDevice *vdev;
hd = (MPT_SCSI_HOST *)host->hostdata;
if (hd == NULL)
return ENODEV;
if ((vdev = hd->Targets[device->id]) == NULL) {
if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) {
printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%d) FAILED!\n",
hd->ioc->name, (int)sizeof(VirtDevice));
return ENOMEM;
} else {
memset(vdev, 0, sizeof(VirtDevice));
rwlock_init(&vdev->VdevLock);
Q_INIT(&vdev->WaitQ, void);
Q_INIT(&vdev->SentQ, void);
Q_INIT(&vdev->DoneQ, void);
vdev->tflags = 0;
vdev->ioc_id = hd->ioc->id;
vdev->target_id = device->id;
vdev->bus_id = hd->port;
hd->Targets[device->id] = vdev;
}
}
vdev->num_luns++;
return 0;
}
/*
* OS entry point to allow for host driver to free allocated memory
* Called if no device present or device being unloaded
*/
void
mptscsih_slave_destroy(Scsi_Device *device)
{
struct Scsi_Host *host = device->host;
MPT_SCSI_HOST *hd;
VirtDevice *vdev;
hd = (MPT_SCSI_HOST *)host->hostdata;
if (hd == NULL)
return;
mptscsih_search_running_cmds(hd, device->id, device->lun);
/* Free memory and reset all flags for this target
*/
if ((vdev = hd->Targets[device->id]) != NULL) {
vdev->num_luns--;
if (vdev->luns & (1 << device->lun))
vdev->luns &= ~(1 << device->lun);
/* Free device structure only if number of luns is 0.
*/
if (vdev->num_luns == 0) {
kfree(hd->Targets[device->id]);
hd->Targets[device->id] = NULL;
if (hd->is_spi) {
hd->ioc->spi_data.dvStatus[device->id] = MPT_SCSICFG_NEGOTIATE;
if (hd->negoNvram == 0)
hd->ioc->spi_data.dvStatus[device->id] |= MPT_SCSICFG_DV_NOT_DONE;
/* Don't alter isRaid, not allowed to move
* volumes on a running system.
*/
if (hd->ioc->spi_data.isRaid & (1 << (device->id)))
hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
}
}
}
return;
}
/*
* OS entry point to adjust the queue_depths on a per-device basis.
* Called once per device the bus scan. Use it to force the queue_depth
* member to 1 if a device does not support Q tags.
* Return non-zero if fails.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52)
int
mptscsih_slave_configure(Scsi_Device *device)
{
struct Scsi_Host *host = device->host;
VirtDevice *pTarget;
VirtDevice *vdev;
MPT_SCSI_HOST *hd;
hd = (MPT_SCSI_HOST *)host->hostdata;
dsprintk((KERN_INFO "slave_configure: device @ %p, id=%d, LUN=%d, channel=%d\n",
device, device->id, device->lun, device->channel));
dsprintk((KERN_INFO "sdtr %d wdtr %d ppr %d inq length=%d\n",
device->sdtr, device->wdtr, device->ppr, device->inquiry_len));
dsprintk(("tagged %d queue %d simple %d ordered %d\n",
device->tagged_supported, device->tagged_queue,
device->simple_tags, device->ordered_tags));
/* set target parameters, queue depths, set dv flags ? */
if (hd && (hd->Targets != NULL)) {
pTarget = hd->Targets[device->id];
if (pTarget) {
vdev = hd->Targets[device->id];
if (vdev && !(vdev->tflags & MPT_TARGET_FLAGS_CONFIGURED)) {
/* Configure only the first discovered LUN
*/
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));
}
mptscsih_target_settings(hd, vdev, device);
vdev->tflags |= MPT_TARGET_FLAGS_CONFIGURED;
}
if (vdev) {
/* set the queue depth for all devices
*/
if (!device->tagged_supported ||
!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) {
!(vdev->tflags & MPT_TARGET_FLAGS_Q_YES)) {
scsi_adjust_queue_depth(device, 0, 1);
} else if ((pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)
&& (pTarget->inq_data[0] & 0x1f) == 0x00
&& (pTarget->minSyncFactor <= MPT_ULTRA160 || !hd->is_spi)) {
} else if (vdev->type == 0x00
&& (vdev->minSyncFactor <= MPT_ULTRA160 || !hd->is_spi)) {
scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
MPT_SCSI_CMD_PER_DEV_HIGH);
} else {
scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
MPT_SCSI_CMD_PER_DEV_LOW);
scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
MPT_SCSI_CMD_PER_DEV_LOW);
}
vdev->luns |= (1 << device->lun);
vdev->tflags |= MPT_TARGET_FLAGS_CONFIGURED;
}
}
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Update the target negotiation parameters based on the
* the Inquiry data, adapter capabilities, and NVRAM settings.
*
*/
static void
mptscsih_target_settings(MPT_SCSI_HOST *hd, VirtDevice *target, Scsi_Device *sdev)
{
ScsiCfgData *pspi_data = &hd->ioc->spi_data;
int id = (int) target->target_id;
int nvram;
u8 width = MPT_NARROW;
u8 factor = MPT_ASYNC;
u8 offset = 0;
u8 nfactor;
u8 noQas = 1;
ddvtprintk((KERN_INFO "set Target: (id %d) \n", id));
if (!hd->is_spi) {
/* FC - only care about QTag support
*/
if (sdev->tagged_supported)
target->tflags |= MPT_TARGET_FLAGS_Q_YES;
return;
}
/* SCSI - Set flags based on Inquiry data
*/
if (sdev->scsi_level < 2) {
width = 0;
factor = MPT_ULTRA2;
offset = pspi_data->maxSyncOffset;
} else {
width = sdev->wdtr;
if (sdev->sdtr) {
if (sdev->ppr) {
/* U320 requires IU capability */
if ((sdev->inquiry_len > 56) && (sdev->inquiry[56] & 0x01))
factor = MPT_ULTRA320;
else
factor = MPT_ULTRA160;
} else
factor = MPT_ULTRA2;
/* If RAID, never disable QAS
* else if non RAID, do not disable
* QAS if bit 1 is set
* bit 1 QAS support, non-raid only
* bit 0 IU support
*/
if ((target->raidVolume == 1) ||
((sdev->inquiry_len > 56) && (sdev->inquiry[56] & 0x02)))
noQas = 0;
offset = pspi_data->maxSyncOffset;
} else {
factor = MPT_ASYNC;
offset = 0;
}
}
/* Update tflags based on NVRAM settings. (SCSI only)
*/
if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
nvram = pspi_data->nvram[id];
nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
if (width)
width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
if (offset > 0) {
/* Ensure factor is set to the
* maximum of: adapter, nvram, inquiry
*/
if (nfactor) {
if (nfactor < pspi_data->minSyncFactor )
nfactor = pspi_data->minSyncFactor;
factor = MAX (factor, nfactor);
if (factor == MPT_ASYNC)
offset = 0;
} else {
offset = 0;
factor = MPT_ASYNC;
}
}
} else
factor = MPT_ASYNC;
}
return 0;
}
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52) */
void
mptscsih_select_queue_depths(struct Scsi_Host *sh, Scsi_Device *sdList)
{
struct scsi_device *device;
VirtDevice *pTarget;
MPT_SCSI_HOST *hd;
int ii, max;
for (device = sdList; device != NULL; device = device->next) {
/* Make sure data is consistent
*/
if ((!width) && (factor < MPT_ULTRA2))
factor = MPT_ULTRA2;
/* Save the data to the target structure.
*/
target->minSyncFactor = factor;
target->maxOffset = offset;
target->maxWidth = width;
if (sdev->tagged_supported)
target->tflags |= MPT_TARGET_FLAGS_Q_YES;
if (device->host != sh)
continue;
/* Disable unused features.
*/
target->negoFlags = pspi_data->noQas;
if (!width)
target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
hd = (MPT_SCSI_HOST *) sh->hostdata;
if (hd == NULL)
continue;
if (!offset)
target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
if (hd->Targets != NULL) {
if (hd->is_spi)
max = MPT_MAX_SCSI_DEVICES;
else
max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
if (noQas)
target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
for (ii=0; ii < max; ii++) {
pTarget = hd->Targets[ii];
if (pTarget == NULL) {
continue;
}
if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) {
device->queue_depth = 1;
} else if ((pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)
&& (pTarget->inq_data[0] & 0x1f) == 0x00
&& (pTarget->minSyncFactor <= MPT_ULTRA160 || !hd->is_spi)) {
device->queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
} else {
device->queue_depth = MPT_SCSI_CMD_PER_DEV_LOW;
}
dprintk((MYIOC_s_INFO_FMT
"target = %d, sync factor = %#x, queue depth = %d\n",
hd->ioc->name, pTarget->target_id,
pTarget->minSyncFactor, device->queue_depth));
}
/* GEM, processor WORKAROUND
*/
target->type = sdev->inquiry[0] & 0x1F;
if ((target->type == 0x03) || (target->type > 0x08)){
target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
}
/* Disable QAS if mixed configuration case
*/
if ((noQas) && (!pspi_data->noQas) && (target->type == 0x00)){
VirtDevice *vdev;
int ii;
ddvtprintk((KERN_INFO "Disabling QAS!\n"));
pspi_data->noQas = MPT_TARGET_NO_NEGO_QAS;
for (ii = 0; ii < id; ii++) {
vdev = hd->Targets[id];
if (vdev != NULL)
vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
}
}
ddvtprintk((KERN_INFO "Final settings id %d: dvstatus 0x%x\n", sdev->id, pspi_data->dvStatus[id]));
ddvtprintk(("wide %d, factor 0x%x offset 0x%x neg flags 0x%x flags 0x%x\n",
width, factor, offset, target->negoFlags, target->tflags));
return;
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52) */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
......@@ -4175,34 +3557,6 @@ copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply
sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
/* save sense data to the target device
*/
if (target) {
#ifdef MPT_SAVE_AUTOSENSE
int sz;
sz = MIN(pReq->SenseBufferLength, sense_count);
if (sz > SCSI_STD_SENSE_BYTES)
sz = SCSI_STD_SENSE_BYTES;
memcpy(target->sense, sense_data, sz);
target->tflags |= MPT_TARGET_FLAGS_VALID_SENSE;
#endif
#ifdef ABORT_FIX
if (sz >= SCSI_STD_SENSE_BYTES) {
if ((sense_data[02] == ABORTED_COMMAND) &&
(sense_data[12] == 0x47) && (sense_data[13] == 0x00)){
target->numAborts++;
if ((target->raidVolume == 0) && (target->numAborts > 5)) {
target->numAborts = 0;
target->minSyncFactor++;
hd->ioc->spi_data.dvStatus[index] |= MPT_SCSICFG_NEGOTIATE;
}
}
}
#endif
}
/* Log SMART data (asc = 0x5D, non-IM case only) if required.
*/
if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
......@@ -4440,13 +3794,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
mpt_free_msg_frame(ScsiTaskCtx, ioc->id, hd->tmPtr);
}
#ifndef MPT_SCSI_USE_NEW_EH
/* 2e. Delete all commands on taskQ
* Should be superfluous - as this taskQ should
* be empty.
*/
clean_taskQ(hd);
#endif
dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset handling complete.\n",
ioc->name));
......@@ -4489,9 +3836,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
hd->resetPending = 0;
hd->numTMrequests = 0;
#ifdef MPT_SCSI_USE_NEW_EH
hd->tmState = TM_STATE_NONE;
#endif
/* 6. If there was an internal command,
* wake this process up.
......@@ -4517,8 +3862,10 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
/* 8. Set flag to force DV and re-read IOC Page 3
*/
ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
ddvtprintk(("Set reload IOC Pg3 Flag\n"));
if (hd->is_spi) {
ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
ddvtprintk(("Set reload IOC Pg3 Flag\n"));
}
}
......@@ -4642,22 +3989,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
return 1; /* currently means nothing really */
}
#if 0 /* { */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* scsiherr.c - Fusion MPT SCSI Host driver error handling/reporting.
*
* drivers/message/fusion/scsiherr.c
*/
//extern const char **mpt_ScsiOpcodesPtr; /* needed by mptscsih.c */
//extern ASCQ_Table_t *mpt_ASCQ_TablePtr;
//extern int mpt_ASCQ_TableSz;
#define MYNAM "mptscsih"
#endif /* } */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Private data...
......@@ -4688,44 +4019,6 @@ static u8 dummyScsiData[16]
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
#if 0
static const char *PeripheralDeviceTypeString[32] = {
"Direct-access", /* 00h */
"Sequential-access", /* 01h */
"Printer", /* 02h */
"Processor", /* 03h */
/*"Write-Once-Read-Multiple",*/ /* 04h */
"WORM", /* 04h */
"CD-ROM", /* 05h */
"Scanner", /* 06h */
"Optical memory", /* 07h */
"Media Changer", /* 08h */
"Communications", /* 09h */
"(Graphics arts pre-press)", /* 0Ah */
"(Graphics arts pre-press)", /* 0Bh */
"Array controller", /* 0Ch */
"Enclosure services", /* 0Dh */
"Simplified direct-access", /* 0Eh */
"Reserved-0Fh", /* 0Fh */
"Reserved-10h", /* 10h */
"Reserved-11h", /* 11h */
"Reserved-12h", /* 12h */
"Reserved-13h", /* 13h */
"Reserved-14h", /* 14h */
"Reserved-15h", /* 15h */
"Reserved-16h", /* 16h */
"Reserved-17h", /* 17h */
"Reserved-18h", /* 18h */
"Reserved-19h", /* 19h */
"Reserved-1Ah", /* 1Ah */
"Reserved-1Bh", /* 1Bh */
"Reserved-1Ch", /* 1Ch */
"Reserved-1Dh", /* 1Dh */
"Reserved-1Eh", /* 1Eh */
"Unknown" /* 1Fh */
};
#endif
static char *ScsiStatusString[] = {
"GOOD", /* 00h */
NULL, /* 01h */
......@@ -4825,52 +4118,6 @@ static const char *SenseKeyString[] = {
#define SPECIAL_ASCQ(c,q) \
(((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
#if 0
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Sense_Key_Specific() - If Sense_Key_Specific_Valid bit is set,
* then print additional information via
* a call to SDMS_SystemAlert().
*/
static void Sense_Key_Specific(IO_Info_t *ioop, char *msg1)
{
u8 *sd;
u8 BadValue;
u8 SenseKey;
int Offset;
int len = strlen(msg1);
sd = ioop->sensePtr;
if (SD_Additional_Sense_Length(sd) < 8)
return;
SenseKey = SD_Sense_Key(sd);
if (SD_Sense_Key_Specific_Valid(sd)) {
if (SenseKey == SK_ILLEGAL_REQUEST) {
Offset = SD_Bad_Byte(sd);
if (SD_Was_Illegal_Request(sd)) {
BadValue = ioop->cdbPtr[Offset];
len += sprintf(msg1+len, "\n Illegal CDB value=%02Xh found at CDB ",
BadValue);
} else {
BadValue = ioop->dataPtr[Offset];
len += sprintf(msg1+len, "\n Illegal DATA value=%02Xh found at DATA ",
BadValue);
}
len += sprintf(msg1+len, "byte=%02Xh", Offset);
if (SD_SKS_Bit_Pointer_Valid(sd))
len += sprintf(msg1+len, "/bit=%1Xh", SD_SKS_Bit_Pointer(sd));
} else if ((SenseKey == SK_RECOVERED_ERROR) ||
(SenseKey == SK_HARDWARE_ERROR) ||
(SenseKey == SK_MEDIUM_ERROR)) {
len += sprintf(msg1+len, "\n Recovery algorithm Actual_Retry_Count=%02Xh",
SD_Actual_Retry_Count(sd));
}
}
}
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static int dump_cdb(char *foo, unsigned char *cdb)
{
......@@ -4894,21 +4141,6 @@ static int dump_cdb(char *foo, unsigned char *cdb)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#if 0
static int dump_sd(char *foo, unsigned char *sd)
{
int snsLen = 8 + SD_Additional_Sense_Length(sd);
int l = 0;
int i;
for (i=0; i < MIN(snsLen,18); i++)
l += sprintf(foo+l, " %02X", sd[i]);
l += sprintf(foo+l, "%s", snsLen>18 ? " ..." : "");
return l;
}
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* Do ASC/ASCQ lookup/grindage to English readable string(s) */
static const char * ascq_set_strings_4max(
......@@ -5141,269 +4373,6 @@ int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptscsih_initTarget - Target, LUN alloc/free functionality.
* @hd: Pointer to MPT_SCSI_HOST structure
* @bus_id: Bus number (?)
* @target_id: SCSI target id
* @lun: SCSI LUN id
* @data: Pointer to data
* @dlen: Number of INQUIRY bytes
*
* NOTE: It's only SAFE to call this routine if data points to
* sane & valid STANDARD INQUIRY data!
*
* Allocate and initialize memory for this target.
* Save inquiry data.
*
* Returns pointer to VirtDevice structure.
*/
static VirtDevice *
mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
{
VirtDevice *vdev;
int sz;
dprintk((MYIOC_s_INFO_FMT "initTarget (%d,%d,%d) called, hd=%p\n",
hd->ioc->name, bus_id, target_id, lun, hd));
if ((vdev = hd->Targets[target_id]) == NULL) {
if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) {
printk(MYIOC_s_ERR_FMT "initTarget kmalloc(%d) FAILED!\n",
hd->ioc->name, (int)sizeof(VirtDevice));
} else {
memset(vdev, 0, sizeof(VirtDevice));
rwlock_init(&vdev->VdevLock);
Q_INIT(&vdev->WaitQ, void);
Q_INIT(&vdev->SentQ, void);
Q_INIT(&vdev->DoneQ, void);
vdev->tflags = 0;
vdev->ioc_id = hd->ioc->id;
vdev->target_id = target_id;
vdev->bus_id = bus_id;
hd->Targets[target_id] = vdev;
dprintk((KERN_INFO " *NEW* Target structure (id %d) @ %p\n",
target_id, vdev));
}
}
if (vdev) {
if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
vdev->raidVolume = 1;
ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
} else
vdev->raidVolume = 0;
}
if (vdev && data) {
if ((!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) ||
((dlen > 56) && (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56)))) {
/* Copy the inquiry data - if we haven't yet.
*/
sz = MIN(dlen, SCSI_STD_INQUIRY_BYTES);
memcpy (vdev->inq_data, data, sz);
vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
/* Update the target capabilities
*/
if (dlen > 56) {
mptscsih_setTargetNegoParms(hd, vdev, data[56]);
vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
} else
mptscsih_setTargetNegoParms(hd, vdev, 0);
/* If LUN 0, tape and have not done DV, set the DV flag.
*/
if ((lun == 0) && ((data[0] & 0x1F) == 0x01)) {
ScsiCfgData *pSpi = &hd->ioc->spi_data;
if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
}
}
/* Is LUN supported? If so, upper 3 bits will be 0
* in first byte of inquiry data.
*/
if ((*data & 0xe0) == 0)
vdev->luns |= (1 << lun);
}
dprintk((KERN_INFO " target = %p\n", vdev));
return vdev;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Update the target negotiation parameters based on the
* the Inquiry data, adapter capabilities, and NVRAM settings.
*
*/
void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
{
ScsiCfgData *pspi_data = &hd->ioc->spi_data;
int id = (int) target->target_id;
int nvram;
char canQ = 0;
u8 width = MPT_NARROW;
u8 factor = MPT_ASYNC;
u8 offset = 0;
u8 version, nfactor;
u8 noQas = 1;
ddvtprintk((KERN_INFO "set Target: (id %d) byte56 0x%x\n", id, byte56));
/* Set flags based on Inquiry data
*/
if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
version = target->inq_data[2] & 0x07;
if (version < 2) {
width = 0;
factor = MPT_ULTRA2;
offset = pspi_data->maxSyncOffset;
} else {
if (target->inq_data[7] & 0x20) {
width = 1;
}
if (target->inq_data[7] & 0x10) {
/* bits 2 & 3 show DT support
*/
if ((byte56 & 0x04) == 0)
factor = MPT_ULTRA2;
else if ((byte56 & 0x03) == 0)
factor = MPT_ULTRA160;
else
factor = MPT_ULTRA320;
/* If RAID, never disable QAS
* else if non RAID, do not disable
* QAS if bit 1 is set
* bit 1 QAS support, non-raid only
* bit 0 IU support
*/
if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0))
noQas = 0;
offset = pspi_data->maxSyncOffset;
} else {
factor = MPT_ASYNC;
offset = 0;
}
}
if (target->inq_data[7] & 0x02) {
canQ = 1;
}
/* Update tflags based on NVRAM settings. (SCSI only)
*/
if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
nvram = pspi_data->nvram[id];
nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
if (width)
width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
if (offset > 0) {
/* Ensure factor is set to the
* maximum of: adapter, nvram, inquiry
*/
if (nfactor) {
if (nfactor < pspi_data->minSyncFactor )
nfactor = pspi_data->minSyncFactor;
factor = MAX (factor, nfactor);
if (factor == MPT_ASYNC)
offset = 0;
} else {
offset = 0;
factor = MPT_ASYNC;
}
} else {
factor = MPT_ASYNC;
}
}
/* Make sure data is consistent
*/
if ((!width) && (factor < MPT_ULTRA2)) {
factor = MPT_ULTRA2;
}
/* Save the data to the target structure.
*/
target->minSyncFactor = factor;
target->maxOffset = offset;
target->maxWidth = width;
if (canQ) {
target->tflags |= MPT_TARGET_FLAGS_Q_YES;
}
target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
/* Disable unused features.
*/
target->negoFlags = pspi_data->noQas;
if (!width)
target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
if (!offset)
target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
if (noQas)
target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
/* GEM, processor WORKAROUND
*/
if (((target->inq_data[0] & 0x1F) == 0x03) || ((target->inq_data[0] & 0x1F) > 0x08)){
target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
}
/* Disable QAS if mixed configuration case
*/
if ((noQas) && (!pspi_data->noQas) && ((target->inq_data[0] & 0x1F) == 0x00)){
VirtDevice *vdev;
int ii;
ddvtprintk((KERN_INFO "Disabling QAS!\n"));
pspi_data->noQas = MPT_TARGET_NO_NEGO_QAS;
for (ii = 0; ii < id; ii++) {
vdev = hd->Targets[id];
if (vdev != NULL)
vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
}
}
}
return;
}
#ifdef MPT_SAVE_AUTOSENSE
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Clear sense valid flag.
*/
static void clear_sense_flag(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
{
VirtDevice *target;
int index = (int) pReq->TargetID;
if ((target = hd->Targets[index])) {
target->tflags &= ~MPT_TARGET_FLAGS_VALID_SENSE;
}
return;
}
#endif
/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
* Else set the NEED_DV flag after Read Capacity Issued (disks)
* or Mode Sense (cdroms).
......@@ -5442,14 +4411,16 @@ static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* If no Target, bus reset on 1st I/O. Set the flag to
* prevent any future negotiations to this device.
* If no Target (old) or Target unconfigured (new) and bus reset on 1st I/O,
* set the flag to prevent any future negotiations to this device.
*/
static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
{
if ((hd->Targets) && (hd->Targets[target_id] == NULL))
hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
if (hd->Targets) {
VirtDevice *vdev = hd->Targets[target_id];
if ((vdev == NULL) || !(vdev->tflags & MPT_TARGET_FLAGS_CONFIGURED))
hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
}
return;
}
......@@ -5615,7 +4586,8 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
/* If id is not a raid volume, get the updated
* transmission settings from the target structure.
*/
if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume
&& (pTarget->tflags & MPT_TARGET_FLAGS_CONFIGURED)) {
width = pTarget->maxWidth;
factor = pTarget->minSyncFactor;
offset = pTarget->maxOffset;
......@@ -5691,7 +4663,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
pData->Reserved = 0;
pData->Configuration = cpu_to_le32(configuration);
dprintk((MYIOC_s_INFO_FMT
dsprintk((MYIOC_s_INFO_FMT
"write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
ioc->name, id, (id | (bus<<8)),
requested, configuration));
......@@ -5726,9 +4698,7 @@ static void mptscsih_taskmgmt_timeout(unsigned long data)
*/
if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
}
#ifdef MPT_SCSI_USE_NEW_EH
else {
} else {
/* Because we have reset the IOC, no TM requests can be
* pending. So let's make sure the tmPending flag is reset.
*/
......@@ -5737,7 +4707,6 @@ static void mptscsih_taskmgmt_timeout(unsigned long data)
hd->ioc->name));
hd->tmPending = 0;
}
#endif
return;
}
......@@ -5805,10 +4774,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
/* If target struct exists, clear sense valid flag.
*/
#ifdef MPT_SAVE_AUTOSENSE
clear_sense_flag(hd, pReq);
#endif
if (mr == NULL) {
completionCode = MPT_SCANDV_GOOD;
} else {
......@@ -5859,9 +4824,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
completionCode = MPT_SCANDV_SOME_ERROR;
} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
#ifdef MPT_SAVE_AUTOSENSE
VirtDevice *target;
#endif
u8 *sense_data;
int sz;
......@@ -5876,15 +4838,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
SCSI_STD_SENSE_BYTES);
memcpy(hd->pLocal->sense, sense_data, sz);
#ifdef MPT_SAVE_AUTOSENSE
target = hd->Targets[pReq->TargetID];
if (target) {
memcpy(target->sense, sense_data, sz);
target->tflags
|= MPT_TARGET_FLAGS_VALID_SENSE;
}
#endif
ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
sense_data));
} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
......@@ -5949,10 +4902,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
static void mptscsih_timer_expired(unsigned long data)
{
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
#ifndef MPT_SCSI_USE_NEW_EH
unsigned long flags;
#endif
ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
......@@ -5966,22 +4915,7 @@ static void mptscsih_timer_expired(unsigned long data)
* If new eh code, do nothing. Wait for OS cmd timeout
* for bus reset.
*/
#ifndef MPT_SCSI_USE_NEW_EH
spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
if (hd->tmPending) {
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
return;
} else
hd->tmPending = 1;
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
0, 0, 0, NO_SLEEP) < 0) {
printk(MYIOC_s_WARN_FMT "TM FAILED!\n", hd->ioc->name);
}
#else
ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
#endif
} else {
/* Perform a FW reload */
if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
......@@ -6440,7 +5374,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
/* If target Ptr NULL or if this target is NOT a disk, skip.
*/
// if (pTarget && ((pTarget->inq_data[0] & 0x1F) == 0)) {
if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
for (lun=0; lun <= MPT_LAST_LUN; lun++) {
/* If LUN present, issue the command
......@@ -6768,11 +5701,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
iocmd.rsvd = iocmd.rsvd2 = 0;
pTarget = hd->Targets[id];
if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_CONFIGURED)) {
/* Another GEM workaround. Check peripheral device type,
* if PROCESSOR, quit DV.
*/
if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) {
if ((pTarget->type == 0x03) || (pTarget->type > 0x08)) {
pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
return 0;
}
......@@ -6853,6 +5786,14 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
dv.cmd = MPT_SET_MAX;
mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
cfg.hdr = &header1;
/* Double writes to SDP1 can cause problems,
* skip save of the final negotiated settings to
* SCSI device page 1.
*/
cfg.physAddr = cfg1_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
mpt_config(hd->ioc, &cfg);
goto target_done;
}
......@@ -7491,19 +6432,16 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
dv.cmd = MPT_SAVE;
mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
#if 0
/* Double writes to SDP1 can cause problems,
* skip here since unnecessary
*/
/* Save the final negotiated settings to
/* Double writes to SDP1 can cause problems,
* skip save of the final negotiated settings to
* SCSI device page 1.
*/
*
cfg.hdr = &header1;
cfg.physAddr = cfg1_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
mpt_config(hd->ioc, &cfg);
#endif
*/
}
/* If this is a RAID Passthrough, enable internal IOs
......
......@@ -72,7 +72,7 @@
/*
* Try to keep these at 2^N-1
*/
#define MPT_FC_CAN_QUEUE 63
#define MPT_FC_CAN_QUEUE 127
#if defined MPT_SCSI_USE_NEW_EH
#define MPT_SCSI_CAN_QUEUE 127
#else
......@@ -148,59 +148,18 @@ struct mptscsih_driver_setup
* Issue discovered 20001213 by: sshirron
*/
#define MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS 1
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,0)
# if LINUX_VERSION_CODE == KERNEL_VERSION(2,4,0)
/*
* Super HACK! -by sralston:-(
* (good grief; heaven help me!)
*/
# include <linux/capability.h>
# if !defined(CAP_LEASE) && !defined(MODULE)
# undef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS
# endif
# else
# ifndef MODULE
# undef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS
# endif
# endif
#endif
/*
* tq_scheduler disappeared @ lk-2.4.0-test12
* (right when <linux/sched.h> newly defined TQ_ACTIVE)
* tq_struct reworked in 2.5.41. Include workqueue.h.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41)
# include <linux/sched.h>
# include <linux/workqueue.h>
#define SCHEDULE_TASK(x) \
if (schedule_work(x) == 0) { \
/*MOD_DEC_USE_COUNT*/; \
}
#else
#define HAVE_TQ_SCHED 1
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
# include <linux/sched.h>
# ifdef TQ_ACTIVE
# undef HAVE_TQ_SCHED
# endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,40)
# undef HAVE_TQ_SCHED
#endif
#endif
#ifdef HAVE_TQ_SCHED
#define SCHEDULE_TASK(x) \
/*MOD_INC_USE_COUNT*/; \
(x)->next = NULL; \
queue_task(x, &tq_scheduler)
#else
#define SCHEDULE_TASK(x) \
/*MOD_INC_USE_COUNT*/; \
if (schedule_task(x) == 0) { \
/*MOD_DEC_USE_COUNT*/; \
}
#endif
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......@@ -217,11 +176,9 @@ struct mptscsih_driver_setup
#define x_scsi_taskmgmt_bh mptscsih_taskmgmt_bh
#define x_scsi_old_abort mptscsih_old_abort
#define x_scsi_old_reset mptscsih_old_reset
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52)
#define x_scsi_slave_alloc mptscsih_slave_alloc
#define x_scsi_slave_configure mptscsih_slave_configure
#else
#define x_scsi_select_queue_depths mptscsih_select_queue_depths
#endif
#define x_scsi_slave_destroy mptscsih_slave_destroy
#define x_scsi_proc_info mptscsih_proc_info
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......@@ -232,41 +189,19 @@ 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 *));
#ifdef MPT_SCSI_USE_NEW_EH
extern int x_scsi_abort(Scsi_Cmnd *);
extern int x_scsi_bus_reset(Scsi_Cmnd *);
extern int x_scsi_dev_reset(Scsi_Cmnd *);
extern int x_scsi_host_reset(Scsi_Cmnd *);
#else
extern int x_scsi_old_abort(Scsi_Cmnd *);
extern int x_scsi_old_reset(Scsi_Cmnd *, unsigned int);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)
extern int x_scsi_bios_param(struct scsi_device * sdev, struct block_device *bdev,
sector_t capacity, int *ip);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28)
extern int x_scsi_bios_param(Disk *, struct block_device *, int *);
#else
extern int x_scsi_bios_param(Disk *, kdev_t, int *);
#endif
extern void x_scsi_taskmgmt_bh(void *);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52)
extern int x_scsi_slave_alloc(Scsi_Device *);
extern int x_scsi_slave_configure(Scsi_Device *);
#else
extern void x_scsi_select_queue_depths(struct Scsi_Host *, Scsi_Device *);
#endif
extern void x_scsi_slave_destroy(Scsi_Device *);
extern int x_scsi_proc_info(char *, char **, off_t, int, int, int);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
#define PROC_SCSI_DECL
#else
#define PROC_SCSI_DECL proc_name: "mptscsih",
#endif
#ifdef MPT_SCSI_USE_NEW_EH
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52)
#define PROC_SCSI_DECL .proc_name = "mptscsih",
#define MPT_SCSIHOST { \
PROC_SCSI_DECL \
......@@ -277,7 +212,9 @@ extern int x_scsi_proc_info(char *, char **, off_t, int, int, int);
.info = x_scsi_info, \
.command = NULL, \
.queuecommand = x_scsi_queuecommand, \
.slave_alloc = x_scsi_slave_alloc, \
.slave_configure = x_scsi_slave_configure, \
.slave_destroy = x_scsi_slave_destroy, \
.eh_strategy_handler = NULL, \
.eh_abort_handler = x_scsi_abort, \
.eh_device_reset_handler = x_scsi_dev_reset, \
......@@ -293,58 +230,6 @@ extern int x_scsi_proc_info(char *, char **, off_t, int, int, int);
.use_clustering = ENABLE_CLUSTERING, \
}
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) */
#define MPT_SCSIHOST { \
.next = NULL, \
PROC_SCSI_DECL \
.proc_info = x_scsi_proc_info, \
.name = "MPT SCSI Host", \
.detect = x_scsi_detect, \
.release = x_scsi_release, \
.info = x_scsi_info, \
.command = NULL, \
.queuecommand = x_scsi_queuecommand, \
.eh_strategy_handler = NULL, \
.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 = NULL, \
.bios_param = x_scsi_bios_param, \
.can_queue = MPT_SCSI_CAN_QUEUE, \
.this_id = -1, \
.sg_tablesize = MPT_SCSI_SG_DEPTH, \
.cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \
.unchecked_isa_dma = 0, \
.use_clustering = ENABLE_CLUSTERING, \
.use_new_eh_code = 1 \
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) */
#else /* MPT_SCSI_USE_NEW_EH */
#define MPT_SCSIHOST { \
.next = NULL, \
PROC_SCSI_DECL \
.name = "MPT SCSI Host", \
.detect = x_scsi_detect, \
.release = x_scsi_release, \
.info = x_scsi_info, \
.command = NULL, \
.queuecommand = x_scsi_queuecommand, \
.abort = x_scsi_old_abort, \
.reset = x_scsi_old_reset, \
.bios_param = x_scsi_bios_param, \
.can_queue = MPT_SCSI_CAN_QUEUE, \
.this_id = -1, \
.sg_tablesize = MPT_SCSI_SG_DEPTH, \
.cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \
.unchecked_isa_dma = 0, \
.use_clustering = ENABLE_CLUSTERING \
}
#endif /* MPT_SCSI_USE_NEW_EH */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......
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