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