Linux 2.6.20.7
[linux/fpc-iii.git] / drivers / message / fusion / mptscsih.c
blobf0cca3ea93b20b8d4f72279480ac56e81e681b13
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.
6 * Copyright (c) 1999-2007 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
9 */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
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.
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.
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
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
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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>
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>
67 #include "mptbase.h"
68 #include "mptscsih.h"
69 #include "lsi/mpi_log_sas.h"
71 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
72 #define my_NAME "Fusion MPT SCSI Host driver"
73 #define my_VERSION MPT_LINUX_VERSION_COMMON
74 #define MYNAM "mptscsih"
76 MODULE_AUTHOR(MODULEAUTHOR);
77 MODULE_DESCRIPTION(my_NAME);
78 MODULE_LICENSE("GPL");
79 MODULE_VERSION(my_VERSION);
81 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
83 typedef struct _BIG_SENSE_BUF {
84 u8 data[MPT_SENSE_BUFFER_ALLOC];
85 } BIG_SENSE_BUF;
87 #define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
88 #define MPT_SCANDV_DID_RESET (0x00000001)
89 #define MPT_SCANDV_SENSE (0x00000002)
90 #define MPT_SCANDV_SOME_ERROR (0x00000004)
91 #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
92 #define MPT_SCANDV_ISSUE_SENSE (0x00000010)
93 #define MPT_SCANDV_FALLBACK (0x00000020)
95 #define MPT_SCANDV_MAX_RETRIES (10)
97 #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
98 #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
99 #define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */
100 #define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */
101 #define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */
102 #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
103 #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
105 typedef struct _internal_cmd {
106 char *data; /* data pointer */
107 dma_addr_t data_dma; /* data dma address */
108 int size; /* transfer size */
109 u8 cmd; /* SCSI Op Code */
110 u8 bus; /* bus number */
111 u8 id; /* SCSI ID (virtual) */
112 u8 lun;
113 u8 flags; /* Bit Field - See above */
114 u8 physDiskNum; /* Phys disk number, -1 else */
115 u8 rsvd2;
116 u8 rsvd;
117 } INTERNAL_CMD;
120 * Other private/forward protos...
122 int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
123 static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
124 int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
126 static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
127 SCSIIORequest_t *pReq, int req_idx);
128 static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
129 static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
130 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
131 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
132 static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
134 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
136 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
137 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
139 static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
140 static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
141 static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
142 int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
143 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
144 static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
146 void mptscsih_remove(struct pci_dev *);
147 void mptscsih_shutdown(struct pci_dev *);
148 #ifdef CONFIG_PM
149 int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
150 int mptscsih_resume(struct pci_dev *pdev);
151 #endif
153 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
155 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
157 * mptscsih_add_sge - Place a simple SGE at address pAddr.
158 * @pAddr: virtual address for SGE
159 * @flagslength: SGE flags and data transfer length
160 * @dma_addr: Physical address
162 * This routine places a MPT request frame back on the MPT adapter's
163 * FreeQ.
165 static inline void
166 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
168 if (sizeof(dma_addr_t) == sizeof(u64)) {
169 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
170 u32 tmp = dma_addr & 0xFFFFFFFF;
172 pSge->FlagsLength = cpu_to_le32(flagslength);
173 pSge->Address.Low = cpu_to_le32(tmp);
174 tmp = (u32) ((u64)dma_addr >> 32);
175 pSge->Address.High = cpu_to_le32(tmp);
177 } else {
178 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
179 pSge->FlagsLength = cpu_to_le32(flagslength);
180 pSge->Address = cpu_to_le32(dma_addr);
182 } /* mptscsih_add_sge() */
184 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
186 * mptscsih_add_chain - Place a chain SGE at address pAddr.
187 * @pAddr: virtual address for SGE
188 * @next: nextChainOffset value (u32's)
189 * @length: length of next SGL segment
190 * @dma_addr: Physical address
192 * This routine places a MPT request frame back on the MPT adapter's
193 * FreeQ.
195 static inline void
196 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
198 if (sizeof(dma_addr_t) == sizeof(u64)) {
199 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
200 u32 tmp = dma_addr & 0xFFFFFFFF;
202 pChain->Length = cpu_to_le16(length);
203 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
205 pChain->NextChainOffset = next;
207 pChain->Address.Low = cpu_to_le32(tmp);
208 tmp = (u32) ((u64)dma_addr >> 32);
209 pChain->Address.High = cpu_to_le32(tmp);
210 } else {
211 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
212 pChain->Length = cpu_to_le16(length);
213 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
214 pChain->NextChainOffset = next;
215 pChain->Address = cpu_to_le32(dma_addr);
217 } /* mptscsih_add_chain() */
219 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
221 * mptscsih_getFreeChainBuffer - Function to get a free chain
222 * from the MPT_SCSI_HOST FreeChainQ.
223 * @ioc: Pointer to MPT_ADAPTER structure
224 * @req_idx: Index of the SCSI IO request frame. (output)
226 * return SUCCESS or FAILED
228 static inline int
229 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
231 MPT_FRAME_HDR *chainBuf;
232 unsigned long flags;
233 int rc;
234 int chain_idx;
236 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
237 ioc->name));
238 spin_lock_irqsave(&ioc->FreeQlock, flags);
239 if (!list_empty(&ioc->FreeChainQ)) {
240 int offset;
242 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
243 u.frame.linkage.list);
244 list_del(&chainBuf->u.frame.linkage.list);
245 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
246 chain_idx = offset / ioc->req_sz;
247 rc = SUCCESS;
248 dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
249 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
250 } else {
251 rc = FAILED;
252 chain_idx = MPT_HOST_NO_CHAIN;
253 dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
254 ioc->name));
256 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
258 *retIndex = chain_idx;
259 return rc;
260 } /* mptscsih_getFreeChainBuffer() */
262 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
264 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
265 * SCSIIORequest_t Message Frame.
266 * @ioc: Pointer to MPT_ADAPTER structure
267 * @SCpnt: Pointer to scsi_cmnd structure
268 * @pReq: Pointer to SCSIIORequest_t structure
270 * Returns ...
272 static int
273 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
274 SCSIIORequest_t *pReq, int req_idx)
276 char *psge;
277 char *chainSge;
278 struct scatterlist *sg;
279 int frm_sz;
280 int sges_left, sg_done;
281 int chain_idx = MPT_HOST_NO_CHAIN;
282 int sgeOffset;
283 int numSgeSlots, numSgeThisFrame;
284 u32 sgflags, sgdir, thisxfer = 0;
285 int chain_dma_off = 0;
286 int newIndex;
287 int ii;
288 dma_addr_t v2;
289 u32 RequestNB;
291 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
292 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
293 sgdir = MPT_TRANSFER_HOST_TO_IOC;
294 } else {
295 sgdir = MPT_TRANSFER_IOC_TO_HOST;
298 psge = (char *) &pReq->SGL;
299 frm_sz = ioc->req_sz;
301 /* Map the data portion, if any.
302 * sges_left = 0 if no data transfer.
304 if ( (sges_left = SCpnt->use_sg) ) {
305 sges_left = pci_map_sg(ioc->pcidev,
306 (struct scatterlist *) SCpnt->request_buffer,
307 SCpnt->use_sg,
308 SCpnt->sc_data_direction);
309 if (sges_left == 0)
310 return FAILED;
311 } else if (SCpnt->request_bufflen) {
312 SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
313 SCpnt->request_buffer,
314 SCpnt->request_bufflen,
315 SCpnt->sc_data_direction);
316 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
317 ioc->name, SCpnt, SCpnt->request_bufflen));
318 mptscsih_add_sge((char *) &pReq->SGL,
319 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
320 SCpnt->SCp.dma_handle);
322 return SUCCESS;
325 /* Handle the SG case.
327 sg = (struct scatterlist *) SCpnt->request_buffer;
328 sg_done = 0;
329 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
330 chainSge = NULL;
332 /* Prior to entering this loop - the following must be set
333 * current MF: sgeOffset (bytes)
334 * chainSge (Null if original MF is not a chain buffer)
335 * sg_done (num SGE done for this MF)
338 nextSGEset:
339 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
340 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
342 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
344 /* Get first (num - 1) SG elements
345 * Skip any SG entries with a length of 0
346 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
348 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
349 thisxfer = sg_dma_len(sg);
350 if (thisxfer == 0) {
351 sg ++; /* Get next SG element from the OS */
352 sg_done++;
353 continue;
356 v2 = sg_dma_address(sg);
357 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
359 sg++; /* Get next SG element from the OS */
360 psge += (sizeof(u32) + sizeof(dma_addr_t));
361 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
362 sg_done++;
365 if (numSgeThisFrame == sges_left) {
366 /* Add last element, end of buffer and end of list flags.
368 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
369 MPT_SGE_FLAGS_END_OF_BUFFER |
370 MPT_SGE_FLAGS_END_OF_LIST;
372 /* Add last SGE and set termination flags.
373 * Note: Last SGE may have a length of 0 - which should be ok.
375 thisxfer = sg_dma_len(sg);
377 v2 = sg_dma_address(sg);
378 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
380 sg++;
381 psge += (sizeof(u32) + sizeof(dma_addr_t));
383 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
384 sg_done++;
386 if (chainSge) {
387 /* The current buffer is a chain buffer,
388 * but there is not another one.
389 * Update the chain element
390 * Offset and Length fields.
392 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
393 } else {
394 /* The current buffer is the original MF
395 * and there is no Chain buffer.
397 pReq->ChainOffset = 0;
398 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
399 dsgprintk((MYIOC_s_INFO_FMT
400 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
401 ioc->RequestNB[req_idx] = RequestNB;
403 } else {
404 /* At least one chain buffer is needed.
405 * Complete the first MF
406 * - last SGE element, set the LastElement bit
407 * - set ChainOffset (words) for orig MF
408 * (OR finish previous MF chain buffer)
409 * - update MFStructPtr ChainIndex
410 * - Populate chain element
411 * Also
412 * Loop until done.
415 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
416 ioc->name, sg_done));
418 /* Set LAST_ELEMENT flag for last non-chain element
419 * in the buffer. Since psge points at the NEXT
420 * SGE element, go back one SGE element, update the flags
421 * and reset the pointer. (Note: sgflags & thisxfer are already
422 * set properly).
424 if (sg_done) {
425 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
426 sgflags = le32_to_cpu(*ptmp);
427 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
428 *ptmp = cpu_to_le32(sgflags);
431 if (chainSge) {
432 /* The current buffer is a chain buffer.
433 * chainSge points to the previous Chain Element.
434 * Update its chain element Offset and Length (must
435 * include chain element size) fields.
436 * Old chain element is now complete.
438 u8 nextChain = (u8) (sgeOffset >> 2);
439 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
440 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
441 } else {
442 /* The original MF buffer requires a chain buffer -
443 * set the offset.
444 * Last element in this MF is a chain element.
446 pReq->ChainOffset = (u8) (sgeOffset >> 2);
447 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
448 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
449 ioc->RequestNB[req_idx] = RequestNB;
452 sges_left -= sg_done;
455 /* NOTE: psge points to the beginning of the chain element
456 * in current buffer. Get a chain buffer.
458 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
459 dfailprintk((MYIOC_s_INFO_FMT
460 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
461 ioc->name, pReq->CDB[0], SCpnt));
462 return FAILED;
465 /* Update the tracking arrays.
466 * If chainSge == NULL, update ReqToChain, else ChainToChain
468 if (chainSge) {
469 ioc->ChainToChain[chain_idx] = newIndex;
470 } else {
471 ioc->ReqToChain[req_idx] = newIndex;
473 chain_idx = newIndex;
474 chain_dma_off = ioc->req_sz * chain_idx;
476 /* Populate the chainSGE for the current buffer.
477 * - Set chain buffer pointer to psge and fill
478 * out the Address and Flags fields.
480 chainSge = (char *) psge;
481 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
482 psge, req_idx));
484 /* Start the SGE for the next buffer
486 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
487 sgeOffset = 0;
488 sg_done = 0;
490 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
491 psge, chain_idx));
493 /* Start the SGE for the next buffer
496 goto nextSGEset;
499 return SUCCESS;
500 } /* mptscsih_AddSGE() */
502 static void
503 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
504 U32 SlotStatus)
506 MPT_FRAME_HDR *mf;
507 SEPRequest_t *SEPMsg;
509 if (ioc->bus_type == FC)
510 return;
512 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
513 dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
514 ioc->name,__FUNCTION__));
515 return;
518 SEPMsg = (SEPRequest_t *)mf;
519 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
520 SEPMsg->Bus = vtarget->bus_id;
521 SEPMsg->TargetID = vtarget->target_id;
522 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
523 SEPMsg->SlotStatus = SlotStatus;
524 devtverboseprintk((MYIOC_s_WARN_FMT
525 "Sending SEP cmd=%x id=%d bus=%d\n",
526 ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
527 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
530 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
532 * mptscsih_io_done - Main SCSI IO callback routine registered to
533 * Fusion MPT (base) driver
534 * @ioc: Pointer to MPT_ADAPTER structure
535 * @mf: Pointer to original MPT request frame
536 * @r: Pointer to MPT reply frame (NULL if TurboReply)
538 * This routine is called from mpt.c::mpt_interrupt() at the completion
539 * of any SCSI IO request.
540 * This routine is registered with the Fusion MPT (base) driver at driver
541 * load/init time via the mpt_register() API call.
543 * Returns 1 indicating alloc'd request frame ptr should be freed.
546 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
548 struct scsi_cmnd *sc;
549 MPT_SCSI_HOST *hd;
550 SCSIIORequest_t *pScsiReq;
551 SCSIIOReply_t *pScsiReply;
552 u16 req_idx, req_idx_MR;
553 VirtDevice *vdev;
554 VirtTarget *vtarget;
556 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
558 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
559 req_idx_MR = (mr != NULL) ?
560 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
561 if ((req_idx != req_idx_MR) ||
562 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
563 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
564 ioc->name);
565 printk (MYIOC_s_ERR_FMT
566 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
567 ioc->name, req_idx, req_idx_MR, mf, mr,
568 hd->ScsiLookup[req_idx_MR]);
569 return 0;
572 sc = hd->ScsiLookup[req_idx];
573 hd->ScsiLookup[req_idx] = NULL;
574 if (sc == NULL) {
575 MPIHeader_t *hdr = (MPIHeader_t *)mf;
577 /* Remark: writeSDP1 will use the ScsiDoneCtx
578 * If a SCSI I/O cmd, device disabled by OS and
579 * completion done. Cannot touch sc struct. Just free mem.
581 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
582 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
583 ioc->name);
585 mptscsih_freeChainBuffers(ioc, req_idx);
586 return 1;
589 if ((unsigned char *)mf != sc->host_scribble) {
590 mptscsih_freeChainBuffers(ioc, req_idx);
591 return 1;
594 sc->host_scribble = NULL;
595 sc->result = DID_OK << 16; /* Set default reply as OK */
596 pScsiReq = (SCSIIORequest_t *) mf;
597 pScsiReply = (SCSIIOReply_t *) mr;
599 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
600 dmfprintk((MYIOC_s_INFO_FMT
601 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
602 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
603 }else{
604 dmfprintk((MYIOC_s_INFO_FMT
605 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
606 ioc->name, mf, mr, sc, req_idx));
609 if (pScsiReply == NULL) {
610 /* special context reply handling */
612 } else {
613 u32 xfer_cnt;
614 u16 status;
615 u8 scsi_state, scsi_status;
617 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
618 scsi_state = pScsiReply->SCSIState;
619 scsi_status = pScsiReply->SCSIStatus;
620 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
621 sc->resid = sc->request_bufflen - xfer_cnt;
624 * if we get a data underrun indication, yet no data was
625 * transferred and the SCSI status indicates that the
626 * command was never started, change the data underrun
627 * to success
629 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
630 (scsi_status == MPI_SCSI_STATUS_BUSY ||
631 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
632 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
633 status = MPI_IOCSTATUS_SUCCESS;
636 dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
637 "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
638 "resid=%d bufflen=%d xfer_cnt=%d\n",
639 ioc->id, sc->device->id, sc->device->lun,
640 status, scsi_state, scsi_status, sc->resid,
641 sc->request_bufflen, xfer_cnt));
643 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
644 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
647 * Look for + dump FCP ResponseInfo[]!
649 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
650 pScsiReply->ResponseInfo) {
651 printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
652 "FCP_ResponseInfo=%08xh\n",
653 ioc->id, sc->device->id, sc->device->lun,
654 le32_to_cpu(pScsiReply->ResponseInfo));
657 switch(status) {
658 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
659 /* CHECKME!
660 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
661 * But not: DID_BUS_BUSY lest one risk
662 * killing interrupt handler:-(
664 sc->result = SAM_STAT_BUSY;
665 break;
667 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
668 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
669 sc->result = DID_BAD_TARGET << 16;
670 break;
672 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
673 /* Spoof to SCSI Selection Timeout! */
674 if (ioc->bus_type != FC)
675 sc->result = DID_NO_CONNECT << 16;
676 /* else fibre, just stall until rescan event */
677 else
678 sc->result = DID_REQUEUE << 16;
680 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
681 hd->sel_timeout[pScsiReq->TargetID]++;
683 vdev = sc->device->hostdata;
684 if (!vdev)
685 break;
686 vtarget = vdev->vtarget;
687 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
688 mptscsih_issue_sep_command(ioc, vtarget,
689 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
690 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
692 break;
694 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
695 if ( ioc->bus_type == SAS ) {
696 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
697 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
698 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
699 log_info &=SAS_LOGINFO_MASK;
700 if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
701 sc->result = (DID_BUS_BUSY << 16);
702 break;
705 } else if (ioc->bus_type == FC) {
707 * The FC IOC may kill a request for variety of
708 * reasons, some of which may be recovered by a
709 * retry, some which are unlikely to be
710 * recovered. Return DID_ERROR instead of
711 * DID_RESET to permit retry of the command,
712 * just not an infinite number of them
714 sc->result = DID_ERROR << 16;
715 break;
719 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
722 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
723 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
724 /* Linux handles an unsolicited DID_RESET better
725 * than an unsolicited DID_ABORT.
727 sc->result = DID_RESET << 16;
729 break;
731 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
732 sc->resid = sc->request_bufflen - xfer_cnt;
733 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
734 sc->result=DID_SOFT_ERROR << 16;
735 else /* Sufficient data transfer occurred */
736 sc->result = (DID_OK << 16) | scsi_status;
737 dreplyprintk((KERN_NOTICE
738 "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
739 break;
741 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
743 * Do upfront check for valid SenseData and give it
744 * precedence!
746 sc->result = (DID_OK << 16) | scsi_status;
747 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
748 /* Have already saved the status and sense data
751 } else {
752 if (xfer_cnt < sc->underflow) {
753 if (scsi_status == SAM_STAT_BUSY)
754 sc->result = SAM_STAT_BUSY;
755 else
756 sc->result = DID_SOFT_ERROR << 16;
758 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
759 /* What to do?
761 sc->result = DID_SOFT_ERROR << 16;
763 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
764 /* Not real sure here either... */
765 sc->result = DID_RESET << 16;
769 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
770 sc->underflow));
771 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
772 /* Report Queue Full
774 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
775 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
777 break;
779 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
780 sc->resid=0;
781 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
782 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
783 if (scsi_status == MPI_SCSI_STATUS_BUSY)
784 sc->result = (DID_BUS_BUSY << 16) | scsi_status;
785 else
786 sc->result = (DID_OK << 16) | scsi_status;
787 if (scsi_state == 0) {
789 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
791 * If running against circa 200003dd 909 MPT f/w,
792 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
793 * (QUEUE_FULL) returned from device! --> get 0x0000?128
794 * and with SenseBytes set to 0.
796 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
797 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
800 else if (scsi_state &
801 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
804 * What to do?
806 sc->result = DID_SOFT_ERROR << 16;
808 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
809 /* Not real sure here either... */
810 sc->result = DID_RESET << 16;
812 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
813 /* Device Inq. data indicates that it supports
814 * QTags, but rejects QTag messages.
815 * This command completed OK.
817 * Not real sure here either so do nothing... */
820 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
821 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
823 /* Add handling of:
824 * Reservation Conflict, Busy,
825 * Command Terminated, CHECK
827 break;
829 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
830 sc->result = DID_SOFT_ERROR << 16;
831 break;
833 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
834 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
835 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
836 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
837 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
838 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
839 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
840 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
841 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
842 default:
844 * What to do?
846 sc->result = DID_SOFT_ERROR << 16;
847 break;
849 } /* switch(status) */
851 dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
852 } /* end of address reply case */
854 /* Unmap the DMA buffers, if any. */
855 if (sc->use_sg) {
856 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
857 sc->use_sg, sc->sc_data_direction);
858 } else if (sc->request_bufflen) {
859 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
860 sc->request_bufflen, sc->sc_data_direction);
863 sc->scsi_done(sc); /* Issue the command callback */
865 /* Free Chain buffers */
866 mptscsih_freeChainBuffers(ioc, req_idx);
867 return 1;
871 * mptscsih_flush_running_cmds - For each command found, search
872 * Scsi_Host instance taskQ and reply to OS.
873 * Called only if recovering from a FW reload.
874 * @hd: Pointer to a SCSI HOST structure
876 * Returns: None.
878 * Must be called while new I/Os are being queued.
880 static void
881 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
883 MPT_ADAPTER *ioc = hd->ioc;
884 struct scsi_cmnd *SCpnt;
885 MPT_FRAME_HDR *mf;
886 int ii;
887 int max = ioc->req_depth;
889 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
890 for (ii= 0; ii < max; ii++) {
891 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
893 /* Command found.
896 /* Null ScsiLookup index
898 hd->ScsiLookup[ii] = NULL;
900 mf = MPT_INDEX_2_MFPTR(ioc, ii);
901 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
902 mf, SCpnt));
904 /* Free Chain buffers */
905 mptscsih_freeChainBuffers(ioc, ii);
907 /* Free Message frames */
908 mpt_free_msg_frame(ioc, mf);
910 if ((unsigned char *)mf != SCpnt->host_scribble)
911 continue;
913 /* Set status, free OS resources (SG DMA buffers)
914 * Do OS callback
916 if (SCpnt->use_sg) {
917 pci_unmap_sg(ioc->pcidev,
918 (struct scatterlist *) SCpnt->request_buffer,
919 SCpnt->use_sg,
920 SCpnt->sc_data_direction);
921 } else if (SCpnt->request_bufflen) {
922 pci_unmap_single(ioc->pcidev,
923 SCpnt->SCp.dma_handle,
924 SCpnt->request_bufflen,
925 SCpnt->sc_data_direction);
927 SCpnt->result = DID_RESET << 16;
928 SCpnt->host_scribble = NULL;
930 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
934 return;
938 * mptscsih_search_running_cmds - Delete any commands associated
939 * with the specified target and lun. Function called only
940 * when a lun is disable by mid-layer.
941 * Do NOT access the referenced scsi_cmnd structure or
942 * members. Will cause either a paging or NULL ptr error.
943 * (BUT, BUT, BUT, the code does reference it! - mdr)
944 * @hd: Pointer to a SCSI HOST structure
945 * @vdevice: per device private data
947 * Returns: None.
949 * Called from slave_destroy.
951 static void
952 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
954 SCSIIORequest_t *mf = NULL;
955 int ii;
956 int max = hd->ioc->req_depth;
957 struct scsi_cmnd *sc;
959 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
960 vdevice->vtarget->target_id, vdevice->lun, max));
962 for (ii=0; ii < max; ii++) {
963 if ((sc = hd->ScsiLookup[ii]) != NULL) {
965 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
966 if (mf == NULL)
967 continue;
968 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
969 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
970 if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
971 continue;
973 /* Cleanup
975 hd->ScsiLookup[ii] = NULL;
976 mptscsih_freeChainBuffers(hd->ioc, ii);
977 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
978 if ((unsigned char *)mf != sc->host_scribble)
979 continue;
980 if (sc->use_sg) {
981 pci_unmap_sg(hd->ioc->pcidev,
982 (struct scatterlist *) sc->request_buffer,
983 sc->use_sg,
984 sc->sc_data_direction);
985 } else if (sc->request_bufflen) {
986 pci_unmap_single(hd->ioc->pcidev,
987 sc->SCp.dma_handle,
988 sc->request_bufflen,
989 sc->sc_data_direction);
991 sc->host_scribble = NULL;
992 sc->result = DID_NO_CONNECT << 16;
993 sc->scsi_done(sc);
996 return;
999 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1001 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1003 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1004 * from a SCSI target device.
1005 * @sc: Pointer to scsi_cmnd structure
1006 * @pScsiReply: Pointer to SCSIIOReply_t
1007 * @pScsiReq: Pointer to original SCSI request
1009 * This routine periodically reports QUEUE_FULL status returned from a
1010 * SCSI target device. It reports this to the console via kernel
1011 * printk() API call, not more than once every 10 seconds.
1013 static void
1014 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1016 long time = jiffies;
1017 MPT_SCSI_HOST *hd;
1019 if (sc->device == NULL)
1020 return;
1021 if (sc->device->host == NULL)
1022 return;
1023 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
1024 return;
1026 if (time - hd->last_queue_full > 10 * HZ) {
1027 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1028 hd->ioc->name, 0, sc->device->id, sc->device->lun));
1029 hd->last_queue_full = time;
1033 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1035 * mptscsih_remove - Removed scsi devices
1036 * @pdev: Pointer to pci_dev structure
1040 void
1041 mptscsih_remove(struct pci_dev *pdev)
1043 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1044 struct Scsi_Host *host = ioc->sh;
1045 MPT_SCSI_HOST *hd;
1046 int sz1;
1048 if(!host) {
1049 mpt_detach(pdev);
1050 return;
1053 scsi_remove_host(host);
1055 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1056 return;
1058 mptscsih_shutdown(pdev);
1060 sz1=0;
1062 if (hd->ScsiLookup != NULL) {
1063 sz1 = hd->ioc->req_depth * sizeof(void *);
1064 kfree(hd->ScsiLookup);
1065 hd->ScsiLookup = NULL;
1069 * Free pointer array.
1071 kfree(hd->Targets);
1072 hd->Targets = NULL;
1074 dprintk((MYIOC_s_INFO_FMT
1075 "Free'd ScsiLookup (%d) memory\n",
1076 hd->ioc->name, sz1));
1078 kfree(hd->info_kbuf);
1080 /* NULL the Scsi_Host pointer
1082 hd->ioc->sh = NULL;
1084 scsi_host_put(host);
1086 mpt_detach(pdev);
1090 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1092 * mptscsih_shutdown - reboot notifier
1095 void
1096 mptscsih_shutdown(struct pci_dev *pdev)
1098 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1099 struct Scsi_Host *host = ioc->sh;
1100 MPT_SCSI_HOST *hd;
1102 if(!host)
1103 return;
1105 hd = (MPT_SCSI_HOST *)host->hostdata;
1109 #ifdef CONFIG_PM
1110 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1112 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1117 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1119 mptscsih_shutdown(pdev);
1120 return mpt_suspend(pdev,state);
1123 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1125 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1130 mptscsih_resume(struct pci_dev *pdev)
1132 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1133 struct Scsi_Host *host = ioc->sh;
1134 MPT_SCSI_HOST *hd;
1136 mpt_resume(pdev);
1138 if(!host)
1139 return 0;
1141 hd = (MPT_SCSI_HOST *)host->hostdata;
1142 if(!hd)
1143 return 0;
1145 return 0;
1148 #endif
1150 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1152 * mptscsih_info - Return information about MPT adapter
1153 * @SChost: Pointer to Scsi_Host structure
1155 * (linux scsi_host_template.info routine)
1157 * Returns pointer to buffer where information was written.
1159 const char *
1160 mptscsih_info(struct Scsi_Host *SChost)
1162 MPT_SCSI_HOST *h;
1163 int size = 0;
1165 h = (MPT_SCSI_HOST *)SChost->hostdata;
1167 if (h) {
1168 if (h->info_kbuf == NULL)
1169 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1170 return h->info_kbuf;
1171 h->info_kbuf[0] = '\0';
1173 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1174 h->info_kbuf[size-1] = '\0';
1177 return h->info_kbuf;
1180 struct info_str {
1181 char *buffer;
1182 int length;
1183 int offset;
1184 int pos;
1187 static void
1188 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1190 if (info->pos + len > info->length)
1191 len = info->length - info->pos;
1193 if (info->pos + len < info->offset) {
1194 info->pos += len;
1195 return;
1198 if (info->pos < info->offset) {
1199 data += (info->offset - info->pos);
1200 len -= (info->offset - info->pos);
1203 if (len > 0) {
1204 memcpy(info->buffer + info->pos, data, len);
1205 info->pos += len;
1209 static int
1210 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1212 va_list args;
1213 char buf[81];
1214 int len;
1216 va_start(args, fmt);
1217 len = vsprintf(buf, fmt, args);
1218 va_end(args);
1220 mptscsih_copy_mem_info(info, buf, len);
1221 return len;
1224 static int
1225 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1227 struct info_str info;
1229 info.buffer = pbuf;
1230 info.length = len;
1231 info.offset = offset;
1232 info.pos = 0;
1234 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1235 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1236 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1237 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1239 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1242 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1244 * mptscsih_proc_info - Return information about MPT adapter
1245 * @host: scsi host struct
1246 * @buffer: if write, user data; if read, buffer for user
1247 * @start: returns the buffer address
1248 * @offset: if write, 0; if read, the current offset into the buffer from
1249 * the previous read.
1250 * @length: if write, return length;
1251 * @func: write = 1; read = 0
1253 * (linux scsi_host_template.info routine)
1256 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1257 int length, int func)
1259 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1260 MPT_ADAPTER *ioc = hd->ioc;
1261 int size = 0;
1263 if (func) {
1265 * write is not supported
1267 } else {
1268 if (start)
1269 *start = buffer;
1271 size = mptscsih_host_info(ioc, buffer, offset, length);
1274 return size;
1277 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1278 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1280 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1282 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1283 * @SCpnt: Pointer to scsi_cmnd structure
1284 * @done: Pointer SCSI mid-layer IO completion function
1286 * (linux scsi_host_template.queuecommand routine)
1287 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1288 * from a linux scsi_cmnd request and send it to the IOC.
1290 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1293 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1295 MPT_SCSI_HOST *hd;
1296 MPT_FRAME_HDR *mf;
1297 SCSIIORequest_t *pScsiReq;
1298 VirtDevice *vdev = SCpnt->device->hostdata;
1299 int lun;
1300 u32 datalen;
1301 u32 scsictl;
1302 u32 scsidir;
1303 u32 cmd_len;
1304 int my_idx;
1305 int ii;
1307 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1308 lun = SCpnt->device->lun;
1309 SCpnt->scsi_done = done;
1311 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1312 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1314 if (hd->resetPending) {
1315 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1316 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1317 return SCSI_MLQUEUE_HOST_BUSY;
1320 if ((hd->ioc->bus_type == SPI) &&
1321 vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT &&
1322 mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) {
1323 SCpnt->result = DID_NO_CONNECT << 16;
1324 done(SCpnt);
1325 return 0;
1329 * Put together a MPT SCSI request...
1331 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1332 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1333 hd->ioc->name));
1334 return SCSI_MLQUEUE_HOST_BUSY;
1337 pScsiReq = (SCSIIORequest_t *) mf;
1339 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1341 ADD_INDEX_LOG(my_idx);
1343 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1344 * Seems we may receive a buffer (datalen>0) even when there
1345 * will be no data transfer! GRRRRR...
1347 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1348 datalen = SCpnt->request_bufflen;
1349 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1350 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1351 datalen = SCpnt->request_bufflen;
1352 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1353 } else {
1354 datalen = 0;
1355 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1358 /* Default to untagged. Once a target structure has been allocated,
1359 * use the Inquiry data to determine if device supports tagged.
1361 if (vdev
1362 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1363 && (SCpnt->device->tagged_supported)) {
1364 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1365 } else {
1366 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1369 /* Use the above information to set up the message frame
1371 pScsiReq->TargetID = (u8) vdev->vtarget->target_id;
1372 pScsiReq->Bus = vdev->vtarget->bus_id;
1373 pScsiReq->ChainOffset = 0;
1374 if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
1375 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1376 else
1377 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1378 pScsiReq->CDBLength = SCpnt->cmd_len;
1379 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1380 pScsiReq->Reserved = 0;
1381 pScsiReq->MsgFlags = mpt_msg_flags();
1382 pScsiReq->LUN[0] = 0;
1383 pScsiReq->LUN[1] = lun;
1384 pScsiReq->LUN[2] = 0;
1385 pScsiReq->LUN[3] = 0;
1386 pScsiReq->LUN[4] = 0;
1387 pScsiReq->LUN[5] = 0;
1388 pScsiReq->LUN[6] = 0;
1389 pScsiReq->LUN[7] = 0;
1390 pScsiReq->Control = cpu_to_le32(scsictl);
1393 * Write SCSI CDB into the message
1395 cmd_len = SCpnt->cmd_len;
1396 for (ii=0; ii < cmd_len; ii++)
1397 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1399 for (ii=cmd_len; ii < 16; ii++)
1400 pScsiReq->CDB[ii] = 0;
1402 /* DataLength */
1403 pScsiReq->DataLength = cpu_to_le32(datalen);
1405 /* SenseBuffer low address */
1406 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1407 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1409 /* Now add the SG list
1410 * Always have a SGE even if null length.
1412 if (datalen == 0) {
1413 /* Add a NULL SGE */
1414 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1415 (dma_addr_t) -1);
1416 } else {
1417 /* Add a 32 or 64 bit SGE */
1418 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1419 goto fail;
1422 SCpnt->host_scribble = (unsigned char *)mf;
1423 hd->ScsiLookup[my_idx] = SCpnt;
1425 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1426 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1427 hd->ioc->name, SCpnt, mf, my_idx));
1428 DBG_DUMP_REQUEST_FRAME(mf)
1429 return 0;
1431 fail:
1432 hd->ScsiLookup[my_idx] = NULL;
1433 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1434 mpt_free_msg_frame(hd->ioc, mf);
1435 return SCSI_MLQUEUE_HOST_BUSY;
1438 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1440 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1441 * with a SCSI IO request
1442 * @hd: Pointer to the MPT_SCSI_HOST instance
1443 * @req_idx: Index of the SCSI IO request frame.
1445 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1446 * No return.
1448 static void
1449 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1451 MPT_FRAME_HDR *chain;
1452 unsigned long flags;
1453 int chain_idx;
1454 int next;
1456 /* Get the first chain index and reset
1457 * tracker state.
1459 chain_idx = ioc->ReqToChain[req_idx];
1460 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1462 while (chain_idx != MPT_HOST_NO_CHAIN) {
1464 /* Save the next chain buffer index */
1465 next = ioc->ChainToChain[chain_idx];
1467 /* Free this chain buffer and reset
1468 * tracker
1470 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1472 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1473 + (chain_idx * ioc->req_sz));
1475 spin_lock_irqsave(&ioc->FreeQlock, flags);
1476 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1477 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1479 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1480 ioc->name, chain_idx));
1482 /* handle next */
1483 chain_idx = next;
1485 return;
1488 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1490 * Reset Handling
1493 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1495 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1496 * Fall through to mpt_HardResetHandler if: not operational, too many
1497 * failed TM requests or handshake failure.
1499 * @ioc: Pointer to MPT_ADAPTER structure
1500 * @type: Task Management type
1501 * @target: Logical Target ID for reset (if appropriate)
1502 * @lun: Logical Unit for reset (if appropriate)
1503 * @ctx2abort: Context for the task to be aborted (if appropriate)
1505 * Remark: Currently invoked from a non-interrupt thread (_bh).
1507 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1508 * will be active.
1510 * Returns 0 for SUCCESS or -1 if FAILED.
1513 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1515 MPT_ADAPTER *ioc;
1516 int rc = -1;
1517 int doTask = 1;
1518 u32 ioc_raw_state;
1519 unsigned long flags;
1521 /* If FW is being reloaded currently, return success to
1522 * the calling function.
1524 if (hd == NULL)
1525 return 0;
1527 ioc = hd->ioc;
1528 if (ioc == NULL) {
1529 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1530 return FAILED;
1532 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1534 // SJR - CHECKME - Can we avoid this here?
1535 // (mpt_HardResetHandler has this check...)
1536 spin_lock_irqsave(&ioc->diagLock, flags);
1537 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1538 spin_unlock_irqrestore(&ioc->diagLock, flags);
1539 return FAILED;
1541 spin_unlock_irqrestore(&ioc->diagLock, flags);
1543 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1544 * If we time out and not bus reset, then we return a FAILED status to the caller.
1545 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1546 * successful. Otherwise, reload the FW.
1548 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1549 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1550 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1551 "Timed out waiting for last TM (%d) to complete! \n",
1552 hd->ioc->name, hd->tmPending));
1553 return FAILED;
1554 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1555 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
1556 "Timed out waiting for last TM (%d) to complete! \n",
1557 hd->ioc->name, hd->tmPending));
1558 return FAILED;
1559 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1560 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1561 "Timed out waiting for last TM (%d) to complete! \n",
1562 hd->ioc->name, hd->tmPending));
1563 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
1564 return FAILED;
1566 doTask = 0;
1568 } else {
1569 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1570 hd->tmPending |= (1 << type);
1571 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1574 /* Is operational?
1576 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1578 #ifdef MPT_DEBUG_RESET
1579 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1580 printk(MYIOC_s_WARN_FMT
1581 "TM Handler: IOC Not operational(0x%x)!\n",
1582 hd->ioc->name, ioc_raw_state);
1584 #endif
1586 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1587 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1589 /* Isse the Task Mgmt request.
1591 if (hd->hard_resets < -1)
1592 hd->hard_resets++;
1593 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
1594 if (rc) {
1595 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
1596 } else {
1597 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
1601 /* Only fall through to the HRH if this is a bus reset
1603 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
1604 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
1605 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1606 hd->ioc->name));
1607 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1611 * Check IOCStatus from TM reply message
1613 if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
1614 rc = FAILED;
1616 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1618 return rc;
1622 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1624 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1625 * @hd: Pointer to MPT_SCSI_HOST structure
1626 * @type: Task Management type
1627 * @target: Logical Target ID for reset (if appropriate)
1628 * @lun: Logical Unit for reset (if appropriate)
1629 * @ctx2abort: Context for the task to be aborted (if appropriate)
1631 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1632 * or a non-interrupt thread. In the former, must not call schedule().
1634 * Not all fields are meaningfull for all task types.
1636 * Returns 0 for SUCCESS, -999 for "no msg frames",
1637 * else other non-zero value returned.
1639 static int
1640 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1642 MPT_FRAME_HDR *mf;
1643 SCSITaskMgmt_t *pScsiTm;
1644 int ii;
1645 int retval;
1647 /* Return Fail to calling function if no message frames available.
1649 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1650 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1651 hd->ioc->name));
1652 return FAILED;
1654 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1655 hd->ioc->name, mf));
1657 /* Format the Request
1659 pScsiTm = (SCSITaskMgmt_t *) mf;
1660 pScsiTm->TargetID = target;
1661 pScsiTm->Bus = channel;
1662 pScsiTm->ChainOffset = 0;
1663 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1665 pScsiTm->Reserved = 0;
1666 pScsiTm->TaskType = type;
1667 pScsiTm->Reserved1 = 0;
1668 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1669 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1671 for (ii= 0; ii < 8; ii++) {
1672 pScsiTm->LUN[ii] = 0;
1674 pScsiTm->LUN[1] = lun;
1676 for (ii=0; ii < 7; ii++)
1677 pScsiTm->Reserved2[ii] = 0;
1679 pScsiTm->TaskMsgContext = ctx2abort;
1681 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1682 hd->ioc->name, ctx2abort, type));
1684 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1686 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1687 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
1688 CAN_SLEEP)) != 0) {
1689 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
1690 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1691 hd->ioc, mf));
1692 mpt_free_msg_frame(hd->ioc, mf);
1693 return retval;
1696 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1697 dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
1698 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1699 hd->ioc, mf));
1700 mpt_free_msg_frame(hd->ioc, mf);
1701 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1702 hd->ioc->name));
1703 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1706 return retval;
1709 static int
1710 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1712 switch (ioc->bus_type) {
1713 case FC:
1714 return 40;
1715 case SAS:
1716 return 10;
1717 case SPI:
1718 default:
1719 return 2;
1723 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1725 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1726 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1728 * (linux scsi_host_template.eh_abort_handler routine)
1730 * Returns SUCCESS or FAILED.
1733 mptscsih_abort(struct scsi_cmnd * SCpnt)
1735 MPT_SCSI_HOST *hd;
1736 MPT_FRAME_HDR *mf;
1737 u32 ctx2abort;
1738 int scpnt_idx;
1739 int retval;
1740 VirtDevice *vdev;
1741 ulong sn = SCpnt->serial_number;
1743 /* If we can't locate our host adapter structure, return FAILED status.
1745 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1746 SCpnt->result = DID_RESET << 16;
1747 SCpnt->scsi_done(SCpnt);
1748 dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1749 "Can't locate host! (sc=%p)\n",
1750 SCpnt));
1751 return FAILED;
1754 /* Find this command
1756 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1757 /* Cmd not found in ScsiLookup.
1758 * Do OS callback.
1760 SCpnt->result = DID_RESET << 16;
1761 dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1762 "Command not in the active list! (sc=%p)\n",
1763 hd->ioc->name, SCpnt));
1764 return SUCCESS;
1767 if (hd->resetPending) {
1768 return FAILED;
1771 if (hd->timeouts < -1)
1772 hd->timeouts++;
1774 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1775 hd->ioc->name, SCpnt);
1776 scsi_print_command(SCpnt);
1778 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1779 * (the IO to be ABORT'd)
1781 * NOTE: Since we do not byteswap MsgContext, we do not
1782 * swap it here either. It is an opaque cookie to
1783 * the controller, so it does not matter. -DaveM
1785 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1786 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1788 hd->abortSCpnt = SCpnt;
1790 vdev = SCpnt->device->hostdata;
1791 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1792 vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
1793 ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1795 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1796 SCpnt->serial_number == sn) {
1797 retval = FAILED;
1800 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1801 hd->ioc->name,
1802 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1804 if (retval == 0)
1805 return SUCCESS;
1807 if(retval != FAILED ) {
1808 hd->tmPending = 0;
1809 hd->tmState = TM_STATE_NONE;
1811 return FAILED;
1814 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1816 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1817 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1819 * (linux scsi_host_template.eh_dev_reset_handler routine)
1821 * Returns SUCCESS or FAILED.
1824 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1826 MPT_SCSI_HOST *hd;
1827 int retval;
1828 VirtDevice *vdev;
1830 /* If we can't locate our host adapter structure, return FAILED status.
1832 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1833 dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1834 "Can't locate host! (sc=%p)\n",
1835 SCpnt));
1836 return FAILED;
1839 if (hd->resetPending)
1840 return FAILED;
1842 printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1843 hd->ioc->name, SCpnt);
1844 scsi_print_command(SCpnt);
1846 vdev = SCpnt->device->hostdata;
1847 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1848 vdev->vtarget->bus_id, vdev->vtarget->target_id,
1849 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1851 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1852 hd->ioc->name,
1853 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1855 if (retval == 0)
1856 return SUCCESS;
1858 if(retval != FAILED ) {
1859 hd->tmPending = 0;
1860 hd->tmState = TM_STATE_NONE;
1862 return FAILED;
1865 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1867 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1868 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1870 * (linux scsi_host_template.eh_bus_reset_handler routine)
1872 * Returns SUCCESS or FAILED.
1875 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1877 MPT_SCSI_HOST *hd;
1878 int retval;
1879 VirtDevice *vdev;
1881 /* If we can't locate our host adapter structure, return FAILED status.
1883 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1884 dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1885 "Can't locate host! (sc=%p)\n",
1886 SCpnt ) );
1887 return FAILED;
1890 printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1891 hd->ioc->name, SCpnt);
1892 scsi_print_command(SCpnt);
1894 if (hd->timeouts < -1)
1895 hd->timeouts++;
1897 vdev = SCpnt->device->hostdata;
1898 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1899 vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1901 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1902 hd->ioc->name,
1903 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1905 if (retval == 0)
1906 return SUCCESS;
1908 if(retval != FAILED ) {
1909 hd->tmPending = 0;
1910 hd->tmState = TM_STATE_NONE;
1912 return FAILED;
1915 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1917 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1918 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1920 * (linux scsi_host_template.eh_host_reset_handler routine)
1922 * Returns SUCCESS or FAILED.
1925 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1927 MPT_SCSI_HOST * hd;
1928 int status = SUCCESS;
1930 /* If we can't locate the host to reset, then we failed. */
1931 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1932 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1933 "Can't locate host! (sc=%p)\n",
1934 SCpnt ) );
1935 return FAILED;
1938 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1939 hd->ioc->name, SCpnt);
1941 /* If our attempts to reset the host failed, then return a failed
1942 * status. The host will be taken off line by the SCSI mid-layer.
1944 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1945 status = FAILED;
1946 } else {
1947 /* Make sure TM pending is cleared and TM state is set to
1948 * NONE.
1950 hd->tmPending = 0;
1951 hd->tmState = TM_STATE_NONE;
1954 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1955 "Status = %s\n",
1956 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1958 return status;
1961 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1963 * mptscsih_tm_pending_wait - wait for pending task management request to complete
1964 * @hd: Pointer to MPT host structure.
1966 * Returns {SUCCESS,FAILED}.
1968 static int
1969 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1971 unsigned long flags;
1972 int loop_count = 4 * 10; /* Wait 10 seconds */
1973 int status = FAILED;
1975 do {
1976 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1977 if (hd->tmState == TM_STATE_NONE) {
1978 hd->tmState = TM_STATE_IN_PROGRESS;
1979 hd->tmPending = 1;
1980 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1981 status = SUCCESS;
1982 break;
1984 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1985 msleep(250);
1986 } while (--loop_count);
1988 return status;
1991 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1993 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1994 * @hd: Pointer to MPT host structure.
1995 * @timeout: timeout in seconds
1997 * Returns {SUCCESS,FAILED}.
1999 static int
2000 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2002 unsigned long flags;
2003 int loop_count = 4 * timeout;
2004 int status = FAILED;
2006 do {
2007 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2008 if(hd->tmPending == 0) {
2009 status = SUCCESS;
2010 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2011 break;
2013 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2014 msleep(250);
2015 } while (--loop_count);
2017 return status;
2020 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2021 static void
2022 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2024 char *desc;
2026 switch (response_code) {
2027 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2028 desc = "The task completed.";
2029 break;
2030 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2031 desc = "The IOC received an invalid frame status.";
2032 break;
2033 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2034 desc = "The task type is not supported.";
2035 break;
2036 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2037 desc = "The requested task failed.";
2038 break;
2039 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2040 desc = "The task completed successfully.";
2041 break;
2042 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2043 desc = "The LUN request is invalid.";
2044 break;
2045 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2046 desc = "The task is in the IOC queue and has not been sent to target.";
2047 break;
2048 default:
2049 desc = "unknown";
2050 break;
2052 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2053 ioc->name, response_code, desc);
2056 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2058 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2059 * @ioc: Pointer to MPT_ADAPTER structure
2060 * @mf: Pointer to SCSI task mgmt request frame
2061 * @mr: Pointer to SCSI task mgmt reply frame
2063 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2064 * of any SCSI task management request.
2065 * This routine is registered with the MPT (base) driver at driver
2066 * load/init time via the mpt_register() API call.
2068 * Returns 1 indicating alloc'd request frame ptr should be freed.
2071 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2073 SCSITaskMgmtReply_t *pScsiTmReply;
2074 SCSITaskMgmt_t *pScsiTmReq;
2075 MPT_SCSI_HOST *hd;
2076 unsigned long flags;
2077 u16 iocstatus;
2078 u8 tmType;
2080 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2081 ioc->name, mf, mr));
2082 if (ioc->sh) {
2083 /* Depending on the thread, a timer is activated for
2084 * the TM request. Delete this timer on completion of TM.
2085 * Decrement count of outstanding TM requests.
2087 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2088 } else {
2089 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
2090 ioc->name));
2091 return 1;
2094 if (mr == NULL) {
2095 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
2096 ioc->name, mf));
2097 return 1;
2098 } else {
2099 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2100 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2102 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2103 tmType = pScsiTmReq->TaskType;
2105 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2106 pScsiTmReply->ResponseCode)
2107 mptscsih_taskmgmt_response_code(ioc,
2108 pScsiTmReply->ResponseCode);
2110 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
2111 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2112 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2114 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2115 hd->tm_iocstatus = iocstatus;
2116 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2117 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2118 /* Error? (anything non-zero?) */
2119 if (iocstatus) {
2121 /* clear flags and continue.
2123 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2124 hd->abortSCpnt = NULL;
2126 /* If an internal command is present
2127 * or the TM failed - reload the FW.
2128 * FC FW may respond FAILED to an ABORT
2130 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2131 if ((hd->cmdPtr) ||
2132 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
2133 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2134 printk((KERN_WARNING
2135 " Firmware Reload FAILED!!\n"));
2139 } else {
2140 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2142 hd->abortSCpnt = NULL;
2147 spin_lock_irqsave(&ioc->FreeQlock, flags);
2148 hd->tmPending = 0;
2149 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2150 hd->tmState = TM_STATE_NONE;
2152 return 1;
2155 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2157 * This is anyones guess quite frankly.
2160 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2161 sector_t capacity, int geom[])
2163 int heads;
2164 int sectors;
2165 sector_t cylinders;
2166 ulong dummy;
2168 heads = 64;
2169 sectors = 32;
2171 dummy = heads * sectors;
2172 cylinders = capacity;
2173 sector_div(cylinders,dummy);
2176 * Handle extended translation size for logical drives
2177 * > 1Gb
2179 if ((ulong)capacity >= 0x200000) {
2180 heads = 255;
2181 sectors = 63;
2182 dummy = heads * sectors;
2183 cylinders = capacity;
2184 sector_div(cylinders,dummy);
2187 /* return result */
2188 geom[0] = heads;
2189 geom[1] = sectors;
2190 geom[2] = cylinders;
2192 dprintk((KERN_NOTICE
2193 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2194 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
2196 return 0;
2199 /* Search IOC page 3 to determine if this is hidden physical disk
2203 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
2205 int i;
2207 if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
2208 return 0;
2209 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2210 if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
2211 return 1;
2213 return 0;
2215 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2218 mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid)
2220 int i;
2222 if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3)
2223 return -ENXIO;
2225 for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2226 if (physdiskid ==
2227 hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
2228 return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2231 return -ENXIO;
2233 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2235 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2237 * OS entry point to allow host driver to alloc memory
2238 * for each scsi target. Called once per device the bus scan.
2239 * Return non-zero if allocation fails.
2242 mptscsih_target_alloc(struct scsi_target *starget)
2244 VirtTarget *vtarget;
2246 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
2247 if (!vtarget)
2248 return -ENOMEM;
2249 starget->hostdata = vtarget;
2250 vtarget->starget = starget;
2251 return 0;
2254 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2256 * OS entry point to allow host driver to alloc memory
2257 * for each scsi device. Called once per device the bus scan.
2258 * Return non-zero if allocation fails.
2261 mptscsih_slave_alloc(struct scsi_device *sdev)
2263 struct Scsi_Host *host = sdev->host;
2264 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2265 VirtTarget *vtarget;
2266 VirtDevice *vdev;
2267 struct scsi_target *starget;
2269 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
2270 if (!vdev) {
2271 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
2272 hd->ioc->name, sizeof(VirtDevice));
2273 return -ENOMEM;
2276 vdev->lun = sdev->lun;
2277 sdev->hostdata = vdev;
2279 starget = scsi_target(sdev);
2280 vtarget = starget->hostdata;
2282 vdev->vtarget = vtarget;
2284 if (vtarget->num_luns == 0) {
2285 hd->Targets[sdev->id] = vtarget;
2286 vtarget->ioc_id = hd->ioc->id;
2287 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
2288 vtarget->target_id = sdev->id;
2289 vtarget->bus_id = sdev->channel;
2290 if (hd->ioc->bus_type == SPI && sdev->channel == 0 &&
2291 hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
2292 vtarget->raidVolume = 1;
2293 ddvtprintk((KERN_INFO
2294 "RAID Volume @ id %d\n", sdev->id));
2297 vtarget->num_luns++;
2298 return 0;
2302 * OS entry point to allow for host driver to free allocated memory
2303 * Called if no device present or device being unloaded
2305 void
2306 mptscsih_target_destroy(struct scsi_target *starget)
2308 if (starget->hostdata)
2309 kfree(starget->hostdata);
2310 starget->hostdata = NULL;
2314 * OS entry point to allow for host driver to free allocated memory
2315 * Called if no device present or device being unloaded
2317 void
2318 mptscsih_slave_destroy(struct scsi_device *sdev)
2320 struct Scsi_Host *host = sdev->host;
2321 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2322 VirtTarget *vtarget;
2323 VirtDevice *vdevice;
2324 struct scsi_target *starget;
2326 starget = scsi_target(sdev);
2327 vtarget = starget->hostdata;
2328 vdevice = sdev->hostdata;
2330 mptscsih_search_running_cmds(hd, vdevice);
2331 vtarget->luns[0] &= ~(1 << vdevice->lun);
2332 vtarget->num_luns--;
2333 if (vtarget->num_luns == 0) {
2334 hd->Targets[sdev->id] = NULL;
2336 mptscsih_synchronize_cache(hd, vdevice);
2337 kfree(vdevice);
2338 sdev->hostdata = NULL;
2341 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2343 * mptscsih_change_queue_depth - This function will set a devices queue depth
2344 * @sdev: per scsi_device pointer
2345 * @qdepth: requested queue depth
2347 * Adding support for new 'change_queue_depth' api.
2350 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2352 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2353 VirtTarget *vtarget;
2354 struct scsi_target *starget;
2355 int max_depth;
2356 int tagged;
2358 starget = scsi_target(sdev);
2359 vtarget = starget->hostdata;
2361 if (hd->ioc->bus_type == SPI) {
2362 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2363 max_depth = 1;
2364 else if (sdev->type == TYPE_DISK &&
2365 vtarget->minSyncFactor <= MPT_ULTRA160)
2366 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2367 else
2368 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2369 } else
2370 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2372 if (qdepth > max_depth)
2373 qdepth = max_depth;
2374 if (qdepth == 1)
2375 tagged = 0;
2376 else
2377 tagged = MSG_SIMPLE_TAG;
2379 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2380 return sdev->queue_depth;
2384 * OS entry point to adjust the queue_depths on a per-device basis.
2385 * Called once per device the bus scan. Use it to force the queue_depth
2386 * member to 1 if a device does not support Q tags.
2387 * Return non-zero if fails.
2390 mptscsih_slave_configure(struct scsi_device *sdev)
2392 struct Scsi_Host *sh = sdev->host;
2393 VirtTarget *vtarget;
2394 VirtDevice *vdevice;
2395 struct scsi_target *starget;
2396 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2397 int indexed_lun, lun_index;
2399 starget = scsi_target(sdev);
2400 vtarget = starget->hostdata;
2401 vdevice = sdev->hostdata;
2403 dsprintk((MYIOC_s_INFO_FMT
2404 "device @ %p, id=%d, LUN=%d, channel=%d\n",
2405 hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
2406 if (hd->ioc->bus_type == SPI)
2407 dsprintk((MYIOC_s_INFO_FMT
2408 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2409 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2410 sdev->ppr, sdev->inquiry_len));
2412 if (sdev->id > sh->max_id) {
2413 /* error case, should never happen */
2414 scsi_adjust_queue_depth(sdev, 0, 1);
2415 goto slave_configure_exit;
2418 vdevice->configured_lun=1;
2419 lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */
2420 indexed_lun = (vdevice->lun % 32);
2421 vtarget->luns[lun_index] |= (1 << indexed_lun);
2422 mptscsih_initTarget(hd, vtarget, sdev);
2423 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2425 dsprintk((MYIOC_s_INFO_FMT
2426 "Queue depth=%d, tflags=%x\n",
2427 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2429 if (hd->ioc->bus_type == SPI)
2430 dsprintk((MYIOC_s_INFO_FMT
2431 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2432 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2433 vtarget->minSyncFactor));
2435 slave_configure_exit:
2437 dsprintk((MYIOC_s_INFO_FMT
2438 "tagged %d, simple %d, ordered %d\n",
2439 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2440 sdev->ordered_tags));
2442 return 0;
2445 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2447 * Private routines...
2450 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2451 /* Utility function to copy sense data from the scsi_cmnd buffer
2452 * to the FC and SCSI target structures.
2455 static void
2456 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2458 VirtDevice *vdev;
2459 SCSIIORequest_t *pReq;
2460 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2462 /* Get target structure
2464 pReq = (SCSIIORequest_t *) mf;
2465 vdev = sc->device->hostdata;
2467 if (sense_count) {
2468 u8 *sense_data;
2469 int req_index;
2471 /* Copy the sense received into the scsi command block. */
2472 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2473 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2474 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2476 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2478 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2479 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2480 int idx;
2481 MPT_ADAPTER *ioc = hd->ioc;
2483 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2484 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2485 ioc->events[idx].eventContext = ioc->eventContext;
2487 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2488 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2489 (sc->device->channel << 8) || sc->device->id;
2491 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2493 ioc->eventContext++;
2494 if (hd->ioc->pcidev->vendor ==
2495 PCI_VENDOR_ID_IBM) {
2496 mptscsih_issue_sep_command(hd->ioc,
2497 vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2498 vdev->vtarget->tflags |=
2499 MPT_TARGET_FLAGS_LED_ON;
2503 } else {
2504 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2505 hd->ioc->name));
2509 static int
2510 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2512 MPT_SCSI_HOST *hd;
2513 int i;
2515 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2517 for (i = 0; i < hd->ioc->req_depth; i++) {
2518 if (hd->ScsiLookup[i] == sc) {
2519 return i;
2523 return -1;
2526 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2528 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2530 MPT_SCSI_HOST *hd;
2531 unsigned long flags;
2532 int ii;
2534 dtmprintk((KERN_WARNING MYNAM
2535 ": IOC %s_reset routed to SCSI host driver!\n",
2536 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2537 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2539 /* If a FW reload request arrives after base installed but
2540 * before all scsi hosts have been attached, then an alt_ioc
2541 * may have a NULL sh pointer.
2543 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2544 return 0;
2545 else
2546 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2548 if (reset_phase == MPT_IOC_SETUP_RESET) {
2549 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2551 /* Clean Up:
2552 * 1. Set Hard Reset Pending Flag
2553 * All new commands go to doneQ
2555 hd->resetPending = 1;
2557 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2558 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2560 /* 2. Flush running commands
2561 * Clean ScsiLookup (and associated memory)
2562 * AND clean mytaskQ
2565 /* 2b. Reply to OS all known outstanding I/O commands.
2567 mptscsih_flush_running_cmds(hd);
2569 /* 2c. If there was an internal command that
2570 * has not completed, configuration or io request,
2571 * free these resources.
2573 if (hd->cmdPtr) {
2574 del_timer(&hd->timer);
2575 mpt_free_msg_frame(ioc, hd->cmdPtr);
2578 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2580 } else {
2581 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2583 /* Once a FW reload begins, all new OS commands are
2584 * redirected to the doneQ w/ a reset status.
2585 * Init all control structures.
2588 /* ScsiLookup initialization
2590 for (ii=0; ii < hd->ioc->req_depth; ii++)
2591 hd->ScsiLookup[ii] = NULL;
2593 /* 2. Chain Buffer initialization
2596 /* 4. Renegotiate to all devices, if SPI
2599 /* 5. Enable new commands to be posted
2601 spin_lock_irqsave(&ioc->FreeQlock, flags);
2602 hd->tmPending = 0;
2603 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2604 hd->resetPending = 0;
2605 hd->tmState = TM_STATE_NONE;
2607 /* 6. If there was an internal command,
2608 * wake this process up.
2610 if (hd->cmdPtr) {
2612 * Wake up the original calling thread
2614 hd->pLocal = &hd->localReply;
2615 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2616 hd->scandv_wait_done = 1;
2617 wake_up(&hd->scandv_waitq);
2618 hd->cmdPtr = NULL;
2621 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2625 return 1; /* currently means nothing really */
2628 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2630 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2632 MPT_SCSI_HOST *hd;
2633 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2635 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2636 ioc->name, event));
2638 if (ioc->sh == NULL ||
2639 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2640 return 1;
2642 switch (event) {
2643 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2644 /* FIXME! */
2645 break;
2646 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2647 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2648 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2649 hd->soft_resets++;
2650 break;
2651 case MPI_EVENT_LOGOUT: /* 09 */
2652 /* FIXME! */
2653 break;
2655 case MPI_EVENT_RESCAN: /* 06 */
2656 break;
2659 * CHECKME! Don't think we need to do
2660 * anything for these, but...
2662 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2663 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2665 * CHECKME! Falling thru...
2667 break;
2669 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2670 break;
2672 case MPI_EVENT_NONE: /* 00 */
2673 case MPI_EVENT_LOG_DATA: /* 01 */
2674 case MPI_EVENT_STATE_CHANGE: /* 02 */
2675 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2676 default:
2677 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2678 break;
2681 return 1; /* currently means nothing really */
2684 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2686 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2687 * @hd: Pointer to MPT_SCSI_HOST structure
2688 * @vtarget: per target private data
2689 * @sdev: SCSI device
2691 * NOTE: It's only SAFE to call this routine if data points to
2692 * sane & valid STANDARD INQUIRY data!
2694 * Allocate and initialize memory for this target.
2695 * Save inquiry data.
2698 static void
2699 mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
2700 struct scsi_device *sdev)
2702 dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
2703 hd->ioc->name, vtarget->bus_id, vtarget->target_id,
2704 sdev->lun, hd));
2706 /* Is LUN supported? If so, upper 2 bits will be 0
2707 * in first byte of inquiry data.
2709 if (sdev->inq_periph_qual != 0)
2710 return;
2712 if (vtarget == NULL)
2713 return;
2715 vtarget->type = sdev->type;
2717 if (hd->ioc->bus_type != SPI)
2718 return;
2720 if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
2721 /* Treat all Processors as SAF-TE if
2722 * command line option is set */
2723 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2724 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
2725 }else if ((sdev->type == TYPE_PROCESSOR) &&
2726 !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
2727 if (sdev->inquiry_len > 49 ) {
2728 if (sdev->inquiry[44] == 'S' &&
2729 sdev->inquiry[45] == 'A' &&
2730 sdev->inquiry[46] == 'F' &&
2731 sdev->inquiry[47] == '-' &&
2732 sdev->inquiry[48] == 'T' &&
2733 sdev->inquiry[49] == 'E' ) {
2734 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2735 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
2739 mptscsih_setTargetNegoParms(hd, vtarget, sdev);
2742 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2744 * Update the target negotiation parameters based on the
2745 * the Inquiry data, adapter capabilities, and NVRAM settings.
2748 static void
2749 mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
2750 struct scsi_device *sdev)
2752 SpiCfgData *pspi_data = &hd->ioc->spi_data;
2753 int id = (int) target->target_id;
2754 int nvram;
2755 u8 width = MPT_NARROW;
2756 u8 factor = MPT_ASYNC;
2757 u8 offset = 0;
2758 u8 nfactor;
2759 u8 noQas = 1;
2761 target->negoFlags = pspi_data->noQas;
2763 /* noQas == 0 => device supports QAS. */
2765 if (sdev->scsi_level < SCSI_2) {
2766 width = 0;
2767 factor = MPT_ULTRA2;
2768 offset = pspi_data->maxSyncOffset;
2769 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2770 } else {
2771 if (scsi_device_wide(sdev)) {
2772 width = 1;
2775 if (scsi_device_sync(sdev)) {
2776 factor = pspi_data->minSyncFactor;
2777 if (!scsi_device_dt(sdev))
2778 factor = MPT_ULTRA2;
2779 else {
2780 if (!scsi_device_ius(sdev) &&
2781 !scsi_device_qas(sdev))
2782 factor = MPT_ULTRA160;
2783 else {
2784 factor = MPT_ULTRA320;
2785 if (scsi_device_qas(sdev)) {
2786 ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
2787 noQas = 0;
2789 if (sdev->type == TYPE_TAPE &&
2790 scsi_device_ius(sdev))
2791 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2794 offset = pspi_data->maxSyncOffset;
2796 /* If RAID, never disable QAS
2797 * else if non RAID, do not disable
2798 * QAS if bit 1 is set
2799 * bit 1 QAS support, non-raid only
2800 * bit 0 IU support
2802 if (target->raidVolume == 1) {
2803 noQas = 0;
2805 } else {
2806 factor = MPT_ASYNC;
2807 offset = 0;
2811 if (!sdev->tagged_supported) {
2812 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2815 /* Update tflags based on NVRAM settings. (SCSI only)
2817 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2818 nvram = pspi_data->nvram[id];
2819 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2821 if (width)
2822 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2824 if (offset > 0) {
2825 /* Ensure factor is set to the
2826 * maximum of: adapter, nvram, inquiry
2828 if (nfactor) {
2829 if (nfactor < pspi_data->minSyncFactor )
2830 nfactor = pspi_data->minSyncFactor;
2832 factor = max(factor, nfactor);
2833 if (factor == MPT_ASYNC)
2834 offset = 0;
2835 } else {
2836 offset = 0;
2837 factor = MPT_ASYNC;
2839 } else {
2840 factor = MPT_ASYNC;
2844 /* Make sure data is consistent
2846 if ((!width) && (factor < MPT_ULTRA2)) {
2847 factor = MPT_ULTRA2;
2850 /* Save the data to the target structure.
2852 target->minSyncFactor = factor;
2853 target->maxOffset = offset;
2854 target->maxWidth = width;
2856 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2858 /* Disable unused features.
2860 if (!width)
2861 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2863 if (!offset)
2864 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2866 if ( factor > MPT_ULTRA320 )
2867 noQas = 0;
2869 if (noQas && (pspi_data->noQas == 0)) {
2870 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2871 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2873 /* Disable QAS in a mixed configuration case
2876 ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
2880 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2882 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2884 * SCSI Config Page functionality ...
2887 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2888 /* mptscsih_writeIOCPage4 - write IOC Page 4
2889 * @hd: Pointer to a SCSI Host Structure
2890 * @target_id: write IOC Page4 for this ID & Bus
2892 * Return: -EAGAIN if unable to obtain a Message Frame
2893 * or 0 if success.
2895 * Remark: We do not wait for a return, write pages sequentially.
2897 static int
2898 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
2900 MPT_ADAPTER *ioc = hd->ioc;
2901 Config_t *pReq;
2902 IOCPage4_t *IOCPage4Ptr;
2903 MPT_FRAME_HDR *mf;
2904 dma_addr_t dataDma;
2905 u16 req_idx;
2906 u32 frameOffset;
2907 u32 flagsLength;
2908 int ii;
2910 /* Get a MF for this command.
2912 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
2913 dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
2914 ioc->name));
2915 return -EAGAIN;
2918 /* Set the request and the data pointers.
2919 * Place data at end of MF.
2921 pReq = (Config_t *)mf;
2923 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2924 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
2926 /* Complete the request frame (same for all requests).
2928 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2929 pReq->Reserved = 0;
2930 pReq->ChainOffset = 0;
2931 pReq->Function = MPI_FUNCTION_CONFIG;
2932 pReq->ExtPageLength = 0;
2933 pReq->ExtPageType = 0;
2934 pReq->MsgFlags = 0;
2935 for (ii=0; ii < 8; ii++) {
2936 pReq->Reserved2[ii] = 0;
2939 IOCPage4Ptr = ioc->spi_data.pIocPg4;
2940 dataDma = ioc->spi_data.IocPg4_dma;
2941 ii = IOCPage4Ptr->ActiveSEP++;
2942 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
2943 IOCPage4Ptr->SEP[ii].SEPBus = bus;
2944 pReq->Header = IOCPage4Ptr->Header;
2945 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
2947 /* Add a SGE to the config request.
2949 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
2950 (IOCPage4Ptr->Header.PageLength + ii) * 4;
2952 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
2954 dinitprintk((MYIOC_s_INFO_FMT
2955 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
2956 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
2958 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
2960 return 0;
2963 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2965 * Bus Scan and Domain Validation functionality ...
2968 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2970 * mptscsih_scandv_complete - Scan and DV callback routine registered
2971 * to Fustion MPT (base) driver.
2973 * @ioc: Pointer to MPT_ADAPTER structure
2974 * @mf: Pointer to original MPT request frame
2975 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2977 * This routine is called from mpt.c::mpt_interrupt() at the completion
2978 * of any SCSI IO request.
2979 * This routine is registered with the Fusion MPT (base) driver at driver
2980 * load/init time via the mpt_register() API call.
2982 * Returns 1 indicating alloc'd request frame ptr should be freed.
2984 * Remark: Sets a completion code and (possibly) saves sense data
2985 * in the IOC member localReply structure.
2986 * Used ONLY for DV and other internal commands.
2989 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2991 MPT_SCSI_HOST *hd;
2992 SCSIIORequest_t *pReq;
2993 int completionCode;
2994 u16 req_idx;
2996 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2998 if ((mf == NULL) ||
2999 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
3000 printk(MYIOC_s_ERR_FMT
3001 "ScanDvComplete, %s req frame ptr! (=%p)\n",
3002 ioc->name, mf?"BAD":"NULL", (void *) mf);
3003 goto wakeup;
3006 del_timer(&hd->timer);
3007 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3008 hd->ScsiLookup[req_idx] = NULL;
3009 pReq = (SCSIIORequest_t *) mf;
3011 if (mf != hd->cmdPtr) {
3012 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3013 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
3015 hd->cmdPtr = NULL;
3017 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3018 hd->ioc->name, mf, mr, req_idx));
3020 hd->pLocal = &hd->localReply;
3021 hd->pLocal->scsiStatus = 0;
3023 /* If target struct exists, clear sense valid flag.
3025 if (mr == NULL) {
3026 completionCode = MPT_SCANDV_GOOD;
3027 } else {
3028 SCSIIOReply_t *pReply;
3029 u16 status;
3030 u8 scsi_status;
3032 pReply = (SCSIIOReply_t *) mr;
3034 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3035 scsi_status = pReply->SCSIStatus;
3037 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3038 status, pReply->SCSIState, scsi_status,
3039 le32_to_cpu(pReply->IOCLogInfo)));
3041 switch(status) {
3043 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
3044 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3045 break;
3047 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
3048 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
3049 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
3050 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
3051 completionCode = MPT_SCANDV_DID_RESET;
3052 break;
3054 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
3055 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
3056 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
3057 if (pReply->Function == MPI_FUNCTION_CONFIG) {
3058 ConfigReply_t *pr = (ConfigReply_t *)mr;
3059 completionCode = MPT_SCANDV_GOOD;
3060 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
3061 hd->pLocal->header.PageLength = pr->Header.PageLength;
3062 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
3063 hd->pLocal->header.PageType = pr->Header.PageType;
3065 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
3066 /* If the RAID Volume request is successful,
3067 * return GOOD, else indicate that
3068 * some type of error occurred.
3070 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
3071 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
3072 completionCode = MPT_SCANDV_GOOD;
3073 else
3074 completionCode = MPT_SCANDV_SOME_ERROR;
3075 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
3077 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3078 u8 *sense_data;
3079 int sz;
3081 /* save sense data in global structure
3083 completionCode = MPT_SCANDV_SENSE;
3084 hd->pLocal->scsiStatus = scsi_status;
3085 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
3086 (req_idx * MPT_SENSE_BUFFER_ALLOC));
3088 sz = min_t(int, pReq->SenseBufferLength,
3089 SCSI_STD_SENSE_BYTES);
3090 memcpy(hd->pLocal->sense, sense_data, sz);
3092 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
3093 sense_data));
3094 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
3095 if (pReq->CDB[0] == INQUIRY)
3096 completionCode = MPT_SCANDV_ISSUE_SENSE;
3097 else
3098 completionCode = MPT_SCANDV_DID_RESET;
3100 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
3101 completionCode = MPT_SCANDV_DID_RESET;
3102 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3103 completionCode = MPT_SCANDV_DID_RESET;
3104 else {
3105 completionCode = MPT_SCANDV_GOOD;
3106 hd->pLocal->scsiStatus = scsi_status;
3108 break;
3110 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
3111 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3112 completionCode = MPT_SCANDV_DID_RESET;
3113 else
3114 completionCode = MPT_SCANDV_SOME_ERROR;
3115 break;
3117 default:
3118 completionCode = MPT_SCANDV_SOME_ERROR;
3119 break;
3121 } /* switch(status) */
3123 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
3124 completionCode));
3125 } /* end of address reply case */
3127 hd->pLocal->completion = completionCode;
3129 /* MF and RF are freed in mpt_interrupt
3131 wakeup:
3132 /* Free Chain buffers (will never chain) in scan or dv */
3133 //mptscsih_freeChainBuffers(ioc, req_idx);
3136 * Wake up the original calling thread
3138 hd->scandv_wait_done = 1;
3139 wake_up(&hd->scandv_waitq);
3141 return 1;
3144 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3145 /* mptscsih_timer_expired - Call back for timer process.
3146 * Used only for dv functionality.
3147 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3150 void
3151 mptscsih_timer_expired(unsigned long data)
3153 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3155 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3157 if (hd->cmdPtr) {
3158 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3160 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3161 /* Desire to issue a task management request here.
3162 * TM requests MUST be single threaded.
3163 * If old eh code and no TM current, issue request.
3164 * If new eh code, do nothing. Wait for OS cmd timeout
3165 * for bus reset.
3167 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3168 } else {
3169 /* Perform a FW reload */
3170 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3171 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3174 } else {
3175 /* This should NEVER happen */
3176 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3179 /* No more processing.
3180 * TM call will generate an interrupt for SCSI TM Management.
3181 * The FW will reply to all outstanding commands, callback will finish cleanup.
3182 * Hard reset clean-up will free all resources.
3184 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3186 return;
3190 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3192 * mptscsih_do_cmd - Do internal command.
3193 * @hd: MPT_SCSI_HOST pointer
3194 * @io: INTERNAL_CMD pointer.
3196 * Issue the specified internally generated command and do command
3197 * specific cleanup. For bus scan / DV only.
3198 * NOTES: If command is Inquiry and status is good,
3199 * initialize a target structure, save the data
3201 * Remark: Single threaded access only.
3203 * Return:
3204 * < 0 if an illegal command or no resources
3206 * 0 if good
3208 * > 0 if command complete but some type of completion error.
3210 static int
3211 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3213 MPT_FRAME_HDR *mf;
3214 SCSIIORequest_t *pScsiReq;
3215 SCSIIORequest_t ReqCopy;
3216 int my_idx, ii, dir;
3217 int rc, cmdTimeout;
3218 int in_isr;
3219 char cmdLen;
3220 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3221 char cmd = io->cmd;
3223 in_isr = in_interrupt();
3224 if (in_isr) {
3225 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3226 hd->ioc->name));
3227 return -EPERM;
3231 /* Set command specific information
3233 switch (cmd) {
3234 case INQUIRY:
3235 cmdLen = 6;
3236 dir = MPI_SCSIIO_CONTROL_READ;
3237 CDB[0] = cmd;
3238 CDB[4] = io->size;
3239 cmdTimeout = 10;
3240 break;
3242 case TEST_UNIT_READY:
3243 cmdLen = 6;
3244 dir = MPI_SCSIIO_CONTROL_READ;
3245 cmdTimeout = 10;
3246 break;
3248 case START_STOP:
3249 cmdLen = 6;
3250 dir = MPI_SCSIIO_CONTROL_READ;
3251 CDB[0] = cmd;
3252 CDB[4] = 1; /*Spin up the disk */
3253 cmdTimeout = 15;
3254 break;
3256 case REQUEST_SENSE:
3257 cmdLen = 6;
3258 CDB[0] = cmd;
3259 CDB[4] = io->size;
3260 dir = MPI_SCSIIO_CONTROL_READ;
3261 cmdTimeout = 10;
3262 break;
3264 case READ_BUFFER:
3265 cmdLen = 10;
3266 dir = MPI_SCSIIO_CONTROL_READ;
3267 CDB[0] = cmd;
3268 if (io->flags & MPT_ICFLAG_ECHO) {
3269 CDB[1] = 0x0A;
3270 } else {
3271 CDB[1] = 0x02;
3274 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3275 CDB[1] |= 0x01;
3277 CDB[6] = (io->size >> 16) & 0xFF;
3278 CDB[7] = (io->size >> 8) & 0xFF;
3279 CDB[8] = io->size & 0xFF;
3280 cmdTimeout = 10;
3281 break;
3283 case WRITE_BUFFER:
3284 cmdLen = 10;
3285 dir = MPI_SCSIIO_CONTROL_WRITE;
3286 CDB[0] = cmd;
3287 if (io->flags & MPT_ICFLAG_ECHO) {
3288 CDB[1] = 0x0A;
3289 } else {
3290 CDB[1] = 0x02;
3292 CDB[6] = (io->size >> 16) & 0xFF;
3293 CDB[7] = (io->size >> 8) & 0xFF;
3294 CDB[8] = io->size & 0xFF;
3295 cmdTimeout = 10;
3296 break;
3298 case RESERVE:
3299 cmdLen = 6;
3300 dir = MPI_SCSIIO_CONTROL_READ;
3301 CDB[0] = cmd;
3302 cmdTimeout = 10;
3303 break;
3305 case RELEASE:
3306 cmdLen = 6;
3307 dir = MPI_SCSIIO_CONTROL_READ;
3308 CDB[0] = cmd;
3309 cmdTimeout = 10;
3310 break;
3312 case SYNCHRONIZE_CACHE:
3313 cmdLen = 10;
3314 dir = MPI_SCSIIO_CONTROL_READ;
3315 CDB[0] = cmd;
3316 // CDB[1] = 0x02; /* set immediate bit */
3317 cmdTimeout = 10;
3318 break;
3320 default:
3321 /* Error Case */
3322 return -EFAULT;
3325 /* Get and Populate a free Frame
3327 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3328 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3329 hd->ioc->name));
3330 return -EBUSY;
3333 pScsiReq = (SCSIIORequest_t *) mf;
3335 /* Get the request index */
3336 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3337 ADD_INDEX_LOG(my_idx); /* for debug */
3339 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3340 pScsiReq->TargetID = io->physDiskNum;
3341 pScsiReq->Bus = 0;
3342 pScsiReq->ChainOffset = 0;
3343 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3344 } else {
3345 pScsiReq->TargetID = io->id;
3346 pScsiReq->Bus = io->bus;
3347 pScsiReq->ChainOffset = 0;
3348 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3351 pScsiReq->CDBLength = cmdLen;
3352 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3354 pScsiReq->Reserved = 0;
3356 pScsiReq->MsgFlags = mpt_msg_flags();
3357 /* MsgContext set in mpt_get_msg_fram call */
3359 for (ii=0; ii < 8; ii++)
3360 pScsiReq->LUN[ii] = 0;
3361 pScsiReq->LUN[1] = io->lun;
3363 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3364 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3365 else
3366 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3368 if (cmd == REQUEST_SENSE) {
3369 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3370 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3371 hd->ioc->name, cmd));
3374 for (ii=0; ii < 16; ii++)
3375 pScsiReq->CDB[ii] = CDB[ii];
3377 pScsiReq->DataLength = cpu_to_le32(io->size);
3378 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3379 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3381 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3382 hd->ioc->name, cmd, io->bus, io->id, io->lun));
3384 if (dir == MPI_SCSIIO_CONTROL_READ) {
3385 mpt_add_sge((char *) &pScsiReq->SGL,
3386 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3387 io->data_dma);
3388 } else {
3389 mpt_add_sge((char *) &pScsiReq->SGL,
3390 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3391 io->data_dma);
3394 /* The ISR will free the request frame, but we need
3395 * the information to initialize the target. Duplicate.
3397 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3399 /* Issue this command after:
3400 * finish init
3401 * add timer
3402 * Wait until the reply has been received
3403 * ScsiScanDvCtx callback function will
3404 * set hd->pLocal;
3405 * set scandv_wait_done and call wake_up
3407 hd->pLocal = NULL;
3408 hd->timer.expires = jiffies + HZ*cmdTimeout;
3409 hd->scandv_wait_done = 0;
3411 /* Save cmd pointer, for resource free if timeout or
3412 * FW reload occurs
3414 hd->cmdPtr = mf;
3416 add_timer(&hd->timer);
3417 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3418 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3420 if (hd->pLocal) {
3421 rc = hd->pLocal->completion;
3422 hd->pLocal->skip = 0;
3424 /* Always set fatal error codes in some cases.
3426 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3427 rc = -ENXIO;
3428 else if (rc == MPT_SCANDV_SOME_ERROR)
3429 rc = -rc;
3430 } else {
3431 rc = -EFAULT;
3432 /* This should never happen. */
3433 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3434 hd->ioc->name));
3437 return rc;
3440 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3442 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3443 * @hd: Pointer to a SCSI HOST structure
3444 * @vdevice: virtual target device
3446 * Uses the ISR, but with special processing.
3447 * MUST be single-threaded.
3450 static void
3451 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3453 INTERNAL_CMD iocmd;
3455 /* Following parameters will not change
3456 * in this routine.
3458 iocmd.cmd = SYNCHRONIZE_CACHE;
3459 iocmd.flags = 0;
3460 iocmd.physDiskNum = -1;
3461 iocmd.data = NULL;
3462 iocmd.data_dma = -1;
3463 iocmd.size = 0;
3464 iocmd.rsvd = iocmd.rsvd2 = 0;
3465 iocmd.bus = vdevice->vtarget->bus_id;
3466 iocmd.id = vdevice->vtarget->target_id;
3467 iocmd.lun = (u8)vdevice->lun;
3469 if ((vdevice->vtarget->type == TYPE_DISK) &&
3470 (vdevice->configured_lun))
3471 mptscsih_do_cmd(hd, &iocmd);
3474 EXPORT_SYMBOL(mptscsih_remove);
3475 EXPORT_SYMBOL(mptscsih_shutdown);
3476 #ifdef CONFIG_PM
3477 EXPORT_SYMBOL(mptscsih_suspend);
3478 EXPORT_SYMBOL(mptscsih_resume);
3479 #endif
3480 EXPORT_SYMBOL(mptscsih_proc_info);
3481 EXPORT_SYMBOL(mptscsih_info);
3482 EXPORT_SYMBOL(mptscsih_qcmd);
3483 EXPORT_SYMBOL(mptscsih_target_alloc);
3484 EXPORT_SYMBOL(mptscsih_slave_alloc);
3485 EXPORT_SYMBOL(mptscsih_target_destroy);
3486 EXPORT_SYMBOL(mptscsih_slave_destroy);
3487 EXPORT_SYMBOL(mptscsih_slave_configure);
3488 EXPORT_SYMBOL(mptscsih_abort);
3489 EXPORT_SYMBOL(mptscsih_dev_reset);
3490 EXPORT_SYMBOL(mptscsih_bus_reset);
3491 EXPORT_SYMBOL(mptscsih_host_reset);
3492 EXPORT_SYMBOL(mptscsih_bios_param);
3493 EXPORT_SYMBOL(mptscsih_io_done);
3494 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3495 EXPORT_SYMBOL(mptscsih_scandv_complete);
3496 EXPORT_SYMBOL(mptscsih_event_process);
3497 EXPORT_SYMBOL(mptscsih_ioc_reset);
3498 EXPORT_SYMBOL(mptscsih_change_queue_depth);
3499 EXPORT_SYMBOL(mptscsih_timer_expired);
3500 EXPORT_SYMBOL(mptscsih_TMHandler);
3502 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/