diff options
author | Kashyap, Desai <kashyap.desai@lsi.com> | 2009-05-29 07:07:04 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-09 18:21:31 -0400 |
commit | 14d0f0b063f5363984dd305a792854f9c23e9e97 (patch) | |
tree | 6d3e62845bc5273244f3b9ec535159cf5a8bdbc6 /drivers/message/fusion/mptctl.c | |
parent | 238ddbb98c327a7392ced5ae65216c55969749ea (diff) |
[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: Kashyap Desai <kadesai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/message/fusion/mptctl.c')
-rw-r--r-- | drivers/message/fusion/mptctl.c | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index c63817117c0a..bece386f1d4b 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c | |||
@@ -841,8 +841,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
841 | * 96 8 | 841 | * 96 8 |
842 | * 64 4 | 842 | * 64 4 |
843 | */ | 843 | */ |
844 | maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t)) | 844 | maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - |
845 | / (sizeof(dma_addr_t) + sizeof(u32)); | 845 | sizeof(FWDownloadTCSGE_t)) |
846 | / iocp->SGE_size; | ||
846 | if (numfrags > maxfrags) { | 847 | if (numfrags > maxfrags) { |
847 | ret = -EMLINK; | 848 | ret = -EMLINK; |
848 | goto fwdl_out; | 849 | goto fwdl_out; |
@@ -870,7 +871,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
870 | if (nib == 0 || nib == 3) { | 871 | if (nib == 0 || nib == 3) { |
871 | ; | 872 | ; |
872 | } else if (sgIn->Address) { | 873 | } else if (sgIn->Address) { |
873 | mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address); | 874 | iocp->add_sge(sgOut, sgIn->FlagsLength, sgIn->Address); |
874 | n++; | 875 | n++; |
875 | if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) { | 876 | if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) { |
876 | printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - " | 877 | 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 | } | 883 | } |
883 | sgIn++; | 884 | sgIn++; |
884 | bl++; | 885 | bl++; |
885 | sgOut += (sizeof(dma_addr_t) + sizeof(u32)); | 886 | sgOut += iocp->SGE_size; |
886 | } | 887 | } |
887 | 888 | ||
888 | DBG_DUMP_FW_DOWNLOAD(iocp, (u32 *)mf, numfrags); | 889 | 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 | * | 1004 | * |
1004 | */ | 1005 | */ |
1005 | sgl = sglbuf; | 1006 | sgl = sglbuf; |
1006 | sg_spill = ((ioc->req_sz - sge_offset)/(sizeof(dma_addr_t) + sizeof(u32))) - 1; | 1007 | sg_spill = ((ioc->req_sz - sge_offset)/ioc->SGE_size) - 1; |
1007 | while (bytes_allocd < bytes) { | 1008 | while (bytes_allocd < bytes) { |
1008 | this_alloc = min(alloc_sz, bytes-bytes_allocd); | 1009 | this_alloc = min(alloc_sz, bytes-bytes_allocd); |
1009 | buflist[buflist_ent].len = this_alloc; | 1010 | buflist[buflist_ent].len = this_alloc; |
@@ -1024,8 +1025,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, | |||
1024 | dma_addr_t dma_addr; | 1025 | dma_addr_t dma_addr; |
1025 | 1026 | ||
1026 | bytes_allocd += this_alloc; | 1027 | bytes_allocd += this_alloc; |
1027 | sgl->FlagsLength = (0x10000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|this_alloc); | 1028 | sgl->FlagsLength = (0x10000000|sgdir|this_alloc); |
1028 | dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir); | 1029 | dma_addr = pci_map_single(ioc->pcidev, |
1030 | buflist[buflist_ent].kptr, this_alloc, dir); | ||
1029 | sgl->Address = dma_addr; | 1031 | sgl->Address = dma_addr; |
1030 | 1032 | ||
1031 | fragcnt++; | 1033 | fragcnt++; |
@@ -1799,9 +1801,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
1799 | */ | 1801 | */ |
1800 | sz = karg.dataSgeOffset * 4; | 1802 | sz = karg.dataSgeOffset * 4; |
1801 | if (karg.dataInSize > 0) | 1803 | if (karg.dataInSize > 0) |
1802 | sz += sizeof(dma_addr_t) + sizeof(u32); | 1804 | sz += ioc->SGE_size; |
1803 | if (karg.dataOutSize > 0) | 1805 | if (karg.dataOutSize > 0) |
1804 | sz += sizeof(dma_addr_t) + sizeof(u32); | 1806 | sz += ioc->SGE_size; |
1805 | 1807 | ||
1806 | if (sz > ioc->req_sz) { | 1808 | if (sz > ioc->req_sz) { |
1807 | printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " | 1809 | 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 | } | 1895 | } |
1894 | 1896 | ||
1895 | pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; | 1897 | pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; |
1896 | pScsiReq->MsgFlags |= mpt_msg_flags(); | 1898 | pScsiReq->MsgFlags |= mpt_msg_flags(ioc); |
1897 | 1899 | ||
1898 | 1900 | ||
1899 | /* verify that app has not requested | 1901 | /* verify that app has not requested |
@@ -1979,7 +1981,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
1979 | int dataSize; | 1981 | int dataSize; |
1980 | 1982 | ||
1981 | pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; | 1983 | pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; |
1982 | pScsiReq->MsgFlags |= mpt_msg_flags(); | 1984 | pScsiReq->MsgFlags |= mpt_msg_flags(ioc); |
1983 | 1985 | ||
1984 | 1986 | ||
1985 | /* verify that app has not requested | 1987 | /* verify that app has not requested |
@@ -2123,8 +2125,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
2123 | if (karg.dataInSize > 0) { | 2125 | if (karg.dataInSize > 0) { |
2124 | flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | | 2126 | flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | |
2125 | MPI_SGE_FLAGS_END_OF_BUFFER | | 2127 | MPI_SGE_FLAGS_END_OF_BUFFER | |
2126 | MPI_SGE_FLAGS_DIRECTION | | 2128 | MPI_SGE_FLAGS_DIRECTION) |
2127 | mpt_addr_size() ) | ||
2128 | << MPI_SGE_FLAGS_SHIFT; | 2129 | << MPI_SGE_FLAGS_SHIFT; |
2129 | } else { | 2130 | } else { |
2130 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; | 2131 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; |
@@ -2141,8 +2142,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
2141 | /* Set up this SGE. | 2142 | /* Set up this SGE. |
2142 | * Copy to MF and to sglbuf | 2143 | * Copy to MF and to sglbuf |
2143 | */ | 2144 | */ |
2144 | mpt_add_sge(psge, flagsLength, dma_addr_out); | 2145 | ioc->add_sge(psge, flagsLength, dma_addr_out); |
2145 | psge += (sizeof(u32) + sizeof(dma_addr_t)); | 2146 | psge += ioc->SGE_size; |
2146 | 2147 | ||
2147 | /* Copy user data to kernel space. | 2148 | /* Copy user data to kernel space. |
2148 | */ | 2149 | */ |
@@ -2175,13 +2176,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
2175 | /* Set up this SGE | 2176 | /* Set up this SGE |
2176 | * Copy to MF and to sglbuf | 2177 | * Copy to MF and to sglbuf |
2177 | */ | 2178 | */ |
2178 | mpt_add_sge(psge, flagsLength, dma_addr_in); | 2179 | ioc->add_sge(psge, flagsLength, dma_addr_in); |
2179 | } | 2180 | } |
2180 | } | 2181 | } |
2181 | } else { | 2182 | } else { |
2182 | /* Add a NULL SGE | 2183 | /* Add a NULL SGE |
2183 | */ | 2184 | */ |
2184 | mpt_add_sge(psge, flagsLength, (dma_addr_t) -1); | 2185 | ioc->add_sge(psge, flagsLength, (dma_addr_t) -1); |
2185 | } | 2186 | } |
2186 | 2187 | ||
2187 | ioc->ioctl->wait_done = 0; | 2188 | ioc->ioctl->wait_done = 0; |
@@ -2498,7 +2499,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) | |||
2498 | pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma); | 2499 | pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma); |
2499 | if (!pbuf) | 2500 | if (!pbuf) |
2500 | goto out; | 2501 | goto out; |
2501 | mpt_add_sge((char *)&IstwiRWRequest->SGL, | 2502 | ioc->add_sge((char *)&IstwiRWRequest->SGL, |
2502 | (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma); | 2503 | (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma); |
2503 | 2504 | ||
2504 | ioc->ioctl->wait_done = 0; | 2505 | ioc->ioctl->wait_done = 0; |