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)
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.
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>
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME "Fusion MPT SCSI Host driver"
72 #define my_VERSION MPT_LINUX_VERSION_COMMON
73 #define MYNAM "mptscsih"
75 MODULE_AUTHOR(MODULEAUTHOR);
76 MODULE_DESCRIPTION(my_NAME);
77 MODULE_LICENSE("GPL");
79 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
81 typedef struct _BIG_SENSE_BUF {
82 u8 data[MPT_SENSE_BUFFER_ALLOC];
85 #define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
86 #define MPT_SCANDV_DID_RESET (0x00000001)
87 #define MPT_SCANDV_SENSE (0x00000002)
88 #define MPT_SCANDV_SOME_ERROR (0x00000004)
89 #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
90 #define MPT_SCANDV_ISSUE_SENSE (0x00000010)
91 #define MPT_SCANDV_FALLBACK (0x00000020)
93 #define MPT_SCANDV_MAX_RETRIES (10)
95 #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
96 #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
97 #define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */
98 #define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */
99 #define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */
100 #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
101 #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
103 typedef struct _internal_cmd {
104 char *data; /* data pointer */
105 dma_addr_t data_dma; /* data dma address */
106 int size; /* transfer size */
107 u8 cmd; /* SCSI Op Code */
108 u8 bus; /* bus number */
109 u8 id; /* SCSI ID (virtual) */
111 u8 flags; /* Bit Field - See above */
112 u8 physDiskNum; /* Phys disk number, -1 else */
117 typedef struct _negoparms {
124 typedef struct _dv_parameters {
133 * Other private/forward protos...
135 int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
136 static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
137 int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
139 static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
140 SCSIIORequest_t *pReq, int req_idx);
141 static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
142 static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
143 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
144 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
145 static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
147 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
149 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
150 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
152 static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen);
153 static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, char byte56);
154 static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
155 static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc);
156 static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
157 static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
158 int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
159 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
160 static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
161 static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget);
162 static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
164 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
165 static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
166 static void mptscsih_domainValidation(void *hd);
167 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
168 static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
169 static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
170 static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
171 static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id);
172 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc);
175 void mptscsih_remove(struct pci_dev *);
176 void mptscsih_shutdown(struct pci_dev *);
178 int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
179 int mptscsih_resume(struct pci_dev *pdev);
182 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
184 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
186 * Domain Validation task structure
188 static DEFINE_SPINLOCK(dvtaskQ_lock);
189 static int dvtaskQ_active = 0;
190 static int dvtaskQ_release = 0;
191 static struct work_struct dvTaskQ_task;
194 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
196 * mptscsih_add_sge - Place a simple SGE at address pAddr.
197 * @pAddr: virtual address for SGE
198 * @flagslength: SGE flags and data transfer length
199 * @dma_addr: Physical address
201 * This routine places a MPT request frame back on the MPT adapter's
205 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
207 if (sizeof(dma_addr_t) == sizeof(u64)) {
208 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
209 u32 tmp = dma_addr & 0xFFFFFFFF;
211 pSge->FlagsLength = cpu_to_le32(flagslength);
212 pSge->Address.Low = cpu_to_le32(tmp);
213 tmp = (u32) ((u64)dma_addr >> 32);
214 pSge->Address.High = cpu_to_le32(tmp);
217 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
218 pSge->FlagsLength = cpu_to_le32(flagslength);
219 pSge->Address = cpu_to_le32(dma_addr);
221 } /* mptscsih_add_sge() */
223 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
225 * mptscsih_add_chain - Place a chain SGE at address pAddr.
226 * @pAddr: virtual address for SGE
227 * @next: nextChainOffset value (u32's)
228 * @length: length of next SGL segment
229 * @dma_addr: Physical address
231 * This routine places a MPT request frame back on the MPT adapter's
235 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
237 if (sizeof(dma_addr_t) == sizeof(u64)) {
238 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
239 u32 tmp = dma_addr & 0xFFFFFFFF;
241 pChain->Length = cpu_to_le16(length);
242 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
244 pChain->NextChainOffset = next;
246 pChain->Address.Low = cpu_to_le32(tmp);
247 tmp = (u32) ((u64)dma_addr >> 32);
248 pChain->Address.High = cpu_to_le32(tmp);
250 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
251 pChain->Length = cpu_to_le16(length);
252 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
253 pChain->NextChainOffset = next;
254 pChain->Address = cpu_to_le32(dma_addr);
256 } /* mptscsih_add_chain() */
258 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
260 * mptscsih_getFreeChainBuffer - Function to get a free chain
261 * from the MPT_SCSI_HOST FreeChainQ.
262 * @ioc: Pointer to MPT_ADAPTER structure
263 * @req_idx: Index of the SCSI IO request frame. (output)
265 * return SUCCESS or FAILED
268 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
270 MPT_FRAME_HDR *chainBuf;
275 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
277 spin_lock_irqsave(&ioc->FreeQlock, flags);
278 if (!list_empty(&ioc->FreeChainQ)) {
281 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
282 u.frame.linkage.list);
283 list_del(&chainBuf->u.frame.linkage.list);
284 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
285 chain_idx = offset / ioc->req_sz;
287 dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
288 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
291 chain_idx = MPT_HOST_NO_CHAIN;
292 dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
295 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
297 *retIndex = chain_idx;
299 } /* mptscsih_getFreeChainBuffer() */
301 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
303 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
304 * SCSIIORequest_t Message Frame.
305 * @ioc: Pointer to MPT_ADAPTER structure
306 * @SCpnt: Pointer to scsi_cmnd structure
307 * @pReq: Pointer to SCSIIORequest_t structure
312 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
313 SCSIIORequest_t *pReq, int req_idx)
317 struct scatterlist *sg;
319 int sges_left, sg_done;
320 int chain_idx = MPT_HOST_NO_CHAIN;
322 int numSgeSlots, numSgeThisFrame;
323 u32 sgflags, sgdir, thisxfer = 0;
324 int chain_dma_off = 0;
330 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
331 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
332 sgdir = MPT_TRANSFER_HOST_TO_IOC;
334 sgdir = MPT_TRANSFER_IOC_TO_HOST;
337 psge = (char *) &pReq->SGL;
338 frm_sz = ioc->req_sz;
340 /* Map the data portion, if any.
341 * sges_left = 0 if no data transfer.
343 if ( (sges_left = SCpnt->use_sg) ) {
344 sges_left = pci_map_sg(ioc->pcidev,
345 (struct scatterlist *) SCpnt->request_buffer,
347 SCpnt->sc_data_direction);
350 } else if (SCpnt->request_bufflen) {
351 SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
352 SCpnt->request_buffer,
353 SCpnt->request_bufflen,
354 SCpnt->sc_data_direction);
355 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
356 ioc->name, SCpnt, SCpnt->request_bufflen));
357 mptscsih_add_sge((char *) &pReq->SGL,
358 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
359 SCpnt->SCp.dma_handle);
364 /* Handle the SG case.
366 sg = (struct scatterlist *) SCpnt->request_buffer;
368 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
371 /* Prior to entering this loop - the following must be set
372 * current MF: sgeOffset (bytes)
373 * chainSge (Null if original MF is not a chain buffer)
374 * sg_done (num SGE done for this MF)
378 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
379 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
381 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
383 /* Get first (num - 1) SG elements
384 * Skip any SG entries with a length of 0
385 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
387 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
388 thisxfer = sg_dma_len(sg);
390 sg ++; /* Get next SG element from the OS */
395 v2 = sg_dma_address(sg);
396 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
398 sg++; /* Get next SG element from the OS */
399 psge += (sizeof(u32) + sizeof(dma_addr_t));
400 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
404 if (numSgeThisFrame == sges_left) {
405 /* Add last element, end of buffer and end of list flags.
407 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
408 MPT_SGE_FLAGS_END_OF_BUFFER |
409 MPT_SGE_FLAGS_END_OF_LIST;
411 /* Add last SGE and set termination flags.
412 * Note: Last SGE may have a length of 0 - which should be ok.
414 thisxfer = sg_dma_len(sg);
416 v2 = sg_dma_address(sg);
417 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
420 psge += (sizeof(u32) + sizeof(dma_addr_t));
422 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
426 /* The current buffer is a chain buffer,
427 * but there is not another one.
428 * Update the chain element
429 * Offset and Length fields.
431 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
433 /* The current buffer is the original MF
434 * and there is no Chain buffer.
436 pReq->ChainOffset = 0;
437 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
438 dsgprintk((MYIOC_s_INFO_FMT
439 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
440 ioc->RequestNB[req_idx] = RequestNB;
443 /* At least one chain buffer is needed.
444 * Complete the first MF
445 * - last SGE element, set the LastElement bit
446 * - set ChainOffset (words) for orig MF
447 * (OR finish previous MF chain buffer)
448 * - update MFStructPtr ChainIndex
449 * - Populate chain element
454 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
455 ioc->name, sg_done));
457 /* Set LAST_ELEMENT flag for last non-chain element
458 * in the buffer. Since psge points at the NEXT
459 * SGE element, go back one SGE element, update the flags
460 * and reset the pointer. (Note: sgflags & thisxfer are already
464 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
465 sgflags = le32_to_cpu(*ptmp);
466 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
467 *ptmp = cpu_to_le32(sgflags);
471 /* The current buffer is a chain buffer.
472 * chainSge points to the previous Chain Element.
473 * Update its chain element Offset and Length (must
474 * include chain element size) fields.
475 * Old chain element is now complete.
477 u8 nextChain = (u8) (sgeOffset >> 2);
478 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
479 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
481 /* The original MF buffer requires a chain buffer -
483 * Last element in this MF is a chain element.
485 pReq->ChainOffset = (u8) (sgeOffset >> 2);
486 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
487 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
488 ioc->RequestNB[req_idx] = RequestNB;
491 sges_left -= sg_done;
494 /* NOTE: psge points to the beginning of the chain element
495 * in current buffer. Get a chain buffer.
497 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
498 dfailprintk((MYIOC_s_INFO_FMT
499 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
500 ioc->name, pReq->CDB[0], SCpnt));
504 /* Update the tracking arrays.
505 * If chainSge == NULL, update ReqToChain, else ChainToChain
508 ioc->ChainToChain[chain_idx] = newIndex;
510 ioc->ReqToChain[req_idx] = newIndex;
512 chain_idx = newIndex;
513 chain_dma_off = ioc->req_sz * chain_idx;
515 /* Populate the chainSGE for the current buffer.
516 * - Set chain buffer pointer to psge and fill
517 * out the Address and Flags fields.
519 chainSge = (char *) psge;
520 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
523 /* Start the SGE for the next buffer
525 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
529 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
532 /* Start the SGE for the next buffer
539 } /* mptscsih_AddSGE() */
541 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
543 * mptscsih_io_done - Main SCSI IO callback routine registered to
544 * Fusion MPT (base) driver
545 * @ioc: Pointer to MPT_ADAPTER structure
546 * @mf: Pointer to original MPT request frame
547 * @r: Pointer to MPT reply frame (NULL if TurboReply)
549 * This routine is called from mpt.c::mpt_interrupt() at the completion
550 * of any SCSI IO request.
551 * This routine is registered with the Fusion MPT (base) driver at driver
552 * load/init time via the mpt_register() API call.
554 * Returns 1 indicating alloc'd request frame ptr should be freed.
557 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
559 struct scsi_cmnd *sc;
561 SCSIIORequest_t *pScsiReq;
562 SCSIIOReply_t *pScsiReply;
565 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
567 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
568 sc = hd->ScsiLookup[req_idx];
570 MPIHeader_t *hdr = (MPIHeader_t *)mf;
572 /* Remark: writeSDP1 will use the ScsiDoneCtx
573 * If a SCSI I/O cmd, device disabled by OS and
574 * completion done. Cannot touch sc struct. Just free mem.
576 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
577 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
580 mptscsih_freeChainBuffers(ioc, req_idx);
584 sc->result = DID_OK << 16; /* Set default reply as OK */
585 pScsiReq = (SCSIIORequest_t *) mf;
586 pScsiReply = (SCSIIOReply_t *) mr;
588 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
589 dmfprintk((MYIOC_s_INFO_FMT
590 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
591 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
593 dmfprintk((MYIOC_s_INFO_FMT
594 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
595 ioc->name, mf, mr, sc, req_idx));
598 if (pScsiReply == NULL) {
599 /* special context reply handling */
604 u8 scsi_state, scsi_status;
606 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
607 scsi_state = pScsiReply->SCSIState;
608 scsi_status = pScsiReply->SCSIStatus;
609 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
610 sc->resid = sc->request_bufflen - xfer_cnt;
613 * if we get a data underrun indication, yet no data was
614 * transferred and the SCSI status indicates that the
615 * command was never started, change the data underrun
618 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
619 (scsi_status == MPI_SCSI_STATUS_BUSY ||
620 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
621 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
622 status = MPI_IOCSTATUS_SUCCESS;
625 dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
626 "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
627 "resid=%d bufflen=%d xfer_cnt=%d\n",
628 ioc->id, sc->device->id, sc->device->lun,
629 status, scsi_state, scsi_status, sc->resid,
630 sc->request_bufflen, xfer_cnt));
632 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
633 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
636 * Look for + dump FCP ResponseInfo[]!
638 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
639 pScsiReply->ResponseInfo) {
640 printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
641 "FCP_ResponseInfo=%08xh\n",
642 ioc->id, sc->device->id, sc->device->lun,
643 le32_to_cpu(pScsiReply->ResponseInfo));
647 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
649 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
650 * But not: DID_BUS_BUSY lest one risk
651 * killing interrupt handler:-(
653 sc->result = SAM_STAT_BUSY;
656 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
657 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
658 sc->result = DID_BAD_TARGET << 16;
661 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
662 /* Spoof to SCSI Selection Timeout! */
663 sc->result = DID_NO_CONNECT << 16;
665 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
666 hd->sel_timeout[pScsiReq->TargetID]++;
669 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
670 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
671 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
672 /* Linux handles an unsolicited DID_RESET better
673 * than an unsolicited DID_ABORT.
675 sc->result = DID_RESET << 16;
677 /* GEM Workaround. */
678 if (ioc->bus_type == SPI)
679 mptscsih_no_negotiate(hd, sc);
682 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
683 sc->resid = sc->request_bufflen - xfer_cnt;
684 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
685 sc->result=DID_SOFT_ERROR << 16;
686 else /* Sufficient data transfer occurred */
687 sc->result = (DID_OK << 16) | scsi_status;
688 dreplyprintk((KERN_NOTICE
689 "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
692 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
694 * Do upfront check for valid SenseData and give it
697 sc->result = (DID_OK << 16) | scsi_status;
698 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
699 /* Have already saved the status and sense data
703 if (xfer_cnt < sc->underflow) {
704 if (scsi_status == SAM_STAT_BUSY)
705 sc->result = SAM_STAT_BUSY;
707 sc->result = DID_SOFT_ERROR << 16;
709 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
712 sc->result = DID_SOFT_ERROR << 16;
714 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
715 /* Not real sure here either... */
716 sc->result = DID_RESET << 16;
720 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
722 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
725 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
726 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
730 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
731 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
732 if (scsi_status == MPI_SCSI_STATUS_BUSY)
733 sc->result = (DID_BUS_BUSY << 16) | scsi_status;
735 sc->result = (DID_OK << 16) | scsi_status;
736 if (scsi_state == 0) {
738 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
740 * If running against circa 200003dd 909 MPT f/w,
741 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
742 * (QUEUE_FULL) returned from device! --> get 0x0000?128
743 * and with SenseBytes set to 0.
745 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
746 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
749 else if (scsi_state &
750 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
755 sc->result = DID_SOFT_ERROR << 16;
757 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
758 /* Not real sure here either... */
759 sc->result = DID_RESET << 16;
761 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
762 /* Device Inq. data indicates that it supports
763 * QTags, but rejects QTag messages.
764 * This command completed OK.
766 * Not real sure here either so do nothing... */
769 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
770 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
773 * Reservation Conflict, Busy,
774 * Command Terminated, CHECK
778 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
779 sc->result = DID_SOFT_ERROR << 16;
782 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
783 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
784 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
785 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
786 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
787 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
788 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
789 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
790 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
791 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
796 sc->result = DID_SOFT_ERROR << 16;
799 } /* switch(status) */
801 dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
802 } /* end of address reply case */
804 /* Unmap the DMA buffers, if any. */
806 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
807 sc->use_sg, sc->sc_data_direction);
808 } else if (sc->request_bufflen) {
809 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
810 sc->request_bufflen, sc->sc_data_direction);
813 hd->ScsiLookup[req_idx] = NULL;
815 sc->scsi_done(sc); /* Issue the command callback */
817 /* Free Chain buffers */
818 mptscsih_freeChainBuffers(ioc, req_idx);
823 * mptscsih_flush_running_cmds - For each command found, search
824 * Scsi_Host instance taskQ and reply to OS.
825 * Called only if recovering from a FW reload.
826 * @hd: Pointer to a SCSI HOST structure
830 * Must be called while new I/Os are being queued.
833 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
835 MPT_ADAPTER *ioc = hd->ioc;
836 struct scsi_cmnd *SCpnt;
839 int max = ioc->req_depth;
841 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
842 for (ii= 0; ii < max; ii++) {
843 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
848 /* Null ScsiLookup index
850 hd->ScsiLookup[ii] = NULL;
852 mf = MPT_INDEX_2_MFPTR(ioc, ii);
853 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
856 /* Set status, free OS resources (SG DMA buffers)
858 * Free driver resources (chain, msg buffers)
861 pci_unmap_sg(ioc->pcidev,
862 (struct scatterlist *) SCpnt->request_buffer,
864 SCpnt->sc_data_direction);
865 } else if (SCpnt->request_bufflen) {
866 pci_unmap_single(ioc->pcidev,
867 SCpnt->SCp.dma_handle,
868 SCpnt->request_bufflen,
869 SCpnt->sc_data_direction);
871 SCpnt->result = DID_RESET << 16;
872 SCpnt->host_scribble = NULL;
874 /* Free Chain buffers */
875 mptscsih_freeChainBuffers(ioc, ii);
877 /* Free Message frames */
878 mpt_free_msg_frame(ioc, mf);
880 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
888 * mptscsih_search_running_cmds - Delete any commands associated
889 * with the specified target and lun. Function called only
890 * when a lun is disable by mid-layer.
891 * Do NOT access the referenced scsi_cmnd structure or
892 * members. Will cause either a paging or NULL ptr error.
893 * (BUT, BUT, BUT, the code does reference it! - mdr)
894 * @hd: Pointer to a SCSI HOST structure
895 * @vdevice: per device private data
899 * Called from slave_destroy.
902 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
904 SCSIIORequest_t *mf = NULL;
906 int max = hd->ioc->req_depth;
907 struct scsi_cmnd *sc;
909 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
910 vdevice->target_id, vdevice->lun, max));
912 for (ii=0; ii < max; ii++) {
913 if ((sc = hd->ScsiLookup[ii]) != NULL) {
915 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
917 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
918 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
920 if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
925 hd->ScsiLookup[ii] = NULL;
926 mptscsih_freeChainBuffers(hd->ioc, ii);
927 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
929 pci_unmap_sg(hd->ioc->pcidev,
930 (struct scatterlist *) sc->request_buffer,
932 sc->sc_data_direction);
933 } else if (sc->request_bufflen) {
934 pci_unmap_single(hd->ioc->pcidev,
937 sc->sc_data_direction);
939 sc->host_scribble = NULL;
940 sc->result = DID_NO_CONNECT << 16;
947 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
949 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
951 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
952 * from a SCSI target device.
953 * @sc: Pointer to scsi_cmnd structure
954 * @pScsiReply: Pointer to SCSIIOReply_t
955 * @pScsiReq: Pointer to original SCSI request
957 * This routine periodically reports QUEUE_FULL status returned from a
958 * SCSI target device. It reports this to the console via kernel
959 * printk() API call, not more than once every 10 seconds.
962 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
967 if (sc->device == NULL)
969 if (sc->device->host == NULL)
971 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
974 if (time - hd->last_queue_full > 10 * HZ) {
975 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
976 hd->ioc->name, 0, sc->device->id, sc->device->lun));
977 hd->last_queue_full = time;
981 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
983 * mptscsih_remove - Removed scsi devices
984 * @pdev: Pointer to pci_dev structure
989 mptscsih_remove(struct pci_dev *pdev)
991 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
992 struct Scsi_Host *host = ioc->sh;
994 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1005 scsi_remove_host(host);
1007 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1010 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1011 /* Check DV thread active */
1013 spin_lock_irqsave(&dvtaskQ_lock, flags);
1014 if (dvtaskQ_active) {
1015 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1016 while(dvtaskQ_active && --count)
1017 schedule_timeout_interruptible(1);
1019 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1022 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
1023 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
1025 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
1029 mptscsih_shutdown(pdev);
1033 if (hd->ScsiLookup != NULL) {
1034 sz1 = hd->ioc->req_depth * sizeof(void *);
1035 kfree(hd->ScsiLookup);
1036 hd->ScsiLookup = NULL;
1040 * Free pointer array.
1045 dprintk((MYIOC_s_INFO_FMT
1046 "Free'd ScsiLookup (%d) memory\n",
1047 hd->ioc->name, sz1));
1049 kfree(hd->info_kbuf);
1051 /* NULL the Scsi_Host pointer
1055 scsi_host_put(host);
1061 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1063 * mptscsih_shutdown - reboot notifier
1067 mptscsih_shutdown(struct pci_dev *pdev)
1069 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1070 struct Scsi_Host *host = ioc->sh;
1076 hd = (MPT_SCSI_HOST *)host->hostdata;
1081 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1083 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1088 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1090 mptscsih_shutdown(pdev);
1091 return mpt_suspend(pdev,state);
1094 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1096 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1101 mptscsih_resume(struct pci_dev *pdev)
1103 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1104 struct Scsi_Host *host = ioc->sh;
1112 hd = (MPT_SCSI_HOST *)host->hostdata;
1116 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1118 unsigned long lflags;
1119 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1120 if (!dvtaskQ_active) {
1122 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1123 INIT_WORK(&dvTaskQ_task,
1124 mptscsih_domainValidation, (void *) hd);
1125 schedule_work(&dvTaskQ_task);
1127 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1136 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1138 * mptscsih_info - Return information about MPT adapter
1139 * @SChost: Pointer to Scsi_Host structure
1141 * (linux scsi_host_template.info routine)
1143 * Returns pointer to buffer where information was written.
1146 mptscsih_info(struct Scsi_Host *SChost)
1151 h = (MPT_SCSI_HOST *)SChost->hostdata;
1154 if (h->info_kbuf == NULL)
1155 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1156 return h->info_kbuf;
1157 h->info_kbuf[0] = '\0';
1159 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1160 h->info_kbuf[size-1] = '\0';
1163 return h->info_kbuf;
1174 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1176 if (info->pos + len > info->length)
1177 len = info->length - info->pos;
1179 if (info->pos + len < info->offset) {
1184 if (info->pos < info->offset) {
1185 data += (info->offset - info->pos);
1186 len -= (info->offset - info->pos);
1190 memcpy(info->buffer + info->pos, data, len);
1196 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1202 va_start(args, fmt);
1203 len = vsprintf(buf, fmt, args);
1206 mptscsih_copy_mem_info(info, buf, len);
1211 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1213 struct info_str info;
1217 info.offset = offset;
1220 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1221 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1222 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1223 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1225 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1228 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1230 * mptscsih_proc_info - Return information about MPT adapter
1232 * (linux scsi_host_template.info routine)
1234 * buffer: if write, user data; if read, buffer for user
1235 * length: if write, return length;
1236 * offset: if write, 0; if read, the current offset into the buffer from
1237 * the previous read.
1238 * hostno: scsi host number
1239 * func: if write = 1; if read = 0
1242 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1243 int length, int func)
1245 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1246 MPT_ADAPTER *ioc = hd->ioc;
1251 * write is not supported
1257 size = mptscsih_host_info(ioc, buffer, offset, length);
1263 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1264 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1266 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1268 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1269 * @SCpnt: Pointer to scsi_cmnd structure
1270 * @done: Pointer SCSI mid-layer IO completion function
1272 * (linux scsi_host_template.queuecommand routine)
1273 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1274 * from a linux scsi_cmnd request and send it to the IOC.
1276 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1279 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1283 SCSIIORequest_t *pScsiReq;
1284 VirtDevice *vdev = SCpnt->device->hostdata;
1293 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1294 lun = SCpnt->device->lun;
1295 SCpnt->scsi_done = done;
1297 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1298 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1300 if (hd->resetPending) {
1301 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1302 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1303 return SCSI_MLQUEUE_HOST_BUSY;
1307 * Put together a MPT SCSI request...
1309 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1310 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1312 return SCSI_MLQUEUE_HOST_BUSY;
1315 pScsiReq = (SCSIIORequest_t *) mf;
1317 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1319 ADD_INDEX_LOG(my_idx);
1321 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1322 * Seems we may receive a buffer (datalen>0) even when there
1323 * will be no data transfer! GRRRRR...
1325 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1326 datalen = SCpnt->request_bufflen;
1327 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1328 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1329 datalen = SCpnt->request_bufflen;
1330 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1333 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1336 /* Default to untagged. Once a target structure has been allocated,
1337 * use the Inquiry data to determine if device supports tagged.
1340 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1341 && (SCpnt->device->tagged_supported)) {
1342 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1344 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1347 /* Use the above information to set up the message frame
1349 pScsiReq->TargetID = (u8) vdev->target_id;
1350 pScsiReq->Bus = vdev->bus_id;
1351 pScsiReq->ChainOffset = 0;
1352 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1353 pScsiReq->CDBLength = SCpnt->cmd_len;
1354 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1355 pScsiReq->Reserved = 0;
1356 pScsiReq->MsgFlags = mpt_msg_flags();
1357 pScsiReq->LUN[0] = 0;
1358 pScsiReq->LUN[1] = lun;
1359 pScsiReq->LUN[2] = 0;
1360 pScsiReq->LUN[3] = 0;
1361 pScsiReq->LUN[4] = 0;
1362 pScsiReq->LUN[5] = 0;
1363 pScsiReq->LUN[6] = 0;
1364 pScsiReq->LUN[7] = 0;
1365 pScsiReq->Control = cpu_to_le32(scsictl);
1368 * Write SCSI CDB into the message
1370 cmd_len = SCpnt->cmd_len;
1371 for (ii=0; ii < cmd_len; ii++)
1372 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1374 for (ii=cmd_len; ii < 16; ii++)
1375 pScsiReq->CDB[ii] = 0;
1378 pScsiReq->DataLength = cpu_to_le32(datalen);
1380 /* SenseBuffer low address */
1381 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1382 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1384 /* Now add the SG list
1385 * Always have a SGE even if null length.
1388 /* Add a NULL SGE */
1389 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1392 /* Add a 32 or 64 bit SGE */
1393 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1397 hd->ScsiLookup[my_idx] = SCpnt;
1398 SCpnt->host_scribble = NULL;
1400 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1401 if (hd->ioc->bus_type == SPI) {
1402 int dvStatus = hd->ioc->spi_data.dvStatus[vdev->target_id];
1405 if (dvStatus || hd->ioc->spi_data.forceDv) {
1407 if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
1408 (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
1409 unsigned long lflags;
1410 /* Schedule DV if necessary */
1411 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1412 if (!dvtaskQ_active) {
1414 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1415 INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
1417 schedule_work(&dvTaskQ_task);
1419 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1421 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
1424 /* Trying to do DV to this target, extend timeout.
1425 * Wait to issue until flag is clear
1427 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
1428 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
1432 /* Set the DV flags.
1434 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
1435 mptscsih_set_dvflags(hd, SCpnt);
1443 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1444 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1445 hd->ioc->name, SCpnt, mf, my_idx));
1446 DBG_DUMP_REQUEST_FRAME(mf)
1450 hd->ScsiLookup[my_idx] = NULL;
1451 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1452 mpt_free_msg_frame(hd->ioc, mf);
1453 return SCSI_MLQUEUE_HOST_BUSY;
1456 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1458 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1459 * with a SCSI IO request
1460 * @hd: Pointer to the MPT_SCSI_HOST instance
1461 * @req_idx: Index of the SCSI IO request frame.
1463 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1467 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1469 MPT_FRAME_HDR *chain;
1470 unsigned long flags;
1474 /* Get the first chain index and reset
1477 chain_idx = ioc->ReqToChain[req_idx];
1478 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1480 while (chain_idx != MPT_HOST_NO_CHAIN) {
1482 /* Save the next chain buffer index */
1483 next = ioc->ChainToChain[chain_idx];
1485 /* Free this chain buffer and reset
1488 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1490 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1491 + (chain_idx * ioc->req_sz));
1493 spin_lock_irqsave(&ioc->FreeQlock, flags);
1494 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1495 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1497 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1498 ioc->name, chain_idx));
1506 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1511 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1513 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1514 * Fall through to mpt_HardResetHandler if: not operational, too many
1515 * failed TM requests or handshake failure.
1517 * @ioc: Pointer to MPT_ADAPTER structure
1518 * @type: Task Management type
1519 * @target: Logical Target ID for reset (if appropriate)
1520 * @lun: Logical Unit for reset (if appropriate)
1521 * @ctx2abort: Context for the task to be aborted (if appropriate)
1523 * Remark: Currently invoked from a non-interrupt thread (_bh).
1525 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1528 * Returns 0 for SUCCESS or -1 if FAILED.
1531 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1537 unsigned long flags;
1539 /* If FW is being reloaded currently, return success to
1540 * the calling function.
1547 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1550 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1552 // SJR - CHECKME - Can we avoid this here?
1553 // (mpt_HardResetHandler has this check...)
1554 spin_lock_irqsave(&ioc->diagLock, flags);
1555 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1556 spin_unlock_irqrestore(&ioc->diagLock, flags);
1559 spin_unlock_irqrestore(&ioc->diagLock, flags);
1561 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1562 * If we time out and not bus reset, then we return a FAILED status to the caller.
1563 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1564 * successful. Otherwise, reload the FW.
1566 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1567 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1568 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1569 "Timed out waiting for last TM (%d) to complete! \n",
1570 hd->ioc->name, hd->tmPending));
1572 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1573 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
1574 "Timed out waiting for last TM (%d) to complete! \n",
1575 hd->ioc->name, hd->tmPending));
1577 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1578 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1579 "Timed out waiting for last TM (%d) to complete! \n",
1580 hd->ioc->name, hd->tmPending));
1581 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
1587 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1588 hd->tmPending |= (1 << type);
1589 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1594 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1596 #ifdef MPT_DEBUG_RESET
1597 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1598 printk(MYIOC_s_WARN_FMT
1599 "TM Handler: IOC Not operational(0x%x)!\n",
1600 hd->ioc->name, ioc_raw_state);
1604 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1605 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1607 /* Isse the Task Mgmt request.
1609 if (hd->hard_resets < -1)
1611 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
1613 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
1615 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
1619 /* Only fall through to the HRH if this is a bus reset
1621 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
1622 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
1623 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1625 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1628 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1634 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1636 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1637 * @hd: Pointer to MPT_SCSI_HOST structure
1638 * @type: Task Management type
1639 * @target: Logical Target ID for reset (if appropriate)
1640 * @lun: Logical Unit for reset (if appropriate)
1641 * @ctx2abort: Context for the task to be aborted (if appropriate)
1643 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1644 * or a non-interrupt thread. In the former, must not call schedule().
1646 * Not all fields are meaningfull for all task types.
1648 * Returns 0 for SUCCESS, -999 for "no msg frames",
1649 * else other non-zero value returned.
1652 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1655 SCSITaskMgmt_t *pScsiTm;
1659 /* Return Fail to calling function if no message frames available.
1661 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1662 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1666 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1667 hd->ioc->name, mf));
1669 /* Format the Request
1671 pScsiTm = (SCSITaskMgmt_t *) mf;
1672 pScsiTm->TargetID = target;
1673 pScsiTm->Bus = channel;
1674 pScsiTm->ChainOffset = 0;
1675 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1677 pScsiTm->Reserved = 0;
1678 pScsiTm->TaskType = type;
1679 pScsiTm->Reserved1 = 0;
1680 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1681 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1683 for (ii= 0; ii < 8; ii++) {
1684 pScsiTm->LUN[ii] = 0;
1686 pScsiTm->LUN[1] = lun;
1688 for (ii=0; ii < 7; ii++)
1689 pScsiTm->Reserved2[ii] = 0;
1691 pScsiTm->TaskMsgContext = ctx2abort;
1693 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1694 hd->ioc->name, ctx2abort, type));
1696 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1698 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1699 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
1701 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
1702 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1704 mpt_free_msg_frame(hd->ioc, mf);
1708 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1709 dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
1710 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1712 mpt_free_msg_frame(hd->ioc, mf);
1713 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1715 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1721 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1723 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1724 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1726 * (linux scsi_host_template.eh_abort_handler routine)
1728 * Returns SUCCESS or FAILED.
1731 mptscsih_abort(struct scsi_cmnd * SCpnt)
1741 /* If we can't locate our host adapter structure, return FAILED status.
1743 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1744 SCpnt->result = DID_RESET << 16;
1745 SCpnt->scsi_done(SCpnt);
1746 dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1747 "Can't locate host! (sc=%p)\n",
1753 if (hd->resetPending) {
1757 if (hd->timeouts < -1)
1760 /* Find this command
1762 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1763 /* Cmd not found in ScsiLookup.
1766 SCpnt->result = DID_RESET << 16;
1767 dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1768 "Command not in the active list! (sc=%p)\n",
1769 hd->ioc->name, SCpnt));
1773 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1774 hd->ioc->name, SCpnt);
1775 scsi_print_command(SCpnt);
1777 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1778 * (the IO to be ABORT'd)
1780 * NOTE: Since we do not byteswap MsgContext, we do not
1781 * swap it here either. It is an opaque cookie to
1782 * the controller, so it does not matter. -DaveM
1784 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1785 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1787 hd->abortSCpnt = SCpnt;
1789 vdev = SCpnt->device->hostdata;
1790 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1791 vdev->bus_id, vdev->target_id, vdev->lun,
1792 ctx2abort, 2 /* 2 second timeout */);
1794 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1796 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1801 if(retval != FAILED ) {
1803 hd->tmState = TM_STATE_NONE;
1808 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1810 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1811 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1813 * (linux scsi_host_template.eh_dev_reset_handler routine)
1815 * Returns SUCCESS or FAILED.
1818 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1824 /* If we can't locate our host adapter structure, return FAILED status.
1826 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1827 dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1828 "Can't locate host! (sc=%p)\n",
1833 if (hd->resetPending)
1836 printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1837 hd->ioc->name, SCpnt);
1838 scsi_print_command(SCpnt);
1840 vdev = SCpnt->device->hostdata;
1841 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1842 vdev->bus_id, vdev->target_id,
1843 0, 0, 5 /* 5 second timeout */);
1845 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1847 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1852 if(retval != FAILED ) {
1854 hd->tmState = TM_STATE_NONE;
1859 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1861 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1862 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1864 * (linux scsi_host_template.eh_bus_reset_handler routine)
1866 * Returns SUCCESS or FAILED.
1869 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1875 /* If we can't locate our host adapter structure, return FAILED status.
1877 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1878 dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1879 "Can't locate host! (sc=%p)\n",
1884 printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1885 hd->ioc->name, SCpnt);
1886 scsi_print_command(SCpnt);
1888 if (hd->timeouts < -1)
1891 vdev = SCpnt->device->hostdata;
1892 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1893 vdev->bus_id, 0, 0, 0, 5 /* 5 second timeout */);
1895 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1897 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1902 if(retval != FAILED ) {
1904 hd->tmState = TM_STATE_NONE;
1909 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1911 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
1913 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1915 * (linux scsi_host_template.eh_host_reset_handler routine)
1917 * Returns SUCCESS or FAILED.
1920 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1923 int status = SUCCESS;
1925 /* If we can't locate the host to reset, then we failed. */
1926 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1927 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1928 "Can't locate host! (sc=%p)\n",
1933 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1934 hd->ioc->name, SCpnt);
1936 /* If our attempts to reset the host failed, then return a failed
1937 * status. The host will be taken off line by the SCSI mid-layer.
1939 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1942 /* Make sure TM pending is cleared and TM state is set to
1946 hd->tmState = TM_STATE_NONE;
1949 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1951 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1956 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1958 * mptscsih_tm_pending_wait - wait for pending task management request to
1960 * @hd: Pointer to MPT host structure.
1962 * Returns {SUCCESS,FAILED}.
1965 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1967 unsigned long flags;
1968 int loop_count = 4 * 10; /* Wait 10 seconds */
1969 int status = FAILED;
1972 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1973 if (hd->tmState == TM_STATE_NONE) {
1974 hd->tmState = TM_STATE_IN_PROGRESS;
1976 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1980 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1982 } while (--loop_count);
1987 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1989 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1990 * @hd: Pointer to MPT host structure.
1992 * Returns {SUCCESS,FAILED}.
1995 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
1997 unsigned long flags;
1998 int loop_count = 4 * timeout;
1999 int status = FAILED;
2002 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2003 if(hd->tmPending == 0) {
2005 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2008 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2009 msleep_interruptible(250);
2010 } while (--loop_count);
2015 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2017 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2018 * @ioc: Pointer to MPT_ADAPTER structure
2019 * @mf: Pointer to SCSI task mgmt request frame
2020 * @mr: Pointer to SCSI task mgmt reply frame
2022 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2023 * of any SCSI task management request.
2024 * This routine is registered with the MPT (base) driver at driver
2025 * load/init time via the mpt_register() API call.
2027 * Returns 1 indicating alloc'd request frame ptr should be freed.
2030 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2032 SCSITaskMgmtReply_t *pScsiTmReply;
2033 SCSITaskMgmt_t *pScsiTmReq;
2035 unsigned long flags;
2039 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2040 ioc->name, mf, mr));
2042 /* Depending on the thread, a timer is activated for
2043 * the TM request. Delete this timer on completion of TM.
2044 * Decrement count of outstanding TM requests.
2046 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2048 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
2054 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
2058 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2059 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2061 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2062 tmType = pScsiTmReq->TaskType;
2064 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
2065 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2066 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2068 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2069 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2070 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2071 /* Error? (anything non-zero?) */
2074 /* clear flags and continue.
2076 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2077 hd->abortSCpnt = NULL;
2079 /* If an internal command is present
2080 * or the TM failed - reload the FW.
2081 * FC FW may respond FAILED to an ABORT
2083 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2085 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
2086 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2087 printk((KERN_WARNING
2088 " Firmware Reload FAILED!!\n"));
2093 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2095 hd->abortSCpnt = NULL;
2100 spin_lock_irqsave(&ioc->FreeQlock, flags);
2102 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2103 hd->tmState = TM_STATE_NONE;
2108 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2110 * This is anyones guess quite frankly.
2113 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2114 sector_t capacity, int geom[])
2124 dummy = heads * sectors;
2125 cylinders = capacity;
2126 sector_div(cylinders,dummy);
2129 * Handle extended translation size for logical drives
2132 if ((ulong)capacity >= 0x200000) {
2135 dummy = heads * sectors;
2136 cylinders = capacity;
2137 sector_div(cylinders,dummy);
2143 geom[2] = cylinders;
2145 dprintk((KERN_NOTICE
2146 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2147 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
2152 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2154 * OS entry point to allow host driver to alloc memory
2155 * for each scsi target. Called once per device the bus scan.
2156 * Return non-zero if allocation fails.
2159 mptscsih_target_alloc(struct scsi_target *starget)
2161 VirtTarget *vtarget;
2163 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
2166 starget->hostdata = vtarget;
2170 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2172 * OS entry point to allow host driver to alloc memory
2173 * for each scsi device. Called once per device the bus scan.
2174 * Return non-zero if allocation fails.
2177 mptscsih_slave_alloc(struct scsi_device *sdev)
2179 struct Scsi_Host *host = sdev->host;
2180 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2181 VirtTarget *vtarget;
2183 struct scsi_target *starget;
2185 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
2187 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
2188 hd->ioc->name, sizeof(VirtDevice));
2192 vdev->ioc_id = hd->ioc->id;
2193 vdev->target_id = sdev->id;
2194 vdev->bus_id = sdev->channel;
2195 vdev->lun = sdev->lun;
2196 sdev->hostdata = vdev;
2198 starget = scsi_target(sdev);
2199 vtarget = starget->hostdata;
2200 vdev->vtarget = vtarget;
2202 if (vtarget->num_luns == 0) {
2203 hd->Targets[sdev->id] = vtarget;
2204 vtarget->ioc_id = hd->ioc->id;
2205 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
2206 vtarget->target_id = sdev->id;
2207 vtarget->bus_id = sdev->channel;
2208 if (hd->ioc->bus_type == SPI) {
2209 if (hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
2210 vtarget->raidVolume = 1;
2211 ddvtprintk((KERN_INFO
2212 "RAID Volume @ id %d\n", sdev->id));
2215 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2218 vtarget->num_luns++;
2223 * OS entry point to allow for host driver to free allocated memory
2224 * Called if no device present or device being unloaded
2227 mptscsih_target_destroy(struct scsi_target *starget)
2229 if (starget->hostdata)
2230 kfree(starget->hostdata);
2231 starget->hostdata = NULL;
2235 * OS entry point to allow for host driver to free allocated memory
2236 * Called if no device present or device being unloaded
2239 mptscsih_slave_destroy(struct scsi_device *sdev)
2241 struct Scsi_Host *host = sdev->host;
2242 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2243 VirtTarget *vtarget;
2244 VirtDevice *vdevice;
2245 struct scsi_target *starget;
2247 starget = scsi_target(sdev);
2248 vtarget = starget->hostdata;
2249 vdevice = sdev->hostdata;
2251 mptscsih_search_running_cmds(hd, vdevice);
2252 vtarget->luns[0] &= ~(1 << vdevice->lun);
2253 vtarget->num_luns--;
2254 if (vtarget->num_luns == 0) {
2255 mptscsih_negotiate_to_asyn_narrow(hd, vtarget);
2256 if (hd->ioc->bus_type == SPI) {
2257 if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) {
2258 hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
2260 hd->ioc->spi_data.dvStatus[vtarget->target_id] =
2261 MPT_SCSICFG_NEGOTIATE;
2262 if (!hd->negoNvram) {
2263 hd->ioc->spi_data.dvStatus[vtarget->target_id] |=
2264 MPT_SCSICFG_DV_NOT_DONE;
2268 hd->Targets[sdev->id] = NULL;
2270 mptscsih_synchronize_cache(hd, vdevice);
2272 sdev->hostdata = NULL;
2275 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2277 * mptscsih_change_queue_depth - This function will set a devices queue depth
2278 * @sdev: per scsi_device pointer
2279 * @qdepth: requested queue depth
2281 * Adding support for new 'change_queue_depth' api.
2284 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2286 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2287 VirtTarget *vtarget;
2288 struct scsi_target *starget;
2292 starget = scsi_target(sdev);
2293 vtarget = starget->hostdata;
2295 if (hd->ioc->bus_type == SPI) {
2296 if (vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
2297 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2299 else if (((vtarget->inq_data[0] & 0x1f) == 0x00) &&
2300 (vtarget->minSyncFactor <= MPT_ULTRA160 ))
2301 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2303 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2305 /* error case - No Inq. Data */
2309 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2311 if (qdepth > max_depth)
2316 tagged = MSG_SIMPLE_TAG;
2318 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2319 return sdev->queue_depth;
2323 * OS entry point to adjust the queue_depths on a per-device basis.
2324 * Called once per device the bus scan. Use it to force the queue_depth
2325 * member to 1 if a device does not support Q tags.
2326 * Return non-zero if fails.
2329 mptscsih_slave_configure(struct scsi_device *sdev)
2331 struct Scsi_Host *sh = sdev->host;
2332 VirtTarget *vtarget;
2333 VirtDevice *vdevice;
2334 struct scsi_target *starget;
2335 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2336 int indexed_lun, lun_index;
2338 starget = scsi_target(sdev);
2339 vtarget = starget->hostdata;
2340 vdevice = sdev->hostdata;
2342 dsprintk((MYIOC_s_INFO_FMT
2343 "device @ %p, id=%d, LUN=%d, channel=%d\n",
2344 hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
2345 if (hd->ioc->bus_type == SPI)
2346 dsprintk((MYIOC_s_INFO_FMT
2347 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2348 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2349 sdev->ppr, sdev->inquiry_len));
2351 if (sdev->id > sh->max_id) {
2352 /* error case, should never happen */
2353 scsi_adjust_queue_depth(sdev, 0, 1);
2354 goto slave_configure_exit;
2357 vdevice->configured_lun=1;
2358 lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */
2359 indexed_lun = (vdevice->lun % 32);
2360 vtarget->luns[lun_index] |= (1 << indexed_lun);
2361 mptscsih_initTarget(hd, vtarget, sdev->lun, sdev->inquiry,
2362 sdev->inquiry_len );
2363 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2365 dsprintk((MYIOC_s_INFO_FMT
2366 "Queue depth=%d, tflags=%x\n",
2367 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2369 if (hd->ioc->bus_type == SPI)
2370 dsprintk((MYIOC_s_INFO_FMT
2371 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2372 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2373 vtarget->minSyncFactor));
2375 slave_configure_exit:
2377 dsprintk((MYIOC_s_INFO_FMT
2378 "tagged %d, simple %d, ordered %d\n",
2379 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2380 sdev->ordered_tags));
2385 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2387 * Private routines...
2390 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2391 /* Utility function to copy sense data from the scsi_cmnd buffer
2392 * to the FC and SCSI target structures.
2396 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2399 SCSIIORequest_t *pReq;
2400 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2402 /* Get target structure
2404 pReq = (SCSIIORequest_t *) mf;
2405 vdev = sc->device->hostdata;
2411 /* Copy the sense received into the scsi command block. */
2412 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2413 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2414 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2416 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2418 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2419 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2421 MPT_ADAPTER *ioc = hd->ioc;
2423 idx = ioc->eventContext % ioc->eventLogSize;
2424 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2425 ioc->events[idx].eventContext = ioc->eventContext;
2427 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2428 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2429 (sc->device->channel << 8) || sc->device->id;
2431 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2433 ioc->eventContext++;
2437 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2443 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2448 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2450 for (i = 0; i < hd->ioc->req_depth; i++) {
2451 if (hd->ScsiLookup[i] == sc) {
2459 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2461 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2464 unsigned long flags;
2467 dtmprintk((KERN_WARNING MYNAM
2468 ": IOC %s_reset routed to SCSI host driver!\n",
2469 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2470 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2472 /* If a FW reload request arrives after base installed but
2473 * before all scsi hosts have been attached, then an alt_ioc
2474 * may have a NULL sh pointer.
2476 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2479 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2481 if (reset_phase == MPT_IOC_SETUP_RESET) {
2482 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2485 * 1. Set Hard Reset Pending Flag
2486 * All new commands go to doneQ
2488 hd->resetPending = 1;
2490 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2491 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2493 /* 2. Flush running commands
2494 * Clean ScsiLookup (and associated memory)
2498 /* 2b. Reply to OS all known outstanding I/O commands.
2500 mptscsih_flush_running_cmds(hd);
2502 /* 2c. If there was an internal command that
2503 * has not completed, configuration or io request,
2504 * free these resources.
2507 del_timer(&hd->timer);
2508 mpt_free_msg_frame(ioc, hd->cmdPtr);
2511 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2514 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2516 /* Once a FW reload begins, all new OS commands are
2517 * redirected to the doneQ w/ a reset status.
2518 * Init all control structures.
2521 /* ScsiLookup initialization
2523 for (ii=0; ii < hd->ioc->req_depth; ii++)
2524 hd->ScsiLookup[ii] = NULL;
2526 /* 2. Chain Buffer initialization
2529 /* 4. Renegotiate to all devices, if SPI
2531 if (ioc->bus_type == SPI) {
2532 dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
2533 mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
2536 /* 5. Enable new commands to be posted
2538 spin_lock_irqsave(&ioc->FreeQlock, flags);
2540 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2541 hd->resetPending = 0;
2542 hd->tmState = TM_STATE_NONE;
2544 /* 6. If there was an internal command,
2545 * wake this process up.
2549 * Wake up the original calling thread
2551 hd->pLocal = &hd->localReply;
2552 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2553 hd->scandv_wait_done = 1;
2554 wake_up(&hd->scandv_waitq);
2558 /* 7. SPI: Set flag to force DV and re-read IOC Page 3
2560 if (ioc->bus_type == SPI) {
2561 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2562 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
2565 /* 7. FC: Rescan for blocked rports which might have returned.
2567 else if (ioc->bus_type == FC) {
2569 unsigned long flags;
2571 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
2572 work_count = ++ioc->fc_rescan_work_count;
2573 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
2574 if (work_count == 1)
2575 schedule_work(&ioc->fc_rescan_work);
2577 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2581 return 1; /* currently means nothing really */
2584 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2586 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2589 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2591 unsigned long flags;
2593 devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2596 if (ioc->sh == NULL ||
2597 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2601 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2604 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2605 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2606 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2609 case MPI_EVENT_LOGOUT: /* 09 */
2613 case MPI_EVENT_RESCAN: /* 06 */
2614 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
2615 work_count = ++ioc->fc_rescan_work_count;
2616 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
2617 if (work_count == 1)
2618 schedule_work(&ioc->fc_rescan_work);
2622 * CHECKME! Don't think we need to do
2623 * anything for these, but...
2625 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2626 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2628 * CHECKME! Falling thru...
2632 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2634 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2635 pMpiEventDataRaid_t pRaidEventData =
2636 (pMpiEventDataRaid_t) pEvReply->Data;
2637 /* Domain Validation Needed */
2638 if (ioc->bus_type == SPI &&
2639 pRaidEventData->ReasonCode ==
2640 MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED)
2641 mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
2646 case MPI_EVENT_NONE: /* 00 */
2647 case MPI_EVENT_LOG_DATA: /* 01 */
2648 case MPI_EVENT_STATE_CHANGE: /* 02 */
2649 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2651 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2655 return 1; /* currently means nothing really */
2658 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2660 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2661 * @hd: Pointer to MPT_SCSI_HOST structure
2662 * @vtarget: per target private data
2664 * @data: Pointer to data
2665 * @dlen: Number of INQUIRY bytes
2667 * NOTE: It's only SAFE to call this routine if data points to
2668 * sane & valid STANDARD INQUIRY data!
2670 * Allocate and initialize memory for this target.
2671 * Save inquiry data.
2675 mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen)
2681 dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
2682 hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd));
2685 * If the peripheral qualifier filter is enabled then if the target reports a 0x1
2686 * (i.e. The targer is capable of supporting the specified peripheral device type
2687 * on this logical unit; however, the physical device is not currently connected
2688 * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
2689 * capable of supporting a physical device on this logical unit). This is to work
2690 * around a bug in th emid-layer in some distributions in which the mid-layer will
2691 * continue to try to communicate to the LUN and evntually create a dummy LUN.
2693 if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
2696 /* Is LUN supported? If so, upper 2 bits will be 0
2697 * in first byte of inquiry data.
2702 if (vtarget == NULL)
2706 vtarget->type = data[0];
2708 if (hd->ioc->bus_type != SPI)
2711 if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
2712 /* Treat all Processors as SAF-TE if
2713 * command line option is set */
2714 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2715 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
2716 }else if ((data[0] == TYPE_PROCESSOR) &&
2717 !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
2719 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2720 if ( data[44] == 'S' &&
2726 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2727 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
2731 if (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
2732 inq_len = dlen < 8 ? dlen : 8;
2733 memcpy (vtarget->inq_data, data, inq_len);
2734 /* If have not done DV, set the DV flag.
2736 pSpi = &hd->ioc->spi_data;
2737 if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
2738 if (pSpi->dvStatus[vtarget->target_id] & MPT_SCSICFG_DV_NOT_DONE)
2739 pSpi->dvStatus[vtarget->target_id] |= MPT_SCSICFG_NEED_DV;
2741 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2743 data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */
2745 if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2746 /* Update the target capabilities
2749 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
2752 mptscsih_setTargetNegoParms(hd, vtarget, data_56);
2754 /* Initial Inquiry may not request enough data bytes to
2755 * obtain byte 57. DV will; if target doesn't return
2756 * at least 57 bytes, data[56] will be zero. */
2758 if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2759 /* Update the target capabilities
2762 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
2763 mptscsih_setTargetNegoParms(hd, vtarget, data_56);
2769 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2771 * Update the target negotiation parameters based on the
2772 * the Inquiry data, adapter capabilities, and NVRAM settings.
2776 mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56)
2778 SpiCfgData *pspi_data = &hd->ioc->spi_data;
2779 int id = (int) target->target_id;
2781 VirtTarget *vtarget;
2783 u8 width = MPT_NARROW;
2784 u8 factor = MPT_ASYNC;
2786 u8 version, nfactor;
2789 target->negoFlags = pspi_data->noQas;
2791 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
2792 * support. If available, default QAS to off and allow enabling.
2793 * If not available, default QAS to on, turn off for non-disks.
2796 /* Set flags based on Inquiry data
2798 version = target->inq_data[2] & 0x07;
2801 factor = MPT_ULTRA2;
2802 offset = pspi_data->maxSyncOffset;
2803 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2805 if (target->inq_data[7] & 0x20) {
2809 if (target->inq_data[7] & 0x10) {
2810 factor = pspi_data->minSyncFactor;
2811 if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
2812 /* bits 2 & 3 show Clocking support */
2813 if ((byte56 & 0x0C) == 0)
2814 factor = MPT_ULTRA2;
2816 if ((byte56 & 0x03) == 0)
2817 factor = MPT_ULTRA160;
2819 factor = MPT_ULTRA320;
2822 ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
2825 if (target->inq_data[0] == TYPE_TAPE) {
2827 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2832 ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
2836 offset = pspi_data->maxSyncOffset;
2838 /* If RAID, never disable QAS
2839 * else if non RAID, do not disable
2840 * QAS if bit 1 is set
2841 * bit 1 QAS support, non-raid only
2844 if (target->raidVolume == 1) {
2853 if ( (target->inq_data[7] & 0x02) == 0) {
2854 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2857 /* Update tflags based on NVRAM settings. (SCSI only)
2859 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2860 nvram = pspi_data->nvram[id];
2861 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2864 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2867 /* Ensure factor is set to the
2868 * maximum of: adapter, nvram, inquiry
2871 if (nfactor < pspi_data->minSyncFactor )
2872 nfactor = pspi_data->minSyncFactor;
2874 factor = max(factor, nfactor);
2875 if (factor == MPT_ASYNC)
2886 /* Make sure data is consistent
2888 if ((!width) && (factor < MPT_ULTRA2)) {
2889 factor = MPT_ULTRA2;
2892 /* Save the data to the target structure.
2894 target->minSyncFactor = factor;
2895 target->maxOffset = offset;
2896 target->maxWidth = width;
2898 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2900 /* Disable unused features.
2903 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2906 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2908 if ( factor > MPT_ULTRA320 )
2911 /* GEM, processor WORKAROUND
2913 if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
2914 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
2915 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
2917 if (noQas && (pspi_data->noQas == 0)) {
2918 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2919 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2921 /* Disable QAS in a mixed configuration case
2924 ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
2925 for (ii = 0; ii < id; ii++) {
2926 if ( (vtarget = hd->Targets[ii]) ) {
2927 vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2928 mptscsih_writeSDP1(hd, 0, ii, vtarget->negoFlags);
2934 /* Write SDP1 on this I/O to this target */
2935 if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
2936 ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
2937 mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
2938 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
2939 } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
2940 ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
2941 mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
2942 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
2946 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2948 * If no Target, bus reset on 1st I/O. Set the flag to
2949 * prevent any future negotiations to this device.
2952 mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
2956 if ((vdev = sc->device->hostdata) != NULL)
2957 hd->ioc->spi_data.dvStatus[vdev->target_id] |= MPT_SCSICFG_BLK_NEGO;
2961 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2963 * SCSI Config Page functionality ...
2965 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2966 /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
2967 * based on width, factor and offset parameters.
2969 * @factor: sync factor
2970 * @offset: sync offset
2971 * @requestedPtr: pointer to requested values (updated)
2972 * @configurationPtr: pointer to configuration values (updated)
2973 * @flags: flags to block WDTR or SDTR negotiation
2977 * Remark: Called by writeSDP1 and _dv_params
2980 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
2982 u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
2983 u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
2985 *configurationPtr = 0;
2986 *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
2987 *requestedPtr |= (offset << 16) | (factor << 8);
2989 if (width && offset && !nowide && !nosync) {
2990 if (factor < MPT_ULTRA160) {
2991 *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
2992 if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
2993 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
2994 if (flags & MPT_TAPE_NEGO_IDP)
2995 *requestedPtr |= 0x08000000;
2996 } else if (factor < MPT_ULTRA2) {
2997 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
3002 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
3005 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
3010 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3011 /* mptscsih_writeSDP1 - write SCSI Device Page 1
3012 * @hd: Pointer to a SCSI Host Strucutre
3013 * @portnum: IOC port number
3014 * @target_id: writeSDP1 for single ID
3015 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
3017 * Return: -EFAULT if read of config page header fails
3020 * Remark: If a target has been found, the settings from the
3021 * target structure are used, else the device is set
3024 * Remark: Called during init and after a FW reload.
3025 * Remark: We do not wait for a return, write pages sequentially.
3028 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
3030 MPT_ADAPTER *ioc = hd->ioc;
3032 SCSIDevicePage1_t *pData;
3033 VirtTarget *vtarget=NULL;
3038 u32 requested, configuration, flagsLength;
3040 int id = 0, maxid = 0;
3046 u8 maxwidth, maxoffset, maxfactor;
3048 if (ioc->spi_data.sdp1length == 0)
3051 if (flags & MPT_SCSICFG_ALL_IDS) {
3053 maxid = ioc->sh->max_id - 1;
3054 } else if (ioc->sh) {
3056 maxid = min_t(int, id, ioc->sh->max_id - 1);
3059 for (; id <= maxid; id++) {
3061 if (id == ioc->pfacts[portnum].PortSCSIID)
3064 /* Use NVRAM to get adapter and target maximums
3065 * Data over-riden by target structure information, if present
3067 maxwidth = ioc->spi_data.maxBusWidth;
3068 maxoffset = ioc->spi_data.maxSyncOffset;
3069 maxfactor = ioc->spi_data.minSyncFactor;
3070 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3071 nvram = ioc->spi_data.nvram[id];
3074 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
3076 if (maxoffset > 0) {
3077 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
3078 if (maxfactor == 0) {
3080 maxfactor = MPT_ASYNC;
3082 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
3083 maxfactor = ioc->spi_data.minSyncFactor;
3086 maxfactor = MPT_ASYNC;
3089 /* Set the negotiation flags.
3091 negoFlags = ioc->spi_data.noQas;
3093 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
3096 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
3098 if (flags & MPT_SCSICFG_USE_NVRAM) {
3107 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
3110 /* If id is not a raid volume, get the updated
3111 * transmission settings from the target structure.
3113 if (hd->Targets && (vtarget = hd->Targets[id]) && !vtarget->raidVolume) {
3114 width = vtarget->maxWidth;
3115 factor = vtarget->minSyncFactor;
3116 offset = vtarget->maxOffset;
3117 negoFlags = vtarget->negoFlags;
3120 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3121 /* Force to async and narrow if DV has not been executed
3124 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
3131 if (flags & MPT_SCSICFG_BLK_NEGO)
3132 negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
3134 mptscsih_setDevicePage1Flags(width, factor, offset,
3135 &requested, &configuration, negoFlags);
3136 dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
3137 target_id, width, factor, offset, negoFlags, requested, configuration));
3139 /* Get a MF for this command.
3141 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
3142 dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
3147 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
3148 hd->ioc->name, mf, id, requested, configuration));
3151 /* Set the request and the data pointers.
3152 * Request takes: 36 bytes (32 bit SGE)
3153 * SCSI Device Page 1 requires 16 bytes
3154 * 40 + 16 <= size of SCSI IO Request = 56 bytes
3155 * and MF size >= 64 bytes.
3156 * Place data at end of MF.
3158 pReq = (Config_t *)mf;
3160 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3161 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
3163 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
3164 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
3166 /* Complete the request frame (same for all requests).
3168 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3170 pReq->ChainOffset = 0;
3171 pReq->Function = MPI_FUNCTION_CONFIG;
3172 pReq->ExtPageLength = 0;
3173 pReq->ExtPageType = 0;
3175 for (ii=0; ii < 8; ii++) {
3176 pReq->Reserved2[ii] = 0;
3178 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
3179 pReq->Header.PageLength = ioc->spi_data.sdp1length;
3180 pReq->Header.PageNumber = 1;
3181 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3182 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
3184 /* Add a SGE to the config request.
3186 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
3188 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3190 /* Set up the common data portion
3192 pData->Header.PageVersion = pReq->Header.PageVersion;
3193 pData->Header.PageLength = pReq->Header.PageLength;
3194 pData->Header.PageNumber = pReq->Header.PageNumber;
3195 pData->Header.PageType = pReq->Header.PageType;
3196 pData->RequestedParameters = cpu_to_le32(requested);
3197 pData->Reserved = 0;
3198 pData->Configuration = cpu_to_le32(configuration);
3200 dprintk((MYIOC_s_INFO_FMT
3201 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
3202 ioc->name, id, (id | (bus<<8)),
3203 requested, configuration));
3205 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3211 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3212 /* mptscsih_writeIOCPage4 - write IOC Page 4
3213 * @hd: Pointer to a SCSI Host Structure
3214 * @target_id: write IOC Page4 for this ID & Bus
3216 * Return: -EAGAIN if unable to obtain a Message Frame
3219 * Remark: We do not wait for a return, write pages sequentially.
3222 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
3224 MPT_ADAPTER *ioc = hd->ioc;
3226 IOCPage4_t *IOCPage4Ptr;
3234 /* Get a MF for this command.
3236 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
3237 dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
3242 /* Set the request and the data pointers.
3243 * Place data at end of MF.
3245 pReq = (Config_t *)mf;
3247 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3248 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
3250 /* Complete the request frame (same for all requests).
3252 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3254 pReq->ChainOffset = 0;
3255 pReq->Function = MPI_FUNCTION_CONFIG;
3256 pReq->ExtPageLength = 0;
3257 pReq->ExtPageType = 0;
3259 for (ii=0; ii < 8; ii++) {
3260 pReq->Reserved2[ii] = 0;
3263 IOCPage4Ptr = ioc->spi_data.pIocPg4;
3264 dataDma = ioc->spi_data.IocPg4_dma;
3265 ii = IOCPage4Ptr->ActiveSEP++;
3266 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
3267 IOCPage4Ptr->SEP[ii].SEPBus = bus;
3268 pReq->Header = IOCPage4Ptr->Header;
3269 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
3271 /* Add a SGE to the config request.
3273 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
3274 (IOCPage4Ptr->Header.PageLength + ii) * 4;
3276 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3278 dinitprintk((MYIOC_s_INFO_FMT
3279 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
3280 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
3282 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3287 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3289 * Bus Scan and Domain Validation functionality ...
3292 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3294 * mptscsih_scandv_complete - Scan and DV callback routine registered
3295 * to Fustion MPT (base) driver.
3297 * @ioc: Pointer to MPT_ADAPTER structure
3298 * @mf: Pointer to original MPT request frame
3299 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
3301 * This routine is called from mpt.c::mpt_interrupt() at the completion
3302 * of any SCSI IO request.
3303 * This routine is registered with the Fusion MPT (base) driver at driver
3304 * load/init time via the mpt_register() API call.
3306 * Returns 1 indicating alloc'd request frame ptr should be freed.
3308 * Remark: Sets a completion code and (possibly) saves sense data
3309 * in the IOC member localReply structure.
3310 * Used ONLY for DV and other internal commands.
3313 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3316 SCSIIORequest_t *pReq;
3320 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3323 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
3324 printk(MYIOC_s_ERR_FMT
3325 "ScanDvComplete, %s req frame ptr! (=%p)\n",
3326 ioc->name, mf?"BAD":"NULL", (void *) mf);
3330 del_timer(&hd->timer);
3331 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3332 hd->ScsiLookup[req_idx] = NULL;
3333 pReq = (SCSIIORequest_t *) mf;
3335 if (mf != hd->cmdPtr) {
3336 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3337 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
3341 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3342 hd->ioc->name, mf, mr, req_idx));
3344 hd->pLocal = &hd->localReply;
3345 hd->pLocal->scsiStatus = 0;
3347 /* If target struct exists, clear sense valid flag.
3350 completionCode = MPT_SCANDV_GOOD;
3352 SCSIIOReply_t *pReply;
3356 pReply = (SCSIIOReply_t *) mr;
3358 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3359 scsi_status = pReply->SCSIStatus;
3361 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3362 status, pReply->SCSIState, scsi_status,
3363 le32_to_cpu(pReply->IOCLogInfo)));
3367 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
3368 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3371 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
3372 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
3373 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
3374 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
3375 completionCode = MPT_SCANDV_DID_RESET;
3378 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
3379 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
3380 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
3381 if (pReply->Function == MPI_FUNCTION_CONFIG) {
3382 ConfigReply_t *pr = (ConfigReply_t *)mr;
3383 completionCode = MPT_SCANDV_GOOD;
3384 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
3385 hd->pLocal->header.PageLength = pr->Header.PageLength;
3386 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
3387 hd->pLocal->header.PageType = pr->Header.PageType;
3389 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
3390 /* If the RAID Volume request is successful,
3391 * return GOOD, else indicate that
3392 * some type of error occurred.
3394 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
3395 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
3396 completionCode = MPT_SCANDV_GOOD;
3398 completionCode = MPT_SCANDV_SOME_ERROR;
3400 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3404 /* save sense data in global structure
3406 completionCode = MPT_SCANDV_SENSE;
3407 hd->pLocal->scsiStatus = scsi_status;
3408 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
3409 (req_idx * MPT_SENSE_BUFFER_ALLOC));
3411 sz = min_t(int, pReq->SenseBufferLength,
3412 SCSI_STD_SENSE_BYTES);
3413 memcpy(hd->pLocal->sense, sense_data, sz);
3415 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
3417 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
3418 if (pReq->CDB[0] == INQUIRY)
3419 completionCode = MPT_SCANDV_ISSUE_SENSE;
3421 completionCode = MPT_SCANDV_DID_RESET;
3423 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
3424 completionCode = MPT_SCANDV_DID_RESET;
3425 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3426 completionCode = MPT_SCANDV_DID_RESET;
3428 completionCode = MPT_SCANDV_GOOD;
3429 hd->pLocal->scsiStatus = scsi_status;
3433 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
3434 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3435 completionCode = MPT_SCANDV_DID_RESET;
3437 completionCode = MPT_SCANDV_SOME_ERROR;
3441 completionCode = MPT_SCANDV_SOME_ERROR;
3444 } /* switch(status) */
3446 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
3448 } /* end of address reply case */
3450 hd->pLocal->completion = completionCode;
3452 /* MF and RF are freed in mpt_interrupt
3455 /* Free Chain buffers (will never chain) in scan or dv */
3456 //mptscsih_freeChainBuffers(ioc, req_idx);
3459 * Wake up the original calling thread
3461 hd->scandv_wait_done = 1;
3462 wake_up(&hd->scandv_waitq);
3467 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3468 /* mptscsih_timer_expired - Call back for timer process.
3469 * Used only for dv functionality.
3470 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3474 mptscsih_timer_expired(unsigned long data)
3476 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3478 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3481 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3483 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3484 /* Desire to issue a task management request here.
3485 * TM requests MUST be single threaded.
3486 * If old eh code and no TM current, issue request.
3487 * If new eh code, do nothing. Wait for OS cmd timeout
3490 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3492 /* Perform a FW reload */
3493 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3494 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3498 /* This should NEVER happen */
3499 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3502 /* No more processing.
3503 * TM call will generate an interrupt for SCSI TM Management.
3504 * The FW will reply to all outstanding commands, callback will finish cleanup.
3505 * Hard reset clean-up will free all resources.
3507 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3512 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3513 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3514 /* mptscsih_do_raid - Format and Issue a RAID volume request message.
3515 * @hd: Pointer to scsi host structure
3516 * @action: What do be done.
3517 * @id: Logical target id.
3518 * @bus: Target locations bus.
3520 * Returns: < 0 on a fatal error
3523 * Remark: Wait to return until reply processed by the ISR.
3526 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
3528 MpiRaidActionRequest_t *pReq;
3532 in_isr = in_interrupt();
3534 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
3539 /* Get and Populate a free Frame
3541 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3542 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
3546 pReq = (MpiRaidActionRequest_t *)mf;
3547 pReq->Action = action;
3548 pReq->Reserved1 = 0;
3549 pReq->ChainOffset = 0;
3550 pReq->Function = MPI_FUNCTION_RAID_ACTION;
3551 pReq->VolumeID = io->id;
3552 pReq->VolumeBus = io->bus;
3553 pReq->PhysDiskNum = io->physDiskNum;
3555 pReq->Reserved2 = 0;
3556 pReq->ActionDataWord = 0; /* Reserved for this action */
3557 //pReq->ActionDataSGE = 0;
3559 mpt_add_sge((char *)&pReq->ActionDataSGE,
3560 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
3562 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
3563 hd->ioc->name, action, io->id));
3566 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
3567 hd->scandv_wait_done = 0;
3569 /* Save cmd pointer, for resource free if timeout or
3574 add_timer(&hd->timer);
3575 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3576 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3578 if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
3583 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
3585 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3587 * mptscsih_do_cmd - Do internal command.
3588 * @hd: MPT_SCSI_HOST pointer
3589 * @io: INTERNAL_CMD pointer.
3591 * Issue the specified internally generated command and do command
3592 * specific cleanup. For bus scan / DV only.
3593 * NOTES: If command is Inquiry and status is good,
3594 * initialize a target structure, save the data
3596 * Remark: Single threaded access only.
3599 * < 0 if an illegal command or no resources
3603 * > 0 if command complete but some type of completion error.
3606 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3609 SCSIIORequest_t *pScsiReq;
3610 SCSIIORequest_t ReqCopy;
3611 int my_idx, ii, dir;
3615 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3618 in_isr = in_interrupt();
3620 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3626 /* Set command specific information
3631 dir = MPI_SCSIIO_CONTROL_READ;
3637 case TEST_UNIT_READY:
3639 dir = MPI_SCSIIO_CONTROL_READ;
3645 dir = MPI_SCSIIO_CONTROL_READ;
3647 CDB[4] = 1; /*Spin up the disk */
3655 dir = MPI_SCSIIO_CONTROL_READ;
3661 dir = MPI_SCSIIO_CONTROL_READ;
3663 if (io->flags & MPT_ICFLAG_ECHO) {
3669 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3672 CDB[6] = (io->size >> 16) & 0xFF;
3673 CDB[7] = (io->size >> 8) & 0xFF;
3674 CDB[8] = io->size & 0xFF;
3680 dir = MPI_SCSIIO_CONTROL_WRITE;
3682 if (io->flags & MPT_ICFLAG_ECHO) {
3687 CDB[6] = (io->size >> 16) & 0xFF;
3688 CDB[7] = (io->size >> 8) & 0xFF;
3689 CDB[8] = io->size & 0xFF;
3695 dir = MPI_SCSIIO_CONTROL_READ;
3702 dir = MPI_SCSIIO_CONTROL_READ;
3707 case SYNCHRONIZE_CACHE:
3709 dir = MPI_SCSIIO_CONTROL_READ;
3711 // CDB[1] = 0x02; /* set immediate bit */
3720 /* Get and Populate a free Frame
3722 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3723 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3728 pScsiReq = (SCSIIORequest_t *) mf;
3730 /* Get the request index */
3731 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3732 ADD_INDEX_LOG(my_idx); /* for debug */
3734 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3735 pScsiReq->TargetID = io->physDiskNum;
3737 pScsiReq->ChainOffset = 0;
3738 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3740 pScsiReq->TargetID = io->id;
3741 pScsiReq->Bus = io->bus;
3742 pScsiReq->ChainOffset = 0;
3743 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3746 pScsiReq->CDBLength = cmdLen;
3747 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3749 pScsiReq->Reserved = 0;
3751 pScsiReq->MsgFlags = mpt_msg_flags();
3752 /* MsgContext set in mpt_get_msg_fram call */
3754 for (ii=0; ii < 8; ii++)
3755 pScsiReq->LUN[ii] = 0;
3756 pScsiReq->LUN[1] = io->lun;
3758 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3759 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3761 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3763 if (cmd == REQUEST_SENSE) {
3764 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3765 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3766 hd->ioc->name, cmd));
3769 for (ii=0; ii < 16; ii++)
3770 pScsiReq->CDB[ii] = CDB[ii];
3772 pScsiReq->DataLength = cpu_to_le32(io->size);
3773 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3774 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3776 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3777 hd->ioc->name, cmd, io->bus, io->id, io->lun));
3779 if (dir == MPI_SCSIIO_CONTROL_READ) {
3780 mpt_add_sge((char *) &pScsiReq->SGL,
3781 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3784 mpt_add_sge((char *) &pScsiReq->SGL,
3785 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3789 /* The ISR will free the request frame, but we need
3790 * the information to initialize the target. Duplicate.
3792 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3794 /* Issue this command after:
3797 * Wait until the reply has been received
3798 * ScsiScanDvCtx callback function will
3800 * set scandv_wait_done and call wake_up
3803 hd->timer.expires = jiffies + HZ*cmdTimeout;
3804 hd->scandv_wait_done = 0;
3806 /* Save cmd pointer, for resource free if timeout or
3811 add_timer(&hd->timer);
3812 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3813 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3816 rc = hd->pLocal->completion;
3817 hd->pLocal->skip = 0;
3819 /* Always set fatal error codes in some cases.
3821 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3823 else if (rc == MPT_SCANDV_SOME_ERROR)
3827 /* This should never happen. */
3828 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3835 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3837 * mptscsih_negotiate_to_asyn_narrow - Restore devices to default state
3838 * @hd: Pointer to a SCSI HOST structure
3839 * @vtarget: per device private data
3841 * Uses the ISR, but with special processing.
3842 * MUST be single-threaded.
3846 mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
3848 MPT_ADAPTER *ioc= hd->ioc;
3849 SCSIDevicePage1_t *pcfg1Data;
3851 dma_addr_t cfg1_dma_addr;
3852 ConfigPageHeader_t header;
3854 int requested, configuration, data,i;
3857 if (ioc->bus_type != SPI)
3860 if (!ioc->spi_data.sdp1length)
3863 pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
3864 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
3866 if (pcfg1Data == NULL)
3869 header.PageVersion = ioc->spi_data.sdp1version;
3870 header.PageLength = ioc->spi_data.sdp1length;
3871 header.PageNumber = 1;
3872 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3873 cfg.cfghdr.hdr = &header;
3874 cfg.physAddr = cfg1_dma_addr;
3875 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3879 if (vtarget->raidVolume && ioc->raid_data.pIocPg3) {
3880 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
3881 id = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID;
3882 flags = hd->ioc->spi_data.noQas;
3883 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3884 data = hd->ioc->spi_data.nvram[id];
3885 if (data & MPT_NVRAM_WIDE_DISABLE)
3886 flags |= MPT_TARGET_NO_NEGO_WIDE;
3887 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
3888 if ((factor == 0) || (factor == MPT_ASYNC))
3889 flags |= MPT_TARGET_NO_NEGO_SYNC;
3891 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
3892 &configuration, flags);
3893 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
3894 "offset=0 negoFlags=%x request=%x config=%x\n",
3895 id, flags, requested, configuration));
3896 pcfg1Data->RequestedParameters = cpu_to_le32(requested);
3897 pcfg1Data->Reserved = 0;
3898 pcfg1Data->Configuration = cpu_to_le32(configuration);
3899 cfg.pageAddr = (vtarget->bus_id<<8) | id;
3900 mpt_config(hd->ioc, &cfg);
3903 flags = vtarget->negoFlags;
3904 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
3905 &configuration, flags);
3906 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
3907 "offset=0 negoFlags=%x request=%x config=%x\n",
3908 vtarget->target_id, flags, requested, configuration));
3909 pcfg1Data->RequestedParameters = cpu_to_le32(requested);
3910 pcfg1Data->Reserved = 0;
3911 pcfg1Data->Configuration = cpu_to_le32(configuration);
3912 cfg.pageAddr = (vtarget->bus_id<<8) | vtarget->target_id;
3913 mpt_config(hd->ioc, &cfg);
3917 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pcfg1Data, cfg1_dma_addr);
3920 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3922 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3923 * @hd: Pointer to a SCSI HOST structure
3924 * @vtarget: per device private data
3927 * Uses the ISR, but with special processing.
3928 * MUST be single-threaded.
3932 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3936 /* Following parameters will not change
3939 iocmd.cmd = SYNCHRONIZE_CACHE;
3941 iocmd.physDiskNum = -1;
3943 iocmd.data_dma = -1;
3945 iocmd.rsvd = iocmd.rsvd2 = 0;
3946 iocmd.bus = vdevice->bus_id;
3947 iocmd.id = vdevice->target_id;
3948 iocmd.lun = (u8)vdevice->lun;
3950 if ((vdevice->vtarget->type & TYPE_DISK) &&
3951 (vdevice->configured_lun))
3952 mptscsih_do_cmd(hd, &iocmd);
3955 /* Search IOC page 3 to determine if this is hidden physical disk
3958 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
3962 if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
3965 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
3966 if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
3973 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3974 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3976 * mptscsih_domainValidation - Top level handler for domain validation.
3977 * @hd: Pointer to MPT_SCSI_HOST structure.
3979 * Uses the ISR, but with special processing.
3980 * Called from schedule, should not be in interrupt mode.
3981 * While thread alive, do dv for all devices needing dv
3986 mptscsih_domainValidation(void *arg)
3990 unsigned long flags;
3991 int id, maxid, dvStatus, did;
3994 spin_lock_irqsave(&dvtaskQ_lock, flags);
3996 if (dvtaskQ_release) {
3998 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4001 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4003 /* For this ioc, loop through all devices and do dv to each device.
4004 * When complete with this ioc, search through the ioc list, and
4005 * for each scsi ioc found, do dv for all devices. Exit when no
4011 list_for_each_entry(ioc, &ioc_list, list) {
4012 spin_lock_irqsave(&dvtaskQ_lock, flags);
4013 if (dvtaskQ_release) {
4015 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4018 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4022 /* DV only to SPI adapters */
4023 if (ioc->bus_type != SPI)
4026 /* Make sure everything looks ok */
4027 if (ioc->sh == NULL)
4030 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4034 if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
4035 mpt_read_ioc_pg_3(ioc);
4036 if (ioc->raid_data.pIocPg3) {
4037 Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
4038 int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
4041 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
4042 ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4048 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
4051 maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
4053 for (id = 0; id < maxid; id++) {
4054 spin_lock_irqsave(&dvtaskQ_lock, flags);
4055 if (dvtaskQ_release) {
4057 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4060 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4061 dvStatus = hd->ioc->spi_data.dvStatus[id];
4063 if (dvStatus & MPT_SCSICFG_NEED_DV) {
4065 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
4066 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
4070 /* If hidden phys disk, block IO's to all
4072 * else, process normally
4074 isPhysDisk = mptscsih_is_phys_disk(ioc, id);
4076 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4077 if (hd->ioc->raid_data.isRaid & (1 << ii)) {
4078 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
4083 if(mpt_alt_ioc_wait(hd->ioc)!=0) {
4084 ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n",
4089 if (mptscsih_doDv(hd, 0, id) == 1) {
4090 /* Untagged device was busy, try again
4092 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
4093 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
4095 /* DV is complete. Clear flags.
4097 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
4100 spin_lock(&hd->ioc->initializing_hba_lock);
4101 hd->ioc->initializing_hba_lock_flag=0;
4102 spin_unlock(&hd->ioc->initializing_hba_lock);
4105 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4106 if (hd->ioc->raid_data.isRaid & (1 << ii)) {
4107 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
4112 if (hd->ioc->spi_data.noQas)
4113 mptscsih_qas_check(hd, id);
4119 spin_lock_irqsave(&dvtaskQ_lock, flags);
4121 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4126 /* Write SDP1 if no QAS has been enabled
4129 mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
4131 VirtTarget *vtarget;
4134 if (hd->Targets == NULL)
4137 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4141 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
4144 vtarget = hd->Targets[ii];
4146 if ((vtarget != NULL) && (!vtarget->raidVolume)) {
4147 if ((vtarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
4148 vtarget->negoFlags |= hd->ioc->spi_data.noQas;
4149 dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
4150 mptscsih_writeSDP1(hd, 0, ii, 0);
4153 if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
4154 dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
4155 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
4164 #define MPT_GET_NVRAM_VALS 0x01
4165 #define MPT_UPDATE_MAX 0x02
4166 #define MPT_SET_MAX 0x04
4167 #define MPT_SET_MIN 0x08
4168 #define MPT_FALLBACK 0x10
4169 #define MPT_SAVE 0x20
4171 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4173 * mptscsih_doDv - Perform domain validation to a target.
4174 * @hd: Pointer to MPT_SCSI_HOST structure.
4175 * @portnum: IOC port number.
4176 * @target: Physical ID of this target
4178 * Uses the ISR, but with special processing.
4179 * MUST be single-threaded.
4180 * Test will exit if target is at async & narrow.
4185 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
4187 MPT_ADAPTER *ioc = hd->ioc;
4188 VirtTarget *vtarget;
4189 SCSIDevicePage1_t *pcfg1Data;
4190 SCSIDevicePage0_t *pcfg0Data;
4194 dma_addr_t dvbuf_dma = -1;
4195 dma_addr_t buf1_dma = -1;
4196 dma_addr_t buf2_dma = -1;
4197 dma_addr_t cfg1_dma_addr = -1;
4198 dma_addr_t cfg0_dma_addr = -1;
4199 ConfigPageHeader_t header1;
4200 ConfigPageHeader_t header0;
4207 int dataBufSize = 0;
4208 int echoBufSize = 0;
4213 int nfactor = MPT_ULTRA320;
4215 char doFallback = 0;
4220 if (ioc->spi_data.sdp1length == 0)
4223 if (ioc->spi_data.sdp0length == 0)
4226 /* If multiple buses are used, require that the initiator
4227 * id be the same on all buses.
4229 if (id == ioc->pfacts[0].PortSCSIID)
4233 bus = (u8) bus_number;
4234 ddvtprintk((MYIOC_s_NOTE_FMT
4235 "DV started: bus=%d, id=%d dv @ %p\n",
4236 ioc->name, bus, id, &dv));
4238 /* Prep DV structure
4240 memset (&dv, 0, sizeof(DVPARAMETERS));
4243 /* Populate tmax with the current maximum
4244 * transfer parameters for this target.
4245 * Exit if narrow and async.
4247 dv.cmd = MPT_GET_NVRAM_VALS;
4248 mptscsih_dv_parms(hd, &dv, NULL);
4250 /* Prep SCSI IO structure
4256 iocmd.physDiskNum = -1;
4257 iocmd.rsvd = iocmd.rsvd2 = 0;
4259 vtarget = hd->Targets[id];
4261 /* Use tagged commands if possible.
4264 if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
4265 iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
4267 if (hd->ioc->facts.FWVersion.Word < 0x01000600)
4270 if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4271 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
4276 /* Prep cfg structure
4278 cfg.pageAddr = (bus<<8) | id;
4279 cfg.cfghdr.hdr = NULL;
4283 header0.PageVersion = ioc->spi_data.sdp0version;
4284 header0.PageLength = ioc->spi_data.sdp0length;
4285 header0.PageNumber = 0;
4286 header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4290 header1.PageVersion = ioc->spi_data.sdp1version;
4291 header1.PageLength = ioc->spi_data.sdp1length;
4292 header1.PageNumber = 1;
4293 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4295 if (header0.PageLength & 1)
4296 dv_alloc = (header0.PageLength * 4) + 4;
4298 dv_alloc += (2048 + (header1.PageLength * 4));
4300 pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
4305 pbuf1 = (u8 *)pDvBuf;
4306 buf1_dma = dvbuf_dma;
4309 pbuf2 = (u8 *) (pDvBuf + sz);
4310 buf2_dma = dvbuf_dma + sz;
4313 pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
4314 cfg0_dma_addr = dvbuf_dma + sz;
4315 sz += header0.PageLength * 4;
4319 if (header0.PageLength & 1)
4322 pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
4323 cfg1_dma_addr = dvbuf_dma + sz;
4325 /* Skip this ID? Set cfg.cfghdr.hdr to force config page write
4328 SpiCfgData *pspi_data = &hd->ioc->spi_data;
4329 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4330 /* Set the factor from nvram */
4331 nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
4332 if (nfactor < pspi_data->minSyncFactor )
4333 nfactor = pspi_data->minSyncFactor;
4335 if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
4336 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
4338 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
4339 ioc->name, bus, id, lun));
4341 dv.cmd = MPT_SET_MAX;
4342 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4343 cfg.cfghdr.hdr = &header1;
4345 /* Save the final negotiated settings to
4346 * SCSI device page 1.
4348 cfg.physAddr = cfg1_dma_addr;
4349 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4351 mpt_config(hd->ioc, &cfg);
4357 /* Finish iocmd inititialization - hidden or visible disk? */
4358 if (ioc->raid_data.pIocPg3) {
4359 /* Search IOC page 3 for matching id
4361 Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
4362 int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
4365 if (pPDisk->PhysDiskID == id) {
4367 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
4368 iocmd.physDiskNum = pPDisk->PhysDiskNum;
4372 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
4373 ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
4383 /* RAID Volume ID's may double for a physical device. If RAID but
4384 * not a physical ID as well, skip DV.
4386 if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
4391 * Async & Narrow - Inquiry
4392 * Async & Narrow - Inquiry
4393 * Maximum transfer rate - Inquiry
4395 * If compare, test complete.
4396 * If miscompare and first pass, repeat
4397 * If miscompare and not first pass, fall back and repeat
4401 sz = SCSI_MAX_INQUIRY_BYTES;
4402 rc = MPT_SCANDV_GOOD;
4404 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
4406 dv.cmd = MPT_SET_MIN;
4407 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4409 cfg.cfghdr.hdr = &header1;
4410 cfg.physAddr = cfg1_dma_addr;
4411 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4413 if (mpt_config(hd->ioc, &cfg) != 0)
4416 /* Wide - narrow - wide workaround case
4418 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
4419 /* Send an untagged command to reset disk Qs corrupted
4420 * when a parity error occurs on a Request Sense.
4422 if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
4423 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4424 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
4426 iocmd.cmd = REQUEST_SENSE;
4427 iocmd.data_dma = buf1_dma;
4430 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4433 if (hd->pLocal == NULL)
4435 rc = hd->pLocal->completion;
4436 if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
4446 iocmd.cmd = INQUIRY;
4447 iocmd.data_dma = buf1_dma;
4450 memset(pbuf1, 0x00, sz);
4451 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4454 if (hd->pLocal == NULL)
4456 rc = hd->pLocal->completion;
4457 if (rc == MPT_SCANDV_GOOD) {
4458 if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
4459 if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
4466 } else if (rc == MPT_SCANDV_SENSE) {
4469 /* If first command doesn't complete
4470 * with a good status or with a check condition,
4477 /* Reset the size for disks
4479 inq0 = (*pbuf1) & 0x1F;
4480 if ((inq0 == 0) && vtarget && !vtarget->raidVolume) {
4485 /* Another GEM workaround. Check peripheral device type,
4486 * if PROCESSOR, quit DV.
4488 if (inq0 == TYPE_PROCESSOR) {
4489 mptscsih_initTarget(hd,
4500 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4504 if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A)
4505 && (vtarget->minSyncFactor > 0x09)) {
4506 if ((pbuf1[56] & 0x04) == 0)
4508 else if ((pbuf1[56] & 0x01) == 1) {
4509 vtarget->minSyncFactor =
4510 nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
4512 vtarget->minSyncFactor =
4513 nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
4516 dv.max.factor = vtarget->minSyncFactor;
4518 if ((pbuf1[56] & 0x02) == 0) {
4519 vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4520 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
4521 ddvprintk((MYIOC_s_NOTE_FMT
4522 "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
4523 ioc->name, id, pbuf1[56]));
4529 dv.cmd = MPT_FALLBACK;
4531 dv.cmd = MPT_SET_MAX;
4533 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4534 if (mpt_config(hd->ioc, &cfg) != 0)
4537 if ((!dv.now.width) && (!dv.now.offset))
4540 iocmd.cmd = INQUIRY;
4541 iocmd.data_dma = buf2_dma;
4544 memset(pbuf2, 0x00, sz);
4545 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4547 else if (hd->pLocal == NULL)
4550 /* Save the return code.
4551 * If this is the first pass,
4552 * read SCSI Device Page 0
4553 * and update the target max parameters.
4555 rc = hd->pLocal->completion;
4557 if (rc == MPT_SCANDV_GOOD) {
4562 cfg.cfghdr.hdr = &header0;
4563 cfg.physAddr = cfg0_dma_addr;
4564 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4567 if (mpt_config(hd->ioc, &cfg) != 0)
4570 sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
4571 sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
4573 /* Quantum and Fujitsu workarounds.
4574 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
4575 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
4576 * Resetart with a request for U160.
4578 if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
4581 dv.cmd = MPT_UPDATE_MAX;
4582 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
4583 /* Update the SCSI device page 1 area
4585 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
4590 /* Quantum workaround. Restart this test will the fallback
4593 if (doFallback == 0) {
4594 if (memcmp(pbuf1, pbuf2, sz) != 0) {
4598 ddvprintk((MYIOC_s_NOTE_FMT
4599 "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
4600 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
4601 mptscsih_initTarget(hd,
4606 break; /* test complete */
4611 } else if (rc == MPT_SCANDV_ISSUE_SENSE)
4612 doFallback = 1; /* set fallback flag */
4613 else if ((rc == MPT_SCANDV_DID_RESET) ||
4614 (rc == MPT_SCANDV_SENSE) ||
4615 (rc == MPT_SCANDV_FALLBACK))
4616 doFallback = 1; /* set fallback flag */
4623 ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
4625 if (ioc->spi_data.mpt_dv == 0)
4628 inq0 = (*pbuf1) & 0x1F;
4630 /* Continue only for disks
4635 if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
4638 /* Start the Enhanced Test.
4639 * 0) issue TUR to clear out check conditions
4640 * 1) read capacity of echo (regular) buffer
4642 * 3) do write-read-compare data pattern test
4644 * 5) update nego parms to target struct
4646 cfg.cfghdr.hdr = &header1;
4647 cfg.physAddr = cfg1_dma_addr;
4648 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4651 iocmd.cmd = TEST_UNIT_READY;
4652 iocmd.data_dma = -1;
4657 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4660 if (hd->pLocal == NULL)
4663 rc = hd->pLocal->completion;
4664 if (rc == MPT_SCANDV_GOOD)
4666 else if (rc == MPT_SCANDV_SENSE) {
4667 u8 skey = hd->pLocal->sense[2] & 0x0F;
4668 u8 asc = hd->pLocal->sense[12];
4669 u8 ascq = hd->pLocal->sense[13];
4670 ddvprintk((MYIOC_s_INFO_FMT
4671 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4672 ioc->name, skey, asc, ascq));
4674 if (skey == UNIT_ATTENTION)
4675 notDone++; /* repeat */
4676 else if ((skey == NOT_READY) &&
4677 (asc == 0x04)&&(ascq == 0x01)) {
4678 /* wait then repeat */
4681 } else if ((skey == NOT_READY) && (asc == 0x3A)) {
4682 /* no medium, try read test anyway */
4685 /* All other errors are fatal.
4687 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4695 iocmd.cmd = READ_BUFFER;
4696 iocmd.data_dma = buf1_dma;
4699 iocmd.flags |= MPT_ICFLAG_BUF_CAP;
4703 for (patt = 0; patt < 2; patt++) {
4705 iocmd.flags |= MPT_ICFLAG_ECHO;
4707 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4713 /* If not ready after 8 trials,
4714 * give up on this device.
4719 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4721 else if (hd->pLocal == NULL)
4724 rc = hd->pLocal->completion;
4725 ddvprintk(("ReadBuffer Comp Code %d", rc));
4726 ddvprintk((" buff: %0x %0x %0x %0x\n",
4727 pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
4729 if (rc == MPT_SCANDV_GOOD) {
4731 if (iocmd.flags & MPT_ICFLAG_ECHO) {
4732 bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
4733 if (pbuf1[0] & 0x01)
4734 iocmd.flags |= MPT_ICFLAG_EBOS;
4736 bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
4738 } else if (rc == MPT_SCANDV_SENSE) {
4739 u8 skey = hd->pLocal->sense[2] & 0x0F;
4740 u8 asc = hd->pLocal->sense[12];
4741 u8 ascq = hd->pLocal->sense[13];
4742 ddvprintk((MYIOC_s_INFO_FMT
4743 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4744 ioc->name, skey, asc, ascq));
4745 if (skey == ILLEGAL_REQUEST) {
4747 } else if (skey == UNIT_ATTENTION) {
4748 notDone++; /* repeat */
4749 } else if ((skey == NOT_READY) &&
4750 (asc == 0x04)&&(ascq == 0x01)) {
4751 /* wait then repeat */
4755 /* All other errors are fatal.
4757 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4762 /* All other errors are fatal
4769 if (iocmd.flags & MPT_ICFLAG_ECHO)
4770 echoBufSize = bufsize;
4772 dataBufSize = bufsize;
4775 iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
4777 /* Use echo buffers if possible,
4778 * Exit if both buffers are 0.
4780 if (echoBufSize > 0) {
4781 iocmd.flags |= MPT_ICFLAG_ECHO;
4782 if (dataBufSize > 0)
4783 bufsize = min(echoBufSize, dataBufSize);
4785 bufsize = echoBufSize;
4786 } else if (dataBufSize == 0)
4789 ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
4790 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
4792 /* Data buffers for write-read-compare test max 1K.
4794 sz = min(bufsize, 1024);
4797 * On first pass, always issue a reserve.
4798 * On additional loops, only if a reset has occurred.
4799 * iocmd.flags indicates if echo or regular buffer
4801 for (patt = 0; patt < 4; patt++) {
4802 ddvprintk(("Pattern %d\n", patt));
4803 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
4804 iocmd.cmd = TEST_UNIT_READY;
4805 iocmd.data_dma = -1;
4808 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4811 iocmd.cmd = RELEASE;
4812 iocmd.data_dma = -1;
4815 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4817 else if (hd->pLocal == NULL)
4820 rc = hd->pLocal->completion;
4821 ddvprintk(("Release rc %d\n", rc));
4822 if (rc == MPT_SCANDV_GOOD)
4823 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4827 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4829 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
4831 if (iocmd.flags & MPT_ICFLAG_EBOS)
4835 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
4836 iocmd.cmd = RESERVE;
4837 iocmd.data_dma = -1;
4840 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4842 else if (hd->pLocal == NULL)
4845 rc = hd->pLocal->completion;
4846 if (rc == MPT_SCANDV_GOOD) {
4847 iocmd.flags |= MPT_ICFLAG_RESERVED;
4848 } else if (rc == MPT_SCANDV_SENSE) {
4849 /* Wait if coming ready
4851 u8 skey = hd->pLocal->sense[2] & 0x0F;
4852 u8 asc = hd->pLocal->sense[12];
4853 u8 ascq = hd->pLocal->sense[13];
4854 ddvprintk((MYIOC_s_INFO_FMT
4855 "DV: Reserve Failed: ", ioc->name));
4856 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4859 if ((skey == NOT_READY) && (asc == 0x04)&&
4861 /* wait then repeat */
4865 ddvprintk((MYIOC_s_INFO_FMT
4866 "DV: Reserved Failed.", ioc->name));
4870 ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
4878 mptscsih_fillbuf(pbuf1, sz, patt, 1);
4879 iocmd.cmd = WRITE_BUFFER;
4880 iocmd.data_dma = buf1_dma;
4883 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4885 else if (hd->pLocal == NULL)
4888 rc = hd->pLocal->completion;
4889 if (rc == MPT_SCANDV_GOOD)
4890 ; /* Issue read buffer */
4891 else if (rc == MPT_SCANDV_DID_RESET) {
4892 /* If using echo buffers, reset to data buffers.
4893 * Else do Fallback and restart
4894 * this test (re-issue reserve
4895 * because of bus reset).
4897 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
4898 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4900 dv.cmd = MPT_FALLBACK;
4901 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4903 if (mpt_config(hd->ioc, &cfg) != 0)
4906 if ((!dv.now.width) && (!dv.now.offset))
4910 iocmd.flags |= MPT_ICFLAG_DID_RESET;
4913 } else if (rc == MPT_SCANDV_SENSE) {
4914 /* Restart data test if UA, else quit.
4916 u8 skey = hd->pLocal->sense[2] & 0x0F;
4917 ddvprintk((MYIOC_s_INFO_FMT
4918 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
4919 hd->pLocal->sense[12], hd->pLocal->sense[13]));
4920 if (skey == UNIT_ATTENTION) {
4923 } else if (skey == ILLEGAL_REQUEST) {
4924 if (iocmd.flags & MPT_ICFLAG_ECHO) {
4925 if (dataBufSize >= bufsize) {
4926 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4941 iocmd.cmd = READ_BUFFER;
4942 iocmd.data_dma = buf2_dma;
4945 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4947 else if (hd->pLocal == NULL)
4950 rc = hd->pLocal->completion;
4951 if (rc == MPT_SCANDV_GOOD) {
4952 /* If buffers compare,
4953 * go to next pattern,
4954 * else, do a fallback and restart
4955 * data transfer test.
4957 if (memcmp (pbuf1, pbuf2, sz) == 0) {
4958 ; /* goto next pattern */
4960 /* Miscompare with Echo buffer, go to data buffer,
4961 * if that buffer exists.
4962 * Miscompare with Data buffer, check first 4 bytes,
4963 * some devices return capacity. Exit in this case.
4965 if (iocmd.flags & MPT_ICFLAG_ECHO) {
4966 if (dataBufSize >= bufsize)
4967 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4971 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
4972 /* Argh. Device returning wrong data.
4973 * Quit DV for this device.
4978 /* Had an actual miscompare. Slow down.*/
4979 dv.cmd = MPT_FALLBACK;
4980 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4982 if (mpt_config(hd->ioc, &cfg) != 0)
4985 if ((!dv.now.width) && (!dv.now.offset))
4992 } else if (rc == MPT_SCANDV_DID_RESET) {
4993 /* Do Fallback and restart
4994 * this test (re-issue reserve
4995 * because of bus reset).
4997 dv.cmd = MPT_FALLBACK;
4998 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5000 if (mpt_config(hd->ioc, &cfg) != 0)
5003 if ((!dv.now.width) && (!dv.now.offset))
5006 iocmd.flags |= MPT_ICFLAG_DID_RESET;
5009 } else if (rc == MPT_SCANDV_SENSE) {
5010 /* Restart data test if UA, else quit.
5012 u8 skey = hd->pLocal->sense[2] & 0x0F;
5013 ddvprintk((MYIOC_s_INFO_FMT
5014 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
5015 hd->pLocal->sense[12], hd->pLocal->sense[13]));
5016 if (skey == UNIT_ATTENTION) {
5028 } /* --- end of patt loop ---- */
5031 if (iocmd.flags & MPT_ICFLAG_RESERVED) {
5032 iocmd.cmd = RELEASE;
5033 iocmd.data_dma = -1;
5036 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5037 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5039 else if (hd->pLocal) {
5040 if (hd->pLocal->completion == MPT_SCANDV_GOOD)
5041 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
5043 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5049 /* Set if cfg1_dma_addr contents is valid
5051 if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){
5052 /* If disk, not U320, disable QAS
5054 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
5055 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
5056 ddvprintk((MYIOC_s_NOTE_FMT
5057 "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
5061 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5063 /* Double writes to SDP1 can cause problems,
5064 * skip save of the final negotiated settings to
5065 * SCSI device page 1.
5067 cfg.cfghdr.hdr = &header1;
5068 cfg.physAddr = cfg1_dma_addr;
5069 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5071 mpt_config(hd->ioc, &cfg);
5075 /* If this is a RAID Passthrough, enable internal IOs
5077 if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
5078 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
5079 ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
5082 /* Done with the DV scan of the current target
5085 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
5087 ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
5093 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5094 /* mptscsih_dv_parms - perform a variety of operations on the
5095 * parameters used for negotiation.
5096 * @hd: Pointer to a SCSI host.
5097 * @dv: Pointer to a structure that contains the maximum and current
5098 * negotiated parameters.
5101 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
5103 VirtTarget *vtarget;
5104 SCSIDevicePage0_t *pPage0;
5105 SCSIDevicePage1_t *pPage1;
5106 int val = 0, data, configuration;
5115 case MPT_GET_NVRAM_VALS:
5116 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
5118 /* Get the NVRAM values and save in tmax
5119 * If not an LVD bus, the adapter minSyncFactor has been
5120 * already throttled back.
5122 negoFlags = hd->ioc->spi_data.noQas;
5123 if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume) {
5124 width = vtarget->maxWidth;
5125 offset = vtarget->maxOffset;
5126 factor = vtarget->minSyncFactor;
5127 negoFlags |= vtarget->negoFlags;
5129 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5130 data = hd->ioc->spi_data.nvram[id];
5131 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
5132 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
5135 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5136 if ((factor == 0) || (factor == MPT_ASYNC)){
5147 /* Set the negotiation flags */
5149 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
5152 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
5155 /* limit by adapter capabilities */
5156 width = min(width, hd->ioc->spi_data.maxBusWidth);
5157 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
5158 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
5160 /* Check Consistency */
5161 if (offset && (factor < MPT_ULTRA2) && !width)
5162 factor = MPT_ULTRA2;
5164 dv->max.width = width;
5165 dv->max.offset = offset;
5166 dv->max.factor = factor;
5167 dv->max.flags = negoFlags;
5168 ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
5169 id, width, factor, offset, negoFlags));
5172 case MPT_UPDATE_MAX:
5173 ddvprintk((MYIOC_s_NOTE_FMT
5174 "Updating with SDP0 Data: ", hd->ioc->name));
5175 /* Update tmax values with those from Device Page 0.*/
5176 pPage0 = (SCSIDevicePage0_t *) pPage;
5178 val = le32_to_cpu(pPage0->NegotiatedParameters);
5179 dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
5180 dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
5181 dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
5184 dv->now.width = dv->max.width;
5185 dv->now.offset = dv->max.offset;
5186 dv->now.factor = dv->max.factor;
5187 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
5188 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5192 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
5194 /* Set current to the max values. Update the config page.*/
5195 dv->now.width = dv->max.width;
5196 dv->now.offset = dv->max.offset;
5197 dv->now.factor = dv->max.factor;
5198 dv->now.flags = dv->max.flags;
5200 pPage1 = (SCSIDevicePage1_t *)pPage;
5202 mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
5203 dv->now.offset, &val, &configuration, dv->now.flags);
5204 dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5205 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5206 pPage1->RequestedParameters = cpu_to_le32(val);
5207 pPage1->Reserved = 0;
5208 pPage1->Configuration = cpu_to_le32(configuration);
5211 ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
5212 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5216 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
5218 /* Set page to asynchronous and narrow
5219 * Do not update now, breaks fallback routine. */
5223 negoFlags = dv->max.flags;
5225 pPage1 = (SCSIDevicePage1_t *)pPage;
5227 mptscsih_setDevicePage1Flags (width, factor,
5228 offset, &val, &configuration, negoFlags);
5229 dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5230 id, width, factor, offset, negoFlags, val, configuration));
5231 pPage1->RequestedParameters = cpu_to_le32(val);
5232 pPage1->Reserved = 0;
5233 pPage1->Configuration = cpu_to_le32(configuration);
5235 ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
5236 id, width, factor, offset, val, configuration, negoFlags));
5240 ddvprintk((MYIOC_s_NOTE_FMT
5241 "Fallback: Start: offset %d, factor %x, width %d \n",
5242 hd->ioc->name, dv->now.offset,
5243 dv->now.factor, dv->now.width));
5244 width = dv->now.width;
5245 offset = dv->now.offset;
5246 factor = dv->now.factor;
5247 if ((offset) && (dv->max.width)) {
5248 if (factor < MPT_ULTRA160)
5249 factor = MPT_ULTRA160;
5250 else if (factor < MPT_ULTRA2) {
5251 factor = MPT_ULTRA2;
5253 } else if ((factor == MPT_ULTRA2) && width) {
5254 factor = MPT_ULTRA2;
5256 } else if (factor < MPT_ULTRA) {
5259 } else if ((factor == MPT_ULTRA) && width) {
5261 } else if (factor < MPT_FAST) {
5264 } else if ((factor == MPT_FAST) && width) {
5267 } else if (factor < MPT_SCSI) {
5270 } else if ((factor == MPT_SCSI) && width) {
5278 } else if (offset) {
5280 if (factor < MPT_ULTRA)
5282 else if (factor < MPT_FAST)
5284 else if (factor < MPT_SCSI)
5295 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
5296 dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
5298 dv->now.width = width;
5299 dv->now.offset = offset;
5300 dv->now.factor = factor;
5301 dv->now.flags = dv->max.flags;
5303 pPage1 = (SCSIDevicePage1_t *)pPage;
5305 mptscsih_setDevicePage1Flags (width, factor, offset, &val,
5306 &configuration, dv->now.flags);
5307 dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
5308 id, width, offset, factor, dv->now.flags, val, configuration));
5310 pPage1->RequestedParameters = cpu_to_le32(val);
5311 pPage1->Reserved = 0;
5312 pPage1->Configuration = cpu_to_le32(configuration);
5315 ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
5316 id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
5320 ddvprintk((MYIOC_s_NOTE_FMT
5321 "Saving to Target structure: ", hd->ioc->name));
5322 ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
5323 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5325 /* Save these values to target structures
5326 * or overwrite nvram (phys disks only).
5329 if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume ) {
5330 vtarget->maxWidth = dv->now.width;
5331 vtarget->maxOffset = dv->now.offset;
5332 vtarget->minSyncFactor = dv->now.factor;
5333 vtarget->negoFlags = dv->now.flags;
5335 /* Preserv all flags, use
5336 * read-modify-write algorithm
5338 if (hd->ioc->spi_data.nvram) {
5339 data = hd->ioc->spi_data.nvram[id];
5342 data &= ~MPT_NVRAM_WIDE_DISABLE;
5344 data |= MPT_NVRAM_WIDE_DISABLE;
5346 if (!dv->now.offset)
5349 data &= ~MPT_NVRAM_SYNC_MASK;
5350 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
5352 hd->ioc->spi_data.nvram[id] = data;
5359 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5360 /* mptscsih_fillbuf - fill a buffer with a special data pattern
5361 * cleanup. For bus scan only.
5363 * @buffer: Pointer to data buffer to be filled.
5364 * @size: Number of bytes to fill
5365 * @index: Pattern index
5366 * @width: bus width, 0 (8 bits) or 1 (16 bits)
5369 mptscsih_fillbuf(char *buffer, int size, int index, int width)
5380 /* Pattern: 0000 FFFF 0000 FFFF
5382 for (ii=0; ii < size; ii++, ptr++) {
5389 /* Pattern: 00 FF 00 FF
5391 for (ii=0; ii < size; ii++, ptr++) {
5402 /* Pattern: 5555 AAAA 5555 AAAA 5555
5404 for (ii=0; ii < size; ii++, ptr++) {
5411 /* Pattern: 55 AA 55 AA 55
5413 for (ii=0; ii < size; ii++, ptr++) {
5423 /* Pattern: 00 01 02 03 04 05
5426 for (ii=0; ii < size; ii++, ptr++)
5432 /* Wide Pattern: FFFE 0001 FFFD 0002
5433 * ... 4000 DFFF 8000 EFFF
5436 for (ii=0; ii < size/2; ii++) {
5437 /* Create the base pattern
5440 /* every 64 (0x40) bytes flip the pattern
5441 * since we fill 2 bytes / iteration,
5442 * test for ii = 0x20
5448 *ptr = (char)( (val & 0xFF00) >> 8);
5450 *ptr = (char)(val & 0xFF);
5455 *ptr = (char)( (val & 0xFF00) >> 8);
5457 *ptr = (char)(val & 0xFF);
5463 /* Narrow Pattern: FE 01 FD 02 FB 04
5464 * .. 7F 80 01 FE 02 FD ... 80 7F
5467 for (ii=0; ii < size; ii++, ptr++) {
5468 /* Base pattern - first 32 bytes
5475 *ptr = (char) (~(1 << byte));
5478 /* Flip the pattern every 32 bytes
5488 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5489 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
5490 * Else set the NEED_DV flag after Read Capacity Issued (disks)
5491 * or Mode Sense (cdroms).
5493 * Tapes, initTarget will set this flag on completion of Inquiry command.
5494 * Called only if DV_NOT_DONE flag is set
5497 mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
5499 MPT_ADAPTER *ioc = hd->ioc;
5503 ddvtprintk((MYIOC_s_NOTE_FMT
5504 " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
5505 hd->ioc->name, sc->device->id, sc->device->lun , hd->negoNvram, sc->cmnd[0]));
5507 if ((sc->device->lun != 0) || (hd->negoNvram != 0))
5512 if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
5513 pSpi = &ioc->spi_data;
5514 if ((ioc->raid_data.isRaid & (1 << sc->device->id)) && ioc->raid_data.pIocPg3) {
5515 /* Set NEED_DV for all hidden disks
5517 Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
5518 int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
5521 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
5522 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
5527 pSpi->dvStatus[sc->device->id] |= MPT_SCSICFG_NEED_DV;
5528 ddvtprintk(("NEED_DV set for visible disk id %d\n", sc->device->id));
5532 /* mptscsih_raid_set_dv_flags()
5534 * New or replaced disk. Set DV flag and schedule DV.
5537 mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
5539 MPT_ADAPTER *ioc = hd->ioc;
5540 SpiCfgData *pSpi = &ioc->spi_data;
5541 Ioc3PhysDisk_t *pPDisk;
5544 if (hd->negoNvram != 0)
5547 ddvtprintk(("DV requested for phys disk id %d\n", id));
5548 if (ioc->raid_data.pIocPg3) {
5549 pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
5550 numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
5552 if (id == pPDisk->PhysDiskNum) {
5553 pSpi->dvStatus[pPDisk->PhysDiskID] =
5554 (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
5555 pSpi->forceDv = MPT_SCSICFG_NEED_DV;
5556 ddvtprintk(("NEED_DV set for phys disk id %d\n",
5557 pPDisk->PhysDiskID));
5564 if (numPDisk == 0) {
5565 /* The physical disk that needs DV was not found
5566 * in the stored IOC Page 3. The driver must reload
5567 * this page. DV routine will set the NEED_DV flag for
5568 * all phys disks that have DV_NOT_DONE set.
5570 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
5571 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
5575 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5577 EXPORT_SYMBOL(mptscsih_remove);
5578 EXPORT_SYMBOL(mptscsih_shutdown);
5580 EXPORT_SYMBOL(mptscsih_suspend);
5581 EXPORT_SYMBOL(mptscsih_resume);
5583 EXPORT_SYMBOL(mptscsih_proc_info);
5584 EXPORT_SYMBOL(mptscsih_info);
5585 EXPORT_SYMBOL(mptscsih_qcmd);
5586 EXPORT_SYMBOL(mptscsih_target_alloc);
5587 EXPORT_SYMBOL(mptscsih_slave_alloc);
5588 EXPORT_SYMBOL(mptscsih_target_destroy);
5589 EXPORT_SYMBOL(mptscsih_slave_destroy);
5590 EXPORT_SYMBOL(mptscsih_slave_configure);
5591 EXPORT_SYMBOL(mptscsih_abort);
5592 EXPORT_SYMBOL(mptscsih_dev_reset);
5593 EXPORT_SYMBOL(mptscsih_bus_reset);
5594 EXPORT_SYMBOL(mptscsih_host_reset);
5595 EXPORT_SYMBOL(mptscsih_bios_param);
5596 EXPORT_SYMBOL(mptscsih_io_done);
5597 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
5598 EXPORT_SYMBOL(mptscsih_scandv_complete);
5599 EXPORT_SYMBOL(mptscsih_event_process);
5600 EXPORT_SYMBOL(mptscsih_ioc_reset);
5601 EXPORT_SYMBOL(mptscsih_change_queue_depth);
5602 EXPORT_SYMBOL(mptscsih_timer_expired);
5603 EXPORT_SYMBOL(mptscsih_TMHandler);
5605 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/