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