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