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_DATA_OVERRUN: /* 0x0044 */
732 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
733 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
734 if (scsi_status == MPI_SCSI_STATUS_BUSY)
735 sc->result = (DID_BUS_BUSY << 16) | scsi_status;
737 sc->result = (DID_OK << 16) | scsi_status;
738 if (scsi_state == 0) {
740 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
742 * If running against circa 200003dd 909 MPT f/w,
743 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
744 * (QUEUE_FULL) returned from device! --> get 0x0000?128
745 * and with SenseBytes set to 0.
747 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
748 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
751 else if (scsi_state &
752 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
757 sc->result = DID_SOFT_ERROR << 16;
759 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
760 /* Not real sure here either... */
761 sc->result = DID_RESET << 16;
763 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
764 /* Device Inq. data indicates that it supports
765 * QTags, but rejects QTag messages.
766 * This command completed OK.
768 * Not real sure here either so do nothing... */
771 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
772 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
775 * Reservation Conflict, Busy,
776 * Command Terminated, CHECK
780 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
781 sc->result = DID_SOFT_ERROR << 16;
784 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
785 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
786 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
787 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
788 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
789 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
790 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
791 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
792 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
797 sc->result = DID_SOFT_ERROR << 16;
800 } /* switch(status) */
802 dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
803 } /* end of address reply case */
805 /* Unmap the DMA buffers, if any. */
807 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
808 sc->use_sg, sc->sc_data_direction);
809 } else if (sc->request_bufflen) {
810 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
811 sc->request_bufflen, sc->sc_data_direction);
814 hd->ScsiLookup[req_idx] = NULL;
816 sc->scsi_done(sc); /* Issue the command callback */
818 /* Free Chain buffers */
819 mptscsih_freeChainBuffers(ioc, req_idx);
824 * mptscsih_flush_running_cmds - For each command found, search
825 * Scsi_Host instance taskQ and reply to OS.
826 * Called only if recovering from a FW reload.
827 * @hd: Pointer to a SCSI HOST structure
831 * Must be called while new I/Os are being queued.
834 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
836 MPT_ADAPTER *ioc = hd->ioc;
837 struct scsi_cmnd *SCpnt;
840 int max = ioc->req_depth;
842 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
843 for (ii= 0; ii < max; ii++) {
844 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
849 /* Null ScsiLookup index
851 hd->ScsiLookup[ii] = NULL;
853 mf = MPT_INDEX_2_MFPTR(ioc, ii);
854 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
857 /* Set status, free OS resources (SG DMA buffers)
859 * Free driver resources (chain, msg buffers)
862 pci_unmap_sg(ioc->pcidev,
863 (struct scatterlist *) SCpnt->request_buffer,
865 SCpnt->sc_data_direction);
866 } else if (SCpnt->request_bufflen) {
867 pci_unmap_single(ioc->pcidev,
868 SCpnt->SCp.dma_handle,
869 SCpnt->request_bufflen,
870 SCpnt->sc_data_direction);
872 SCpnt->result = DID_RESET << 16;
873 SCpnt->host_scribble = NULL;
875 /* Free Chain buffers */
876 mptscsih_freeChainBuffers(ioc, ii);
878 /* Free Message frames */
879 mpt_free_msg_frame(ioc, mf);
881 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
889 * mptscsih_search_running_cmds - Delete any commands associated
890 * with the specified target and lun. Function called only
891 * when a lun is disable by mid-layer.
892 * Do NOT access the referenced scsi_cmnd structure or
893 * members. Will cause either a paging or NULL ptr error.
894 * (BUT, BUT, BUT, the code does reference it! - mdr)
895 * @hd: Pointer to a SCSI HOST structure
896 * @vdevice: per device private data
900 * Called from slave_destroy.
903 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
905 SCSIIORequest_t *mf = NULL;
907 int max = hd->ioc->req_depth;
908 struct scsi_cmnd *sc;
910 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
911 vdevice->target_id, vdevice->lun, max));
913 for (ii=0; ii < max; ii++) {
914 if ((sc = hd->ScsiLookup[ii]) != NULL) {
916 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
918 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
919 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
921 if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
926 hd->ScsiLookup[ii] = NULL;
927 mptscsih_freeChainBuffers(hd->ioc, ii);
928 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
930 pci_unmap_sg(hd->ioc->pcidev,
931 (struct scatterlist *) sc->request_buffer,
933 sc->sc_data_direction);
934 } else if (sc->request_bufflen) {
935 pci_unmap_single(hd->ioc->pcidev,
938 sc->sc_data_direction);
940 sc->host_scribble = NULL;
941 sc->result = DID_NO_CONNECT << 16;
948 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
950 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
952 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
953 * from a SCSI target device.
954 * @sc: Pointer to scsi_cmnd structure
955 * @pScsiReply: Pointer to SCSIIOReply_t
956 * @pScsiReq: Pointer to original SCSI request
958 * This routine periodically reports QUEUE_FULL status returned from a
959 * SCSI target device. It reports this to the console via kernel
960 * printk() API call, not more than once every 10 seconds.
963 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
968 if (sc->device == NULL)
970 if (sc->device->host == NULL)
972 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
975 if (time - hd->last_queue_full > 10 * HZ) {
976 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
977 hd->ioc->name, 0, sc->device->id, sc->device->lun));
978 hd->last_queue_full = time;
982 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
984 * mptscsih_remove - Removed scsi devices
985 * @pdev: Pointer to pci_dev structure
990 mptscsih_remove(struct pci_dev *pdev)
992 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
993 struct Scsi_Host *host = ioc->sh;
995 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1006 scsi_remove_host(host);
1008 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1011 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1012 /* Check DV thread active */
1014 spin_lock_irqsave(&dvtaskQ_lock, flags);
1015 if (dvtaskQ_active) {
1016 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1017 while(dvtaskQ_active && --count)
1018 schedule_timeout_interruptible(1);
1020 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1023 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
1024 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
1026 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
1030 mptscsih_shutdown(pdev);
1034 if (hd->ScsiLookup != NULL) {
1035 sz1 = hd->ioc->req_depth * sizeof(void *);
1036 kfree(hd->ScsiLookup);
1037 hd->ScsiLookup = NULL;
1041 * Free pointer array.
1046 dprintk((MYIOC_s_INFO_FMT
1047 "Free'd ScsiLookup (%d) memory\n",
1048 hd->ioc->name, sz1));
1050 kfree(hd->info_kbuf);
1052 /* NULL the Scsi_Host pointer
1056 scsi_host_put(host);
1062 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1064 * mptscsih_shutdown - reboot notifier
1068 mptscsih_shutdown(struct pci_dev *pdev)
1070 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1071 struct Scsi_Host *host = ioc->sh;
1077 hd = (MPT_SCSI_HOST *)host->hostdata;
1082 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1084 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1089 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1091 mptscsih_shutdown(pdev);
1092 return mpt_suspend(pdev,state);
1095 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1097 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1102 mptscsih_resume(struct pci_dev *pdev)
1104 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1105 struct Scsi_Host *host = ioc->sh;
1113 hd = (MPT_SCSI_HOST *)host->hostdata;
1117 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1119 unsigned long lflags;
1120 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1121 if (!dvtaskQ_active) {
1123 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1124 INIT_WORK(&dvTaskQ_task,
1125 mptscsih_domainValidation, (void *) hd);
1126 schedule_work(&dvTaskQ_task);
1128 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1137 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1139 * mptscsih_info - Return information about MPT adapter
1140 * @SChost: Pointer to Scsi_Host structure
1142 * (linux scsi_host_template.info routine)
1144 * Returns pointer to buffer where information was written.
1147 mptscsih_info(struct Scsi_Host *SChost)
1152 h = (MPT_SCSI_HOST *)SChost->hostdata;
1155 if (h->info_kbuf == NULL)
1156 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1157 return h->info_kbuf;
1158 h->info_kbuf[0] = '\0';
1160 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1161 h->info_kbuf[size-1] = '\0';
1164 return h->info_kbuf;
1175 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1177 if (info->pos + len > info->length)
1178 len = info->length - info->pos;
1180 if (info->pos + len < info->offset) {
1185 if (info->pos < info->offset) {
1186 data += (info->offset - info->pos);
1187 len -= (info->offset - info->pos);
1191 memcpy(info->buffer + info->pos, data, len);
1197 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1203 va_start(args, fmt);
1204 len = vsprintf(buf, fmt, args);
1207 mptscsih_copy_mem_info(info, buf, len);
1212 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1214 struct info_str info;
1218 info.offset = offset;
1221 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1222 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1223 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1224 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1226 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1229 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1231 * mptscsih_proc_info - Return information about MPT adapter
1233 * (linux scsi_host_template.info routine)
1235 * buffer: if write, user data; if read, buffer for user
1236 * length: if write, return length;
1237 * offset: if write, 0; if read, the current offset into the buffer from
1238 * the previous read.
1239 * hostno: scsi host number
1240 * func: if write = 1; if read = 0
1243 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1244 int length, int func)
1246 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1247 MPT_ADAPTER *ioc = hd->ioc;
1252 * write is not supported
1258 size = mptscsih_host_info(ioc, buffer, offset, length);
1264 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1265 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1267 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1269 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1270 * @SCpnt: Pointer to scsi_cmnd structure
1271 * @done: Pointer SCSI mid-layer IO completion function
1273 * (linux scsi_host_template.queuecommand routine)
1274 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1275 * from a linux scsi_cmnd request and send it to the IOC.
1277 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1280 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1284 SCSIIORequest_t *pScsiReq;
1285 VirtDevice *vdev = SCpnt->device->hostdata;
1294 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1295 lun = SCpnt->device->lun;
1296 SCpnt->scsi_done = done;
1298 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1299 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1301 if (hd->resetPending) {
1302 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1303 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1304 return SCSI_MLQUEUE_HOST_BUSY;
1308 * Put together a MPT SCSI request...
1310 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1311 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1313 return SCSI_MLQUEUE_HOST_BUSY;
1316 pScsiReq = (SCSIIORequest_t *) mf;
1318 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1320 ADD_INDEX_LOG(my_idx);
1322 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1323 * Seems we may receive a buffer (datalen>0) even when there
1324 * will be no data transfer! GRRRRR...
1326 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1327 datalen = SCpnt->request_bufflen;
1328 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1329 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1330 datalen = SCpnt->request_bufflen;
1331 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1334 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1337 /* Default to untagged. Once a target structure has been allocated,
1338 * use the Inquiry data to determine if device supports tagged.
1341 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1342 && (SCpnt->device->tagged_supported)) {
1343 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1345 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1348 /* Use the above information to set up the message frame
1350 pScsiReq->TargetID = (u8) vdev->target_id;
1351 pScsiReq->Bus = vdev->bus_id;
1352 pScsiReq->ChainOffset = 0;
1353 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1354 pScsiReq->CDBLength = SCpnt->cmd_len;
1355 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1356 pScsiReq->Reserved = 0;
1357 pScsiReq->MsgFlags = mpt_msg_flags();
1358 pScsiReq->LUN[0] = 0;
1359 pScsiReq->LUN[1] = lun;
1360 pScsiReq->LUN[2] = 0;
1361 pScsiReq->LUN[3] = 0;
1362 pScsiReq->LUN[4] = 0;
1363 pScsiReq->LUN[5] = 0;
1364 pScsiReq->LUN[6] = 0;
1365 pScsiReq->LUN[7] = 0;
1366 pScsiReq->Control = cpu_to_le32(scsictl);
1369 * Write SCSI CDB into the message
1371 cmd_len = SCpnt->cmd_len;
1372 for (ii=0; ii < cmd_len; ii++)
1373 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1375 for (ii=cmd_len; ii < 16; ii++)
1376 pScsiReq->CDB[ii] = 0;
1379 pScsiReq->DataLength = cpu_to_le32(datalen);
1381 /* SenseBuffer low address */
1382 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1383 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1385 /* Now add the SG list
1386 * Always have a SGE even if null length.
1389 /* Add a NULL SGE */
1390 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1393 /* Add a 32 or 64 bit SGE */
1394 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1398 hd->ScsiLookup[my_idx] = SCpnt;
1399 SCpnt->host_scribble = NULL;
1401 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1402 if (hd->ioc->bus_type == SPI) {
1403 int dvStatus = hd->ioc->spi_data.dvStatus[vdev->target_id];
1406 if (dvStatus || hd->ioc->spi_data.forceDv) {
1408 if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
1409 (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
1410 unsigned long lflags;
1411 /* Schedule DV if necessary */
1412 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1413 if (!dvtaskQ_active) {
1415 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1416 INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
1418 schedule_work(&dvTaskQ_task);
1420 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1422 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
1425 /* Trying to do DV to this target, extend timeout.
1426 * Wait to issue until flag is clear
1428 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
1429 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
1433 /* Set the DV flags.
1435 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
1436 mptscsih_set_dvflags(hd, SCpnt);
1444 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1445 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1446 hd->ioc->name, SCpnt, mf, my_idx));
1447 DBG_DUMP_REQUEST_FRAME(mf)
1451 hd->ScsiLookup[my_idx] = NULL;
1452 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1453 mpt_free_msg_frame(hd->ioc, mf);
1454 return SCSI_MLQUEUE_HOST_BUSY;
1457 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1459 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1460 * with a SCSI IO request
1461 * @hd: Pointer to the MPT_SCSI_HOST instance
1462 * @req_idx: Index of the SCSI IO request frame.
1464 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1468 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1470 MPT_FRAME_HDR *chain;
1471 unsigned long flags;
1475 /* Get the first chain index and reset
1478 chain_idx = ioc->ReqToChain[req_idx];
1479 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1481 while (chain_idx != MPT_HOST_NO_CHAIN) {
1483 /* Save the next chain buffer index */
1484 next = ioc->ChainToChain[chain_idx];
1486 /* Free this chain buffer and reset
1489 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1491 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1492 + (chain_idx * ioc->req_sz));
1494 spin_lock_irqsave(&ioc->FreeQlock, flags);
1495 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1496 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1498 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1499 ioc->name, chain_idx));
1507 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1512 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1514 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1515 * Fall through to mpt_HardResetHandler if: not operational, too many
1516 * failed TM requests or handshake failure.
1518 * @ioc: Pointer to MPT_ADAPTER structure
1519 * @type: Task Management type
1520 * @target: Logical Target ID for reset (if appropriate)
1521 * @lun: Logical Unit for reset (if appropriate)
1522 * @ctx2abort: Context for the task to be aborted (if appropriate)
1524 * Remark: Currently invoked from a non-interrupt thread (_bh).
1526 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1529 * Returns 0 for SUCCESS or -1 if FAILED.
1532 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1538 unsigned long flags;
1540 /* If FW is being reloaded currently, return success to
1541 * the calling function.
1548 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1551 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1553 // SJR - CHECKME - Can we avoid this here?
1554 // (mpt_HardResetHandler has this check...)
1555 spin_lock_irqsave(&ioc->diagLock, flags);
1556 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1557 spin_unlock_irqrestore(&ioc->diagLock, flags);
1560 spin_unlock_irqrestore(&ioc->diagLock, flags);
1562 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1563 * If we time out and not bus reset, then we return a FAILED status to the caller.
1564 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1565 * successful. Otherwise, reload the FW.
1567 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1568 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1569 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1570 "Timed out waiting for last TM (%d) to complete! \n",
1571 hd->ioc->name, hd->tmPending));
1573 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1574 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
1575 "Timed out waiting for last TM (%d) to complete! \n",
1576 hd->ioc->name, hd->tmPending));
1578 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1579 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1580 "Timed out waiting for last TM (%d) to complete! \n",
1581 hd->ioc->name, hd->tmPending));
1582 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
1588 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1589 hd->tmPending |= (1 << type);
1590 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1595 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1597 #ifdef MPT_DEBUG_RESET
1598 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1599 printk(MYIOC_s_WARN_FMT
1600 "TM Handler: IOC Not operational(0x%x)!\n",
1601 hd->ioc->name, ioc_raw_state);
1605 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1606 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1608 /* Isse the Task Mgmt request.
1610 if (hd->hard_resets < -1)
1612 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
1614 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
1616 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
1620 /* Only fall through to the HRH if this is a bus reset
1622 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
1623 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
1624 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1626 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1629 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1635 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1637 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1638 * @hd: Pointer to MPT_SCSI_HOST structure
1639 * @type: Task Management type
1640 * @target: Logical Target ID for reset (if appropriate)
1641 * @lun: Logical Unit for reset (if appropriate)
1642 * @ctx2abort: Context for the task to be aborted (if appropriate)
1644 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1645 * or a non-interrupt thread. In the former, must not call schedule().
1647 * Not all fields are meaningfull for all task types.
1649 * Returns 0 for SUCCESS, -999 for "no msg frames",
1650 * else other non-zero value returned.
1653 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1656 SCSITaskMgmt_t *pScsiTm;
1660 /* Return Fail to calling function if no message frames available.
1662 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1663 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1667 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1668 hd->ioc->name, mf));
1670 /* Format the Request
1672 pScsiTm = (SCSITaskMgmt_t *) mf;
1673 pScsiTm->TargetID = target;
1674 pScsiTm->Bus = channel;
1675 pScsiTm->ChainOffset = 0;
1676 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1678 pScsiTm->Reserved = 0;
1679 pScsiTm->TaskType = type;
1680 pScsiTm->Reserved1 = 0;
1681 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1682 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1684 for (ii= 0; ii < 8; ii++) {
1685 pScsiTm->LUN[ii] = 0;
1687 pScsiTm->LUN[1] = lun;
1689 for (ii=0; ii < 7; ii++)
1690 pScsiTm->Reserved2[ii] = 0;
1692 pScsiTm->TaskMsgContext = ctx2abort;
1694 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1695 hd->ioc->name, ctx2abort, type));
1697 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1699 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1700 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
1702 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
1703 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1705 mpt_free_msg_frame(hd->ioc, mf);
1709 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1710 dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
1711 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1713 mpt_free_msg_frame(hd->ioc, mf);
1714 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1716 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1723 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1725 switch (ioc->bus_type) {
1736 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1738 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1739 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1741 * (linux scsi_host_template.eh_abort_handler routine)
1743 * Returns SUCCESS or FAILED.
1746 mptscsih_abort(struct scsi_cmnd * SCpnt)
1756 /* If we can't locate our host adapter structure, return FAILED status.
1758 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1759 SCpnt->result = DID_RESET << 16;
1760 SCpnt->scsi_done(SCpnt);
1761 dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1762 "Can't locate host! (sc=%p)\n",
1768 if (hd->resetPending) {
1772 if (hd->timeouts < -1)
1775 /* Find this command
1777 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1778 /* Cmd not found in ScsiLookup.
1781 SCpnt->result = DID_RESET << 16;
1782 dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1783 "Command not in the active list! (sc=%p)\n",
1784 hd->ioc->name, SCpnt));
1788 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1789 hd->ioc->name, SCpnt);
1790 scsi_print_command(SCpnt);
1792 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1793 * (the IO to be ABORT'd)
1795 * NOTE: Since we do not byteswap MsgContext, we do not
1796 * swap it here either. It is an opaque cookie to
1797 * the controller, so it does not matter. -DaveM
1799 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1800 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1802 hd->abortSCpnt = SCpnt;
1804 vdev = SCpnt->device->hostdata;
1805 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1806 vdev->bus_id, vdev->target_id, vdev->lun,
1807 ctx2abort, mptscsih_get_tm_timeout(ioc));
1809 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1811 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1816 if(retval != FAILED ) {
1818 hd->tmState = TM_STATE_NONE;
1823 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1825 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1826 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1828 * (linux scsi_host_template.eh_dev_reset_handler routine)
1830 * Returns SUCCESS or FAILED.
1833 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1839 /* If we can't locate our host adapter structure, return FAILED status.
1841 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1842 dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1843 "Can't locate host! (sc=%p)\n",
1848 if (hd->resetPending)
1851 printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1852 hd->ioc->name, SCpnt);
1853 scsi_print_command(SCpnt);
1855 vdev = SCpnt->device->hostdata;
1856 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1857 vdev->bus_id, vdev->target_id,
1858 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1860 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1862 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1867 if(retval != FAILED ) {
1869 hd->tmState = TM_STATE_NONE;
1874 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1876 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1877 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1879 * (linux scsi_host_template.eh_bus_reset_handler routine)
1881 * Returns SUCCESS or FAILED.
1884 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1890 /* If we can't locate our host adapter structure, return FAILED status.
1892 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1893 dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1894 "Can't locate host! (sc=%p)\n",
1899 printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1900 hd->ioc->name, SCpnt);
1901 scsi_print_command(SCpnt);
1903 if (hd->timeouts < -1)
1906 vdev = SCpnt->device->hostdata;
1907 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1908 vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1910 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1912 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1917 if(retval != FAILED ) {
1919 hd->tmState = TM_STATE_NONE;
1924 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1926 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
1928 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1930 * (linux scsi_host_template.eh_host_reset_handler routine)
1932 * Returns SUCCESS or FAILED.
1935 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1938 int status = SUCCESS;
1940 /* If we can't locate the host to reset, then we failed. */
1941 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1942 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1943 "Can't locate host! (sc=%p)\n",
1948 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1949 hd->ioc->name, SCpnt);
1951 /* If our attempts to reset the host failed, then return a failed
1952 * status. The host will be taken off line by the SCSI mid-layer.
1954 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1957 /* Make sure TM pending is cleared and TM state is set to
1961 hd->tmState = TM_STATE_NONE;
1964 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1966 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1971 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1973 * mptscsih_tm_pending_wait - wait for pending task management request to
1975 * @hd: Pointer to MPT host structure.
1977 * Returns {SUCCESS,FAILED}.
1980 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1982 unsigned long flags;
1983 int loop_count = 4 * 10; /* Wait 10 seconds */
1984 int status = FAILED;
1987 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1988 if (hd->tmState == TM_STATE_NONE) {
1989 hd->tmState = TM_STATE_IN_PROGRESS;
1991 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1995 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1997 } while (--loop_count);
2002 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2004 * mptscsih_tm_wait_for_completion - wait for completion of TM task
2005 * @hd: Pointer to MPT host structure.
2007 * Returns {SUCCESS,FAILED}.
2010 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2012 unsigned long flags;
2013 int loop_count = 4 * timeout;
2014 int status = FAILED;
2017 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2018 if(hd->tmPending == 0) {
2020 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2023 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2024 msleep_interruptible(250);
2025 } while (--loop_count);
2030 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2032 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2036 switch (response_code) {
2037 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2038 desc = "The task completed.";
2040 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2041 desc = "The IOC received an invalid frame status.";
2043 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2044 desc = "The task type is not supported.";
2046 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2047 desc = "The requested task failed.";
2049 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2050 desc = "The task completed successfully.";
2052 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2053 desc = "The LUN request is invalid.";
2055 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2056 desc = "The task is in the IOC queue and has not been sent to target.";
2062 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2063 ioc->name, response_code, desc);
2066 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2068 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2069 * @ioc: Pointer to MPT_ADAPTER structure
2070 * @mf: Pointer to SCSI task mgmt request frame
2071 * @mr: Pointer to SCSI task mgmt reply frame
2073 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2074 * of any SCSI task management request.
2075 * This routine is registered with the MPT (base) driver at driver
2076 * load/init time via the mpt_register() API call.
2078 * Returns 1 indicating alloc'd request frame ptr should be freed.
2081 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2083 SCSITaskMgmtReply_t *pScsiTmReply;
2084 SCSITaskMgmt_t *pScsiTmReq;
2086 unsigned long flags;
2090 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2091 ioc->name, mf, mr));
2093 /* Depending on the thread, a timer is activated for
2094 * the TM request. Delete this timer on completion of TM.
2095 * Decrement count of outstanding TM requests.
2097 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2099 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
2105 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
2109 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2110 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2112 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2113 tmType = pScsiTmReq->TaskType;
2115 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2116 pScsiTmReply->ResponseCode)
2117 mptscsih_taskmgmt_response_code(ioc,
2118 pScsiTmReply->ResponseCode);
2120 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
2121 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2122 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2124 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2125 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2126 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2127 /* Error? (anything non-zero?) */
2130 /* clear flags and continue.
2132 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2133 hd->abortSCpnt = NULL;
2135 /* If an internal command is present
2136 * or the TM failed - reload the FW.
2137 * FC FW may respond FAILED to an ABORT
2139 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2141 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
2142 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2143 printk((KERN_WARNING
2144 " Firmware Reload FAILED!!\n"));
2149 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2151 hd->abortSCpnt = NULL;
2156 spin_lock_irqsave(&ioc->FreeQlock, flags);
2158 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2159 hd->tmState = TM_STATE_NONE;
2164 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2166 * This is anyones guess quite frankly.
2169 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2170 sector_t capacity, int geom[])
2180 dummy = heads * sectors;
2181 cylinders = capacity;
2182 sector_div(cylinders,dummy);
2185 * Handle extended translation size for logical drives
2188 if ((ulong)capacity >= 0x200000) {
2191 dummy = heads * sectors;
2192 cylinders = capacity;
2193 sector_div(cylinders,dummy);
2199 geom[2] = cylinders;
2201 dprintk((KERN_NOTICE
2202 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2203 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
2208 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2210 * OS entry point to allow host driver to alloc memory
2211 * for each scsi target. Called once per device the bus scan.
2212 * Return non-zero if allocation fails.
2215 mptscsih_target_alloc(struct scsi_target *starget)
2217 VirtTarget *vtarget;
2219 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
2222 starget->hostdata = vtarget;
2226 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2228 * OS entry point to allow host driver to alloc memory
2229 * for each scsi device. Called once per device the bus scan.
2230 * Return non-zero if allocation fails.
2233 mptscsih_slave_alloc(struct scsi_device *sdev)
2235 struct Scsi_Host *host = sdev->host;
2236 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2237 VirtTarget *vtarget;
2239 struct scsi_target *starget;
2241 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
2243 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
2244 hd->ioc->name, sizeof(VirtDevice));
2248 vdev->ioc_id = hd->ioc->id;
2249 vdev->target_id = sdev->id;
2250 vdev->bus_id = sdev->channel;
2251 vdev->lun = sdev->lun;
2252 sdev->hostdata = vdev;
2254 starget = scsi_target(sdev);
2255 vtarget = starget->hostdata;
2256 vdev->vtarget = vtarget;
2258 if (vtarget->num_luns == 0) {
2259 hd->Targets[sdev->id] = vtarget;
2260 vtarget->ioc_id = hd->ioc->id;
2261 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
2262 vtarget->target_id = sdev->id;
2263 vtarget->bus_id = sdev->channel;
2264 if (hd->ioc->bus_type == SPI) {
2265 if (hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
2266 vtarget->raidVolume = 1;
2267 ddvtprintk((KERN_INFO
2268 "RAID Volume @ id %d\n", sdev->id));
2271 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2274 vtarget->num_luns++;
2279 * OS entry point to allow for host driver to free allocated memory
2280 * Called if no device present or device being unloaded
2283 mptscsih_target_destroy(struct scsi_target *starget)
2285 if (starget->hostdata)
2286 kfree(starget->hostdata);
2287 starget->hostdata = NULL;
2291 * OS entry point to allow for host driver to free allocated memory
2292 * Called if no device present or device being unloaded
2295 mptscsih_slave_destroy(struct scsi_device *sdev)
2297 struct Scsi_Host *host = sdev->host;
2298 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2299 VirtTarget *vtarget;
2300 VirtDevice *vdevice;
2301 struct scsi_target *starget;
2303 starget = scsi_target(sdev);
2304 vtarget = starget->hostdata;
2305 vdevice = sdev->hostdata;
2307 mptscsih_search_running_cmds(hd, vdevice);
2308 vtarget->luns[0] &= ~(1 << vdevice->lun);
2309 vtarget->num_luns--;
2310 if (vtarget->num_luns == 0) {
2311 mptscsih_negotiate_to_asyn_narrow(hd, vtarget);
2312 if (hd->ioc->bus_type == SPI) {
2313 if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) {
2314 hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
2316 hd->ioc->spi_data.dvStatus[vtarget->target_id] =
2317 MPT_SCSICFG_NEGOTIATE;
2318 if (!hd->negoNvram) {
2319 hd->ioc->spi_data.dvStatus[vtarget->target_id] |=
2320 MPT_SCSICFG_DV_NOT_DONE;
2324 hd->Targets[sdev->id] = NULL;
2326 mptscsih_synchronize_cache(hd, vdevice);
2328 sdev->hostdata = NULL;
2331 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2333 * mptscsih_change_queue_depth - This function will set a devices queue depth
2334 * @sdev: per scsi_device pointer
2335 * @qdepth: requested queue depth
2337 * Adding support for new 'change_queue_depth' api.
2340 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2342 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2343 VirtTarget *vtarget;
2344 struct scsi_target *starget;
2348 starget = scsi_target(sdev);
2349 vtarget = starget->hostdata;
2351 if (hd->ioc->bus_type == SPI) {
2352 if (vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
2353 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2355 else if (((vtarget->inq_data[0] & 0x1f) == 0x00) &&
2356 (vtarget->minSyncFactor <= MPT_ULTRA160 ))
2357 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2359 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2361 /* error case - No Inq. Data */
2365 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2367 if (qdepth > max_depth)
2372 tagged = MSG_SIMPLE_TAG;
2374 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2375 return sdev->queue_depth;
2379 * OS entry point to adjust the queue_depths on a per-device basis.
2380 * Called once per device the bus scan. Use it to force the queue_depth
2381 * member to 1 if a device does not support Q tags.
2382 * Return non-zero if fails.
2385 mptscsih_slave_configure(struct scsi_device *sdev)
2387 struct Scsi_Host *sh = sdev->host;
2388 VirtTarget *vtarget;
2389 VirtDevice *vdevice;
2390 struct scsi_target *starget;
2391 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2392 int indexed_lun, lun_index;
2394 starget = scsi_target(sdev);
2395 vtarget = starget->hostdata;
2396 vdevice = sdev->hostdata;
2398 dsprintk((MYIOC_s_INFO_FMT
2399 "device @ %p, id=%d, LUN=%d, channel=%d\n",
2400 hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
2401 if (hd->ioc->bus_type == SPI)
2402 dsprintk((MYIOC_s_INFO_FMT
2403 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2404 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2405 sdev->ppr, sdev->inquiry_len));
2407 if (sdev->id > sh->max_id) {
2408 /* error case, should never happen */
2409 scsi_adjust_queue_depth(sdev, 0, 1);
2410 goto slave_configure_exit;
2413 vdevice->configured_lun=1;
2414 lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */
2415 indexed_lun = (vdevice->lun % 32);
2416 vtarget->luns[lun_index] |= (1 << indexed_lun);
2417 mptscsih_initTarget(hd, vtarget, sdev->lun, sdev->inquiry,
2418 sdev->inquiry_len );
2419 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2421 dsprintk((MYIOC_s_INFO_FMT
2422 "Queue depth=%d, tflags=%x\n",
2423 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2425 if (hd->ioc->bus_type == SPI)
2426 dsprintk((MYIOC_s_INFO_FMT
2427 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2428 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2429 vtarget->minSyncFactor));
2431 slave_configure_exit:
2433 dsprintk((MYIOC_s_INFO_FMT
2434 "tagged %d, simple %d, ordered %d\n",
2435 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2436 sdev->ordered_tags));
2441 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2443 * Private routines...
2446 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2447 /* Utility function to copy sense data from the scsi_cmnd buffer
2448 * to the FC and SCSI target structures.
2452 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2455 SCSIIORequest_t *pReq;
2456 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2458 /* Get target structure
2460 pReq = (SCSIIORequest_t *) mf;
2461 vdev = sc->device->hostdata;
2467 /* Copy the sense received into the scsi command block. */
2468 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2469 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2470 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2472 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2474 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2475 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2477 MPT_ADAPTER *ioc = hd->ioc;
2479 idx = ioc->eventContext % ioc->eventLogSize;
2480 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2481 ioc->events[idx].eventContext = ioc->eventContext;
2483 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2484 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2485 (sc->device->channel << 8) || sc->device->id;
2487 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2489 ioc->eventContext++;
2493 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2499 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2504 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2506 for (i = 0; i < hd->ioc->req_depth; i++) {
2507 if (hd->ScsiLookup[i] == sc) {
2515 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2517 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2520 unsigned long flags;
2523 dtmprintk((KERN_WARNING MYNAM
2524 ": IOC %s_reset routed to SCSI host driver!\n",
2525 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2526 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2528 /* If a FW reload request arrives after base installed but
2529 * before all scsi hosts have been attached, then an alt_ioc
2530 * may have a NULL sh pointer.
2532 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2535 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2537 if (reset_phase == MPT_IOC_SETUP_RESET) {
2538 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2541 * 1. Set Hard Reset Pending Flag
2542 * All new commands go to doneQ
2544 hd->resetPending = 1;
2546 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2547 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2549 /* 2. Flush running commands
2550 * Clean ScsiLookup (and associated memory)
2554 /* 2b. Reply to OS all known outstanding I/O commands.
2556 mptscsih_flush_running_cmds(hd);
2558 /* 2c. If there was an internal command that
2559 * has not completed, configuration or io request,
2560 * free these resources.
2563 del_timer(&hd->timer);
2564 mpt_free_msg_frame(ioc, hd->cmdPtr);
2567 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2570 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2572 /* Once a FW reload begins, all new OS commands are
2573 * redirected to the doneQ w/ a reset status.
2574 * Init all control structures.
2577 /* ScsiLookup initialization
2579 for (ii=0; ii < hd->ioc->req_depth; ii++)
2580 hd->ScsiLookup[ii] = NULL;
2582 /* 2. Chain Buffer initialization
2585 /* 4. Renegotiate to all devices, if SPI
2587 if (ioc->bus_type == SPI) {
2588 dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
2589 mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
2592 /* 5. Enable new commands to be posted
2594 spin_lock_irqsave(&ioc->FreeQlock, flags);
2596 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2597 hd->resetPending = 0;
2598 hd->tmState = TM_STATE_NONE;
2600 /* 6. If there was an internal command,
2601 * wake this process up.
2605 * Wake up the original calling thread
2607 hd->pLocal = &hd->localReply;
2608 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2609 hd->scandv_wait_done = 1;
2610 wake_up(&hd->scandv_waitq);
2614 /* 7. SPI: Set flag to force DV and re-read IOC Page 3
2616 if (ioc->bus_type == SPI) {
2617 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2618 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
2621 /* 7. FC: Rescan for blocked rports which might have returned.
2623 else if (ioc->bus_type == FC) {
2625 unsigned long flags;
2627 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
2628 work_count = ++ioc->fc_rescan_work_count;
2629 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
2630 if (work_count == 1)
2631 schedule_work(&ioc->fc_rescan_work);
2633 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2637 return 1; /* currently means nothing really */
2640 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2642 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2645 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2647 unsigned long flags;
2649 devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2652 if (ioc->sh == NULL ||
2653 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2657 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2660 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2661 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2662 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2665 case MPI_EVENT_LOGOUT: /* 09 */
2669 case MPI_EVENT_RESCAN: /* 06 */
2670 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
2671 work_count = ++ioc->fc_rescan_work_count;
2672 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
2673 if (work_count == 1)
2674 schedule_work(&ioc->fc_rescan_work);
2678 * CHECKME! Don't think we need to do
2679 * anything for these, but...
2681 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2682 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2684 * CHECKME! Falling thru...
2688 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2690 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2691 pMpiEventDataRaid_t pRaidEventData =
2692 (pMpiEventDataRaid_t) pEvReply->Data;
2693 /* Domain Validation Needed */
2694 if (ioc->bus_type == SPI &&
2695 pRaidEventData->ReasonCode ==
2696 MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED)
2697 mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
2702 case MPI_EVENT_NONE: /* 00 */
2703 case MPI_EVENT_LOG_DATA: /* 01 */
2704 case MPI_EVENT_STATE_CHANGE: /* 02 */
2705 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2707 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2711 return 1; /* currently means nothing really */
2714 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2716 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2717 * @hd: Pointer to MPT_SCSI_HOST structure
2718 * @vtarget: per target private data
2720 * @data: Pointer to data
2721 * @dlen: Number of INQUIRY bytes
2723 * NOTE: It's only SAFE to call this routine if data points to
2724 * sane & valid STANDARD INQUIRY data!
2726 * Allocate and initialize memory for this target.
2727 * Save inquiry data.
2731 mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen)
2737 dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
2738 hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd));
2741 * If the peripheral qualifier filter is enabled then if the target reports a 0x1
2742 * (i.e. The targer is capable of supporting the specified peripheral device type
2743 * on this logical unit; however, the physical device is not currently connected
2744 * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
2745 * capable of supporting a physical device on this logical unit). This is to work
2746 * around a bug in th emid-layer in some distributions in which the mid-layer will
2747 * continue to try to communicate to the LUN and evntually create a dummy LUN.
2749 if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
2752 /* Is LUN supported? If so, upper 2 bits will be 0
2753 * in first byte of inquiry data.
2758 if (vtarget == NULL)
2762 vtarget->type = data[0];
2764 if (hd->ioc->bus_type != SPI)
2767 if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
2768 /* Treat all Processors as SAF-TE if
2769 * command line option is set */
2770 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2771 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
2772 }else if ((data[0] == TYPE_PROCESSOR) &&
2773 !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
2775 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2776 if ( data[44] == 'S' &&
2782 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2783 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
2787 if (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
2788 inq_len = dlen < 8 ? dlen : 8;
2789 memcpy (vtarget->inq_data, data, inq_len);
2790 /* If have not done DV, set the DV flag.
2792 pSpi = &hd->ioc->spi_data;
2793 if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
2794 if (pSpi->dvStatus[vtarget->target_id] & MPT_SCSICFG_DV_NOT_DONE)
2795 pSpi->dvStatus[vtarget->target_id] |= MPT_SCSICFG_NEED_DV;
2797 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2799 data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */
2801 if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2802 /* Update the target capabilities
2805 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
2808 mptscsih_setTargetNegoParms(hd, vtarget, data_56);
2810 /* Initial Inquiry may not request enough data bytes to
2811 * obtain byte 57. DV will; if target doesn't return
2812 * at least 57 bytes, data[56] will be zero. */
2814 if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2815 /* Update the target capabilities
2818 vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
2819 mptscsih_setTargetNegoParms(hd, vtarget, data_56);
2825 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2827 * Update the target negotiation parameters based on the
2828 * the Inquiry data, adapter capabilities, and NVRAM settings.
2832 mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56)
2834 SpiCfgData *pspi_data = &hd->ioc->spi_data;
2835 int id = (int) target->target_id;
2837 VirtTarget *vtarget;
2839 u8 width = MPT_NARROW;
2840 u8 factor = MPT_ASYNC;
2842 u8 version, nfactor;
2845 target->negoFlags = pspi_data->noQas;
2847 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
2848 * support. If available, default QAS to off and allow enabling.
2849 * If not available, default QAS to on, turn off for non-disks.
2852 /* Set flags based on Inquiry data
2854 version = target->inq_data[2] & 0x07;
2857 factor = MPT_ULTRA2;
2858 offset = pspi_data->maxSyncOffset;
2859 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2861 if (target->inq_data[7] & 0x20) {
2865 if (target->inq_data[7] & 0x10) {
2866 factor = pspi_data->minSyncFactor;
2867 if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
2868 /* bits 2 & 3 show Clocking support */
2869 if ((byte56 & 0x0C) == 0)
2870 factor = MPT_ULTRA2;
2872 if ((byte56 & 0x03) == 0)
2873 factor = MPT_ULTRA160;
2875 factor = MPT_ULTRA320;
2878 ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
2881 if (target->inq_data[0] == TYPE_TAPE) {
2883 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2888 ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
2892 offset = pspi_data->maxSyncOffset;
2894 /* If RAID, never disable QAS
2895 * else if non RAID, do not disable
2896 * QAS if bit 1 is set
2897 * bit 1 QAS support, non-raid only
2900 if (target->raidVolume == 1) {
2909 if ( (target->inq_data[7] & 0x02) == 0) {
2910 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2913 /* Update tflags based on NVRAM settings. (SCSI only)
2915 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2916 nvram = pspi_data->nvram[id];
2917 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2920 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2923 /* Ensure factor is set to the
2924 * maximum of: adapter, nvram, inquiry
2927 if (nfactor < pspi_data->minSyncFactor )
2928 nfactor = pspi_data->minSyncFactor;
2930 factor = max(factor, nfactor);
2931 if (factor == MPT_ASYNC)
2942 /* Make sure data is consistent
2944 if ((!width) && (factor < MPT_ULTRA2)) {
2945 factor = MPT_ULTRA2;
2948 /* Save the data to the target structure.
2950 target->minSyncFactor = factor;
2951 target->maxOffset = offset;
2952 target->maxWidth = width;
2954 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2956 /* Disable unused features.
2959 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2962 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2964 if ( factor > MPT_ULTRA320 )
2967 /* GEM, processor WORKAROUND
2969 if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
2970 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
2971 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
2973 if (noQas && (pspi_data->noQas == 0)) {
2974 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2975 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2977 /* Disable QAS in a mixed configuration case
2980 ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
2981 for (ii = 0; ii < id; ii++) {
2982 if ( (vtarget = hd->Targets[ii]) ) {
2983 vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2984 mptscsih_writeSDP1(hd, 0, ii, vtarget->negoFlags);
2990 /* Write SDP1 on this I/O to this target */
2991 if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
2992 ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
2993 mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
2994 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
2995 } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
2996 ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
2997 mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
2998 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
3002 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3004 * If no Target, bus reset on 1st I/O. Set the flag to
3005 * prevent any future negotiations to this device.
3008 mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
3012 if ((vdev = sc->device->hostdata) != NULL)
3013 hd->ioc->spi_data.dvStatus[vdev->target_id] |= MPT_SCSICFG_BLK_NEGO;
3017 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3019 * SCSI Config Page functionality ...
3021 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3022 /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
3023 * based on width, factor and offset parameters.
3025 * @factor: sync factor
3026 * @offset: sync offset
3027 * @requestedPtr: pointer to requested values (updated)
3028 * @configurationPtr: pointer to configuration values (updated)
3029 * @flags: flags to block WDTR or SDTR negotiation
3033 * Remark: Called by writeSDP1 and _dv_params
3036 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
3038 u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
3039 u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
3041 *configurationPtr = 0;
3042 *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
3043 *requestedPtr |= (offset << 16) | (factor << 8);
3045 if (width && offset && !nowide && !nosync) {
3046 if (factor < MPT_ULTRA160) {
3047 *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
3048 if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
3049 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
3050 if (flags & MPT_TAPE_NEGO_IDP)
3051 *requestedPtr |= 0x08000000;
3052 } else if (factor < MPT_ULTRA2) {
3053 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
3058 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
3061 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
3066 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3067 /* mptscsih_writeSDP1 - write SCSI Device Page 1
3068 * @hd: Pointer to a SCSI Host Strucutre
3069 * @portnum: IOC port number
3070 * @target_id: writeSDP1 for single ID
3071 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
3073 * Return: -EFAULT if read of config page header fails
3076 * Remark: If a target has been found, the settings from the
3077 * target structure are used, else the device is set
3080 * Remark: Called during init and after a FW reload.
3081 * Remark: We do not wait for a return, write pages sequentially.
3084 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
3086 MPT_ADAPTER *ioc = hd->ioc;
3088 SCSIDevicePage1_t *pData;
3089 VirtTarget *vtarget=NULL;
3094 u32 requested, configuration, flagsLength;
3096 int id = 0, maxid = 0;
3102 u8 maxwidth, maxoffset, maxfactor;
3104 if (ioc->spi_data.sdp1length == 0)
3107 if (flags & MPT_SCSICFG_ALL_IDS) {
3109 maxid = ioc->sh->max_id - 1;
3110 } else if (ioc->sh) {
3112 maxid = min_t(int, id, ioc->sh->max_id - 1);
3115 for (; id <= maxid; id++) {
3117 if (id == ioc->pfacts[portnum].PortSCSIID)
3120 /* Use NVRAM to get adapter and target maximums
3121 * Data over-riden by target structure information, if present
3123 maxwidth = ioc->spi_data.maxBusWidth;
3124 maxoffset = ioc->spi_data.maxSyncOffset;
3125 maxfactor = ioc->spi_data.minSyncFactor;
3126 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3127 nvram = ioc->spi_data.nvram[id];
3130 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
3132 if (maxoffset > 0) {
3133 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
3134 if (maxfactor == 0) {
3136 maxfactor = MPT_ASYNC;
3138 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
3139 maxfactor = ioc->spi_data.minSyncFactor;
3142 maxfactor = MPT_ASYNC;
3145 /* Set the negotiation flags.
3147 negoFlags = ioc->spi_data.noQas;
3149 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
3152 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
3154 if (flags & MPT_SCSICFG_USE_NVRAM) {
3163 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
3166 /* If id is not a raid volume, get the updated
3167 * transmission settings from the target structure.
3169 if (hd->Targets && (vtarget = hd->Targets[id]) && !vtarget->raidVolume) {
3170 width = vtarget->maxWidth;
3171 factor = vtarget->minSyncFactor;
3172 offset = vtarget->maxOffset;
3173 negoFlags = vtarget->negoFlags;
3176 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3177 /* Force to async and narrow if DV has not been executed
3180 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
3187 if (flags & MPT_SCSICFG_BLK_NEGO)
3188 negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
3190 mptscsih_setDevicePage1Flags(width, factor, offset,
3191 &requested, &configuration, negoFlags);
3192 dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
3193 target_id, width, factor, offset, negoFlags, requested, configuration));
3195 /* Get a MF for this command.
3197 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
3198 dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
3203 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
3204 hd->ioc->name, mf, id, requested, configuration));
3207 /* Set the request and the data pointers.
3208 * Request takes: 36 bytes (32 bit SGE)
3209 * SCSI Device Page 1 requires 16 bytes
3210 * 40 + 16 <= size of SCSI IO Request = 56 bytes
3211 * and MF size >= 64 bytes.
3212 * Place data at end of MF.
3214 pReq = (Config_t *)mf;
3216 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3217 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
3219 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
3220 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
3222 /* Complete the request frame (same for all requests).
3224 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3226 pReq->ChainOffset = 0;
3227 pReq->Function = MPI_FUNCTION_CONFIG;
3228 pReq->ExtPageLength = 0;
3229 pReq->ExtPageType = 0;
3231 for (ii=0; ii < 8; ii++) {
3232 pReq->Reserved2[ii] = 0;
3234 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
3235 pReq->Header.PageLength = ioc->spi_data.sdp1length;
3236 pReq->Header.PageNumber = 1;
3237 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3238 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
3240 /* Add a SGE to the config request.
3242 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
3244 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3246 /* Set up the common data portion
3248 pData->Header.PageVersion = pReq->Header.PageVersion;
3249 pData->Header.PageLength = pReq->Header.PageLength;
3250 pData->Header.PageNumber = pReq->Header.PageNumber;
3251 pData->Header.PageType = pReq->Header.PageType;
3252 pData->RequestedParameters = cpu_to_le32(requested);
3253 pData->Reserved = 0;
3254 pData->Configuration = cpu_to_le32(configuration);
3256 dprintk((MYIOC_s_INFO_FMT
3257 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
3258 ioc->name, id, (id | (bus<<8)),
3259 requested, configuration));
3261 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3267 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3268 /* mptscsih_writeIOCPage4 - write IOC Page 4
3269 * @hd: Pointer to a SCSI Host Structure
3270 * @target_id: write IOC Page4 for this ID & Bus
3272 * Return: -EAGAIN if unable to obtain a Message Frame
3275 * Remark: We do not wait for a return, write pages sequentially.
3278 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
3280 MPT_ADAPTER *ioc = hd->ioc;
3282 IOCPage4_t *IOCPage4Ptr;
3290 /* Get a MF for this command.
3292 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
3293 dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
3298 /* Set the request and the data pointers.
3299 * Place data at end of MF.
3301 pReq = (Config_t *)mf;
3303 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3304 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
3306 /* Complete the request frame (same for all requests).
3308 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3310 pReq->ChainOffset = 0;
3311 pReq->Function = MPI_FUNCTION_CONFIG;
3312 pReq->ExtPageLength = 0;
3313 pReq->ExtPageType = 0;
3315 for (ii=0; ii < 8; ii++) {
3316 pReq->Reserved2[ii] = 0;
3319 IOCPage4Ptr = ioc->spi_data.pIocPg4;
3320 dataDma = ioc->spi_data.IocPg4_dma;
3321 ii = IOCPage4Ptr->ActiveSEP++;
3322 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
3323 IOCPage4Ptr->SEP[ii].SEPBus = bus;
3324 pReq->Header = IOCPage4Ptr->Header;
3325 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
3327 /* Add a SGE to the config request.
3329 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
3330 (IOCPage4Ptr->Header.PageLength + ii) * 4;
3332 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3334 dinitprintk((MYIOC_s_INFO_FMT
3335 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
3336 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
3338 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3343 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3345 * Bus Scan and Domain Validation functionality ...
3348 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3350 * mptscsih_scandv_complete - Scan and DV callback routine registered
3351 * to Fustion MPT (base) driver.
3353 * @ioc: Pointer to MPT_ADAPTER structure
3354 * @mf: Pointer to original MPT request frame
3355 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
3357 * This routine is called from mpt.c::mpt_interrupt() at the completion
3358 * of any SCSI IO request.
3359 * This routine is registered with the Fusion MPT (base) driver at driver
3360 * load/init time via the mpt_register() API call.
3362 * Returns 1 indicating alloc'd request frame ptr should be freed.
3364 * Remark: Sets a completion code and (possibly) saves sense data
3365 * in the IOC member localReply structure.
3366 * Used ONLY for DV and other internal commands.
3369 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3372 SCSIIORequest_t *pReq;
3376 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3379 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
3380 printk(MYIOC_s_ERR_FMT
3381 "ScanDvComplete, %s req frame ptr! (=%p)\n",
3382 ioc->name, mf?"BAD":"NULL", (void *) mf);
3386 del_timer(&hd->timer);
3387 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3388 hd->ScsiLookup[req_idx] = NULL;
3389 pReq = (SCSIIORequest_t *) mf;
3391 if (mf != hd->cmdPtr) {
3392 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3393 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
3397 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3398 hd->ioc->name, mf, mr, req_idx));
3400 hd->pLocal = &hd->localReply;
3401 hd->pLocal->scsiStatus = 0;
3403 /* If target struct exists, clear sense valid flag.
3406 completionCode = MPT_SCANDV_GOOD;
3408 SCSIIOReply_t *pReply;
3412 pReply = (SCSIIOReply_t *) mr;
3414 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3415 scsi_status = pReply->SCSIStatus;
3417 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3418 status, pReply->SCSIState, scsi_status,
3419 le32_to_cpu(pReply->IOCLogInfo)));
3423 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
3424 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3427 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
3428 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
3429 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
3430 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
3431 completionCode = MPT_SCANDV_DID_RESET;
3434 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
3435 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
3436 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
3437 if (pReply->Function == MPI_FUNCTION_CONFIG) {
3438 ConfigReply_t *pr = (ConfigReply_t *)mr;
3439 completionCode = MPT_SCANDV_GOOD;
3440 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
3441 hd->pLocal->header.PageLength = pr->Header.PageLength;
3442 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
3443 hd->pLocal->header.PageType = pr->Header.PageType;
3445 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
3446 /* If the RAID Volume request is successful,
3447 * return GOOD, else indicate that
3448 * some type of error occurred.
3450 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
3451 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
3452 completionCode = MPT_SCANDV_GOOD;
3454 completionCode = MPT_SCANDV_SOME_ERROR;
3456 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3460 /* save sense data in global structure
3462 completionCode = MPT_SCANDV_SENSE;
3463 hd->pLocal->scsiStatus = scsi_status;
3464 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
3465 (req_idx * MPT_SENSE_BUFFER_ALLOC));
3467 sz = min_t(int, pReq->SenseBufferLength,
3468 SCSI_STD_SENSE_BYTES);
3469 memcpy(hd->pLocal->sense, sense_data, sz);
3471 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
3473 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
3474 if (pReq->CDB[0] == INQUIRY)
3475 completionCode = MPT_SCANDV_ISSUE_SENSE;
3477 completionCode = MPT_SCANDV_DID_RESET;
3479 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
3480 completionCode = MPT_SCANDV_DID_RESET;
3481 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3482 completionCode = MPT_SCANDV_DID_RESET;
3484 completionCode = MPT_SCANDV_GOOD;
3485 hd->pLocal->scsiStatus = scsi_status;
3489 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
3490 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3491 completionCode = MPT_SCANDV_DID_RESET;
3493 completionCode = MPT_SCANDV_SOME_ERROR;
3497 completionCode = MPT_SCANDV_SOME_ERROR;
3500 } /* switch(status) */
3502 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
3504 } /* end of address reply case */
3506 hd->pLocal->completion = completionCode;
3508 /* MF and RF are freed in mpt_interrupt
3511 /* Free Chain buffers (will never chain) in scan or dv */
3512 //mptscsih_freeChainBuffers(ioc, req_idx);
3515 * Wake up the original calling thread
3517 hd->scandv_wait_done = 1;
3518 wake_up(&hd->scandv_waitq);
3523 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3524 /* mptscsih_timer_expired - Call back for timer process.
3525 * Used only for dv functionality.
3526 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3530 mptscsih_timer_expired(unsigned long data)
3532 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3534 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3537 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3539 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3540 /* Desire to issue a task management request here.
3541 * TM requests MUST be single threaded.
3542 * If old eh code and no TM current, issue request.
3543 * If new eh code, do nothing. Wait for OS cmd timeout
3546 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3548 /* Perform a FW reload */
3549 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3550 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3554 /* This should NEVER happen */
3555 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3558 /* No more processing.
3559 * TM call will generate an interrupt for SCSI TM Management.
3560 * The FW will reply to all outstanding commands, callback will finish cleanup.
3561 * Hard reset clean-up will free all resources.
3563 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3568 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3569 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3570 /* mptscsih_do_raid - Format and Issue a RAID volume request message.
3571 * @hd: Pointer to scsi host structure
3572 * @action: What do be done.
3573 * @id: Logical target id.
3574 * @bus: Target locations bus.
3576 * Returns: < 0 on a fatal error
3579 * Remark: Wait to return until reply processed by the ISR.
3582 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
3584 MpiRaidActionRequest_t *pReq;
3588 in_isr = in_interrupt();
3590 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
3595 /* Get and Populate a free Frame
3597 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3598 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
3602 pReq = (MpiRaidActionRequest_t *)mf;
3603 pReq->Action = action;
3604 pReq->Reserved1 = 0;
3605 pReq->ChainOffset = 0;
3606 pReq->Function = MPI_FUNCTION_RAID_ACTION;
3607 pReq->VolumeID = io->id;
3608 pReq->VolumeBus = io->bus;
3609 pReq->PhysDiskNum = io->physDiskNum;
3611 pReq->Reserved2 = 0;
3612 pReq->ActionDataWord = 0; /* Reserved for this action */
3613 //pReq->ActionDataSGE = 0;
3615 mpt_add_sge((char *)&pReq->ActionDataSGE,
3616 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
3618 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
3619 hd->ioc->name, action, io->id));
3622 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
3623 hd->scandv_wait_done = 0;
3625 /* Save cmd pointer, for resource free if timeout or
3630 add_timer(&hd->timer);
3631 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3632 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3634 if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
3639 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
3641 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3643 * mptscsih_do_cmd - Do internal command.
3644 * @hd: MPT_SCSI_HOST pointer
3645 * @io: INTERNAL_CMD pointer.
3647 * Issue the specified internally generated command and do command
3648 * specific cleanup. For bus scan / DV only.
3649 * NOTES: If command is Inquiry and status is good,
3650 * initialize a target structure, save the data
3652 * Remark: Single threaded access only.
3655 * < 0 if an illegal command or no resources
3659 * > 0 if command complete but some type of completion error.
3662 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3665 SCSIIORequest_t *pScsiReq;
3666 SCSIIORequest_t ReqCopy;
3667 int my_idx, ii, dir;
3671 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3674 in_isr = in_interrupt();
3676 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3682 /* Set command specific information
3687 dir = MPI_SCSIIO_CONTROL_READ;
3693 case TEST_UNIT_READY:
3695 dir = MPI_SCSIIO_CONTROL_READ;
3701 dir = MPI_SCSIIO_CONTROL_READ;
3703 CDB[4] = 1; /*Spin up the disk */
3711 dir = MPI_SCSIIO_CONTROL_READ;
3717 dir = MPI_SCSIIO_CONTROL_READ;
3719 if (io->flags & MPT_ICFLAG_ECHO) {
3725 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3728 CDB[6] = (io->size >> 16) & 0xFF;
3729 CDB[7] = (io->size >> 8) & 0xFF;
3730 CDB[8] = io->size & 0xFF;
3736 dir = MPI_SCSIIO_CONTROL_WRITE;
3738 if (io->flags & MPT_ICFLAG_ECHO) {
3743 CDB[6] = (io->size >> 16) & 0xFF;
3744 CDB[7] = (io->size >> 8) & 0xFF;
3745 CDB[8] = io->size & 0xFF;
3751 dir = MPI_SCSIIO_CONTROL_READ;
3758 dir = MPI_SCSIIO_CONTROL_READ;
3763 case SYNCHRONIZE_CACHE:
3765 dir = MPI_SCSIIO_CONTROL_READ;
3767 // CDB[1] = 0x02; /* set immediate bit */
3776 /* Get and Populate a free Frame
3778 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3779 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3784 pScsiReq = (SCSIIORequest_t *) mf;
3786 /* Get the request index */
3787 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3788 ADD_INDEX_LOG(my_idx); /* for debug */
3790 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3791 pScsiReq->TargetID = io->physDiskNum;
3793 pScsiReq->ChainOffset = 0;
3794 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3796 pScsiReq->TargetID = io->id;
3797 pScsiReq->Bus = io->bus;
3798 pScsiReq->ChainOffset = 0;
3799 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3802 pScsiReq->CDBLength = cmdLen;
3803 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3805 pScsiReq->Reserved = 0;
3807 pScsiReq->MsgFlags = mpt_msg_flags();
3808 /* MsgContext set in mpt_get_msg_fram call */
3810 for (ii=0; ii < 8; ii++)
3811 pScsiReq->LUN[ii] = 0;
3812 pScsiReq->LUN[1] = io->lun;
3814 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3815 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3817 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3819 if (cmd == REQUEST_SENSE) {
3820 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3821 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3822 hd->ioc->name, cmd));
3825 for (ii=0; ii < 16; ii++)
3826 pScsiReq->CDB[ii] = CDB[ii];
3828 pScsiReq->DataLength = cpu_to_le32(io->size);
3829 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3830 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3832 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3833 hd->ioc->name, cmd, io->bus, io->id, io->lun));
3835 if (dir == MPI_SCSIIO_CONTROL_READ) {
3836 mpt_add_sge((char *) &pScsiReq->SGL,
3837 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3840 mpt_add_sge((char *) &pScsiReq->SGL,
3841 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3845 /* The ISR will free the request frame, but we need
3846 * the information to initialize the target. Duplicate.
3848 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3850 /* Issue this command after:
3853 * Wait until the reply has been received
3854 * ScsiScanDvCtx callback function will
3856 * set scandv_wait_done and call wake_up
3859 hd->timer.expires = jiffies + HZ*cmdTimeout;
3860 hd->scandv_wait_done = 0;
3862 /* Save cmd pointer, for resource free if timeout or
3867 add_timer(&hd->timer);
3868 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3869 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3872 rc = hd->pLocal->completion;
3873 hd->pLocal->skip = 0;
3875 /* Always set fatal error codes in some cases.
3877 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3879 else if (rc == MPT_SCANDV_SOME_ERROR)
3883 /* This should never happen. */
3884 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3891 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3893 * mptscsih_negotiate_to_asyn_narrow - Restore devices to default state
3894 * @hd: Pointer to a SCSI HOST structure
3895 * @vtarget: per device private data
3897 * Uses the ISR, but with special processing.
3898 * MUST be single-threaded.
3902 mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
3904 MPT_ADAPTER *ioc= hd->ioc;
3905 SCSIDevicePage1_t *pcfg1Data;
3907 dma_addr_t cfg1_dma_addr;
3908 ConfigPageHeader_t header;
3910 int requested, configuration, data,i;
3913 if (ioc->bus_type != SPI)
3916 if (!ioc->spi_data.sdp1length)
3919 pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
3920 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
3922 if (pcfg1Data == NULL)
3925 header.PageVersion = ioc->spi_data.sdp1version;
3926 header.PageLength = ioc->spi_data.sdp1length;
3927 header.PageNumber = 1;
3928 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3929 cfg.cfghdr.hdr = &header;
3930 cfg.physAddr = cfg1_dma_addr;
3931 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3935 if (vtarget->raidVolume && ioc->raid_data.pIocPg3) {
3936 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
3937 id = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID;
3938 flags = hd->ioc->spi_data.noQas;
3939 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3940 data = hd->ioc->spi_data.nvram[id];
3941 if (data & MPT_NVRAM_WIDE_DISABLE)
3942 flags |= MPT_TARGET_NO_NEGO_WIDE;
3943 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
3944 if ((factor == 0) || (factor == MPT_ASYNC))
3945 flags |= MPT_TARGET_NO_NEGO_SYNC;
3947 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
3948 &configuration, flags);
3949 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
3950 "offset=0 negoFlags=%x request=%x config=%x\n",
3951 id, flags, requested, configuration));
3952 pcfg1Data->RequestedParameters = cpu_to_le32(requested);
3953 pcfg1Data->Reserved = 0;
3954 pcfg1Data->Configuration = cpu_to_le32(configuration);
3955 cfg.pageAddr = (vtarget->bus_id<<8) | id;
3956 mpt_config(hd->ioc, &cfg);
3959 flags = vtarget->negoFlags;
3960 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
3961 &configuration, flags);
3962 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
3963 "offset=0 negoFlags=%x request=%x config=%x\n",
3964 vtarget->target_id, flags, requested, configuration));
3965 pcfg1Data->RequestedParameters = cpu_to_le32(requested);
3966 pcfg1Data->Reserved = 0;
3967 pcfg1Data->Configuration = cpu_to_le32(configuration);
3968 cfg.pageAddr = (vtarget->bus_id<<8) | vtarget->target_id;
3969 mpt_config(hd->ioc, &cfg);
3973 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pcfg1Data, cfg1_dma_addr);
3976 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3978 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3979 * @hd: Pointer to a SCSI HOST structure
3980 * @vtarget: per device private data
3983 * Uses the ISR, but with special processing.
3984 * MUST be single-threaded.
3988 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3992 /* Following parameters will not change
3995 iocmd.cmd = SYNCHRONIZE_CACHE;
3997 iocmd.physDiskNum = -1;
3999 iocmd.data_dma = -1;
4001 iocmd.rsvd = iocmd.rsvd2 = 0;
4002 iocmd.bus = vdevice->bus_id;
4003 iocmd.id = vdevice->target_id;
4004 iocmd.lun = (u8)vdevice->lun;
4006 if ((vdevice->vtarget->type & TYPE_DISK) &&
4007 (vdevice->configured_lun))
4008 mptscsih_do_cmd(hd, &iocmd);
4011 /* Search IOC page 3 to determine if this is hidden physical disk
4014 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
4018 if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
4021 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
4022 if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
4029 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4030 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4032 * mptscsih_domainValidation - Top level handler for domain validation.
4033 * @hd: Pointer to MPT_SCSI_HOST structure.
4035 * Uses the ISR, but with special processing.
4036 * Called from schedule, should not be in interrupt mode.
4037 * While thread alive, do dv for all devices needing dv
4042 mptscsih_domainValidation(void *arg)
4046 unsigned long flags;
4047 int id, maxid, dvStatus, did;
4050 spin_lock_irqsave(&dvtaskQ_lock, flags);
4052 if (dvtaskQ_release) {
4054 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4057 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4059 /* For this ioc, loop through all devices and do dv to each device.
4060 * When complete with this ioc, search through the ioc list, and
4061 * for each scsi ioc found, do dv for all devices. Exit when no
4067 list_for_each_entry(ioc, &ioc_list, list) {
4068 spin_lock_irqsave(&dvtaskQ_lock, flags);
4069 if (dvtaskQ_release) {
4071 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4074 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4078 /* DV only to SPI adapters */
4079 if (ioc->bus_type != SPI)
4082 /* Make sure everything looks ok */
4083 if (ioc->sh == NULL)
4086 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4090 if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
4091 mpt_read_ioc_pg_3(ioc);
4092 if (ioc->raid_data.pIocPg3) {
4093 Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
4094 int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
4097 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
4098 ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4104 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
4107 maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
4109 for (id = 0; id < maxid; id++) {
4110 spin_lock_irqsave(&dvtaskQ_lock, flags);
4111 if (dvtaskQ_release) {
4113 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4116 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4117 dvStatus = hd->ioc->spi_data.dvStatus[id];
4119 if (dvStatus & MPT_SCSICFG_NEED_DV) {
4121 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
4122 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
4126 /* If hidden phys disk, block IO's to all
4128 * else, process normally
4130 isPhysDisk = mptscsih_is_phys_disk(ioc, id);
4132 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4133 if (hd->ioc->raid_data.isRaid & (1 << ii)) {
4134 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
4139 if(mpt_alt_ioc_wait(hd->ioc)!=0) {
4140 ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n",
4145 if (mptscsih_doDv(hd, 0, id) == 1) {
4146 /* Untagged device was busy, try again
4148 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
4149 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
4151 /* DV is complete. Clear flags.
4153 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
4156 spin_lock(&hd->ioc->initializing_hba_lock);
4157 hd->ioc->initializing_hba_lock_flag=0;
4158 spin_unlock(&hd->ioc->initializing_hba_lock);
4161 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4162 if (hd->ioc->raid_data.isRaid & (1 << ii)) {
4163 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
4168 if (hd->ioc->spi_data.noQas)
4169 mptscsih_qas_check(hd, id);
4175 spin_lock_irqsave(&dvtaskQ_lock, flags);
4177 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4182 /* Write SDP1 if no QAS has been enabled
4185 mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
4187 VirtTarget *vtarget;
4190 if (hd->Targets == NULL)
4193 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4197 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
4200 vtarget = hd->Targets[ii];
4202 if ((vtarget != NULL) && (!vtarget->raidVolume)) {
4203 if ((vtarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
4204 vtarget->negoFlags |= hd->ioc->spi_data.noQas;
4205 dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
4206 mptscsih_writeSDP1(hd, 0, ii, 0);
4209 if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
4210 dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
4211 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
4220 #define MPT_GET_NVRAM_VALS 0x01
4221 #define MPT_UPDATE_MAX 0x02
4222 #define MPT_SET_MAX 0x04
4223 #define MPT_SET_MIN 0x08
4224 #define MPT_FALLBACK 0x10
4225 #define MPT_SAVE 0x20
4227 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4229 * mptscsih_doDv - Perform domain validation to a target.
4230 * @hd: Pointer to MPT_SCSI_HOST structure.
4231 * @portnum: IOC port number.
4232 * @target: Physical ID of this target
4234 * Uses the ISR, but with special processing.
4235 * MUST be single-threaded.
4236 * Test will exit if target is at async & narrow.
4241 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
4243 MPT_ADAPTER *ioc = hd->ioc;
4244 VirtTarget *vtarget;
4245 SCSIDevicePage1_t *pcfg1Data;
4246 SCSIDevicePage0_t *pcfg0Data;
4250 dma_addr_t dvbuf_dma = -1;
4251 dma_addr_t buf1_dma = -1;
4252 dma_addr_t buf2_dma = -1;
4253 dma_addr_t cfg1_dma_addr = -1;
4254 dma_addr_t cfg0_dma_addr = -1;
4255 ConfigPageHeader_t header1;
4256 ConfigPageHeader_t header0;
4263 int dataBufSize = 0;
4264 int echoBufSize = 0;
4269 int nfactor = MPT_ULTRA320;
4271 char doFallback = 0;
4276 if (ioc->spi_data.sdp1length == 0)
4279 if (ioc->spi_data.sdp0length == 0)
4282 /* If multiple buses are used, require that the initiator
4283 * id be the same on all buses.
4285 if (id == ioc->pfacts[0].PortSCSIID)
4289 bus = (u8) bus_number;
4290 ddvtprintk((MYIOC_s_NOTE_FMT
4291 "DV started: bus=%d, id=%d dv @ %p\n",
4292 ioc->name, bus, id, &dv));
4294 /* Prep DV structure
4296 memset (&dv, 0, sizeof(DVPARAMETERS));
4299 /* Populate tmax with the current maximum
4300 * transfer parameters for this target.
4301 * Exit if narrow and async.
4303 dv.cmd = MPT_GET_NVRAM_VALS;
4304 mptscsih_dv_parms(hd, &dv, NULL);
4306 /* Prep SCSI IO structure
4312 iocmd.physDiskNum = -1;
4313 iocmd.rsvd = iocmd.rsvd2 = 0;
4315 vtarget = hd->Targets[id];
4317 /* Use tagged commands if possible.
4320 if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
4321 iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
4323 if (hd->ioc->facts.FWVersion.Word < 0x01000600)
4326 if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4327 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
4332 /* Prep cfg structure
4334 cfg.pageAddr = (bus<<8) | id;
4335 cfg.cfghdr.hdr = NULL;
4339 header0.PageVersion = ioc->spi_data.sdp0version;
4340 header0.PageLength = ioc->spi_data.sdp0length;
4341 header0.PageNumber = 0;
4342 header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4346 header1.PageVersion = ioc->spi_data.sdp1version;
4347 header1.PageLength = ioc->spi_data.sdp1length;
4348 header1.PageNumber = 1;
4349 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4351 if (header0.PageLength & 1)
4352 dv_alloc = (header0.PageLength * 4) + 4;
4354 dv_alloc += (2048 + (header1.PageLength * 4));
4356 pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
4361 pbuf1 = (u8 *)pDvBuf;
4362 buf1_dma = dvbuf_dma;
4365 pbuf2 = (u8 *) (pDvBuf + sz);
4366 buf2_dma = dvbuf_dma + sz;
4369 pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
4370 cfg0_dma_addr = dvbuf_dma + sz;
4371 sz += header0.PageLength * 4;
4375 if (header0.PageLength & 1)
4378 pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
4379 cfg1_dma_addr = dvbuf_dma + sz;
4381 /* Skip this ID? Set cfg.cfghdr.hdr to force config page write
4384 SpiCfgData *pspi_data = &hd->ioc->spi_data;
4385 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4386 /* Set the factor from nvram */
4387 nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
4388 if (nfactor < pspi_data->minSyncFactor )
4389 nfactor = pspi_data->minSyncFactor;
4391 if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
4392 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
4394 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
4395 ioc->name, bus, id, lun));
4397 dv.cmd = MPT_SET_MAX;
4398 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4399 cfg.cfghdr.hdr = &header1;
4401 /* Save the final negotiated settings to
4402 * SCSI device page 1.
4404 cfg.physAddr = cfg1_dma_addr;
4405 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4407 mpt_config(hd->ioc, &cfg);
4413 /* Finish iocmd inititialization - hidden or visible disk? */
4414 if (ioc->raid_data.pIocPg3) {
4415 /* Search IOC page 3 for matching id
4417 Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
4418 int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
4421 if (pPDisk->PhysDiskID == id) {
4423 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
4424 iocmd.physDiskNum = pPDisk->PhysDiskNum;
4428 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
4429 ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
4439 /* RAID Volume ID's may double for a physical device. If RAID but
4440 * not a physical ID as well, skip DV.
4442 if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
4447 * Async & Narrow - Inquiry
4448 * Async & Narrow - Inquiry
4449 * Maximum transfer rate - Inquiry
4451 * If compare, test complete.
4452 * If miscompare and first pass, repeat
4453 * If miscompare and not first pass, fall back and repeat
4457 sz = SCSI_MAX_INQUIRY_BYTES;
4458 rc = MPT_SCANDV_GOOD;
4460 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
4462 dv.cmd = MPT_SET_MIN;
4463 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4465 cfg.cfghdr.hdr = &header1;
4466 cfg.physAddr = cfg1_dma_addr;
4467 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4469 if (mpt_config(hd->ioc, &cfg) != 0)
4472 /* Wide - narrow - wide workaround case
4474 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
4475 /* Send an untagged command to reset disk Qs corrupted
4476 * when a parity error occurs on a Request Sense.
4478 if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
4479 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4480 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
4482 iocmd.cmd = REQUEST_SENSE;
4483 iocmd.data_dma = buf1_dma;
4486 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4489 if (hd->pLocal == NULL)
4491 rc = hd->pLocal->completion;
4492 if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
4502 iocmd.cmd = INQUIRY;
4503 iocmd.data_dma = buf1_dma;
4506 memset(pbuf1, 0x00, sz);
4507 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4510 if (hd->pLocal == NULL)
4512 rc = hd->pLocal->completion;
4513 if (rc == MPT_SCANDV_GOOD) {
4514 if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
4515 if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
4522 } else if (rc == MPT_SCANDV_SENSE) {
4525 /* If first command doesn't complete
4526 * with a good status or with a check condition,
4533 /* Reset the size for disks
4535 inq0 = (*pbuf1) & 0x1F;
4536 if ((inq0 == 0) && vtarget && !vtarget->raidVolume) {
4541 /* Another GEM workaround. Check peripheral device type,
4542 * if PROCESSOR, quit DV.
4544 if (inq0 == TYPE_PROCESSOR) {
4545 mptscsih_initTarget(hd,
4556 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4560 if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A)
4561 && (vtarget->minSyncFactor > 0x09)) {
4562 if ((pbuf1[56] & 0x04) == 0)
4564 else if ((pbuf1[56] & 0x01) == 1) {
4565 vtarget->minSyncFactor =
4566 nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
4568 vtarget->minSyncFactor =
4569 nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
4572 dv.max.factor = vtarget->minSyncFactor;
4574 if ((pbuf1[56] & 0x02) == 0) {
4575 vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4576 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
4577 ddvprintk((MYIOC_s_NOTE_FMT
4578 "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
4579 ioc->name, id, pbuf1[56]));
4585 dv.cmd = MPT_FALLBACK;
4587 dv.cmd = MPT_SET_MAX;
4589 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4590 if (mpt_config(hd->ioc, &cfg) != 0)
4593 if ((!dv.now.width) && (!dv.now.offset))
4596 iocmd.cmd = INQUIRY;
4597 iocmd.data_dma = buf2_dma;
4600 memset(pbuf2, 0x00, sz);
4601 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4603 else if (hd->pLocal == NULL)
4606 /* Save the return code.
4607 * If this is the first pass,
4608 * read SCSI Device Page 0
4609 * and update the target max parameters.
4611 rc = hd->pLocal->completion;
4613 if (rc == MPT_SCANDV_GOOD) {
4618 cfg.cfghdr.hdr = &header0;
4619 cfg.physAddr = cfg0_dma_addr;
4620 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4623 if (mpt_config(hd->ioc, &cfg) != 0)
4626 sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
4627 sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
4629 /* Quantum and Fujitsu workarounds.
4630 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
4631 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
4632 * Resetart with a request for U160.
4634 if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
4637 dv.cmd = MPT_UPDATE_MAX;
4638 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
4639 /* Update the SCSI device page 1 area
4641 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
4646 /* Quantum workaround. Restart this test will the fallback
4649 if (doFallback == 0) {
4650 if (memcmp(pbuf1, pbuf2, sz) != 0) {
4654 ddvprintk((MYIOC_s_NOTE_FMT
4655 "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
4656 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
4657 mptscsih_initTarget(hd,
4662 break; /* test complete */
4667 } else if (rc == MPT_SCANDV_ISSUE_SENSE)
4668 doFallback = 1; /* set fallback flag */
4669 else if ((rc == MPT_SCANDV_DID_RESET) ||
4670 (rc == MPT_SCANDV_SENSE) ||
4671 (rc == MPT_SCANDV_FALLBACK))
4672 doFallback = 1; /* set fallback flag */
4679 ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
4681 if (ioc->spi_data.mpt_dv == 0)
4684 inq0 = (*pbuf1) & 0x1F;
4686 /* Continue only for disks
4691 if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
4694 /* Start the Enhanced Test.
4695 * 0) issue TUR to clear out check conditions
4696 * 1) read capacity of echo (regular) buffer
4698 * 3) do write-read-compare data pattern test
4700 * 5) update nego parms to target struct
4702 cfg.cfghdr.hdr = &header1;
4703 cfg.physAddr = cfg1_dma_addr;
4704 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4707 iocmd.cmd = TEST_UNIT_READY;
4708 iocmd.data_dma = -1;
4713 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4716 if (hd->pLocal == NULL)
4719 rc = hd->pLocal->completion;
4720 if (rc == MPT_SCANDV_GOOD)
4722 else if (rc == MPT_SCANDV_SENSE) {
4723 u8 skey = hd->pLocal->sense[2] & 0x0F;
4724 u8 asc = hd->pLocal->sense[12];
4725 u8 ascq = hd->pLocal->sense[13];
4726 ddvprintk((MYIOC_s_INFO_FMT
4727 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4728 ioc->name, skey, asc, ascq));
4730 if (skey == UNIT_ATTENTION)
4731 notDone++; /* repeat */
4732 else if ((skey == NOT_READY) &&
4733 (asc == 0x04)&&(ascq == 0x01)) {
4734 /* wait then repeat */
4737 } else if ((skey == NOT_READY) && (asc == 0x3A)) {
4738 /* no medium, try read test anyway */
4741 /* All other errors are fatal.
4743 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4751 iocmd.cmd = READ_BUFFER;
4752 iocmd.data_dma = buf1_dma;
4755 iocmd.flags |= MPT_ICFLAG_BUF_CAP;
4759 for (patt = 0; patt < 2; patt++) {
4761 iocmd.flags |= MPT_ICFLAG_ECHO;
4763 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4769 /* If not ready after 8 trials,
4770 * give up on this device.
4775 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4777 else if (hd->pLocal == NULL)
4780 rc = hd->pLocal->completion;
4781 ddvprintk(("ReadBuffer Comp Code %d", rc));
4782 ddvprintk((" buff: %0x %0x %0x %0x\n",
4783 pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
4785 if (rc == MPT_SCANDV_GOOD) {
4787 if (iocmd.flags & MPT_ICFLAG_ECHO) {
4788 bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
4789 if (pbuf1[0] & 0x01)
4790 iocmd.flags |= MPT_ICFLAG_EBOS;
4792 bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
4794 } else if (rc == MPT_SCANDV_SENSE) {
4795 u8 skey = hd->pLocal->sense[2] & 0x0F;
4796 u8 asc = hd->pLocal->sense[12];
4797 u8 ascq = hd->pLocal->sense[13];
4798 ddvprintk((MYIOC_s_INFO_FMT
4799 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4800 ioc->name, skey, asc, ascq));
4801 if (skey == ILLEGAL_REQUEST) {
4803 } else if (skey == UNIT_ATTENTION) {
4804 notDone++; /* repeat */
4805 } else if ((skey == NOT_READY) &&
4806 (asc == 0x04)&&(ascq == 0x01)) {
4807 /* wait then repeat */
4811 /* All other errors are fatal.
4813 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4818 /* All other errors are fatal
4825 if (iocmd.flags & MPT_ICFLAG_ECHO)
4826 echoBufSize = bufsize;
4828 dataBufSize = bufsize;
4831 iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
4833 /* Use echo buffers if possible,
4834 * Exit if both buffers are 0.
4836 if (echoBufSize > 0) {
4837 iocmd.flags |= MPT_ICFLAG_ECHO;
4838 if (dataBufSize > 0)
4839 bufsize = min(echoBufSize, dataBufSize);
4841 bufsize = echoBufSize;
4842 } else if (dataBufSize == 0)
4845 ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
4846 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
4848 /* Data buffers for write-read-compare test max 1K.
4850 sz = min(bufsize, 1024);
4853 * On first pass, always issue a reserve.
4854 * On additional loops, only if a reset has occurred.
4855 * iocmd.flags indicates if echo or regular buffer
4857 for (patt = 0; patt < 4; patt++) {
4858 ddvprintk(("Pattern %d\n", patt));
4859 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
4860 iocmd.cmd = TEST_UNIT_READY;
4861 iocmd.data_dma = -1;
4864 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4867 iocmd.cmd = RELEASE;
4868 iocmd.data_dma = -1;
4871 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4873 else if (hd->pLocal == NULL)
4876 rc = hd->pLocal->completion;
4877 ddvprintk(("Release rc %d\n", rc));
4878 if (rc == MPT_SCANDV_GOOD)
4879 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4883 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4885 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
4887 if (iocmd.flags & MPT_ICFLAG_EBOS)
4891 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
4892 iocmd.cmd = RESERVE;
4893 iocmd.data_dma = -1;
4896 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4898 else if (hd->pLocal == NULL)
4901 rc = hd->pLocal->completion;
4902 if (rc == MPT_SCANDV_GOOD) {
4903 iocmd.flags |= MPT_ICFLAG_RESERVED;
4904 } else if (rc == MPT_SCANDV_SENSE) {
4905 /* Wait if coming ready
4907 u8 skey = hd->pLocal->sense[2] & 0x0F;
4908 u8 asc = hd->pLocal->sense[12];
4909 u8 ascq = hd->pLocal->sense[13];
4910 ddvprintk((MYIOC_s_INFO_FMT
4911 "DV: Reserve Failed: ", ioc->name));
4912 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4915 if ((skey == NOT_READY) && (asc == 0x04)&&
4917 /* wait then repeat */
4921 ddvprintk((MYIOC_s_INFO_FMT
4922 "DV: Reserved Failed.", ioc->name));
4926 ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
4934 mptscsih_fillbuf(pbuf1, sz, patt, 1);
4935 iocmd.cmd = WRITE_BUFFER;
4936 iocmd.data_dma = buf1_dma;
4939 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4941 else if (hd->pLocal == NULL)
4944 rc = hd->pLocal->completion;
4945 if (rc == MPT_SCANDV_GOOD)
4946 ; /* Issue read buffer */
4947 else if (rc == MPT_SCANDV_DID_RESET) {
4948 /* If using echo buffers, reset to data buffers.
4949 * Else do Fallback and restart
4950 * this test (re-issue reserve
4951 * because of bus reset).
4953 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
4954 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4956 dv.cmd = MPT_FALLBACK;
4957 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4959 if (mpt_config(hd->ioc, &cfg) != 0)
4962 if ((!dv.now.width) && (!dv.now.offset))
4966 iocmd.flags |= MPT_ICFLAG_DID_RESET;
4969 } else if (rc == MPT_SCANDV_SENSE) {
4970 /* Restart data test if UA, else quit.
4972 u8 skey = hd->pLocal->sense[2] & 0x0F;
4973 ddvprintk((MYIOC_s_INFO_FMT
4974 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
4975 hd->pLocal->sense[12], hd->pLocal->sense[13]));
4976 if (skey == UNIT_ATTENTION) {
4979 } else if (skey == ILLEGAL_REQUEST) {
4980 if (iocmd.flags & MPT_ICFLAG_ECHO) {
4981 if (dataBufSize >= bufsize) {
4982 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4997 iocmd.cmd = READ_BUFFER;
4998 iocmd.data_dma = buf2_dma;
5001 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5003 else if (hd->pLocal == NULL)
5006 rc = hd->pLocal->completion;
5007 if (rc == MPT_SCANDV_GOOD) {
5008 /* If buffers compare,
5009 * go to next pattern,
5010 * else, do a fallback and restart
5011 * data transfer test.
5013 if (memcmp (pbuf1, pbuf2, sz) == 0) {
5014 ; /* goto next pattern */
5016 /* Miscompare with Echo buffer, go to data buffer,
5017 * if that buffer exists.
5018 * Miscompare with Data buffer, check first 4 bytes,
5019 * some devices return capacity. Exit in this case.
5021 if (iocmd.flags & MPT_ICFLAG_ECHO) {
5022 if (dataBufSize >= bufsize)
5023 iocmd.flags &= ~MPT_ICFLAG_ECHO;
5027 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
5028 /* Argh. Device returning wrong data.
5029 * Quit DV for this device.
5034 /* Had an actual miscompare. Slow down.*/
5035 dv.cmd = MPT_FALLBACK;
5036 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5038 if (mpt_config(hd->ioc, &cfg) != 0)
5041 if ((!dv.now.width) && (!dv.now.offset))
5048 } else if (rc == MPT_SCANDV_DID_RESET) {
5049 /* Do Fallback and restart
5050 * this test (re-issue reserve
5051 * because of bus reset).
5053 dv.cmd = MPT_FALLBACK;
5054 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5056 if (mpt_config(hd->ioc, &cfg) != 0)
5059 if ((!dv.now.width) && (!dv.now.offset))
5062 iocmd.flags |= MPT_ICFLAG_DID_RESET;
5065 } else if (rc == MPT_SCANDV_SENSE) {
5066 /* Restart data test if UA, else quit.
5068 u8 skey = hd->pLocal->sense[2] & 0x0F;
5069 ddvprintk((MYIOC_s_INFO_FMT
5070 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
5071 hd->pLocal->sense[12], hd->pLocal->sense[13]));
5072 if (skey == UNIT_ATTENTION) {
5084 } /* --- end of patt loop ---- */
5087 if (iocmd.flags & MPT_ICFLAG_RESERVED) {
5088 iocmd.cmd = RELEASE;
5089 iocmd.data_dma = -1;
5092 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5093 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5095 else if (hd->pLocal) {
5096 if (hd->pLocal->completion == MPT_SCANDV_GOOD)
5097 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
5099 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5105 /* Set if cfg1_dma_addr contents is valid
5107 if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){
5108 /* If disk, not U320, disable QAS
5110 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
5111 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
5112 ddvprintk((MYIOC_s_NOTE_FMT
5113 "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
5117 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5119 /* Double writes to SDP1 can cause problems,
5120 * skip save of the final negotiated settings to
5121 * SCSI device page 1.
5123 cfg.cfghdr.hdr = &header1;
5124 cfg.physAddr = cfg1_dma_addr;
5125 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5127 mpt_config(hd->ioc, &cfg);
5131 /* If this is a RAID Passthrough, enable internal IOs
5133 if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
5134 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
5135 ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
5138 /* Done with the DV scan of the current target
5141 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
5143 ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
5149 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5150 /* mptscsih_dv_parms - perform a variety of operations on the
5151 * parameters used for negotiation.
5152 * @hd: Pointer to a SCSI host.
5153 * @dv: Pointer to a structure that contains the maximum and current
5154 * negotiated parameters.
5157 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
5159 VirtTarget *vtarget;
5160 SCSIDevicePage0_t *pPage0;
5161 SCSIDevicePage1_t *pPage1;
5162 int val = 0, data, configuration;
5171 case MPT_GET_NVRAM_VALS:
5172 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
5174 /* Get the NVRAM values and save in tmax
5175 * If not an LVD bus, the adapter minSyncFactor has been
5176 * already throttled back.
5178 negoFlags = hd->ioc->spi_data.noQas;
5179 if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume) {
5180 width = vtarget->maxWidth;
5181 offset = vtarget->maxOffset;
5182 factor = vtarget->minSyncFactor;
5183 negoFlags |= vtarget->negoFlags;
5185 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5186 data = hd->ioc->spi_data.nvram[id];
5187 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
5188 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
5191 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5192 if ((factor == 0) || (factor == MPT_ASYNC)){
5203 /* Set the negotiation flags */
5205 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
5208 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
5211 /* limit by adapter capabilities */
5212 width = min(width, hd->ioc->spi_data.maxBusWidth);
5213 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
5214 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
5216 /* Check Consistency */
5217 if (offset && (factor < MPT_ULTRA2) && !width)
5218 factor = MPT_ULTRA2;
5220 dv->max.width = width;
5221 dv->max.offset = offset;
5222 dv->max.factor = factor;
5223 dv->max.flags = negoFlags;
5224 ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
5225 id, width, factor, offset, negoFlags));
5228 case MPT_UPDATE_MAX:
5229 ddvprintk((MYIOC_s_NOTE_FMT
5230 "Updating with SDP0 Data: ", hd->ioc->name));
5231 /* Update tmax values with those from Device Page 0.*/
5232 pPage0 = (SCSIDevicePage0_t *) pPage;
5234 val = le32_to_cpu(pPage0->NegotiatedParameters);
5235 dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
5236 dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
5237 dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
5240 dv->now.width = dv->max.width;
5241 dv->now.offset = dv->max.offset;
5242 dv->now.factor = dv->max.factor;
5243 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
5244 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5248 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
5250 /* Set current to the max values. Update the config page.*/
5251 dv->now.width = dv->max.width;
5252 dv->now.offset = dv->max.offset;
5253 dv->now.factor = dv->max.factor;
5254 dv->now.flags = dv->max.flags;
5256 pPage1 = (SCSIDevicePage1_t *)pPage;
5258 mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
5259 dv->now.offset, &val, &configuration, dv->now.flags);
5260 dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5261 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5262 pPage1->RequestedParameters = cpu_to_le32(val);
5263 pPage1->Reserved = 0;
5264 pPage1->Configuration = cpu_to_le32(configuration);
5267 ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
5268 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5272 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
5274 /* Set page to asynchronous and narrow
5275 * Do not update now, breaks fallback routine. */
5279 negoFlags = dv->max.flags;
5281 pPage1 = (SCSIDevicePage1_t *)pPage;
5283 mptscsih_setDevicePage1Flags (width, factor,
5284 offset, &val, &configuration, negoFlags);
5285 dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5286 id, width, factor, offset, negoFlags, val, configuration));
5287 pPage1->RequestedParameters = cpu_to_le32(val);
5288 pPage1->Reserved = 0;
5289 pPage1->Configuration = cpu_to_le32(configuration);
5291 ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
5292 id, width, factor, offset, val, configuration, negoFlags));
5296 ddvprintk((MYIOC_s_NOTE_FMT
5297 "Fallback: Start: offset %d, factor %x, width %d \n",
5298 hd->ioc->name, dv->now.offset,
5299 dv->now.factor, dv->now.width));
5300 width = dv->now.width;
5301 offset = dv->now.offset;
5302 factor = dv->now.factor;
5303 if ((offset) && (dv->max.width)) {
5304 if (factor < MPT_ULTRA160)
5305 factor = MPT_ULTRA160;
5306 else if (factor < MPT_ULTRA2) {
5307 factor = MPT_ULTRA2;
5309 } else if ((factor == MPT_ULTRA2) && width) {
5310 factor = MPT_ULTRA2;
5312 } else if (factor < MPT_ULTRA) {
5315 } else if ((factor == MPT_ULTRA) && width) {
5317 } else if (factor < MPT_FAST) {
5320 } else if ((factor == MPT_FAST) && width) {
5323 } else if (factor < MPT_SCSI) {
5326 } else if ((factor == MPT_SCSI) && width) {
5334 } else if (offset) {
5336 if (factor < MPT_ULTRA)
5338 else if (factor < MPT_FAST)
5340 else if (factor < MPT_SCSI)
5351 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
5352 dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
5354 dv->now.width = width;
5355 dv->now.offset = offset;
5356 dv->now.factor = factor;
5357 dv->now.flags = dv->max.flags;
5359 pPage1 = (SCSIDevicePage1_t *)pPage;
5361 mptscsih_setDevicePage1Flags (width, factor, offset, &val,
5362 &configuration, dv->now.flags);
5363 dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
5364 id, width, offset, factor, dv->now.flags, val, configuration));
5366 pPage1->RequestedParameters = cpu_to_le32(val);
5367 pPage1->Reserved = 0;
5368 pPage1->Configuration = cpu_to_le32(configuration);
5371 ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
5372 id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
5376 ddvprintk((MYIOC_s_NOTE_FMT
5377 "Saving to Target structure: ", hd->ioc->name));
5378 ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
5379 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5381 /* Save these values to target structures
5382 * or overwrite nvram (phys disks only).
5385 if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume ) {
5386 vtarget->maxWidth = dv->now.width;
5387 vtarget->maxOffset = dv->now.offset;
5388 vtarget->minSyncFactor = dv->now.factor;
5389 vtarget->negoFlags = dv->now.flags;
5391 /* Preserv all flags, use
5392 * read-modify-write algorithm
5394 if (hd->ioc->spi_data.nvram) {
5395 data = hd->ioc->spi_data.nvram[id];
5398 data &= ~MPT_NVRAM_WIDE_DISABLE;
5400 data |= MPT_NVRAM_WIDE_DISABLE;
5402 if (!dv->now.offset)
5405 data &= ~MPT_NVRAM_SYNC_MASK;
5406 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
5408 hd->ioc->spi_data.nvram[id] = data;
5415 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5416 /* mptscsih_fillbuf - fill a buffer with a special data pattern
5417 * cleanup. For bus scan only.
5419 * @buffer: Pointer to data buffer to be filled.
5420 * @size: Number of bytes to fill
5421 * @index: Pattern index
5422 * @width: bus width, 0 (8 bits) or 1 (16 bits)
5425 mptscsih_fillbuf(char *buffer, int size, int index, int width)
5436 /* Pattern: 0000 FFFF 0000 FFFF
5438 for (ii=0; ii < size; ii++, ptr++) {
5445 /* Pattern: 00 FF 00 FF
5447 for (ii=0; ii < size; ii++, ptr++) {
5458 /* Pattern: 5555 AAAA 5555 AAAA 5555
5460 for (ii=0; ii < size; ii++, ptr++) {
5467 /* Pattern: 55 AA 55 AA 55
5469 for (ii=0; ii < size; ii++, ptr++) {
5479 /* Pattern: 00 01 02 03 04 05
5482 for (ii=0; ii < size; ii++, ptr++)
5488 /* Wide Pattern: FFFE 0001 FFFD 0002
5489 * ... 4000 DFFF 8000 EFFF
5492 for (ii=0; ii < size/2; ii++) {
5493 /* Create the base pattern
5496 /* every 64 (0x40) bytes flip the pattern
5497 * since we fill 2 bytes / iteration,
5498 * test for ii = 0x20
5504 *ptr = (char)( (val & 0xFF00) >> 8);
5506 *ptr = (char)(val & 0xFF);
5511 *ptr = (char)( (val & 0xFF00) >> 8);
5513 *ptr = (char)(val & 0xFF);
5519 /* Narrow Pattern: FE 01 FD 02 FB 04
5520 * .. 7F 80 01 FE 02 FD ... 80 7F
5523 for (ii=0; ii < size; ii++, ptr++) {
5524 /* Base pattern - first 32 bytes
5531 *ptr = (char) (~(1 << byte));
5534 /* Flip the pattern every 32 bytes
5544 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5545 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
5546 * Else set the NEED_DV flag after Read Capacity Issued (disks)
5547 * or Mode Sense (cdroms).
5549 * Tapes, initTarget will set this flag on completion of Inquiry command.
5550 * Called only if DV_NOT_DONE flag is set
5553 mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
5555 MPT_ADAPTER *ioc = hd->ioc;
5559 ddvtprintk((MYIOC_s_NOTE_FMT
5560 " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
5561 hd->ioc->name, sc->device->id, sc->device->lun , hd->negoNvram, sc->cmnd[0]));
5563 if ((sc->device->lun != 0) || (hd->negoNvram != 0))
5568 if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
5569 pSpi = &ioc->spi_data;
5570 if ((ioc->raid_data.isRaid & (1 << sc->device->id)) && ioc->raid_data.pIocPg3) {
5571 /* Set NEED_DV for all hidden disks
5573 Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
5574 int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
5577 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
5578 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
5583 pSpi->dvStatus[sc->device->id] |= MPT_SCSICFG_NEED_DV;
5584 ddvtprintk(("NEED_DV set for visible disk id %d\n", sc->device->id));
5588 /* mptscsih_raid_set_dv_flags()
5590 * New or replaced disk. Set DV flag and schedule DV.
5593 mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
5595 MPT_ADAPTER *ioc = hd->ioc;
5596 SpiCfgData *pSpi = &ioc->spi_data;
5597 Ioc3PhysDisk_t *pPDisk;
5600 if (hd->negoNvram != 0)
5603 ddvtprintk(("DV requested for phys disk id %d\n", id));
5604 if (ioc->raid_data.pIocPg3) {
5605 pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
5606 numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
5608 if (id == pPDisk->PhysDiskNum) {
5609 pSpi->dvStatus[pPDisk->PhysDiskID] =
5610 (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
5611 pSpi->forceDv = MPT_SCSICFG_NEED_DV;
5612 ddvtprintk(("NEED_DV set for phys disk id %d\n",
5613 pPDisk->PhysDiskID));
5620 if (numPDisk == 0) {
5621 /* The physical disk that needs DV was not found
5622 * in the stored IOC Page 3. The driver must reload
5623 * this page. DV routine will set the NEED_DV flag for
5624 * all phys disks that have DV_NOT_DONE set.
5626 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
5627 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
5631 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5633 EXPORT_SYMBOL(mptscsih_remove);
5634 EXPORT_SYMBOL(mptscsih_shutdown);
5636 EXPORT_SYMBOL(mptscsih_suspend);
5637 EXPORT_SYMBOL(mptscsih_resume);
5639 EXPORT_SYMBOL(mptscsih_proc_info);
5640 EXPORT_SYMBOL(mptscsih_info);
5641 EXPORT_SYMBOL(mptscsih_qcmd);
5642 EXPORT_SYMBOL(mptscsih_target_alloc);
5643 EXPORT_SYMBOL(mptscsih_slave_alloc);
5644 EXPORT_SYMBOL(mptscsih_target_destroy);
5645 EXPORT_SYMBOL(mptscsih_slave_destroy);
5646 EXPORT_SYMBOL(mptscsih_slave_configure);
5647 EXPORT_SYMBOL(mptscsih_abort);
5648 EXPORT_SYMBOL(mptscsih_dev_reset);
5649 EXPORT_SYMBOL(mptscsih_bus_reset);
5650 EXPORT_SYMBOL(mptscsih_host_reset);
5651 EXPORT_SYMBOL(mptscsih_bios_param);
5652 EXPORT_SYMBOL(mptscsih_io_done);
5653 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
5654 EXPORT_SYMBOL(mptscsih_scandv_complete);
5655 EXPORT_SYMBOL(mptscsih_event_process);
5656 EXPORT_SYMBOL(mptscsih_ioc_reset);
5657 EXPORT_SYMBOL(mptscsih_change_queue_depth);
5658 EXPORT_SYMBOL(mptscsih_timer_expired);
5659 EXPORT_SYMBOL(mptscsih_TMHandler);
5661 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/