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