Linux 2.6.18.8
[linux-2.6/suspend2-2.6.18.git] / drivers / message / fusion / mptscsih.c
blob30524dc54b16b720dea158f45c5f477ff446cf19
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-2005 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");
80 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
82 typedef struct _BIG_SENSE_BUF {
83 u8 data[MPT_SENSE_BUFFER_ALLOC];
84 } BIG_SENSE_BUF;
86 #define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
87 #define MPT_SCANDV_DID_RESET (0x00000001)
88 #define MPT_SCANDV_SENSE (0x00000002)
89 #define MPT_SCANDV_SOME_ERROR (0x00000004)
90 #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
91 #define MPT_SCANDV_ISSUE_SENSE (0x00000010)
92 #define MPT_SCANDV_FALLBACK (0x00000020)
94 #define MPT_SCANDV_MAX_RETRIES (10)
96 #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
97 #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
98 #define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */
99 #define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */
100 #define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */
101 #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
102 #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
104 typedef struct _internal_cmd {
105 char *data; /* data pointer */
106 dma_addr_t data_dma; /* data dma address */
107 int size; /* transfer size */
108 u8 cmd; /* SCSI Op Code */
109 u8 bus; /* bus number */
110 u8 id; /* SCSI ID (virtual) */
111 u8 lun;
112 u8 flags; /* Bit Field - See above */
113 u8 physDiskNum; /* Phys disk number, -1 else */
114 u8 rsvd2;
115 u8 rsvd;
116 } INTERNAL_CMD;
119 * Other private/forward protos...
121 int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
122 static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
123 int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
125 static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
126 SCSIIORequest_t *pReq, int req_idx);
127 static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
128 static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
129 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
130 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
131 static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
133 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
135 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
136 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
138 static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
139 static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
140 static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
141 int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
142 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
143 static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
145 void mptscsih_remove(struct pci_dev *);
146 void mptscsih_shutdown(struct pci_dev *);
147 #ifdef CONFIG_PM
148 int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
149 int mptscsih_resume(struct pci_dev *pdev);
150 #endif
152 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
154 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
156 * mptscsih_add_sge - Place a simple SGE at address pAddr.
157 * @pAddr: virtual address for SGE
158 * @flagslength: SGE flags and data transfer length
159 * @dma_addr: Physical address
161 * This routine places a MPT request frame back on the MPT adapter's
162 * FreeQ.
164 static inline void
165 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
167 if (sizeof(dma_addr_t) == sizeof(u64)) {
168 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
169 u32 tmp = dma_addr & 0xFFFFFFFF;
171 pSge->FlagsLength = cpu_to_le32(flagslength);
172 pSge->Address.Low = cpu_to_le32(tmp);
173 tmp = (u32) ((u64)dma_addr >> 32);
174 pSge->Address.High = cpu_to_le32(tmp);
176 } else {
177 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
178 pSge->FlagsLength = cpu_to_le32(flagslength);
179 pSge->Address = cpu_to_le32(dma_addr);
181 } /* mptscsih_add_sge() */
183 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
185 * mptscsih_add_chain - Place a chain SGE at address pAddr.
186 * @pAddr: virtual address for SGE
187 * @next: nextChainOffset value (u32's)
188 * @length: length of next SGL segment
189 * @dma_addr: Physical address
191 * This routine places a MPT request frame back on the MPT adapter's
192 * FreeQ.
194 static inline void
195 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
197 if (sizeof(dma_addr_t) == sizeof(u64)) {
198 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
199 u32 tmp = dma_addr & 0xFFFFFFFF;
201 pChain->Length = cpu_to_le16(length);
202 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
204 pChain->NextChainOffset = next;
206 pChain->Address.Low = cpu_to_le32(tmp);
207 tmp = (u32) ((u64)dma_addr >> 32);
208 pChain->Address.High = cpu_to_le32(tmp);
209 } else {
210 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
211 pChain->Length = cpu_to_le16(length);
212 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
213 pChain->NextChainOffset = next;
214 pChain->Address = cpu_to_le32(dma_addr);
216 } /* mptscsih_add_chain() */
218 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
220 * mptscsih_getFreeChainBuffer - Function to get a free chain
221 * from the MPT_SCSI_HOST FreeChainQ.
222 * @ioc: Pointer to MPT_ADAPTER structure
223 * @req_idx: Index of the SCSI IO request frame. (output)
225 * return SUCCESS or FAILED
227 static inline int
228 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
230 MPT_FRAME_HDR *chainBuf;
231 unsigned long flags;
232 int rc;
233 int chain_idx;
235 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
236 ioc->name));
237 spin_lock_irqsave(&ioc->FreeQlock, flags);
238 if (!list_empty(&ioc->FreeChainQ)) {
239 int offset;
241 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
242 u.frame.linkage.list);
243 list_del(&chainBuf->u.frame.linkage.list);
244 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
245 chain_idx = offset / ioc->req_sz;
246 rc = SUCCESS;
247 dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
248 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
249 } else {
250 rc = FAILED;
251 chain_idx = MPT_HOST_NO_CHAIN;
252 dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
253 ioc->name));
255 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
257 *retIndex = chain_idx;
258 return rc;
259 } /* mptscsih_getFreeChainBuffer() */
261 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
263 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
264 * SCSIIORequest_t Message Frame.
265 * @ioc: Pointer to MPT_ADAPTER structure
266 * @SCpnt: Pointer to scsi_cmnd structure
267 * @pReq: Pointer to SCSIIORequest_t structure
269 * Returns ...
271 static int
272 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
273 SCSIIORequest_t *pReq, int req_idx)
275 char *psge;
276 char *chainSge;
277 struct scatterlist *sg;
278 int frm_sz;
279 int sges_left, sg_done;
280 int chain_idx = MPT_HOST_NO_CHAIN;
281 int sgeOffset;
282 int numSgeSlots, numSgeThisFrame;
283 u32 sgflags, sgdir, thisxfer = 0;
284 int chain_dma_off = 0;
285 int newIndex;
286 int ii;
287 dma_addr_t v2;
288 u32 RequestNB;
290 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
291 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
292 sgdir = MPT_TRANSFER_HOST_TO_IOC;
293 } else {
294 sgdir = MPT_TRANSFER_IOC_TO_HOST;
297 psge = (char *) &pReq->SGL;
298 frm_sz = ioc->req_sz;
300 /* Map the data portion, if any.
301 * sges_left = 0 if no data transfer.
303 if ( (sges_left = SCpnt->use_sg) ) {
304 sges_left = pci_map_sg(ioc->pcidev,
305 (struct scatterlist *) SCpnt->request_buffer,
306 SCpnt->use_sg,
307 SCpnt->sc_data_direction);
308 if (sges_left == 0)
309 return FAILED;
310 } else if (SCpnt->request_bufflen) {
311 SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
312 SCpnt->request_buffer,
313 SCpnt->request_bufflen,
314 SCpnt->sc_data_direction);
315 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
316 ioc->name, SCpnt, SCpnt->request_bufflen));
317 mptscsih_add_sge((char *) &pReq->SGL,
318 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
319 SCpnt->SCp.dma_handle);
321 return SUCCESS;
324 /* Handle the SG case.
326 sg = (struct scatterlist *) SCpnt->request_buffer;
327 sg_done = 0;
328 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
329 chainSge = NULL;
331 /* Prior to entering this loop - the following must be set
332 * current MF: sgeOffset (bytes)
333 * chainSge (Null if original MF is not a chain buffer)
334 * sg_done (num SGE done for this MF)
337 nextSGEset:
338 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
339 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
341 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
343 /* Get first (num - 1) SG elements
344 * Skip any SG entries with a length of 0
345 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
347 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
348 thisxfer = sg_dma_len(sg);
349 if (thisxfer == 0) {
350 sg ++; /* Get next SG element from the OS */
351 sg_done++;
352 continue;
355 v2 = sg_dma_address(sg);
356 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
358 sg++; /* Get next SG element from the OS */
359 psge += (sizeof(u32) + sizeof(dma_addr_t));
360 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
361 sg_done++;
364 if (numSgeThisFrame == sges_left) {
365 /* Add last element, end of buffer and end of list flags.
367 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
368 MPT_SGE_FLAGS_END_OF_BUFFER |
369 MPT_SGE_FLAGS_END_OF_LIST;
371 /* Add last SGE and set termination flags.
372 * Note: Last SGE may have a length of 0 - which should be ok.
374 thisxfer = sg_dma_len(sg);
376 v2 = sg_dma_address(sg);
377 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
379 sg++;
380 psge += (sizeof(u32) + sizeof(dma_addr_t));
382 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
383 sg_done++;
385 if (chainSge) {
386 /* The current buffer is a chain buffer,
387 * but there is not another one.
388 * Update the chain element
389 * Offset and Length fields.
391 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
392 } else {
393 /* The current buffer is the original MF
394 * and there is no Chain buffer.
396 pReq->ChainOffset = 0;
397 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
398 dsgprintk((MYIOC_s_INFO_FMT
399 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
400 ioc->RequestNB[req_idx] = RequestNB;
402 } else {
403 /* At least one chain buffer is needed.
404 * Complete the first MF
405 * - last SGE element, set the LastElement bit
406 * - set ChainOffset (words) for orig MF
407 * (OR finish previous MF chain buffer)
408 * - update MFStructPtr ChainIndex
409 * - Populate chain element
410 * Also
411 * Loop until done.
414 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
415 ioc->name, sg_done));
417 /* Set LAST_ELEMENT flag for last non-chain element
418 * in the buffer. Since psge points at the NEXT
419 * SGE element, go back one SGE element, update the flags
420 * and reset the pointer. (Note: sgflags & thisxfer are already
421 * set properly).
423 if (sg_done) {
424 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
425 sgflags = le32_to_cpu(*ptmp);
426 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
427 *ptmp = cpu_to_le32(sgflags);
430 if (chainSge) {
431 /* The current buffer is a chain buffer.
432 * chainSge points to the previous Chain Element.
433 * Update its chain element Offset and Length (must
434 * include chain element size) fields.
435 * Old chain element is now complete.
437 u8 nextChain = (u8) (sgeOffset >> 2);
438 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
439 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
440 } else {
441 /* The original MF buffer requires a chain buffer -
442 * set the offset.
443 * Last element in this MF is a chain element.
445 pReq->ChainOffset = (u8) (sgeOffset >> 2);
446 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
447 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
448 ioc->RequestNB[req_idx] = RequestNB;
451 sges_left -= sg_done;
454 /* NOTE: psge points to the beginning of the chain element
455 * in current buffer. Get a chain buffer.
457 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
458 dfailprintk((MYIOC_s_INFO_FMT
459 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
460 ioc->name, pReq->CDB[0], SCpnt));
461 return FAILED;
464 /* Update the tracking arrays.
465 * If chainSge == NULL, update ReqToChain, else ChainToChain
467 if (chainSge) {
468 ioc->ChainToChain[chain_idx] = newIndex;
469 } else {
470 ioc->ReqToChain[req_idx] = newIndex;
472 chain_idx = newIndex;
473 chain_dma_off = ioc->req_sz * chain_idx;
475 /* Populate the chainSGE for the current buffer.
476 * - Set chain buffer pointer to psge and fill
477 * out the Address and Flags fields.
479 chainSge = (char *) psge;
480 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
481 psge, req_idx));
483 /* Start the SGE for the next buffer
485 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
486 sgeOffset = 0;
487 sg_done = 0;
489 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
490 psge, chain_idx));
492 /* Start the SGE for the next buffer
495 goto nextSGEset;
498 return SUCCESS;
499 } /* mptscsih_AddSGE() */
501 static void
502 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
503 U32 SlotStatus)
505 MPT_FRAME_HDR *mf;
506 SEPRequest_t *SEPMsg;
508 if (ioc->bus_type == FC)
509 return;
511 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
512 dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
513 ioc->name,__FUNCTION__));
514 return;
517 SEPMsg = (SEPRequest_t *)mf;
518 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
519 SEPMsg->Bus = vtarget->bus_id;
520 SEPMsg->TargetID = vtarget->target_id;
521 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
522 SEPMsg->SlotStatus = SlotStatus;
523 devtverboseprintk((MYIOC_s_WARN_FMT
524 "Sending SEP cmd=%x id=%d bus=%d\n",
525 ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
526 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
529 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
531 * mptscsih_io_done - Main SCSI IO callback routine registered to
532 * Fusion MPT (base) driver
533 * @ioc: Pointer to MPT_ADAPTER structure
534 * @mf: Pointer to original MPT request frame
535 * @r: Pointer to MPT reply frame (NULL if TurboReply)
537 * This routine is called from mpt.c::mpt_interrupt() at the completion
538 * of any SCSI IO request.
539 * This routine is registered with the Fusion MPT (base) driver at driver
540 * load/init time via the mpt_register() API call.
542 * Returns 1 indicating alloc'd request frame ptr should be freed.
545 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
547 struct scsi_cmnd *sc;
548 MPT_SCSI_HOST *hd;
549 SCSIIORequest_t *pScsiReq;
550 SCSIIOReply_t *pScsiReply;
551 u16 req_idx, req_idx_MR;
552 VirtDevice *vdev;
553 VirtTarget *vtarget;
555 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
557 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
558 req_idx_MR = (mr != NULL) ?
559 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
560 if ((req_idx != req_idx_MR) ||
561 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
562 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
563 ioc->name);
564 printk (MYIOC_s_ERR_FMT
565 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
566 ioc->name, req_idx, req_idx_MR, mf, mr,
567 hd->ScsiLookup[req_idx_MR]);
568 return 0;
571 sc = hd->ScsiLookup[req_idx];
572 hd->ScsiLookup[req_idx] = NULL;
573 if (sc == NULL) {
574 MPIHeader_t *hdr = (MPIHeader_t *)mf;
576 /* Remark: writeSDP1 will use the ScsiDoneCtx
577 * If a SCSI I/O cmd, device disabled by OS and
578 * completion done. Cannot touch sc struct. Just free mem.
580 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
581 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
582 ioc->name);
584 mptscsih_freeChainBuffers(ioc, req_idx);
585 return 1;
588 if ((unsigned char *)mf != sc->host_scribble) {
589 mptscsih_freeChainBuffers(ioc, req_idx);
590 return 1;
593 sc->host_scribble = NULL;
594 sc->result = DID_OK << 16; /* Set default reply as OK */
595 pScsiReq = (SCSIIORequest_t *) mf;
596 pScsiReply = (SCSIIOReply_t *) mr;
598 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
599 dmfprintk((MYIOC_s_INFO_FMT
600 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
601 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
602 }else{
603 dmfprintk((MYIOC_s_INFO_FMT
604 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
605 ioc->name, mf, mr, sc, req_idx));
608 if (pScsiReply == NULL) {
609 /* special context reply handling */
611 } else {
612 u32 xfer_cnt;
613 u16 status;
614 u8 scsi_state, scsi_status;
616 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
617 scsi_state = pScsiReply->SCSIState;
618 scsi_status = pScsiReply->SCSIStatus;
619 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
620 sc->resid = sc->request_bufflen - xfer_cnt;
623 * if we get a data underrun indication, yet no data was
624 * transferred and the SCSI status indicates that the
625 * command was never started, change the data underrun
626 * to success
628 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
629 (scsi_status == MPI_SCSI_STATUS_BUSY ||
630 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
631 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
632 status = MPI_IOCSTATUS_SUCCESS;
635 dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
636 "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
637 "resid=%d bufflen=%d xfer_cnt=%d\n",
638 ioc->id, sc->device->id, sc->device->lun,
639 status, scsi_state, scsi_status, sc->resid,
640 sc->request_bufflen, xfer_cnt));
642 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
643 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
646 * Look for + dump FCP ResponseInfo[]!
648 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
649 pScsiReply->ResponseInfo) {
650 printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
651 "FCP_ResponseInfo=%08xh\n",
652 ioc->id, sc->device->id, sc->device->lun,
653 le32_to_cpu(pScsiReply->ResponseInfo));
656 switch(status) {
657 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
658 /* CHECKME!
659 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
660 * But not: DID_BUS_BUSY lest one risk
661 * killing interrupt handler:-(
663 sc->result = SAM_STAT_BUSY;
664 break;
666 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
667 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
668 sc->result = DID_BAD_TARGET << 16;
669 break;
671 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
672 /* Spoof to SCSI Selection Timeout! */
673 if (ioc->bus_type != FC)
674 sc->result = DID_NO_CONNECT << 16;
675 /* else fibre, just stall until rescan event */
676 else
677 sc->result = DID_REQUEUE << 16;
679 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
680 hd->sel_timeout[pScsiReq->TargetID]++;
682 vdev = sc->device->hostdata;
683 if (!vdev)
684 break;
685 vtarget = vdev->vtarget;
686 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
687 mptscsih_issue_sep_command(ioc, vtarget,
688 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
689 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
691 break;
693 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
694 if ( ioc->bus_type == SAS ) {
695 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
696 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
697 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
698 log_info &=SAS_LOGINFO_MASK;
699 if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
700 sc->result = (DID_BUS_BUSY << 16);
701 break;
707 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
710 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
711 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
712 /* Linux handles an unsolicited DID_RESET better
713 * than an unsolicited DID_ABORT.
715 sc->result = DID_RESET << 16;
717 break;
719 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
720 sc->resid = sc->request_bufflen - xfer_cnt;
721 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
722 sc->result=DID_SOFT_ERROR << 16;
723 else /* Sufficient data transfer occurred */
724 sc->result = (DID_OK << 16) | scsi_status;
725 dreplyprintk((KERN_NOTICE
726 "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
727 break;
729 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
731 * Do upfront check for valid SenseData and give it
732 * precedence!
734 sc->result = (DID_OK << 16) | scsi_status;
735 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
736 /* Have already saved the status and sense data
739 } else {
740 if (xfer_cnt < sc->underflow) {
741 if (scsi_status == SAM_STAT_BUSY)
742 sc->result = SAM_STAT_BUSY;
743 else
744 sc->result = DID_SOFT_ERROR << 16;
746 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
747 /* What to do?
749 sc->result = DID_SOFT_ERROR << 16;
751 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
752 /* Not real sure here either... */
753 sc->result = DID_RESET << 16;
757 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
758 sc->underflow));
759 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
760 /* Report Queue Full
762 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
763 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
765 break;
767 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
768 sc->resid=0;
769 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
770 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
771 if (scsi_status == MPI_SCSI_STATUS_BUSY)
772 sc->result = (DID_BUS_BUSY << 16) | scsi_status;
773 else
774 sc->result = (DID_OK << 16) | scsi_status;
775 if (scsi_state == 0) {
777 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
779 * If running against circa 200003dd 909 MPT f/w,
780 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
781 * (QUEUE_FULL) returned from device! --> get 0x0000?128
782 * and with SenseBytes set to 0.
784 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
785 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
788 else if (scsi_state &
789 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
792 * What to do?
794 sc->result = DID_SOFT_ERROR << 16;
796 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
797 /* Not real sure here either... */
798 sc->result = DID_RESET << 16;
800 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
801 /* Device Inq. data indicates that it supports
802 * QTags, but rejects QTag messages.
803 * This command completed OK.
805 * Not real sure here either so do nothing... */
808 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
809 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
811 /* Add handling of:
812 * Reservation Conflict, Busy,
813 * Command Terminated, CHECK
815 break;
817 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
818 sc->result = DID_SOFT_ERROR << 16;
819 break;
821 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
822 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
823 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
824 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
825 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
826 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
827 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
828 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
829 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
830 default:
832 * What to do?
834 sc->result = DID_SOFT_ERROR << 16;
835 break;
837 } /* switch(status) */
839 dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
840 } /* end of address reply case */
842 /* Unmap the DMA buffers, if any. */
843 if (sc->use_sg) {
844 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
845 sc->use_sg, sc->sc_data_direction);
846 } else if (sc->request_bufflen) {
847 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
848 sc->request_bufflen, sc->sc_data_direction);
851 sc->scsi_done(sc); /* Issue the command callback */
853 /* Free Chain buffers */
854 mptscsih_freeChainBuffers(ioc, req_idx);
855 return 1;
859 * mptscsih_flush_running_cmds - For each command found, search
860 * Scsi_Host instance taskQ and reply to OS.
861 * Called only if recovering from a FW reload.
862 * @hd: Pointer to a SCSI HOST structure
864 * Returns: None.
866 * Must be called while new I/Os are being queued.
868 static void
869 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
871 MPT_ADAPTER *ioc = hd->ioc;
872 struct scsi_cmnd *SCpnt;
873 MPT_FRAME_HDR *mf;
874 int ii;
875 int max = ioc->req_depth;
877 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
878 for (ii= 0; ii < max; ii++) {
879 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
881 /* Command found.
884 /* Null ScsiLookup index
886 hd->ScsiLookup[ii] = NULL;
888 mf = MPT_INDEX_2_MFPTR(ioc, ii);
889 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
890 mf, SCpnt));
892 /* Free Chain buffers */
893 mptscsih_freeChainBuffers(ioc, ii);
895 /* Free Message frames */
896 mpt_free_msg_frame(ioc, mf);
898 if ((unsigned char *)mf != SCpnt->host_scribble)
899 continue;
901 /* Set status, free OS resources (SG DMA buffers)
902 * Do OS callback
904 if (SCpnt->use_sg) {
905 pci_unmap_sg(ioc->pcidev,
906 (struct scatterlist *) SCpnt->request_buffer,
907 SCpnt->use_sg,
908 SCpnt->sc_data_direction);
909 } else if (SCpnt->request_bufflen) {
910 pci_unmap_single(ioc->pcidev,
911 SCpnt->SCp.dma_handle,
912 SCpnt->request_bufflen,
913 SCpnt->sc_data_direction);
915 SCpnt->result = DID_RESET << 16;
916 SCpnt->host_scribble = NULL;
918 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
922 return;
926 * mptscsih_search_running_cmds - Delete any commands associated
927 * with the specified target and lun. Function called only
928 * when a lun is disable by mid-layer.
929 * Do NOT access the referenced scsi_cmnd structure or
930 * members. Will cause either a paging or NULL ptr error.
931 * (BUT, BUT, BUT, the code does reference it! - mdr)
932 * @hd: Pointer to a SCSI HOST structure
933 * @vdevice: per device private data
935 * Returns: None.
937 * Called from slave_destroy.
939 static void
940 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
942 SCSIIORequest_t *mf = NULL;
943 int ii;
944 int max = hd->ioc->req_depth;
945 struct scsi_cmnd *sc;
947 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
948 vdevice->vtarget->target_id, vdevice->lun, max));
950 for (ii=0; ii < max; ii++) {
951 if ((sc = hd->ScsiLookup[ii]) != NULL) {
953 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
954 if (mf == NULL)
955 continue;
956 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
957 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
958 if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
959 continue;
961 /* Cleanup
963 hd->ScsiLookup[ii] = NULL;
964 mptscsih_freeChainBuffers(hd->ioc, ii);
965 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
966 if ((unsigned char *)mf != sc->host_scribble)
967 continue;
968 if (sc->use_sg) {
969 pci_unmap_sg(hd->ioc->pcidev,
970 (struct scatterlist *) sc->request_buffer,
971 sc->use_sg,
972 sc->sc_data_direction);
973 } else if (sc->request_bufflen) {
974 pci_unmap_single(hd->ioc->pcidev,
975 sc->SCp.dma_handle,
976 sc->request_bufflen,
977 sc->sc_data_direction);
979 sc->host_scribble = NULL;
980 sc->result = DID_NO_CONNECT << 16;
981 sc->scsi_done(sc);
984 return;
987 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
989 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
991 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
992 * from a SCSI target device.
993 * @sc: Pointer to scsi_cmnd structure
994 * @pScsiReply: Pointer to SCSIIOReply_t
995 * @pScsiReq: Pointer to original SCSI request
997 * This routine periodically reports QUEUE_FULL status returned from a
998 * SCSI target device. It reports this to the console via kernel
999 * printk() API call, not more than once every 10 seconds.
1001 static void
1002 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1004 long time = jiffies;
1005 MPT_SCSI_HOST *hd;
1007 if (sc->device == NULL)
1008 return;
1009 if (sc->device->host == NULL)
1010 return;
1011 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
1012 return;
1014 if (time - hd->last_queue_full > 10 * HZ) {
1015 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1016 hd->ioc->name, 0, sc->device->id, sc->device->lun));
1017 hd->last_queue_full = time;
1021 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1023 * mptscsih_remove - Removed scsi devices
1024 * @pdev: Pointer to pci_dev structure
1028 void
1029 mptscsih_remove(struct pci_dev *pdev)
1031 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1032 struct Scsi_Host *host = ioc->sh;
1033 MPT_SCSI_HOST *hd;
1034 int sz1;
1036 if(!host) {
1037 mpt_detach(pdev);
1038 return;
1041 scsi_remove_host(host);
1043 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1044 return;
1046 mptscsih_shutdown(pdev);
1048 sz1=0;
1050 if (hd->ScsiLookup != NULL) {
1051 sz1 = hd->ioc->req_depth * sizeof(void *);
1052 kfree(hd->ScsiLookup);
1053 hd->ScsiLookup = NULL;
1057 * Free pointer array.
1059 kfree(hd->Targets);
1060 hd->Targets = NULL;
1062 dprintk((MYIOC_s_INFO_FMT
1063 "Free'd ScsiLookup (%d) memory\n",
1064 hd->ioc->name, sz1));
1066 kfree(hd->info_kbuf);
1068 /* NULL the Scsi_Host pointer
1070 hd->ioc->sh = NULL;
1072 scsi_host_put(host);
1074 mpt_detach(pdev);
1078 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1080 * mptscsih_shutdown - reboot notifier
1083 void
1084 mptscsih_shutdown(struct pci_dev *pdev)
1086 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1087 struct Scsi_Host *host = ioc->sh;
1088 MPT_SCSI_HOST *hd;
1090 if(!host)
1091 return;
1093 hd = (MPT_SCSI_HOST *)host->hostdata;
1097 #ifdef CONFIG_PM
1098 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1100 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1105 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1107 mptscsih_shutdown(pdev);
1108 return mpt_suspend(pdev,state);
1111 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1113 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1118 mptscsih_resume(struct pci_dev *pdev)
1120 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1121 struct Scsi_Host *host = ioc->sh;
1122 MPT_SCSI_HOST *hd;
1124 mpt_resume(pdev);
1126 if(!host)
1127 return 0;
1129 hd = (MPT_SCSI_HOST *)host->hostdata;
1130 if(!hd)
1131 return 0;
1133 return 0;
1136 #endif
1138 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1140 * mptscsih_info - Return information about MPT adapter
1141 * @SChost: Pointer to Scsi_Host structure
1143 * (linux scsi_host_template.info routine)
1145 * Returns pointer to buffer where information was written.
1147 const char *
1148 mptscsih_info(struct Scsi_Host *SChost)
1150 MPT_SCSI_HOST *h;
1151 int size = 0;
1153 h = (MPT_SCSI_HOST *)SChost->hostdata;
1155 if (h) {
1156 if (h->info_kbuf == NULL)
1157 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1158 return h->info_kbuf;
1159 h->info_kbuf[0] = '\0';
1161 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1162 h->info_kbuf[size-1] = '\0';
1165 return h->info_kbuf;
1168 struct info_str {
1169 char *buffer;
1170 int length;
1171 int offset;
1172 int pos;
1175 static void
1176 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1178 if (info->pos + len > info->length)
1179 len = info->length - info->pos;
1181 if (info->pos + len < info->offset) {
1182 info->pos += len;
1183 return;
1186 if (info->pos < info->offset) {
1187 data += (info->offset - info->pos);
1188 len -= (info->offset - info->pos);
1191 if (len > 0) {
1192 memcpy(info->buffer + info->pos, data, len);
1193 info->pos += len;
1197 static int
1198 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1200 va_list args;
1201 char buf[81];
1202 int len;
1204 va_start(args, fmt);
1205 len = vsprintf(buf, fmt, args);
1206 va_end(args);
1208 mptscsih_copy_mem_info(info, buf, len);
1209 return len;
1212 static int
1213 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1215 struct info_str info;
1217 info.buffer = pbuf;
1218 info.length = len;
1219 info.offset = offset;
1220 info.pos = 0;
1222 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1223 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1224 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1225 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1227 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1230 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1232 * mptscsih_proc_info - Return information about MPT adapter
1234 * (linux scsi_host_template.info routine)
1236 * buffer: if write, user data; if read, buffer for user
1237 * length: if write, return length;
1238 * offset: if write, 0; if read, the current offset into the buffer from
1239 * the previous read.
1240 * hostno: scsi host number
1241 * func: if write = 1; if read = 0
1244 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1245 int length, int func)
1247 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1248 MPT_ADAPTER *ioc = hd->ioc;
1249 int size = 0;
1251 if (func) {
1253 * write is not supported
1255 } else {
1256 if (start)
1257 *start = buffer;
1259 size = mptscsih_host_info(ioc, buffer, offset, length);
1262 return size;
1265 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1266 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1268 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1270 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1271 * @SCpnt: Pointer to scsi_cmnd structure
1272 * @done: Pointer SCSI mid-layer IO completion function
1274 * (linux scsi_host_template.queuecommand routine)
1275 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1276 * from a linux scsi_cmnd request and send it to the IOC.
1278 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1281 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1283 MPT_SCSI_HOST *hd;
1284 MPT_FRAME_HDR *mf;
1285 SCSIIORequest_t *pScsiReq;
1286 VirtDevice *vdev = SCpnt->device->hostdata;
1287 int lun;
1288 u32 datalen;
1289 u32 scsictl;
1290 u32 scsidir;
1291 u32 cmd_len;
1292 int my_idx;
1293 int ii;
1295 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1296 lun = SCpnt->device->lun;
1297 SCpnt->scsi_done = done;
1299 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1300 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1302 if (hd->resetPending) {
1303 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1304 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1305 return SCSI_MLQUEUE_HOST_BUSY;
1308 if ((hd->ioc->bus_type == SPI) &&
1309 vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT &&
1310 mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) {
1311 SCpnt->result = DID_NO_CONNECT << 16;
1312 done(SCpnt);
1313 return 0;
1317 * Put together a MPT SCSI request...
1319 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1320 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1321 hd->ioc->name));
1322 return SCSI_MLQUEUE_HOST_BUSY;
1325 pScsiReq = (SCSIIORequest_t *) mf;
1327 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1329 ADD_INDEX_LOG(my_idx);
1331 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1332 * Seems we may receive a buffer (datalen>0) even when there
1333 * will be no data transfer! GRRRRR...
1335 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1336 datalen = SCpnt->request_bufflen;
1337 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1338 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1339 datalen = SCpnt->request_bufflen;
1340 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1341 } else {
1342 datalen = 0;
1343 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1346 /* Default to untagged. Once a target structure has been allocated,
1347 * use the Inquiry data to determine if device supports tagged.
1349 if (vdev
1350 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1351 && (SCpnt->device->tagged_supported)) {
1352 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1353 } else {
1354 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1357 /* Use the above information to set up the message frame
1359 pScsiReq->TargetID = (u8) vdev->vtarget->target_id;
1360 pScsiReq->Bus = vdev->vtarget->bus_id;
1361 pScsiReq->ChainOffset = 0;
1362 if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
1363 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1364 else
1365 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1366 pScsiReq->CDBLength = SCpnt->cmd_len;
1367 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1368 pScsiReq->Reserved = 0;
1369 pScsiReq->MsgFlags = mpt_msg_flags();
1370 pScsiReq->LUN[0] = 0;
1371 pScsiReq->LUN[1] = lun;
1372 pScsiReq->LUN[2] = 0;
1373 pScsiReq->LUN[3] = 0;
1374 pScsiReq->LUN[4] = 0;
1375 pScsiReq->LUN[5] = 0;
1376 pScsiReq->LUN[6] = 0;
1377 pScsiReq->LUN[7] = 0;
1378 pScsiReq->Control = cpu_to_le32(scsictl);
1381 * Write SCSI CDB into the message
1383 cmd_len = SCpnt->cmd_len;
1384 for (ii=0; ii < cmd_len; ii++)
1385 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1387 for (ii=cmd_len; ii < 16; ii++)
1388 pScsiReq->CDB[ii] = 0;
1390 /* DataLength */
1391 pScsiReq->DataLength = cpu_to_le32(datalen);
1393 /* SenseBuffer low address */
1394 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1395 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1397 /* Now add the SG list
1398 * Always have a SGE even if null length.
1400 if (datalen == 0) {
1401 /* Add a NULL SGE */
1402 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1403 (dma_addr_t) -1);
1404 } else {
1405 /* Add a 32 or 64 bit SGE */
1406 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1407 goto fail;
1410 SCpnt->host_scribble = (unsigned char *)mf;
1411 hd->ScsiLookup[my_idx] = SCpnt;
1413 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1414 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1415 hd->ioc->name, SCpnt, mf, my_idx));
1416 DBG_DUMP_REQUEST_FRAME(mf)
1417 return 0;
1419 fail:
1420 hd->ScsiLookup[my_idx] = NULL;
1421 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1422 mpt_free_msg_frame(hd->ioc, mf);
1423 return SCSI_MLQUEUE_HOST_BUSY;
1426 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1428 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1429 * with a SCSI IO request
1430 * @hd: Pointer to the MPT_SCSI_HOST instance
1431 * @req_idx: Index of the SCSI IO request frame.
1433 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1434 * No return.
1436 static void
1437 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1439 MPT_FRAME_HDR *chain;
1440 unsigned long flags;
1441 int chain_idx;
1442 int next;
1444 /* Get the first chain index and reset
1445 * tracker state.
1447 chain_idx = ioc->ReqToChain[req_idx];
1448 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1450 while (chain_idx != MPT_HOST_NO_CHAIN) {
1452 /* Save the next chain buffer index */
1453 next = ioc->ChainToChain[chain_idx];
1455 /* Free this chain buffer and reset
1456 * tracker
1458 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1460 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1461 + (chain_idx * ioc->req_sz));
1463 spin_lock_irqsave(&ioc->FreeQlock, flags);
1464 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1465 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1467 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1468 ioc->name, chain_idx));
1470 /* handle next */
1471 chain_idx = next;
1473 return;
1476 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1478 * Reset Handling
1481 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1483 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1484 * Fall through to mpt_HardResetHandler if: not operational, too many
1485 * failed TM requests or handshake failure.
1487 * @ioc: Pointer to MPT_ADAPTER structure
1488 * @type: Task Management type
1489 * @target: Logical Target ID for reset (if appropriate)
1490 * @lun: Logical Unit for reset (if appropriate)
1491 * @ctx2abort: Context for the task to be aborted (if appropriate)
1493 * Remark: Currently invoked from a non-interrupt thread (_bh).
1495 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1496 * will be active.
1498 * Returns 0 for SUCCESS or -1 if FAILED.
1501 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1503 MPT_ADAPTER *ioc;
1504 int rc = -1;
1505 int doTask = 1;
1506 u32 ioc_raw_state;
1507 unsigned long flags;
1509 /* If FW is being reloaded currently, return success to
1510 * the calling function.
1512 if (hd == NULL)
1513 return 0;
1515 ioc = hd->ioc;
1516 if (ioc == NULL) {
1517 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1518 return FAILED;
1520 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1522 // SJR - CHECKME - Can we avoid this here?
1523 // (mpt_HardResetHandler has this check...)
1524 spin_lock_irqsave(&ioc->diagLock, flags);
1525 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1526 spin_unlock_irqrestore(&ioc->diagLock, flags);
1527 return FAILED;
1529 spin_unlock_irqrestore(&ioc->diagLock, flags);
1531 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1532 * If we time out and not bus reset, then we return a FAILED status to the caller.
1533 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1534 * successful. Otherwise, reload the FW.
1536 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1537 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1538 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1539 "Timed out waiting for last TM (%d) to complete! \n",
1540 hd->ioc->name, hd->tmPending));
1541 return FAILED;
1542 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1543 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
1544 "Timed out waiting for last TM (%d) to complete! \n",
1545 hd->ioc->name, hd->tmPending));
1546 return FAILED;
1547 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1548 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1549 "Timed out waiting for last TM (%d) to complete! \n",
1550 hd->ioc->name, hd->tmPending));
1551 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
1552 return FAILED;
1554 doTask = 0;
1556 } else {
1557 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1558 hd->tmPending |= (1 << type);
1559 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1562 /* Is operational?
1564 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1566 #ifdef MPT_DEBUG_RESET
1567 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1568 printk(MYIOC_s_WARN_FMT
1569 "TM Handler: IOC Not operational(0x%x)!\n",
1570 hd->ioc->name, ioc_raw_state);
1572 #endif
1574 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1575 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1577 /* Isse the Task Mgmt request.
1579 if (hd->hard_resets < -1)
1580 hd->hard_resets++;
1581 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
1582 if (rc) {
1583 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
1584 } else {
1585 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
1589 /* Only fall through to the HRH if this is a bus reset
1591 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
1592 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
1593 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1594 hd->ioc->name));
1595 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1599 * Check IOCStatus from TM reply message
1601 if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
1602 rc = FAILED;
1604 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1606 return rc;
1610 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1612 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1613 * @hd: Pointer to MPT_SCSI_HOST structure
1614 * @type: Task Management type
1615 * @target: Logical Target ID for reset (if appropriate)
1616 * @lun: Logical Unit for reset (if appropriate)
1617 * @ctx2abort: Context for the task to be aborted (if appropriate)
1619 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1620 * or a non-interrupt thread. In the former, must not call schedule().
1622 * Not all fields are meaningfull for all task types.
1624 * Returns 0 for SUCCESS, -999 for "no msg frames",
1625 * else other non-zero value returned.
1627 static int
1628 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1630 MPT_FRAME_HDR *mf;
1631 SCSITaskMgmt_t *pScsiTm;
1632 int ii;
1633 int retval;
1635 /* Return Fail to calling function if no message frames available.
1637 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1638 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1639 hd->ioc->name));
1640 return FAILED;
1642 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1643 hd->ioc->name, mf));
1645 /* Format the Request
1647 pScsiTm = (SCSITaskMgmt_t *) mf;
1648 pScsiTm->TargetID = target;
1649 pScsiTm->Bus = channel;
1650 pScsiTm->ChainOffset = 0;
1651 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1653 pScsiTm->Reserved = 0;
1654 pScsiTm->TaskType = type;
1655 pScsiTm->Reserved1 = 0;
1656 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1657 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1659 for (ii= 0; ii < 8; ii++) {
1660 pScsiTm->LUN[ii] = 0;
1662 pScsiTm->LUN[1] = lun;
1664 for (ii=0; ii < 7; ii++)
1665 pScsiTm->Reserved2[ii] = 0;
1667 pScsiTm->TaskMsgContext = ctx2abort;
1669 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1670 hd->ioc->name, ctx2abort, type));
1672 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1674 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1675 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
1676 CAN_SLEEP)) != 0) {
1677 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
1678 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1679 hd->ioc, mf));
1680 mpt_free_msg_frame(hd->ioc, mf);
1681 return retval;
1684 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1685 dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
1686 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1687 hd->ioc, mf));
1688 mpt_free_msg_frame(hd->ioc, mf);
1689 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1690 hd->ioc->name));
1691 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1694 return retval;
1697 static int
1698 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1700 switch (ioc->bus_type) {
1701 case FC:
1702 return 40;
1703 case SAS:
1704 return 10;
1705 case SPI:
1706 default:
1707 return 2;
1711 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1713 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1714 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1716 * (linux scsi_host_template.eh_abort_handler routine)
1718 * Returns SUCCESS or FAILED.
1721 mptscsih_abort(struct scsi_cmnd * SCpnt)
1723 MPT_SCSI_HOST *hd;
1724 MPT_FRAME_HDR *mf;
1725 u32 ctx2abort;
1726 int scpnt_idx;
1727 int retval;
1728 VirtDevice *vdev;
1729 ulong sn = SCpnt->serial_number;
1731 /* If we can't locate our host adapter structure, return FAILED status.
1733 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1734 SCpnt->result = DID_RESET << 16;
1735 SCpnt->scsi_done(SCpnt);
1736 dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1737 "Can't locate host! (sc=%p)\n",
1738 SCpnt));
1739 return FAILED;
1742 /* Find this command
1744 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1745 /* Cmd not found in ScsiLookup.
1746 * Do OS callback.
1748 SCpnt->result = DID_RESET << 16;
1749 dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1750 "Command not in the active list! (sc=%p)\n",
1751 hd->ioc->name, SCpnt));
1752 return SUCCESS;
1755 if (hd->resetPending) {
1756 return FAILED;
1759 if (hd->timeouts < -1)
1760 hd->timeouts++;
1762 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1763 hd->ioc->name, SCpnt);
1764 scsi_print_command(SCpnt);
1766 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1767 * (the IO to be ABORT'd)
1769 * NOTE: Since we do not byteswap MsgContext, we do not
1770 * swap it here either. It is an opaque cookie to
1771 * the controller, so it does not matter. -DaveM
1773 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1774 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1776 hd->abortSCpnt = SCpnt;
1778 vdev = SCpnt->device->hostdata;
1779 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1780 vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
1781 ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1783 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1784 SCpnt->serial_number == sn) {
1785 retval = FAILED;
1788 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1789 hd->ioc->name,
1790 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1792 if (retval == 0)
1793 return SUCCESS;
1795 if(retval != FAILED ) {
1796 hd->tmPending = 0;
1797 hd->tmState = TM_STATE_NONE;
1799 return FAILED;
1802 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1804 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1805 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1807 * (linux scsi_host_template.eh_dev_reset_handler routine)
1809 * Returns SUCCESS or FAILED.
1812 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1814 MPT_SCSI_HOST *hd;
1815 int retval;
1816 VirtDevice *vdev;
1818 /* If we can't locate our host adapter structure, return FAILED status.
1820 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1821 dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1822 "Can't locate host! (sc=%p)\n",
1823 SCpnt));
1824 return FAILED;
1827 if (hd->resetPending)
1828 return FAILED;
1830 printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1831 hd->ioc->name, SCpnt);
1832 scsi_print_command(SCpnt);
1834 vdev = SCpnt->device->hostdata;
1835 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1836 vdev->vtarget->bus_id, vdev->vtarget->target_id,
1837 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1839 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1840 hd->ioc->name,
1841 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1843 if (retval == 0)
1844 return SUCCESS;
1846 if(retval != FAILED ) {
1847 hd->tmPending = 0;
1848 hd->tmState = TM_STATE_NONE;
1850 return FAILED;
1853 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1855 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1856 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1858 * (linux scsi_host_template.eh_bus_reset_handler routine)
1860 * Returns SUCCESS or FAILED.
1863 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1865 MPT_SCSI_HOST *hd;
1866 int retval;
1867 VirtDevice *vdev;
1869 /* If we can't locate our host adapter structure, return FAILED status.
1871 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1872 dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1873 "Can't locate host! (sc=%p)\n",
1874 SCpnt ) );
1875 return FAILED;
1878 printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1879 hd->ioc->name, SCpnt);
1880 scsi_print_command(SCpnt);
1882 if (hd->timeouts < -1)
1883 hd->timeouts++;
1885 vdev = SCpnt->device->hostdata;
1886 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1887 vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1889 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1890 hd->ioc->name,
1891 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1893 if (retval == 0)
1894 return SUCCESS;
1896 if(retval != FAILED ) {
1897 hd->tmPending = 0;
1898 hd->tmState = TM_STATE_NONE;
1900 return FAILED;
1903 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1905 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
1906 * new_eh variant
1907 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1909 * (linux scsi_host_template.eh_host_reset_handler routine)
1911 * Returns SUCCESS or FAILED.
1914 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1916 MPT_SCSI_HOST * hd;
1917 int status = SUCCESS;
1919 /* If we can't locate the host to reset, then we failed. */
1920 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1921 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1922 "Can't locate host! (sc=%p)\n",
1923 SCpnt ) );
1924 return FAILED;
1927 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1928 hd->ioc->name, SCpnt);
1930 /* If our attempts to reset the host failed, then return a failed
1931 * status. The host will be taken off line by the SCSI mid-layer.
1933 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1934 status = FAILED;
1935 } else {
1936 /* Make sure TM pending is cleared and TM state is set to
1937 * NONE.
1939 hd->tmPending = 0;
1940 hd->tmState = TM_STATE_NONE;
1943 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1944 "Status = %s\n",
1945 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1947 return status;
1950 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1952 * mptscsih_tm_pending_wait - wait for pending task management request to
1953 * complete.
1954 * @hd: Pointer to MPT host structure.
1956 * Returns {SUCCESS,FAILED}.
1958 static int
1959 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1961 unsigned long flags;
1962 int loop_count = 4 * 10; /* Wait 10 seconds */
1963 int status = FAILED;
1965 do {
1966 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1967 if (hd->tmState == TM_STATE_NONE) {
1968 hd->tmState = TM_STATE_IN_PROGRESS;
1969 hd->tmPending = 1;
1970 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1971 status = SUCCESS;
1972 break;
1974 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1975 msleep(250);
1976 } while (--loop_count);
1978 return status;
1981 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1983 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1984 * @hd: Pointer to MPT host structure.
1986 * Returns {SUCCESS,FAILED}.
1988 static int
1989 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
1991 unsigned long flags;
1992 int loop_count = 4 * timeout;
1993 int status = FAILED;
1995 do {
1996 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1997 if(hd->tmPending == 0) {
1998 status = SUCCESS;
1999 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2000 break;
2002 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2003 msleep(250);
2004 } while (--loop_count);
2006 return status;
2009 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2010 static void
2011 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2013 char *desc;
2015 switch (response_code) {
2016 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2017 desc = "The task completed.";
2018 break;
2019 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2020 desc = "The IOC received an invalid frame status.";
2021 break;
2022 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2023 desc = "The task type is not supported.";
2024 break;
2025 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2026 desc = "The requested task failed.";
2027 break;
2028 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2029 desc = "The task completed successfully.";
2030 break;
2031 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2032 desc = "The LUN request is invalid.";
2033 break;
2034 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2035 desc = "The task is in the IOC queue and has not been sent to target.";
2036 break;
2037 default:
2038 desc = "unknown";
2039 break;
2041 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2042 ioc->name, response_code, desc);
2045 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2047 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2048 * @ioc: Pointer to MPT_ADAPTER structure
2049 * @mf: Pointer to SCSI task mgmt request frame
2050 * @mr: Pointer to SCSI task mgmt reply frame
2052 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2053 * of any SCSI task management request.
2054 * This routine is registered with the MPT (base) driver at driver
2055 * load/init time via the mpt_register() API call.
2057 * Returns 1 indicating alloc'd request frame ptr should be freed.
2060 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2062 SCSITaskMgmtReply_t *pScsiTmReply;
2063 SCSITaskMgmt_t *pScsiTmReq;
2064 MPT_SCSI_HOST *hd;
2065 unsigned long flags;
2066 u16 iocstatus;
2067 u8 tmType;
2069 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2070 ioc->name, mf, mr));
2071 if (ioc->sh) {
2072 /* Depending on the thread, a timer is activated for
2073 * the TM request. Delete this timer on completion of TM.
2074 * Decrement count of outstanding TM requests.
2076 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2077 } else {
2078 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
2079 ioc->name));
2080 return 1;
2083 if (mr == NULL) {
2084 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
2085 ioc->name, mf));
2086 return 1;
2087 } else {
2088 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2089 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2091 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2092 tmType = pScsiTmReq->TaskType;
2094 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2095 pScsiTmReply->ResponseCode)
2096 mptscsih_taskmgmt_response_code(ioc,
2097 pScsiTmReply->ResponseCode);
2099 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
2100 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2101 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2103 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2104 hd->tm_iocstatus = iocstatus;
2105 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2106 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2107 /* Error? (anything non-zero?) */
2108 if (iocstatus) {
2110 /* clear flags and continue.
2112 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2113 hd->abortSCpnt = NULL;
2115 /* If an internal command is present
2116 * or the TM failed - reload the FW.
2117 * FC FW may respond FAILED to an ABORT
2119 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2120 if ((hd->cmdPtr) ||
2121 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
2122 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2123 printk((KERN_WARNING
2124 " Firmware Reload FAILED!!\n"));
2128 } else {
2129 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2131 hd->abortSCpnt = NULL;
2136 spin_lock_irqsave(&ioc->FreeQlock, flags);
2137 hd->tmPending = 0;
2138 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2139 hd->tmState = TM_STATE_NONE;
2141 return 1;
2144 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2146 * This is anyones guess quite frankly.
2149 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2150 sector_t capacity, int geom[])
2152 int heads;
2153 int sectors;
2154 sector_t cylinders;
2155 ulong dummy;
2157 heads = 64;
2158 sectors = 32;
2160 dummy = heads * sectors;
2161 cylinders = capacity;
2162 sector_div(cylinders,dummy);
2165 * Handle extended translation size for logical drives
2166 * > 1Gb
2168 if ((ulong)capacity >= 0x200000) {
2169 heads = 255;
2170 sectors = 63;
2171 dummy = heads * sectors;
2172 cylinders = capacity;
2173 sector_div(cylinders,dummy);
2176 /* return result */
2177 geom[0] = heads;
2178 geom[1] = sectors;
2179 geom[2] = cylinders;
2181 dprintk((KERN_NOTICE
2182 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2183 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
2185 return 0;
2188 /* Search IOC page 3 to determine if this is hidden physical disk
2192 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
2194 int i;
2196 if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
2197 return 0;
2198 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2199 if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
2200 return 1;
2202 return 0;
2204 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2207 mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid)
2209 int i;
2211 if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3)
2212 return -ENXIO;
2214 for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2215 if (physdiskid ==
2216 hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
2217 return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2220 return -ENXIO;
2222 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2224 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2226 * OS entry point to allow host driver to alloc memory
2227 * for each scsi target. Called once per device the bus scan.
2228 * Return non-zero if allocation fails.
2231 mptscsih_target_alloc(struct scsi_target *starget)
2233 VirtTarget *vtarget;
2235 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
2236 if (!vtarget)
2237 return -ENOMEM;
2238 starget->hostdata = vtarget;
2239 vtarget->starget = starget;
2240 return 0;
2243 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2245 * OS entry point to allow host driver to alloc memory
2246 * for each scsi device. Called once per device the bus scan.
2247 * Return non-zero if allocation fails.
2250 mptscsih_slave_alloc(struct scsi_device *sdev)
2252 struct Scsi_Host *host = sdev->host;
2253 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2254 VirtTarget *vtarget;
2255 VirtDevice *vdev;
2256 struct scsi_target *starget;
2258 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
2259 if (!vdev) {
2260 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
2261 hd->ioc->name, sizeof(VirtDevice));
2262 return -ENOMEM;
2265 vdev->lun = sdev->lun;
2266 sdev->hostdata = vdev;
2268 starget = scsi_target(sdev);
2269 vtarget = starget->hostdata;
2271 vdev->vtarget = vtarget;
2273 if (vtarget->num_luns == 0) {
2274 hd->Targets[sdev->id] = vtarget;
2275 vtarget->ioc_id = hd->ioc->id;
2276 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
2277 vtarget->target_id = sdev->id;
2278 vtarget->bus_id = sdev->channel;
2279 if (hd->ioc->bus_type == SPI && sdev->channel == 0 &&
2280 hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
2281 vtarget->raidVolume = 1;
2282 ddvtprintk((KERN_INFO
2283 "RAID Volume @ id %d\n", sdev->id));
2286 vtarget->num_luns++;
2287 return 0;
2291 * OS entry point to allow for host driver to free allocated memory
2292 * Called if no device present or device being unloaded
2294 void
2295 mptscsih_target_destroy(struct scsi_target *starget)
2297 if (starget->hostdata)
2298 kfree(starget->hostdata);
2299 starget->hostdata = NULL;
2303 * OS entry point to allow for host driver to free allocated memory
2304 * Called if no device present or device being unloaded
2306 void
2307 mptscsih_slave_destroy(struct scsi_device *sdev)
2309 struct Scsi_Host *host = sdev->host;
2310 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2311 VirtTarget *vtarget;
2312 VirtDevice *vdevice;
2313 struct scsi_target *starget;
2315 starget = scsi_target(sdev);
2316 vtarget = starget->hostdata;
2317 vdevice = sdev->hostdata;
2319 mptscsih_search_running_cmds(hd, vdevice);
2320 vtarget->luns[0] &= ~(1 << vdevice->lun);
2321 vtarget->num_luns--;
2322 if (vtarget->num_luns == 0) {
2323 hd->Targets[sdev->id] = NULL;
2325 mptscsih_synchronize_cache(hd, vdevice);
2326 kfree(vdevice);
2327 sdev->hostdata = NULL;
2330 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2332 * mptscsih_change_queue_depth - This function will set a devices queue depth
2333 * @sdev: per scsi_device pointer
2334 * @qdepth: requested queue depth
2336 * Adding support for new 'change_queue_depth' api.
2339 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2341 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2342 VirtTarget *vtarget;
2343 struct scsi_target *starget;
2344 int max_depth;
2345 int tagged;
2347 starget = scsi_target(sdev);
2348 vtarget = starget->hostdata;
2350 if (hd->ioc->bus_type == SPI) {
2351 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2352 max_depth = 1;
2353 else if (sdev->type == TYPE_DISK &&
2354 vtarget->minSyncFactor <= MPT_ULTRA160)
2355 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2356 else
2357 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2358 } else
2359 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2361 if (qdepth > max_depth)
2362 qdepth = max_depth;
2363 if (qdepth == 1)
2364 tagged = 0;
2365 else
2366 tagged = MSG_SIMPLE_TAG;
2368 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2369 return sdev->queue_depth;
2373 * OS entry point to adjust the queue_depths on a per-device basis.
2374 * Called once per device the bus scan. Use it to force the queue_depth
2375 * member to 1 if a device does not support Q tags.
2376 * Return non-zero if fails.
2379 mptscsih_slave_configure(struct scsi_device *sdev)
2381 struct Scsi_Host *sh = sdev->host;
2382 VirtTarget *vtarget;
2383 VirtDevice *vdevice;
2384 struct scsi_target *starget;
2385 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2386 int indexed_lun, lun_index;
2388 starget = scsi_target(sdev);
2389 vtarget = starget->hostdata;
2390 vdevice = sdev->hostdata;
2392 dsprintk((MYIOC_s_INFO_FMT
2393 "device @ %p, id=%d, LUN=%d, channel=%d\n",
2394 hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
2395 if (hd->ioc->bus_type == SPI)
2396 dsprintk((MYIOC_s_INFO_FMT
2397 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2398 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2399 sdev->ppr, sdev->inquiry_len));
2401 if (sdev->id > sh->max_id) {
2402 /* error case, should never happen */
2403 scsi_adjust_queue_depth(sdev, 0, 1);
2404 goto slave_configure_exit;
2407 vdevice->configured_lun=1;
2408 lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */
2409 indexed_lun = (vdevice->lun % 32);
2410 vtarget->luns[lun_index] |= (1 << indexed_lun);
2411 mptscsih_initTarget(hd, vtarget, sdev);
2412 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2414 dsprintk((MYIOC_s_INFO_FMT
2415 "Queue depth=%d, tflags=%x\n",
2416 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2418 if (hd->ioc->bus_type == SPI)
2419 dsprintk((MYIOC_s_INFO_FMT
2420 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2421 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2422 vtarget->minSyncFactor));
2424 slave_configure_exit:
2426 dsprintk((MYIOC_s_INFO_FMT
2427 "tagged %d, simple %d, ordered %d\n",
2428 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2429 sdev->ordered_tags));
2431 return 0;
2434 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2436 * Private routines...
2439 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2440 /* Utility function to copy sense data from the scsi_cmnd buffer
2441 * to the FC and SCSI target structures.
2444 static void
2445 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2447 VirtDevice *vdev;
2448 SCSIIORequest_t *pReq;
2449 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2451 /* Get target structure
2453 pReq = (SCSIIORequest_t *) mf;
2454 vdev = sc->device->hostdata;
2456 if (sense_count) {
2457 u8 *sense_data;
2458 int req_index;
2460 /* Copy the sense received into the scsi command block. */
2461 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2462 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2463 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2465 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2467 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2468 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2469 int idx;
2470 MPT_ADAPTER *ioc = hd->ioc;
2472 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2473 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2474 ioc->events[idx].eventContext = ioc->eventContext;
2476 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2477 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2478 (sc->device->channel << 8) || sc->device->id;
2480 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2482 ioc->eventContext++;
2483 if (hd->ioc->pcidev->vendor ==
2484 PCI_VENDOR_ID_IBM) {
2485 mptscsih_issue_sep_command(hd->ioc,
2486 vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2487 vdev->vtarget->tflags |=
2488 MPT_TARGET_FLAGS_LED_ON;
2492 } else {
2493 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2494 hd->ioc->name));
2498 static int
2499 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2501 MPT_SCSI_HOST *hd;
2502 int i;
2504 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2506 for (i = 0; i < hd->ioc->req_depth; i++) {
2507 if (hd->ScsiLookup[i] == sc) {
2508 return i;
2512 return -1;
2515 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2517 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2519 MPT_SCSI_HOST *hd;
2520 unsigned long flags;
2521 int ii;
2523 dtmprintk((KERN_WARNING MYNAM
2524 ": IOC %s_reset routed to SCSI host driver!\n",
2525 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2526 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2528 /* If a FW reload request arrives after base installed but
2529 * before all scsi hosts have been attached, then an alt_ioc
2530 * may have a NULL sh pointer.
2532 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2533 return 0;
2534 else
2535 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2537 if (reset_phase == MPT_IOC_SETUP_RESET) {
2538 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2540 /* Clean Up:
2541 * 1. Set Hard Reset Pending Flag
2542 * All new commands go to doneQ
2544 hd->resetPending = 1;
2546 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2547 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2549 /* 2. Flush running commands
2550 * Clean ScsiLookup (and associated memory)
2551 * AND clean mytaskQ
2554 /* 2b. Reply to OS all known outstanding I/O commands.
2556 mptscsih_flush_running_cmds(hd);
2558 /* 2c. If there was an internal command that
2559 * has not completed, configuration or io request,
2560 * free these resources.
2562 if (hd->cmdPtr) {
2563 del_timer(&hd->timer);
2564 mpt_free_msg_frame(ioc, hd->cmdPtr);
2567 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2569 } else {
2570 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2572 /* Once a FW reload begins, all new OS commands are
2573 * redirected to the doneQ w/ a reset status.
2574 * Init all control structures.
2577 /* ScsiLookup initialization
2579 for (ii=0; ii < hd->ioc->req_depth; ii++)
2580 hd->ScsiLookup[ii] = NULL;
2582 /* 2. Chain Buffer initialization
2585 /* 4. Renegotiate to all devices, if SPI
2588 /* 5. Enable new commands to be posted
2590 spin_lock_irqsave(&ioc->FreeQlock, flags);
2591 hd->tmPending = 0;
2592 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2593 hd->resetPending = 0;
2594 hd->tmState = TM_STATE_NONE;
2596 /* 6. If there was an internal command,
2597 * wake this process up.
2599 if (hd->cmdPtr) {
2601 * Wake up the original calling thread
2603 hd->pLocal = &hd->localReply;
2604 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2605 hd->scandv_wait_done = 1;
2606 wake_up(&hd->scandv_waitq);
2607 hd->cmdPtr = NULL;
2610 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2614 return 1; /* currently means nothing really */
2617 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2619 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2621 MPT_SCSI_HOST *hd;
2622 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2624 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2625 ioc->name, event));
2627 if (ioc->sh == NULL ||
2628 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2629 return 1;
2631 switch (event) {
2632 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2633 /* FIXME! */
2634 break;
2635 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2636 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2637 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2638 hd->soft_resets++;
2639 break;
2640 case MPI_EVENT_LOGOUT: /* 09 */
2641 /* FIXME! */
2642 break;
2644 case MPI_EVENT_RESCAN: /* 06 */
2645 break;
2648 * CHECKME! Don't think we need to do
2649 * anything for these, but...
2651 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2652 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2654 * CHECKME! Falling thru...
2656 break;
2658 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2659 break;
2661 case MPI_EVENT_NONE: /* 00 */
2662 case MPI_EVENT_LOG_DATA: /* 01 */
2663 case MPI_EVENT_STATE_CHANGE: /* 02 */
2664 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2665 default:
2666 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2667 break;
2670 return 1; /* currently means nothing really */
2673 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2675 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2676 * @hd: Pointer to MPT_SCSI_HOST structure
2677 * @vtarget: per target private data
2678 * @sdev: SCSI device
2680 * NOTE: It's only SAFE to call this routine if data points to
2681 * sane & valid STANDARD INQUIRY data!
2683 * Allocate and initialize memory for this target.
2684 * Save inquiry data.
2687 static void
2688 mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
2689 struct scsi_device *sdev)
2691 dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
2692 hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd));
2694 /* Is LUN supported? If so, upper 2 bits will be 0
2695 * in first byte of inquiry data.
2697 if (sdev->inq_periph_qual != 0)
2698 return;
2700 if (vtarget == NULL)
2701 return;
2703 vtarget->type = sdev->type;
2705 if (hd->ioc->bus_type != SPI)
2706 return;
2708 if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
2709 /* Treat all Processors as SAF-TE if
2710 * command line option is set */
2711 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2712 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
2713 }else if ((sdev->type == TYPE_PROCESSOR) &&
2714 !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
2715 if (sdev->inquiry_len > 49 ) {
2716 if (sdev->inquiry[44] == 'S' &&
2717 sdev->inquiry[45] == 'A' &&
2718 sdev->inquiry[46] == 'F' &&
2719 sdev->inquiry[47] == '-' &&
2720 sdev->inquiry[48] == 'T' &&
2721 sdev->inquiry[49] == 'E' ) {
2722 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2723 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
2727 mptscsih_setTargetNegoParms(hd, vtarget, sdev);
2730 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2732 * Update the target negotiation parameters based on the
2733 * the Inquiry data, adapter capabilities, and NVRAM settings.
2736 static void
2737 mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
2738 struct scsi_device *sdev)
2740 SpiCfgData *pspi_data = &hd->ioc->spi_data;
2741 int id = (int) target->target_id;
2742 int nvram;
2743 u8 width = MPT_NARROW;
2744 u8 factor = MPT_ASYNC;
2745 u8 offset = 0;
2746 u8 nfactor;
2747 u8 noQas = 1;
2749 target->negoFlags = pspi_data->noQas;
2751 /* noQas == 0 => device supports QAS. */
2753 if (sdev->scsi_level < SCSI_2) {
2754 width = 0;
2755 factor = MPT_ULTRA2;
2756 offset = pspi_data->maxSyncOffset;
2757 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2758 } else {
2759 if (scsi_device_wide(sdev)) {
2760 width = 1;
2763 if (scsi_device_sync(sdev)) {
2764 factor = pspi_data->minSyncFactor;
2765 if (!scsi_device_dt(sdev))
2766 factor = MPT_ULTRA2;
2767 else {
2768 if (!scsi_device_ius(sdev) &&
2769 !scsi_device_qas(sdev))
2770 factor = MPT_ULTRA160;
2771 else {
2772 factor = MPT_ULTRA320;
2773 if (scsi_device_qas(sdev)) {
2774 ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
2775 noQas = 0;
2777 if (sdev->type == TYPE_TAPE &&
2778 scsi_device_ius(sdev))
2779 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2782 offset = pspi_data->maxSyncOffset;
2784 /* If RAID, never disable QAS
2785 * else if non RAID, do not disable
2786 * QAS if bit 1 is set
2787 * bit 1 QAS support, non-raid only
2788 * bit 0 IU support
2790 if (target->raidVolume == 1) {
2791 noQas = 0;
2793 } else {
2794 factor = MPT_ASYNC;
2795 offset = 0;
2799 if (!sdev->tagged_supported) {
2800 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2803 /* Update tflags based on NVRAM settings. (SCSI only)
2805 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2806 nvram = pspi_data->nvram[id];
2807 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2809 if (width)
2810 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2812 if (offset > 0) {
2813 /* Ensure factor is set to the
2814 * maximum of: adapter, nvram, inquiry
2816 if (nfactor) {
2817 if (nfactor < pspi_data->minSyncFactor )
2818 nfactor = pspi_data->minSyncFactor;
2820 factor = max(factor, nfactor);
2821 if (factor == MPT_ASYNC)
2822 offset = 0;
2823 } else {
2824 offset = 0;
2825 factor = MPT_ASYNC;
2827 } else {
2828 factor = MPT_ASYNC;
2832 /* Make sure data is consistent
2834 if ((!width) && (factor < MPT_ULTRA2)) {
2835 factor = MPT_ULTRA2;
2838 /* Save the data to the target structure.
2840 target->minSyncFactor = factor;
2841 target->maxOffset = offset;
2842 target->maxWidth = width;
2844 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2846 /* Disable unused features.
2848 if (!width)
2849 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2851 if (!offset)
2852 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2854 if ( factor > MPT_ULTRA320 )
2855 noQas = 0;
2857 if (noQas && (pspi_data->noQas == 0)) {
2858 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2859 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2861 /* Disable QAS in a mixed configuration case
2864 ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
2868 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2870 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2872 * SCSI Config Page functionality ...
2875 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2876 /* mptscsih_writeIOCPage4 - write IOC Page 4
2877 * @hd: Pointer to a SCSI Host Structure
2878 * @target_id: write IOC Page4 for this ID & Bus
2880 * Return: -EAGAIN if unable to obtain a Message Frame
2881 * or 0 if success.
2883 * Remark: We do not wait for a return, write pages sequentially.
2885 static int
2886 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
2888 MPT_ADAPTER *ioc = hd->ioc;
2889 Config_t *pReq;
2890 IOCPage4_t *IOCPage4Ptr;
2891 MPT_FRAME_HDR *mf;
2892 dma_addr_t dataDma;
2893 u16 req_idx;
2894 u32 frameOffset;
2895 u32 flagsLength;
2896 int ii;
2898 /* Get a MF for this command.
2900 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
2901 dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
2902 ioc->name));
2903 return -EAGAIN;
2906 /* Set the request and the data pointers.
2907 * Place data at end of MF.
2909 pReq = (Config_t *)mf;
2911 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2912 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
2914 /* Complete the request frame (same for all requests).
2916 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2917 pReq->Reserved = 0;
2918 pReq->ChainOffset = 0;
2919 pReq->Function = MPI_FUNCTION_CONFIG;
2920 pReq->ExtPageLength = 0;
2921 pReq->ExtPageType = 0;
2922 pReq->MsgFlags = 0;
2923 for (ii=0; ii < 8; ii++) {
2924 pReq->Reserved2[ii] = 0;
2927 IOCPage4Ptr = ioc->spi_data.pIocPg4;
2928 dataDma = ioc->spi_data.IocPg4_dma;
2929 ii = IOCPage4Ptr->ActiveSEP++;
2930 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
2931 IOCPage4Ptr->SEP[ii].SEPBus = bus;
2932 pReq->Header = IOCPage4Ptr->Header;
2933 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
2935 /* Add a SGE to the config request.
2937 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
2938 (IOCPage4Ptr->Header.PageLength + ii) * 4;
2940 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
2942 dinitprintk((MYIOC_s_INFO_FMT
2943 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
2944 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
2946 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
2948 return 0;
2951 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2953 * Bus Scan and Domain Validation functionality ...
2956 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2958 * mptscsih_scandv_complete - Scan and DV callback routine registered
2959 * to Fustion MPT (base) driver.
2961 * @ioc: Pointer to MPT_ADAPTER structure
2962 * @mf: Pointer to original MPT request frame
2963 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2965 * This routine is called from mpt.c::mpt_interrupt() at the completion
2966 * of any SCSI IO request.
2967 * This routine is registered with the Fusion MPT (base) driver at driver
2968 * load/init time via the mpt_register() API call.
2970 * Returns 1 indicating alloc'd request frame ptr should be freed.
2972 * Remark: Sets a completion code and (possibly) saves sense data
2973 * in the IOC member localReply structure.
2974 * Used ONLY for DV and other internal commands.
2977 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2979 MPT_SCSI_HOST *hd;
2980 SCSIIORequest_t *pReq;
2981 int completionCode;
2982 u16 req_idx;
2984 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2986 if ((mf == NULL) ||
2987 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
2988 printk(MYIOC_s_ERR_FMT
2989 "ScanDvComplete, %s req frame ptr! (=%p)\n",
2990 ioc->name, mf?"BAD":"NULL", (void *) mf);
2991 goto wakeup;
2994 del_timer(&hd->timer);
2995 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2996 hd->ScsiLookup[req_idx] = NULL;
2997 pReq = (SCSIIORequest_t *) mf;
2999 if (mf != hd->cmdPtr) {
3000 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3001 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
3003 hd->cmdPtr = NULL;
3005 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3006 hd->ioc->name, mf, mr, req_idx));
3008 hd->pLocal = &hd->localReply;
3009 hd->pLocal->scsiStatus = 0;
3011 /* If target struct exists, clear sense valid flag.
3013 if (mr == NULL) {
3014 completionCode = MPT_SCANDV_GOOD;
3015 } else {
3016 SCSIIOReply_t *pReply;
3017 u16 status;
3018 u8 scsi_status;
3020 pReply = (SCSIIOReply_t *) mr;
3022 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3023 scsi_status = pReply->SCSIStatus;
3025 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3026 status, pReply->SCSIState, scsi_status,
3027 le32_to_cpu(pReply->IOCLogInfo)));
3029 switch(status) {
3031 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
3032 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3033 break;
3035 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
3036 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
3037 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
3038 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
3039 completionCode = MPT_SCANDV_DID_RESET;
3040 break;
3042 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
3043 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
3044 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
3045 if (pReply->Function == MPI_FUNCTION_CONFIG) {
3046 ConfigReply_t *pr = (ConfigReply_t *)mr;
3047 completionCode = MPT_SCANDV_GOOD;
3048 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
3049 hd->pLocal->header.PageLength = pr->Header.PageLength;
3050 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
3051 hd->pLocal->header.PageType = pr->Header.PageType;
3053 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
3054 /* If the RAID Volume request is successful,
3055 * return GOOD, else indicate that
3056 * some type of error occurred.
3058 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
3059 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
3060 completionCode = MPT_SCANDV_GOOD;
3061 else
3062 completionCode = MPT_SCANDV_SOME_ERROR;
3063 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
3065 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3066 u8 *sense_data;
3067 int sz;
3069 /* save sense data in global structure
3071 completionCode = MPT_SCANDV_SENSE;
3072 hd->pLocal->scsiStatus = scsi_status;
3073 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
3074 (req_idx * MPT_SENSE_BUFFER_ALLOC));
3076 sz = min_t(int, pReq->SenseBufferLength,
3077 SCSI_STD_SENSE_BYTES);
3078 memcpy(hd->pLocal->sense, sense_data, sz);
3080 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
3081 sense_data));
3082 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
3083 if (pReq->CDB[0] == INQUIRY)
3084 completionCode = MPT_SCANDV_ISSUE_SENSE;
3085 else
3086 completionCode = MPT_SCANDV_DID_RESET;
3088 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
3089 completionCode = MPT_SCANDV_DID_RESET;
3090 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3091 completionCode = MPT_SCANDV_DID_RESET;
3092 else {
3093 completionCode = MPT_SCANDV_GOOD;
3094 hd->pLocal->scsiStatus = scsi_status;
3096 break;
3098 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
3099 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3100 completionCode = MPT_SCANDV_DID_RESET;
3101 else
3102 completionCode = MPT_SCANDV_SOME_ERROR;
3103 break;
3105 default:
3106 completionCode = MPT_SCANDV_SOME_ERROR;
3107 break;
3109 } /* switch(status) */
3111 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
3112 completionCode));
3113 } /* end of address reply case */
3115 hd->pLocal->completion = completionCode;
3117 /* MF and RF are freed in mpt_interrupt
3119 wakeup:
3120 /* Free Chain buffers (will never chain) in scan or dv */
3121 //mptscsih_freeChainBuffers(ioc, req_idx);
3124 * Wake up the original calling thread
3126 hd->scandv_wait_done = 1;
3127 wake_up(&hd->scandv_waitq);
3129 return 1;
3132 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3133 /* mptscsih_timer_expired - Call back for timer process.
3134 * Used only for dv functionality.
3135 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3138 void
3139 mptscsih_timer_expired(unsigned long data)
3141 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3143 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3145 if (hd->cmdPtr) {
3146 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3148 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3149 /* Desire to issue a task management request here.
3150 * TM requests MUST be single threaded.
3151 * If old eh code and no TM current, issue request.
3152 * If new eh code, do nothing. Wait for OS cmd timeout
3153 * for bus reset.
3155 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3156 } else {
3157 /* Perform a FW reload */
3158 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3159 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3162 } else {
3163 /* This should NEVER happen */
3164 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3167 /* No more processing.
3168 * TM call will generate an interrupt for SCSI TM Management.
3169 * The FW will reply to all outstanding commands, callback will finish cleanup.
3170 * Hard reset clean-up will free all resources.
3172 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3174 return;
3178 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3180 * mptscsih_do_cmd - Do internal command.
3181 * @hd: MPT_SCSI_HOST pointer
3182 * @io: INTERNAL_CMD pointer.
3184 * Issue the specified internally generated command and do command
3185 * specific cleanup. For bus scan / DV only.
3186 * NOTES: If command is Inquiry and status is good,
3187 * initialize a target structure, save the data
3189 * Remark: Single threaded access only.
3191 * Return:
3192 * < 0 if an illegal command or no resources
3194 * 0 if good
3196 * > 0 if command complete but some type of completion error.
3198 static int
3199 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3201 MPT_FRAME_HDR *mf;
3202 SCSIIORequest_t *pScsiReq;
3203 SCSIIORequest_t ReqCopy;
3204 int my_idx, ii, dir;
3205 int rc, cmdTimeout;
3206 int in_isr;
3207 char cmdLen;
3208 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3209 char cmd = io->cmd;
3211 in_isr = in_interrupt();
3212 if (in_isr) {
3213 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3214 hd->ioc->name));
3215 return -EPERM;
3219 /* Set command specific information
3221 switch (cmd) {
3222 case INQUIRY:
3223 cmdLen = 6;
3224 dir = MPI_SCSIIO_CONTROL_READ;
3225 CDB[0] = cmd;
3226 CDB[4] = io->size;
3227 cmdTimeout = 10;
3228 break;
3230 case TEST_UNIT_READY:
3231 cmdLen = 6;
3232 dir = MPI_SCSIIO_CONTROL_READ;
3233 cmdTimeout = 10;
3234 break;
3236 case START_STOP:
3237 cmdLen = 6;
3238 dir = MPI_SCSIIO_CONTROL_READ;
3239 CDB[0] = cmd;
3240 CDB[4] = 1; /*Spin up the disk */
3241 cmdTimeout = 15;
3242 break;
3244 case REQUEST_SENSE:
3245 cmdLen = 6;
3246 CDB[0] = cmd;
3247 CDB[4] = io->size;
3248 dir = MPI_SCSIIO_CONTROL_READ;
3249 cmdTimeout = 10;
3250 break;
3252 case READ_BUFFER:
3253 cmdLen = 10;
3254 dir = MPI_SCSIIO_CONTROL_READ;
3255 CDB[0] = cmd;
3256 if (io->flags & MPT_ICFLAG_ECHO) {
3257 CDB[1] = 0x0A;
3258 } else {
3259 CDB[1] = 0x02;
3262 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3263 CDB[1] |= 0x01;
3265 CDB[6] = (io->size >> 16) & 0xFF;
3266 CDB[7] = (io->size >> 8) & 0xFF;
3267 CDB[8] = io->size & 0xFF;
3268 cmdTimeout = 10;
3269 break;
3271 case WRITE_BUFFER:
3272 cmdLen = 10;
3273 dir = MPI_SCSIIO_CONTROL_WRITE;
3274 CDB[0] = cmd;
3275 if (io->flags & MPT_ICFLAG_ECHO) {
3276 CDB[1] = 0x0A;
3277 } else {
3278 CDB[1] = 0x02;
3280 CDB[6] = (io->size >> 16) & 0xFF;
3281 CDB[7] = (io->size >> 8) & 0xFF;
3282 CDB[8] = io->size & 0xFF;
3283 cmdTimeout = 10;
3284 break;
3286 case RESERVE:
3287 cmdLen = 6;
3288 dir = MPI_SCSIIO_CONTROL_READ;
3289 CDB[0] = cmd;
3290 cmdTimeout = 10;
3291 break;
3293 case RELEASE:
3294 cmdLen = 6;
3295 dir = MPI_SCSIIO_CONTROL_READ;
3296 CDB[0] = cmd;
3297 cmdTimeout = 10;
3298 break;
3300 case SYNCHRONIZE_CACHE:
3301 cmdLen = 10;
3302 dir = MPI_SCSIIO_CONTROL_READ;
3303 CDB[0] = cmd;
3304 // CDB[1] = 0x02; /* set immediate bit */
3305 cmdTimeout = 10;
3306 break;
3308 default:
3309 /* Error Case */
3310 return -EFAULT;
3313 /* Get and Populate a free Frame
3315 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3316 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3317 hd->ioc->name));
3318 return -EBUSY;
3321 pScsiReq = (SCSIIORequest_t *) mf;
3323 /* Get the request index */
3324 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3325 ADD_INDEX_LOG(my_idx); /* for debug */
3327 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3328 pScsiReq->TargetID = io->physDiskNum;
3329 pScsiReq->Bus = 0;
3330 pScsiReq->ChainOffset = 0;
3331 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3332 } else {
3333 pScsiReq->TargetID = io->id;
3334 pScsiReq->Bus = io->bus;
3335 pScsiReq->ChainOffset = 0;
3336 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3339 pScsiReq->CDBLength = cmdLen;
3340 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3342 pScsiReq->Reserved = 0;
3344 pScsiReq->MsgFlags = mpt_msg_flags();
3345 /* MsgContext set in mpt_get_msg_fram call */
3347 for (ii=0; ii < 8; ii++)
3348 pScsiReq->LUN[ii] = 0;
3349 pScsiReq->LUN[1] = io->lun;
3351 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3352 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3353 else
3354 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3356 if (cmd == REQUEST_SENSE) {
3357 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3358 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3359 hd->ioc->name, cmd));
3362 for (ii=0; ii < 16; ii++)
3363 pScsiReq->CDB[ii] = CDB[ii];
3365 pScsiReq->DataLength = cpu_to_le32(io->size);
3366 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3367 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3369 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3370 hd->ioc->name, cmd, io->bus, io->id, io->lun));
3372 if (dir == MPI_SCSIIO_CONTROL_READ) {
3373 mpt_add_sge((char *) &pScsiReq->SGL,
3374 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3375 io->data_dma);
3376 } else {
3377 mpt_add_sge((char *) &pScsiReq->SGL,
3378 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3379 io->data_dma);
3382 /* The ISR will free the request frame, but we need
3383 * the information to initialize the target. Duplicate.
3385 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3387 /* Issue this command after:
3388 * finish init
3389 * add timer
3390 * Wait until the reply has been received
3391 * ScsiScanDvCtx callback function will
3392 * set hd->pLocal;
3393 * set scandv_wait_done and call wake_up
3395 hd->pLocal = NULL;
3396 hd->timer.expires = jiffies + HZ*cmdTimeout;
3397 hd->scandv_wait_done = 0;
3399 /* Save cmd pointer, for resource free if timeout or
3400 * FW reload occurs
3402 hd->cmdPtr = mf;
3404 add_timer(&hd->timer);
3405 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3406 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3408 if (hd->pLocal) {
3409 rc = hd->pLocal->completion;
3410 hd->pLocal->skip = 0;
3412 /* Always set fatal error codes in some cases.
3414 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3415 rc = -ENXIO;
3416 else if (rc == MPT_SCANDV_SOME_ERROR)
3417 rc = -rc;
3418 } else {
3419 rc = -EFAULT;
3420 /* This should never happen. */
3421 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3422 hd->ioc->name));
3425 return rc;
3428 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3430 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3431 * @hd: Pointer to a SCSI HOST structure
3432 * @vtarget: per device private data
3433 * @lun: lun
3435 * Uses the ISR, but with special processing.
3436 * MUST be single-threaded.
3439 static void
3440 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3442 INTERNAL_CMD iocmd;
3444 /* Following parameters will not change
3445 * in this routine.
3447 iocmd.cmd = SYNCHRONIZE_CACHE;
3448 iocmd.flags = 0;
3449 iocmd.physDiskNum = -1;
3450 iocmd.data = NULL;
3451 iocmd.data_dma = -1;
3452 iocmd.size = 0;
3453 iocmd.rsvd = iocmd.rsvd2 = 0;
3454 iocmd.bus = vdevice->vtarget->bus_id;
3455 iocmd.id = vdevice->vtarget->target_id;
3456 iocmd.lun = (u8)vdevice->lun;
3458 if ((vdevice->vtarget->type == TYPE_DISK) &&
3459 (vdevice->configured_lun))
3460 mptscsih_do_cmd(hd, &iocmd);
3463 EXPORT_SYMBOL(mptscsih_remove);
3464 EXPORT_SYMBOL(mptscsih_shutdown);
3465 #ifdef CONFIG_PM
3466 EXPORT_SYMBOL(mptscsih_suspend);
3467 EXPORT_SYMBOL(mptscsih_resume);
3468 #endif
3469 EXPORT_SYMBOL(mptscsih_proc_info);
3470 EXPORT_SYMBOL(mptscsih_info);
3471 EXPORT_SYMBOL(mptscsih_qcmd);
3472 EXPORT_SYMBOL(mptscsih_target_alloc);
3473 EXPORT_SYMBOL(mptscsih_slave_alloc);
3474 EXPORT_SYMBOL(mptscsih_target_destroy);
3475 EXPORT_SYMBOL(mptscsih_slave_destroy);
3476 EXPORT_SYMBOL(mptscsih_slave_configure);
3477 EXPORT_SYMBOL(mptscsih_abort);
3478 EXPORT_SYMBOL(mptscsih_dev_reset);
3479 EXPORT_SYMBOL(mptscsih_bus_reset);
3480 EXPORT_SYMBOL(mptscsih_host_reset);
3481 EXPORT_SYMBOL(mptscsih_bios_param);
3482 EXPORT_SYMBOL(mptscsih_io_done);
3483 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3484 EXPORT_SYMBOL(mptscsih_scandv_complete);
3485 EXPORT_SYMBOL(mptscsih_event_process);
3486 EXPORT_SYMBOL(mptscsih_ioc_reset);
3487 EXPORT_SYMBOL(mptscsih_change_queue_depth);
3488 EXPORT_SYMBOL(mptscsih_timer_expired);
3489 EXPORT_SYMBOL(mptscsih_TMHandler);
3491 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/