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