aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptsas.c
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2009-05-29 07:07:04 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-06-09 18:21:31 -0400
commit14d0f0b063f5363984dd305a792854f9c23e9e97 (patch)
tree6d3e62845bc5273244f3b9ec535159cf5a8bdbc6 /drivers/message/fusion/mptsas.c
parent238ddbb98c327a7392ced5ae65216c55969749ea (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/mptsas.c')
-rw-r--r--drivers/message/fusion/mptsas.c18
1 files changed, 8 insertions, 10 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index a9019f081b97..b162f7a1c563 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1319,15 +1319,15 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1319 /* request */ 1319 /* request */
1320 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT | 1320 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1321 MPI_SGE_FLAGS_END_OF_BUFFER | 1321 MPI_SGE_FLAGS_END_OF_BUFFER |
1322 MPI_SGE_FLAGS_DIRECTION | 1322 MPI_SGE_FLAGS_DIRECTION)
1323 mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT; 1323 << MPI_SGE_FLAGS_SHIFT;
1324 flagsLength |= (req->data_len - 4); 1324 flagsLength |= (req->data_len - 4);
1325 1325
1326 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio), 1326 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
1327 req->data_len, PCI_DMA_BIDIRECTIONAL); 1327 req->data_len, PCI_DMA_BIDIRECTIONAL);
1328 if (!dma_addr_out) 1328 if (!dma_addr_out)
1329 goto put_mf; 1329 goto put_mf;
1330 mpt_add_sge(psge, flagsLength, dma_addr_out); 1330 ioc->add_sge(psge, flagsLength, dma_addr_out);
1331 psge += (sizeof(u32) + sizeof(dma_addr_t)); 1331 psge += (sizeof(u32) + sizeof(dma_addr_t));
1332 1332
1333 /* response */ 1333 /* response */
@@ -1337,7 +1337,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1337 rsp->data_len, PCI_DMA_BIDIRECTIONAL); 1337 rsp->data_len, PCI_DMA_BIDIRECTIONAL);
1338 if (!dma_addr_in) 1338 if (!dma_addr_in)
1339 goto unmap; 1339 goto unmap;
1340 mpt_add_sge(psge, flagsLength, dma_addr_in); 1340 ioc->add_sge(psge, flagsLength, dma_addr_in);
1341 1341
1342 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf); 1342 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1343 1343
@@ -3211,17 +3211,15 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3211 * A slightly different algorithm is required for 3211 * A slightly different algorithm is required for
3212 * 64bit SGEs. 3212 * 64bit SGEs.
3213 */ 3213 */
3214 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); 3214 scale = ioc->req_sz/ioc->SGE_size;
3215 if (sizeof(dma_addr_t) == sizeof(u64)) { 3215 if (ioc->sg_addr_size == sizeof(u64)) {
3216 numSGE = (scale - 1) * 3216 numSGE = (scale - 1) *
3217 (ioc->facts.MaxChainDepth-1) + scale + 3217 (ioc->facts.MaxChainDepth-1) + scale +
3218 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + 3218 (ioc->req_sz - 60) / ioc->SGE_size;
3219 sizeof(u32));
3220 } else { 3219 } else {
3221 numSGE = 1 + (scale - 1) * 3220 numSGE = 1 + (scale - 1) *
3222 (ioc->facts.MaxChainDepth-1) + scale + 3221 (ioc->facts.MaxChainDepth-1) + scale +
3223 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + 3222 (ioc->req_sz - 64) / ioc->SGE_size;
3224 sizeof(u32));
3225 } 3223 }
3226 3224
3227 if (numSGE < sh->sg_tablesize) { 3225 if (numSGE < sh->sg_tablesize) {