Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
[deliverable/linux.git] / drivers / message / fusion / mptscsih.c
1 /*
2 * linux/drivers/message/fusion/mptscsih.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
6 * Copyright (c) 1999-2007 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsi.com)
8 *
9 */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11 /*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44 */
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47 #include "linux_compat.h" /* linux-2.6 tweaks */
48 #include <linux/module.h>
49 #include <linux/kernel.h>
50 #include <linux/init.h>
51 #include <linux/errno.h>
52 #include <linux/kdev_t.h>
53 #include <linux/blkdev.h>
54 #include <linux/delay.h> /* for mdelay */
55 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
56 #include <linux/reboot.h> /* notifier code */
57 #include <linux/workqueue.h>
58
59 #include <scsi/scsi.h>
60 #include <scsi/scsi_cmnd.h>
61 #include <scsi/scsi_device.h>
62 #include <scsi/scsi_host.h>
63 #include <scsi/scsi_tcq.h>
64 #include <scsi/scsi_dbg.h>
65
66 #include "mptbase.h"
67 #include "mptscsih.h"
68 #include "lsi/mpi_log_sas.h"
69
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME "Fusion MPT SCSI Host driver"
72 #define my_VERSION MPT_LINUX_VERSION_COMMON
73 #define MYNAM "mptscsih"
74
75 MODULE_AUTHOR(MODULEAUTHOR);
76 MODULE_DESCRIPTION(my_NAME);
77 MODULE_LICENSE("GPL");
78 MODULE_VERSION(my_VERSION);
79
80 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
81 /*
82 * Other private/forward protos...
83 */
84 int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
85 static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
86 int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
87
88 static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
89 SCSIIORequest_t *pReq, int req_idx);
90 static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
91 static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
92 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
93 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
94 static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
95
96 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
97
98 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
99 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
100
101 int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
102 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
103 static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
104
105 void mptscsih_remove(struct pci_dev *);
106 void mptscsih_shutdown(struct pci_dev *);
107 #ifdef CONFIG_PM
108 int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
109 int mptscsih_resume(struct pci_dev *pdev);
110 #endif
111
112 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
113
114 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
115 /**
116 * mptscsih_add_sge - Place a simple SGE at address pAddr.
117 * @pAddr: virtual address for SGE
118 * @flagslength: SGE flags and data transfer length
119 * @dma_addr: Physical address
120 *
121 * This routine places a MPT request frame back on the MPT adapter's
122 * FreeQ.
123 */
124 static inline void
125 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
126 {
127 if (sizeof(dma_addr_t) == sizeof(u64)) {
128 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
129 u32 tmp = dma_addr & 0xFFFFFFFF;
130
131 pSge->FlagsLength = cpu_to_le32(flagslength);
132 pSge->Address.Low = cpu_to_le32(tmp);
133 tmp = (u32) ((u64)dma_addr >> 32);
134 pSge->Address.High = cpu_to_le32(tmp);
135
136 } else {
137 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
138 pSge->FlagsLength = cpu_to_le32(flagslength);
139 pSge->Address = cpu_to_le32(dma_addr);
140 }
141 } /* mptscsih_add_sge() */
142
143 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
144 /**
145 * mptscsih_add_chain - Place a chain SGE at address pAddr.
146 * @pAddr: virtual address for SGE
147 * @next: nextChainOffset value (u32's)
148 * @length: length of next SGL segment
149 * @dma_addr: Physical address
150 *
151 * This routine places a MPT request frame back on the MPT adapter's
152 * FreeQ.
153 */
154 static inline void
155 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
156 {
157 if (sizeof(dma_addr_t) == sizeof(u64)) {
158 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
159 u32 tmp = dma_addr & 0xFFFFFFFF;
160
161 pChain->Length = cpu_to_le16(length);
162 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
163
164 pChain->NextChainOffset = next;
165
166 pChain->Address.Low = cpu_to_le32(tmp);
167 tmp = (u32) ((u64)dma_addr >> 32);
168 pChain->Address.High = cpu_to_le32(tmp);
169 } else {
170 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
171 pChain->Length = cpu_to_le16(length);
172 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
173 pChain->NextChainOffset = next;
174 pChain->Address = cpu_to_le32(dma_addr);
175 }
176 } /* mptscsih_add_chain() */
177
178 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
179 /*
180 * mptscsih_getFreeChainBuffer - Function to get a free chain
181 * from the MPT_SCSI_HOST FreeChainQ.
182 * @ioc: Pointer to MPT_ADAPTER structure
183 * @req_idx: Index of the SCSI IO request frame. (output)
184 *
185 * return SUCCESS or FAILED
186 */
187 static inline int
188 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
189 {
190 MPT_FRAME_HDR *chainBuf;
191 unsigned long flags;
192 int rc;
193 int chain_idx;
194
195 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
196 ioc->name));
197 spin_lock_irqsave(&ioc->FreeQlock, flags);
198 if (!list_empty(&ioc->FreeChainQ)) {
199 int offset;
200
201 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
202 u.frame.linkage.list);
203 list_del(&chainBuf->u.frame.linkage.list);
204 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
205 chain_idx = offset / ioc->req_sz;
206 rc = SUCCESS;
207 dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
208 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
209 } else {
210 rc = FAILED;
211 chain_idx = MPT_HOST_NO_CHAIN;
212 dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
213 ioc->name));
214 }
215 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
216
217 *retIndex = chain_idx;
218 return rc;
219 } /* mptscsih_getFreeChainBuffer() */
220
221 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
222 /*
223 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
224 * SCSIIORequest_t Message Frame.
225 * @ioc: Pointer to MPT_ADAPTER structure
226 * @SCpnt: Pointer to scsi_cmnd structure
227 * @pReq: Pointer to SCSIIORequest_t structure
228 *
229 * Returns ...
230 */
231 static int
232 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
233 SCSIIORequest_t *pReq, int req_idx)
234 {
235 char *psge;
236 char *chainSge;
237 struct scatterlist *sg;
238 int frm_sz;
239 int sges_left, sg_done;
240 int chain_idx = MPT_HOST_NO_CHAIN;
241 int sgeOffset;
242 int numSgeSlots, numSgeThisFrame;
243 u32 sgflags, sgdir, thisxfer = 0;
244 int chain_dma_off = 0;
245 int newIndex;
246 int ii;
247 dma_addr_t v2;
248 u32 RequestNB;
249
250 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
251 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
252 sgdir = MPT_TRANSFER_HOST_TO_IOC;
253 } else {
254 sgdir = MPT_TRANSFER_IOC_TO_HOST;
255 }
256
257 psge = (char *) &pReq->SGL;
258 frm_sz = ioc->req_sz;
259
260 /* Map the data portion, if any.
261 * sges_left = 0 if no data transfer.
262 */
263 if ( (sges_left = SCpnt->use_sg) ) {
264 sges_left = pci_map_sg(ioc->pcidev,
265 (struct scatterlist *) SCpnt->request_buffer,
266 SCpnt->use_sg,
267 SCpnt->sc_data_direction);
268 if (sges_left == 0)
269 return FAILED;
270 } else if (SCpnt->request_bufflen) {
271 SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
272 SCpnt->request_buffer,
273 SCpnt->request_bufflen,
274 SCpnt->sc_data_direction);
275 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
276 ioc->name, SCpnt, SCpnt->request_bufflen));
277 mptscsih_add_sge((char *) &pReq->SGL,
278 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
279 SCpnt->SCp.dma_handle);
280
281 return SUCCESS;
282 }
283
284 /* Handle the SG case.
285 */
286 sg = (struct scatterlist *) SCpnt->request_buffer;
287 sg_done = 0;
288 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
289 chainSge = NULL;
290
291 /* Prior to entering this loop - the following must be set
292 * current MF: sgeOffset (bytes)
293 * chainSge (Null if original MF is not a chain buffer)
294 * sg_done (num SGE done for this MF)
295 */
296
297 nextSGEset:
298 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
299 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
300
301 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
302
303 /* Get first (num - 1) SG elements
304 * Skip any SG entries with a length of 0
305 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
306 */
307 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
308 thisxfer = sg_dma_len(sg);
309 if (thisxfer == 0) {
310 sg ++; /* Get next SG element from the OS */
311 sg_done++;
312 continue;
313 }
314
315 v2 = sg_dma_address(sg);
316 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
317
318 sg++; /* Get next SG element from the OS */
319 psge += (sizeof(u32) + sizeof(dma_addr_t));
320 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
321 sg_done++;
322 }
323
324 if (numSgeThisFrame == sges_left) {
325 /* Add last element, end of buffer and end of list flags.
326 */
327 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
328 MPT_SGE_FLAGS_END_OF_BUFFER |
329 MPT_SGE_FLAGS_END_OF_LIST;
330
331 /* Add last SGE and set termination flags.
332 * Note: Last SGE may have a length of 0 - which should be ok.
333 */
334 thisxfer = sg_dma_len(sg);
335
336 v2 = sg_dma_address(sg);
337 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
338 /*
339 sg++;
340 psge += (sizeof(u32) + sizeof(dma_addr_t));
341 */
342 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
343 sg_done++;
344
345 if (chainSge) {
346 /* The current buffer is a chain buffer,
347 * but there is not another one.
348 * Update the chain element
349 * Offset and Length fields.
350 */
351 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
352 } else {
353 /* The current buffer is the original MF
354 * and there is no Chain buffer.
355 */
356 pReq->ChainOffset = 0;
357 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
358 dsgprintk((MYIOC_s_INFO_FMT
359 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
360 ioc->RequestNB[req_idx] = RequestNB;
361 }
362 } else {
363 /* At least one chain buffer is needed.
364 * Complete the first MF
365 * - last SGE element, set the LastElement bit
366 * - set ChainOffset (words) for orig MF
367 * (OR finish previous MF chain buffer)
368 * - update MFStructPtr ChainIndex
369 * - Populate chain element
370 * Also
371 * Loop until done.
372 */
373
374 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
375 ioc->name, sg_done));
376
377 /* Set LAST_ELEMENT flag for last non-chain element
378 * in the buffer. Since psge points at the NEXT
379 * SGE element, go back one SGE element, update the flags
380 * and reset the pointer. (Note: sgflags & thisxfer are already
381 * set properly).
382 */
383 if (sg_done) {
384 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
385 sgflags = le32_to_cpu(*ptmp);
386 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
387 *ptmp = cpu_to_le32(sgflags);
388 }
389
390 if (chainSge) {
391 /* The current buffer is a chain buffer.
392 * chainSge points to the previous Chain Element.
393 * Update its chain element Offset and Length (must
394 * include chain element size) fields.
395 * Old chain element is now complete.
396 */
397 u8 nextChain = (u8) (sgeOffset >> 2);
398 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
399 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
400 } else {
401 /* The original MF buffer requires a chain buffer -
402 * set the offset.
403 * Last element in this MF is a chain element.
404 */
405 pReq->ChainOffset = (u8) (sgeOffset >> 2);
406 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
407 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
408 ioc->RequestNB[req_idx] = RequestNB;
409 }
410
411 sges_left -= sg_done;
412
413
414 /* NOTE: psge points to the beginning of the chain element
415 * in current buffer. Get a chain buffer.
416 */
417 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
418 dfailprintk((MYIOC_s_INFO_FMT
419 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
420 ioc->name, pReq->CDB[0], SCpnt));
421 return FAILED;
422 }
423
424 /* Update the tracking arrays.
425 * If chainSge == NULL, update ReqToChain, else ChainToChain
426 */
427 if (chainSge) {
428 ioc->ChainToChain[chain_idx] = newIndex;
429 } else {
430 ioc->ReqToChain[req_idx] = newIndex;
431 }
432 chain_idx = newIndex;
433 chain_dma_off = ioc->req_sz * chain_idx;
434
435 /* Populate the chainSGE for the current buffer.
436 * - Set chain buffer pointer to psge and fill
437 * out the Address and Flags fields.
438 */
439 chainSge = (char *) psge;
440 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
441 psge, req_idx));
442
443 /* Start the SGE for the next buffer
444 */
445 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
446 sgeOffset = 0;
447 sg_done = 0;
448
449 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
450 psge, chain_idx));
451
452 /* Start the SGE for the next buffer
453 */
454
455 goto nextSGEset;
456 }
457
458 return SUCCESS;
459 } /* mptscsih_AddSGE() */
460
461 static void
462 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
463 U32 SlotStatus)
464 {
465 MPT_FRAME_HDR *mf;
466 SEPRequest_t *SEPMsg;
467
468 if (ioc->bus_type == FC)
469 return;
470
471 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
472 dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
473 ioc->name,__FUNCTION__));
474 return;
475 }
476
477 SEPMsg = (SEPRequest_t *)mf;
478 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
479 SEPMsg->Bus = vtarget->channel;
480 SEPMsg->TargetID = vtarget->id;
481 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
482 SEPMsg->SlotStatus = SlotStatus;
483 devtverboseprintk((MYIOC_s_WARN_FMT
484 "Sending SEP cmd=%x channel=%d id=%d\n",
485 ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
486 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
487 }
488
489 #ifdef MPT_DEBUG_REPLY
490 /**
491 * mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO
492 * @ioc: Pointer to MPT_ADAPTER structure
493 * @ioc_status: U32 IOCStatus word from IOC
494 * @scsi_status: U8 sam status from target
495 * @scsi_state: U8 scsi state
496 * @sc: original scsi cmnd pointer
497 * @mf: Pointer to MPT request frame
498 *
499 * Refer to lsi/mpi.h.
500 **/
501 static void
502 mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status,
503 u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc)
504 {
505 char extend_desc[EVENT_DESCR_STR_SZ];
506 char *desc = NULL;
507
508 switch (ioc_status) {
509
510 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
511 desc = "SCSI Invalid Bus";
512 break;
513
514 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
515 desc = "SCSI Invalid TargetID";
516 break;
517
518 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
519 /*
520 * Inquiry is issued for device scanning
521 */
522 if (sc->cmnd[0] != 0x12)
523 desc = "SCSI Device Not There";
524 break;
525
526 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
527 desc = "SCSI Data Overrun";
528 break;
529
530 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
531 desc = "SCSI I/O Data Error";
532 break;
533
534 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
535 desc = "SCSI Protocol Error";
536 break;
537
538 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
539 desc = "SCSI Task Terminated";
540 break;
541
542 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
543 desc = "SCSI Residual Mismatch";
544 break;
545
546 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
547 desc = "SCSI Task Management Failed";
548 break;
549
550 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
551 desc = "SCSI IOC Terminated";
552 break;
553
554 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
555 desc = "SCSI Ext Terminated";
556 break;
557 }
558
559 if (!desc)
560 return;
561
562 snprintf(extend_desc, EVENT_DESCR_STR_SZ,
563 "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh",
564 sc->device->host->host_no,
565 sc->device->channel, sc->device->id, sc->device->lun,
566 sc->cmnd[0], scsi_status, scsi_state);
567
568 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
569 ioc->name, ioc_status, desc, extend_desc);
570 }
571 #endif
572
573 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
574 /*
575 * mptscsih_io_done - Main SCSI IO callback routine registered to
576 * Fusion MPT (base) driver
577 * @ioc: Pointer to MPT_ADAPTER structure
578 * @mf: Pointer to original MPT request frame
579 * @r: Pointer to MPT reply frame (NULL if TurboReply)
580 *
581 * This routine is called from mpt.c::mpt_interrupt() at the completion
582 * of any SCSI IO request.
583 * This routine is registered with the Fusion MPT (base) driver at driver
584 * load/init time via the mpt_register() API call.
585 *
586 * Returns 1 indicating alloc'd request frame ptr should be freed.
587 */
588 int
589 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
590 {
591 struct scsi_cmnd *sc;
592 MPT_SCSI_HOST *hd;
593 SCSIIORequest_t *pScsiReq;
594 SCSIIOReply_t *pScsiReply;
595 u16 req_idx, req_idx_MR;
596 VirtDevice *vdev;
597 VirtTarget *vtarget;
598
599 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
600
601 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
602 req_idx_MR = (mr != NULL) ?
603 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
604 if ((req_idx != req_idx_MR) ||
605 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
606 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
607 ioc->name);
608 printk (MYIOC_s_ERR_FMT
609 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
610 ioc->name, req_idx, req_idx_MR, mf, mr,
611 hd->ScsiLookup[req_idx_MR]);
612 return 0;
613 }
614
615 sc = hd->ScsiLookup[req_idx];
616 hd->ScsiLookup[req_idx] = NULL;
617 if (sc == NULL) {
618 MPIHeader_t *hdr = (MPIHeader_t *)mf;
619
620 /* Remark: writeSDP1 will use the ScsiDoneCtx
621 * If a SCSI I/O cmd, device disabled by OS and
622 * completion done. Cannot touch sc struct. Just free mem.
623 */
624 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
625 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
626 ioc->name);
627
628 mptscsih_freeChainBuffers(ioc, req_idx);
629 return 1;
630 }
631
632 if ((unsigned char *)mf != sc->host_scribble) {
633 mptscsih_freeChainBuffers(ioc, req_idx);
634 return 1;
635 }
636
637 sc->host_scribble = NULL;
638 sc->result = DID_OK << 16; /* Set default reply as OK */
639 pScsiReq = (SCSIIORequest_t *) mf;
640 pScsiReply = (SCSIIOReply_t *) mr;
641
642 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
643 dmfprintk((MYIOC_s_INFO_FMT
644 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
645 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
646 }else{
647 dmfprintk((MYIOC_s_INFO_FMT
648 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
649 ioc->name, mf, mr, sc, req_idx));
650 }
651
652 if (pScsiReply == NULL) {
653 /* special context reply handling */
654 ;
655 } else {
656 u32 xfer_cnt;
657 u16 status;
658 u8 scsi_state, scsi_status;
659 u32 log_info;
660
661 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
662 scsi_state = pScsiReply->SCSIState;
663 scsi_status = pScsiReply->SCSIStatus;
664 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
665 sc->resid = sc->request_bufflen - xfer_cnt;
666 log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
667
668 /*
669 * if we get a data underrun indication, yet no data was
670 * transferred and the SCSI status indicates that the
671 * command was never started, change the data underrun
672 * to success
673 */
674 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
675 (scsi_status == MPI_SCSI_STATUS_BUSY ||
676 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
677 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
678 status = MPI_IOCSTATUS_SUCCESS;
679 }
680
681 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
682 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
683
684 /*
685 * Look for + dump FCP ResponseInfo[]!
686 */
687 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
688 pScsiReply->ResponseInfo) {
689 printk(KERN_NOTICE "[%d:%d:%d:%d] "
690 "FCP_ResponseInfo=%08xh\n",
691 sc->device->host->host_no, sc->device->channel,
692 sc->device->id, sc->device->lun,
693 le32_to_cpu(pScsiReply->ResponseInfo));
694 }
695
696 switch(status) {
697 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
698 /* CHECKME!
699 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
700 * But not: DID_BUS_BUSY lest one risk
701 * killing interrupt handler:-(
702 */
703 sc->result = SAM_STAT_BUSY;
704 break;
705
706 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
707 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
708 sc->result = DID_BAD_TARGET << 16;
709 break;
710
711 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
712 /* Spoof to SCSI Selection Timeout! */
713 if (ioc->bus_type != FC)
714 sc->result = DID_NO_CONNECT << 16;
715 /* else fibre, just stall until rescan event */
716 else
717 sc->result = DID_REQUEUE << 16;
718
719 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
720 hd->sel_timeout[pScsiReq->TargetID]++;
721
722 vdev = sc->device->hostdata;
723 if (!vdev)
724 break;
725 vtarget = vdev->vtarget;
726 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
727 mptscsih_issue_sep_command(ioc, vtarget,
728 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
729 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
730 }
731 break;
732
733 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
734 if ( ioc->bus_type == SAS ) {
735 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
736 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
737 if ((log_info & SAS_LOGINFO_MASK)
738 == SAS_LOGINFO_NEXUS_LOSS) {
739 sc->result = (DID_BUS_BUSY << 16);
740 break;
741 }
742 }
743 } else if (ioc->bus_type == FC) {
744 /*
745 * The FC IOC may kill a request for variety of
746 * reasons, some of which may be recovered by a
747 * retry, some which are unlikely to be
748 * recovered. Return DID_ERROR instead of
749 * DID_RESET to permit retry of the command,
750 * just not an infinite number of them
751 */
752 sc->result = DID_ERROR << 16;
753 break;
754 }
755
756 /*
757 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
758 */
759
760 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
761 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
762 /* Linux handles an unsolicited DID_RESET better
763 * than an unsolicited DID_ABORT.
764 */
765 sc->result = DID_RESET << 16;
766
767 break;
768
769 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
770 sc->resid = sc->request_bufflen - xfer_cnt;
771 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
772 sc->result=DID_SOFT_ERROR << 16;
773 else /* Sufficient data transfer occurred */
774 sc->result = (DID_OK << 16) | scsi_status;
775 dreplyprintk((KERN_NOTICE
776 "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
777 sc->result, sc->device->channel, sc->device->id));
778 break;
779
780 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
781 /*
782 * Do upfront check for valid SenseData and give it
783 * precedence!
784 */
785 sc->result = (DID_OK << 16) | scsi_status;
786 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
787 /* Have already saved the status and sense data
788 */
789 ;
790 } else {
791 if (xfer_cnt < sc->underflow) {
792 if (scsi_status == SAM_STAT_BUSY)
793 sc->result = SAM_STAT_BUSY;
794 else
795 sc->result = DID_SOFT_ERROR << 16;
796 }
797 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
798 /* What to do?
799 */
800 sc->result = DID_SOFT_ERROR << 16;
801 }
802 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
803 /* Not real sure here either... */
804 sc->result = DID_RESET << 16;
805 }
806 }
807
808 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
809 sc->underflow));
810 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
811 /* Report Queue Full
812 */
813 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
814 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
815
816 break;
817
818 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
819 sc->resid=0;
820 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
821 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
822 sc->result = (DID_OK << 16) | scsi_status;
823 if (scsi_state == 0) {
824 ;
825 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
826 /*
827 * If running against circa 200003dd 909 MPT f/w,
828 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
829 * (QUEUE_FULL) returned from device! --> get 0x0000?128
830 * and with SenseBytes set to 0.
831 */
832 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
833 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
834
835 }
836 else if (scsi_state &
837 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
838 ) {
839 /*
840 * What to do?
841 */
842 sc->result = DID_SOFT_ERROR << 16;
843 }
844 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
845 /* Not real sure here either... */
846 sc->result = DID_RESET << 16;
847 }
848 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
849 /* Device Inq. data indicates that it supports
850 * QTags, but rejects QTag messages.
851 * This command completed OK.
852 *
853 * Not real sure here either so do nothing... */
854 }
855
856 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
857 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
858
859 /* Add handling of:
860 * Reservation Conflict, Busy,
861 * Command Terminated, CHECK
862 */
863 break;
864
865 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
866 sc->result = DID_SOFT_ERROR << 16;
867 break;
868
869 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
870 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
871 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
872 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
873 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
874 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
875 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
876 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
877 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
878 default:
879 /*
880 * What to do?
881 */
882 sc->result = DID_SOFT_ERROR << 16;
883 break;
884
885 } /* switch(status) */
886
887 #ifdef MPT_DEBUG_REPLY
888 if (sc->result) {
889
890 mptscsih_iocstatus_info_scsiio(ioc, status,
891 scsi_status, scsi_state, sc);
892
893 dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x "
894 "result=0x%08x\n\tiocstatus=0x%04X "
895 "scsi_state=0x%02X scsi_status=0x%02X "
896 "loginfo=0x%08X\n", __FUNCTION__,
897 sc->device->host->host_no, sc->device->channel, sc->device->id,
898 sc->device->lun, sc->cmnd[0], sc->result, status,
899 scsi_state, scsi_status, log_info));
900
901 dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
902 "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
903 sc->device->host->host_no, sc->device->channel, sc->device->id,
904 sc->device->lun, sc->resid, sc->request_bufflen,
905 xfer_cnt));
906 }
907 #endif
908
909 } /* end of address reply case */
910
911 /* Unmap the DMA buffers, if any. */
912 if (sc->use_sg) {
913 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
914 sc->use_sg, sc->sc_data_direction);
915 } else if (sc->request_bufflen) {
916 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
917 sc->request_bufflen, sc->sc_data_direction);
918 }
919
920 sc->scsi_done(sc); /* Issue the command callback */
921
922 /* Free Chain buffers */
923 mptscsih_freeChainBuffers(ioc, req_idx);
924 return 1;
925 }
926
927 /*
928 * mptscsih_flush_running_cmds - For each command found, search
929 * Scsi_Host instance taskQ and reply to OS.
930 * Called only if recovering from a FW reload.
931 * @hd: Pointer to a SCSI HOST structure
932 *
933 * Returns: None.
934 *
935 * Must be called while new I/Os are being queued.
936 */
937 static void
938 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
939 {
940 MPT_ADAPTER *ioc = hd->ioc;
941 struct scsi_cmnd *SCpnt;
942 MPT_FRAME_HDR *mf;
943 int ii;
944 int max = ioc->req_depth;
945
946 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
947 for (ii= 0; ii < max; ii++) {
948 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
949
950 /* Command found.
951 */
952
953 /* Null ScsiLookup index
954 */
955 hd->ScsiLookup[ii] = NULL;
956
957 mf = MPT_INDEX_2_MFPTR(ioc, ii);
958 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
959 mf, SCpnt));
960
961 /* Free Chain buffers */
962 mptscsih_freeChainBuffers(ioc, ii);
963
964 /* Free Message frames */
965 mpt_free_msg_frame(ioc, mf);
966
967 if ((unsigned char *)mf != SCpnt->host_scribble)
968 continue;
969
970 /* Set status, free OS resources (SG DMA buffers)
971 * Do OS callback
972 */
973 if (SCpnt->use_sg) {
974 pci_unmap_sg(ioc->pcidev,
975 (struct scatterlist *) SCpnt->request_buffer,
976 SCpnt->use_sg,
977 SCpnt->sc_data_direction);
978 } else if (SCpnt->request_bufflen) {
979 pci_unmap_single(ioc->pcidev,
980 SCpnt->SCp.dma_handle,
981 SCpnt->request_bufflen,
982 SCpnt->sc_data_direction);
983 }
984 SCpnt->result = DID_RESET << 16;
985 SCpnt->host_scribble = NULL;
986
987 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
988 }
989 }
990
991 return;
992 }
993
994 /*
995 * mptscsih_search_running_cmds - Delete any commands associated
996 * with the specified target and lun. Function called only
997 * when a lun is disable by mid-layer.
998 * Do NOT access the referenced scsi_cmnd structure or
999 * members. Will cause either a paging or NULL ptr error.
1000 * (BUT, BUT, BUT, the code does reference it! - mdr)
1001 * @hd: Pointer to a SCSI HOST structure
1002 * @vdevice: per device private data
1003 *
1004 * Returns: None.
1005 *
1006 * Called from slave_destroy.
1007 */
1008 static void
1009 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1010 {
1011 SCSIIORequest_t *mf = NULL;
1012 int ii;
1013 int max = hd->ioc->req_depth;
1014 struct scsi_cmnd *sc;
1015 struct scsi_lun lun;
1016
1017 dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n",
1018 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
1019
1020 for (ii=0; ii < max; ii++) {
1021 if ((sc = hd->ScsiLookup[ii]) != NULL) {
1022
1023 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
1024 if (mf == NULL)
1025 continue;
1026 int_to_scsilun(vdevice->lun, &lun);
1027 if ((mf->Bus != vdevice->vtarget->channel) ||
1028 (mf->TargetID != vdevice->vtarget->id) ||
1029 memcmp(lun.scsi_lun, mf->LUN, 8))
1030 continue;
1031 dsprintk(( "search_running: found (sc=%p, mf = %p) "
1032 "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
1033 mf, mf->Bus, mf->TargetID, vdevice->lun));
1034
1035 /* Cleanup
1036 */
1037 hd->ScsiLookup[ii] = NULL;
1038 mptscsih_freeChainBuffers(hd->ioc, ii);
1039 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
1040 if ((unsigned char *)mf != sc->host_scribble)
1041 continue;
1042 if (sc->use_sg) {
1043 pci_unmap_sg(hd->ioc->pcidev,
1044 (struct scatterlist *) sc->request_buffer,
1045 sc->use_sg,
1046 sc->sc_data_direction);
1047 } else if (sc->request_bufflen) {
1048 pci_unmap_single(hd->ioc->pcidev,
1049 sc->SCp.dma_handle,
1050 sc->request_bufflen,
1051 sc->sc_data_direction);
1052 }
1053 sc->host_scribble = NULL;
1054 sc->result = DID_NO_CONNECT << 16;
1055 sc->scsi_done(sc);
1056 }
1057 }
1058 return;
1059 }
1060
1061 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1062
1063 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1064 /*
1065 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1066 * from a SCSI target device.
1067 * @sc: Pointer to scsi_cmnd structure
1068 * @pScsiReply: Pointer to SCSIIOReply_t
1069 * @pScsiReq: Pointer to original SCSI request
1070 *
1071 * This routine periodically reports QUEUE_FULL status returned from a
1072 * SCSI target device. It reports this to the console via kernel
1073 * printk() API call, not more than once every 10 seconds.
1074 */
1075 static void
1076 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1077 {
1078 long time = jiffies;
1079 MPT_SCSI_HOST *hd;
1080
1081 if (sc->device == NULL)
1082 return;
1083 if (sc->device->host == NULL)
1084 return;
1085 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
1086 return;
1087
1088 if (time - hd->last_queue_full > 10 * HZ) {
1089 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1090 hd->ioc->name, 0, sc->device->id, sc->device->lun));
1091 hd->last_queue_full = time;
1092 }
1093 }
1094
1095 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1096 /*
1097 * mptscsih_remove - Removed scsi devices
1098 * @pdev: Pointer to pci_dev structure
1099 *
1100 *
1101 */
1102 void
1103 mptscsih_remove(struct pci_dev *pdev)
1104 {
1105 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1106 struct Scsi_Host *host = ioc->sh;
1107 MPT_SCSI_HOST *hd;
1108 int sz1;
1109
1110 if(!host) {
1111 mpt_detach(pdev);
1112 return;
1113 }
1114
1115 scsi_remove_host(host);
1116
1117 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1118 return;
1119
1120 mptscsih_shutdown(pdev);
1121
1122 sz1=0;
1123
1124 if (hd->ScsiLookup != NULL) {
1125 sz1 = hd->ioc->req_depth * sizeof(void *);
1126 kfree(hd->ScsiLookup);
1127 hd->ScsiLookup = NULL;
1128 }
1129
1130 dprintk((MYIOC_s_INFO_FMT
1131 "Free'd ScsiLookup (%d) memory\n",
1132 hd->ioc->name, sz1));
1133
1134 kfree(hd->info_kbuf);
1135
1136 /* NULL the Scsi_Host pointer
1137 */
1138 hd->ioc->sh = NULL;
1139
1140 scsi_host_put(host);
1141
1142 mpt_detach(pdev);
1143
1144 }
1145
1146 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1147 /*
1148 * mptscsih_shutdown - reboot notifier
1149 *
1150 */
1151 void
1152 mptscsih_shutdown(struct pci_dev *pdev)
1153 {
1154 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1155 struct Scsi_Host *host = ioc->sh;
1156 MPT_SCSI_HOST *hd;
1157
1158 if(!host)
1159 return;
1160
1161 hd = (MPT_SCSI_HOST *)host->hostdata;
1162
1163 }
1164
1165 #ifdef CONFIG_PM
1166 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1167 /*
1168 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1169 *
1170 *
1171 */
1172 int
1173 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1174 {
1175 mptscsih_shutdown(pdev);
1176 return mpt_suspend(pdev,state);
1177 }
1178
1179 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1180 /*
1181 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1182 *
1183 *
1184 */
1185 int
1186 mptscsih_resume(struct pci_dev *pdev)
1187 {
1188 return mpt_resume(pdev);
1189 }
1190
1191 #endif
1192
1193 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1194 /**
1195 * mptscsih_info - Return information about MPT adapter
1196 * @SChost: Pointer to Scsi_Host structure
1197 *
1198 * (linux scsi_host_template.info routine)
1199 *
1200 * Returns pointer to buffer where information was written.
1201 */
1202 const char *
1203 mptscsih_info(struct Scsi_Host *SChost)
1204 {
1205 MPT_SCSI_HOST *h;
1206 int size = 0;
1207
1208 h = (MPT_SCSI_HOST *)SChost->hostdata;
1209
1210 if (h) {
1211 if (h->info_kbuf == NULL)
1212 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1213 return h->info_kbuf;
1214 h->info_kbuf[0] = '\0';
1215
1216 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1217 h->info_kbuf[size-1] = '\0';
1218 }
1219
1220 return h->info_kbuf;
1221 }
1222
1223 struct info_str {
1224 char *buffer;
1225 int length;
1226 int offset;
1227 int pos;
1228 };
1229
1230 static void
1231 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1232 {
1233 if (info->pos + len > info->length)
1234 len = info->length - info->pos;
1235
1236 if (info->pos + len < info->offset) {
1237 info->pos += len;
1238 return;
1239 }
1240
1241 if (info->pos < info->offset) {
1242 data += (info->offset - info->pos);
1243 len -= (info->offset - info->pos);
1244 }
1245
1246 if (len > 0) {
1247 memcpy(info->buffer + info->pos, data, len);
1248 info->pos += len;
1249 }
1250 }
1251
1252 static int
1253 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1254 {
1255 va_list args;
1256 char buf[81];
1257 int len;
1258
1259 va_start(args, fmt);
1260 len = vsprintf(buf, fmt, args);
1261 va_end(args);
1262
1263 mptscsih_copy_mem_info(info, buf, len);
1264 return len;
1265 }
1266
1267 static int
1268 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1269 {
1270 struct info_str info;
1271
1272 info.buffer = pbuf;
1273 info.length = len;
1274 info.offset = offset;
1275 info.pos = 0;
1276
1277 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1278 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1279 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1280 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1281
1282 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1283 }
1284
1285 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1286 /**
1287 * mptscsih_proc_info - Return information about MPT adapter
1288 * @host: scsi host struct
1289 * @buffer: if write, user data; if read, buffer for user
1290 * @start: returns the buffer address
1291 * @offset: if write, 0; if read, the current offset into the buffer from
1292 * the previous read.
1293 * @length: if write, return length;
1294 * @func: write = 1; read = 0
1295 *
1296 * (linux scsi_host_template.info routine)
1297 */
1298 int
1299 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1300 int length, int func)
1301 {
1302 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1303 MPT_ADAPTER *ioc = hd->ioc;
1304 int size = 0;
1305
1306 if (func) {
1307 /*
1308 * write is not supported
1309 */
1310 } else {
1311 if (start)
1312 *start = buffer;
1313
1314 size = mptscsih_host_info(ioc, buffer, offset, length);
1315 }
1316
1317 return size;
1318 }
1319
1320 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1321 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1322
1323 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1324 /**
1325 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1326 * @SCpnt: Pointer to scsi_cmnd structure
1327 * @done: Pointer SCSI mid-layer IO completion function
1328 *
1329 * (linux scsi_host_template.queuecommand routine)
1330 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1331 * from a linux scsi_cmnd request and send it to the IOC.
1332 *
1333 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1334 */
1335 int
1336 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1337 {
1338 MPT_SCSI_HOST *hd;
1339 MPT_FRAME_HDR *mf;
1340 SCSIIORequest_t *pScsiReq;
1341 VirtDevice *vdev = SCpnt->device->hostdata;
1342 int lun;
1343 u32 datalen;
1344 u32 scsictl;
1345 u32 scsidir;
1346 u32 cmd_len;
1347 int my_idx;
1348 int ii;
1349
1350 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1351 lun = SCpnt->device->lun;
1352 SCpnt->scsi_done = done;
1353
1354 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1355 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1356
1357 if (hd->resetPending) {
1358 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1359 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1360 return SCSI_MLQUEUE_HOST_BUSY;
1361 }
1362
1363 /*
1364 * Put together a MPT SCSI request...
1365 */
1366 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1367 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1368 hd->ioc->name));
1369 return SCSI_MLQUEUE_HOST_BUSY;
1370 }
1371
1372 pScsiReq = (SCSIIORequest_t *) mf;
1373
1374 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1375
1376 ADD_INDEX_LOG(my_idx);
1377
1378 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1379 * Seems we may receive a buffer (datalen>0) even when there
1380 * will be no data transfer! GRRRRR...
1381 */
1382 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1383 datalen = SCpnt->request_bufflen;
1384 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1385 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1386 datalen = SCpnt->request_bufflen;
1387 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1388 } else {
1389 datalen = 0;
1390 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1391 }
1392
1393 /* Default to untagged. Once a target structure has been allocated,
1394 * use the Inquiry data to determine if device supports tagged.
1395 */
1396 if (vdev
1397 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1398 && (SCpnt->device->tagged_supported)) {
1399 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1400 } else {
1401 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1402 }
1403
1404 /* Use the above information to set up the message frame
1405 */
1406 pScsiReq->TargetID = (u8) vdev->vtarget->id;
1407 pScsiReq->Bus = vdev->vtarget->channel;
1408 pScsiReq->ChainOffset = 0;
1409 if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
1410 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1411 else
1412 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1413 pScsiReq->CDBLength = SCpnt->cmd_len;
1414 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1415 pScsiReq->Reserved = 0;
1416 pScsiReq->MsgFlags = mpt_msg_flags();
1417 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1418 pScsiReq->Control = cpu_to_le32(scsictl);
1419
1420 /*
1421 * Write SCSI CDB into the message
1422 */
1423 cmd_len = SCpnt->cmd_len;
1424 for (ii=0; ii < cmd_len; ii++)
1425 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1426
1427 for (ii=cmd_len; ii < 16; ii++)
1428 pScsiReq->CDB[ii] = 0;
1429
1430 /* DataLength */
1431 pScsiReq->DataLength = cpu_to_le32(datalen);
1432
1433 /* SenseBuffer low address */
1434 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1435 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1436
1437 /* Now add the SG list
1438 * Always have a SGE even if null length.
1439 */
1440 if (datalen == 0) {
1441 /* Add a NULL SGE */
1442 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1443 (dma_addr_t) -1);
1444 } else {
1445 /* Add a 32 or 64 bit SGE */
1446 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1447 goto fail;
1448 }
1449
1450 SCpnt->host_scribble = (unsigned char *)mf;
1451 hd->ScsiLookup[my_idx] = SCpnt;
1452
1453 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1454 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1455 hd->ioc->name, SCpnt, mf, my_idx));
1456 DBG_DUMP_REQUEST_FRAME(mf)
1457 return 0;
1458
1459 fail:
1460 hd->ScsiLookup[my_idx] = NULL;
1461 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1462 mpt_free_msg_frame(hd->ioc, mf);
1463 return SCSI_MLQUEUE_HOST_BUSY;
1464 }
1465
1466 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1467 /*
1468 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1469 * with a SCSI IO request
1470 * @hd: Pointer to the MPT_SCSI_HOST instance
1471 * @req_idx: Index of the SCSI IO request frame.
1472 *
1473 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1474 * No return.
1475 */
1476 static void
1477 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1478 {
1479 MPT_FRAME_HDR *chain;
1480 unsigned long flags;
1481 int chain_idx;
1482 int next;
1483
1484 /* Get the first chain index and reset
1485 * tracker state.
1486 */
1487 chain_idx = ioc->ReqToChain[req_idx];
1488 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1489
1490 while (chain_idx != MPT_HOST_NO_CHAIN) {
1491
1492 /* Save the next chain buffer index */
1493 next = ioc->ChainToChain[chain_idx];
1494
1495 /* Free this chain buffer and reset
1496 * tracker
1497 */
1498 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1499
1500 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1501 + (chain_idx * ioc->req_sz));
1502
1503 spin_lock_irqsave(&ioc->FreeQlock, flags);
1504 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1505 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1506
1507 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1508 ioc->name, chain_idx));
1509
1510 /* handle next */
1511 chain_idx = next;
1512 }
1513 return;
1514 }
1515
1516 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1517 /*
1518 * Reset Handling
1519 */
1520
1521 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1522 /**
1523 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1524 * @hd: Pointer to MPT SCSI HOST structure
1525 * @type: Task Management type
1526 * @channel: channel number for task management
1527 * @id: Logical Target ID for reset (if appropriate)
1528 * @lun: Logical Unit for reset (if appropriate)
1529 * @ctx2abort: Context for the task to be aborted (if appropriate)
1530 * @timeout: timeout for task management control
1531 *
1532 * Fall through to mpt_HardResetHandler if: not operational, too many
1533 * failed TM requests or handshake failure.
1534 *
1535 * Remark: Currently invoked from a non-interrupt thread (_bh).
1536 *
1537 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1538 * will be active.
1539 *
1540 * Returns 0 for SUCCESS, or %FAILED.
1541 **/
1542 int
1543 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1544 {
1545 MPT_ADAPTER *ioc;
1546 int rc = -1;
1547 u32 ioc_raw_state;
1548 unsigned long flags;
1549
1550 ioc = hd->ioc;
1551 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1552
1553 // SJR - CHECKME - Can we avoid this here?
1554 // (mpt_HardResetHandler has this check...)
1555 spin_lock_irqsave(&ioc->diagLock, flags);
1556 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1557 spin_unlock_irqrestore(&ioc->diagLock, flags);
1558 return FAILED;
1559 }
1560 spin_unlock_irqrestore(&ioc->diagLock, flags);
1561
1562 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1563 * If we time out and not bus reset, then we return a FAILED status
1564 * to the caller.
1565 * The call to mptscsih_tm_pending_wait() will set the pending flag
1566 * if we are
1567 * successful. Otherwise, reload the FW.
1568 */
1569 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1570 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1571 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1572 "Timed out waiting for last TM (%d) to complete! \n",
1573 hd->ioc->name, hd->tmPending));
1574 return FAILED;
1575 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1576 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target "
1577 "reset: Timed out waiting for last TM (%d) "
1578 "to complete! \n", hd->ioc->name,
1579 hd->tmPending));
1580 return FAILED;
1581 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1582 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1583 "Timed out waiting for last TM (%d) to complete! \n",
1584 hd->ioc->name, hd->tmPending));
1585 return FAILED;
1586 }
1587 } else {
1588 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1589 hd->tmPending |= (1 << type);
1590 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1591 }
1592
1593 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1594
1595 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1596 printk(MYIOC_s_WARN_FMT
1597 "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
1598 ioc->name, type, ioc_raw_state);
1599 printk(KERN_WARNING " Issuing HardReset!!\n");
1600 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
1601 printk((KERN_WARNING "TMHandler: HardReset "
1602 "FAILED!!\n"));
1603 return FAILED;
1604 }
1605
1606 if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
1607 printk(MYIOC_s_WARN_FMT
1608 "TM Handler for type=%x: ioc_state: "
1609 "DOORBELL_ACTIVE (0x%x)!\n",
1610 ioc->name, type, ioc_raw_state);
1611 return FAILED;
1612 }
1613
1614 /* Isse the Task Mgmt request.
1615 */
1616 if (hd->hard_resets < -1)
1617 hd->hard_resets++;
1618
1619 rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
1620 ctx2abort, timeout);
1621 if (rc)
1622 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
1623 hd->ioc->name);
1624 else
1625 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n",
1626 hd->ioc->name));
1627
1628 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1629
1630 return rc;
1631 }
1632
1633
1634 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1635 /**
1636 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1637 * @hd: Pointer to MPT_SCSI_HOST structure
1638 * @type: Task Management type
1639 * @channel: channel number for task management
1640 * @id: Logical Target ID for reset (if appropriate)
1641 * @lun: Logical Unit for reset (if appropriate)
1642 * @ctx2abort: Context for the task to be aborted (if appropriate)
1643 * @timeout: timeout for task management control
1644 *
1645 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1646 * or a non-interrupt thread. In the former, must not call schedule().
1647 *
1648 * Not all fields are meaningfull for all task types.
1649 *
1650 * Returns 0 for SUCCESS, or FAILED.
1651 *
1652 **/
1653 static int
1654 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1655 {
1656 MPT_FRAME_HDR *mf;
1657 SCSITaskMgmt_t *pScsiTm;
1658 int ii;
1659 int retval;
1660
1661 /* Return Fail to calling function if no message frames available.
1662 */
1663 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1664 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1665 hd->ioc->name));
1666 return FAILED;
1667 }
1668 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1669 hd->ioc->name, mf));
1670
1671 /* Format the Request
1672 */
1673 pScsiTm = (SCSITaskMgmt_t *) mf;
1674 pScsiTm->TargetID = id;
1675 pScsiTm->Bus = channel;
1676 pScsiTm->ChainOffset = 0;
1677 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1678
1679 pScsiTm->Reserved = 0;
1680 pScsiTm->TaskType = type;
1681 pScsiTm->Reserved1 = 0;
1682 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1683 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1684
1685 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1686
1687 for (ii=0; ii < 7; ii++)
1688 pScsiTm->Reserved2[ii] = 0;
1689
1690 pScsiTm->TaskMsgContext = ctx2abort;
1691
1692 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
1693 "type=%d\n", hd->ioc->name, ctx2abort, type));
1694
1695 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1696
1697 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1698 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
1699 dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!"
1700 " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
1701 hd->ioc, mf, retval));
1702 goto fail_out;
1703 }
1704
1705 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1706 dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!"
1707 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1708 hd->ioc, mf));
1709 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1710 hd->ioc->name));
1711 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1712 dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n",
1713 hd->ioc->name, retval));
1714 goto fail_out;
1715 }
1716
1717 /*
1718 * Handle success case, see if theres a non-zero ioc_status.
1719 */
1720 if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
1721 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
1722 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
1723 retval = 0;
1724 else
1725 retval = FAILED;
1726
1727 return retval;
1728
1729 fail_out:
1730
1731 /*
1732 * Free task managment mf, and corresponding tm flags
1733 */
1734 mpt_free_msg_frame(hd->ioc, mf);
1735 hd->tmPending = 0;
1736 hd->tmState = TM_STATE_NONE;
1737 return FAILED;
1738 }
1739
1740 static int
1741 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1742 {
1743 switch (ioc->bus_type) {
1744 case FC:
1745 return 40;
1746 case SAS:
1747 return 10;
1748 case SPI:
1749 default:
1750 return 2;
1751 }
1752 }
1753
1754 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1755 /**
1756 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1757 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1758 *
1759 * (linux scsi_host_template.eh_abort_handler routine)
1760 *
1761 * Returns SUCCESS or FAILED.
1762 **/
1763 int
1764 mptscsih_abort(struct scsi_cmnd * SCpnt)
1765 {
1766 MPT_SCSI_HOST *hd;
1767 MPT_FRAME_HDR *mf;
1768 u32 ctx2abort;
1769 int scpnt_idx;
1770 int retval;
1771 VirtDevice *vdev;
1772 ulong sn = SCpnt->serial_number;
1773
1774 /* If we can't locate our host adapter structure, return FAILED status.
1775 */
1776 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1777 SCpnt->result = DID_RESET << 16;
1778 SCpnt->scsi_done(SCpnt);
1779 dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1780 "Can't locate host! (sc=%p)\n",
1781 SCpnt));
1782 return FAILED;
1783 }
1784
1785 /* Find this command
1786 */
1787 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1788 /* Cmd not found in ScsiLookup.
1789 * Do OS callback.
1790 */
1791 SCpnt->result = DID_RESET << 16;
1792 dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1793 "Command not in the active list! (sc=%p)\n",
1794 hd->ioc->name, SCpnt));
1795 return SUCCESS;
1796 }
1797
1798 if (hd->resetPending)
1799 return FAILED;
1800
1801 if (hd->timeouts < -1)
1802 hd->timeouts++;
1803
1804 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1805 hd->ioc->name, SCpnt);
1806 scsi_print_command(SCpnt);
1807
1808 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1809 * (the IO to be ABORT'd)
1810 *
1811 * NOTE: Since we do not byteswap MsgContext, we do not
1812 * swap it here either. It is an opaque cookie to
1813 * the controller, so it does not matter. -DaveM
1814 */
1815 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1816 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1817
1818 hd->abortSCpnt = SCpnt;
1819
1820 vdev = SCpnt->device->hostdata;
1821 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1822 vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
1823 ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1824
1825 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1826 SCpnt->serial_number == sn)
1827 retval = FAILED;
1828
1829 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1830 hd->ioc->name,
1831 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1832
1833 if (retval == 0)
1834 return SUCCESS;
1835 else
1836 return FAILED;
1837 }
1838
1839 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1840 /**
1841 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1842 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1843 *
1844 * (linux scsi_host_template.eh_dev_reset_handler routine)
1845 *
1846 * Returns SUCCESS or FAILED.
1847 **/
1848 int
1849 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1850 {
1851 MPT_SCSI_HOST *hd;
1852 int retval;
1853 VirtDevice *vdev;
1854
1855 /* If we can't locate our host adapter structure, return FAILED status.
1856 */
1857 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1858 dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1859 "Can't locate host! (sc=%p)\n",
1860 SCpnt));
1861 return FAILED;
1862 }
1863
1864 if (hd->resetPending)
1865 return FAILED;
1866
1867 printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1868 hd->ioc->name, SCpnt);
1869 scsi_print_command(SCpnt);
1870
1871 vdev = SCpnt->device->hostdata;
1872 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1873 vdev->vtarget->channel, vdev->vtarget->id,
1874 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1875
1876 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1877 hd->ioc->name,
1878 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1879
1880 if (retval == 0)
1881 return SUCCESS;
1882 else
1883 return FAILED;
1884 }
1885
1886
1887 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1888 /**
1889 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1890 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1891 *
1892 * (linux scsi_host_template.eh_bus_reset_handler routine)
1893 *
1894 * Returns SUCCESS or FAILED.
1895 **/
1896 int
1897 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1898 {
1899 MPT_SCSI_HOST *hd;
1900 int retval;
1901 VirtDevice *vdev;
1902
1903 /* If we can't locate our host adapter structure, return FAILED status.
1904 */
1905 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1906 dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1907 "Can't locate host! (sc=%p)\n",
1908 SCpnt ) );
1909 return FAILED;
1910 }
1911
1912 printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1913 hd->ioc->name, SCpnt);
1914 scsi_print_command(SCpnt);
1915
1916 if (hd->timeouts < -1)
1917 hd->timeouts++;
1918
1919 vdev = SCpnt->device->hostdata;
1920 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1921 vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1922
1923 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1924 hd->ioc->name,
1925 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1926
1927 if (retval == 0)
1928 return SUCCESS;
1929 else
1930 return FAILED;
1931 }
1932
1933 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1934 /**
1935 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1936 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1937 *
1938 * (linux scsi_host_template.eh_host_reset_handler routine)
1939 *
1940 * Returns SUCCESS or FAILED.
1941 */
1942 int
1943 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1944 {
1945 MPT_SCSI_HOST * hd;
1946 int status = SUCCESS;
1947
1948 /* If we can't locate the host to reset, then we failed. */
1949 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1950 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1951 "Can't locate host! (sc=%p)\n",
1952 SCpnt ) );
1953 return FAILED;
1954 }
1955
1956 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1957 hd->ioc->name, SCpnt);
1958
1959 /* If our attempts to reset the host failed, then return a failed
1960 * status. The host will be taken off line by the SCSI mid-layer.
1961 */
1962 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1963 status = FAILED;
1964 } else {
1965 /* Make sure TM pending is cleared and TM state is set to
1966 * NONE.
1967 */
1968 hd->tmPending = 0;
1969 hd->tmState = TM_STATE_NONE;
1970 }
1971
1972 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1973 "Status = %s\n",
1974 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1975
1976 return status;
1977 }
1978
1979 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1980 /**
1981 * mptscsih_tm_pending_wait - wait for pending task management request to complete
1982 * @hd: Pointer to MPT host structure.
1983 *
1984 * Returns {SUCCESS,FAILED}.
1985 */
1986 static int
1987 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1988 {
1989 unsigned long flags;
1990 int loop_count = 4 * 10; /* Wait 10 seconds */
1991 int status = FAILED;
1992
1993 do {
1994 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1995 if (hd->tmState == TM_STATE_NONE) {
1996 hd->tmState = TM_STATE_IN_PROGRESS;
1997 hd->tmPending = 1;
1998 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1999 status = SUCCESS;
2000 break;
2001 }
2002 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2003 msleep(250);
2004 } while (--loop_count);
2005
2006 return status;
2007 }
2008
2009 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2010 /**
2011 * mptscsih_tm_wait_for_completion - wait for completion of TM task
2012 * @hd: Pointer to MPT host structure.
2013 * @timeout: timeout value
2014 *
2015 * Returns {SUCCESS,FAILED}.
2016 */
2017 static int
2018 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2019 {
2020 unsigned long flags;
2021 int loop_count = 4 * timeout;
2022 int status = FAILED;
2023
2024 do {
2025 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2026 if(hd->tmPending == 0) {
2027 status = SUCCESS;
2028 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2029 break;
2030 }
2031 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2032 msleep(250);
2033 } while (--loop_count);
2034
2035 return status;
2036 }
2037
2038 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2039 static void
2040 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2041 {
2042 char *desc;
2043
2044 switch (response_code) {
2045 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2046 desc = "The task completed.";
2047 break;
2048 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2049 desc = "The IOC received an invalid frame status.";
2050 break;
2051 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2052 desc = "The task type is not supported.";
2053 break;
2054 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2055 desc = "The requested task failed.";
2056 break;
2057 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2058 desc = "The task completed successfully.";
2059 break;
2060 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2061 desc = "The LUN request is invalid.";
2062 break;
2063 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2064 desc = "The task is in the IOC queue and has not been sent to target.";
2065 break;
2066 default:
2067 desc = "unknown";
2068 break;
2069 }
2070 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2071 ioc->name, response_code, desc);
2072 }
2073
2074 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2075 /**
2076 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2077 * @ioc: Pointer to MPT_ADAPTER structure
2078 * @mf: Pointer to SCSI task mgmt request frame
2079 * @mr: Pointer to SCSI task mgmt reply frame
2080 *
2081 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2082 * of any SCSI task management request.
2083 * This routine is registered with the MPT (base) driver at driver
2084 * load/init time via the mpt_register() API call.
2085 *
2086 * Returns 1 indicating alloc'd request frame ptr should be freed.
2087 **/
2088 int
2089 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2090 {
2091 SCSITaskMgmtReply_t *pScsiTmReply;
2092 SCSITaskMgmt_t *pScsiTmReq;
2093 MPT_SCSI_HOST *hd;
2094 unsigned long flags;
2095 u16 iocstatus;
2096 u8 tmType;
2097 u32 termination_count;
2098
2099 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2100 ioc->name, mf, mr));
2101 if (!ioc->sh) {
2102 dtmprintk((MYIOC_s_WARN_FMT
2103 "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
2104 return 1;
2105 }
2106
2107 if (mr == NULL) {
2108 dtmprintk((MYIOC_s_WARN_FMT
2109 "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
2110 return 1;
2111 }
2112
2113 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2114 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2115 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2116 tmType = pScsiTmReq->TaskType;
2117 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2118 termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
2119
2120 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2121 pScsiTmReply->ResponseCode)
2122 mptscsih_taskmgmt_response_code(ioc,
2123 pScsiTmReply->ResponseCode);
2124 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2125
2126 #if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM)
2127 printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
2128 "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
2129 "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
2130 pScsiTmReply->TargetID, pScsiTmReq->TaskType,
2131 le16_to_cpu(pScsiTmReply->IOCStatus),
2132 le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
2133 le32_to_cpu(pScsiTmReply->TerminationCount));
2134 #endif
2135 if (!iocstatus) {
2136 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2137 hd->abortSCpnt = NULL;
2138 goto out;
2139 }
2140
2141 /* Error? (anything non-zero?) */
2142
2143 /* clear flags and continue.
2144 */
2145 switch (tmType) {
2146
2147 case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2148 if (termination_count == 1)
2149 iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
2150 hd->abortSCpnt = NULL;
2151 break;
2152
2153 case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
2154
2155 /* If an internal command is present
2156 * or the TM failed - reload the FW.
2157 * FC FW may respond FAILED to an ABORT
2158 */
2159 if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
2160 hd->cmdPtr)
2161 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
2162 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
2163 break;
2164
2165 case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2166 default:
2167 break;
2168 }
2169
2170 out:
2171 spin_lock_irqsave(&ioc->FreeQlock, flags);
2172 hd->tmPending = 0;
2173 hd->tmState = TM_STATE_NONE;
2174 hd->tm_iocstatus = iocstatus;
2175 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2176
2177 return 1;
2178 }
2179
2180 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2181 /*
2182 * This is anyones guess quite frankly.
2183 */
2184 int
2185 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2186 sector_t capacity, int geom[])
2187 {
2188 int heads;
2189 int sectors;
2190 sector_t cylinders;
2191 ulong dummy;
2192
2193 heads = 64;
2194 sectors = 32;
2195
2196 dummy = heads * sectors;
2197 cylinders = capacity;
2198 sector_div(cylinders,dummy);
2199
2200 /*
2201 * Handle extended translation size for logical drives
2202 * > 1Gb
2203 */
2204 if ((ulong)capacity >= 0x200000) {
2205 heads = 255;
2206 sectors = 63;
2207 dummy = heads * sectors;
2208 cylinders = capacity;
2209 sector_div(cylinders,dummy);
2210 }
2211
2212 /* return result */
2213 geom[0] = heads;
2214 geom[1] = sectors;
2215 geom[2] = cylinders;
2216
2217 dprintk((KERN_NOTICE
2218 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2219 sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors));
2220
2221 return 0;
2222 }
2223
2224 /* Search IOC page 3 to determine if this is hidden physical disk
2225 *
2226 */
2227 int
2228 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
2229 {
2230 struct inactive_raid_component_info *component_info;
2231 int i;
2232 int rc = 0;
2233
2234 if (!ioc->raid_data.pIocPg3)
2235 goto out;
2236 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2237 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2238 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2239 rc = 1;
2240 goto out;
2241 }
2242 }
2243
2244 /*
2245 * Check inactive list for matching phys disks
2246 */
2247 if (list_empty(&ioc->raid_data.inactive_list))
2248 goto out;
2249
2250 down(&ioc->raid_data.inactive_list_mutex);
2251 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2252 list) {
2253 if ((component_info->d.PhysDiskID == id) &&
2254 (component_info->d.PhysDiskBus == channel))
2255 rc = 1;
2256 }
2257 up(&ioc->raid_data.inactive_list_mutex);
2258
2259 out:
2260 return rc;
2261 }
2262 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2263
2264 u8
2265 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2266 {
2267 struct inactive_raid_component_info *component_info;
2268 int i;
2269 int rc = -ENXIO;
2270
2271 if (!ioc->raid_data.pIocPg3)
2272 goto out;
2273 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2274 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2275 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2276 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2277 goto out;
2278 }
2279 }
2280
2281 /*
2282 * Check inactive list for matching phys disks
2283 */
2284 if (list_empty(&ioc->raid_data.inactive_list))
2285 goto out;
2286
2287 down(&ioc->raid_data.inactive_list_mutex);
2288 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2289 list) {
2290 if ((component_info->d.PhysDiskID == id) &&
2291 (component_info->d.PhysDiskBus == channel))
2292 rc = component_info->d.PhysDiskNum;
2293 }
2294 up(&ioc->raid_data.inactive_list_mutex);
2295
2296 out:
2297 return rc;
2298 }
2299 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2300
2301 /*
2302 * OS entry point to allow for host driver to free allocated memory
2303 * Called if no device present or device being unloaded
2304 */
2305 void
2306 mptscsih_slave_destroy(struct scsi_device *sdev)
2307 {
2308 struct Scsi_Host *host = sdev->host;
2309 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2310 VirtTarget *vtarget;
2311 VirtDevice *vdevice;
2312 struct scsi_target *starget;
2313
2314 starget = scsi_target(sdev);
2315 vtarget = starget->hostdata;
2316 vdevice = sdev->hostdata;
2317
2318 mptscsih_search_running_cmds(hd, vdevice);
2319 vtarget->num_luns--;
2320 mptscsih_synchronize_cache(hd, vdevice);
2321 kfree(vdevice);
2322 sdev->hostdata = NULL;
2323 }
2324
2325 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2326 /*
2327 * mptscsih_change_queue_depth - This function will set a devices queue depth
2328 * @sdev: per scsi_device pointer
2329 * @qdepth: requested queue depth
2330 *
2331 * Adding support for new 'change_queue_depth' api.
2332 */
2333 int
2334 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2335 {
2336 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2337 VirtTarget *vtarget;
2338 struct scsi_target *starget;
2339 int max_depth;
2340 int tagged;
2341
2342 starget = scsi_target(sdev);
2343 vtarget = starget->hostdata;
2344
2345 if (hd->ioc->bus_type == SPI) {
2346 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2347 max_depth = 1;
2348 else if (sdev->type == TYPE_DISK &&
2349 vtarget->minSyncFactor <= MPT_ULTRA160)
2350 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2351 else
2352 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2353 } else
2354 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2355
2356 if (qdepth > max_depth)
2357 qdepth = max_depth;
2358 if (qdepth == 1)
2359 tagged = 0;
2360 else
2361 tagged = MSG_SIMPLE_TAG;
2362
2363 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2364 return sdev->queue_depth;
2365 }
2366
2367 /*
2368 * OS entry point to adjust the queue_depths on a per-device basis.
2369 * Called once per device the bus scan. Use it to force the queue_depth
2370 * member to 1 if a device does not support Q tags.
2371 * Return non-zero if fails.
2372 */
2373 int
2374 mptscsih_slave_configure(struct scsi_device *sdev)
2375 {
2376 struct Scsi_Host *sh = sdev->host;
2377 VirtTarget *vtarget;
2378 VirtDevice *vdevice;
2379 struct scsi_target *starget;
2380 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2381
2382 starget = scsi_target(sdev);
2383 vtarget = starget->hostdata;
2384 vdevice = sdev->hostdata;
2385
2386 dsprintk((MYIOC_s_INFO_FMT
2387 "device @ %p, channel=%d, id=%d, lun=%d\n",
2388 hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2389 if (hd->ioc->bus_type == SPI)
2390 dsprintk((MYIOC_s_INFO_FMT
2391 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2392 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2393 sdev->ppr, sdev->inquiry_len));
2394
2395 if (sdev->id > sh->max_id) {
2396 /* error case, should never happen */
2397 scsi_adjust_queue_depth(sdev, 0, 1);
2398 goto slave_configure_exit;
2399 }
2400
2401 vdevice->configured_lun = 1;
2402 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2403
2404 dsprintk((MYIOC_s_INFO_FMT
2405 "Queue depth=%d, tflags=%x\n",
2406 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2407
2408 if (hd->ioc->bus_type == SPI)
2409 dsprintk((MYIOC_s_INFO_FMT
2410 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2411 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2412 vtarget->minSyncFactor));
2413
2414 slave_configure_exit:
2415
2416 dsprintk((MYIOC_s_INFO_FMT
2417 "tagged %d, simple %d, ordered %d\n",
2418 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2419 sdev->ordered_tags));
2420
2421 return 0;
2422 }
2423
2424 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2425 /*
2426 * Private routines...
2427 */
2428
2429 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2430 /* Utility function to copy sense data from the scsi_cmnd buffer
2431 * to the FC and SCSI target structures.
2432 *
2433 */
2434 static void
2435 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2436 {
2437 VirtDevice *vdev;
2438 SCSIIORequest_t *pReq;
2439 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2440
2441 /* Get target structure
2442 */
2443 pReq = (SCSIIORequest_t *) mf;
2444 vdev = sc->device->hostdata;
2445
2446 if (sense_count) {
2447 u8 *sense_data;
2448 int req_index;
2449
2450 /* Copy the sense received into the scsi command block. */
2451 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2452 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2453 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2454
2455 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2456 */
2457 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2458 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2459 int idx;
2460 MPT_ADAPTER *ioc = hd->ioc;
2461
2462 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2463 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2464 ioc->events[idx].eventContext = ioc->eventContext;
2465
2466 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
2467 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
2468 (sc->device->channel << 8) | sc->device->id;
2469
2470 ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
2471
2472 ioc->eventContext++;
2473 if (hd->ioc->pcidev->vendor ==
2474 PCI_VENDOR_ID_IBM) {
2475 mptscsih_issue_sep_command(hd->ioc,
2476 vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2477 vdev->vtarget->tflags |=
2478 MPT_TARGET_FLAGS_LED_ON;
2479 }
2480 }
2481 }
2482 } else {
2483 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2484 hd->ioc->name));
2485 }
2486 }
2487
2488 static int
2489 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2490 {
2491 MPT_SCSI_HOST *hd;
2492 int i;
2493
2494 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2495
2496 for (i = 0; i < hd->ioc->req_depth; i++) {
2497 if (hd->ScsiLookup[i] == sc) {
2498 return i;
2499 }
2500 }
2501
2502 return -1;
2503 }
2504
2505 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2506 int
2507 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2508 {
2509 MPT_SCSI_HOST *hd;
2510 unsigned long flags;
2511 int ii;
2512
2513 dtmprintk((KERN_WARNING MYNAM
2514 ": IOC %s_reset routed to SCSI host driver!\n",
2515 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2516 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2517
2518 /* If a FW reload request arrives after base installed but
2519 * before all scsi hosts have been attached, then an alt_ioc
2520 * may have a NULL sh pointer.
2521 */
2522 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2523 return 0;
2524 else
2525 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2526
2527 if (reset_phase == MPT_IOC_SETUP_RESET) {
2528 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2529
2530 /* Clean Up:
2531 * 1. Set Hard Reset Pending Flag
2532 * All new commands go to doneQ
2533 */
2534 hd->resetPending = 1;
2535
2536 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2537 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2538
2539 /* 2. Flush running commands
2540 * Clean ScsiLookup (and associated memory)
2541 * AND clean mytaskQ
2542 */
2543
2544 /* 2b. Reply to OS all known outstanding I/O commands.
2545 */
2546 mptscsih_flush_running_cmds(hd);
2547
2548 /* 2c. If there was an internal command that
2549 * has not completed, configuration or io request,
2550 * free these resources.
2551 */
2552 if (hd->cmdPtr) {
2553 del_timer(&hd->timer);
2554 mpt_free_msg_frame(ioc, hd->cmdPtr);
2555 }
2556
2557 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2558
2559 } else {
2560 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2561
2562 /* Once a FW reload begins, all new OS commands are
2563 * redirected to the doneQ w/ a reset status.
2564 * Init all control structures.
2565 */
2566
2567 /* ScsiLookup initialization
2568 */
2569 for (ii=0; ii < hd->ioc->req_depth; ii++)
2570 hd->ScsiLookup[ii] = NULL;
2571
2572 /* 2. Chain Buffer initialization
2573 */
2574
2575 /* 4. Renegotiate to all devices, if SPI
2576 */
2577
2578 /* 5. Enable new commands to be posted
2579 */
2580 spin_lock_irqsave(&ioc->FreeQlock, flags);
2581 hd->tmPending = 0;
2582 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2583 hd->resetPending = 0;
2584 hd->tmState = TM_STATE_NONE;
2585
2586 /* 6. If there was an internal command,
2587 * wake this process up.
2588 */
2589 if (hd->cmdPtr) {
2590 /*
2591 * Wake up the original calling thread
2592 */
2593 hd->pLocal = &hd->localReply;
2594 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2595 hd->scandv_wait_done = 1;
2596 wake_up(&hd->scandv_waitq);
2597 hd->cmdPtr = NULL;
2598 }
2599
2600 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2601
2602 }
2603
2604 return 1; /* currently means nothing really */
2605 }
2606
2607 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2608 int
2609 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2610 {
2611 MPT_SCSI_HOST *hd;
2612 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2613
2614 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2615 ioc->name, event));
2616
2617 if (ioc->sh == NULL ||
2618 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2619 return 1;
2620
2621 switch (event) {
2622 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2623 /* FIXME! */
2624 break;
2625 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2626 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2627 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2628 hd->soft_resets++;
2629 break;
2630 case MPI_EVENT_LOGOUT: /* 09 */
2631 /* FIXME! */
2632 break;
2633
2634 case MPI_EVENT_RESCAN: /* 06 */
2635 break;
2636
2637 /*
2638 * CHECKME! Don't think we need to do
2639 * anything for these, but...
2640 */
2641 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2642 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2643 /*
2644 * CHECKME! Falling thru...
2645 */
2646 break;
2647
2648 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2649 break;
2650
2651 case MPI_EVENT_NONE: /* 00 */
2652 case MPI_EVENT_LOG_DATA: /* 01 */
2653 case MPI_EVENT_STATE_CHANGE: /* 02 */
2654 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2655 default:
2656 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2657 break;
2658 }
2659
2660 return 1; /* currently means nothing really */
2661 }
2662
2663 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2664 /*
2665 * Bus Scan and Domain Validation functionality ...
2666 */
2667
2668 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2669 /*
2670 * mptscsih_scandv_complete - Scan and DV callback routine registered
2671 * to Fustion MPT (base) driver.
2672 *
2673 * @ioc: Pointer to MPT_ADAPTER structure
2674 * @mf: Pointer to original MPT request frame
2675 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2676 *
2677 * This routine is called from mpt.c::mpt_interrupt() at the completion
2678 * of any SCSI IO request.
2679 * This routine is registered with the Fusion MPT (base) driver at driver
2680 * load/init time via the mpt_register() API call.
2681 *
2682 * Returns 1 indicating alloc'd request frame ptr should be freed.
2683 *
2684 * Remark: Sets a completion code and (possibly) saves sense data
2685 * in the IOC member localReply structure.
2686 * Used ONLY for DV and other internal commands.
2687 */
2688 int
2689 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2690 {
2691 MPT_SCSI_HOST *hd;
2692 SCSIIORequest_t *pReq;
2693 int completionCode;
2694 u16 req_idx;
2695
2696 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2697
2698 if ((mf == NULL) ||
2699 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
2700 printk(MYIOC_s_ERR_FMT
2701 "ScanDvComplete, %s req frame ptr! (=%p)\n",
2702 ioc->name, mf?"BAD":"NULL", (void *) mf);
2703 goto wakeup;
2704 }
2705
2706 del_timer(&hd->timer);
2707 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2708 hd->ScsiLookup[req_idx] = NULL;
2709 pReq = (SCSIIORequest_t *) mf;
2710
2711 if (mf != hd->cmdPtr) {
2712 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
2713 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
2714 }
2715 hd->cmdPtr = NULL;
2716
2717 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
2718 hd->ioc->name, mf, mr, req_idx));
2719
2720 hd->pLocal = &hd->localReply;
2721 hd->pLocal->scsiStatus = 0;
2722
2723 /* If target struct exists, clear sense valid flag.
2724 */
2725 if (mr == NULL) {
2726 completionCode = MPT_SCANDV_GOOD;
2727 } else {
2728 SCSIIOReply_t *pReply;
2729 u16 status;
2730 u8 scsi_status;
2731
2732 pReply = (SCSIIOReply_t *) mr;
2733
2734 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2735 scsi_status = pReply->SCSIStatus;
2736
2737 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
2738 status, pReply->SCSIState, scsi_status,
2739 le32_to_cpu(pReply->IOCLogInfo)));
2740
2741 switch(status) {
2742
2743 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2744 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
2745 break;
2746
2747 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
2748 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
2749 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
2750 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
2751 completionCode = MPT_SCANDV_DID_RESET;
2752 break;
2753
2754 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2755 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2756 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2757 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2758 ConfigReply_t *pr = (ConfigReply_t *)mr;
2759 completionCode = MPT_SCANDV_GOOD;
2760 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
2761 hd->pLocal->header.PageLength = pr->Header.PageLength;
2762 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
2763 hd->pLocal->header.PageType = pr->Header.PageType;
2764
2765 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2766 /* If the RAID Volume request is successful,
2767 * return GOOD, else indicate that
2768 * some type of error occurred.
2769 */
2770 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
2771 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
2772 completionCode = MPT_SCANDV_GOOD;
2773 else
2774 completionCode = MPT_SCANDV_SOME_ERROR;
2775 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
2776
2777 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
2778 u8 *sense_data;
2779 int sz;
2780
2781 /* save sense data in global structure
2782 */
2783 completionCode = MPT_SCANDV_SENSE;
2784 hd->pLocal->scsiStatus = scsi_status;
2785 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
2786 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2787
2788 sz = min_t(int, pReq->SenseBufferLength,
2789 SCSI_STD_SENSE_BYTES);
2790 memcpy(hd->pLocal->sense, sense_data, sz);
2791
2792 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
2793 sense_data));
2794 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2795 if (pReq->CDB[0] == INQUIRY)
2796 completionCode = MPT_SCANDV_ISSUE_SENSE;
2797 else
2798 completionCode = MPT_SCANDV_DID_RESET;
2799 }
2800 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2801 completionCode = MPT_SCANDV_DID_RESET;
2802 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2803 completionCode = MPT_SCANDV_DID_RESET;
2804 else {
2805 completionCode = MPT_SCANDV_GOOD;
2806 hd->pLocal->scsiStatus = scsi_status;
2807 }
2808 break;
2809
2810 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2811 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2812 completionCode = MPT_SCANDV_DID_RESET;
2813 else
2814 completionCode = MPT_SCANDV_SOME_ERROR;
2815 break;
2816
2817 default:
2818 completionCode = MPT_SCANDV_SOME_ERROR;
2819 break;
2820
2821 } /* switch(status) */
2822
2823 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
2824 completionCode));
2825 } /* end of address reply case */
2826
2827 hd->pLocal->completion = completionCode;
2828
2829 /* MF and RF are freed in mpt_interrupt
2830 */
2831 wakeup:
2832 /* Free Chain buffers (will never chain) in scan or dv */
2833 //mptscsih_freeChainBuffers(ioc, req_idx);
2834
2835 /*
2836 * Wake up the original calling thread
2837 */
2838 hd->scandv_wait_done = 1;
2839 wake_up(&hd->scandv_waitq);
2840
2841 return 1;
2842 }
2843
2844 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2845 /* mptscsih_timer_expired - Call back for timer process.
2846 * Used only for dv functionality.
2847 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
2848 *
2849 */
2850 void
2851 mptscsih_timer_expired(unsigned long data)
2852 {
2853 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
2854
2855 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
2856
2857 if (hd->cmdPtr) {
2858 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
2859
2860 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
2861 /* Desire to issue a task management request here.
2862 * TM requests MUST be single threaded.
2863 * If old eh code and no TM current, issue request.
2864 * If new eh code, do nothing. Wait for OS cmd timeout
2865 * for bus reset.
2866 */
2867 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
2868 } else {
2869 /* Perform a FW reload */
2870 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
2871 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
2872 }
2873 }
2874 } else {
2875 /* This should NEVER happen */
2876 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
2877 }
2878
2879 /* No more processing.
2880 * TM call will generate an interrupt for SCSI TM Management.
2881 * The FW will reply to all outstanding commands, callback will finish cleanup.
2882 * Hard reset clean-up will free all resources.
2883 */
2884 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
2885
2886 return;
2887 }
2888
2889
2890 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2891 /**
2892 * mptscsih_do_cmd - Do internal command.
2893 * @hd: MPT_SCSI_HOST pointer
2894 * @io: INTERNAL_CMD pointer.
2895 *
2896 * Issue the specified internally generated command and do command
2897 * specific cleanup. For bus scan / DV only.
2898 * NOTES: If command is Inquiry and status is good,
2899 * initialize a target structure, save the data
2900 *
2901 * Remark: Single threaded access only.
2902 *
2903 * Return:
2904 * < 0 if an illegal command or no resources
2905 *
2906 * 0 if good
2907 *
2908 * > 0 if command complete but some type of completion error.
2909 */
2910 static int
2911 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2912 {
2913 MPT_FRAME_HDR *mf;
2914 SCSIIORequest_t *pScsiReq;
2915 SCSIIORequest_t ReqCopy;
2916 int my_idx, ii, dir;
2917 int rc, cmdTimeout;
2918 int in_isr;
2919 char cmdLen;
2920 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2921 char cmd = io->cmd;
2922
2923 in_isr = in_interrupt();
2924 if (in_isr) {
2925 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
2926 hd->ioc->name));
2927 return -EPERM;
2928 }
2929
2930
2931 /* Set command specific information
2932 */
2933 switch (cmd) {
2934 case INQUIRY:
2935 cmdLen = 6;
2936 dir = MPI_SCSIIO_CONTROL_READ;
2937 CDB[0] = cmd;
2938 CDB[4] = io->size;
2939 cmdTimeout = 10;
2940 break;
2941
2942 case TEST_UNIT_READY:
2943 cmdLen = 6;
2944 dir = MPI_SCSIIO_CONTROL_READ;
2945 cmdTimeout = 10;
2946 break;
2947
2948 case START_STOP:
2949 cmdLen = 6;
2950 dir = MPI_SCSIIO_CONTROL_READ;
2951 CDB[0] = cmd;
2952 CDB[4] = 1; /*Spin up the disk */
2953 cmdTimeout = 15;
2954 break;
2955
2956 case REQUEST_SENSE:
2957 cmdLen = 6;
2958 CDB[0] = cmd;
2959 CDB[4] = io->size;
2960 dir = MPI_SCSIIO_CONTROL_READ;
2961 cmdTimeout = 10;
2962 break;
2963
2964 case READ_BUFFER:
2965 cmdLen = 10;
2966 dir = MPI_SCSIIO_CONTROL_READ;
2967 CDB[0] = cmd;
2968 if (io->flags & MPT_ICFLAG_ECHO) {
2969 CDB[1] = 0x0A;
2970 } else {
2971 CDB[1] = 0x02;
2972 }
2973
2974 if (io->flags & MPT_ICFLAG_BUF_CAP) {
2975 CDB[1] |= 0x01;
2976 }
2977 CDB[6] = (io->size >> 16) & 0xFF;
2978 CDB[7] = (io->size >> 8) & 0xFF;
2979 CDB[8] = io->size & 0xFF;
2980 cmdTimeout = 10;
2981 break;
2982
2983 case WRITE_BUFFER:
2984 cmdLen = 10;
2985 dir = MPI_SCSIIO_CONTROL_WRITE;
2986 CDB[0] = cmd;
2987 if (io->flags & MPT_ICFLAG_ECHO) {
2988 CDB[1] = 0x0A;
2989 } else {
2990 CDB[1] = 0x02;
2991 }
2992 CDB[6] = (io->size >> 16) & 0xFF;
2993 CDB[7] = (io->size >> 8) & 0xFF;
2994 CDB[8] = io->size & 0xFF;
2995 cmdTimeout = 10;
2996 break;
2997
2998 case RESERVE:
2999 cmdLen = 6;
3000 dir = MPI_SCSIIO_CONTROL_READ;
3001 CDB[0] = cmd;
3002 cmdTimeout = 10;
3003 break;
3004
3005 case RELEASE:
3006 cmdLen = 6;
3007 dir = MPI_SCSIIO_CONTROL_READ;
3008 CDB[0] = cmd;
3009 cmdTimeout = 10;
3010 break;
3011
3012 case SYNCHRONIZE_CACHE:
3013 cmdLen = 10;
3014 dir = MPI_SCSIIO_CONTROL_READ;
3015 CDB[0] = cmd;
3016 // CDB[1] = 0x02; /* set immediate bit */
3017 cmdTimeout = 10;
3018 break;
3019
3020 default:
3021 /* Error Case */
3022 return -EFAULT;
3023 }
3024
3025 /* Get and Populate a free Frame
3026 */
3027 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3028 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3029 hd->ioc->name));
3030 return -EBUSY;
3031 }
3032
3033 pScsiReq = (SCSIIORequest_t *) mf;
3034
3035 /* Get the request index */
3036 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3037 ADD_INDEX_LOG(my_idx); /* for debug */
3038
3039 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3040 pScsiReq->TargetID = io->physDiskNum;
3041 pScsiReq->Bus = 0;
3042 pScsiReq->ChainOffset = 0;
3043 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3044 } else {
3045 pScsiReq->TargetID = io->id;
3046 pScsiReq->Bus = io->channel;
3047 pScsiReq->ChainOffset = 0;
3048 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3049 }
3050
3051 pScsiReq->CDBLength = cmdLen;
3052 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3053
3054 pScsiReq->Reserved = 0;
3055
3056 pScsiReq->MsgFlags = mpt_msg_flags();
3057 /* MsgContext set in mpt_get_msg_fram call */
3058
3059 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
3060
3061 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3062 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3063 else
3064 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3065
3066 if (cmd == REQUEST_SENSE) {
3067 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3068 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3069 hd->ioc->name, cmd));
3070 }
3071
3072 for (ii=0; ii < 16; ii++)
3073 pScsiReq->CDB[ii] = CDB[ii];
3074
3075 pScsiReq->DataLength = cpu_to_le32(io->size);
3076 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3077 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3078
3079 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3080 hd->ioc->name, cmd, io->channel, io->id, io->lun));
3081
3082 if (dir == MPI_SCSIIO_CONTROL_READ) {
3083 mpt_add_sge((char *) &pScsiReq->SGL,
3084 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3085 io->data_dma);
3086 } else {
3087 mpt_add_sge((char *) &pScsiReq->SGL,
3088 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3089 io->data_dma);
3090 }
3091
3092 /* The ISR will free the request frame, but we need
3093 * the information to initialize the target. Duplicate.
3094 */
3095 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3096
3097 /* Issue this command after:
3098 * finish init
3099 * add timer
3100 * Wait until the reply has been received
3101 * ScsiScanDvCtx callback function will
3102 * set hd->pLocal;
3103 * set scandv_wait_done and call wake_up
3104 */
3105 hd->pLocal = NULL;
3106 hd->timer.expires = jiffies + HZ*cmdTimeout;
3107 hd->scandv_wait_done = 0;
3108
3109 /* Save cmd pointer, for resource free if timeout or
3110 * FW reload occurs
3111 */
3112 hd->cmdPtr = mf;
3113
3114 add_timer(&hd->timer);
3115 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3116 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3117
3118 if (hd->pLocal) {
3119 rc = hd->pLocal->completion;
3120 hd->pLocal->skip = 0;
3121
3122 /* Always set fatal error codes in some cases.
3123 */
3124 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3125 rc = -ENXIO;
3126 else if (rc == MPT_SCANDV_SOME_ERROR)
3127 rc = -rc;
3128 } else {
3129 rc = -EFAULT;
3130 /* This should never happen. */
3131 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3132 hd->ioc->name));
3133 }
3134
3135 return rc;
3136 }
3137
3138 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3139 /**
3140 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3141 * @hd: Pointer to a SCSI HOST structure
3142 * @vdevice: virtual target device
3143 *
3144 * Uses the ISR, but with special processing.
3145 * MUST be single-threaded.
3146 *
3147 */
3148 static void
3149 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3150 {
3151 INTERNAL_CMD iocmd;
3152
3153 /* Following parameters will not change
3154 * in this routine.
3155 */
3156 iocmd.cmd = SYNCHRONIZE_CACHE;
3157 iocmd.flags = 0;
3158 iocmd.physDiskNum = -1;
3159 iocmd.data = NULL;
3160 iocmd.data_dma = -1;
3161 iocmd.size = 0;
3162 iocmd.rsvd = iocmd.rsvd2 = 0;
3163 iocmd.channel = vdevice->vtarget->channel;
3164 iocmd.id = vdevice->vtarget->id;
3165 iocmd.lun = vdevice->lun;
3166
3167 if ((vdevice->vtarget->type == TYPE_DISK) &&
3168 (vdevice->configured_lun))
3169 mptscsih_do_cmd(hd, &iocmd);
3170 }
3171
3172 EXPORT_SYMBOL(mptscsih_remove);
3173 EXPORT_SYMBOL(mptscsih_shutdown);
3174 #ifdef CONFIG_PM
3175 EXPORT_SYMBOL(mptscsih_suspend);
3176 EXPORT_SYMBOL(mptscsih_resume);
3177 #endif
3178 EXPORT_SYMBOL(mptscsih_proc_info);
3179 EXPORT_SYMBOL(mptscsih_info);
3180 EXPORT_SYMBOL(mptscsih_qcmd);
3181 EXPORT_SYMBOL(mptscsih_slave_destroy);
3182 EXPORT_SYMBOL(mptscsih_slave_configure);
3183 EXPORT_SYMBOL(mptscsih_abort);
3184 EXPORT_SYMBOL(mptscsih_dev_reset);
3185 EXPORT_SYMBOL(mptscsih_bus_reset);
3186 EXPORT_SYMBOL(mptscsih_host_reset);
3187 EXPORT_SYMBOL(mptscsih_bios_param);
3188 EXPORT_SYMBOL(mptscsih_io_done);
3189 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3190 EXPORT_SYMBOL(mptscsih_scandv_complete);
3191 EXPORT_SYMBOL(mptscsih_event_process);
3192 EXPORT_SYMBOL(mptscsih_ioc_reset);
3193 EXPORT_SYMBOL(mptscsih_change_queue_depth);
3194 EXPORT_SYMBOL(mptscsih_timer_expired);
3195 EXPORT_SYMBOL(mptscsih_TMHandler);
3196
3197 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
This page took 0.232326 seconds and 6 git commands to generate.