summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorPam Delaney <pdelaney@lsil.com>2002-12-31 19:56:26 -0800
committerChristoph Hellwig <hch@lst.de>2002-12-31 19:56:26 -0800
commit17bb4650aed90b1c071a27a9b8daa88ca3d48d99 (patch)
tree18551e6ba72fbd78ca06297b54e6ebdea898a098 /drivers
parent2c3808d629348516590c17ea98e455a1df02d109 (diff)
[PATCH] Fusion-MPT Update (2.03.01.01)
This upgrades the Fusion-MPT driver from 2.03.00.02 to 2.03.01.01. Bug Fixes: o Added back missing queuecommand entry point define ?! o Added to code to break marriage of two controllers during unload (could cause a panic) o SCSI driver will de-register with base driver if no SCSI-capable adapters found Minor Changes: o Removed errant spaces at ends of lines (most of the changes) o Moved code around (and in-lined) some functions for performance reasons. o Modified /proc functionality to facilitate testing with 2.5 o Added a call to synchronize_irq on unload (HP request) o Modified load of base to close a potential hole o Added code to set the FW IO coalescing depth (IBM request) o Changed return when mptctl driver registration fails (Kernel.org request) o SCSI driver detect routine calls a generic spinlock for all kernels (Kernel.org request) o Controller RAID page dynamic instead of static Currently running a multi-disk stress test w/ 2.5.53, this patch and driver built-in. Verified basic reset handling is working properly.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/message/fusion/linux_compat.h33
-rw-r--r--drivers/message/fusion/mptbase.c327
-rw-r--r--drivers/message/fusion/mptbase.h21
-rw-r--r--drivers/message/fusion/mptctl.c6
-rw-r--r--drivers/message/fusion/mptctl.h2
-rw-r--r--drivers/message/fusion/mptscsih.c1328
-rw-r--r--drivers/message/fusion/mptscsih.h38
7 files changed, 1165 insertions, 590 deletions
diff --git a/drivers/message/fusion/linux_compat.h b/drivers/message/fusion/linux_compat.h
index 99575438c027..bb8cb954e3a2 100644
--- a/drivers/message/fusion/linux_compat.h
+++ b/drivers/message/fusion/linux_compat.h
@@ -246,35 +246,17 @@ static __inline__ int __get_order(unsigned long size)
#endif
/*
- * We use our new error handling code if the kernel version is 2.5.1 or newer.
+ * We use our new error handling code if the kernel version is 2.4.18 or newer.
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,18)
#define MPT_SCSI_USE_NEW_EH
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28)
-#define mptscsih_lock(iocp, flags) \
- spin_lock_irqsave(&iocp->FreeQlock, flags)
-#else
-#define mptscsih_lock(iocp, flags) \
-({ save_flags(flags); \
- cli(); \
-})
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28)
-#define mptscsih_unlock(iocp, flags) \
- spin_unlock_irqrestore(&iocp->FreeQlock, flags)
-#else
-#define mptscsih_unlock(iocp, flags) restore_flags(flags);
-#endif
-
-
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41)
-#define mpt_work_struct work_struct
+#define mpt_work_struct work_struct
#define MPT_INIT_WORK(_task, _func, _data) INIT_WORK(_task, _func, _data)
#else
-#define mpt_work_struct tq_struct
+#define mpt_work_struct tq_struct
#define MPT_INIT_WORK(_task, _func, _data) \
({ (_task)->sync = 0; \
(_task)->routine = (_func); \
@@ -282,6 +264,13 @@ static __inline__ int __get_order(unsigned long size)
})
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28)
+#define mptscsih_sync_irq(_irq) synchronize_irq(_irq)
+#else
+#define mptscsih_sync_irq(_irq) synchronize_irq()
+#endif
+
+
/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#endif /* _LINUX_COMPAT_H */
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index cb7d91bc07a6..16e0b31dc75e 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -49,7 +49,7 @@
* (mailto:sjralston1@netscape.net)
* (mailto:Pam.Delaney@lsil.com)
*
- * $Id: mptbase.c,v 1.123 2002/10/17 20:15:56 pdelaney Exp $
+ * $Id: mptbase.c,v 1.125 2002/12/03 21:26:32 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -208,6 +208,7 @@ static int GetIoUnitPage2(MPT_ADAPTER *ioc);
static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
static int mpt_findImVolumes(MPT_ADAPTER *ioc);
+static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
static void mpt_timer_expired(unsigned long data);
static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
@@ -443,7 +444,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
*/
if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
|| (mf < ioc->req_frames)) ) {
- printk(MYIOC_s_WARN_FMT
+ printk(MYIOC_s_WARN_FMT
"mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx);
cb_idx = 0;
pa = 0;
@@ -451,14 +452,14 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
}
if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth))
|| (mr < ioc->reply_frames)) ) {
- printk(MYIOC_s_WARN_FMT
+ printk(MYIOC_s_WARN_FMT
"mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr);
cb_idx = 0;
pa = 0;
freeme = 0;
}
if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) {
- printk(MYIOC_s_WARN_FMT
+ printk(MYIOC_s_WARN_FMT
"mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx);
cb_idx = 0;
pa = 0;
@@ -576,9 +577,11 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
CONFIGPARMS *pCfg;
unsigned long flags;
- dprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
+ 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) {
@@ -599,7 +602,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
u16 status;
status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
- dprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
+ dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
status, le32_to_cpu(pReply->IOCLogInfo)));
pCfg->status = status;
@@ -943,7 +946,7 @@ mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
* mpt_add_sge - Place a simple SGE at address pAddr.
* @pAddr: virtual address for SGE
* @flagslength: SGE flags and data transfer length
- * @dma_addr: Physical address
+ * @dma_addr: Physical address
*
* This routine places a MPT request frame back on the MPT adapter's
* FreeQ.
@@ -973,7 +976,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
* @pAddr: virtual address for SGE
* @next: nextChainOffset value (u32's)
* @length: length of next SGL segment
- * @dma_addr: Physical address
+ * @dma_addr: Physical address
*
* This routine places a MPT request frame back on the MPT adapter's
* FreeQ.
@@ -986,7 +989,7 @@ mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
u32 tmp = dma_addr & 0xFFFFFFFF;
pChain->Length = cpu_to_le16(length);
- pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
+ pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
pChain->NextChainOffset = next;
@@ -1283,7 +1286,7 @@ mpt_adapter_install(struct pci_dev *pdev)
return r;
if (!pci_set_dma_mask(pdev, mask)) {
- dprintk((KERN_INFO MYNAM
+ dprintk((KERN_INFO MYNAM
": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
} else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
@@ -1470,6 +1473,12 @@ mpt_adapter_install(struct pci_dev *pdev)
ioc->active = 0;
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+ /* tack onto tail of our MPT adapter list */
+ Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER);
+
+ /* Set lookup ptr. */
+ mpt_adapters[ioc->id] = ioc;
+
ioc->pci_irq = -1;
if (pdev->irq) {
r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
@@ -1482,6 +1491,8 @@ mpt_adapter_install(struct pci_dev *pdev)
printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
ioc->name, __irq_itoa(pdev->irq));
#endif
+ Q_DEL_ITEM(ioc);
+ mpt_adapters[ioc->id] = NULL;
iounmap(mem);
kfree(ioc);
return -EBUSY;
@@ -1498,16 +1509,10 @@ mpt_adapter_install(struct pci_dev *pdev)
#endif
}
- /* tack onto tail of our MPT adapter list */
- Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER);
-
- /* Set lookup ptr. */
- mpt_adapters[ioc->id] = ioc;
-
/* NEW! 20010220 -sralston
* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
*/
- if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030)
+ if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030)
|| (ioc->chip_type == C1035) || (ioc->chip_type == FC929X))
mpt_detect_bound_ports(ioc, pdev);
@@ -1638,6 +1643,9 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
/* Handle the alt IOC too */
if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){
+ ddlprintk((MYIOC_s_INFO_FMT
+ "Alt-ioc firmware upload required!\n",
+ ioc->name));
r = mpt_do_upload(ioc->alt_ioc, sleepFlag);
if (r != 0)
printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
@@ -1706,14 +1714,18 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
*/
mpt_GetScsiPortSettings(ioc, 0);
- /* Get version and length of SDP 1
+ /* Get version and length of SDP 1
*/
mpt_readScsiDevicePageHeaders(ioc, 0);
- /* Find IM volumes
+ /* Find IM volumes
*/
if (ioc->facts.MsgVersion >= 0x0102)
mpt_findImVolumes(ioc);
+
+ /* Check, and possibly reset, the coalescing value
+ */
+ mpt_read_ioc_pg_1(ioc);
}
GetIoUnitPage2(ioc);
@@ -1819,7 +1831,7 @@ mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n"));
if ((state = mpt_downloadboot(this, NO_SLEEP)) < 0) {
- printk(KERN_WARNING MYNAM
+ printk(KERN_WARNING MYNAM
": firmware downloadboot failure (%d)!\n", state);
}
}
@@ -1919,6 +1931,11 @@ mpt_adapter_dispose(MPT_ADAPTER *this)
sz_first = this->alloc_total;
+ if (this->alt_ioc != NULL) {
+ this->alt_ioc->alt_ioc = NULL;
+ this->alt_ioc = NULL;
+ }
+
mpt_adapter_disable(this, 1);
if (this->pci_irq != -1) {
@@ -1998,8 +2015,8 @@ MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
*
* Returns:
* 1 - DIAG reset and READY
- * 0 - READY initially OR soft reset and READY
- * -1 - Any failure on KickStart
+ * 0 - READY initially OR soft reset and READY
+ * -1 - Any failure on KickStart
* -2 - Msg Unit Reset Failed
* -3 - IO Unit Reset Failed
* -4 - IOC owned by a PEER
@@ -2042,7 +2059,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
else
statefault = 4;
}
- }
+ }
/*
* Check to see if IOC is in FAULT state.
@@ -2244,7 +2261,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
/*
- * FC f/w version changed between 1.1 and 1.2
+ * FC f/w version changed between 1.1 and 1.2
* Old: u16{Major(4),Minor(4),SubMinor(8)}
* New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
*/
@@ -2417,10 +2434,10 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw))
ioc_init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE;
- else
+ else
ioc->upload_fw = 1;
}
- ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n",
+ ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n",
ioc->name, ioc_init.Flags, ioc->upload_fw));
if ((int)ioc->chip_type <= (int)FC929) {
@@ -2554,8 +2571,8 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
* Outputs: frags - number of fragments needed
* Return NULL if failed.
*/
-void *
-mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz)
+void *
+mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz)
{
fw_image_t **cached_fw = NULL;
u8 *mem = NULL;
@@ -2564,7 +2581,7 @@ mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz)
int bytes_left, bytes, num_frags;
int sz, ii;
- /* cached_fw
+ /* cached_fw
*/
sz = ioc->num_fw_frags * sizeof(void *);
mem = kmalloc(sz, GFP_ATOMIC);
@@ -2721,8 +2738,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
ioc->num_fw_frags = ioc->req_sz - sizeof(FWUpload_t) + sizeof(dma_addr_t) + sizeof(u32) -1;
ioc->num_fw_frags /= sizeof(dma_addr_t) + sizeof(u32);
- ioc->cached_fw = (fw_image_t **) mpt_alloc_fw_memory(ioc,
- ioc->facts.FWImageSize, &num_frags, &alloc_sz);
+ ioc->cached_fw = (fw_image_t **) mpt_alloc_fw_memory(ioc,
+ ioc->facts.FWImageSize, &num_frags, &alloc_sz);
if (ioc->cached_fw == NULL) {
/* Major Failure.
@@ -2769,8 +2786,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
}
- mpt_add_sge(&request[sgeoffset],
- MPT_SGE_FLAGS_SSIMPLE_READ |(u32) ioc->cached_fw[ii]->size,
+ mpt_add_sge(&request[sgeoffset],
+ MPT_SGE_FLAGS_SSIMPLE_READ |(u32) ioc->cached_fw[ii]->size,
ioc->cached_fw[ii]->fw_dma);
sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
@@ -3117,8 +3134,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
* 0 - no reset due to History bit, READY
* -1 - no reset due to History bit but not READY
* OR reset but failed to come READY
- * -2 - no reset, could not enter DIAG mode
- * -3 - reset but bad FW bit
+ * -2 - no reset, could not enter DIAG mode
+ * -3 - reset but bad FW bit
*/
static int
KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
@@ -3254,18 +3271,14 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
ioc->name, diag0val, diag1val));
#endif
/* Write the PreventIocBoot bit */
-#if 1
if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
-#else
- if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
-#endif
diag0val |= MPI_DIAG_PREVENT_IOC_BOOT;
CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
}
/*
* Disable the ARM (Bug fix)
- *
+ *
*/
CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
mdelay (1);
@@ -3304,11 +3317,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
/* FIXME? Examine results here? */
}
-#if 1
if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
-#else
- if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
-#endif
/* If the DownloadBoot operation fails, the
* IOC will be left unusable. This is a fatal error
* case. _diag_reset will return < 0
@@ -3318,7 +3327,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
#ifdef MPT_DEBUG
if (ioc->alt_ioc)
diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
- dprintk((MYIOC_s_INFO_FMT
+ dprintk((MYIOC_s_INFO_FMT
"DbG2b: diag0=%08x, diag1=%08x\n",
ioc->name, diag0val, diag1val));
#endif
@@ -3335,7 +3344,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
}
}
if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
- printk(KERN_WARNING MYNAM
+ printk(KERN_WARNING MYNAM
": firmware downloadboot failure (%d)!\n", count);
}
@@ -3467,7 +3476,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
if ((r = WaitForDoorbellAck(ioc, 2, sleepFlag)) < 0)
return r;
- /* FW ACK'd request, wait for READY state
+ /* FW ACK'd request, wait for READY state
*/
cntdn = HZ * 15;
count = 0;
@@ -3631,6 +3640,9 @@ 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);
@@ -4267,7 +4279,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
int ii;
int data, rc = 0;
- /* Allocate memory
+ /* Allocate memory
*/
if (!ioc->spi_data.nvram) {
int sz;
@@ -4446,12 +4458,17 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
ioc->spi_data.sdp0length = cfg.hdr->PageLength;
+ dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
+ ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
+
+ dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
+ ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
+ * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
* @ioc: Pointer to a Adapter Strucutre
* @portnum: IOC port number
*
@@ -4464,17 +4481,13 @@ static int
mpt_findImVolumes(MPT_ADAPTER *ioc)
{
IOCPage2_t *pIoc2 = NULL;
- IOCPage3_t *pIoc3 = NULL;
ConfigPageIoc2RaidVol_t *pIocRv = NULL;
- u8 *mem;
dma_addr_t ioc2_dma;
- dma_addr_t ioc3_dma;
CONFIGPARMS cfg;
ConfigPageHeader_t header;
int jj;
int rc = 0;
int iocpage2sz;
- int iocpage3sz = 0;
u8 nVols, nPhys;
u8 vid, vbus, vioc;
@@ -4541,44 +4554,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
/* No physical disks. Done.
*/
} else {
- /* There is at least one physical disk.
- * Read and save IOC Page 3
- */
- header.PageVersion = 0;
- header.PageLength = 0;
- header.PageNumber = 3;
- header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
- cfg.physAddr = -1;
- cfg.pageAddr = 0;
- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
- cfg.dir = 0;
- cfg.timeout = 0;
- if (mpt_config(ioc, &cfg) != 0)
- goto done_and_free;
-
- if (header.PageLength == 0)
- goto done_and_free;
-
- /* Read Header good, alloc memory
- */
- iocpage3sz = header.PageLength * 4;
- pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
- if (!pIoc3)
- goto done_and_free;
-
- /* Read the Page and save the data
- * into malloc'd memory.
- */
- cfg.physAddr = ioc3_dma;
- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
- if (mpt_config(ioc, &cfg) == 0) {
- mem = kmalloc(iocpage3sz, GFP_ATOMIC);
- if (mem) {
- memcpy(mem, (u8 *)pIoc3, iocpage3sz);
- ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
- }
- }
+ mpt_read_ioc_pg_3(ioc);
}
done_and_free:
@@ -4587,14 +4563,159 @@ done_and_free:
pIoc2 = NULL;
}
+ return rc;
+}
+
+int
+mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
+{
+ IOCPage3_t *pIoc3 = NULL;
+ u8 *mem;
+ CONFIGPARMS cfg;
+ ConfigPageHeader_t header;
+ dma_addr_t ioc3_dma;
+ int iocpage3sz = 0;
+
+ /* Free the old page
+ */
+ if (ioc->spi_data.pIocPg3) {
+ kfree(ioc->spi_data.pIocPg3);
+ ioc->spi_data.pIocPg3 = NULL;
+ }
+
+ /* There is at least one physical disk.
+ * Read and save IOC Page 3
+ */
+ header.PageVersion = 0;
+ header.PageLength = 0;
+ header.PageNumber = 3;
+ header.PageType = MPI_CONFIG_PAGETYPE_IOC;
+ cfg.hdr = &header;
+ cfg.physAddr = -1;
+ cfg.pageAddr = 0;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+ cfg.dir = 0;
+ cfg.timeout = 0;
+ if (mpt_config(ioc, &cfg) != 0)
+ return 0;
+
+ if (header.PageLength == 0)
+ return 0;
+
+ /* Read Header good, alloc memory
+ */
+ iocpage3sz = header.PageLength * 4;
+ pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
+ if (!pIoc3)
+ return 0;
+
+ /* Read the Page and save the data
+ * into malloc'd memory.
+ */
+ cfg.physAddr = ioc3_dma;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+ if (mpt_config(ioc, &cfg) == 0) {
+ mem = kmalloc(iocpage3sz, GFP_ATOMIC);
+ if (mem) {
+ memcpy(mem, (u8 *)pIoc3, iocpage3sz);
+ ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
+ }
+ }
+
if (pIoc3) {
pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
pIoc3 = NULL;
}
- return rc;
+ return 0;
}
+static void
+mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
+{
+ IOCPage1_t *pIoc1 = NULL;
+ CONFIGPARMS cfg;
+ ConfigPageHeader_t header;
+ dma_addr_t ioc1_dma;
+ int iocpage1sz = 0;
+ u32 tmp;
+
+ /* Check the Coalescing Timeout in IOC Page 1
+ */
+ header.PageVersion = 0;
+ header.PageLength = 0;
+ header.PageNumber = 1;
+ header.PageType = MPI_CONFIG_PAGETYPE_IOC;
+ cfg.hdr = &header;
+ cfg.physAddr = -1;
+ cfg.pageAddr = 0;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+ cfg.dir = 0;
+ cfg.timeout = 0;
+ if (mpt_config(ioc, &cfg) != 0)
+ return;
+
+ if (header.PageLength == 0)
+ return;
+
+ /* Read Header good, alloc memory
+ */
+ iocpage1sz = header.PageLength * 4;
+ pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
+ if (!pIoc1)
+ return;
+
+ /* Read the Page and check coalescing timeout
+ */
+ cfg.physAddr = ioc1_dma;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+ if (mpt_config(ioc, &cfg) == 0) {
+
+ tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
+ if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
+ tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
+
+ dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
+ ioc->name, tmp));
+
+ if (tmp > MPT_COALESCING_TIMEOUT) {
+ pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
+
+ /* Write NVRAM and current
+ */
+ cfg.dir = 1;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+ if (mpt_config(ioc, &cfg) == 0) {
+ dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
+ ioc->name, MPT_COALESCING_TIMEOUT));
+
+ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
+ if (mpt_config(ioc, &cfg) == 0) {
+ dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
+ ioc->name, MPT_COALESCING_TIMEOUT));
+ } else {
+ dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
+ ioc->name));
+ }
+
+ } else {
+ dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
+ ioc->name));
+ }
+ }
+
+ } else {
+ dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
+ }
+ }
+
+ if (pIoc1) {
+ pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
+ pIoc1 = NULL;
+ }
+
+ return;
+}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -4690,7 +4811,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
*/
in_isr = in_interrupt();
if (in_isr) {
- dprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
+ dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
ioc->name));
return -EPERM;
}
@@ -4698,7 +4819,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
/* Get and Populate a free Frame
*/
if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
- dprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
+ dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
ioc->name));
return -EAGAIN;
}
@@ -4731,7 +4852,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
- dprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+ dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
/* Append pCfg pointer to end of mf
@@ -4778,7 +4899,7 @@ mpt_timer_expired(unsigned long data)
{
MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
- dprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
+ dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
/* Perform a FW reload */
if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
@@ -4788,7 +4909,7 @@ mpt_timer_expired(unsigned long data)
* Hard reset clean-up will wake up
* process and free all resources.
*/
- dprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
+ dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
return;
}
@@ -4829,7 +4950,7 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
} else {
CONFIGPARMS *pNext;
- /* Search the configQ for internal commands.
+ /* Search the configQ for internal commands.
* Flush the Q, and wake up all suspended threads.
*/
#if 1
@@ -5096,8 +5217,7 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo
*/
if (isense_idx == ii)
len += sprintf(buf+len, " Fusion MPT isense driver\n");
- } else
- break;
+ }
}
MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
@@ -5774,6 +5894,7 @@ EXPORT_SYMBOL(mpt_lan_index);
EXPORT_SYMBOL(mpt_stm_index);
EXPORT_SYMBOL(mpt_HardResetHandler);
EXPORT_SYMBOL(mpt_config);
+EXPORT_SYMBOL(mpt_read_ioc_pg_3);
EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
@@ -5843,6 +5964,7 @@ static void
fusion_exit(void)
{
MPT_ADAPTER *this;
+ struct pci_dev *pdev = NULL;
dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
@@ -5861,9 +5983,14 @@ fusion_exit(void)
this->active = 0;
+ pdev = (struct pci_dev *)this->pcidev;
+ mptscsih_sync_irq(pdev->irq);
+
/* Clear any lingering interrupt */
CHIPREG_WRITE32(&this->chip->IntStatus, 0);
+ CHIPREG_READ32(&this->chip->IntStatus);
+
Q_DEL_ITEM(this);
mpt_adapter_dispose(this);
}
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index c992a7f70379..916b3b299e3d 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -13,7 +13,7 @@
* (mailto:sjralston1@netscape.net)
* (mailto:Pam.Delaney@lsil.com)
*
- * $Id: mptbase.h,v 1.136 2002/10/21 13:51:54 pdelaney Exp $
+ * $Id: mptbase.h,v 1.141 2002/12/03 21:26:32 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -80,8 +80,8 @@
#define COPYRIGHT "Copyright (c) 1999-2002 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "2.03.00.02"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.03.00.02"
+#define MPT_LINUX_VERSION_COMMON "2.03.01.01"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.03.01.01"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -134,8 +134,10 @@
#define CAN_SLEEP 1
#define NO_SLEEP 0
-/*
- * SCSI transfer rate defines.
+#define MPT_COALESCING_TIMEOUT 0x10
+
+/*
+ * SCSI transfer rate defines.
*/
#define MPT_ULTRA320 0x08
#define MPT_ULTRA160 0x09
@@ -524,7 +526,7 @@ typedef struct _mpt_ioctl_events {
#define MPT_SCSICFG_DV_PENDING 0x04 /* DV on this physical id pending */
#define MPT_SCSICFG_DV_NOT_DONE 0x08 /* DV has not been performed */
#define MPT_SCSICFG_BLK_NEGO 0x10 /* WriteSDP1 with WDTR and SDTR disabled */
-
+#define MPT_SCSICFG_RELOAD_IOC_PG3 0x20 /* IOC Pg 3 data is obsolete */
/* Args passed to writeSDP1: */
#define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */
#define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */
@@ -756,6 +758,12 @@ typedef struct _mpt_sge {
#define nehprintk(x)
#endif
+#if defined(MPT_DEBUG_CONFIG) || defined(MPT_DEBUG)
+#define dcprintk(x) printk x
+#else
+#define dcprintk(x)
+#endif
+
#define MPT_INDEX_2_MFPTR(ioc,idx) \
(MPT_FRAME_HDR*)( (u8*)(ioc)->req_frames + (ioc)->req_sz * (idx) )
@@ -1009,6 +1017,7 @@ extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
extern void *mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz);
extern void mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img);
+extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
/*
* Public data decl's...
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 445afed79fd9..37b5799fd184 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -34,7 +34,7 @@
* (mailto:sjralston1@netscape.net)
* (mailto:Pam.Delaney@lsil.com)
*
- * $Id: mptctl.c,v 1.61 2002/10/17 20:15:57 pdelaney Exp $
+ * $Id: mptctl.c,v 1.63 2002/12/03 21:26:33 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -2911,9 +2911,9 @@ int __init mptctl_init(void)
#endif /*} sparc */
/* Register this device */
- if (misc_register(&mptctl_miscdev) == -1) {
+ err = misc_register(&mptctl_miscdev);
+ if (err < 0) {
printk(KERN_ERR MYNAM ": Can't register misc device [minor=%d].\n", MPT_MINOR);
- err = -EBUSY;
goto out_fail;
}
printk(KERN_INFO MYNAM ": Registered with Fusion MPT base driver\n");
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index 444a5009c9ba..e7fedd5d38cb 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -20,7 +20,7 @@
* (mailto:sjralston1@netscape.net)
* (mailto:Pam.Delaney@lsil.com)
*
- * $Id: mptctl.h,v 1.12 2002/10/17 20:15:58 pdelaney Exp $
+ * $Id: mptctl.h,v 1.13 2002/12/03 21:26:33 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 57faa74cba29..965c1bb9636d 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -26,7 +26,7 @@
* (mailto:sjralston1@netscape.net)
* (mailto:Pam.Delaney@lsil.com)
*
- * $Id: mptscsih.c,v 1.103 2002/10/17 20:15:59 pdelaney Exp $
+ * $Id: mptscsih.c,v 1.104 2002/12/03 21:26:34 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -159,11 +159,9 @@ typedef struct _dv_parameters {
static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
static void mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
-static int mptscsih_io_direction(Scsi_Cmnd *cmd);
static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
SCSIIORequest_t *pReq, int req_idx);
-static int mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex);
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);
@@ -274,6 +272,436 @@ static struct mptscsih_driver_setup
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
+ * Private inline routines...
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* 19991030 -sralston
+ * Return absolute SCSI data direction:
+ * 1 = _DATA_OUT
+ * 0 = _DIR_NONE
+ * -1 = _DATA_IN
+ *
+ * Changed: 3-20-2002 pdelaney to use the default data
+ * direction and the defines set up in the
+ * 2.4 kernel series
+ * 1 = _DATA_OUT changed to SCSI_DATA_WRITE (1)
+ * 0 = _DIR_NONE changed to SCSI_DATA_NONE (3)
+ * -1 = _DATA_IN changed to SCSI_DATA_READ (2)
+ * If the direction is unknown, fall through to original code.
+ *
+ * Mid-layer bug fix(): sg interface generates the wrong data
+ * direction in some cases. Set the direction the hard way for
+ * the most common commands.
+ */
+static inline int
+mptscsih_io_direction(Scsi_Cmnd *cmd)
+{
+ switch (cmd->cmnd[0]) {
+ case WRITE_6:
+ case WRITE_10:
+ return SCSI_DATA_WRITE;
+ break;
+ case READ_6:
+ case READ_10:
+ return SCSI_DATA_READ;
+ 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:
+ case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER:
+ case WRITE_VERIFY: case WRITE_VERIFY_12:
+ case COMPARE: case COPY: case COPY_VERIFY:
+ case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
+ case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12:
+ case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT:
+ case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK:
+ case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG:
+ case REASSIGN_BLOCKS:
+ case PERSISTENT_RESERVE_OUT:
+ case 0xea:
+ case 0xa3:
+ return SCSI_DATA_WRITE;
+
+ /* No data transfer commands */
+ case SEEK_6: case SEEK_10:
+ case RESERVE: case RELEASE:
+ case TEST_UNIT_READY:
+ case START_STOP:
+ case ALLOW_MEDIUM_REMOVAL:
+ return SCSI_DATA_NONE;
+
+ /* Conditional data transfer commands */
+ case FORMAT_UNIT:
+ if (cmd->cmnd[1] & 0x10) /* FmtData (data out phase)? */
+ return SCSI_DATA_WRITE;
+ else
+ return SCSI_DATA_NONE;
+
+ case VERIFY:
+ if (cmd->cmnd[1] & 0x02) /* VERIFY:BYTCHK (data out phase)? */
+ return SCSI_DATA_WRITE;
+ else
+ return SCSI_DATA_NONE;
+
+ case RESERVE_10:
+ if (cmd->cmnd[1] & 0x03) /* RESERVE:{LongID|Extent} (data out phase)? */
+ return SCSI_DATA_WRITE;
+ else
+ return SCSI_DATA_NONE;
+
+ /* Must be data _IN! */
+ default:
+ return SCSI_DATA_READ;
+ }
+} /* mptscsih_io_direction() */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptscsih_add_sge - Place a simple SGE at address pAddr.
+ * @pAddr: virtual address for SGE
+ * @flagslength: SGE flags and data transfer length
+ * @dma_addr: Physical address
+ *
+ * This routine places a MPT request frame back on the MPT adapter's
+ * FreeQ.
+ */
+static inline void
+mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
+{
+ if (sizeof(dma_addr_t) == sizeof(u64)) {
+ SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
+ u32 tmp = dma_addr & 0xFFFFFFFF;
+
+ pSge->FlagsLength = cpu_to_le32(flagslength);
+ pSge->Address.Low = cpu_to_le32(tmp);
+ tmp = (u32) ((u64)dma_addr >> 32);
+ pSge->Address.High = cpu_to_le32(tmp);
+
+ } else {
+ SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
+ pSge->FlagsLength = cpu_to_le32(flagslength);
+ pSge->Address = cpu_to_le32(dma_addr);
+ }
+} /* mptscsih_add_sge() */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptscsih_add_chain - Place a chain SGE at address pAddr.
+ * @pAddr: virtual address for SGE
+ * @next: nextChainOffset value (u32's)
+ * @length: length of next SGL segment
+ * @dma_addr: Physical address
+ *
+ * This routine places a MPT request frame back on the MPT adapter's
+ * FreeQ.
+ */
+static inline void
+mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
+{
+ if (sizeof(dma_addr_t) == sizeof(u64)) {
+ SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
+ u32 tmp = dma_addr & 0xFFFFFFFF;
+
+ pChain->Length = cpu_to_le16(length);
+ pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
+
+ pChain->NextChainOffset = next;
+
+ pChain->Address.Low = cpu_to_le32(tmp);
+ tmp = (u32) ((u64)dma_addr >> 32);
+ pChain->Address.High = cpu_to_le32(tmp);
+ } else {
+ SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
+ pChain->Length = cpu_to_le16(length);
+ pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
+ pChain->NextChainOffset = next;
+ pChain->Address = cpu_to_le32(dma_addr);
+ }
+} /* mptscsih_add_chain() */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptscsih_getFreeChainBuffes - Function to get a free chain
+ * from the MPT_SCSI_HOST FreeChainQ.
+ * @hd: Pointer to the MPT_SCSI_HOST instance
+ * @req_idx: Index of the SCSI IO request frame. (output)
+ *
+ * return SUCCESS or FAILED
+ */
+static inline int
+mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
+{
+ MPT_FRAME_HDR *chainBuf = NULL;
+ unsigned long flags;
+ int rc = FAILED;
+ int chain_idx = MPT_HOST_NO_CHAIN;
+
+ spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+ if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
+
+ int offset;
+
+ chainBuf = hd->FreeChainQ.head;
+ Q_DEL_ITEM(&chainBuf->u.frame.linkage);
+ offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;
+ chain_idx = offset / hd->ioc->req_sz;
+ rc = SUCCESS;
+ }
+ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+
+
+ *retIndex = chain_idx;
+
+ dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
+ hd->ioc->name, *retIndex, chainBuf));
+
+ return rc;
+} /* mptscsih_getFreeChainBuffer() */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
+ * SCSIIORequest_t Message Frame.
+ * @hd: Pointer to MPT_SCSI_HOST structure
+ * @SCpnt: Pointer to Scsi_Cmnd structure
+ * @pReq: Pointer to SCSIIORequest_t structure
+ *
+ * Returns ...
+ */
+static int
+mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
+ SCSIIORequest_t *pReq, int req_idx)
+{
+ char *psge;
+ char *chainSge;
+ struct scatterlist *sg;
+ int frm_sz;
+ int sges_left, sg_done;
+ int chain_idx = MPT_HOST_NO_CHAIN;
+ int sgeOffset;
+ int numSgeSlots, numSgeThisFrame;
+ u32 sgflags, sgdir, thisxfer = 0;
+ int chain_dma_off = 0;
+ int newIndex;
+ int ii;
+ dma_addr_t v2;
+
+ sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
+ if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
+ sgdir = MPT_TRANSFER_HOST_TO_IOC;
+ } else {
+ sgdir = MPT_TRANSFER_IOC_TO_HOST;
+ }
+
+ psge = (char *) &pReq->SGL;
+ frm_sz = hd->ioc->req_sz;
+
+ /* Map the data portion, if any.
+ * sges_left = 0 if no data transfer.
+ */
+ sges_left = SCpnt->use_sg;
+ if (SCpnt->use_sg) {
+ sges_left = pci_map_sg(hd->ioc->pcidev,
+ (struct scatterlist *) SCpnt->request_buffer,
+ SCpnt->use_sg,
+ scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+ } else if (SCpnt->request_bufflen) {
+ dma_addr_t buf_dma_addr;
+ scPrivate *my_priv;
+
+ buf_dma_addr = pci_map_single(hd->ioc->pcidev,
+ SCpnt->request_buffer,
+ SCpnt->request_bufflen,
+ scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+
+ /* We hide it here for later unmap. */
+ my_priv = (scPrivate *) &SCpnt->SCp;
+ my_priv->p1 = (void *)(ulong) buf_dma_addr;
+
+ dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
+ hd->ioc->name, SCpnt, SCpnt->request_bufflen));
+
+ mptscsih_add_sge((char *) &pReq->SGL,
+ 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
+ buf_dma_addr);
+
+ return SUCCESS;
+ }
+
+ /* Handle the SG case.
+ */
+ sg = (struct scatterlist *) SCpnt->request_buffer;
+ sg_done = 0;
+ sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
+ chainSge = NULL;
+
+ /* Prior to entering this loop - the following must be set
+ * current MF: sgeOffset (bytes)
+ * chainSge (Null if original MF is not a chain buffer)
+ * sg_done (num SGE done for this MF)
+ */
+
+nextSGEset:
+ numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
+ numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
+
+ sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
+
+ /* Get first (num - 1) SG elements
+ * Skip any SG entries with a length of 0
+ * NOTE: at finish, sg and psge pointed to NEXT data/location positions
+ */
+ for (ii=0; ii < (numSgeThisFrame-1); ii++) {
+ thisxfer = sg_dma_len(sg);
+ if (thisxfer == 0) {
+ sg ++; /* Get next SG element from the OS */
+ sg_done++;
+ continue;
+ }
+
+ v2 = sg_dma_address(sg);
+ mptscsih_add_sge(psge, sgflags | thisxfer, v2);
+
+ sg++; /* Get next SG element from the OS */
+ psge += (sizeof(u32) + sizeof(dma_addr_t));
+ sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
+ sg_done++;
+ }
+
+ if (numSgeThisFrame == sges_left) {
+ /* Add last element, end of buffer and end of list flags.
+ */
+ sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
+ MPT_SGE_FLAGS_END_OF_BUFFER |
+ MPT_SGE_FLAGS_END_OF_LIST;
+
+ /* Add last SGE and set termination flags.
+ * Note: Last SGE may have a length of 0 - which should be ok.
+ */
+ thisxfer = sg_dma_len(sg);
+
+ v2 = sg_dma_address(sg);
+ mptscsih_add_sge(psge, sgflags | thisxfer, v2);
+ /*
+ sg++;
+ psge += (sizeof(u32) + sizeof(dma_addr_t));
+ */
+ sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
+ sg_done++;
+
+ if (chainSge) {
+ /* The current buffer is a chain buffer,
+ * but there is not another one.
+ * Update the chain element
+ * Offset and Length fields.
+ */
+ mptscsih_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
+ } else {
+ /* The current buffer is the original MF
+ * and there is no Chain buffer.
+ */
+ pReq->ChainOffset = 0;
+ }
+ } else {
+ /* At least one chain buffer is needed.
+ * Complete the first MF
+ * - last SGE element, set the LastElement bit
+ * - set ChainOffset (words) for orig MF
+ * (OR finish previous MF chain buffer)
+ * - update MFStructPtr ChainIndex
+ * - Populate chain element
+ * Also
+ * Loop until done.
+ */
+
+ dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
+ hd->ioc->name, sg_done));
+
+ /* Set LAST_ELEMENT flag for last non-chain element
+ * in the buffer. Since psge points at the NEXT
+ * SGE element, go back one SGE element, update the flags
+ * and reset the pointer. (Note: sgflags & thisxfer are already
+ * set properly).
+ */
+ if (sg_done) {
+ u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
+ sgflags = le32_to_cpu(*ptmp);
+ sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
+ *ptmp = cpu_to_le32(sgflags);
+ }
+
+ if (chainSge) {
+ /* The current buffer is a chain buffer.
+ * chainSge points to the previous Chain Element.
+ * Update its chain element Offset and Length (must
+ * include chain element size) fields.
+ * Old chain element is now complete.
+ */
+ u8 nextChain = (u8) (sgeOffset >> 2);
+ sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
+ mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
+ } else {
+ /* The original MF buffer requires a chain buffer -
+ * set the offset.
+ * Last element in this MF is a chain element.
+ */
+ pReq->ChainOffset = (u8) (sgeOffset >> 2);
+ }
+
+ sges_left -= sg_done;
+
+
+ /* NOTE: psge points to the beginning of the chain element
+ * in current buffer. Get a chain buffer.
+ */
+ if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)
+ return FAILED;
+
+ /* Update the tracking arrays.
+ * If chainSge == NULL, update ReqToChain, else ChainToChain
+ */
+ if (chainSge) {
+ hd->ChainToChain[chain_idx] = newIndex;
+ } else {
+ hd->ReqToChain[req_idx] = newIndex;
+ }
+ chain_idx = newIndex;
+ chain_dma_off = hd->ioc->req_sz * chain_idx;
+
+ /* Populate the chainSGE for the current buffer.
+ * - Set chain buffer pointer to psge and fill
+ * out the Address and Flags fields.
+ */
+ chainSge = (char *) psge;
+ dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
+ psge, req_idx));
+
+ /* Start the SGE for the next buffer
+ */
+ psge = (char *) (hd->ChainBuffer + chain_dma_off);
+ sgeOffset = 0;
+ sg_done = 0;
+
+ dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
+ psge, chain_idx));
+
+ /* Start the SGE for the next buffer
+ */
+
+ goto nextSGEset;
+ }
+
+ return SUCCESS;
+} /* mptscsih_AddSGE() */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
* mptscsih_io_done - Main SCSI IO callback routine registered to
* Fusion MPT (base) driver
* @ioc: Pointer to MPT_ADAPTER structure
@@ -294,7 +722,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
MPT_SCSI_HOST *hd;
SCSIIORequest_t *pScsiReq;
SCSIIOReply_t *pScsiReply;
-#ifndef MPT_SCSI_USE_NEW_EH
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
unsigned long flags;
#endif
u16 req_idx;
@@ -305,7 +733,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
(mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
printk(MYIOC_s_ERR_FMT "%s req frame ptr! (=%p)!\n",
ioc->name, mf?"BAD":"NULL", (void *) mf);
- /* return 1; CHECKME SteveR. Don't free. */
return 0;
}
@@ -411,12 +838,12 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
#ifndef MPT_SCSI_USE_NEW_EH
search_taskQ_for_cmd(sc, hd);
#endif
- /* Linux handles an unsolicited DID_RESET better
+ /* Linux handles an unsolicited DID_RESET better
* than an unsolicited DID_ABORT.
*/
sc->result = DID_RESET << 16;
- /* GEM Workaround. */
+ /* GEM Workaround. */
if (hd->is_spi)
mptscsih_no_negotiate(hd, sc->target);
break;
@@ -428,7 +855,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
#endif
sc->result = DID_RESET << 16;
- /* GEM Workaround. */
+ /* GEM Workaround. */
if (hd->is_spi)
mptscsih_no_negotiate(hd, sc->target);
break;
@@ -506,7 +933,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
;
} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
/*
- * If running agains circa 200003dd 909 MPT f/w,
+ * If running against circa 200003dd 909 MPT f/w,
* may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
* (QUEUE_FULL) returned from device! --> get 0x0000?128
* and with SenseBytes set to 0.
@@ -625,7 +1052,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
hd->ScsiLookup[req_idx] = NULL;
- sc->host_scribble = NULL; /* CHECKME! - Do we need to clear this??? */
+#ifndef MPT_SCSI_USE_NEW_EH
+ sc->host_scribble = NULL;
+#endif
MPT_HOST_LOCK(flags);
sc->scsi_done(sc); /* Issue the command callback */
@@ -894,7 +1323,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
int ii;
int max = hd->ioc->req_depth;
-#ifndef MPT_SCSI_USE_NEW_EH
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
unsigned long flags;
#endif
@@ -911,7 +1340,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
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.
*/
@@ -1061,7 +1490,7 @@ mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
* of chain buffers to be allocated.
* index = chain_idx
*
- * Calculate the number of chain buffers needed(plus 1) per I/O
+ * Calculate the number of chain buffers needed(plus 1) per I/O
* then multiply the the maximum number of simultaneous cmds
*
* num_sge = num sge in request frame + last chain buffer
@@ -1175,6 +1604,7 @@ mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIOReque
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static int BeenHereDoneThat = 0;
+static char *info_kbuf = NULL;
/* SCSI host fops start here... */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1263,9 +1693,10 @@ mptscsih_detect(Scsi_Host_Template *tpnt)
#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) {
- mptscsih_lock(this, flags);
+ spin_lock_irqsave(&this->FreeQlock, flags);
sh->io_port = 0;
sh->n_io_port = 0;
sh->irq = 0;
@@ -1326,7 +1757,7 @@ mptscsih_detect(Scsi_Host_Template *tpnt)
} else {
numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale +
(this->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
- }
+ }
if (numSGE < sh->sg_tablesize) {
/* Reset this value */
@@ -1340,7 +1771,7 @@ mptscsih_detect(Scsi_Host_Template *tpnt)
*/
scsi_set_pci_device(sh, this->pcidev);
- mptscsih_unlock(this, flags);
+ spin_unlock_irqrestore(&this->FreeQlock, flags);
hd = (MPT_SCSI_HOST *) sh->hostdata;
hd->ioc = this;
@@ -1503,12 +1934,25 @@ mptscsih_detect(Scsi_Host_Template *tpnt)
done:
if (mpt_scsi_hosts > 0)
register_reboot_notifier(&mptscsih_notifier);
+ else {
+ mpt_reset_deregister(ScsiDoneCtx);
+ dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n"));
+
+ mpt_event_deregister(ScsiDoneCtx);
+ dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n"));
+
+ mpt_deregister(ScsiScanDvCtx);
+ mpt_deregister(ScsiTaskCtx);
+ mpt_deregister(ScsiDoneCtx);
+
+ if (info_kbuf != NULL)
+ kfree(info_kbuf);
+ }
return mpt_scsi_hosts;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
- static char *info_kbuf = NULL;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_release - Unregister SCSI host from linux scsi mid-layer
@@ -1731,7 +2175,7 @@ mptscsih_halt(struct notifier_block *nb, ulong event, void *buf)
const char *
mptscsih_info(struct Scsi_Host *SChost)
{
- MPT_SCSI_HOST *h;
+ MPT_SCSI_HOST *h = NULL;
int size = 0;
if (info_kbuf == NULL)
@@ -1740,12 +2184,307 @@ mptscsih_info(struct Scsi_Host *SChost)
h = (MPT_SCSI_HOST *)SChost->hostdata;
info_kbuf[0] = '\0';
- mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
- info_kbuf[size-1] = '\0';
+ if (h) {
+ mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
+ info_kbuf[size-1] = '\0';
+ }
return info_kbuf;
}
+struct info_str {
+ char *buffer;
+ int length;
+ int offset;
+ int pos;
+};
+
+static void copy_mem_info(struct info_str *info, char *data, int len)
+{
+ if (info->pos + len > info->length)
+ len = info->length - info->pos;
+
+ if (info->pos + len < info->offset) {
+ info->pos += len;
+ return;
+ }
+
+ if (info->pos < info->offset) {
+ data += (info->offset - info->pos);
+ len -= (info->offset - info->pos);
+ }
+
+ if (len > 0) {
+ memcpy(info->buffer + info->pos, data, len);
+ info->pos += len;
+ }
+}
+
+static int copy_info(struct info_str *info, char *fmt, ...)
+{
+ va_list args;
+ char buf[81];
+ int len;
+
+ va_start(args, fmt);
+ len = vsprintf(buf, fmt, args);
+ va_end(args);
+
+ copy_mem_info(info, buf, len);
+ return len;
+}
+
+static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
+{
+ struct info_str info;
+
+ info.buffer = pbuf;
+ info.length = len;
+ info.offset = offset;
+ info.pos = 0;
+
+ copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
+ copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
+ copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
+ copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
+
+ return ((info.pos > info.offset) ? info.pos - info.offset : 0);
+}
+
+struct mptscsih_usrcmd {
+ ulong target;
+ ulong lun;
+ ulong data;
+ ulong cmd;
+};
+
+#define UC_GET_SPEED 0x10
+
+static void mptscsih_exec_user_cmd(MPT_ADAPTER *ioc, struct mptscsih_usrcmd *uc)
+{
+ CONFIGPARMS cfg;
+ dma_addr_t cfg_dma_addr = -1;
+ ConfigPageHeader_t header;
+
+ dprintk(("exec_user_command: ioc %p cmd %ld target=%ld\n",
+ ioc, uc->cmd, uc->target));
+
+ switch (uc->cmd) {
+ case UC_GET_SPEED:
+ {
+ SCSIDevicePage0_t *pData = NULL;
+
+ if (ioc->spi_data.sdp0length == 0)
+ return;
+
+ pData = (SCSIDevicePage0_t *)pci_alloc_consistent(ioc->pcidev,
+ ioc->spi_data.sdp0length * 4, &cfg_dma_addr);
+
+ if (pData == NULL)
+ return;
+
+ header.PageVersion = ioc->spi_data.sdp0version;
+ header.PageLength = ioc->spi_data.sdp0length;
+ header.PageNumber = 0;
+ header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+
+ cfg.hdr = &header;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+ cfg.dir = 0;
+ cfg.pageAddr = (u32) uc->target; /* bus << 8 | target */
+ cfg.physAddr = cfg_dma_addr;
+
+ if (mpt_config(ioc, &cfg) == 0) {
+ u32 np = le32_to_cpu(pData->NegotiatedParameters);
+ u32 tmp = np & MPI_SCSIDEVPAGE0_NP_WIDE;
+
+ printk("Target %d: %s;",
+ (u32) uc->target,
+ tmp ? "Wide" : "Narrow");
+
+ tmp = np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK;
+ if (tmp) {
+ u32 speed = 0;
+ printk(" Synchronous");
+ tmp = (tmp >> 16);
+ printk(" (Offset=0x%x", tmp);
+ tmp = np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK;
+ tmp = (tmp >> 8);
+ printk(" Factor=0x%x)", tmp);
+ if (tmp <= MPT_ULTRA320)
+ speed=160;
+ else if (tmp <= MPT_ULTRA160)
+ speed=80;
+ else if (tmp <= MPT_ULTRA2)
+ speed=40;
+ else if (tmp <= MPT_ULTRA)
+ speed=20;
+ else if (tmp <= MPT_FAST)
+ speed=10;
+ else if (tmp <= MPT_SCSI)
+ speed=5;
+
+ if (np & MPI_SCSIDEVPAGE0_NP_WIDE)
+ speed*=2;
+
+ printk(" %dMB/sec\n", speed);
+
+ } else
+ printk(" Asynchronous.\n");
+ } else {
+ printk("failed\n" );
+ }
+
+ pci_free_consistent(ioc->pcidev, ioc->spi_data.sdp0length * 4,
+ pData, cfg_dma_addr);
+ }
+ break;
+ }
+}
+
+#define is_digit(c) ((c) >= '0' && (c) <= '9')
+#define digit_to_bin(c) ((c) - '0')
+#define is_space(c) ((c) == ' ' || (c) == '\t')
+
+static int skip_spaces(char *ptr, int len)
+{
+ int cnt, c;
+
+ for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --);
+
+ return (len - cnt);
+}
+
+static int get_int_arg(char *ptr, int len, ulong *pv)
+{
+ int cnt, c;
+ ulong v;
+ for (v = 0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) {
+ v = (v * 10) + digit_to_bin(c);
+ }
+
+ if (pv)
+ *pv = v;
+
+ return (len - cnt);
+}
+
+
+static int is_keyword(char *ptr, int len, char *verb)
+{
+ int verb_len = strlen(verb);
+
+ if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len))
+ return verb_len;
+ else
+ return 0;
+}
+
+#define SKIP_SPACES(min_spaces) \
+ if ((arg_len = skip_spaces(ptr,len)) < (min_spaces)) \
+ return -EINVAL; \
+ ptr += arg_len; \
+ len -= arg_len;
+
+#define GET_INT_ARG(v) \
+ if (!(arg_len = get_int_arg(ptr,len, &(v)))) \
+ return -EINVAL; \
+ ptr += arg_len; \
+ len -= arg_len;
+
+static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length)
+{
+ char *ptr = buffer;
+ struct mptscsih_usrcmd cmd, *uc = &cmd;
+ ulong target;
+ int arg_len;
+ int len = length;
+
+ uc->target = uc->cmd = uc->lun = uc->data = 0;
+
+ if ((len > 0) && (ptr[len -1] == '\n'))
+ --len;
+
+ if ((arg_len = is_keyword(ptr, len, "getspeed")) != 0)
+ uc->cmd = UC_GET_SPEED;
+ else
+ arg_len = 0;
+
+ dprintk(("user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd));
+
+ if (!arg_len)
+ return -EINVAL;
+
+ ptr += arg_len;
+ len -= arg_len;
+
+ switch(uc->cmd) {
+ case UC_GET_SPEED:
+ SKIP_SPACES(1);
+ GET_INT_ARG(target);
+ uc->target = target;
+ break;
+ }
+
+ dprintk(("user_command: target=%ld len=%d\n", uc->target, len));
+
+ if (len)
+ return -EINVAL;
+ else {
+ /* process this command ...
+ */
+ mptscsih_exec_user_cmd(ioc, uc);
+ }
+ /* Not yet implemented */
+ return length;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptscsih_proc_info - Return information about MPT adapter
+ *
+ * (linux Scsi_Host_Template.info routine)
+ *
+ * buffer: if write, user data; if read, buffer for user
+ * length: if write, return length;
+ * offset: if write, 0; if read, the current offset into the buffer from
+ * the previous read.
+ * hostno: scsi host number
+ * func: if write = 1; if read = 0
+ */
+int mptscsih_proc_info(char *buffer, char **start, off_t offset,
+ int length, int hostno, int func)
+{
+ MPT_ADAPTER *ioc = NULL;
+ MPT_SCSI_HOST *hd = NULL;
+ int size = 0;
+
+ dprintk(("Called mptscsih_proc_info: hostno=%d, func=%d\n", hostno, func));
+ dprintk(("buffer %p, start=%p (%p) offset=%ld length = %d\n",
+ buffer, start, *start, offset, length));
+
+ for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
+ if ((ioc->sh) && (ioc->sh->host_no == hostno)) {
+ hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+ break;
+ }
+ }
+ if ((ioc == NULL) || (ioc->sh == NULL) || (hd == NULL))
+ return 0;
+
+ if (func) {
+ size = mptscsih_user_command(ioc, buffer, length);
+ } else {
+ if (start)
+ *start = buffer;
+
+ size = mptscsih_host_info(ioc, buffer, offset, length);
+ }
+
+ return size;
+}
+
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static int max_qd = 1;
#if 0
@@ -1777,16 +2516,16 @@ static int numTMrequested = 0;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptscsih_put_msgframe - Wrapper routine to post message frame to F/W.
- * @context: Call back context (ScsiDoneCtx, ScsiScanDvCtx)
- * @id: IOC id number
- * @mf: Pointer to message frame
+ * @context: Call back context (ScsiDoneCtx, ScsiScanDvCtx)
+ * @id: IOC id number
+ * @mf: Pointer to message frame
*
- * Handles the call to mptbase for posting request and queue depth
+ * Handles the call to mptbase for posting request and queue depth
* tracking.
*
* Returns none.
*/
-static void
+static inline void
mptscsih_put_msgframe(int context, int id, MPT_FRAME_HDR *mf)
{
/* Main banana... */
@@ -1973,12 +2712,11 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
/*
* Write SCSI CDB into the message
+ * Should write from cmd_len up to 16, but skip for performance reasons.
*/
cmd_len = SCpnt->cmd_len;
for (ii=0; ii < cmd_len; ii++)
pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
- for (ii=cmd_len; ii < 16; ii++)
- pScsiReq->CDB[ii] = 0;
/* DataLength */
pScsiReq->DataLength = cpu_to_le32(datalen);
@@ -1993,7 +2731,7 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
rc = SUCCESS;
if (datalen == 0) {
/* Add a NULL SGE */
- mpt_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
+ mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
(dma_addr_t) -1);
} else {
/* Add a 32 or 64 bit SGE */
@@ -2057,24 +2795,25 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
}
#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
- if ((dvStatus & MPT_SCSICFG_NEED_DV) || hd->ioc->spi_data.forceDv) {
+ if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
+ (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
unsigned long lflags;
/* Schedule DV if necessary */
spin_lock_irqsave(&dvtaskQ_lock, lflags);
if (!dvtaskQ_active) {
dvtaskQ_active = 1;
spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
- MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
+ MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
SCHEDULE_TASK(&mptscsih_dvTask);
} else {
spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
}
- hd->ioc->spi_data.forceDv = 0;
+ hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
}
/* Trying to do DV to this target, extend timeout.
- * Wait to issue intil flag is clear
+ * Wait to issue intil flag is clear
*/
if (dvStatus & MPT_SCSICFG_DV_PENDING) {
mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
@@ -2153,283 +2892,6 @@ did_error:
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
- * SCSIIORequest_t Message Frame.
- * @hd: Pointer to MPT_SCSI_HOST structure
- * @SCpnt: Pointer to Scsi_Cmnd structure
- * @pReq: Pointer to SCSIIORequest_t structure
- *
- * Returns ...
- */
-static int
-mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
- SCSIIORequest_t *pReq, int req_idx)
-{
- char *psge;
- char *chainSge;
- struct scatterlist *sg;
- int frm_sz;
- int sges_left, sg_done;
- int chain_idx = MPT_HOST_NO_CHAIN;
- int sgeOffset;
- int numSgeSlots, numSgeThisFrame;
- u32 sgflags, sgdir, thisxfer = 0;
- int chain_dma_off = 0;
- int newIndex;
- int ii;
- dma_addr_t v2;
-
- sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
- if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
- sgdir = MPT_TRANSFER_HOST_TO_IOC;
- } else {
- sgdir = MPT_TRANSFER_IOC_TO_HOST;
- }
-
- psge = (char *) &pReq->SGL;
- frm_sz = hd->ioc->req_sz;
-
- /* Map the data portion, if any.
- * sges_left = 0 if no data transfer.
- */
- sges_left = SCpnt->use_sg;
- if (SCpnt->use_sg) {
- sges_left = pci_map_sg(hd->ioc->pcidev,
- (struct scatterlist *) SCpnt->request_buffer,
- SCpnt->use_sg,
- scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
- } else if (SCpnt->request_bufflen) {
- dma_addr_t buf_dma_addr;
- scPrivate *my_priv;
-
- buf_dma_addr = pci_map_single(hd->ioc->pcidev,
- SCpnt->request_buffer,
- SCpnt->request_bufflen,
- scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
-
- /* We hide it here for later unmap. */
- my_priv = (scPrivate *) &SCpnt->SCp;
- my_priv->p1 = (void *)(ulong) buf_dma_addr;
-
- dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
- hd->ioc->name, SCpnt, SCpnt->request_bufflen));
-
- mpt_add_sge((char *) &pReq->SGL,
- 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
- buf_dma_addr);
-
- return SUCCESS;
- }
-
- /* Handle the SG case.
- */
- sg = (struct scatterlist *) SCpnt->request_buffer;
- sg_done = 0;
- sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
- chainSge = NULL;
-
- /* Prior to entering this loop - the following must be set
- * current MF: sgeOffset (bytes)
- * chainSge (Null if original MF is not a chain buffer)
- * sg_done (num SGE done for this MF)
- */
-
-nextSGEset:
- numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
- numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
-
- sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
-
- /* Get first (num - 1) SG elements
- * Skip any SG entries with a length of 0
- * NOTE: at finish, sg and psge pointed to NEXT data/location positions
- */
- for (ii=0; ii < (numSgeThisFrame-1); ii++) {
- thisxfer = sg_dma_len(sg);
- if (thisxfer == 0) {
- sg ++; /* Get next SG element from the OS */
- sg_done++;
- continue;
- }
-
- v2 = sg_dma_address(sg);
- mpt_add_sge(psge, sgflags | thisxfer, v2);
-
- sg++; /* Get next SG element from the OS */
- psge += (sizeof(u32) + sizeof(dma_addr_t));
- sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
- sg_done++;
- }
-
- if (numSgeThisFrame == sges_left) {
- /* Add last element, end of buffer and end of list flags.
- */
- sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
- MPT_SGE_FLAGS_END_OF_BUFFER |
- MPT_SGE_FLAGS_END_OF_LIST;
-
- /* Add last SGE and set termination flags.
- * Note: Last SGE may have a length of 0 - which should be ok.
- */
- thisxfer = sg_dma_len(sg);
-
- v2 = sg_dma_address(sg);
- mpt_add_sge(psge, sgflags | thisxfer, v2);
- /*
- sg++;
- psge += (sizeof(u32) + sizeof(dma_addr_t));
- */
- sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
- sg_done++;
-
- if (chainSge) {
- /* The current buffer is a chain buffer,
- * but there is not another one.
- * Update the chain element
- * Offset and Length fields.
- */
- mpt_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
- } else {
- /* The current buffer is the original MF
- * and there is no Chain buffer.
- */
- pReq->ChainOffset = 0;
- }
- } else {
- /* At least one chain buffer is needed.
- * Complete the first MF
- * - last SGE element, set the LastElement bit
- * - set ChainOffset (words) for orig MF
- * (OR finish previous MF chain buffer)
- * - update MFStructPtr ChainIndex
- * - Populate chain element
- * Also
- * Loop until done.
- */
-
- dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
- hd->ioc->name, sg_done));
-
- /* Set LAST_ELEMENT flag for last non-chain element
- * in the buffer. Since psge points at the NEXT
- * SGE element, go back one SGE element, update the flags
- * and reset the pointer. (Note: sgflags & thisxfer are already
- * set properly).
- */
- if (sg_done) {
- u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
- sgflags = le32_to_cpu(*ptmp);
- sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
- *ptmp = cpu_to_le32(sgflags);
- }
-
- if (chainSge) {
- /* The current buffer is a chain buffer.
- * chainSge points to the previous Chain Element.
- * Update its chain element Offset and Length (must
- * include chain element size) fields.
- * Old chain element is now complete.
- */
- u8 nextChain = (u8) (sgeOffset >> 2);
- sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
- mpt_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
- } else {
- /* The original MF buffer requires a chain buffer -
- * set the offset.
- * Last element in this MF is a chain element.
- */
- pReq->ChainOffset = (u8) (sgeOffset >> 2);
- }
-
- sges_left -= sg_done;
-
-
- /* NOTE: psge points to the beginning of the chain element
- * in current buffer. Get a chain buffer.
- */
- if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)
- return FAILED;
-
- /* Update the tracking arrays.
- * If chainSge == NULL, update ReqToChain, else ChainToChain
- */
- if (chainSge) {
- hd->ChainToChain[chain_idx] = newIndex;
- } else {
- hd->ReqToChain[req_idx] = newIndex;
- }
- chain_idx = newIndex;
- chain_dma_off = hd->ioc->req_sz * chain_idx;
-
- /* Populate the chainSGE for the current buffer.
- * - Set chain buffer pointer to psge and fill
- * out the Address and Flags fields.
- */
- chainSge = (char *) psge;
- dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
- psge, req_idx));
-
- /* Start the SGE for the next buffer
- */
- psge = (char *) (hd->ChainBuffer + chain_dma_off);
- sgeOffset = 0;
- sg_done = 0;
-
- dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
- psge, chain_idx));
-
- /* Start the SGE for the next buffer
- */
-
- goto nextSGEset;
- }
-
- return SUCCESS;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * mptscsih_getFreeChainBuffes - Function to get a free chain
- * from the MPT_SCSI_HOST FreeChainQ.
- * @hd: Pointer to the MPT_SCSI_HOST instance
- * @req_idx: Index of the SCSI IO request frame. (output)
- *
- * return SUCCESS or FAILED
- */
-static int
-mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
-{
- MPT_FRAME_HDR *chainBuf = NULL;
- unsigned long flags;
- int rc = FAILED;
- int chain_idx = MPT_HOST_NO_CHAIN;
-
- //spin_lock_irqsave(&hd->FreeChainQlock, flags);
- spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
- if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
-
- int offset;
-
- chainBuf = hd->FreeChainQ.head;
- Q_DEL_ITEM(&chainBuf->u.frame.linkage);
- offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;
- chain_idx = offset / hd->ioc->req_sz;
- rc = SUCCESS;
- }
- //spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
- spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-
-
- *retIndex = chain_idx;
-
- dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
- hd->ioc->name, *retIndex, chainBuf));
-
- return rc;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
* mptscsih_freeChainBuffers - Function to free chain buffers associated
* with a SCSI IO request
* @hd: Pointer to the MPT_SCSI_HOST instance
@@ -2547,8 +3009,8 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort,
#ifdef MPT_DEBUG_RESET
if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
- printk(MYIOC_s_WARN_FMT
- "TM Handler: IOC Not operational! state 0x%x Calling HardResetHandler\n",
+ printk(MYIOC_s_WARN_FMT
+ "TM Handler: IOC Not operational! state 0x%x Calling HardResetHandler\n",
hd->ioc->name, ioc_raw_state);
}
#endif
@@ -2765,7 +3227,7 @@ mptscsih_abort(Scsi_Cmnd * SCpnt)
hd->abortSCpnt = SCpnt;
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
- SCpnt->target, SCpnt->lun, ctx2abort, NO_SLEEP)
+ SCpnt->target, SCpnt->lun, ctx2abort, NO_SLEEP)
< 0) {
/* The TM request failed and the subsequent FW-reload failed!
@@ -2830,7 +3292,7 @@ mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
}
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
- SCpnt->target, 0, 0, NO_SLEEP)
+ SCpnt->target, 0, 0, NO_SLEEP)
< 0){
/* The TM request failed and the subsequent FW-reload failed!
* Fatal error case.
@@ -2889,13 +3351,13 @@ mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
/* We are now ready to execute the task management request. */
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
- 0, 0, 0, NO_SLEEP)
+ 0, 0, 0, NO_SLEEP)
< 0){
/* The TM request failed and the subsequent FW-reload failed!
* Fatal error case.
*/
- printk(MYIOC_s_WARN_FMT
+ printk(MYIOC_s_WARN_FMT
"Error processing TaskMgmt request (sc=%p)\n",
hd->ioc->name, SCpnt);
hd->tmPending = 0;
@@ -2941,8 +3403,8 @@ mptscsih_host_reset(Scsi_Cmnd *SCpnt)
if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0){
status = FAILED;
} else {
- /* Make sure TM pending is cleared and TM state is set to
- * NONE.
+ /* Make sure TM pending is cleared and TM state is set to
+ * NONE.
*/
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
@@ -2958,7 +3420,7 @@ mptscsih_host_reset(Scsi_Cmnd *SCpnt)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mptscsih_tm_pending_wait - wait for pending task management request to
+ * mptscsih_tm_pending_wait - wait for pending task management request to
* complete.
* @hd: Pointer to MPT host structure.
*
@@ -3114,7 +3576,7 @@ mptscsih_old_abort(Scsi_Cmnd *SCpnt)
* (bottom/unused portion of) MPT request frame.
*/
ptaskfoo = (struct mpt_work_struct *) &mptscsih_ptaskfoo;
- MPT_INIT_WORK(&mptscsih_ptaskfoo, mptscsih_taskmgmt_bh, (void *) SCpnt);
+ MPT_INIT_WORK(&mptscsih_ptaskfoo, mptscsih_taskmgmt_bh, (void *) SCpnt);
SCHEDULE_TASK(ptaskfoo);
} else {
@@ -3245,7 +3707,7 @@ mptscsih_old_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
* (bottom/unused portion of) MPT request frame.
*/
ptaskfoo = (struct mpt_work_struct *) &mptscsih_ptaskfoo;
- MPT_INIT_WORK(&mptscsih_ptaskfoo, mptscsih_taskmgmt_bh, (void *) SCpnt);
+ MPT_INIT_WORK(&mptscsih_ptaskfoo, mptscsih_taskmgmt_bh, (void *) SCpnt);
SCHEDULE_TASK(ptaskfoo);
} else {
@@ -3599,7 +4061,7 @@ mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip)
* 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.
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52)
int
mptscsih_slave_configure(Scsi_Device *device)
{
@@ -3614,15 +4076,21 @@ mptscsih_slave_configure(Scsi_Device *device)
if (!device->tagged_supported ||
!(pTarget->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)) {
+ scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
+ MPT_SCSI_CMD_PER_DEV_HIGH);
} else {
- scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
- device->host->can_queue >> 1);
+ scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
+ MPT_SCSI_CMD_PER_DEV_LOW);
}
}
}
return 0;
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) */
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52) */
void
mptscsih_select_queue_depths(struct Scsi_Host *sh, Scsi_Device *sdList)
{
@@ -3648,113 +4116,32 @@ mptscsih_select_queue_depths(struct Scsi_Host *sh, Scsi_Device *sdList)
for (ii=0; ii < max; ii++) {
pTarget = hd->Targets[ii];
- if (pTarget && !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) {
+ 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));
}
}
}
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) */
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52) */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Private routines...
*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* 19991030 -sralston
- * Return absolute SCSI data direction:
- * 1 = _DATA_OUT
- * 0 = _DIR_NONE
- * -1 = _DATA_IN
- *
- * Changed: 3-20-2002 pdelaney to use the default data
- * direction and the defines set up in the
- * 2.4 kernel series
- * 1 = _DATA_OUT changed to SCSI_DATA_WRITE (1)
- * 0 = _DIR_NONE changed to SCSI_DATA_NONE (3)
- * -1 = _DATA_IN changed to SCSI_DATA_READ (2)
- * If the direction is unknown, fall through to original code.
- *
- * Mid-layer bug fix(): sg interface generates the wrong data
- * direction in some cases. Set the direction the hard way for
- * the most common commands.
- */
-static int
-mptscsih_io_direction(Scsi_Cmnd *cmd)
-{
- switch (cmd->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
- return SCSI_DATA_WRITE;
- break;
- case READ_6:
- case READ_10:
- return SCSI_DATA_READ;
- 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:
- case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER:
- case WRITE_VERIFY: case WRITE_VERIFY_12:
- case COMPARE: case COPY: case COPY_VERIFY:
- case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
- case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12:
- case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT:
- case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK:
- case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG:
- case REASSIGN_BLOCKS:
- case PERSISTENT_RESERVE_OUT:
- case 0xea:
- case 0xa3:
- return SCSI_DATA_WRITE;
-
- /* No data transfer commands */
- case SEEK_6: case SEEK_10:
- case RESERVE: case RELEASE:
- case TEST_UNIT_READY:
- case START_STOP:
- case ALLOW_MEDIUM_REMOVAL:
- return SCSI_DATA_NONE;
-
- /* Conditional data transfer commands */
- case FORMAT_UNIT:
- if (cmd->cmnd[1] & 0x10) /* FmtData (data out phase)? */
- return SCSI_DATA_WRITE;
- else
- return SCSI_DATA_NONE;
-
- case VERIFY:
- if (cmd->cmnd[1] & 0x02) /* VERIFY:BYTCHK (data out phase)? */
- return SCSI_DATA_WRITE;
- else
- return SCSI_DATA_NONE;
-
- case RESERVE_10:
- if (cmd->cmnd[1] & 0x03) /* RESERVE:{LongID|Extent} (data out phase)? */
- return SCSI_DATA_WRITE;
- else
- return SCSI_DATA_NONE;
-
-#if 0
- case REZERO_UNIT: /* (or REWIND) */
- case SPACE:
- case ERASE: case ERASE_10:
- case SYNCHRONIZE_CACHE:
- case LOCK_UNLOCK_CACHE:
-#endif
-
- /* Must be data _IN! */
- default:
- return SCSI_DATA_READ;
- }
-}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* Utility function to copy sense data from the scsi_cmnd buffer
@@ -3803,7 +4190,7 @@ copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply
#ifdef ABORT_FIX
if (sz >= SCSI_STD_SENSE_BYTES) {
- if ((sense_data[02] == ABORTED_COMMAND) &&
+ if ((sense_data[02] == ABORTED_COMMAND) &&
(sense_data[12] == 0x47) && (sense_data[13] == 0x00)){
target->numAborts++;
if ((target->raidVolume == 0) && (target->numAborts > 5)) {
@@ -3896,7 +4283,7 @@ SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* Search the pendingQ for a command with specific index.
- * If found, delete and return mf pointer
+ * If found, delete and return mf pointer
* If not found, return NULL
*/
static MPT_FRAME_HDR *
@@ -4126,6 +4513,13 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
dtmprintk((MYIOC_s_WARN_FMT "Post-Reset handling complete.\n",
ioc->name));
+
+
+ /* 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"));
+
}
return 1; /* currently means nothing really */
@@ -4172,7 +4566,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
case MPI_EVENT_INTEGRATED_RAID: /* 0B */
#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
- /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
+ /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
* if DV disabled. Need to check for target mode.
*/
hd = NULL;
@@ -4188,11 +4582,12 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
- /* New or replaced disk.
+ /* New or replaced disk.
* Set DV flag and schedule DV.
*/
pSpi = &ioc->spi_data;
physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
+ ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
if (pSpi->pIocPg3) {
pPDisk = pSpi->pIocPg3->PhysDisk;
numPDisk =pSpi->pIocPg3->NumPhysDisks;
@@ -4207,6 +4602,16 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
pPDisk++;
numPDisk--;
}
+
+ if (numPDisk == 0) {
+ /* The physical disk that needs DV was not found
+ * in the stored IOC Page 3. The driver must reload
+ * this page. DV routine will set the NEED_DV flag for
+ * all phys disks that have DV_NOT_DONE set.
+ */
+ pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
+ ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
+ }
}
}
}
@@ -4670,7 +5075,7 @@ int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
if (ioop->cdbPtr == NULL) {
return 0;
} else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) ||
- (ioop->cdbPtr[0] == CMD_ReadCapacity) ||
+ (ioop->cdbPtr[0] == CMD_ReadCapacity) ||
(ioop->cdbPtr[0] == 0x43)) {
return 0;
}
@@ -4794,7 +5199,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
}
if (vdev && data) {
- if ((!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) ||
+ 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.
@@ -4877,7 +5282,7 @@ void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byt
factor = MPT_ULTRA320;
/* If RAID, never disable QAS
- * else if non RAID, do not disable
+ * else if non RAID, do not disable
* QAS if bit 1 is set
* bit 1 QAS support, non-raid only
* bit 0 IU support
@@ -5000,8 +5405,8 @@ static void clear_sense_flag(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
#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).
+ * Else set the NEED_DV flag after Read Capacity Issued (disks)
+ * or Mode Sense (cdroms).
*
* Tapes, initTarget will set this flag on completion of Inquiry command.
* Called only if DV_NOT_DONE flag is set
@@ -5037,7 +5442,7 @@ 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
+ * If no Target, 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)
@@ -5286,9 +5691,9 @@ 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
+ dprintk((MYIOC_s_INFO_FMT
"write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
- ioc->name, id, (id | (bus<<8)),
+ ioc->name, id, (id | (bus<<8)),
requested, configuration));
mptscsih_put_msgframe(ScsiDoneCtx, ioc->id, mf);
@@ -5327,8 +5732,8 @@ static void mptscsih_taskmgmt_timeout(unsigned long data)
/* Because we have reset the IOC, no TM requests can be
* pending. So let's make sure the tmPending flag is reset.
*/
- nehprintk((KERN_WARNING MYNAM
- ": %s: mptscsih_taskmgmt_timeout\n",
+ nehprintk((KERN_WARNING MYNAM
+ ": %s: mptscsih_taskmgmt_timeout\n",
hd->ioc->name));
hd->tmPending = 0;
}
@@ -5566,7 +5971,7 @@ static void mptscsih_timer_expired(unsigned long data)
if (hd->tmPending) {
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
return;
- } else
+ } else
hd->tmPending = 1;
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
@@ -5645,7 +6050,7 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
pReq->ActionDataWord = 0; /* Reserved for this action */
//pReq->ActionDataSGE = 0;
- mpt_add_sge((char *)&pReq->ActionDataSGE,
+ mpt_add_sge((char *)&pReq->ActionDataSGE,
MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
@@ -5974,7 +6379,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
if (id == hostId)
id++;
- /* Write SDP1 for all SCSI devices
+ /* Write SDP1 for all SCSI devices
* Alloc memory and set up config buffer
*/
if (hd->is_spi) {
@@ -6097,7 +6502,7 @@ mptscsih_domainValidation(void *arg)
spin_unlock_irqrestore(&dvtaskQ_lock, flags);
/* For this ioc, loop through all devices and do dv to each device.
- * When complete with this ioc, search through the ioc list, and
+ * When complete with this ioc, search through the ioc list, and
* for each scsi ioc found, do dv for all devices. Exit when no
* device needs dv.
*/
@@ -6128,6 +6533,23 @@ mptscsih_domainValidation(void *arg)
if (hd == NULL)
continue;
+ if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
+ mpt_read_ioc_pg_3(ioc);
+ if (ioc->spi_data.pIocPg3) {
+ Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
+ int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
+
+ while (numPDisk) {
+ if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
+ ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
+
+ pPDisk++;
+ numPDisk--;
+ }
+ }
+ ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
+ }
+
maxid = MIN (ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
for (id = 0; id < maxid; id++) {
@@ -6318,7 +6740,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
lun = 0;
bus = 0;
- ddvtprintk((MYIOC_s_NOTE_FMT
+ ddvtprintk((MYIOC_s_NOTE_FMT
"DV started: numIOs %d bus=%d, id %d dv @ %p\n",
ioc->name, atomic_read(&queue_depth), bus, id, &dv));
@@ -6423,7 +6845,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
/* Skip this ID? Set cfg.hdr to force config page write
*/
if ((ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID) &&
- (!(ioc->spi_data.nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE))) {
+ (!(ioc->spi_data.nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE))) {
ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
ioc->name, bus, id, lun));
@@ -6495,11 +6917,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
/* Wide - narrow - wide workaround case
*/
- if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
+ if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
/* Send an untagged command to reset disk Qs corrupted
* when a parity error occurs on a Request Sense.
*/
- if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
+ if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
(hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
@@ -6535,7 +6957,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
rc = hd->pLocal->completion;
if (rc == MPT_SCANDV_GOOD) {
if (hd->pLocal->scsiStatus == STS_BUSY) {
- retcode = 1;
+ if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
+ retcode = 1;
+ else
+ retcode = 0;
+
goto target_done;
}
} else if (rc == MPT_SCANDV_SENSE) {
@@ -6607,7 +7033,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
* Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
* Resetart with a request for U160.
*/
- if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
+ if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
doFallback = 1;
} else {
dv.cmd = MPT_UPDATE_MAX;
@@ -6631,7 +7057,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
}
- } else if (rc == MPT_SCANDV_ISSUE_SENSE)
+ } else if (rc == MPT_SCANDV_ISSUE_SENSE)
doFallback = 1; /* set fallback flag */
else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE))
doFallback = 1; /* set fallback flag */
@@ -6871,7 +7297,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
mdelay (2000);
notDone++;
} else {
- ddvprintk((MYIOC_s_INFO_FMT
+ ddvprintk((MYIOC_s_INFO_FMT
"DV: Reserved Failed.", ioc->name));
goto target_done;
}
@@ -6935,7 +7361,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id)
patt = -1;
continue;
}
- }
+ }
goto target_done;
}
else
@@ -7048,7 +7474,7 @@ target_done:
if (hd->pLocal->completion == MPT_SCANDV_GOOD)
iocmd.flags &= ~MPT_ICFLAG_RESERVED;
} else {
- printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
+ printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
ioc->name, id);
}
}
@@ -7066,7 +7492,7 @@ target_done:
mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
#if 0
- /* Double writes to SDP1 can cause problems,
+ /* Double writes to SDP1 can cause problems,
* skip here since unnecessary
*/
/* Save the final negotiated settings to
@@ -7222,7 +7648,7 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
case MPT_SET_MIN:
ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
hd->ioc->name));
- /* Set page to asynchronous and narrow
+ /* Set page to asynchronous and narrow
* Do not update now, breaks fallback routine. */
width = MPT_NARROW;
offset = 0;
@@ -7244,7 +7670,7 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
case MPT_FALLBACK:
ddvprintk((MYIOC_s_NOTE_FMT
"Fallback: Start: offset %d, factor %x, width %d \n",
- hd->ioc->name, dv->now.offset,
+ hd->ioc->name, dv->now.offset,
dv->now.factor, dv->now.width));
width = dv->now.width;
offset = dv->now.offset;
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 885a1a55c0f1..6c78d41038c1 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -20,7 +20,7 @@
* (mailto:netscape.net)
* (mailto:Pam.Delaney@lsil.com)
*
- * $Id: mptscsih.h,v 1.20 2002/10/17 20:16:00 pdelaney Exp $
+ * $Id: mptscsih.h,v 1.21 2002/12/03 21:26:35 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -73,9 +73,16 @@
* Try to keep these at 2^N-1
*/
#define MPT_FC_CAN_QUEUE 63
-//#define MPT_SCSI_CAN_QUEUE 31
-#define MPT_SCSI_CAN_QUEUE MPT_FC_CAN_QUEUE
-#define MPT_SCSI_CMD_PER_LUN 7
+#if defined MPT_SCSI_USE_NEW_EH
+ #define MPT_SCSI_CAN_QUEUE 127
+#else
+ #define MPT_SCSI_CAN_QUEUE 63
+#endif
+
+#define MPT_SCSI_CMD_PER_DEV_HIGH 31
+#define MPT_SCSI_CMD_PER_DEV_LOW 7
+
+#define MPT_SCSI_CMD_PER_LUN 7
#define MPT_SCSI_MAX_SECTORS 8192
@@ -206,11 +213,16 @@ struct mptscsih_driver_setup
#define x_scsi_dev_reset mptscsih_dev_reset
#define x_scsi_host_reset mptscsih_host_reset
#define x_scsi_bios_param mptscsih_bios_param
-#define x_scsi_slave_configure mptscsih_slave_configure
#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_configure mptscsih_slave_configure
+#else
+#define x_scsi_select_queue_depths mptscsih_select_queue_depths
+#endif
+#define x_scsi_proc_info mptscsih_proc_info
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -237,8 +249,14 @@ extern int x_scsi_bios_param(Disk *, struct block_device *, int *);
#else
extern int x_scsi_bios_param(Disk *, kdev_t, int *);
#endif
-extern int x_scsi_slave_configure(Scsi_Device *);
extern void x_scsi_taskmgmt_bh(void *);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52)
+extern int x_scsi_slave_configure(Scsi_Device *);
+#else
+extern void x_scsi_select_queue_depths(struct Scsi_Host *, Scsi_Device *);
+#endif
+
+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
@@ -248,14 +266,19 @@ extern void x_scsi_taskmgmt_bh(void *);
#ifdef MPT_SCSI_USE_NEW_EH
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,52)
#define MPT_SCSIHOST { \
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, \
+ .slave_configure = x_scsi_slave_configure, \
+ .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, \
@@ -275,6 +298,7 @@ extern void x_scsi_taskmgmt_bh(void *);
#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, \