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