aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptscsih.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/mptscsih.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/mptscsih.c')
-rw-r--r--drivers/message/fusion/mptscsih.c102
1 files changed, 19 insertions, 83 deletions
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index e62c6bc4ad3..8c08c73f194 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -113,69 +113,6 @@ int mptscsih_resume(struct pci_dev *pdev);
113 113
114#define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE 114#define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE
115 115
116/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
117/**
118 * mptscsih_add_sge - Place a simple SGE at address pAddr.
119 * @pAddr: virtual address for SGE
120 * @flagslength: SGE flags and data transfer length
121 * @dma_addr: Physical address
122 *
123 * This routine places a MPT request frame back on the MPT adapter's
124 * FreeQ.
125 */
126static inline void
127mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
128{
129 if (sizeof(dma_addr_t) == sizeof(u64)) {
130 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
131 u32 tmp = dma_addr & 0xFFFFFFFF;
132
133 pSge->FlagsLength = cpu_to_le32(flagslength);
134 pSge->Address.Low = cpu_to_le32(tmp);
135 tmp = (u32) ((u64)dma_addr >> 32);
136 pSge->Address.High = cpu_to_le32(tmp);
137
138 } else {
139 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
140 pSge->FlagsLength = cpu_to_le32(flagslength);
141 pSge->Address = cpu_to_le32(dma_addr);
142 }
143} /* mptscsih_add_sge() */
144
145/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
146/**
147 * mptscsih_add_chain - Place a chain SGE at address pAddr.
148 * @pAddr: virtual address for SGE
149 * @next: nextChainOffset value (u32's)
150 * @length: length of next SGL segment
151 * @dma_addr: Physical address
152 *
153 * This routine places a MPT request frame back on the MPT adapter's
154 * FreeQ.
155 */
156static inline void
157mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
158{
159 if (sizeof(dma_addr_t) == sizeof(u64)) {
160 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
161 u32 tmp = dma_addr & 0xFFFFFFFF;
162
163 pChain->Length = cpu_to_le16(length);
164 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
165
166 pChain->NextChainOffset = next;
167
168 pChain->Address.Low = cpu_to_le32(tmp);
169 tmp = (u32) ((u64)dma_addr >> 32);
170 pChain->Address.High = cpu_to_le32(tmp);
171 } else {
172 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
173 pChain->Length = cpu_to_le16(length);
174 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
175 pChain->NextChainOffset = next;
176 pChain->Address = cpu_to_le32(dma_addr);
177 }
178} /* mptscsih_add_chain() */
179 116
180/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 117/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
181/* 118/*
@@ -281,10 +218,10 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
281 */ 218 */
282 219
283nextSGEset: 220nextSGEset:
284 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) ); 221 numSgeSlots = ((frm_sz - sgeOffset) / ioc->SGE_size);
285 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots; 222 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
286 223
287 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir; 224 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | sgdir;
288 225
289 /* Get first (num - 1) SG elements 226 /* Get first (num - 1) SG elements
290 * Skip any SG entries with a length of 0 227 * Skip any SG entries with a length of 0
@@ -299,11 +236,11 @@ nextSGEset:
299 } 236 }
300 237
301 v2 = sg_dma_address(sg); 238 v2 = sg_dma_address(sg);
302 mptscsih_add_sge(psge, sgflags | thisxfer, v2); 239 ioc->add_sge(psge, sgflags | thisxfer, v2);
303 240
304 sg = sg_next(sg); /* Get next SG element from the OS */ 241 sg = sg_next(sg); /* Get next SG element from the OS */
305 psge += (sizeof(u32) + sizeof(dma_addr_t)); 242 psge += ioc->SGE_size;
306 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); 243 sgeOffset += ioc->SGE_size;
307 sg_done++; 244 sg_done++;
308 } 245 }
309 246
@@ -320,12 +257,8 @@ nextSGEset:
320 thisxfer = sg_dma_len(sg); 257 thisxfer = sg_dma_len(sg);
321 258
322 v2 = sg_dma_address(sg); 259 v2 = sg_dma_address(sg);
323 mptscsih_add_sge(psge, sgflags | thisxfer, v2); 260 ioc->add_sge(psge, sgflags | thisxfer, v2);
324 /* 261 sgeOffset += ioc->SGE_size;
325 sg = sg_next(sg);
326 psge += (sizeof(u32) + sizeof(dma_addr_t));
327 */
328 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
329 sg_done++; 262 sg_done++;
330 263
331 if (chainSge) { 264 if (chainSge) {
@@ -334,7 +267,8 @@ nextSGEset:
334 * Update the chain element 267 * Update the chain element
335 * Offset and Length fields. 268 * Offset and Length fields.
336 */ 269 */
337 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off); 270 ioc->add_chain((char *)chainSge, 0, sgeOffset,
271 ioc->ChainBufferDMA + chain_dma_off);
338 } else { 272 } else {
339 /* The current buffer is the original MF 273 /* The current buffer is the original MF
340 * and there is no Chain buffer. 274 * and there is no Chain buffer.
@@ -367,7 +301,7 @@ nextSGEset:
367 * set properly). 301 * set properly).
368 */ 302 */
369 if (sg_done) { 303 if (sg_done) {
370 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t))); 304 u32 *ptmp = (u32 *) (psge - ioc->SGE_size);
371 sgflags = le32_to_cpu(*ptmp); 305 sgflags = le32_to_cpu(*ptmp);
372 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT; 306 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
373 *ptmp = cpu_to_le32(sgflags); 307 *ptmp = cpu_to_le32(sgflags);
@@ -381,8 +315,9 @@ nextSGEset:
381 * Old chain element is now complete. 315 * Old chain element is now complete.
382 */ 316 */
383 u8 nextChain = (u8) (sgeOffset >> 2); 317 u8 nextChain = (u8) (sgeOffset >> 2);
384 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); 318 sgeOffset += ioc->SGE_size;
385 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off); 319 ioc->add_chain((char *)chainSge, nextChain, sgeOffset,
320 ioc->ChainBufferDMA + chain_dma_off);
386 } else { 321 } else {
387 /* The original MF buffer requires a chain buffer - 322 /* The original MF buffer requires a chain buffer -
388 * set the offset. 323 * set the offset.
@@ -1422,7 +1357,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1422 pScsiReq->CDBLength = SCpnt->cmd_len; 1357 pScsiReq->CDBLength = SCpnt->cmd_len;
1423 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; 1358 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1424 pScsiReq->Reserved = 0; 1359 pScsiReq->Reserved = 0;
1425 pScsiReq->MsgFlags = mpt_msg_flags(); 1360 pScsiReq->MsgFlags = mpt_msg_flags(ioc);
1426 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); 1361 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1427 pScsiReq->Control = cpu_to_le32(scsictl); 1362 pScsiReq->Control = cpu_to_le32(scsictl);
1428 1363
@@ -1448,7 +1383,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1448 */ 1383 */
1449 if (datalen == 0) { 1384 if (datalen == 0) {
1450 /* Add a NULL SGE */ 1385 /* Add a NULL SGE */
1451 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0, 1386 ioc->add_sge((char *)&pScsiReq->SGL,
1387 MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1452 (dma_addr_t) -1); 1388 (dma_addr_t) -1);
1453 } else { 1389 } else {
1454 /* Add a 32 or 64 bit SGE */ 1390 /* Add a 32 or 64 bit SGE */
@@ -3172,7 +3108,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3172 3108
3173 pScsiReq->Reserved = 0; 3109 pScsiReq->Reserved = 0;
3174 3110
3175 pScsiReq->MsgFlags = mpt_msg_flags(); 3111 pScsiReq->MsgFlags = mpt_msg_flags(ioc);
3176 /* MsgContext set in mpt_get_msg_fram call */ 3112 /* MsgContext set in mpt_get_msg_fram call */
3177 3113
3178 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); 3114 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 ioc->name, cmd, io->channel, io->id, io->lun)); 3135 ioc->name, cmd, io->channel, io->id, io->lun));
3200 3136
3201 if (dir == MPI_SCSIIO_CONTROL_READ) { 3137 if (dir == MPI_SCSIIO_CONTROL_READ) {
3202 mpt_add_sge((char *) &pScsiReq->SGL, 3138 ioc->add_sge((char *) &pScsiReq->SGL,
3203 MPT_SGE_FLAGS_SSIMPLE_READ | io->size, 3139 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3204 io->data_dma); 3140 io->data_dma);
3205 } else { 3141 } else {
3206 mpt_add_sge((char *) &pScsiReq->SGL, 3142 ioc->add_sge((char *) &pScsiReq->SGL,
3207 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, 3143 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3208 io->data_dma); 3144 io->data_dma);
3209 } 3145 }