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