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