Commit 14d0f0b0 authored by Kashyap, Desai's avatar Kashyap, Desai Committed by James Bottomley

[SCSI] mpt fusion: Fixing 1078 data corruption issue for 36GB memory region

The reason for this change is there is a data corruption when four different
physical memory regions in the 36GB to 37GB region are
accessed. This is only affecting 1078.

The solution is we need to use different addressing when filling in
the scatter gather table for the effected memory regions.  So instead
of snooping on all four different memory holes, we treat any physical
addresses in the 36GB address with the same algorithm.

The fix is explained below
1) Ensure that the message frames are NOT located in the trouble
region. There is no remapping available for message frames, they must
be allocated outside the problem region.
2) Ensure that Sense buffers are NOT in the trouble region. There is
no remapping available.
3) Walk through the SGE entries and if any are inside the trouble region
   then they need to be remapped as discussed below.
	1) Set the Local Address bit in the SGE Flags field.
  	MPI_SGE_FLAGS_LOCAL_ADDRESS
  	2) Ensure we are using 64-bit SGEs
  	3) Set MSb (Bit 63) of the 64-bit address, this will indicate buffer
	location is Host Memory.
Signed-off-by: default avatarKashyap Desai <kadesai@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 238ddbb9
This diff is collapsed.
...@@ -76,8 +76,8 @@ ...@@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR #define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR
#endif #endif
#define MPT_LINUX_VERSION_COMMON "3.04.07" #define MPT_LINUX_VERSION_COMMON "3.04.08"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.07" #define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.08"
#define WHAT_MAGIC_STRING "@" "(" "#" ")" #define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \ #define show_mptmod_ver(s,ver) \
...@@ -134,6 +134,7 @@ ...@@ -134,6 +134,7 @@
#define MPT_COALESCING_TIMEOUT 0x10 #define MPT_COALESCING_TIMEOUT 0x10
/* /*
* SCSI transfer rate defines. * SCSI transfer rate defines.
*/ */
...@@ -564,6 +565,10 @@ struct mptfc_rport_info ...@@ -564,6 +565,10 @@ struct mptfc_rport_info
u8 flags; u8 flags;
}; };
typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr);
typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length,
dma_addr_t dma_addr);
/* /*
* Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
*/ */
...@@ -600,6 +605,10 @@ typedef struct _MPT_ADAPTER ...@@ -600,6 +605,10 @@ typedef struct _MPT_ADAPTER
int reply_depth; /* Num Allocated reply frames */ int reply_depth; /* Num Allocated reply frames */
int reply_sz; /* Reply frame size */ int reply_sz; /* Reply frame size */
int num_chain; /* Number of chain buffers */ int num_chain; /* Number of chain buffers */
MPT_ADD_SGE add_sge; /* Pointer to add_sge
function */
MPT_ADD_CHAIN add_chain; /* Pointer to add_chain
function */
/* Pool of buffers for chaining. ReqToChain /* Pool of buffers for chaining. ReqToChain
* and ChainToChain track index of chain buffers. * and ChainToChain track index of chain buffers.
* ChainBuffer (DMA) virt/phys addresses. * ChainBuffer (DMA) virt/phys addresses.
...@@ -711,12 +720,15 @@ typedef struct _MPT_ADAPTER ...@@ -711,12 +720,15 @@ typedef struct _MPT_ADAPTER
struct workqueue_struct *fc_rescan_work_q; struct workqueue_struct *fc_rescan_work_q;
struct scsi_cmnd **ScsiLookup; struct scsi_cmnd **ScsiLookup;
spinlock_t scsi_lookup_lock; spinlock_t scsi_lookup_lock;
u64 dma_mask;
char reset_work_q_name[20]; char reset_work_q_name[20];
struct workqueue_struct *reset_work_q; struct workqueue_struct *reset_work_q;
struct delayed_work fault_reset_work; struct delayed_work fault_reset_work;
spinlock_t fault_reset_work_lock; spinlock_t fault_reset_work_lock;
u8 sg_addr_size;
u8 SGE_size;
} MPT_ADAPTER; } MPT_ADAPTER;
/* /*
...@@ -753,13 +765,14 @@ typedef struct _mpt_sge { ...@@ -753,13 +765,14 @@ typedef struct _mpt_sge {
dma_addr_t Address; dma_addr_t Address;
} MptSge_t; } MptSge_t;
#define mpt_addr_size() \
((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SGE_FLAGS_64_BIT_ADDRESSING : \
MPI_SGE_FLAGS_32_BIT_ADDRESSING)
#define mpt_msg_flags() \ #define mpt_msg_flags(ioc) \
((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \ (ioc->sg_addr_size == sizeof(u64)) ? \
MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32) MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \
MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32
#define MPT_SGE_FLAGS_64_BIT_ADDRESSING \
(MPI_SGE_FLAGS_64_BIT_ADDRESSING << MPI_SGE_FLAGS_SHIFT)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* /*
...@@ -909,7 +922,6 @@ extern MPT_FRAME_HDR *mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc); ...@@ -909,7 +922,6 @@ extern MPT_FRAME_HDR *mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc);
extern void mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); extern void mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
extern void mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); extern void mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
extern void mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); extern void mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
extern void mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr);
extern int mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag); extern int mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag);
extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp); extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);
...@@ -959,7 +971,6 @@ extern int mpt_fwfault_debug; ...@@ -959,7 +971,6 @@ extern int mpt_fwfault_debug;
#define MPT_SGE_FLAGS_END_OF_BUFFER (0x40000000) #define MPT_SGE_FLAGS_END_OF_BUFFER (0x40000000)
#define MPT_SGE_FLAGS_LOCAL_ADDRESS (0x08000000) #define MPT_SGE_FLAGS_LOCAL_ADDRESS (0x08000000)
#define MPT_SGE_FLAGS_DIRECTION (0x04000000) #define MPT_SGE_FLAGS_DIRECTION (0x04000000)
#define MPT_SGE_FLAGS_ADDRESSING (mpt_addr_size() << MPI_SGE_FLAGS_SHIFT)
#define MPT_SGE_FLAGS_END_OF_LIST (0x01000000) #define MPT_SGE_FLAGS_END_OF_LIST (0x01000000)
#define MPT_SGE_FLAGS_TRANSACTION_ELEMENT (0x00000000) #define MPT_SGE_FLAGS_TRANSACTION_ELEMENT (0x00000000)
...@@ -972,14 +983,12 @@ extern int mpt_fwfault_debug; ...@@ -972,14 +983,12 @@ extern int mpt_fwfault_debug;
MPT_SGE_FLAGS_END_OF_BUFFER | \ MPT_SGE_FLAGS_END_OF_BUFFER | \
MPT_SGE_FLAGS_END_OF_LIST | \ MPT_SGE_FLAGS_END_OF_LIST | \
MPT_SGE_FLAGS_SIMPLE_ELEMENT | \ MPT_SGE_FLAGS_SIMPLE_ELEMENT | \
MPT_SGE_FLAGS_ADDRESSING | \
MPT_TRANSFER_IOC_TO_HOST) MPT_TRANSFER_IOC_TO_HOST)
#define MPT_SGE_FLAGS_SSIMPLE_WRITE \ #define MPT_SGE_FLAGS_SSIMPLE_WRITE \
(MPT_SGE_FLAGS_LAST_ELEMENT | \ (MPT_SGE_FLAGS_LAST_ELEMENT | \
MPT_SGE_FLAGS_END_OF_BUFFER | \ MPT_SGE_FLAGS_END_OF_BUFFER | \
MPT_SGE_FLAGS_END_OF_LIST | \ MPT_SGE_FLAGS_END_OF_LIST | \
MPT_SGE_FLAGS_SIMPLE_ELEMENT | \ MPT_SGE_FLAGS_SIMPLE_ELEMENT | \
MPT_SGE_FLAGS_ADDRESSING | \
MPT_TRANSFER_HOST_TO_IOC) MPT_TRANSFER_HOST_TO_IOC)
/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......
...@@ -841,8 +841,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) ...@@ -841,8 +841,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
* 96 8 * 96 8
* 64 4 * 64 4
*/ */
maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t)) maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) -
/ (sizeof(dma_addr_t) + sizeof(u32)); sizeof(FWDownloadTCSGE_t))
/ iocp->SGE_size;
if (numfrags > maxfrags) { if (numfrags > maxfrags) {
ret = -EMLINK; ret = -EMLINK;
goto fwdl_out; goto fwdl_out;
...@@ -870,7 +871,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) ...@@ -870,7 +871,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
if (nib == 0 || nib == 3) { if (nib == 0 || nib == 3) {
; ;
} else if (sgIn->Address) { } else if (sgIn->Address) {
mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address); iocp->add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
n++; n++;
if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) { if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - " printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - "
...@@ -882,7 +883,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) ...@@ -882,7 +883,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
} }
sgIn++; sgIn++;
bl++; bl++;
sgOut += (sizeof(dma_addr_t) + sizeof(u32)); sgOut += iocp->SGE_size;
} }
DBG_DUMP_FW_DOWNLOAD(iocp, (u32 *)mf, numfrags); DBG_DUMP_FW_DOWNLOAD(iocp, (u32 *)mf, numfrags);
...@@ -1003,7 +1004,7 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, ...@@ -1003,7 +1004,7 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
* *
*/ */
sgl = sglbuf; sgl = sglbuf;
sg_spill = ((ioc->req_sz - sge_offset)/(sizeof(dma_addr_t) + sizeof(u32))) - 1; sg_spill = ((ioc->req_sz - sge_offset)/ioc->SGE_size) - 1;
while (bytes_allocd < bytes) { while (bytes_allocd < bytes) {
this_alloc = min(alloc_sz, bytes-bytes_allocd); this_alloc = min(alloc_sz, bytes-bytes_allocd);
buflist[buflist_ent].len = this_alloc; buflist[buflist_ent].len = this_alloc;
...@@ -1024,8 +1025,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, ...@@ -1024,8 +1025,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
dma_addr_t dma_addr; dma_addr_t dma_addr;
bytes_allocd += this_alloc; bytes_allocd += this_alloc;
sgl->FlagsLength = (0x10000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|this_alloc); sgl->FlagsLength = (0x10000000|sgdir|this_alloc);
dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir); dma_addr = pci_map_single(ioc->pcidev,
buflist[buflist_ent].kptr, this_alloc, dir);
sgl->Address = dma_addr; sgl->Address = dma_addr;
fragcnt++; fragcnt++;
...@@ -1799,9 +1801,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ...@@ -1799,9 +1801,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
*/ */
sz = karg.dataSgeOffset * 4; sz = karg.dataSgeOffset * 4;
if (karg.dataInSize > 0) if (karg.dataInSize > 0)
sz += sizeof(dma_addr_t) + sizeof(u32); sz += ioc->SGE_size;
if (karg.dataOutSize > 0) if (karg.dataOutSize > 0)
sz += sizeof(dma_addr_t) + sizeof(u32); sz += ioc->SGE_size;
if (sz > ioc->req_sz) { if (sz > ioc->req_sz) {
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
...@@ -1893,7 +1895,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ...@@ -1893,7 +1895,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
} }
pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
pScsiReq->MsgFlags |= mpt_msg_flags(); pScsiReq->MsgFlags |= mpt_msg_flags(ioc);
/* verify that app has not requested /* verify that app has not requested
...@@ -1979,7 +1981,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ...@@ -1979,7 +1981,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
int dataSize; int dataSize;
pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
pScsiReq->MsgFlags |= mpt_msg_flags(); pScsiReq->MsgFlags |= mpt_msg_flags(ioc);
/* verify that app has not requested /* verify that app has not requested
...@@ -2123,8 +2125,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ...@@ -2123,8 +2125,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
if (karg.dataInSize > 0) { if (karg.dataInSize > 0) {
flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
MPI_SGE_FLAGS_END_OF_BUFFER | MPI_SGE_FLAGS_END_OF_BUFFER |
MPI_SGE_FLAGS_DIRECTION | MPI_SGE_FLAGS_DIRECTION)
mpt_addr_size() )
<< MPI_SGE_FLAGS_SHIFT; << MPI_SGE_FLAGS_SHIFT;
} else { } else {
flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
...@@ -2141,8 +2142,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ...@@ -2141,8 +2142,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
/* Set up this SGE. /* Set up this SGE.
* Copy to MF and to sglbuf * Copy to MF and to sglbuf
*/ */
mpt_add_sge(psge, flagsLength, dma_addr_out); ioc->add_sge(psge, flagsLength, dma_addr_out);
psge += (sizeof(u32) + sizeof(dma_addr_t)); psge += ioc->SGE_size;
/* Copy user data to kernel space. /* Copy user data to kernel space.
*/ */
...@@ -2175,13 +2176,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ...@@ -2175,13 +2176,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
/* Set up this SGE /* Set up this SGE
* Copy to MF and to sglbuf * Copy to MF and to sglbuf
*/ */
mpt_add_sge(psge, flagsLength, dma_addr_in); ioc->add_sge(psge, flagsLength, dma_addr_in);
} }
} }
} else { } else {
/* Add a NULL SGE /* Add a NULL SGE
*/ */
mpt_add_sge(psge, flagsLength, (dma_addr_t) -1); ioc->add_sge(psge, flagsLength, (dma_addr_t) -1);
} }
ioc->ioctl->wait_done = 0; ioc->ioctl->wait_done = 0;
...@@ -2498,7 +2499,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) ...@@ -2498,7 +2499,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma); pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
if (!pbuf) if (!pbuf)
goto out; goto out;
mpt_add_sge((char *)&IstwiRWRequest->SGL, ioc->add_sge((char *)&IstwiRWRequest->SGL,
(MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma); (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
ioc->ioctl->wait_done = 0; ioc->ioctl->wait_done = 0;
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#define MPT_DEBUG_FC 0x00080000 #define MPT_DEBUG_FC 0x00080000
#define MPT_DEBUG_SAS 0x00100000 #define MPT_DEBUG_SAS 0x00100000
#define MPT_DEBUG_SAS_WIDE 0x00200000 #define MPT_DEBUG_SAS_WIDE 0x00200000
#define MPT_DEBUG_36GB_MEM 0x00400000
/* /*
* CONFIG_FUSION_LOGGING - enabled in Kconfig * CONFIG_FUSION_LOGGING - enabled in Kconfig
...@@ -135,6 +136,8 @@ ...@@ -135,6 +136,8 @@
#define dsaswideprintk(IOC, CMD) \ #define dsaswideprintk(IOC, CMD) \
MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE) MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE)
#define d36memprintk(IOC, CMD) \
MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_36GB_MEM)
/* /*
......
...@@ -1251,17 +1251,15 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1251,17 +1251,15 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* A slightly different algorithm is required for * A slightly different algorithm is required for
* 64bit SGEs. * 64bit SGEs.
*/ */
scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); scale = ioc->req_sz/ioc->SGE_size;
if (sizeof(dma_addr_t) == sizeof(u64)) { if (ioc->sg_addr_size == sizeof(u64)) {
numSGE = (scale - 1) * numSGE = (scale - 1) *
(ioc->facts.MaxChainDepth-1) + scale + (ioc->facts.MaxChainDepth-1) + scale +
(ioc->req_sz - 60) / (sizeof(dma_addr_t) + (ioc->req_sz - 60) / ioc->SGE_size;
sizeof(u32));
} else { } else {
numSGE = 1 + (scale - 1) * numSGE = 1 + (scale - 1) *
(ioc->facts.MaxChainDepth-1) + scale + (ioc->facts.MaxChainDepth-1) + scale +
(ioc->req_sz - 64) / (sizeof(dma_addr_t) + (ioc->req_sz - 64) / ioc->SGE_size;
sizeof(u32));
} }
if (numSGE < sh->sg_tablesize) { if (numSGE < sh->sg_tablesize) {
......
...@@ -1319,15 +1319,15 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, ...@@ -1319,15 +1319,15 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
/* request */ /* request */
flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT | flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
MPI_SGE_FLAGS_END_OF_BUFFER | MPI_SGE_FLAGS_END_OF_BUFFER |
MPI_SGE_FLAGS_DIRECTION | MPI_SGE_FLAGS_DIRECTION)
mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT; << MPI_SGE_FLAGS_SHIFT;
flagsLength |= (req->data_len - 4); flagsLength |= (req->data_len - 4);
dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio), dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
req->data_len, PCI_DMA_BIDIRECTIONAL); req->data_len, PCI_DMA_BIDIRECTIONAL);
if (!dma_addr_out) if (!dma_addr_out)
goto put_mf; goto put_mf;
mpt_add_sge(psge, flagsLength, dma_addr_out); ioc->add_sge(psge, flagsLength, dma_addr_out);
psge += (sizeof(u32) + sizeof(dma_addr_t)); psge += (sizeof(u32) + sizeof(dma_addr_t));
/* response */ /* response */
...@@ -1337,7 +1337,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, ...@@ -1337,7 +1337,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
rsp->data_len, PCI_DMA_BIDIRECTIONAL); rsp->data_len, PCI_DMA_BIDIRECTIONAL);
if (!dma_addr_in) if (!dma_addr_in)
goto unmap; goto unmap;
mpt_add_sge(psge, flagsLength, dma_addr_in); ioc->add_sge(psge, flagsLength, dma_addr_in);
mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf); mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
...@@ -3211,17 +3211,15 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -3211,17 +3211,15 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* A slightly different algorithm is required for * A slightly different algorithm is required for
* 64bit SGEs. * 64bit SGEs.
*/ */
scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); scale = ioc->req_sz/ioc->SGE_size;
if (sizeof(dma_addr_t) == sizeof(u64)) { if (ioc->sg_addr_size == sizeof(u64)) {
numSGE = (scale - 1) * numSGE = (scale - 1) *
(ioc->facts.MaxChainDepth-1) + scale + (ioc->facts.MaxChainDepth-1) + scale +
(ioc->req_sz - 60) / (sizeof(dma_addr_t) + (ioc->req_sz - 60) / ioc->SGE_size;
sizeof(u32));
} else { } else {
numSGE = 1 + (scale - 1) * numSGE = 1 + (scale - 1) *
(ioc->facts.MaxChainDepth-1) + scale + (ioc->facts.MaxChainDepth-1) + scale +
(ioc->req_sz - 64) / (sizeof(dma_addr_t) + (ioc->req_sz - 64) / ioc->SGE_size;
sizeof(u32));
} }
if (numSGE < sh->sg_tablesize) { if (numSGE < sh->sg_tablesize) {
......
...@@ -113,69 +113,6 @@ int mptscsih_resume(struct pci_dev *pdev); ...@@ -113,69 +113,6 @@ int mptscsih_resume(struct pci_dev *pdev);
#define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE #define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* 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() */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* /*
...@@ -281,10 +218,10 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, ...@@ -281,10 +218,10 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
*/ */
nextSGEset: nextSGEset:
numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) ); numSgeSlots = ((frm_sz - sgeOffset) / ioc->SGE_size);
numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots; numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir; sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | sgdir;
/* Get first (num - 1) SG elements /* Get first (num - 1) SG elements
* Skip any SG entries with a length of 0 * Skip any SG entries with a length of 0
...@@ -299,11 +236,11 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, ...@@ -299,11 +236,11 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
} }
v2 = sg_dma_address(sg); v2 = sg_dma_address(sg);
mptscsih_add_sge(psge, sgflags | thisxfer, v2); ioc->add_sge(psge, sgflags | thisxfer, v2);
sg = sg_next(sg); /* Get next SG element from the OS */ sg = sg_next(sg); /* Get next SG element from the OS */
psge += (sizeof(u32) + sizeof(dma_addr_t)); psge += ioc->SGE_size;
sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); sgeOffset += ioc->SGE_size;
sg_done++; sg_done++;
} }
...@@ -320,12 +257,8 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, ...@@ -320,12 +257,8 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
thisxfer = sg_dma_len(sg); thisxfer = sg_dma_len(sg);
v2 = sg_dma_address(sg); v2 = sg_dma_address(sg);
mptscsih_add_sge(psge, sgflags | thisxfer, v2); ioc->add_sge(psge, sgflags | thisxfer, v2);
/* sgeOffset += ioc->SGE_size;
sg = sg_next(sg);
psge += (sizeof(u32) + sizeof(dma_addr_t));
*/
sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
sg_done++; sg_done++;
if (chainSge) { if (chainSge) {
...@@ -334,7 +267,8 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, ...@@ -334,7 +267,8 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
* Update the chain element * Update the chain element
* Offset and Length fields. * Offset and Length fields.
*/ */
mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off); ioc->add_chain((char *)chainSge, 0, sgeOffset,
ioc->ChainBufferDMA + chain_dma_off);
} else { } else {
/* The current buffer is the original MF /* The current buffer is the original MF
* and there is no Chain buffer. * and there is no Chain buffer.
...@@ -367,7 +301,7 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, ...@@ -367,7 +301,7 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
* set properly). * set properly).
*/ */
if (sg_done) { if (sg_done) {
u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t))); u32 *ptmp = (u32 *) (psge - ioc->SGE_size);
sgflags = le32_to_cpu(*ptmp); sgflags = le32_to_cpu(*ptmp);
sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT; sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
*ptmp = cpu_to_le32(sgflags); *ptmp = cpu_to_le32(sgflags);
...@@ -381,8 +315,9 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, ...@@ -381,8 +315,9 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
* Old chain element is now complete. * Old chain element is now complete.
*/ */
u8 nextChain = (u8) (sgeOffset >> 2); u8 nextChain = (u8) (sgeOffset >> 2);
sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); sgeOffset += ioc->SGE_size;
mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off); ioc->add_chain((char *)chainSge, nextChain, sgeOffset,
ioc->ChainBufferDMA + chain_dma_off);
} else { } else {
/* The original MF buffer requires a chain buffer - /* The original MF buffer requires a chain buffer -
* set the offset. * set the offset.
...@@ -1422,7 +1357,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) ...@@ -1422,7 +1357,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
pScsiReq->CDBLength = SCpnt->cmd_len; pScsiReq->CDBLength = SCpnt->cmd_len;
pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
pScsiReq->Reserved = 0; pScsiReq->Reserved = 0;
pScsiReq->MsgFlags = mpt_msg_flags(); pScsiReq->MsgFlags = mpt_msg_flags(ioc);
int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
pScsiReq->Control = cpu_to_le32(scsictl); pScsiReq->Control = cpu_to_le32(scsictl);
...@@ -1448,7 +1383,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) ...@@ -1448,7 +1383,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
*/ */
if (datalen == 0) { if (datalen == 0) {
/* Add a NULL SGE */ /* Add a NULL SGE */
mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0, ioc->add_sge((char *)&pScsiReq->SGL,
MPT_SGE_FLAGS_SSIMPLE_READ | 0,
(dma_addr_t) -1); (dma_addr_t) -1);
} else { } else {
/* Add a 32 or 64 bit SGE */ /* Add a 32 or 64 bit SGE */
...@@ -3172,7 +3108,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) ...@@ -3172,7 +3108,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
pScsiReq->Reserved = 0; pScsiReq->Reserved = 0;
pScsiReq->MsgFlags = mpt_msg_flags(); pScsiReq->MsgFlags = mpt_msg_flags(ioc);
/* MsgContext set in mpt_get_msg_fram call */ /* MsgContext set in mpt_get_msg_fram call */
int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
...@@ -3199,11 +3135,11 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) ...@@ -3199,11 +3135,11 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
ioc->name, cmd, io->channel, io->id, io->lun)); ioc->name, cmd, io->channel, io->id, io->lun));
if (dir == MPI_SCSIIO_CONTROL_READ) { if (dir == MPI_SCSIIO_CONTROL_READ) {
mpt_add_sge((char *) &pScsiReq->SGL, ioc->add_sge((char *) &pScsiReq->SGL,
MPT_SGE_FLAGS_SSIMPLE_READ | io->size, MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
io->data_dma); io->data_dma);
} else { } else {
mpt_add_sge((char *) &pScsiReq->SGL, ioc->add_sge((char *) &pScsiReq->SGL,
MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
io->data_dma); io->data_dma);
} }
......
...@@ -300,7 +300,7 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id) ...@@ -300,7 +300,7 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id)
flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
(IOCPage4Ptr->Header.PageLength + ii) * 4; (IOCPage4Ptr->Header.PageLength + ii) * 4;
mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
...@@ -643,7 +643,7 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) ...@@ -643,7 +643,7 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
pReq->Reserved2 = 0; pReq->Reserved2 = 0;
pReq->ActionDataWord = 0; /* Reserved for this action */ pReq->ActionDataWord = 0; /* Reserved for this action */
mpt_add_sge((char *)&pReq->ActionDataSGE, ioc->add_sge((char *)&pReq->ActionDataSGE,
MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n", ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n",
...@@ -1423,17 +1423,15 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1423,17 +1423,15 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* A slightly different algorithm is required for * A slightly different algorithm is required for
* 64bit SGEs. * 64bit SGEs.
*/ */
scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); scale = ioc->req_sz/ioc->SGE_size;
if (sizeof(dma_addr_t) == sizeof(u64)) { if (ioc->sg_addr_size == sizeof(u64)) {
numSGE = (scale - 1) * numSGE = (scale - 1) *
(ioc->facts.MaxChainDepth-1) + scale + (ioc->facts.MaxChainDepth-1) + scale +
(ioc->req_sz - 60) / (sizeof(dma_addr_t) + (ioc->req_sz - 60) / ioc->SGE_size;
sizeof(u32));
} else { } else {
numSGE = 1 + (scale - 1) * numSGE = 1 + (scale - 1) *
(ioc->facts.MaxChainDepth-1) + scale + (ioc->facts.MaxChainDepth-1) + scale +
(ioc->req_sz - 64) / (sizeof(dma_addr_t) + (ioc->req_sz - 64) / ioc->SGE_size;
sizeof(u32));
} }
if (numSGE < sh->sg_tablesize) { if (numSGE < sh->sg_tablesize) {
......
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