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>
69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70 #define my_NAME "Fusion MPT SCSI Host driver"
71 #define my_VERSION MPT_LINUX_VERSION_COMMON
72 #define MYNAM "mptscsih"
74 MODULE_AUTHOR(MODULEAUTHOR
);
75 MODULE_DESCRIPTION(my_NAME
);
76 MODULE_LICENSE("GPL");
78 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
80 typedef struct _BIG_SENSE_BUF
{
81 u8 data
[MPT_SENSE_BUFFER_ALLOC
];
84 #define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
85 #define MPT_SCANDV_DID_RESET (0x00000001)
86 #define MPT_SCANDV_SENSE (0x00000002)
87 #define MPT_SCANDV_SOME_ERROR (0x00000004)
88 #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
89 #define MPT_SCANDV_ISSUE_SENSE (0x00000010)
90 #define MPT_SCANDV_FALLBACK (0x00000020)
92 #define MPT_SCANDV_MAX_RETRIES (10)
94 #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
95 #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
96 #define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */
97 #define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */
98 #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
99 #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
101 typedef struct _internal_cmd
{
102 char *data
; /* data pointer */
103 dma_addr_t data_dma
; /* data dma address */
104 int size
; /* transfer size */
105 u8 cmd
; /* SCSI Op Code */
106 u8 bus
; /* bus number */
107 u8 id
; /* SCSI ID (virtual) */
109 u8 flags
; /* Bit Field - See above */
110 u8 physDiskNum
; /* Phys disk number, -1 else */
115 typedef struct _negoparms
{
122 typedef struct _dv_parameters
{
131 * Other private/forward protos...
133 int mptscsih_io_done(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
, MPT_FRAME_HDR
*r
);
134 static void mptscsih_report_queue_full(struct scsi_cmnd
*sc
, SCSIIOReply_t
*pScsiReply
, SCSIIORequest_t
*pScsiReq
);
135 int mptscsih_taskmgmt_complete(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
, MPT_FRAME_HDR
*r
);
137 static int mptscsih_AddSGE(MPT_ADAPTER
*ioc
, struct scsi_cmnd
*SCpnt
,
138 SCSIIORequest_t
*pReq
, int req_idx
);
139 static void mptscsih_freeChainBuffers(MPT_ADAPTER
*ioc
, int req_idx
);
140 static void mptscsih_copy_sense_data(struct scsi_cmnd
*sc
, MPT_SCSI_HOST
*hd
, MPT_FRAME_HDR
*mf
, SCSIIOReply_t
*pScsiReply
);
141 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST
* hd
);
142 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST
* hd
, ulong timeout
);
143 static u32
SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd
*sc
);
145 static int mptscsih_TMHandler(MPT_SCSI_HOST
*hd
, u8 type
, u8 channel
, u8 target
, u8 lun
, int ctx2abort
, ulong timeout
);
146 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST
*hd
, u8 type
, u8 channel
, u8 target
, u8 lun
, int ctx2abort
, ulong timeout
);
148 int mptscsih_ioc_reset(MPT_ADAPTER
*ioc
, int post_reset
);
149 int mptscsih_event_process(MPT_ADAPTER
*ioc
, EventNotificationReply_t
*pEvReply
);
151 static void mptscsih_initTarget(MPT_SCSI_HOST
*hd
, int bus_id
, int target_id
, u8 lun
, char *data
, int dlen
);
152 static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST
*hd
, VirtDevice
*target
, char byte56
);
153 static void mptscsih_set_dvflags(MPT_SCSI_HOST
*hd
, SCSIIORequest_t
*pReq
);
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
, int target_id
);
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 int mptscsih_synchronize_cache(MPT_SCSI_HOST
*hd
, int portnum
);
162 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
163 static int mptscsih_do_raid(MPT_SCSI_HOST
*hd
, u8 action
, INTERNAL_CMD
*io
);
164 static void mptscsih_domainValidation(void *hd
);
165 static int mptscsih_is_phys_disk(MPT_ADAPTER
*ioc
, int id
);
166 static void mptscsih_qas_check(MPT_SCSI_HOST
*hd
, int id
);
167 static int mptscsih_doDv(MPT_SCSI_HOST
*hd
, int channel
, int target
);
168 static void mptscsih_dv_parms(MPT_SCSI_HOST
*hd
, DVPARAMETERS
*dv
,void *pPage
);
169 static void mptscsih_fillbuf(char *buffer
, int size
, int index
, int width
);
172 void mptscsih_remove(struct pci_dev
*);
173 void mptscsih_shutdown(struct device
*);
175 int mptscsih_suspend(struct pci_dev
*pdev
, pm_message_t state
);
176 int mptscsih_resume(struct pci_dev
*pdev
);
179 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
181 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
183 * Domain Validation task structure
185 static DEFINE_SPINLOCK(dvtaskQ_lock
);
186 static int dvtaskQ_active
= 0;
187 static int dvtaskQ_release
= 0;
188 static struct work_struct dvTaskQ_task
;
191 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
193 * mptscsih_add_sge - Place a simple SGE at address pAddr.
194 * @pAddr: virtual address for SGE
195 * @flagslength: SGE flags and data transfer length
196 * @dma_addr: Physical address
198 * This routine places a MPT request frame back on the MPT adapter's
202 mptscsih_add_sge(char *pAddr
, u32 flagslength
, dma_addr_t dma_addr
)
204 if (sizeof(dma_addr_t
) == sizeof(u64
)) {
205 SGESimple64_t
*pSge
= (SGESimple64_t
*) pAddr
;
206 u32 tmp
= dma_addr
& 0xFFFFFFFF;
208 pSge
->FlagsLength
= cpu_to_le32(flagslength
);
209 pSge
->Address
.Low
= cpu_to_le32(tmp
);
210 tmp
= (u32
) ((u64
)dma_addr
>> 32);
211 pSge
->Address
.High
= cpu_to_le32(tmp
);
214 SGESimple32_t
*pSge
= (SGESimple32_t
*) pAddr
;
215 pSge
->FlagsLength
= cpu_to_le32(flagslength
);
216 pSge
->Address
= cpu_to_le32(dma_addr
);
218 } /* mptscsih_add_sge() */
220 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
222 * mptscsih_add_chain - Place a chain SGE at address pAddr.
223 * @pAddr: virtual address for SGE
224 * @next: nextChainOffset value (u32's)
225 * @length: length of next SGL segment
226 * @dma_addr: Physical address
228 * This routine places a MPT request frame back on the MPT adapter's
232 mptscsih_add_chain(char *pAddr
, u8 next
, u16 length
, dma_addr_t dma_addr
)
234 if (sizeof(dma_addr_t
) == sizeof(u64
)) {
235 SGEChain64_t
*pChain
= (SGEChain64_t
*) pAddr
;
236 u32 tmp
= dma_addr
& 0xFFFFFFFF;
238 pChain
->Length
= cpu_to_le16(length
);
239 pChain
->Flags
= MPI_SGE_FLAGS_CHAIN_ELEMENT
| mpt_addr_size();
241 pChain
->NextChainOffset
= next
;
243 pChain
->Address
.Low
= cpu_to_le32(tmp
);
244 tmp
= (u32
) ((u64
)dma_addr
>> 32);
245 pChain
->Address
.High
= cpu_to_le32(tmp
);
247 SGEChain32_t
*pChain
= (SGEChain32_t
*) pAddr
;
248 pChain
->Length
= cpu_to_le16(length
);
249 pChain
->Flags
= MPI_SGE_FLAGS_CHAIN_ELEMENT
| mpt_addr_size();
250 pChain
->NextChainOffset
= next
;
251 pChain
->Address
= cpu_to_le32(dma_addr
);
253 } /* mptscsih_add_chain() */
255 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
257 * mptscsih_getFreeChainBuffer - Function to get a free chain
258 * from the MPT_SCSI_HOST FreeChainQ.
259 * @ioc: Pointer to MPT_ADAPTER structure
260 * @req_idx: Index of the SCSI IO request frame. (output)
262 * return SUCCESS or FAILED
265 mptscsih_getFreeChainBuffer(MPT_ADAPTER
*ioc
, int *retIndex
)
267 MPT_FRAME_HDR
*chainBuf
;
272 dsgprintk((MYIOC_s_INFO_FMT
"getFreeChainBuffer called\n",
274 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
275 if (!list_empty(&ioc
->FreeChainQ
)) {
278 chainBuf
= list_entry(ioc
->FreeChainQ
.next
, MPT_FRAME_HDR
,
279 u
.frame
.linkage
.list
);
280 list_del(&chainBuf
->u
.frame
.linkage
.list
);
281 offset
= (u8
*)chainBuf
- (u8
*)ioc
->ChainBuffer
;
282 chain_idx
= offset
/ ioc
->req_sz
;
284 dsgprintk((MYIOC_s_INFO_FMT
"getFreeChainBuffer (index %d), got buf=%p\n",
285 ioc
->name
, *retIndex
, chainBuf
));
288 chain_idx
= MPT_HOST_NO_CHAIN
;
289 dfailprintk((MYIOC_s_ERR_FMT
"getFreeChainBuffer failed\n",
292 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
294 *retIndex
= chain_idx
;
296 } /* mptscsih_getFreeChainBuffer() */
298 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
300 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
301 * SCSIIORequest_t Message Frame.
302 * @ioc: Pointer to MPT_ADAPTER structure
303 * @SCpnt: Pointer to scsi_cmnd structure
304 * @pReq: Pointer to SCSIIORequest_t structure
309 mptscsih_AddSGE(MPT_ADAPTER
*ioc
, struct scsi_cmnd
*SCpnt
,
310 SCSIIORequest_t
*pReq
, int req_idx
)
314 struct scatterlist
*sg
;
316 int sges_left
, sg_done
;
317 int chain_idx
= MPT_HOST_NO_CHAIN
;
319 int numSgeSlots
, numSgeThisFrame
;
320 u32 sgflags
, sgdir
, thisxfer
= 0;
321 int chain_dma_off
= 0;
327 sgdir
= le32_to_cpu(pReq
->Control
) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK
;
328 if (sgdir
== MPI_SCSIIO_CONTROL_WRITE
) {
329 sgdir
= MPT_TRANSFER_HOST_TO_IOC
;
331 sgdir
= MPT_TRANSFER_IOC_TO_HOST
;
334 psge
= (char *) &pReq
->SGL
;
335 frm_sz
= ioc
->req_sz
;
337 /* Map the data portion, if any.
338 * sges_left = 0 if no data transfer.
340 if ( (sges_left
= SCpnt
->use_sg
) ) {
341 sges_left
= pci_map_sg(ioc
->pcidev
,
342 (struct scatterlist
*) SCpnt
->request_buffer
,
344 SCpnt
->sc_data_direction
);
347 } else if (SCpnt
->request_bufflen
) {
348 SCpnt
->SCp
.dma_handle
= pci_map_single(ioc
->pcidev
,
349 SCpnt
->request_buffer
,
350 SCpnt
->request_bufflen
,
351 SCpnt
->sc_data_direction
);
352 dsgprintk((MYIOC_s_INFO_FMT
"SG: non-SG for %p, len=%d\n",
353 ioc
->name
, SCpnt
, SCpnt
->request_bufflen
));
354 mptscsih_add_sge((char *) &pReq
->SGL
,
355 0xD1000000|MPT_SGE_FLAGS_ADDRESSING
|sgdir
|SCpnt
->request_bufflen
,
356 SCpnt
->SCp
.dma_handle
);
361 /* Handle the SG case.
363 sg
= (struct scatterlist
*) SCpnt
->request_buffer
;
365 sgeOffset
= sizeof(SCSIIORequest_t
) - sizeof(SGE_IO_UNION
);
368 /* Prior to entering this loop - the following must be set
369 * current MF: sgeOffset (bytes)
370 * chainSge (Null if original MF is not a chain buffer)
371 * sg_done (num SGE done for this MF)
375 numSgeSlots
= ((frm_sz
- sgeOffset
) / (sizeof(u32
) + sizeof(dma_addr_t
)) );
376 numSgeThisFrame
= (sges_left
< numSgeSlots
) ? sges_left
: numSgeSlots
;
378 sgflags
= MPT_SGE_FLAGS_SIMPLE_ELEMENT
| MPT_SGE_FLAGS_ADDRESSING
| sgdir
;
380 /* Get first (num - 1) SG elements
381 * Skip any SG entries with a length of 0
382 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
384 for (ii
=0; ii
< (numSgeThisFrame
-1); ii
++) {
385 thisxfer
= sg_dma_len(sg
);
387 sg
++; /* Get next SG element from the OS */
392 v2
= sg_dma_address(sg
);
393 mptscsih_add_sge(psge
, sgflags
| thisxfer
, v2
);
395 sg
++; /* Get next SG element from the OS */
396 psge
+= (sizeof(u32
) + sizeof(dma_addr_t
));
397 sgeOffset
+= (sizeof(u32
) + sizeof(dma_addr_t
));
401 if (numSgeThisFrame
== sges_left
) {
402 /* Add last element, end of buffer and end of list flags.
404 sgflags
|= MPT_SGE_FLAGS_LAST_ELEMENT
|
405 MPT_SGE_FLAGS_END_OF_BUFFER
|
406 MPT_SGE_FLAGS_END_OF_LIST
;
408 /* Add last SGE and set termination flags.
409 * Note: Last SGE may have a length of 0 - which should be ok.
411 thisxfer
= sg_dma_len(sg
);
413 v2
= sg_dma_address(sg
);
414 mptscsih_add_sge(psge
, sgflags
| thisxfer
, v2
);
417 psge += (sizeof(u32) + sizeof(dma_addr_t));
419 sgeOffset
+= (sizeof(u32
) + sizeof(dma_addr_t
));
423 /* The current buffer is a chain buffer,
424 * but there is not another one.
425 * Update the chain element
426 * Offset and Length fields.
428 mptscsih_add_chain((char *)chainSge
, 0, sgeOffset
, ioc
->ChainBufferDMA
+ chain_dma_off
);
430 /* The current buffer is the original MF
431 * and there is no Chain buffer.
433 pReq
->ChainOffset
= 0;
434 RequestNB
= (((sgeOffset
- 1) >> ioc
->NBShiftFactor
) + 1) & 0x03;
435 dsgprintk((MYIOC_s_ERR_FMT
436 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc
->name
, RequestNB
, sgeOffset
));
437 ioc
->RequestNB
[req_idx
] = RequestNB
;
440 /* At least one chain buffer is needed.
441 * Complete the first MF
442 * - last SGE element, set the LastElement bit
443 * - set ChainOffset (words) for orig MF
444 * (OR finish previous MF chain buffer)
445 * - update MFStructPtr ChainIndex
446 * - Populate chain element
451 dsgprintk((MYIOC_s_INFO_FMT
"SG: Chain Required! sg done %d\n",
452 ioc
->name
, sg_done
));
454 /* Set LAST_ELEMENT flag for last non-chain element
455 * in the buffer. Since psge points at the NEXT
456 * SGE element, go back one SGE element, update the flags
457 * and reset the pointer. (Note: sgflags & thisxfer are already
461 u32
*ptmp
= (u32
*) (psge
- (sizeof(u32
) + sizeof(dma_addr_t
)));
462 sgflags
= le32_to_cpu(*ptmp
);
463 sgflags
|= MPT_SGE_FLAGS_LAST_ELEMENT
;
464 *ptmp
= cpu_to_le32(sgflags
);
468 /* The current buffer is a chain buffer.
469 * chainSge points to the previous Chain Element.
470 * Update its chain element Offset and Length (must
471 * include chain element size) fields.
472 * Old chain element is now complete.
474 u8 nextChain
= (u8
) (sgeOffset
>> 2);
475 sgeOffset
+= (sizeof(u32
) + sizeof(dma_addr_t
));
476 mptscsih_add_chain((char *)chainSge
, nextChain
, sgeOffset
, ioc
->ChainBufferDMA
+ chain_dma_off
);
478 /* The original MF buffer requires a chain buffer -
480 * Last element in this MF is a chain element.
482 pReq
->ChainOffset
= (u8
) (sgeOffset
>> 2);
483 RequestNB
= (((sgeOffset
- 1) >> ioc
->NBShiftFactor
) + 1) & 0x03;
484 dsgprintk((MYIOC_s_ERR_FMT
"Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc
->name
, RequestNB
, sgeOffset
));
485 ioc
->RequestNB
[req_idx
] = RequestNB
;
488 sges_left
-= sg_done
;
491 /* NOTE: psge points to the beginning of the chain element
492 * in current buffer. Get a chain buffer.
494 dsgprintk((MYIOC_s_INFO_FMT
495 "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n",
496 ioc
->name
, pReq
->CDB
[0], SCpnt
));
497 if ((mptscsih_getFreeChainBuffer(ioc
, &newIndex
)) == FAILED
)
500 /* Update the tracking arrays.
501 * If chainSge == NULL, update ReqToChain, else ChainToChain
504 ioc
->ChainToChain
[chain_idx
] = newIndex
;
506 ioc
->ReqToChain
[req_idx
] = newIndex
;
508 chain_idx
= newIndex
;
509 chain_dma_off
= ioc
->req_sz
* chain_idx
;
511 /* Populate the chainSGE for the current buffer.
512 * - Set chain buffer pointer to psge and fill
513 * out the Address and Flags fields.
515 chainSge
= (char *) psge
;
516 dsgprintk((KERN_INFO
" Current buff @ %p (index 0x%x)",
519 /* Start the SGE for the next buffer
521 psge
= (char *) (ioc
->ChainBuffer
+ chain_dma_off
);
525 dsgprintk((KERN_INFO
" Chain buff @ %p (index 0x%x)\n",
528 /* Start the SGE for the next buffer
535 } /* mptscsih_AddSGE() */
537 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
539 * mptscsih_io_done - Main SCSI IO callback routine registered to
540 * Fusion MPT (base) driver
541 * @ioc: Pointer to MPT_ADAPTER structure
542 * @mf: Pointer to original MPT request frame
543 * @r: Pointer to MPT reply frame (NULL if TurboReply)
545 * This routine is called from mpt.c::mpt_interrupt() at the completion
546 * of any SCSI IO request.
547 * This routine is registered with the Fusion MPT (base) driver at driver
548 * load/init time via the mpt_register() API call.
550 * Returns 1 indicating alloc'd request frame ptr should be freed.
553 mptscsih_io_done(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
, MPT_FRAME_HDR
*mr
)
555 struct scsi_cmnd
*sc
;
557 SCSIIORequest_t
*pScsiReq
;
558 SCSIIOReply_t
*pScsiReply
;
561 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
563 req_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
564 sc
= hd
->ScsiLookup
[req_idx
];
566 MPIHeader_t
*hdr
= (MPIHeader_t
*)mf
;
568 /* Remark: writeSDP1 will use the ScsiDoneCtx
569 * If a SCSI I/O cmd, device disabled by OS and
570 * completion done. Cannot touch sc struct. Just free mem.
572 if (hdr
->Function
== MPI_FUNCTION_SCSI_IO_REQUEST
)
573 printk(MYIOC_s_ERR_FMT
"NULL ScsiCmd ptr!\n",
576 mptscsih_freeChainBuffers(ioc
, req_idx
);
580 dmfprintk((MYIOC_s_INFO_FMT
581 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
582 ioc
->name
, mf
, mr
, sc
, 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 (pScsiReply
== NULL
) {
589 /* special context reply handling */
594 u8 scsi_state
, scsi_status
;
596 status
= le16_to_cpu(pScsiReply
->IOCStatus
) & MPI_IOCSTATUS_MASK
;
597 scsi_state
= pScsiReply
->SCSIState
;
598 scsi_status
= pScsiReply
->SCSIStatus
;
599 xfer_cnt
= le32_to_cpu(pScsiReply
->TransferCount
);
600 sc
->resid
= sc
->request_bufflen
- xfer_cnt
;
602 dreplyprintk((KERN_NOTICE
"Reply ha=%d id=%d lun=%d:\n"
603 "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
604 "resid=%d bufflen=%d xfer_cnt=%d\n",
605 ioc
->id
, pScsiReq
->TargetID
, pScsiReq
->LUN
[1],
606 status
, scsi_state
, scsi_status
, sc
->resid
,
607 sc
->request_bufflen
, xfer_cnt
));
609 if (scsi_state
& MPI_SCSI_STATE_AUTOSENSE_VALID
)
610 mptscsih_copy_sense_data(sc
, hd
, mf
, pScsiReply
);
613 * Look for + dump FCP ResponseInfo[]!
615 if (scsi_state
& MPI_SCSI_STATE_RESPONSE_INFO_VALID
) {
616 printk(KERN_NOTICE
" FCP_ResponseInfo=%08xh\n",
617 le32_to_cpu(pScsiReply
->ResponseInfo
));
621 case MPI_IOCSTATUS_BUSY
: /* 0x0002 */
623 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
624 * But not: DID_BUS_BUSY lest one risk
625 * killing interrupt handler:-(
627 sc
->result
= SAM_STAT_BUSY
;
630 case MPI_IOCSTATUS_SCSI_INVALID_BUS
: /* 0x0041 */
631 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID
: /* 0x0042 */
632 sc
->result
= DID_BAD_TARGET
<< 16;
635 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE
: /* 0x0043 */
636 /* Spoof to SCSI Selection Timeout! */
637 sc
->result
= DID_NO_CONNECT
<< 16;
639 if (hd
->sel_timeout
[pScsiReq
->TargetID
] < 0xFFFF)
640 hd
->sel_timeout
[pScsiReq
->TargetID
]++;
643 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED
: /* 0x0048 */
644 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED
: /* 0x004B */
645 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED
: /* 0x004C */
646 /* Linux handles an unsolicited DID_RESET better
647 * than an unsolicited DID_ABORT.
649 sc
->result
= DID_RESET
<< 16;
651 /* GEM Workaround. */
652 if (ioc
->bus_type
== SCSI
)
653 mptscsih_no_negotiate(hd
, sc
->device
->id
);
656 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH
: /* 0x0049 */
657 if ( xfer_cnt
>= sc
->underflow
) {
658 /* Sufficient data transfer occurred */
659 sc
->result
= (DID_OK
<< 16) | scsi_status
;
660 } else if ( xfer_cnt
== 0 ) {
661 /* A CRC Error causes this condition; retry */
662 sc
->result
= (DRIVER_SENSE
<< 24) | (DID_OK
<< 16) |
663 (CHECK_CONDITION
<< 1);
664 sc
->sense_buffer
[0] = 0x70;
665 sc
->sense_buffer
[2] = NO_SENSE
;
666 sc
->sense_buffer
[12] = 0;
667 sc
->sense_buffer
[13] = 0;
669 sc
->result
= DID_SOFT_ERROR
<< 16;
671 dreplyprintk((KERN_NOTICE
"RESIDUAL_MISMATCH: result=%x on id=%d\n", sc
->result
, sc
->target
));
674 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN
: /* 0x0045 */
676 * Do upfront check for valid SenseData and give it
679 sc
->result
= (DID_OK
<< 16) | scsi_status
;
680 if (scsi_state
& MPI_SCSI_STATE_AUTOSENSE_VALID
) {
681 /* Have already saved the status and sense data
685 if (xfer_cnt
< sc
->underflow
) {
686 sc
->result
= DID_SOFT_ERROR
<< 16;
688 if (scsi_state
& (MPI_SCSI_STATE_AUTOSENSE_FAILED
| MPI_SCSI_STATE_NO_SCSI_STATUS
)) {
691 sc
->result
= DID_SOFT_ERROR
<< 16;
693 else if (scsi_state
& MPI_SCSI_STATE_TERMINATED
) {
694 /* Not real sure here either... */
695 sc
->result
= DID_RESET
<< 16;
699 dreplyprintk((KERN_NOTICE
" sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
701 dreplyprintk((KERN_NOTICE
" ActBytesXferd=%02xh\n", xfer_cnt
));
704 if (scsi_status
== MPI_SCSI_STATUS_TASK_SET_FULL
)
705 mptscsih_report_queue_full(sc
, pScsiReply
, pScsiReq
);
709 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR
: /* 0x0040 */
710 case MPI_IOCSTATUS_SUCCESS
: /* 0x0000 */
711 scsi_status
= pScsiReply
->SCSIStatus
;
712 sc
->result
= (DID_OK
<< 16) | scsi_status
;
713 if (scsi_state
== 0) {
715 } else if (scsi_state
& MPI_SCSI_STATE_AUTOSENSE_VALID
) {
717 * If running against circa 200003dd 909 MPT f/w,
718 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
719 * (QUEUE_FULL) returned from device! --> get 0x0000?128
720 * and with SenseBytes set to 0.
722 if (pScsiReply
->SCSIStatus
== MPI_SCSI_STATUS_TASK_SET_FULL
)
723 mptscsih_report_queue_full(sc
, pScsiReply
, pScsiReq
);
726 else if (scsi_state
&
727 (MPI_SCSI_STATE_AUTOSENSE_FAILED
| MPI_SCSI_STATE_NO_SCSI_STATUS
)
732 sc
->result
= DID_SOFT_ERROR
<< 16;
734 else if (scsi_state
& MPI_SCSI_STATE_TERMINATED
) {
735 /* Not real sure here either... */
736 sc
->result
= DID_RESET
<< 16;
738 else if (scsi_state
& MPI_SCSI_STATE_QUEUE_TAG_REJECTED
) {
739 /* Device Inq. data indicates that it supports
740 * QTags, but rejects QTag messages.
741 * This command completed OK.
743 * Not real sure here either so do nothing... */
746 if (sc
->result
== MPI_SCSI_STATUS_TASK_SET_FULL
)
747 mptscsih_report_queue_full(sc
, pScsiReply
, pScsiReq
);
750 * Reservation Conflict, Busy,
751 * Command Terminated, CHECK
755 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR
: /* 0x0047 */
756 sc
->result
= DID_SOFT_ERROR
<< 16;
759 case MPI_IOCSTATUS_INVALID_FUNCTION
: /* 0x0001 */
760 case MPI_IOCSTATUS_INVALID_SGL
: /* 0x0003 */
761 case MPI_IOCSTATUS_INTERNAL_ERROR
: /* 0x0004 */
762 case MPI_IOCSTATUS_RESERVED
: /* 0x0005 */
763 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES
: /* 0x0006 */
764 case MPI_IOCSTATUS_INVALID_FIELD
: /* 0x0007 */
765 case MPI_IOCSTATUS_INVALID_STATE
: /* 0x0008 */
766 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN
: /* 0x0044 */
767 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR
: /* 0x0046 */
768 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED
: /* 0x004A */
773 sc
->result
= DID_SOFT_ERROR
<< 16;
776 } /* switch(status) */
778 dreplyprintk((KERN_NOTICE
" sc->result is %08xh\n", sc
->result
));
779 } /* end of address reply case */
781 /* Unmap the DMA buffers, if any. */
783 pci_unmap_sg(ioc
->pcidev
, (struct scatterlist
*) sc
->request_buffer
,
784 sc
->use_sg
, sc
->sc_data_direction
);
785 } else if (sc
->request_bufflen
) {
786 pci_unmap_single(ioc
->pcidev
, sc
->SCp
.dma_handle
,
787 sc
->request_bufflen
, sc
->sc_data_direction
);
790 hd
->ScsiLookup
[req_idx
] = NULL
;
792 sc
->scsi_done(sc
); /* Issue the command callback */
794 /* Free Chain buffers */
795 mptscsih_freeChainBuffers(ioc
, req_idx
);
801 * mptscsih_flush_running_cmds - For each command found, search
802 * Scsi_Host instance taskQ and reply to OS.
803 * Called only if recovering from a FW reload.
804 * @hd: Pointer to a SCSI HOST structure
808 * Must be called while new I/Os are being queued.
811 mptscsih_flush_running_cmds(MPT_SCSI_HOST
*hd
)
813 MPT_ADAPTER
*ioc
= hd
->ioc
;
814 struct scsi_cmnd
*SCpnt
;
817 int max
= ioc
->req_depth
;
819 dprintk((KERN_INFO MYNAM
": flush_ScsiLookup called\n"));
820 for (ii
= 0; ii
< max
; ii
++) {
821 if ((SCpnt
= hd
->ScsiLookup
[ii
]) != NULL
) {
826 /* Null ScsiLookup index
828 hd
->ScsiLookup
[ii
] = NULL
;
830 mf
= MPT_INDEX_2_MFPTR(ioc
, ii
);
831 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
834 /* Set status, free OS resources (SG DMA buffers)
836 * Free driver resources (chain, msg buffers)
839 pci_unmap_sg(ioc
->pcidev
,
840 (struct scatterlist
*) SCpnt
->request_buffer
,
842 SCpnt
->sc_data_direction
);
843 } else if (SCpnt
->request_bufflen
) {
844 pci_unmap_single(ioc
->pcidev
,
845 SCpnt
->SCp
.dma_handle
,
846 SCpnt
->request_bufflen
,
847 SCpnt
->sc_data_direction
);
849 SCpnt
->result
= DID_RESET
<< 16;
850 SCpnt
->host_scribble
= NULL
;
852 /* Free Chain buffers */
853 mptscsih_freeChainBuffers(ioc
, ii
);
855 /* Free Message frames */
856 mpt_free_msg_frame(ioc
, mf
);
858 SCpnt
->scsi_done(SCpnt
); /* Issue the command callback */
866 * mptscsih_search_running_cmds - Delete any commands associated
867 * with the specified target and lun. Function called only
868 * when a lun is disable by mid-layer.
869 * Do NOT access the referenced scsi_cmnd structure or
870 * members. Will cause either a paging or NULL ptr error.
871 * @hd: Pointer to a SCSI HOST structure
877 * Called from slave_destroy.
880 mptscsih_search_running_cmds(MPT_SCSI_HOST
*hd
, uint target
, uint lun
)
882 SCSIIORequest_t
*mf
= NULL
;
884 int max
= hd
->ioc
->req_depth
;
886 dsprintk((KERN_INFO MYNAM
": search_running target %d lun %d max %d\n",
889 for (ii
=0; ii
< max
; ii
++) {
890 if (hd
->ScsiLookup
[ii
] != NULL
) {
892 mf
= (SCSIIORequest_t
*)MPT_INDEX_2_MFPTR(hd
->ioc
, ii
);
894 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
895 hd
->ScsiLookup
[ii
], mf
, mf
->TargetID
, mf
->LUN
[1]));
897 if ((mf
->TargetID
!= ((u8
)target
)) || (mf
->LUN
[1] != ((u8
) lun
)))
902 hd
->ScsiLookup
[ii
] = NULL
;
903 mptscsih_freeChainBuffers(hd
->ioc
, ii
);
904 mpt_free_msg_frame(hd
->ioc
, (MPT_FRAME_HDR
*)mf
);
911 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
913 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
915 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
916 * from a SCSI target device.
917 * @sc: Pointer to scsi_cmnd structure
918 * @pScsiReply: Pointer to SCSIIOReply_t
919 * @pScsiReq: Pointer to original SCSI request
921 * This routine periodically reports QUEUE_FULL status returned from a
922 * SCSI target device. It reports this to the console via kernel
923 * printk() API call, not more than once every 10 seconds.
926 mptscsih_report_queue_full(struct scsi_cmnd
*sc
, SCSIIOReply_t
*pScsiReply
, SCSIIORequest_t
*pScsiReq
)
931 if (sc
->device
== NULL
)
933 if (sc
->device
->host
== NULL
)
935 if ((hd
= (MPT_SCSI_HOST
*)sc
->device
->host
->hostdata
) == NULL
)
938 if (time
- hd
->last_queue_full
> 10 * HZ
) {
939 dprintk((MYIOC_s_WARN_FMT
"Device (%d:%d:%d) reported QUEUE_FULL!\n",
940 hd
->ioc
->name
, 0, sc
->device
->id
, sc
->device
->lun
));
941 hd
->last_queue_full
= time
;
945 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
947 * mptscsih_remove - Removed scsi devices
948 * @pdev: Pointer to pci_dev structure
953 mptscsih_remove(struct pci_dev
*pdev
)
955 MPT_ADAPTER
*ioc
= pci_get_drvdata(pdev
);
956 struct Scsi_Host
*host
= ioc
->sh
;
965 scsi_remove_host(host
);
967 if((hd
= (MPT_SCSI_HOST
*)host
->hostdata
) == NULL
)
970 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
971 /* Check DV thread active */
973 spin_lock_irqsave(&dvtaskQ_lock
, flags
);
974 if (dvtaskQ_active
) {
975 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
976 while(dvtaskQ_active
&& --count
) {
977 set_current_state(TASK_INTERRUPTIBLE
);
981 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
984 printk(KERN_ERR MYNAM
": ERROR - DV thread still active!\n");
985 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
987 printk(KERN_ERR MYNAM
": DV thread orig %d, count %d\n", 10 * HZ
, count
);
991 mptscsih_shutdown(&pdev
->dev
);
995 if (hd
->ScsiLookup
!= NULL
) {
996 sz1
= hd
->ioc
->req_depth
* sizeof(void *);
997 kfree(hd
->ScsiLookup
);
998 hd
->ScsiLookup
= NULL
;
1002 * Free pointer array.
1007 dprintk((MYIOC_s_INFO_FMT
1008 "Free'd ScsiLookup (%d) memory\n",
1009 hd
->ioc
->name
, sz1
));
1011 kfree(hd
->info_kbuf
);
1013 /* NULL the Scsi_Host pointer
1017 scsi_host_put(host
);
1023 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1025 * mptscsih_shutdown - reboot notifier
1029 mptscsih_shutdown(struct device
* dev
)
1031 MPT_ADAPTER
*ioc
= pci_get_drvdata(to_pci_dev(dev
));
1032 struct Scsi_Host
*host
= ioc
->sh
;
1038 hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
1040 /* Flush the cache of this adapter
1043 mptscsih_synchronize_cache(hd
, 0);
1048 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1050 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1055 mptscsih_suspend(struct pci_dev
*pdev
, pm_message_t state
)
1057 mptscsih_shutdown(&pdev
->dev
);
1058 return mpt_suspend(pdev
,state
);
1061 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1063 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1068 mptscsih_resume(struct pci_dev
*pdev
)
1070 MPT_ADAPTER
*ioc
= pci_get_drvdata(pdev
);
1071 struct Scsi_Host
*host
= ioc
->sh
;
1079 hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
1083 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1085 unsigned long lflags
;
1086 spin_lock_irqsave(&dvtaskQ_lock
, lflags
);
1087 if (!dvtaskQ_active
) {
1089 spin_unlock_irqrestore(&dvtaskQ_lock
, lflags
);
1090 INIT_WORK(&dvTaskQ_task
,
1091 mptscsih_domainValidation
, (void *) hd
);
1092 schedule_work(&dvTaskQ_task
);
1094 spin_unlock_irqrestore(&dvtaskQ_lock
, lflags
);
1103 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1105 * mptscsih_info - Return information about MPT adapter
1106 * @SChost: Pointer to Scsi_Host structure
1108 * (linux scsi_host_template.info routine)
1110 * Returns pointer to buffer where information was written.
1113 mptscsih_info(struct Scsi_Host
*SChost
)
1118 h
= (MPT_SCSI_HOST
*)SChost
->hostdata
;
1121 if (h
->info_kbuf
== NULL
)
1122 if ((h
->info_kbuf
= kmalloc(0x1000 /* 4Kb */, GFP_KERNEL
)) == NULL
)
1123 return h
->info_kbuf
;
1124 h
->info_kbuf
[0] = '\0';
1126 mpt_print_ioc_summary(h
->ioc
, h
->info_kbuf
, &size
, 0, 0);
1127 h
->info_kbuf
[size
-1] = '\0';
1130 return h
->info_kbuf
;
1141 mptscsih_copy_mem_info(struct info_str
*info
, char *data
, int len
)
1143 if (info
->pos
+ len
> info
->length
)
1144 len
= info
->length
- info
->pos
;
1146 if (info
->pos
+ len
< info
->offset
) {
1151 if (info
->pos
< info
->offset
) {
1152 data
+= (info
->offset
- info
->pos
);
1153 len
-= (info
->offset
- info
->pos
);
1157 memcpy(info
->buffer
+ info
->pos
, data
, len
);
1163 mptscsih_copy_info(struct info_str
*info
, char *fmt
, ...)
1169 va_start(args
, fmt
);
1170 len
= vsprintf(buf
, fmt
, args
);
1173 mptscsih_copy_mem_info(info
, buf
, len
);
1178 mptscsih_host_info(MPT_ADAPTER
*ioc
, char *pbuf
, off_t offset
, int len
)
1180 struct info_str info
;
1184 info
.offset
= offset
;
1187 mptscsih_copy_info(&info
, "%s: %s, ", ioc
->name
, ioc
->prod_name
);
1188 mptscsih_copy_info(&info
, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING
, ioc
->facts
.FWVersion
.Word
);
1189 mptscsih_copy_info(&info
, "Ports=%d, ", ioc
->facts
.NumberOfPorts
);
1190 mptscsih_copy_info(&info
, "MaxQ=%d\n", ioc
->req_depth
);
1192 return ((info
.pos
> info
.offset
) ? info
.pos
- info
.offset
: 0);
1195 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1197 * mptscsih_proc_info - Return information about MPT adapter
1199 * (linux scsi_host_template.info routine)
1201 * buffer: if write, user data; if read, buffer for user
1202 * length: if write, return length;
1203 * offset: if write, 0; if read, the current offset into the buffer from
1204 * the previous read.
1205 * hostno: scsi host number
1206 * func: if write = 1; if read = 0
1209 mptscsih_proc_info(struct Scsi_Host
*host
, char *buffer
, char **start
, off_t offset
,
1210 int length
, int func
)
1212 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
1213 MPT_ADAPTER
*ioc
= hd
->ioc
;
1218 * write is not supported
1224 size
= mptscsih_host_info(ioc
, buffer
, offset
, length
);
1230 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1231 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1233 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1235 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1236 * @SCpnt: Pointer to scsi_cmnd structure
1237 * @done: Pointer SCSI mid-layer IO completion function
1239 * (linux scsi_host_template.queuecommand routine)
1240 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1241 * from a linux scsi_cmnd request and send it to the IOC.
1243 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1246 mptscsih_qcmd(struct scsi_cmnd
*SCpnt
, void (*done
)(struct scsi_cmnd
*))
1250 SCSIIORequest_t
*pScsiReq
;
1251 VirtDevice
*pTarget
;
1261 hd
= (MPT_SCSI_HOST
*) SCpnt
->device
->host
->hostdata
;
1262 target
= SCpnt
->device
->id
;
1263 lun
= SCpnt
->device
->lun
;
1264 SCpnt
->scsi_done
= done
;
1266 pTarget
= hd
->Targets
[target
];
1268 dmfprintk((MYIOC_s_INFO_FMT
"qcmd: SCpnt=%p, done()=%p\n",
1269 (hd
&& hd
->ioc
) ? hd
->ioc
->name
: "ioc?", SCpnt
, done
));
1271 if (hd
->resetPending
) {
1272 dtmprintk((MYIOC_s_WARN_FMT
"qcmd: SCpnt=%p timeout + 60HZ\n",
1273 (hd
&& hd
->ioc
) ? hd
->ioc
->name
: "ioc?", SCpnt
));
1274 return SCSI_MLQUEUE_HOST_BUSY
;
1278 * Put together a MPT SCSI request...
1280 if ((mf
= mpt_get_msg_frame(hd
->ioc
->DoneCtx
, hd
->ioc
)) == NULL
) {
1281 dprintk((MYIOC_s_WARN_FMT
"QueueCmd, no msg frames!!\n",
1283 return SCSI_MLQUEUE_HOST_BUSY
;
1286 pScsiReq
= (SCSIIORequest_t
*) mf
;
1288 my_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
1290 ADD_INDEX_LOG(my_idx
);
1292 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1293 * Seems we may receive a buffer (datalen>0) even when there
1294 * will be no data transfer! GRRRRR...
1296 if (SCpnt
->sc_data_direction
== DMA_FROM_DEVICE
) {
1297 datalen
= SCpnt
->request_bufflen
;
1298 scsidir
= MPI_SCSIIO_CONTROL_READ
; /* DATA IN (host<--ioc<--dev) */
1299 } else if (SCpnt
->sc_data_direction
== DMA_TO_DEVICE
) {
1300 datalen
= SCpnt
->request_bufflen
;
1301 scsidir
= MPI_SCSIIO_CONTROL_WRITE
; /* DATA OUT (host-->ioc-->dev) */
1304 scsidir
= MPI_SCSIIO_CONTROL_NODATATRANSFER
;
1307 /* Default to untagged. Once a target structure has been allocated,
1308 * use the Inquiry data to determine if device supports tagged.
1311 && (pTarget
->tflags
& MPT_TARGET_FLAGS_Q_YES
)
1312 && (SCpnt
->device
->tagged_supported
)) {
1313 scsictl
= scsidir
| MPI_SCSIIO_CONTROL_SIMPLEQ
;
1315 scsictl
= scsidir
| MPI_SCSIIO_CONTROL_UNTAGGED
;
1318 /* Use the above information to set up the message frame
1320 pScsiReq
->TargetID
= (u8
) target
;
1321 pScsiReq
->Bus
= (u8
) SCpnt
->device
->channel
;
1322 pScsiReq
->ChainOffset
= 0;
1323 pScsiReq
->Function
= MPI_FUNCTION_SCSI_IO_REQUEST
;
1324 pScsiReq
->CDBLength
= SCpnt
->cmd_len
;
1325 pScsiReq
->SenseBufferLength
= MPT_SENSE_BUFFER_SIZE
;
1326 pScsiReq
->Reserved
= 0;
1327 pScsiReq
->MsgFlags
= mpt_msg_flags();
1328 pScsiReq
->LUN
[0] = 0;
1329 pScsiReq
->LUN
[1] = lun
;
1330 pScsiReq
->LUN
[2] = 0;
1331 pScsiReq
->LUN
[3] = 0;
1332 pScsiReq
->LUN
[4] = 0;
1333 pScsiReq
->LUN
[5] = 0;
1334 pScsiReq
->LUN
[6] = 0;
1335 pScsiReq
->LUN
[7] = 0;
1336 pScsiReq
->Control
= cpu_to_le32(scsictl
);
1339 * Write SCSI CDB into the message
1341 cmd_len
= SCpnt
->cmd_len
;
1342 for (ii
=0; ii
< cmd_len
; ii
++)
1343 pScsiReq
->CDB
[ii
] = SCpnt
->cmnd
[ii
];
1345 for (ii
=cmd_len
; ii
< 16; ii
++)
1346 pScsiReq
->CDB
[ii
] = 0;
1349 pScsiReq
->DataLength
= cpu_to_le32(datalen
);
1351 /* SenseBuffer low address */
1352 pScsiReq
->SenseBufferLowAddr
= cpu_to_le32(hd
->ioc
->sense_buf_low_dma
1353 + (my_idx
* MPT_SENSE_BUFFER_ALLOC
));
1355 /* Now add the SG list
1356 * Always have a SGE even if null length.
1359 /* Add a NULL SGE */
1360 mptscsih_add_sge((char *)&pScsiReq
->SGL
, MPT_SGE_FLAGS_SSIMPLE_READ
| 0,
1363 /* Add a 32 or 64 bit SGE */
1364 if (mptscsih_AddSGE(hd
->ioc
, SCpnt
, pScsiReq
, my_idx
) != SUCCESS
)
1368 hd
->ScsiLookup
[my_idx
] = SCpnt
;
1369 SCpnt
->host_scribble
= NULL
;
1371 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1372 if (hd
->ioc
->bus_type
== SCSI
) {
1373 int dvStatus
= hd
->ioc
->spi_data
.dvStatus
[target
];
1376 if (dvStatus
|| hd
->ioc
->spi_data
.forceDv
) {
1378 if ((dvStatus
& MPT_SCSICFG_NEED_DV
) ||
1379 (hd
->ioc
->spi_data
.forceDv
& MPT_SCSICFG_NEED_DV
)) {
1380 unsigned long lflags
;
1381 /* Schedule DV if necessary */
1382 spin_lock_irqsave(&dvtaskQ_lock
, lflags
);
1383 if (!dvtaskQ_active
) {
1385 spin_unlock_irqrestore(&dvtaskQ_lock
, lflags
);
1386 INIT_WORK(&dvTaskQ_task
, mptscsih_domainValidation
, (void *) hd
);
1388 schedule_work(&dvTaskQ_task
);
1390 spin_unlock_irqrestore(&dvtaskQ_lock
, lflags
);
1392 hd
->ioc
->spi_data
.forceDv
&= ~MPT_SCSICFG_NEED_DV
;
1395 /* Trying to do DV to this target, extend timeout.
1396 * Wait to issue until flag is clear
1398 if (dvStatus
& MPT_SCSICFG_DV_PENDING
) {
1399 mod_timer(&SCpnt
->eh_timeout
, jiffies
+ 40 * HZ
);
1403 /* Set the DV flags.
1405 if (dvStatus
& MPT_SCSICFG_DV_NOT_DONE
)
1406 mptscsih_set_dvflags(hd
, pScsiReq
);
1414 mpt_put_msg_frame(hd
->ioc
->DoneCtx
, hd
->ioc
, mf
);
1415 dmfprintk((MYIOC_s_INFO_FMT
"Issued SCSI cmd (%p) mf=%p idx=%d\n",
1416 hd
->ioc
->name
, SCpnt
, mf
, my_idx
));
1417 DBG_DUMP_REQUEST_FRAME(mf
)
1421 mptscsih_freeChainBuffers(hd
->ioc
, my_idx
);
1422 mpt_free_msg_frame(hd
->ioc
, mf
);
1423 return SCSI_MLQUEUE_HOST_BUSY
;
1426 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1428 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1429 * with a SCSI IO request
1430 * @hd: Pointer to the MPT_SCSI_HOST instance
1431 * @req_idx: Index of the SCSI IO request frame.
1433 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1437 mptscsih_freeChainBuffers(MPT_ADAPTER
*ioc
, int req_idx
)
1439 MPT_FRAME_HDR
*chain
;
1440 unsigned long flags
;
1444 /* Get the first chain index and reset
1447 chain_idx
= ioc
->ReqToChain
[req_idx
];
1448 ioc
->ReqToChain
[req_idx
] = MPT_HOST_NO_CHAIN
;
1450 while (chain_idx
!= MPT_HOST_NO_CHAIN
) {
1452 /* Save the next chain buffer index */
1453 next
= ioc
->ChainToChain
[chain_idx
];
1455 /* Free this chain buffer and reset
1458 ioc
->ChainToChain
[chain_idx
] = MPT_HOST_NO_CHAIN
;
1460 chain
= (MPT_FRAME_HDR
*) (ioc
->ChainBuffer
1461 + (chain_idx
* ioc
->req_sz
));
1463 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
1464 list_add_tail(&chain
->u
.frame
.linkage
.list
, &ioc
->FreeChainQ
);
1465 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
1467 dmfprintk((MYIOC_s_INFO_FMT
"FreeChainBuffers (index %d)\n",
1468 ioc
->name
, chain_idx
));
1476 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1481 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1483 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1484 * Fall through to mpt_HardResetHandler if: not operational, too many
1485 * failed TM requests or handshake failure.
1487 * @ioc: Pointer to MPT_ADAPTER structure
1488 * @type: Task Management type
1489 * @target: Logical Target ID for reset (if appropriate)
1490 * @lun: Logical Unit for reset (if appropriate)
1491 * @ctx2abort: Context for the task to be aborted (if appropriate)
1493 * Remark: Currently invoked from a non-interrupt thread (_bh).
1495 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1498 * Returns 0 for SUCCESS or -1 if FAILED.
1501 mptscsih_TMHandler(MPT_SCSI_HOST
*hd
, u8 type
, u8 channel
, u8 target
, u8 lun
, int ctx2abort
, ulong timeout
)
1507 unsigned long flags
;
1509 /* If FW is being reloaded currently, return success to
1510 * the calling function.
1517 printk(KERN_ERR MYNAM
" TMHandler" " NULL ioc!\n");
1520 dtmprintk((MYIOC_s_INFO_FMT
"TMHandler Entered!\n", ioc
->name
));
1522 // SJR - CHECKME - Can we avoid this here?
1523 // (mpt_HardResetHandler has this check...)
1524 spin_lock_irqsave(&ioc
->diagLock
, flags
);
1525 if ((ioc
->diagPending
) || (ioc
->alt_ioc
&& ioc
->alt_ioc
->diagPending
)) {
1526 spin_unlock_irqrestore(&ioc
->diagLock
, flags
);
1529 spin_unlock_irqrestore(&ioc
->diagLock
, flags
);
1531 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1532 * If we time out and not bus reset, then we return a FAILED status to the caller.
1533 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1534 * successful. Otherwise, reload the FW.
1536 if (mptscsih_tm_pending_wait(hd
) == FAILED
) {
1537 if (type
== MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK
) {
1538 dtmprintk((KERN_WARNING MYNAM
": %s: TMHandler abort: "
1539 "Timed out waiting for last TM (%d) to complete! \n",
1540 hd
->ioc
->name
, hd
->tmPending
));
1542 } else if (type
== MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET
) {
1543 dtmprintk((KERN_WARNING MYNAM
": %s: TMHandler target reset: "
1544 "Timed out waiting for last TM (%d) to complete! \n",
1545 hd
->ioc
->name
, hd
->tmPending
));
1547 } else if (type
== MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
) {
1548 dtmprintk((KERN_WARNING MYNAM
": %s: TMHandler bus reset: "
1549 "Timed out waiting for last TM (%d) to complete! \n",
1550 hd
->ioc
->name
, hd
->tmPending
));
1551 if (hd
->tmPending
& (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
))
1557 spin_lock_irqsave(&hd
->ioc
->FreeQlock
, flags
);
1558 hd
->tmPending
|= (1 << type
);
1559 spin_unlock_irqrestore(&hd
->ioc
->FreeQlock
, flags
);
1564 ioc_raw_state
= mpt_GetIocState(hd
->ioc
, 0);
1566 #ifdef MPT_DEBUG_RESET
1567 if ((ioc_raw_state
& MPI_IOC_STATE_MASK
) != MPI_IOC_STATE_OPERATIONAL
) {
1568 printk(MYIOC_s_WARN_FMT
1569 "TM Handler: IOC Not operational(0x%x)!\n",
1570 hd
->ioc
->name
, ioc_raw_state
);
1574 if (doTask
&& ((ioc_raw_state
& MPI_IOC_STATE_MASK
) == MPI_IOC_STATE_OPERATIONAL
)
1575 && !(ioc_raw_state
& MPI_DOORBELL_ACTIVE
)) {
1577 /* Isse the Task Mgmt request.
1579 if (hd
->hard_resets
< -1)
1581 rc
= mptscsih_IssueTaskMgmt(hd
, type
, channel
, target
, lun
, ctx2abort
, timeout
);
1583 printk(MYIOC_s_INFO_FMT
"Issue of TaskMgmt failed!\n", hd
->ioc
->name
);
1585 dtmprintk((MYIOC_s_INFO_FMT
"Issue of TaskMgmt Successful!\n", hd
->ioc
->name
));
1589 /* Only fall through to the HRH if this is a bus reset
1591 if ((type
== MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
) && (rc
||
1592 ioc
->reload_fw
|| (ioc
->alt_ioc
&& ioc
->alt_ioc
->reload_fw
))) {
1593 dtmprintk((MYIOC_s_INFO_FMT
"Calling HardReset! \n",
1595 rc
= mpt_HardResetHandler(hd
->ioc
, CAN_SLEEP
);
1598 dtmprintk((MYIOC_s_INFO_FMT
"TMHandler rc = %d!\n", hd
->ioc
->name
, rc
));
1604 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1606 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1607 * @hd: Pointer to MPT_SCSI_HOST structure
1608 * @type: Task Management type
1609 * @target: Logical Target ID for reset (if appropriate)
1610 * @lun: Logical Unit for reset (if appropriate)
1611 * @ctx2abort: Context for the task to be aborted (if appropriate)
1613 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1614 * or a non-interrupt thread. In the former, must not call schedule().
1616 * Not all fields are meaningfull for all task types.
1618 * Returns 0 for SUCCESS, -999 for "no msg frames",
1619 * else other non-zero value returned.
1622 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST
*hd
, u8 type
, u8 channel
, u8 target
, u8 lun
, int ctx2abort
, ulong timeout
)
1625 SCSITaskMgmt_t
*pScsiTm
;
1629 /* Return Fail to calling function if no message frames available.
1631 if ((mf
= mpt_get_msg_frame(hd
->ioc
->TaskCtx
, hd
->ioc
)) == NULL
) {
1632 dfailprintk((MYIOC_s_ERR_FMT
"IssueTaskMgmt, no msg frames!!\n",
1637 dtmprintk((MYIOC_s_INFO_FMT
"IssueTaskMgmt request @ %p\n",
1638 hd
->ioc
->name
, mf
));
1640 /* Format the Request
1642 pScsiTm
= (SCSITaskMgmt_t
*) mf
;
1643 pScsiTm
->TargetID
= target
;
1644 pScsiTm
->Bus
= channel
;
1645 pScsiTm
->ChainOffset
= 0;
1646 pScsiTm
->Function
= MPI_FUNCTION_SCSI_TASK_MGMT
;
1648 pScsiTm
->Reserved
= 0;
1649 pScsiTm
->TaskType
= type
;
1650 pScsiTm
->Reserved1
= 0;
1651 pScsiTm
->MsgFlags
= (type
== MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
)
1652 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION
: 0;
1654 for (ii
= 0; ii
< 8; ii
++) {
1655 pScsiTm
->LUN
[ii
] = 0;
1657 pScsiTm
->LUN
[1] = lun
;
1659 for (ii
=0; ii
< 7; ii
++)
1660 pScsiTm
->Reserved2
[ii
] = 0;
1662 pScsiTm
->TaskMsgContext
= ctx2abort
;
1664 dtmprintk((MYIOC_s_INFO_FMT
1665 "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1666 hd
->ioc
->name
, ctx2abort
, type
));
1668 DBG_DUMP_TM_REQUEST_FRAME((u32
*)pScsiTm
);
1670 if ((retval
= mpt_send_handshake_request(hd
->ioc
->TaskCtx
, hd
->ioc
,
1671 sizeof(SCSITaskMgmt_t
), (u32
*)pScsiTm
,
1673 dfailprintk((MYIOC_s_ERR_FMT
"_send_handshake FAILED!"
1674 " (hd %p, ioc %p, mf %p) \n", hd
->ioc
->name
, hd
,
1676 mpt_free_msg_frame(hd
->ioc
, mf
);
1680 if(mptscsih_tm_wait_for_completion(hd
, timeout
) == FAILED
) {
1681 dfailprintk((MYIOC_s_ERR_FMT
"_wait_for_completion FAILED!"
1682 " (hd %p, ioc %p, mf %p) \n", hd
->ioc
->name
, hd
,
1684 mpt_free_msg_frame(hd
->ioc
, mf
);
1685 dtmprintk((MYIOC_s_INFO_FMT
"Calling HardReset! \n",
1687 retval
= mpt_HardResetHandler(hd
->ioc
, CAN_SLEEP
);
1693 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1695 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1696 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1698 * (linux scsi_host_template.eh_abort_handler routine)
1700 * Returns SUCCESS or FAILED.
1703 mptscsih_abort(struct scsi_cmnd
* SCpnt
)
1711 /* If we can't locate our host adapter structure, return FAILED status.
1713 if ((hd
= (MPT_SCSI_HOST
*) SCpnt
->device
->host
->hostdata
) == NULL
) {
1714 SCpnt
->result
= DID_RESET
<< 16;
1715 SCpnt
->scsi_done(SCpnt
);
1716 dfailprintk((KERN_WARNING MYNAM
": mptscsih_abort: "
1717 "Can't locate host! (sc=%p)\n",
1723 if (hd
->resetPending
)
1726 printk(KERN_WARNING MYNAM
": %s: >> Attempting task abort! (sc=%p)\n",
1727 hd
->ioc
->name
, SCpnt
);
1729 if (hd
->timeouts
< -1)
1732 /* Find this command
1734 if ((scpnt_idx
= SCPNT_TO_LOOKUP_IDX(SCpnt
)) < 0) {
1735 /* Cmd not found in ScsiLookup.
1738 SCpnt
->result
= DID_RESET
<< 16;
1739 dtmprintk((KERN_WARNING MYNAM
": %s: mptscsih_abort: "
1740 "Command not in the active list! (sc=%p)\n",
1741 hd
->ioc
->name
, SCpnt
));
1745 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1746 * (the IO to be ABORT'd)
1748 * NOTE: Since we do not byteswap MsgContext, we do not
1749 * swap it here either. It is an opaque cookie to
1750 * the controller, so it does not matter. -DaveM
1752 mf
= MPT_INDEX_2_MFPTR(hd
->ioc
, scpnt_idx
);
1753 ctx2abort
= mf
->u
.frame
.hwhdr
.msgctxu
.MsgContext
;
1755 hd
->abortSCpnt
= SCpnt
;
1757 if (mptscsih_TMHandler(hd
, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK
,
1758 SCpnt
->device
->channel
, SCpnt
->device
->id
, SCpnt
->device
->lun
,
1759 ctx2abort
, 2 /* 2 second timeout */)
1762 /* The TM request failed and the subsequent FW-reload failed!
1765 printk(MYIOC_s_WARN_FMT
"Error issuing abort task! (sc=%p)\n",
1766 hd
->ioc
->name
, SCpnt
);
1768 /* We must clear our pending flag before clearing our state.
1771 hd
->tmState
= TM_STATE_NONE
;
1773 /* Unmap the DMA buffers, if any. */
1774 if (SCpnt
->use_sg
) {
1775 pci_unmap_sg(ioc
->pcidev
, (struct scatterlist
*) SCpnt
->request_buffer
,
1776 SCpnt
->use_sg
, SCpnt
->sc_data_direction
);
1777 } else if (SCpnt
->request_bufflen
) {
1778 pci_unmap_single(ioc
->pcidev
, SCpnt
->SCp
.dma_handle
,
1779 SCpnt
->request_bufflen
, SCpnt
->sc_data_direction
);
1781 hd
->ScsiLookup
[scpnt_idx
] = NULL
;
1782 SCpnt
->result
= DID_RESET
<< 16;
1783 SCpnt
->scsi_done(SCpnt
); /* Issue the command callback */
1784 mptscsih_freeChainBuffers(ioc
, scpnt_idx
);
1785 mpt_free_msg_frame(ioc
, mf
);
1791 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1793 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1794 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1796 * (linux scsi_host_template.eh_dev_reset_handler routine)
1798 * Returns SUCCESS or FAILED.
1801 mptscsih_dev_reset(struct scsi_cmnd
* SCpnt
)
1804 spinlock_t
*host_lock
= SCpnt
->device
->host
->host_lock
;
1806 /* If we can't locate our host adapter structure, return FAILED status.
1808 if ((hd
= (MPT_SCSI_HOST
*) SCpnt
->device
->host
->hostdata
) == NULL
){
1809 dtmprintk((KERN_WARNING MYNAM
": mptscsih_dev_reset: "
1810 "Can't locate host! (sc=%p)\n",
1815 if (hd
->resetPending
)
1818 printk(KERN_WARNING MYNAM
": %s: >> Attempting target reset! (sc=%p)\n",
1819 hd
->ioc
->name
, SCpnt
);
1821 spin_unlock_irq(host_lock
);
1822 if (mptscsih_TMHandler(hd
, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET
,
1823 SCpnt
->device
->channel
, SCpnt
->device
->id
,
1824 0, 0, 5 /* 5 second timeout */)
1826 /* The TM request failed and the subsequent FW-reload failed!
1829 printk(MYIOC_s_WARN_FMT
"Error processing TaskMgmt request (sc=%p)\n",
1830 hd
->ioc
->name
, SCpnt
);
1832 hd
->tmState
= TM_STATE_NONE
;
1833 spin_lock_irq(host_lock
);
1836 spin_lock_irq(host_lock
);
1841 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1843 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1844 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1846 * (linux scsi_host_template.eh_bus_reset_handler routine)
1848 * Returns SUCCESS or FAILED.
1851 mptscsih_bus_reset(struct scsi_cmnd
* SCpnt
)
1854 spinlock_t
*host_lock
= SCpnt
->device
->host
->host_lock
;
1856 /* If we can't locate our host adapter structure, return FAILED status.
1858 if ((hd
= (MPT_SCSI_HOST
*) SCpnt
->device
->host
->hostdata
) == NULL
){
1859 dtmprintk((KERN_WARNING MYNAM
": mptscsih_bus_reset: "
1860 "Can't locate host! (sc=%p)\n",
1865 printk(KERN_WARNING MYNAM
": %s: >> Attempting bus reset! (sc=%p)\n",
1866 hd
->ioc
->name
, SCpnt
);
1868 if (hd
->timeouts
< -1)
1871 /* We are now ready to execute the task management request. */
1872 spin_unlock_irq(host_lock
);
1873 if (mptscsih_TMHandler(hd
, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
,
1874 SCpnt
->device
->channel
, 0, 0, 0, 5 /* 5 second timeout */)
1877 /* The TM request failed and the subsequent FW-reload failed!
1880 printk(MYIOC_s_WARN_FMT
1881 "Error processing TaskMgmt request (sc=%p)\n",
1882 hd
->ioc
->name
, SCpnt
);
1884 hd
->tmState
= TM_STATE_NONE
;
1885 spin_lock_irq(host_lock
);
1888 spin_lock_irq(host_lock
);
1892 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1894 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
1896 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1898 * (linux scsi_host_template.eh_host_reset_handler routine)
1900 * Returns SUCCESS or FAILED.
1903 mptscsih_host_reset(struct scsi_cmnd
*SCpnt
)
1906 int status
= SUCCESS
;
1907 spinlock_t
*host_lock
= SCpnt
->device
->host
->host_lock
;
1909 /* If we can't locate the host to reset, then we failed. */
1910 if ((hd
= (MPT_SCSI_HOST
*) SCpnt
->device
->host
->hostdata
) == NULL
){
1911 dtmprintk( ( KERN_WARNING MYNAM
": mptscsih_host_reset: "
1912 "Can't locate host! (sc=%p)\n",
1917 printk(KERN_WARNING MYNAM
": %s: >> Attempting host reset! (sc=%p)\n",
1918 hd
->ioc
->name
, SCpnt
);
1920 /* If our attempts to reset the host failed, then return a failed
1921 * status. The host will be taken off line by the SCSI mid-layer.
1923 spin_unlock_irq(host_lock
);
1924 if (mpt_HardResetHandler(hd
->ioc
, CAN_SLEEP
) < 0){
1927 /* Make sure TM pending is cleared and TM state is set to
1931 hd
->tmState
= TM_STATE_NONE
;
1933 spin_lock_irq(host_lock
);
1936 dtmprintk( ( KERN_WARNING MYNAM
": mptscsih_host_reset: "
1938 (status
== SUCCESS
) ? "SUCCESS" : "FAILED" ) );
1943 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1945 * mptscsih_tm_pending_wait - wait for pending task management request to
1947 * @hd: Pointer to MPT host structure.
1949 * Returns {SUCCESS,FAILED}.
1952 mptscsih_tm_pending_wait(MPT_SCSI_HOST
* hd
)
1954 unsigned long flags
;
1955 int loop_count
= 4 * 10; /* Wait 10 seconds */
1956 int status
= FAILED
;
1959 spin_lock_irqsave(&hd
->ioc
->FreeQlock
, flags
);
1960 if (hd
->tmState
== TM_STATE_NONE
) {
1961 hd
->tmState
= TM_STATE_IN_PROGRESS
;
1964 spin_unlock_irqrestore(&hd
->ioc
->FreeQlock
, flags
);
1967 spin_unlock_irqrestore(&hd
->ioc
->FreeQlock
, flags
);
1969 } while (--loop_count
);
1974 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1976 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1977 * @hd: Pointer to MPT host structure.
1979 * Returns {SUCCESS,FAILED}.
1982 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST
* hd
, ulong timeout
)
1984 unsigned long flags
;
1985 int loop_count
= 4 * timeout
;
1986 int status
= FAILED
;
1989 spin_lock_irqsave(&hd
->ioc
->FreeQlock
, flags
);
1990 if(hd
->tmPending
== 0) {
1992 spin_unlock_irqrestore(&hd
->ioc
->FreeQlock
, flags
);
1995 spin_unlock_irqrestore(&hd
->ioc
->FreeQlock
, flags
);
1996 msleep_interruptible(250);
1997 } while (--loop_count
);
2002 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2004 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2005 * @ioc: Pointer to MPT_ADAPTER structure
2006 * @mf: Pointer to SCSI task mgmt request frame
2007 * @mr: Pointer to SCSI task mgmt reply frame
2009 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2010 * of any SCSI task management request.
2011 * This routine is registered with the MPT (base) driver at driver
2012 * load/init time via the mpt_register() API call.
2014 * Returns 1 indicating alloc'd request frame ptr should be freed.
2017 mptscsih_taskmgmt_complete(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
, MPT_FRAME_HDR
*mr
)
2019 SCSITaskMgmtReply_t
*pScsiTmReply
;
2020 SCSITaskMgmt_t
*pScsiTmReq
;
2022 unsigned long flags
;
2026 dtmprintk((MYIOC_s_WARN_FMT
"TaskMgmt completed (mf=%p,mr=%p)\n",
2027 ioc
->name
, mf
, mr
));
2029 /* Depending on the thread, a timer is activated for
2030 * the TM request. Delete this timer on completion of TM.
2031 * Decrement count of outstanding TM requests.
2033 hd
= (MPT_SCSI_HOST
*)ioc
->sh
->hostdata
;
2035 dtmprintk((MYIOC_s_WARN_FMT
"TaskMgmt Complete: NULL Scsi Host Ptr\n",
2041 dtmprintk((MYIOC_s_WARN_FMT
"ERROR! TaskMgmt Reply: NULL Request %p\n",
2045 pScsiTmReply
= (SCSITaskMgmtReply_t
*)mr
;
2046 pScsiTmReq
= (SCSITaskMgmt_t
*)mf
;
2048 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2049 tmType
= pScsiTmReq
->TaskType
;
2051 dtmprintk((MYIOC_s_WARN_FMT
" TaskType = %d, TerminationCount=%d\n",
2052 ioc
->name
, tmType
, le32_to_cpu(pScsiTmReply
->TerminationCount
)));
2053 DBG_DUMP_TM_REPLY_FRAME((u32
*)pScsiTmReply
);
2055 iocstatus
= le16_to_cpu(pScsiTmReply
->IOCStatus
) & MPI_IOCSTATUS_MASK
;
2056 dtmprintk((MYIOC_s_WARN_FMT
" SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2057 ioc
->name
, tmType
, iocstatus
, le32_to_cpu(pScsiTmReply
->IOCLogInfo
)));
2058 /* Error? (anything non-zero?) */
2061 /* clear flags and continue.
2063 if (tmType
== MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK
)
2064 hd
->abortSCpnt
= NULL
;
2066 /* If an internal command is present
2067 * or the TM failed - reload the FW.
2068 * FC FW may respond FAILED to an ABORT
2070 if (tmType
== MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
) {
2072 (iocstatus
== MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED
)) {
2073 if (mpt_HardResetHandler(ioc
, NO_SLEEP
) < 0) {
2074 printk((KERN_WARNING
2075 " Firmware Reload FAILED!!\n"));
2080 dtmprintk((MYIOC_s_WARN_FMT
" TaskMgmt SUCCESS\n", ioc
->name
));
2082 hd
->abortSCpnt
= NULL
;
2087 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
2089 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
2090 hd
->tmState
= TM_STATE_NONE
;
2095 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2097 * This is anyones guess quite frankly.
2100 mptscsih_bios_param(struct scsi_device
* sdev
, struct block_device
*bdev
,
2101 sector_t capacity
, int geom
[])
2111 dummy
= heads
* sectors
;
2112 cylinders
= capacity
;
2113 sector_div(cylinders
,dummy
);
2116 * Handle extended translation size for logical drives
2119 if ((ulong
)capacity
>= 0x200000) {
2122 dummy
= heads
* sectors
;
2123 cylinders
= capacity
;
2124 sector_div(cylinders
,dummy
);
2130 geom
[2] = cylinders
;
2132 dprintk((KERN_NOTICE
2133 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2134 sdev
->id
, sdev
->lun
,sdev
->channel
,(int)cylinders
,heads
,sectors
));
2139 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2141 * OS entry point to allow host driver to alloc memory
2142 * for each scsi device. Called once per device the bus scan.
2143 * Return non-zero if allocation fails.
2144 * Init memory once per id (not LUN).
2147 mptscsih_slave_alloc(struct scsi_device
*device
)
2149 struct Scsi_Host
*host
= device
->host
;
2150 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
2152 uint target
= device
->id
;
2157 if ((vdev
= hd
->Targets
[target
]) != NULL
)
2160 vdev
= kmalloc(sizeof(VirtDevice
), GFP_KERNEL
);
2162 printk(MYIOC_s_ERR_FMT
"slave_alloc kmalloc(%zd) FAILED!\n",
2163 hd
->ioc
->name
, sizeof(VirtDevice
));
2167 memset(vdev
, 0, sizeof(VirtDevice
));
2168 vdev
->tflags
= MPT_TARGET_FLAGS_Q_YES
;
2169 vdev
->ioc_id
= hd
->ioc
->id
;
2170 vdev
->target_id
= device
->id
;
2171 vdev
->bus_id
= device
->channel
;
2172 vdev
->raidVolume
= 0;
2173 hd
->Targets
[device
->id
] = vdev
;
2174 if (hd
->ioc
->bus_type
== SCSI
) {
2175 if (hd
->ioc
->spi_data
.isRaid
& (1 << device
->id
)) {
2176 vdev
->raidVolume
= 1;
2177 ddvtprintk((KERN_INFO
2178 "RAID Volume @ id %d\n", device
->id
));
2181 vdev
->tflags
|= MPT_TARGET_FLAGS_VALID_INQUIRY
;
2190 mptscsih_is_raid_volume(MPT_SCSI_HOST
*hd
, uint id
)
2194 if (!hd
->ioc
->spi_data
.isRaid
|| !hd
->ioc
->spi_data
.pIocPg3
)
2197 for (i
= 0; i
< hd
->ioc
->spi_data
.pIocPg3
->NumPhysDisks
; i
++) {
2198 if (id
== hd
->ioc
->spi_data
.pIocPg3
->PhysDisk
[i
].PhysDiskID
)
2206 * OS entry point to allow for host driver to free allocated memory
2207 * Called if no device present or device being unloaded
2210 mptscsih_slave_destroy(struct scsi_device
*device
)
2212 struct Scsi_Host
*host
= device
->host
;
2213 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
2215 uint target
= device
->id
;
2216 uint lun
= device
->lun
;
2221 mptscsih_search_running_cmds(hd
, target
, lun
);
2223 vdev
= hd
->Targets
[target
];
2224 vdev
->luns
[0] &= ~(1 << lun
);
2225 if (--vdev
->num_luns
)
2228 kfree(hd
->Targets
[target
]);
2229 hd
->Targets
[target
] = NULL
;
2231 if (hd
->ioc
->bus_type
== SCSI
) {
2232 if (mptscsih_is_raid_volume(hd
, target
)) {
2233 hd
->ioc
->spi_data
.forceDv
|= MPT_SCSICFG_RELOAD_IOC_PG3
;
2235 hd
->ioc
->spi_data
.dvStatus
[target
] =
2236 MPT_SCSICFG_NEGOTIATE
;
2238 if (!hd
->negoNvram
) {
2239 hd
->ioc
->spi_data
.dvStatus
[target
] |=
2240 MPT_SCSICFG_DV_NOT_DONE
;
2247 mptscsih_set_queue_depth(struct scsi_device
*device
, MPT_SCSI_HOST
*hd
,
2248 VirtDevice
*pTarget
, int qdepth
)
2253 if (hd
->ioc
->bus_type
== SCSI
) {
2254 if (pTarget
->tflags
& MPT_TARGET_FLAGS_VALID_INQUIRY
) {
2255 if (!(pTarget
->tflags
& MPT_TARGET_FLAGS_Q_YES
))
2257 else if (((pTarget
->inq_data
[0] & 0x1f) == 0x00) &&
2258 (pTarget
->minSyncFactor
<= MPT_ULTRA160
))
2259 max_depth
= MPT_SCSI_CMD_PER_DEV_HIGH
;
2261 max_depth
= MPT_SCSI_CMD_PER_DEV_LOW
;
2263 /* error case - No Inq. Data */
2267 max_depth
= MPT_SCSI_CMD_PER_DEV_HIGH
;
2269 if (qdepth
> max_depth
)
2274 tagged
= MSG_SIMPLE_TAG
;
2276 scsi_adjust_queue_depth(device
, tagged
, qdepth
);
2281 * OS entry point to adjust the queue_depths on a per-device basis.
2282 * Called once per device the bus scan. Use it to force the queue_depth
2283 * member to 1 if a device does not support Q tags.
2284 * Return non-zero if fails.
2287 mptscsih_slave_configure(struct scsi_device
*device
)
2289 struct Scsi_Host
*sh
= device
->host
;
2290 VirtDevice
*pTarget
;
2291 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*)sh
->hostdata
;
2293 if ((hd
== NULL
) || (hd
->Targets
== NULL
)) {
2297 dsprintk((MYIOC_s_INFO_FMT
2298 "device @ %p, id=%d, LUN=%d, channel=%d\n",
2299 hd
->ioc
->name
, device
, device
->id
, device
->lun
, device
->channel
));
2300 dsprintk((MYIOC_s_INFO_FMT
2301 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2302 hd
->ioc
->name
, device
->sdtr
, device
->wdtr
,
2303 device
->ppr
, device
->inquiry_len
));
2305 if (device
->id
> sh
->max_id
) {
2306 /* error case, should never happen */
2307 scsi_adjust_queue_depth(device
, 0, 1);
2308 goto slave_configure_exit
;
2311 pTarget
= hd
->Targets
[device
->id
];
2313 if (pTarget
== NULL
) {
2314 /* Driver doesn't know about this device.
2315 * Kernel may generate a "Dummy Lun 0" which
2316 * may become a real Lun if a
2317 * "scsi add-single-device" command is executed
2318 * while the driver is active (hot-plug a
2319 * device). LSI Raid controllers need
2320 * queue_depth set to DEV_HIGH for this reason.
2322 scsi_adjust_queue_depth(device
, MSG_SIMPLE_TAG
,
2323 MPT_SCSI_CMD_PER_DEV_HIGH
);
2324 goto slave_configure_exit
;
2327 mptscsih_initTarget(hd
, device
->channel
, device
->id
, device
->lun
,
2328 device
->inquiry
, device
->inquiry_len
);
2329 mptscsih_set_queue_depth(device
, hd
, pTarget
, MPT_SCSI_CMD_PER_DEV_HIGH
);
2331 dsprintk((MYIOC_s_INFO_FMT
2332 "Queue depth=%d, tflags=%x\n",
2333 hd
->ioc
->name
, device
->queue_depth
, pTarget
->tflags
));
2335 dsprintk((MYIOC_s_INFO_FMT
2336 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2337 hd
->ioc
->name
, pTarget
->negoFlags
, pTarget
->maxOffset
, pTarget
->minSyncFactor
));
2339 slave_configure_exit
:
2341 dsprintk((MYIOC_s_INFO_FMT
2342 "tagged %d, simple %d, ordered %d\n",
2343 hd
->ioc
->name
,device
->tagged_supported
, device
->simple_tags
,
2344 device
->ordered_tags
));
2350 mptscsih_store_queue_depth(struct device
*dev
, const char *buf
, size_t count
)
2353 struct scsi_device
*sdev
= to_scsi_device(dev
);
2354 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*) sdev
->host
->hostdata
;
2355 VirtDevice
*pTarget
;
2357 depth
= simple_strtoul(buf
, NULL
, 0);
2360 pTarget
= hd
->Targets
[sdev
->id
];
2361 if (pTarget
== NULL
)
2363 mptscsih_set_queue_depth(sdev
, (MPT_SCSI_HOST
*) sdev
->host
->hostdata
,
2368 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2370 * Private routines...
2373 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2374 /* Utility function to copy sense data from the scsi_cmnd buffer
2375 * to the FC and SCSI target structures.
2379 mptscsih_copy_sense_data(struct scsi_cmnd
*sc
, MPT_SCSI_HOST
*hd
, MPT_FRAME_HDR
*mf
, SCSIIOReply_t
*pScsiReply
)
2382 SCSIIORequest_t
*pReq
;
2383 u32 sense_count
= le32_to_cpu(pScsiReply
->SenseCount
);
2386 /* Get target structure
2388 pReq
= (SCSIIORequest_t
*) mf
;
2389 index
= (int) pReq
->TargetID
;
2390 target
= hd
->Targets
[index
];
2396 /* Copy the sense received into the scsi command block. */
2397 req_index
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
2398 sense_data
= ((u8
*)hd
->ioc
->sense_buf_pool
+ (req_index
* MPT_SENSE_BUFFER_ALLOC
));
2399 memcpy(sc
->sense_buffer
, sense_data
, SNS_LEN(sc
));
2401 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2403 if ((hd
->ioc
->events
) && (hd
->ioc
->eventTypes
& (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE
))) {
2404 if ((sense_data
[12] == 0x5D) && (target
->raidVolume
== 0)) {
2406 MPT_ADAPTER
*ioc
= hd
->ioc
;
2408 idx
= ioc
->eventContext
% ioc
->eventLogSize
;
2409 ioc
->events
[idx
].event
= MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE
;
2410 ioc
->events
[idx
].eventContext
= ioc
->eventContext
;
2412 ioc
->events
[idx
].data
[0] = (pReq
->LUN
[1] << 24) ||
2413 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA
<< 16) ||
2414 (pReq
->Bus
<< 8) || pReq
->TargetID
;
2416 ioc
->events
[idx
].data
[1] = (sense_data
[13] << 8) || sense_data
[12];
2418 ioc
->eventContext
++;
2422 dprintk((MYIOC_s_INFO_FMT
"Hmmm... SenseData len=0! (?)\n",
2428 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd
*sc
)
2433 hd
= (MPT_SCSI_HOST
*) sc
->device
->host
->hostdata
;
2435 for (i
= 0; i
< hd
->ioc
->req_depth
; i
++) {
2436 if (hd
->ScsiLookup
[i
] == sc
) {
2444 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2446 mptscsih_ioc_reset(MPT_ADAPTER
*ioc
, int reset_phase
)
2449 unsigned long flags
;
2451 dtmprintk((KERN_WARNING MYNAM
2452 ": IOC %s_reset routed to SCSI host driver!\n",
2453 reset_phase
==MPT_IOC_SETUP_RESET
? "setup" : (
2454 reset_phase
==MPT_IOC_PRE_RESET
? "pre" : "post")));
2456 /* If a FW reload request arrives after base installed but
2457 * before all scsi hosts have been attached, then an alt_ioc
2458 * may have a NULL sh pointer.
2460 if ((ioc
->sh
== NULL
) || (ioc
->sh
->hostdata
== NULL
))
2463 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
2465 if (reset_phase
== MPT_IOC_SETUP_RESET
) {
2466 dtmprintk((MYIOC_s_WARN_FMT
"Setup-Diag Reset\n", ioc
->name
));
2469 * 1. Set Hard Reset Pending Flag
2470 * All new commands go to doneQ
2472 hd
->resetPending
= 1;
2474 } else if (reset_phase
== MPT_IOC_PRE_RESET
) {
2475 dtmprintk((MYIOC_s_WARN_FMT
"Pre-Diag Reset\n", ioc
->name
));
2477 /* 2. Flush running commands
2478 * Clean ScsiLookup (and associated memory)
2482 /* 2b. Reply to OS all known outstanding I/O commands.
2484 mptscsih_flush_running_cmds(hd
);
2486 /* 2c. If there was an internal command that
2487 * has not completed, configuration or io request,
2488 * free these resources.
2491 del_timer(&hd
->timer
);
2492 mpt_free_msg_frame(ioc
, hd
->cmdPtr
);
2495 dtmprintk((MYIOC_s_WARN_FMT
"Pre-Reset complete.\n", ioc
->name
));
2498 dtmprintk((MYIOC_s_WARN_FMT
"Post-Diag Reset\n", ioc
->name
));
2500 /* Once a FW reload begins, all new OS commands are
2501 * redirected to the doneQ w/ a reset status.
2502 * Init all control structures.
2505 /* ScsiLookup initialization
2509 for (ii
=0; ii
< hd
->ioc
->req_depth
; ii
++)
2510 hd
->ScsiLookup
[ii
] = NULL
;
2513 /* 2. Chain Buffer initialization
2516 /* 4. Renegotiate to all devices, if SCSI
2518 if (ioc
->bus_type
== SCSI
) {
2519 dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
2520 mptscsih_writeSDP1(hd
, 0, 0, MPT_SCSICFG_ALL_IDS
| MPT_SCSICFG_USE_NVRAM
);
2523 /* 5. Enable new commands to be posted
2525 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
2527 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
2528 hd
->resetPending
= 0;
2529 hd
->tmState
= TM_STATE_NONE
;
2531 /* 6. If there was an internal command,
2532 * wake this process up.
2536 * Wake up the original calling thread
2538 hd
->pLocal
= &hd
->localReply
;
2539 hd
->pLocal
->completion
= MPT_SCANDV_DID_RESET
;
2540 hd
->scandv_wait_done
= 1;
2541 wake_up(&hd
->scandv_waitq
);
2545 /* 7. Set flag to force DV and re-read IOC Page 3
2547 if (ioc
->bus_type
== SCSI
) {
2548 ioc
->spi_data
.forceDv
= MPT_SCSICFG_NEED_DV
| MPT_SCSICFG_RELOAD_IOC_PG3
;
2549 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
2552 dtmprintk((MYIOC_s_WARN_FMT
"Post-Reset complete.\n", ioc
->name
));
2556 return 1; /* currently means nothing really */
2559 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2561 mptscsih_event_process(MPT_ADAPTER
*ioc
, EventNotificationReply_t
*pEvReply
)
2564 u8 event
= le32_to_cpu(pEvReply
->Event
) & 0xFF;
2566 devtprintk((MYIOC_s_INFO_FMT
"MPT event (=%02Xh) routed to SCSI host driver!\n",
2570 case MPI_EVENT_UNIT_ATTENTION
: /* 03 */
2573 case MPI_EVENT_IOC_BUS_RESET
: /* 04 */
2574 case MPI_EVENT_EXT_BUS_RESET
: /* 05 */
2577 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
2578 if (hd
&& (ioc
->bus_type
== SCSI
) && (hd
->soft_resets
< -1))
2582 case MPI_EVENT_LOGOUT
: /* 09 */
2587 * CHECKME! Don't think we need to do
2588 * anything for these, but...
2590 case MPI_EVENT_RESCAN
: /* 06 */
2591 case MPI_EVENT_LINK_STATUS_CHANGE
: /* 07 */
2592 case MPI_EVENT_LOOP_STATE_CHANGE
: /* 08 */
2594 * CHECKME! Falling thru...
2598 case MPI_EVENT_INTEGRATED_RAID
: /* 0B */
2599 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2600 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
2601 * if DV disabled. Need to check for target mode.
2605 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
2607 if (hd
&& (ioc
->bus_type
== SCSI
) && (hd
->negoNvram
== 0)) {
2609 Ioc3PhysDisk_t
*pPDisk
;
2614 reason
= (le32_to_cpu(pEvReply
->Data
[0]) & 0x00FF0000) >> 16;
2615 if (reason
== MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED
) {
2616 /* New or replaced disk.
2617 * Set DV flag and schedule DV.
2619 pSpi
= &ioc
->spi_data
;
2620 physDiskNum
= (le32_to_cpu(pEvReply
->Data
[0]) & 0xFF000000) >> 24;
2621 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum
));
2622 if (pSpi
->pIocPg3
) {
2623 pPDisk
= pSpi
->pIocPg3
->PhysDisk
;
2624 numPDisk
=pSpi
->pIocPg3
->NumPhysDisks
;
2627 if (physDiskNum
== pPDisk
->PhysDiskNum
) {
2628 pSpi
->dvStatus
[pPDisk
->PhysDiskID
] = (MPT_SCSICFG_NEED_DV
| MPT_SCSICFG_DV_NOT_DONE
);
2629 pSpi
->forceDv
= MPT_SCSICFG_NEED_DV
;
2630 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk
->PhysDiskID
));
2637 if (numPDisk
== 0) {
2638 /* The physical disk that needs DV was not found
2639 * in the stored IOC Page 3. The driver must reload
2640 * this page. DV routine will set the NEED_DV flag for
2641 * all phys disks that have DV_NOT_DONE set.
2643 pSpi
->forceDv
= MPT_SCSICFG_NEED_DV
| MPT_SCSICFG_RELOAD_IOC_PG3
;
2644 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum
));
2651 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
2652 printk("Raid Event RF: ");
2654 u32
*m
= (u32
*)pEvReply
;
2656 int n
= (int)pEvReply
->MsgLength
;
2657 for (ii
=6; ii
< n
; ii
++)
2658 printk(" %08x", le32_to_cpu(m
[ii
]));
2664 case MPI_EVENT_NONE
: /* 00 */
2665 case MPI_EVENT_LOG_DATA
: /* 01 */
2666 case MPI_EVENT_STATE_CHANGE
: /* 02 */
2667 case MPI_EVENT_EVENT_CHANGE
: /* 0A */
2669 dprintk((KERN_INFO
" Ignoring event (=%02Xh)\n", event
));
2673 return 1; /* currently means nothing really */
2676 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2678 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2679 * @hd: Pointer to MPT_SCSI_HOST structure
2680 * @bus_id: Bus number (?)
2681 * @target_id: SCSI target id
2683 * @data: Pointer to data
2684 * @dlen: Number of INQUIRY bytes
2686 * NOTE: It's only SAFE to call this routine if data points to
2687 * sane & valid STANDARD INQUIRY data!
2689 * Allocate and initialize memory for this target.
2690 * Save inquiry data.
2694 mptscsih_initTarget(MPT_SCSI_HOST
*hd
, int bus_id
, int target_id
, u8 lun
, char *data
, int dlen
)
2696 int indexed_lun
, lun_index
;
2701 dinitprintk((MYIOC_s_INFO_FMT
"initTarget bus=%d id=%d lun=%d hd=%p\n",
2702 hd
->ioc
->name
, bus_id
, target_id
, lun
, hd
));
2705 * If the peripheral qualifier filter is enabled then if the target reports a 0x1
2706 * (i.e. The targer is capable of supporting the specified peripheral device type
2707 * on this logical unit; however, the physical device is not currently connected
2708 * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
2709 * capable of supporting a physical device on this logical unit). This is to work
2710 * around a bug in th emid-layer in some distributions in which the mid-layer will
2711 * continue to try to communicate to the LUN and evntually create a dummy LUN.
2713 if (hd
->mpt_pq_filter
&& dlen
&& (data
[0] & 0xE0))
2716 /* Is LUN supported? If so, upper 2 bits will be 0
2717 * in first byte of inquiry data.
2722 if ((vdev
= hd
->Targets
[target_id
]) == NULL
) {
2726 lun_index
= (lun
>> 5); /* 32 luns per lun_index */
2727 indexed_lun
= (lun
% 32);
2728 vdev
->luns
[lun_index
] |= (1 << indexed_lun
);
2730 if (hd
->ioc
->bus_type
== SCSI
) {
2731 if ((data
[0] == TYPE_PROCESSOR
) && (hd
->ioc
->spi_data
.Saf_Te
)) {
2732 /* Treat all Processors as SAF-TE if
2733 * command line option is set */
2734 vdev
->tflags
|= MPT_TARGET_FLAGS_SAF_TE_ISSUED
;
2735 mptscsih_writeIOCPage4(hd
, target_id
, bus_id
);
2736 }else if ((data
[0] == TYPE_PROCESSOR
) &&
2737 !(vdev
->tflags
& MPT_TARGET_FLAGS_SAF_TE_ISSUED
)) {
2739 vdev
->tflags
|= MPT_TARGET_FLAGS_VALID_INQUIRY
;
2740 if ( data
[44] == 'S' &&
2746 vdev
->tflags
|= MPT_TARGET_FLAGS_SAF_TE_ISSUED
;
2747 mptscsih_writeIOCPage4(hd
, target_id
, bus_id
);
2751 if (!(vdev
->tflags
& MPT_TARGET_FLAGS_VALID_INQUIRY
)) {
2753 memcpy (vdev
->inq_data
, data
, 8);
2755 memcpy (vdev
->inq_data
, data
, dlen
);
2758 /* If have not done DV, set the DV flag.
2760 pSpi
= &hd
->ioc
->spi_data
;
2761 if ((data
[0] == TYPE_TAPE
) || (data
[0] == TYPE_PROCESSOR
)) {
2762 if (pSpi
->dvStatus
[target_id
] & MPT_SCSICFG_DV_NOT_DONE
)
2763 pSpi
->dvStatus
[target_id
] |= MPT_SCSICFG_NEED_DV
;
2766 vdev
->tflags
|= MPT_TARGET_FLAGS_VALID_INQUIRY
;
2769 data_56
= 0x0F; /* Default to full capabilities if Inq data length is < 57 */
2771 if ( (!(vdev
->tflags
& MPT_TARGET_FLAGS_VALID_56
))) {
2772 /* Update the target capabilities
2775 vdev
->tflags
|= MPT_TARGET_FLAGS_VALID_56
;
2778 mptscsih_setTargetNegoParms(hd
, vdev
, data_56
);
2780 /* Initial Inquiry may not request enough data bytes to
2781 * obtain byte 57. DV will; if target doesn't return
2782 * at least 57 bytes, data[56] will be zero. */
2784 if ( (!(vdev
->tflags
& MPT_TARGET_FLAGS_VALID_56
))) {
2785 /* Update the target capabilities
2788 vdev
->tflags
|= MPT_TARGET_FLAGS_VALID_56
;
2789 mptscsih_setTargetNegoParms(hd
, vdev
, data_56
);
2796 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2798 * Update the target negotiation parameters based on the
2799 * the Inquiry data, adapter capabilities, and NVRAM settings.
2803 mptscsih_setTargetNegoParms(MPT_SCSI_HOST
*hd
, VirtDevice
*target
, char byte56
)
2805 ScsiCfgData
*pspi_data
= &hd
->ioc
->spi_data
;
2806 int id
= (int) target
->target_id
;
2810 u8 width
= MPT_NARROW
;
2811 u8 factor
= MPT_ASYNC
;
2813 u8 version
, nfactor
;
2816 target
->negoFlags
= pspi_data
->noQas
;
2818 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
2819 * support. If available, default QAS to off and allow enabling.
2820 * If not available, default QAS to on, turn off for non-disks.
2823 /* Set flags based on Inquiry data
2825 version
= target
->inq_data
[2] & 0x07;
2828 factor
= MPT_ULTRA2
;
2829 offset
= pspi_data
->maxSyncOffset
;
2830 target
->tflags
&= ~MPT_TARGET_FLAGS_Q_YES
;
2832 if (target
->inq_data
[7] & 0x20) {
2836 if (target
->inq_data
[7] & 0x10) {
2837 factor
= pspi_data
->minSyncFactor
;
2838 if (target
->tflags
& MPT_TARGET_FLAGS_VALID_56
) {
2839 /* bits 2 & 3 show Clocking support */
2840 if ((byte56
& 0x0C) == 0)
2841 factor
= MPT_ULTRA2
;
2843 if ((byte56
& 0x03) == 0)
2844 factor
= MPT_ULTRA160
;
2846 factor
= MPT_ULTRA320
;
2849 ddvtprintk((KERN_INFO
"Enabling QAS due to byte56=%02x on id=%d!\n", byte56
, id
));
2852 if (target
->inq_data
[0] == TYPE_TAPE
) {
2854 target
->negoFlags
|= MPT_TAPE_NEGO_IDP
;
2859 ddvtprintk((KERN_INFO
"Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id
));
2863 offset
= pspi_data
->maxSyncOffset
;
2865 /* If RAID, never disable QAS
2866 * else if non RAID, do not disable
2867 * QAS if bit 1 is set
2868 * bit 1 QAS support, non-raid only
2871 if (target
->raidVolume
== 1) {
2880 if ( (target
->inq_data
[7] & 0x02) == 0) {
2881 target
->tflags
&= ~MPT_TARGET_FLAGS_Q_YES
;
2884 /* Update tflags based on NVRAM settings. (SCSI only)
2886 if (pspi_data
->nvram
&& (pspi_data
->nvram
[id
] != MPT_HOST_NVRAM_INVALID
)) {
2887 nvram
= pspi_data
->nvram
[id
];
2888 nfactor
= (nvram
& MPT_NVRAM_SYNC_MASK
) >> 8;
2891 width
= nvram
& MPT_NVRAM_WIDE_DISABLE
? 0 : 1;
2894 /* Ensure factor is set to the
2895 * maximum of: adapter, nvram, inquiry
2898 if (nfactor
< pspi_data
->minSyncFactor
)
2899 nfactor
= pspi_data
->minSyncFactor
;
2901 factor
= max(factor
, nfactor
);
2902 if (factor
== MPT_ASYNC
)
2913 /* Make sure data is consistent
2915 if ((!width
) && (factor
< MPT_ULTRA2
)) {
2916 factor
= MPT_ULTRA2
;
2919 /* Save the data to the target structure.
2921 target
->minSyncFactor
= factor
;
2922 target
->maxOffset
= offset
;
2923 target
->maxWidth
= width
;
2925 target
->tflags
|= MPT_TARGET_FLAGS_VALID_NEGO
;
2927 /* Disable unused features.
2930 target
->negoFlags
|= MPT_TARGET_NO_NEGO_WIDE
;
2933 target
->negoFlags
|= MPT_TARGET_NO_NEGO_SYNC
;
2935 if ( factor
> MPT_ULTRA320
)
2938 /* GEM, processor WORKAROUND
2940 if ((target
->inq_data
[0] == TYPE_PROCESSOR
) || (target
->inq_data
[0] > 0x08)) {
2941 target
->negoFlags
|= (MPT_TARGET_NO_NEGO_WIDE
| MPT_TARGET_NO_NEGO_SYNC
);
2942 pspi_data
->dvStatus
[id
] |= MPT_SCSICFG_BLK_NEGO
;
2944 if (noQas
&& (pspi_data
->noQas
== 0)) {
2945 pspi_data
->noQas
|= MPT_TARGET_NO_NEGO_QAS
;
2946 target
->negoFlags
|= MPT_TARGET_NO_NEGO_QAS
;
2948 /* Disable QAS in a mixed configuration case
2951 ddvtprintk((KERN_INFO
"Disabling QAS due to noQas=%02x on id=%d!\n", noQas
, id
));
2952 for (ii
= 0; ii
< id
; ii
++) {
2953 if ( (vdev
= hd
->Targets
[ii
]) ) {
2954 vdev
->negoFlags
|= MPT_TARGET_NO_NEGO_QAS
;
2955 mptscsih_writeSDP1(hd
, 0, ii
, vdev
->negoFlags
);
2961 /* Write SDP1 on this I/O to this target */
2962 if (pspi_data
->dvStatus
[id
] & MPT_SCSICFG_NEGOTIATE
) {
2963 ddvtprintk((KERN_INFO
"MPT_SCSICFG_NEGOTIATE on id=%d!\n", id
));
2964 mptscsih_writeSDP1(hd
, 0, id
, hd
->negoNvram
);
2965 pspi_data
->dvStatus
[id
] &= ~MPT_SCSICFG_NEGOTIATE
;
2966 } else if (pspi_data
->dvStatus
[id
] & MPT_SCSICFG_BLK_NEGO
) {
2967 ddvtprintk((KERN_INFO
"MPT_SCSICFG_BLK_NEGO on id=%d!\n", id
));
2968 mptscsih_writeSDP1(hd
, 0, id
, MPT_SCSICFG_BLK_NEGO
);
2969 pspi_data
->dvStatus
[id
] &= ~MPT_SCSICFG_BLK_NEGO
;
2973 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2974 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
2975 * Else set the NEED_DV flag after Read Capacity Issued (disks)
2976 * or Mode Sense (cdroms).
2978 * Tapes, initTarget will set this flag on completion of Inquiry command.
2979 * Called only if DV_NOT_DONE flag is set
2982 mptscsih_set_dvflags(MPT_SCSI_HOST
*hd
, SCSIIORequest_t
*pReq
)
2987 ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
2988 pReq
->TargetID
, pReq
->LUN
[1], hd
->negoNvram
, pReq
->CDB
[0]));
2990 if ((pReq
->LUN
[1] != 0) || (hd
->negoNvram
!= 0))
2995 if ((cmd
== READ_CAPACITY
) || (cmd
== MODE_SENSE
)) {
2996 pSpi
= &hd
->ioc
->spi_data
;
2997 if ((pSpi
->isRaid
& (1 << pReq
->TargetID
)) && pSpi
->pIocPg3
) {
2998 /* Set NEED_DV for all hidden disks
3000 Ioc3PhysDisk_t
*pPDisk
= pSpi
->pIocPg3
->PhysDisk
;
3001 int numPDisk
= pSpi
->pIocPg3
->NumPhysDisks
;
3004 pSpi
->dvStatus
[pPDisk
->PhysDiskID
] |= MPT_SCSICFG_NEED_DV
;
3005 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk
->PhysDiskID
));
3010 pSpi
->dvStatus
[pReq
->TargetID
] |= MPT_SCSICFG_NEED_DV
;
3011 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq
->TargetID
));
3015 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3017 * If no Target, bus reset on 1st I/O. Set the flag to
3018 * prevent any future negotiations to this device.
3021 mptscsih_no_negotiate(MPT_SCSI_HOST
*hd
, int target_id
)
3024 if ((hd
->Targets
) && (hd
->Targets
[target_id
] == NULL
))
3025 hd
->ioc
->spi_data
.dvStatus
[target_id
] |= MPT_SCSICFG_BLK_NEGO
;
3030 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3032 * SCSI Config Page functionality ...
3034 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3035 /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
3036 * based on width, factor and offset parameters.
3038 * @factor: sync factor
3039 * @offset: sync offset
3040 * @requestedPtr: pointer to requested values (updated)
3041 * @configurationPtr: pointer to configuration values (updated)
3042 * @flags: flags to block WDTR or SDTR negotiation
3046 * Remark: Called by writeSDP1 and _dv_params
3049 mptscsih_setDevicePage1Flags (u8 width
, u8 factor
, u8 offset
, int *requestedPtr
, int *configurationPtr
, u8 flags
)
3051 u8 nowide
= flags
& MPT_TARGET_NO_NEGO_WIDE
;
3052 u8 nosync
= flags
& MPT_TARGET_NO_NEGO_SYNC
;
3054 *configurationPtr
= 0;
3055 *requestedPtr
= width
? MPI_SCSIDEVPAGE1_RP_WIDE
: 0;
3056 *requestedPtr
|= (offset
<< 16) | (factor
<< 8);
3058 if (width
&& offset
&& !nowide
&& !nosync
) {
3059 if (factor
< MPT_ULTRA160
) {
3060 *requestedPtr
|= (MPI_SCSIDEVPAGE1_RP_IU
+ MPI_SCSIDEVPAGE1_RP_DT
);
3061 if ((flags
& MPT_TARGET_NO_NEGO_QAS
) == 0)
3062 *requestedPtr
|= MPI_SCSIDEVPAGE1_RP_QAS
;
3063 if (flags
& MPT_TAPE_NEGO_IDP
)
3064 *requestedPtr
|= 0x08000000;
3065 } else if (factor
< MPT_ULTRA2
) {
3066 *requestedPtr
|= MPI_SCSIDEVPAGE1_RP_DT
;
3071 *configurationPtr
|= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED
;
3074 *configurationPtr
|= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED
;
3079 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3080 /* mptscsih_writeSDP1 - write SCSI Device Page 1
3081 * @hd: Pointer to a SCSI Host Strucutre
3082 * @portnum: IOC port number
3083 * @target_id: writeSDP1 for single ID
3084 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
3086 * Return: -EFAULT if read of config page header fails
3089 * Remark: If a target has been found, the settings from the
3090 * target structure are used, else the device is set
3093 * Remark: Called during init and after a FW reload.
3094 * Remark: We do not wait for a return, write pages sequentially.
3097 mptscsih_writeSDP1(MPT_SCSI_HOST
*hd
, int portnum
, int target_id
, int flags
)
3099 MPT_ADAPTER
*ioc
= hd
->ioc
;
3101 SCSIDevicePage1_t
*pData
;
3102 VirtDevice
*pTarget
;
3107 u32 requested
, configuration
, flagsLength
;
3109 int id
= 0, maxid
= 0;
3115 u8 maxwidth
, maxoffset
, maxfactor
;
3117 if (ioc
->spi_data
.sdp1length
== 0)
3120 if (flags
& MPT_SCSICFG_ALL_IDS
) {
3122 maxid
= ioc
->sh
->max_id
- 1;
3123 } else if (ioc
->sh
) {
3125 maxid
= min_t(int, id
, ioc
->sh
->max_id
- 1);
3128 for (; id
<= maxid
; id
++) {
3130 if (id
== ioc
->pfacts
[portnum
].PortSCSIID
)
3133 /* Use NVRAM to get adapter and target maximums
3134 * Data over-riden by target structure information, if present
3136 maxwidth
= ioc
->spi_data
.maxBusWidth
;
3137 maxoffset
= ioc
->spi_data
.maxSyncOffset
;
3138 maxfactor
= ioc
->spi_data
.minSyncFactor
;
3139 if (ioc
->spi_data
.nvram
&& (ioc
->spi_data
.nvram
[id
] != MPT_HOST_NVRAM_INVALID
)) {
3140 nvram
= ioc
->spi_data
.nvram
[id
];
3143 maxwidth
= nvram
& MPT_NVRAM_WIDE_DISABLE
? 0 : 1;
3145 if (maxoffset
> 0) {
3146 maxfactor
= (nvram
& MPT_NVRAM_SYNC_MASK
) >> 8;
3147 if (maxfactor
== 0) {
3149 maxfactor
= MPT_ASYNC
;
3151 } else if (maxfactor
< ioc
->spi_data
.minSyncFactor
) {
3152 maxfactor
= ioc
->spi_data
.minSyncFactor
;
3155 maxfactor
= MPT_ASYNC
;
3158 /* Set the negotiation flags.
3160 negoFlags
= ioc
->spi_data
.noQas
;
3162 negoFlags
|= MPT_TARGET_NO_NEGO_WIDE
;
3165 negoFlags
|= MPT_TARGET_NO_NEGO_SYNC
;
3167 if (flags
& MPT_SCSICFG_USE_NVRAM
) {
3176 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
3179 /* If id is not a raid volume, get the updated
3180 * transmission settings from the target structure.
3182 if (hd
->Targets
&& (pTarget
= hd
->Targets
[id
]) && !pTarget
->raidVolume
) {
3183 width
= pTarget
->maxWidth
;
3184 factor
= pTarget
->minSyncFactor
;
3185 offset
= pTarget
->maxOffset
;
3186 negoFlags
= pTarget
->negoFlags
;
3189 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3190 /* Force to async and narrow if DV has not been executed
3193 if ((hd
->ioc
->spi_data
.dvStatus
[id
] & MPT_SCSICFG_DV_NOT_DONE
) != 0) {
3200 if (flags
& MPT_SCSICFG_BLK_NEGO
)
3201 negoFlags
= MPT_TARGET_NO_NEGO_WIDE
| MPT_TARGET_NO_NEGO_SYNC
;
3203 mptscsih_setDevicePage1Flags(width
, factor
, offset
,
3204 &requested
, &configuration
, negoFlags
);
3205 dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
3206 target_id
, width
, factor
, offset
, negoFlags
, requested
, configuration
));
3208 /* Get a MF for this command.
3210 if ((mf
= mpt_get_msg_frame(ioc
->DoneCtx
, ioc
)) == NULL
) {
3211 dprintk((MYIOC_s_WARN_FMT
"write SDP1: no msg frames!\n",
3216 ddvprintk((MYIOC_s_INFO_FMT
"WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
3217 hd
->ioc
->name
, mf
, id
, requested
, configuration
));
3220 /* Set the request and the data pointers.
3221 * Request takes: 36 bytes (32 bit SGE)
3222 * SCSI Device Page 1 requires 16 bytes
3223 * 40 + 16 <= size of SCSI IO Request = 56 bytes
3224 * and MF size >= 64 bytes.
3225 * Place data at end of MF.
3227 pReq
= (Config_t
*)mf
;
3229 req_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
3230 frameOffset
= ioc
->req_sz
- sizeof(SCSIDevicePage1_t
);
3232 pData
= (SCSIDevicePage1_t
*)((u8
*) mf
+ frameOffset
);
3233 dataDma
= ioc
->req_frames_dma
+ (req_idx
* ioc
->req_sz
) + frameOffset
;
3235 /* Complete the request frame (same for all requests).
3237 pReq
->Action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
3239 pReq
->ChainOffset
= 0;
3240 pReq
->Function
= MPI_FUNCTION_CONFIG
;
3241 pReq
->ExtPageLength
= 0;
3242 pReq
->ExtPageType
= 0;
3244 for (ii
=0; ii
< 8; ii
++) {
3245 pReq
->Reserved2
[ii
] = 0;
3247 pReq
->Header
.PageVersion
= ioc
->spi_data
.sdp1version
;
3248 pReq
->Header
.PageLength
= ioc
->spi_data
.sdp1length
;
3249 pReq
->Header
.PageNumber
= 1;
3250 pReq
->Header
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_DEVICE
;
3251 pReq
->PageAddress
= cpu_to_le32(id
| (bus
<< 8 ));
3253 /* Add a SGE to the config request.
3255 flagsLength
= MPT_SGE_FLAGS_SSIMPLE_WRITE
| ioc
->spi_data
.sdp1length
* 4;
3257 mpt_add_sge((char *)&pReq
->PageBufferSGE
, flagsLength
, dataDma
);
3259 /* Set up the common data portion
3261 pData
->Header
.PageVersion
= pReq
->Header
.PageVersion
;
3262 pData
->Header
.PageLength
= pReq
->Header
.PageLength
;
3263 pData
->Header
.PageNumber
= pReq
->Header
.PageNumber
;
3264 pData
->Header
.PageType
= pReq
->Header
.PageType
;
3265 pData
->RequestedParameters
= cpu_to_le32(requested
);
3266 pData
->Reserved
= 0;
3267 pData
->Configuration
= cpu_to_le32(configuration
);
3269 dprintk((MYIOC_s_INFO_FMT
3270 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
3271 ioc
->name
, id
, (id
| (bus
<<8)),
3272 requested
, configuration
));
3274 mpt_put_msg_frame(ioc
->DoneCtx
, ioc
, mf
);
3280 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3281 /* mptscsih_writeIOCPage4 - write IOC Page 4
3282 * @hd: Pointer to a SCSI Host Structure
3283 * @target_id: write IOC Page4 for this ID & Bus
3285 * Return: -EAGAIN if unable to obtain a Message Frame
3288 * Remark: We do not wait for a return, write pages sequentially.
3291 mptscsih_writeIOCPage4(MPT_SCSI_HOST
*hd
, int target_id
, int bus
)
3293 MPT_ADAPTER
*ioc
= hd
->ioc
;
3295 IOCPage4_t
*IOCPage4Ptr
;
3303 /* Get a MF for this command.
3305 if ((mf
= mpt_get_msg_frame(ioc
->DoneCtx
, ioc
)) == NULL
) {
3306 dprintk((MYIOC_s_WARN_FMT
"writeIOCPage4 : no msg frames!\n",
3311 /* Set the request and the data pointers.
3312 * Place data at end of MF.
3314 pReq
= (Config_t
*)mf
;
3316 req_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
3317 frameOffset
= ioc
->req_sz
- sizeof(IOCPage4_t
);
3319 /* Complete the request frame (same for all requests).
3321 pReq
->Action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
3323 pReq
->ChainOffset
= 0;
3324 pReq
->Function
= MPI_FUNCTION_CONFIG
;
3325 pReq
->ExtPageLength
= 0;
3326 pReq
->ExtPageType
= 0;
3328 for (ii
=0; ii
< 8; ii
++) {
3329 pReq
->Reserved2
[ii
] = 0;
3332 IOCPage4Ptr
= ioc
->spi_data
.pIocPg4
;
3333 dataDma
= ioc
->spi_data
.IocPg4_dma
;
3334 ii
= IOCPage4Ptr
->ActiveSEP
++;
3335 IOCPage4Ptr
->SEP
[ii
].SEPTargetID
= target_id
;
3336 IOCPage4Ptr
->SEP
[ii
].SEPBus
= bus
;
3337 pReq
->Header
= IOCPage4Ptr
->Header
;
3338 pReq
->PageAddress
= cpu_to_le32(target_id
| (bus
<< 8 ));
3340 /* Add a SGE to the config request.
3342 flagsLength
= MPT_SGE_FLAGS_SSIMPLE_WRITE
|
3343 (IOCPage4Ptr
->Header
.PageLength
+ ii
) * 4;
3345 mpt_add_sge((char *)&pReq
->PageBufferSGE
, flagsLength
, dataDma
);
3347 dinitprintk((MYIOC_s_INFO_FMT
3348 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
3349 ioc
->name
, IOCPage4Ptr
->MaxSEP
, IOCPage4Ptr
->ActiveSEP
, target_id
, bus
));
3351 mpt_put_msg_frame(ioc
->DoneCtx
, ioc
, mf
);
3356 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3358 * Bus Scan and Domain Validation functionality ...
3361 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3363 * mptscsih_scandv_complete - Scan and DV callback routine registered
3364 * to Fustion MPT (base) driver.
3366 * @ioc: Pointer to MPT_ADAPTER structure
3367 * @mf: Pointer to original MPT request frame
3368 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
3370 * This routine is called from mpt.c::mpt_interrupt() at the completion
3371 * of any SCSI IO request.
3372 * This routine is registered with the Fusion MPT (base) driver at driver
3373 * load/init time via the mpt_register() API call.
3375 * Returns 1 indicating alloc'd request frame ptr should be freed.
3377 * Remark: Sets a completion code and (possibly) saves sense data
3378 * in the IOC member localReply structure.
3379 * Used ONLY for DV and other internal commands.
3382 mptscsih_scandv_complete(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
, MPT_FRAME_HDR
*mr
)
3385 SCSIIORequest_t
*pReq
;
3389 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
3392 (mf
>= MPT_INDEX_2_MFPTR(ioc
, ioc
->req_depth
))) {
3393 printk(MYIOC_s_ERR_FMT
3394 "ScanDvComplete, %s req frame ptr! (=%p)\n",
3395 ioc
->name
, mf
?"BAD":"NULL", (void *) mf
);
3399 del_timer(&hd
->timer
);
3400 req_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
3401 hd
->ScsiLookup
[req_idx
] = NULL
;
3402 pReq
= (SCSIIORequest_t
*) mf
;
3404 if (mf
!= hd
->cmdPtr
) {
3405 printk(MYIOC_s_WARN_FMT
"ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3406 hd
->ioc
->name
, (void *)mf
, (void *) hd
->cmdPtr
, req_idx
);
3410 ddvprintk((MYIOC_s_INFO_FMT
"ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3411 hd
->ioc
->name
, mf
, mr
, req_idx
));
3413 hd
->pLocal
= &hd
->localReply
;
3414 hd
->pLocal
->scsiStatus
= 0;
3416 /* If target struct exists, clear sense valid flag.
3419 completionCode
= MPT_SCANDV_GOOD
;
3421 SCSIIOReply_t
*pReply
;
3425 pReply
= (SCSIIOReply_t
*) mr
;
3427 status
= le16_to_cpu(pReply
->IOCStatus
) & MPI_IOCSTATUS_MASK
;
3428 scsi_status
= pReply
->SCSIStatus
;
3430 ddvtprintk((KERN_NOTICE
" IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3431 status
, pReply
->SCSIState
, scsi_status
,
3432 le32_to_cpu(pReply
->IOCLogInfo
)));
3436 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE
: /* 0x0043 */
3437 completionCode
= MPT_SCANDV_SELECTION_TIMEOUT
;
3440 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR
: /* 0x0046 */
3441 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED
: /* 0x0048 */
3442 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED
: /* 0x004B */
3443 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED
: /* 0x004C */
3444 completionCode
= MPT_SCANDV_DID_RESET
;
3447 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN
: /* 0x0045 */
3448 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR
: /* 0x0040 */
3449 case MPI_IOCSTATUS_SUCCESS
: /* 0x0000 */
3450 if (pReply
->Function
== MPI_FUNCTION_CONFIG
) {
3451 ConfigReply_t
*pr
= (ConfigReply_t
*)mr
;
3452 completionCode
= MPT_SCANDV_GOOD
;
3453 hd
->pLocal
->header
.PageVersion
= pr
->Header
.PageVersion
;
3454 hd
->pLocal
->header
.PageLength
= pr
->Header
.PageLength
;
3455 hd
->pLocal
->header
.PageNumber
= pr
->Header
.PageNumber
;
3456 hd
->pLocal
->header
.PageType
= pr
->Header
.PageType
;
3458 } else if (pReply
->Function
== MPI_FUNCTION_RAID_ACTION
) {
3459 /* If the RAID Volume request is successful,
3460 * return GOOD, else indicate that
3461 * some type of error occurred.
3463 MpiRaidActionReply_t
*pr
= (MpiRaidActionReply_t
*)mr
;
3464 if (pr
->ActionStatus
== MPI_RAID_ACTION_ASTATUS_SUCCESS
)
3465 completionCode
= MPT_SCANDV_GOOD
;
3467 completionCode
= MPT_SCANDV_SOME_ERROR
;
3469 } else if (pReply
->SCSIState
& MPI_SCSI_STATE_AUTOSENSE_VALID
) {
3473 /* save sense data in global structure
3475 completionCode
= MPT_SCANDV_SENSE
;
3476 hd
->pLocal
->scsiStatus
= scsi_status
;
3477 sense_data
= ((u8
*)hd
->ioc
->sense_buf_pool
+
3478 (req_idx
* MPT_SENSE_BUFFER_ALLOC
));
3480 sz
= min_t(int, pReq
->SenseBufferLength
,
3481 SCSI_STD_SENSE_BYTES
);
3482 memcpy(hd
->pLocal
->sense
, sense_data
, sz
);
3484 ddvprintk((KERN_NOTICE
" Check Condition, sense ptr %p\n",
3486 } else if (pReply
->SCSIState
& MPI_SCSI_STATE_AUTOSENSE_FAILED
) {
3487 if (pReq
->CDB
[0] == INQUIRY
)
3488 completionCode
= MPT_SCANDV_ISSUE_SENSE
;
3490 completionCode
= MPT_SCANDV_DID_RESET
;
3492 else if (pReply
->SCSIState
& MPI_SCSI_STATE_NO_SCSI_STATUS
)
3493 completionCode
= MPT_SCANDV_DID_RESET
;
3494 else if (pReply
->SCSIState
& MPI_SCSI_STATE_TERMINATED
)
3495 completionCode
= MPT_SCANDV_DID_RESET
;
3497 completionCode
= MPT_SCANDV_GOOD
;
3498 hd
->pLocal
->scsiStatus
= scsi_status
;
3502 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR
: /* 0x0047 */
3503 if (pReply
->SCSIState
& MPI_SCSI_STATE_TERMINATED
)
3504 completionCode
= MPT_SCANDV_DID_RESET
;
3506 completionCode
= MPT_SCANDV_SOME_ERROR
;
3510 completionCode
= MPT_SCANDV_SOME_ERROR
;
3513 } /* switch(status) */
3515 ddvtprintk((KERN_NOTICE
" completionCode set to %08xh\n",
3517 } /* end of address reply case */
3519 hd
->pLocal
->completion
= completionCode
;
3521 /* MF and RF are freed in mpt_interrupt
3524 /* Free Chain buffers (will never chain) in scan or dv */
3525 //mptscsih_freeChainBuffers(ioc, req_idx);
3528 * Wake up the original calling thread
3530 hd
->scandv_wait_done
= 1;
3531 wake_up(&hd
->scandv_waitq
);
3536 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3537 /* mptscsih_timer_expired - Call back for timer process.
3538 * Used only for dv functionality.
3539 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3543 mptscsih_timer_expired(unsigned long data
)
3545 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*) data
;
3547 ddvprintk((MYIOC_s_WARN_FMT
"Timer Expired! Cmd %p\n", hd
->ioc
->name
, hd
->cmdPtr
));
3550 MPIHeader_t
*cmd
= (MPIHeader_t
*)hd
->cmdPtr
;
3552 if (cmd
->Function
== MPI_FUNCTION_SCSI_IO_REQUEST
) {
3553 /* Desire to issue a task management request here.
3554 * TM requests MUST be single threaded.
3555 * If old eh code and no TM current, issue request.
3556 * If new eh code, do nothing. Wait for OS cmd timeout
3559 ddvtprintk((MYIOC_s_NOTE_FMT
"DV Cmd Timeout: NoOp\n", hd
->ioc
->name
));
3561 /* Perform a FW reload */
3562 if (mpt_HardResetHandler(hd
->ioc
, NO_SLEEP
) < 0) {
3563 printk(MYIOC_s_WARN_FMT
"Firmware Reload FAILED!\n", hd
->ioc
->name
);
3567 /* This should NEVER happen */
3568 printk(MYIOC_s_WARN_FMT
"Null cmdPtr!!!!\n", hd
->ioc
->name
);
3571 /* No more processing.
3572 * TM call will generate an interrupt for SCSI TM Management.
3573 * The FW will reply to all outstanding commands, callback will finish cleanup.
3574 * Hard reset clean-up will free all resources.
3576 ddvprintk((MYIOC_s_WARN_FMT
"Timer Expired Complete!\n", hd
->ioc
->name
));
3581 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3582 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3583 /* mptscsih_do_raid - Format and Issue a RAID volume request message.
3584 * @hd: Pointer to scsi host structure
3585 * @action: What do be done.
3586 * @id: Logical target id.
3587 * @bus: Target locations bus.
3589 * Returns: < 0 on a fatal error
3592 * Remark: Wait to return until reply processed by the ISR.
3595 mptscsih_do_raid(MPT_SCSI_HOST
*hd
, u8 action
, INTERNAL_CMD
*io
)
3597 MpiRaidActionRequest_t
*pReq
;
3601 in_isr
= in_interrupt();
3603 dprintk((MYIOC_s_WARN_FMT
"Internal raid request not allowed in ISR context!\n",
3608 /* Get and Populate a free Frame
3610 if ((mf
= mpt_get_msg_frame(hd
->ioc
->InternalCtx
, hd
->ioc
)) == NULL
) {
3611 ddvprintk((MYIOC_s_WARN_FMT
"_do_raid: no msg frames!\n",
3615 pReq
= (MpiRaidActionRequest_t
*)mf
;
3616 pReq
->Action
= action
;
3617 pReq
->Reserved1
= 0;
3618 pReq
->ChainOffset
= 0;
3619 pReq
->Function
= MPI_FUNCTION_RAID_ACTION
;
3620 pReq
->VolumeID
= io
->id
;
3621 pReq
->VolumeBus
= io
->bus
;
3622 pReq
->PhysDiskNum
= io
->physDiskNum
;
3624 pReq
->Reserved2
= 0;
3625 pReq
->ActionDataWord
= 0; /* Reserved for this action */
3626 //pReq->ActionDataSGE = 0;
3628 mpt_add_sge((char *)&pReq
->ActionDataSGE
,
3629 MPT_SGE_FLAGS_SSIMPLE_READ
| 0, (dma_addr_t
) -1);
3631 ddvprintk((MYIOC_s_INFO_FMT
"RAID Volume action %x id %d\n",
3632 hd
->ioc
->name
, action
, io
->id
));
3635 hd
->timer
.expires
= jiffies
+ HZ
*10; /* 10 second timeout */
3636 hd
->scandv_wait_done
= 0;
3638 /* Save cmd pointer, for resource free if timeout or
3643 add_timer(&hd
->timer
);
3644 mpt_put_msg_frame(hd
->ioc
->InternalCtx
, hd
->ioc
, mf
);
3645 wait_event(hd
->scandv_waitq
, hd
->scandv_wait_done
);
3647 if ((hd
->pLocal
== NULL
) || (hd
->pLocal
->completion
!= MPT_SCANDV_GOOD
))
3652 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
3654 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3656 * mptscsih_do_cmd - Do internal command.
3657 * @hd: MPT_SCSI_HOST pointer
3658 * @io: INTERNAL_CMD pointer.
3660 * Issue the specified internally generated command and do command
3661 * specific cleanup. For bus scan / DV only.
3662 * NOTES: If command is Inquiry and status is good,
3663 * initialize a target structure, save the data
3665 * Remark: Single threaded access only.
3668 * < 0 if an illegal command or no resources
3672 * > 0 if command complete but some type of completion error.
3675 mptscsih_do_cmd(MPT_SCSI_HOST
*hd
, INTERNAL_CMD
*io
)
3678 SCSIIORequest_t
*pScsiReq
;
3679 SCSIIORequest_t ReqCopy
;
3680 int my_idx
, ii
, dir
;
3684 char CDB
[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3687 in_isr
= in_interrupt();
3689 dprintk((MYIOC_s_WARN_FMT
"Internal SCSI IO request not allowed in ISR context!\n",
3695 /* Set command specific information
3700 dir
= MPI_SCSIIO_CONTROL_READ
;
3706 case TEST_UNIT_READY
:
3708 dir
= MPI_SCSIIO_CONTROL_READ
;
3714 dir
= MPI_SCSIIO_CONTROL_READ
;
3716 CDB
[4] = 1; /*Spin up the disk */
3724 dir
= MPI_SCSIIO_CONTROL_READ
;
3730 dir
= MPI_SCSIIO_CONTROL_READ
;
3732 if (io
->flags
& MPT_ICFLAG_ECHO
) {
3738 if (io
->flags
& MPT_ICFLAG_BUF_CAP
) {
3741 CDB
[6] = (io
->size
>> 16) & 0xFF;
3742 CDB
[7] = (io
->size
>> 8) & 0xFF;
3743 CDB
[8] = io
->size
& 0xFF;
3749 dir
= MPI_SCSIIO_CONTROL_WRITE
;
3751 if (io
->flags
& MPT_ICFLAG_ECHO
) {
3756 CDB
[6] = (io
->size
>> 16) & 0xFF;
3757 CDB
[7] = (io
->size
>> 8) & 0xFF;
3758 CDB
[8] = io
->size
& 0xFF;
3764 dir
= MPI_SCSIIO_CONTROL_READ
;
3771 dir
= MPI_SCSIIO_CONTROL_READ
;
3776 case SYNCHRONIZE_CACHE
:
3778 dir
= MPI_SCSIIO_CONTROL_READ
;
3780 // CDB[1] = 0x02; /* set immediate bit */
3789 /* Get and Populate a free Frame
3791 if ((mf
= mpt_get_msg_frame(hd
->ioc
->InternalCtx
, hd
->ioc
)) == NULL
) {
3792 ddvprintk((MYIOC_s_WARN_FMT
"No msg frames!\n",
3797 pScsiReq
= (SCSIIORequest_t
*) mf
;
3799 /* Get the request index */
3800 my_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
3801 ADD_INDEX_LOG(my_idx
); /* for debug */
3803 if (io
->flags
& MPT_ICFLAG_PHYS_DISK
) {
3804 pScsiReq
->TargetID
= io
->physDiskNum
;
3806 pScsiReq
->ChainOffset
= 0;
3807 pScsiReq
->Function
= MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH
;
3809 pScsiReq
->TargetID
= io
->id
;
3810 pScsiReq
->Bus
= io
->bus
;
3811 pScsiReq
->ChainOffset
= 0;
3812 pScsiReq
->Function
= MPI_FUNCTION_SCSI_IO_REQUEST
;
3815 pScsiReq
->CDBLength
= cmdLen
;
3816 pScsiReq
->SenseBufferLength
= MPT_SENSE_BUFFER_SIZE
;
3818 pScsiReq
->Reserved
= 0;
3820 pScsiReq
->MsgFlags
= mpt_msg_flags();
3821 /* MsgContext set in mpt_get_msg_fram call */
3823 for (ii
=0; ii
< 8; ii
++)
3824 pScsiReq
->LUN
[ii
] = 0;
3825 pScsiReq
->LUN
[1] = io
->lun
;
3827 if (io
->flags
& MPT_ICFLAG_TAGGED_CMD
)
3828 pScsiReq
->Control
= cpu_to_le32(dir
| MPI_SCSIIO_CONTROL_SIMPLEQ
);
3830 pScsiReq
->Control
= cpu_to_le32(dir
| MPI_SCSIIO_CONTROL_UNTAGGED
);
3832 if (cmd
== REQUEST_SENSE
) {
3833 pScsiReq
->Control
= cpu_to_le32(dir
| MPI_SCSIIO_CONTROL_UNTAGGED
);
3834 ddvprintk((MYIOC_s_INFO_FMT
"Untagged! 0x%2x\n",
3835 hd
->ioc
->name
, cmd
));
3838 for (ii
=0; ii
< 16; ii
++)
3839 pScsiReq
->CDB
[ii
] = CDB
[ii
];
3841 pScsiReq
->DataLength
= cpu_to_le32(io
->size
);
3842 pScsiReq
->SenseBufferLowAddr
= cpu_to_le32(hd
->ioc
->sense_buf_low_dma
3843 + (my_idx
* MPT_SENSE_BUFFER_ALLOC
));
3845 ddvprintk((MYIOC_s_INFO_FMT
"Sending Command 0x%x for (%d:%d:%d)\n",
3846 hd
->ioc
->name
, cmd
, io
->bus
, io
->id
, io
->lun
));
3848 if (dir
== MPI_SCSIIO_CONTROL_READ
) {
3849 mpt_add_sge((char *) &pScsiReq
->SGL
,
3850 MPT_SGE_FLAGS_SSIMPLE_READ
| io
->size
,
3853 mpt_add_sge((char *) &pScsiReq
->SGL
,
3854 MPT_SGE_FLAGS_SSIMPLE_WRITE
| io
->size
,
3858 /* The ISR will free the request frame, but we need
3859 * the information to initialize the target. Duplicate.
3861 memcpy(&ReqCopy
, pScsiReq
, sizeof(SCSIIORequest_t
));
3863 /* Issue this command after:
3866 * Wait until the reply has been received
3867 * ScsiScanDvCtx callback function will
3869 * set scandv_wait_done and call wake_up
3872 hd
->timer
.expires
= jiffies
+ HZ
*cmdTimeout
;
3873 hd
->scandv_wait_done
= 0;
3875 /* Save cmd pointer, for resource free if timeout or
3880 add_timer(&hd
->timer
);
3881 mpt_put_msg_frame(hd
->ioc
->InternalCtx
, hd
->ioc
, mf
);
3882 wait_event(hd
->scandv_waitq
, hd
->scandv_wait_done
);
3885 rc
= hd
->pLocal
->completion
;
3886 hd
->pLocal
->skip
= 0;
3888 /* Always set fatal error codes in some cases.
3890 if (rc
== MPT_SCANDV_SELECTION_TIMEOUT
)
3892 else if (rc
== MPT_SCANDV_SOME_ERROR
)
3896 /* This should never happen. */
3897 ddvprintk((MYIOC_s_INFO_FMT
"_do_cmd: Null pLocal!!!\n",
3904 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3906 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3907 * @hd: Pointer to MPT_SCSI_HOST structure
3908 * @portnum: IOC port number
3910 * Uses the ISR, but with special processing.
3911 * MUST be single-threaded.
3913 * Return: 0 on completion
3916 mptscsih_synchronize_cache(MPT_SCSI_HOST
*hd
, int portnum
)
3918 MPT_ADAPTER
*ioc
= hd
->ioc
;
3919 VirtDevice
*pTarget
;
3920 SCSIDevicePage1_t
*pcfg1Data
= NULL
;
3923 dma_addr_t cfg1_dma_addr
= -1;
3924 ConfigPageHeader_t header1
;
3928 int indexed_lun
, lun_index
;
3929 int hostId
= ioc
->pfacts
[portnum
].PortSCSIID
;
3931 int requested
, configuration
, data
;
3935 max_id
= ioc
->sh
->max_id
- 1;
3937 /* Following parameters will not change
3940 iocmd
.cmd
= SYNCHRONIZE_CACHE
;
3942 iocmd
.physDiskNum
= -1;
3944 iocmd
.data_dma
= -1;
3946 iocmd
.rsvd
= iocmd
.rsvd2
= 0;
3950 if (hd
->Targets
== NULL
)
3958 /* Write SDP1 for all SCSI devices
3959 * Alloc memory and set up config buffer
3961 if (ioc
->bus_type
== SCSI
) {
3962 if (ioc
->spi_data
.sdp1length
> 0) {
3963 pcfg1Data
= (SCSIDevicePage1_t
*)pci_alloc_consistent(ioc
->pcidev
,
3964 ioc
->spi_data
.sdp1length
* 4, &cfg1_dma_addr
);
3966 if (pcfg1Data
!= NULL
) {
3968 header1
.PageVersion
= ioc
->spi_data
.sdp1version
;
3969 header1
.PageLength
= ioc
->spi_data
.sdp1length
;
3970 header1
.PageNumber
= 1;
3971 header1
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_DEVICE
;
3973 cfg
.physAddr
= cfg1_dma_addr
;
3974 cfg
.action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
3981 /* loop through all devices on this port
3983 while (bus
< MPT_MAX_BUS
) {
3986 pTarget
= hd
->Targets
[(int)id
];
3990 /* Set the negotiation flags */
3991 if (pTarget
&& (pTarget
= hd
->Targets
[id
]) && !pTarget
->raidVolume
) {
3992 flags
= pTarget
->negoFlags
;
3994 flags
= hd
->ioc
->spi_data
.noQas
;
3995 if (hd
->ioc
->spi_data
.nvram
&& (hd
->ioc
->spi_data
.nvram
[id
] != MPT_HOST_NVRAM_INVALID
)) {
3996 data
= hd
->ioc
->spi_data
.nvram
[id
];
3998 if (data
& MPT_NVRAM_WIDE_DISABLE
)
3999 flags
|= MPT_TARGET_NO_NEGO_WIDE
;
4001 factor
= (data
& MPT_NVRAM_SYNC_MASK
) >> MPT_NVRAM_SYNC_SHIFT
;
4002 if ((factor
== 0) || (factor
== MPT_ASYNC
))
4003 flags
|= MPT_TARGET_NO_NEGO_SYNC
;
4007 /* Force to async, narrow */
4008 mptscsih_setDevicePage1Flags(0, MPT_ASYNC
, 0, &requested
,
4009 &configuration
, flags
);
4010 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
4011 "offset=0 negoFlags=%x request=%x config=%x\n",
4012 id
, flags
, requested
, configuration
));
4013 pcfg1Data
->RequestedParameters
= le32_to_cpu(requested
);
4014 pcfg1Data
->Reserved
= 0;
4015 pcfg1Data
->Configuration
= le32_to_cpu(configuration
);
4016 cfg
.pageAddr
= (bus
<<8) | id
;
4017 mpt_config(hd
->ioc
, &cfg
);
4020 /* If target Ptr NULL or if this target is NOT a disk, skip.
4022 if ((pTarget
) && (pTarget
->tflags
& MPT_TARGET_FLAGS_Q_YES
)){
4023 for (lun
=0; lun
<= MPT_LAST_LUN
; lun
++) {
4024 /* If LUN present, issue the command
4026 lun_index
= (lun
>> 5); /* 32 luns per lun_index */
4027 indexed_lun
= (lun
% 32);
4028 if (pTarget
->luns
[lun_index
] & (1<<indexed_lun
)) {
4030 (void) mptscsih_do_cmd(hd
, &iocmd
);
4035 /* get next relevant device */
4048 pci_free_consistent(ioc
->pcidev
, header1
.PageLength
* 4, pcfg1Data
, cfg1_dma_addr
);
4054 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4055 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4057 * mptscsih_domainValidation - Top level handler for domain validation.
4058 * @hd: Pointer to MPT_SCSI_HOST structure.
4060 * Uses the ISR, but with special processing.
4061 * Called from schedule, should not be in interrupt mode.
4062 * While thread alive, do dv for all devices needing dv
4067 mptscsih_domainValidation(void *arg
)
4071 unsigned long flags
;
4072 int id
, maxid
, dvStatus
, did
;
4075 spin_lock_irqsave(&dvtaskQ_lock
, flags
);
4077 if (dvtaskQ_release
) {
4079 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4082 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4084 /* For this ioc, loop through all devices and do dv to each device.
4085 * When complete with this ioc, search through the ioc list, and
4086 * for each scsi ioc found, do dv for all devices. Exit when no
4092 list_for_each_entry(ioc
, &ioc_list
, list
) {
4093 spin_lock_irqsave(&dvtaskQ_lock
, flags
);
4094 if (dvtaskQ_release
) {
4096 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4099 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4103 /* DV only to SCSI adapters */
4104 if (ioc
->bus_type
!= SCSI
)
4107 /* Make sure everything looks ok */
4108 if (ioc
->sh
== NULL
)
4111 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
4115 if ((ioc
->spi_data
.forceDv
& MPT_SCSICFG_RELOAD_IOC_PG3
) != 0) {
4116 mpt_read_ioc_pg_3(ioc
);
4117 if (ioc
->spi_data
.pIocPg3
) {
4118 Ioc3PhysDisk_t
*pPDisk
= ioc
->spi_data
.pIocPg3
->PhysDisk
;
4119 int numPDisk
= ioc
->spi_data
.pIocPg3
->NumPhysDisks
;
4122 if (ioc
->spi_data
.dvStatus
[pPDisk
->PhysDiskID
] & MPT_SCSICFG_DV_NOT_DONE
)
4123 ioc
->spi_data
.dvStatus
[pPDisk
->PhysDiskID
] |= MPT_SCSICFG_NEED_DV
;
4129 ioc
->spi_data
.forceDv
&= ~MPT_SCSICFG_RELOAD_IOC_PG3
;
4132 maxid
= min_t(int, ioc
->sh
->max_id
, MPT_MAX_SCSI_DEVICES
);
4134 for (id
= 0; id
< maxid
; id
++) {
4135 spin_lock_irqsave(&dvtaskQ_lock
, flags
);
4136 if (dvtaskQ_release
) {
4138 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4141 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4142 dvStatus
= hd
->ioc
->spi_data
.dvStatus
[id
];
4144 if (dvStatus
& MPT_SCSICFG_NEED_DV
) {
4146 hd
->ioc
->spi_data
.dvStatus
[id
] |= MPT_SCSICFG_DV_PENDING
;
4147 hd
->ioc
->spi_data
.dvStatus
[id
] &= ~MPT_SCSICFG_NEED_DV
;
4151 /* If hidden phys disk, block IO's to all
4153 * else, process normally
4155 isPhysDisk
= mptscsih_is_phys_disk(ioc
, id
);
4157 for (ii
=0; ii
< MPT_MAX_SCSI_DEVICES
; ii
++) {
4158 if (hd
->ioc
->spi_data
.isRaid
& (1 << ii
)) {
4159 hd
->ioc
->spi_data
.dvStatus
[ii
] |= MPT_SCSICFG_DV_PENDING
;
4164 if (mptscsih_doDv(hd
, 0, id
) == 1) {
4165 /* Untagged device was busy, try again
4167 hd
->ioc
->spi_data
.dvStatus
[id
] |= MPT_SCSICFG_NEED_DV
;
4168 hd
->ioc
->spi_data
.dvStatus
[id
] &= ~MPT_SCSICFG_DV_PENDING
;
4170 /* DV is complete. Clear flags.
4172 hd
->ioc
->spi_data
.dvStatus
[id
] &= ~(MPT_SCSICFG_DV_NOT_DONE
| MPT_SCSICFG_DV_PENDING
);
4176 for (ii
=0; ii
< MPT_MAX_SCSI_DEVICES
; ii
++) {
4177 if (hd
->ioc
->spi_data
.isRaid
& (1 << ii
)) {
4178 hd
->ioc
->spi_data
.dvStatus
[ii
] &= ~MPT_SCSICFG_DV_PENDING
;
4183 if (hd
->ioc
->spi_data
.noQas
)
4184 mptscsih_qas_check(hd
, id
);
4190 spin_lock_irqsave(&dvtaskQ_lock
, flags
);
4192 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4197 /* Search IOC page 3 to determine if this is hidden physical disk
4200 mptscsih_is_phys_disk(MPT_ADAPTER
*ioc
, int id
)
4202 if (ioc
->spi_data
.pIocPg3
) {
4203 Ioc3PhysDisk_t
*pPDisk
= ioc
->spi_data
.pIocPg3
->PhysDisk
;
4204 int numPDisk
= ioc
->spi_data
.pIocPg3
->NumPhysDisks
;
4207 if (pPDisk
->PhysDiskID
== id
) {
4217 /* Write SDP1 if no QAS has been enabled
4220 mptscsih_qas_check(MPT_SCSI_HOST
*hd
, int id
)
4222 VirtDevice
*pTarget
;
4225 if (hd
->Targets
== NULL
)
4228 for (ii
=0; ii
< MPT_MAX_SCSI_DEVICES
; ii
++) {
4232 if ((hd
->ioc
->spi_data
.dvStatus
[ii
] & MPT_SCSICFG_DV_NOT_DONE
) != 0)
4235 pTarget
= hd
->Targets
[ii
];
4237 if ((pTarget
!= NULL
) && (!pTarget
->raidVolume
)) {
4238 if ((pTarget
->negoFlags
& hd
->ioc
->spi_data
.noQas
) == 0) {
4239 pTarget
->negoFlags
|= hd
->ioc
->spi_data
.noQas
;
4240 dnegoprintk(("writeSDP1: id=%d flags=0\n", id
));
4241 mptscsih_writeSDP1(hd
, 0, ii
, 0);
4244 if (mptscsih_is_phys_disk(hd
->ioc
, ii
) == 1) {
4245 dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id
));
4246 mptscsih_writeSDP1(hd
, 0, ii
, MPT_SCSICFG_USE_NVRAM
);
4255 #define MPT_GET_NVRAM_VALS 0x01
4256 #define MPT_UPDATE_MAX 0x02
4257 #define MPT_SET_MAX 0x04
4258 #define MPT_SET_MIN 0x08
4259 #define MPT_FALLBACK 0x10
4260 #define MPT_SAVE 0x20
4262 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4264 * mptscsih_doDv - Perform domain validation to a target.
4265 * @hd: Pointer to MPT_SCSI_HOST structure.
4266 * @portnum: IOC port number.
4267 * @target: Physical ID of this target
4269 * Uses the ISR, but with special processing.
4270 * MUST be single-threaded.
4271 * Test will exit if target is at async & narrow.
4276 mptscsih_doDv(MPT_SCSI_HOST
*hd
, int bus_number
, int id
)
4278 MPT_ADAPTER
*ioc
= hd
->ioc
;
4279 VirtDevice
*pTarget
;
4280 SCSIDevicePage1_t
*pcfg1Data
;
4281 SCSIDevicePage0_t
*pcfg0Data
;
4285 dma_addr_t dvbuf_dma
= -1;
4286 dma_addr_t buf1_dma
= -1;
4287 dma_addr_t buf2_dma
= -1;
4288 dma_addr_t cfg1_dma_addr
= -1;
4289 dma_addr_t cfg0_dma_addr
= -1;
4290 ConfigPageHeader_t header1
;
4291 ConfigPageHeader_t header0
;
4298 int dataBufSize
= 0;
4299 int echoBufSize
= 0;
4304 int nfactor
= MPT_ULTRA320
;
4306 char doFallback
= 0;
4311 if (ioc
->spi_data
.sdp1length
== 0)
4314 if (ioc
->spi_data
.sdp0length
== 0)
4317 /* If multiple buses are used, require that the initiator
4318 * id be the same on all buses.
4320 if (id
== ioc
->pfacts
[0].PortSCSIID
)
4324 bus
= (u8
) bus_number
;
4325 ddvtprintk((MYIOC_s_NOTE_FMT
4326 "DV started: bus=%d, id=%d dv @ %p\n",
4327 ioc
->name
, bus
, id
, &dv
));
4329 /* Prep DV structure
4331 memset (&dv
, 0, sizeof(DVPARAMETERS
));
4334 /* Populate tmax with the current maximum
4335 * transfer parameters for this target.
4336 * Exit if narrow and async.
4338 dv
.cmd
= MPT_GET_NVRAM_VALS
;
4339 mptscsih_dv_parms(hd
, &dv
, NULL
);
4341 /* Prep SCSI IO structure
4347 iocmd
.physDiskNum
= -1;
4348 iocmd
.rsvd
= iocmd
.rsvd2
= 0;
4350 pTarget
= hd
->Targets
[id
];
4352 /* Use tagged commands if possible.
4355 if (pTarget
->tflags
& MPT_TARGET_FLAGS_Q_YES
)
4356 iocmd
.flags
|= MPT_ICFLAG_TAGGED_CMD
;
4358 if (hd
->ioc
->facts
.FWVersion
.Word
< 0x01000600)
4361 if ((hd
->ioc
->facts
.FWVersion
.Word
>= 0x01010000) &&
4362 (hd
->ioc
->facts
.FWVersion
.Word
< 0x01010B00))
4367 /* Prep cfg structure
4369 cfg
.pageAddr
= (bus
<<8) | id
;
4374 header0
.PageVersion
= ioc
->spi_data
.sdp0version
;
4375 header0
.PageLength
= ioc
->spi_data
.sdp0length
;
4376 header0
.PageNumber
= 0;
4377 header0
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_DEVICE
;
4381 header1
.PageVersion
= ioc
->spi_data
.sdp1version
;
4382 header1
.PageLength
= ioc
->spi_data
.sdp1length
;
4383 header1
.PageNumber
= 1;
4384 header1
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_DEVICE
;
4386 if (header0
.PageLength
& 1)
4387 dv_alloc
= (header0
.PageLength
* 4) + 4;
4389 dv_alloc
+= (2048 + (header1
.PageLength
* 4));
4391 pDvBuf
= pci_alloc_consistent(ioc
->pcidev
, dv_alloc
, &dvbuf_dma
);
4396 pbuf1
= (u8
*)pDvBuf
;
4397 buf1_dma
= dvbuf_dma
;
4400 pbuf2
= (u8
*) (pDvBuf
+ sz
);
4401 buf2_dma
= dvbuf_dma
+ sz
;
4404 pcfg0Data
= (SCSIDevicePage0_t
*) (pDvBuf
+ sz
);
4405 cfg0_dma_addr
= dvbuf_dma
+ sz
;
4406 sz
+= header0
.PageLength
* 4;
4410 if (header0
.PageLength
& 1)
4413 pcfg1Data
= (SCSIDevicePage1_t
*) (pDvBuf
+ sz
);
4414 cfg1_dma_addr
= dvbuf_dma
+ sz
;
4416 /* Skip this ID? Set cfg.hdr to force config page write
4419 ScsiCfgData
*pspi_data
= &hd
->ioc
->spi_data
;
4420 if (pspi_data
->nvram
&& (pspi_data
->nvram
[id
] != MPT_HOST_NVRAM_INVALID
)) {
4421 /* Set the factor from nvram */
4422 nfactor
= (pspi_data
->nvram
[id
] & MPT_NVRAM_SYNC_MASK
) >> 8;
4423 if (nfactor
< pspi_data
->minSyncFactor
)
4424 nfactor
= pspi_data
->minSyncFactor
;
4426 if (!(pspi_data
->nvram
[id
] & MPT_NVRAM_ID_SCAN_ENABLE
) ||
4427 (pspi_data
->PortFlags
== MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV
) ) {
4429 ddvprintk((MYIOC_s_NOTE_FMT
"DV Skipped: bus, id, lun (%d, %d, %d)\n",
4430 ioc
->name
, bus
, id
, lun
));
4432 dv
.cmd
= MPT_SET_MAX
;
4433 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
4436 /* Save the final negotiated settings to
4437 * SCSI device page 1.
4439 cfg
.physAddr
= cfg1_dma_addr
;
4440 cfg
.action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
4442 mpt_config(hd
->ioc
, &cfg
);
4448 /* Finish iocmd inititialization - hidden or visible disk? */
4449 if (ioc
->spi_data
.pIocPg3
) {
4450 /* Search IOC page 3 for matching id
4452 Ioc3PhysDisk_t
*pPDisk
= ioc
->spi_data
.pIocPg3
->PhysDisk
;
4453 int numPDisk
= ioc
->spi_data
.pIocPg3
->NumPhysDisks
;
4456 if (pPDisk
->PhysDiskID
== id
) {
4458 iocmd
.flags
|= MPT_ICFLAG_PHYS_DISK
;
4459 iocmd
.physDiskNum
= pPDisk
->PhysDiskNum
;
4463 if (mptscsih_do_raid(hd
, MPI_RAID_ACTION_QUIESCE_PHYS_IO
, &iocmd
) < 0) {
4464 ddvprintk((MYIOC_s_ERR_FMT
"RAID Queisce FAILED!\n", ioc
->name
));
4474 /* RAID Volume ID's may double for a physical device. If RAID but
4475 * not a physical ID as well, skip DV.
4477 if ((hd
->ioc
->spi_data
.isRaid
& (1 << id
)) && !(iocmd
.flags
& MPT_ICFLAG_PHYS_DISK
))
4482 * Async & Narrow - Inquiry
4483 * Async & Narrow - Inquiry
4484 * Maximum transfer rate - Inquiry
4486 * If compare, test complete.
4487 * If miscompare and first pass, repeat
4488 * If miscompare and not first pass, fall back and repeat
4492 sz
= SCSI_MAX_INQUIRY_BYTES
;
4493 rc
= MPT_SCANDV_GOOD
;
4495 ddvprintk((MYIOC_s_NOTE_FMT
"DV: Start Basic test on id=%d\n", ioc
->name
, id
));
4497 dv
.cmd
= MPT_SET_MIN
;
4498 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
4501 cfg
.physAddr
= cfg1_dma_addr
;
4502 cfg
.action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
4504 if (mpt_config(hd
->ioc
, &cfg
) != 0)
4507 /* Wide - narrow - wide workaround case
4509 if ((rc
== MPT_SCANDV_ISSUE_SENSE
) && dv
.max
.width
) {
4510 /* Send an untagged command to reset disk Qs corrupted
4511 * when a parity error occurs on a Request Sense.
4513 if ((hd
->ioc
->facts
.FWVersion
.Word
>= 0x01000600) ||
4514 ((hd
->ioc
->facts
.FWVersion
.Word
>= 0x01010000) &&
4515 (hd
->ioc
->facts
.FWVersion
.Word
< 0x01010B00)) ) {
4517 iocmd
.cmd
= REQUEST_SENSE
;
4518 iocmd
.data_dma
= buf1_dma
;
4521 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4524 if (hd
->pLocal
== NULL
)
4526 rc
= hd
->pLocal
->completion
;
4527 if ((rc
== MPT_SCANDV_GOOD
) || (rc
== MPT_SCANDV_SENSE
)) {
4537 iocmd
.cmd
= INQUIRY
;
4538 iocmd
.data_dma
= buf1_dma
;
4541 memset(pbuf1
, 0x00, sz
);
4542 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4545 if (hd
->pLocal
== NULL
)
4547 rc
= hd
->pLocal
->completion
;
4548 if (rc
== MPT_SCANDV_GOOD
) {
4549 if (hd
->pLocal
->scsiStatus
== SAM_STAT_BUSY
) {
4550 if ((iocmd
.flags
& MPT_ICFLAG_TAGGED_CMD
) == 0)
4557 } else if (rc
== MPT_SCANDV_SENSE
) {
4560 /* If first command doesn't complete
4561 * with a good status or with a check condition,
4568 /* Reset the size for disks
4570 inq0
= (*pbuf1
) & 0x1F;
4571 if ((inq0
== 0) && pTarget
&& !pTarget
->raidVolume
) {
4576 /* Another GEM workaround. Check peripheral device type,
4577 * if PROCESSOR, quit DV.
4579 if (inq0
== TYPE_PROCESSOR
) {
4580 mptscsih_initTarget(hd
,
4592 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4596 if ((pTarget
->maxWidth
== 1) && (pTarget
->maxOffset
) && (nfactor
< 0x0A)
4597 && (pTarget
->minSyncFactor
> 0x09)) {
4598 if ((pbuf1
[56] & 0x04) == 0)
4600 else if ((pbuf1
[56] & 0x01) == 1) {
4601 pTarget
->minSyncFactor
=
4602 nfactor
> MPT_ULTRA320
? nfactor
: MPT_ULTRA320
;
4604 pTarget
->minSyncFactor
=
4605 nfactor
> MPT_ULTRA160
? nfactor
: MPT_ULTRA160
;
4608 dv
.max
.factor
= pTarget
->minSyncFactor
;
4610 if ((pbuf1
[56] & 0x02) == 0) {
4611 pTarget
->negoFlags
|= MPT_TARGET_NO_NEGO_QAS
;
4612 hd
->ioc
->spi_data
.noQas
= MPT_TARGET_NO_NEGO_QAS
;
4613 ddvprintk((MYIOC_s_NOTE_FMT
4614 "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
4615 ioc
->name
, id
, pbuf1
[56]));
4621 dv
.cmd
= MPT_FALLBACK
;
4623 dv
.cmd
= MPT_SET_MAX
;
4625 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
4626 if (mpt_config(hd
->ioc
, &cfg
) != 0)
4629 if ((!dv
.now
.width
) && (!dv
.now
.offset
))
4632 iocmd
.cmd
= INQUIRY
;
4633 iocmd
.data_dma
= buf2_dma
;
4636 memset(pbuf2
, 0x00, sz
);
4637 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4639 else if (hd
->pLocal
== NULL
)
4642 /* Save the return code.
4643 * If this is the first pass,
4644 * read SCSI Device Page 0
4645 * and update the target max parameters.
4647 rc
= hd
->pLocal
->completion
;
4649 if (rc
== MPT_SCANDV_GOOD
) {
4655 cfg
.physAddr
= cfg0_dma_addr
;
4656 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
4659 if (mpt_config(hd
->ioc
, &cfg
) != 0)
4662 sdp0_info
= le32_to_cpu(pcfg0Data
->Information
) & 0x0E;
4663 sdp0_nego
= (le32_to_cpu(pcfg0Data
->NegotiatedParameters
) & 0xFF00 ) >> 8;
4665 /* Quantum and Fujitsu workarounds.
4666 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
4667 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
4668 * Resetart with a request for U160.
4670 if ((dv
.now
.factor
== MPT_ULTRA320
) && (sdp0_nego
== MPT_ULTRA2
)) {
4673 dv
.cmd
= MPT_UPDATE_MAX
;
4674 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg0Data
);
4675 /* Update the SCSI device page 1 area
4677 pcfg1Data
->RequestedParameters
= pcfg0Data
->NegotiatedParameters
;
4682 /* Quantum workaround. Restart this test will the fallback
4685 if (doFallback
== 0) {
4686 if (memcmp(pbuf1
, pbuf2
, sz
) != 0) {
4690 ddvprintk((MYIOC_s_NOTE_FMT
4691 "DV:Inquiry compared id=%d, calling initTarget\n", ioc
->name
, id
));
4692 hd
->ioc
->spi_data
.dvStatus
[id
] &= ~MPT_SCSICFG_DV_NOT_DONE
;
4693 mptscsih_initTarget(hd
,
4699 break; /* test complete */
4704 } else if (rc
== MPT_SCANDV_ISSUE_SENSE
)
4705 doFallback
= 1; /* set fallback flag */
4706 else if ((rc
== MPT_SCANDV_DID_RESET
) ||
4707 (rc
== MPT_SCANDV_SENSE
) ||
4708 (rc
== MPT_SCANDV_FALLBACK
))
4709 doFallback
= 1; /* set fallback flag */
4716 ddvprintk((MYIOC_s_NOTE_FMT
"DV: Basic test on id=%d completed OK.\n", ioc
->name
, id
));
4718 if (ioc
->spi_data
.mpt_dv
== 0)
4721 inq0
= (*pbuf1
) & 0x1F;
4723 /* Continue only for disks
4728 if ( ioc
->spi_data
.PortFlags
== MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY
)
4731 /* Start the Enhanced Test.
4732 * 0) issue TUR to clear out check conditions
4733 * 1) read capacity of echo (regular) buffer
4735 * 3) do write-read-compare data pattern test
4737 * 5) update nego parms to target struct
4740 cfg
.physAddr
= cfg1_dma_addr
;
4741 cfg
.action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
4744 iocmd
.cmd
= TEST_UNIT_READY
;
4745 iocmd
.data_dma
= -1;
4750 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4753 if (hd
->pLocal
== NULL
)
4756 rc
= hd
->pLocal
->completion
;
4757 if (rc
== MPT_SCANDV_GOOD
)
4759 else if (rc
== MPT_SCANDV_SENSE
) {
4760 u8 skey
= hd
->pLocal
->sense
[2] & 0x0F;
4761 u8 asc
= hd
->pLocal
->sense
[12];
4762 u8 ascq
= hd
->pLocal
->sense
[13];
4763 ddvprintk((MYIOC_s_INFO_FMT
4764 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4765 ioc
->name
, skey
, asc
, ascq
));
4767 if (skey
== UNIT_ATTENTION
)
4768 notDone
++; /* repeat */
4769 else if ((skey
== NOT_READY
) &&
4770 (asc
== 0x04)&&(ascq
== 0x01)) {
4771 /* wait then repeat */
4774 } else if ((skey
== NOT_READY
) && (asc
== 0x3A)) {
4775 /* no medium, try read test anyway */
4778 /* All other errors are fatal.
4780 ddvprintk((MYIOC_s_INFO_FMT
"DV: fatal error.",
4788 iocmd
.cmd
= READ_BUFFER
;
4789 iocmd
.data_dma
= buf1_dma
;
4792 iocmd
.flags
|= MPT_ICFLAG_BUF_CAP
;
4796 for (patt
= 0; patt
< 2; patt
++) {
4798 iocmd
.flags
|= MPT_ICFLAG_ECHO
;
4800 iocmd
.flags
&= ~MPT_ICFLAG_ECHO
;
4806 /* If not ready after 8 trials,
4807 * give up on this device.
4812 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4814 else if (hd
->pLocal
== NULL
)
4817 rc
= hd
->pLocal
->completion
;
4818 ddvprintk(("ReadBuffer Comp Code %d", rc
));
4819 ddvprintk((" buff: %0x %0x %0x %0x\n",
4820 pbuf1
[0], pbuf1
[1], pbuf1
[2], pbuf1
[3]));
4822 if (rc
== MPT_SCANDV_GOOD
) {
4824 if (iocmd
.flags
& MPT_ICFLAG_ECHO
) {
4825 bufsize
= ((pbuf1
[2] & 0x1F) <<8) | pbuf1
[3];
4827 bufsize
= pbuf1
[1]<<16 | pbuf1
[2]<<8 | pbuf1
[3];
4829 } else if (rc
== MPT_SCANDV_SENSE
) {
4830 u8 skey
= hd
->pLocal
->sense
[2] & 0x0F;
4831 u8 asc
= hd
->pLocal
->sense
[12];
4832 u8 ascq
= hd
->pLocal
->sense
[13];
4833 ddvprintk((MYIOC_s_INFO_FMT
4834 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4835 ioc
->name
, skey
, asc
, ascq
));
4836 if (skey
== ILLEGAL_REQUEST
) {
4838 } else if (skey
== UNIT_ATTENTION
) {
4839 notDone
++; /* repeat */
4840 } else if ((skey
== NOT_READY
) &&
4841 (asc
== 0x04)&&(ascq
== 0x01)) {
4842 /* wait then repeat */
4846 /* All other errors are fatal.
4848 ddvprintk((MYIOC_s_INFO_FMT
"DV: fatal error.",
4853 /* All other errors are fatal
4860 if (iocmd
.flags
& MPT_ICFLAG_ECHO
)
4861 echoBufSize
= bufsize
;
4863 dataBufSize
= bufsize
;
4866 iocmd
.flags
&= ~MPT_ICFLAG_BUF_CAP
;
4868 /* Use echo buffers if possible,
4869 * Exit if both buffers are 0.
4871 if (echoBufSize
> 0) {
4872 iocmd
.flags
|= MPT_ICFLAG_ECHO
;
4873 if (dataBufSize
> 0)
4874 bufsize
= min(echoBufSize
, dataBufSize
);
4876 bufsize
= echoBufSize
;
4877 } else if (dataBufSize
== 0)
4880 ddvprintk((MYIOC_s_INFO_FMT
"%s Buffer Capacity %d\n", ioc
->name
,
4881 (iocmd
.flags
& MPT_ICFLAG_ECHO
) ? "Echo" : " ", bufsize
));
4883 /* Data buffers for write-read-compare test max 1K.
4885 sz
= min(bufsize
, 1024);
4888 * On first pass, always issue a reserve.
4889 * On additional loops, only if a reset has occurred.
4890 * iocmd.flags indicates if echo or regular buffer
4892 for (patt
= 0; patt
< 4; patt
++) {
4893 ddvprintk(("Pattern %d\n", patt
));
4894 if ((iocmd
.flags
& MPT_ICFLAG_RESERVED
) && (iocmd
.flags
& MPT_ICFLAG_DID_RESET
)) {
4895 iocmd
.cmd
= TEST_UNIT_READY
;
4896 iocmd
.data_dma
= -1;
4899 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4902 iocmd
.cmd
= RELEASE
;
4903 iocmd
.data_dma
= -1;
4906 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4908 else if (hd
->pLocal
== NULL
)
4911 rc
= hd
->pLocal
->completion
;
4912 ddvprintk(("Release rc %d\n", rc
));
4913 if (rc
== MPT_SCANDV_GOOD
)
4914 iocmd
.flags
&= ~MPT_ICFLAG_RESERVED
;
4918 iocmd
.flags
&= ~MPT_ICFLAG_RESERVED
;
4920 iocmd
.flags
&= ~MPT_ICFLAG_DID_RESET
;
4923 while (repeat
&& (!(iocmd
.flags
& MPT_ICFLAG_RESERVED
))) {
4924 iocmd
.cmd
= RESERVE
;
4925 iocmd
.data_dma
= -1;
4928 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4930 else if (hd
->pLocal
== NULL
)
4933 rc
= hd
->pLocal
->completion
;
4934 if (rc
== MPT_SCANDV_GOOD
) {
4935 iocmd
.flags
|= MPT_ICFLAG_RESERVED
;
4936 } else if (rc
== MPT_SCANDV_SENSE
) {
4937 /* Wait if coming ready
4939 u8 skey
= hd
->pLocal
->sense
[2] & 0x0F;
4940 u8 asc
= hd
->pLocal
->sense
[12];
4941 u8 ascq
= hd
->pLocal
->sense
[13];
4942 ddvprintk((MYIOC_s_INFO_FMT
4943 "DV: Reserve Failed: ", ioc
->name
));
4944 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4947 if ((skey
== NOT_READY
) && (asc
== 0x04)&&
4949 /* wait then repeat */
4953 ddvprintk((MYIOC_s_INFO_FMT
4954 "DV: Reserved Failed.", ioc
->name
));
4958 ddvprintk((MYIOC_s_INFO_FMT
"DV: Reserved Failed.",
4965 mptscsih_fillbuf(pbuf1
, sz
, patt
, 1);
4966 iocmd
.cmd
= WRITE_BUFFER
;
4967 iocmd
.data_dma
= buf1_dma
;
4970 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4972 else if (hd
->pLocal
== NULL
)
4975 rc
= hd
->pLocal
->completion
;
4976 if (rc
== MPT_SCANDV_GOOD
)
4977 ; /* Issue read buffer */
4978 else if (rc
== MPT_SCANDV_DID_RESET
) {
4979 /* If using echo buffers, reset to data buffers.
4980 * Else do Fallback and restart
4981 * this test (re-issue reserve
4982 * because of bus reset).
4984 if ((iocmd
.flags
& MPT_ICFLAG_ECHO
) && (dataBufSize
>= bufsize
)) {
4985 iocmd
.flags
&= ~MPT_ICFLAG_ECHO
;
4987 dv
.cmd
= MPT_FALLBACK
;
4988 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
4990 if (mpt_config(hd
->ioc
, &cfg
) != 0)
4993 if ((!dv
.now
.width
) && (!dv
.now
.offset
))
4997 iocmd
.flags
|= MPT_ICFLAG_DID_RESET
;
5000 } else if (rc
== MPT_SCANDV_SENSE
) {
5001 /* Restart data test if UA, else quit.
5003 u8 skey
= hd
->pLocal
->sense
[2] & 0x0F;
5004 ddvprintk((MYIOC_s_INFO_FMT
5005 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc
->name
, skey
,
5006 hd
->pLocal
->sense
[12], hd
->pLocal
->sense
[13]));
5007 if (skey
== UNIT_ATTENTION
) {
5010 } else if (skey
== ILLEGAL_REQUEST
) {
5011 if (iocmd
.flags
& MPT_ICFLAG_ECHO
) {
5012 if (dataBufSize
>= bufsize
) {
5013 iocmd
.flags
&= ~MPT_ICFLAG_ECHO
;
5028 iocmd
.cmd
= READ_BUFFER
;
5029 iocmd
.data_dma
= buf2_dma
;
5032 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
5034 else if (hd
->pLocal
== NULL
)
5037 rc
= hd
->pLocal
->completion
;
5038 if (rc
== MPT_SCANDV_GOOD
) {
5039 /* If buffers compare,
5040 * go to next pattern,
5041 * else, do a fallback and restart
5042 * data transfer test.
5044 if (memcmp (pbuf1
, pbuf2
, sz
) == 0) {
5045 ; /* goto next pattern */
5047 /* Miscompare with Echo buffer, go to data buffer,
5048 * if that buffer exists.
5049 * Miscompare with Data buffer, check first 4 bytes,
5050 * some devices return capacity. Exit in this case.
5052 if (iocmd
.flags
& MPT_ICFLAG_ECHO
) {
5053 if (dataBufSize
>= bufsize
)
5054 iocmd
.flags
&= ~MPT_ICFLAG_ECHO
;
5058 if (dataBufSize
== (pbuf2
[1]<<16 | pbuf2
[2]<<8 | pbuf2
[3])) {
5059 /* Argh. Device returning wrong data.
5060 * Quit DV for this device.
5065 /* Had an actual miscompare. Slow down.*/
5066 dv
.cmd
= MPT_FALLBACK
;
5067 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
5069 if (mpt_config(hd
->ioc
, &cfg
) != 0)
5072 if ((!dv
.now
.width
) && (!dv
.now
.offset
))
5079 } else if (rc
== MPT_SCANDV_DID_RESET
) {
5080 /* Do Fallback and restart
5081 * this test (re-issue reserve
5082 * because of bus reset).
5084 dv
.cmd
= MPT_FALLBACK
;
5085 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
5087 if (mpt_config(hd
->ioc
, &cfg
) != 0)
5090 if ((!dv
.now
.width
) && (!dv
.now
.offset
))
5093 iocmd
.flags
|= MPT_ICFLAG_DID_RESET
;
5096 } else if (rc
== MPT_SCANDV_SENSE
) {
5097 /* Restart data test if UA, else quit.
5099 u8 skey
= hd
->pLocal
->sense
[2] & 0x0F;
5100 ddvprintk((MYIOC_s_INFO_FMT
5101 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc
->name
, skey
,
5102 hd
->pLocal
->sense
[12], hd
->pLocal
->sense
[13]));
5103 if (skey
== UNIT_ATTENTION
) {
5115 } /* --- end of patt loop ---- */
5118 if (iocmd
.flags
& MPT_ICFLAG_RESERVED
) {
5119 iocmd
.cmd
= RELEASE
;
5120 iocmd
.data_dma
= -1;
5123 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
5124 printk(MYIOC_s_INFO_FMT
"DV: Release failed. id %d",
5126 else if (hd
->pLocal
) {
5127 if (hd
->pLocal
->completion
== MPT_SCANDV_GOOD
)
5128 iocmd
.flags
&= ~MPT_ICFLAG_RESERVED
;
5130 printk(MYIOC_s_INFO_FMT
"DV: Release failed. id %d",
5136 /* Set if cfg1_dma_addr contents is valid
5138 if ((cfg
.hdr
!= NULL
) && (retcode
== 0)){
5139 /* If disk, not U320, disable QAS
5141 if ((inq0
== 0) && (dv
.now
.factor
> MPT_ULTRA320
)) {
5142 hd
->ioc
->spi_data
.noQas
= MPT_TARGET_NO_NEGO_QAS
;
5143 ddvprintk((MYIOC_s_NOTE_FMT
5144 "noQas set due to id=%d has factor=%x\n", ioc
->name
, id
, dv
.now
.factor
));
5148 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
5150 /* Double writes to SDP1 can cause problems,
5151 * skip save of the final negotiated settings to
5152 * SCSI device page 1.
5155 cfg.physAddr = cfg1_dma_addr;
5156 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5158 mpt_config(hd->ioc, &cfg);
5162 /* If this is a RAID Passthrough, enable internal IOs
5164 if (iocmd
.flags
& MPT_ICFLAG_PHYS_DISK
) {
5165 if (mptscsih_do_raid(hd
, MPI_RAID_ACTION_ENABLE_PHYS_IO
, &iocmd
) < 0)
5166 ddvprintk((MYIOC_s_ERR_FMT
"RAID Enable FAILED!\n", ioc
->name
));
5169 /* Done with the DV scan of the current target
5172 pci_free_consistent(ioc
->pcidev
, dv_alloc
, pDvBuf
, dvbuf_dma
);
5174 ddvtprintk((MYIOC_s_INFO_FMT
"DV Done id=%d\n",
5180 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5181 /* mptscsih_dv_parms - perform a variety of operations on the
5182 * parameters used for negotiation.
5183 * @hd: Pointer to a SCSI host.
5184 * @dv: Pointer to a structure that contains the maximum and current
5185 * negotiated parameters.
5188 mptscsih_dv_parms(MPT_SCSI_HOST
*hd
, DVPARAMETERS
*dv
,void *pPage
)
5190 VirtDevice
*pTarget
;
5191 SCSIDevicePage0_t
*pPage0
;
5192 SCSIDevicePage1_t
*pPage1
;
5193 int val
= 0, data
, configuration
;
5202 case MPT_GET_NVRAM_VALS
:
5203 ddvprintk((MYIOC_s_NOTE_FMT
"Getting NVRAM: ",
5205 /* Get the NVRAM values and save in tmax
5206 * If not an LVD bus, the adapter minSyncFactor has been
5207 * already throttled back.
5209 if ((hd
->Targets
)&&((pTarget
= hd
->Targets
[(int)id
]) != NULL
) && !pTarget
->raidVolume
) {
5210 width
= pTarget
->maxWidth
;
5211 offset
= pTarget
->maxOffset
;
5212 factor
= pTarget
->minSyncFactor
;
5213 negoFlags
= pTarget
->negoFlags
;
5215 if (hd
->ioc
->spi_data
.nvram
&& (hd
->ioc
->spi_data
.nvram
[id
] != MPT_HOST_NVRAM_INVALID
)) {
5216 data
= hd
->ioc
->spi_data
.nvram
[id
];
5217 width
= data
& MPT_NVRAM_WIDE_DISABLE
? 0 : 1;
5218 if ((offset
= hd
->ioc
->spi_data
.maxSyncOffset
) == 0)
5221 factor
= (data
& MPT_NVRAM_SYNC_MASK
) >> MPT_NVRAM_SYNC_SHIFT
;
5222 if ((factor
== 0) || (factor
== MPT_ASYNC
)){
5233 /* Set the negotiation flags */
5234 negoFlags
= hd
->ioc
->spi_data
.noQas
;
5236 negoFlags
|= MPT_TARGET_NO_NEGO_WIDE
;
5239 negoFlags
|= MPT_TARGET_NO_NEGO_SYNC
;
5242 /* limit by adapter capabilities */
5243 width
= min(width
, hd
->ioc
->spi_data
.maxBusWidth
);
5244 offset
= min(offset
, hd
->ioc
->spi_data
.maxSyncOffset
);
5245 factor
= max(factor
, hd
->ioc
->spi_data
.minSyncFactor
);
5247 /* Check Consistency */
5248 if (offset
&& (factor
< MPT_ULTRA2
) && !width
)
5249 factor
= MPT_ULTRA2
;
5251 dv
->max
.width
= width
;
5252 dv
->max
.offset
= offset
;
5253 dv
->max
.factor
= factor
;
5254 dv
->max
.flags
= negoFlags
;
5255 ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
5256 id
, width
, factor
, offset
, negoFlags
));
5259 case MPT_UPDATE_MAX
:
5260 ddvprintk((MYIOC_s_NOTE_FMT
5261 "Updating with SDP0 Data: ", hd
->ioc
->name
));
5262 /* Update tmax values with those from Device Page 0.*/
5263 pPage0
= (SCSIDevicePage0_t
*) pPage
;
5265 val
= cpu_to_le32(pPage0
->NegotiatedParameters
);
5266 dv
->max
.width
= val
& MPI_SCSIDEVPAGE0_NP_WIDE
? 1 : 0;
5267 dv
->max
.offset
= (val
&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK
) >> 16;
5268 dv
->max
.factor
= (val
&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK
) >> 8;
5271 dv
->now
.width
= dv
->max
.width
;
5272 dv
->now
.offset
= dv
->max
.offset
;
5273 dv
->now
.factor
= dv
->max
.factor
;
5274 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
5275 id
, dv
->now
.width
, dv
->now
.factor
, dv
->now
.offset
, dv
->now
.flags
));
5279 ddvprintk((MYIOC_s_NOTE_FMT
"Setting Max: ",
5281 /* Set current to the max values. Update the config page.*/
5282 dv
->now
.width
= dv
->max
.width
;
5283 dv
->now
.offset
= dv
->max
.offset
;
5284 dv
->now
.factor
= dv
->max
.factor
;
5285 dv
->now
.flags
= dv
->max
.flags
;
5287 pPage1
= (SCSIDevicePage1_t
*)pPage
;
5289 mptscsih_setDevicePage1Flags (dv
->now
.width
, dv
->now
.factor
,
5290 dv
->now
.offset
, &val
, &configuration
, dv
->now
.flags
);
5291 dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5292 id
, dv
->now
.width
, dv
->now
.factor
, dv
->now
.offset
, dv
->now
.flags
, val
, configuration
));
5293 pPage1
->RequestedParameters
= le32_to_cpu(val
);
5294 pPage1
->Reserved
= 0;
5295 pPage1
->Configuration
= le32_to_cpu(configuration
);
5298 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n",
5299 id
, dv
->now
.width
, dv
->now
.factor
, dv
->now
.offset
, dv
->now
.flags
, val
, configuration
));
5303 ddvprintk((MYIOC_s_NOTE_FMT
"Setting Min: ",
5305 /* Set page to asynchronous and narrow
5306 * Do not update now, breaks fallback routine. */
5310 negoFlags
= dv
->max
.flags
;
5312 pPage1
= (SCSIDevicePage1_t
*)pPage
;
5314 mptscsih_setDevicePage1Flags (width
, factor
,
5315 offset
, &val
, &configuration
, negoFlags
);
5316 dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5317 id
, width
, factor
, offset
, negoFlags
, val
, configuration
));
5318 pPage1
->RequestedParameters
= le32_to_cpu(val
);
5319 pPage1
->Reserved
= 0;
5320 pPage1
->Configuration
= le32_to_cpu(configuration
);
5322 ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
5323 id
, width
, factor
, offset
, val
, configuration
, negoFlags
));
5327 ddvprintk((MYIOC_s_NOTE_FMT
5328 "Fallback: Start: offset %d, factor %x, width %d \n",
5329 hd
->ioc
->name
, dv
->now
.offset
,
5330 dv
->now
.factor
, dv
->now
.width
));
5331 width
= dv
->now
.width
;
5332 offset
= dv
->now
.offset
;
5333 factor
= dv
->now
.factor
;
5334 if ((offset
) && (dv
->max
.width
)) {
5335 if (factor
< MPT_ULTRA160
)
5336 factor
= MPT_ULTRA160
;
5337 else if (factor
< MPT_ULTRA2
) {
5338 factor
= MPT_ULTRA2
;
5340 } else if ((factor
== MPT_ULTRA2
) && width
) {
5341 factor
= MPT_ULTRA2
;
5343 } else if (factor
< MPT_ULTRA
) {
5346 } else if ((factor
== MPT_ULTRA
) && width
) {
5348 } else if (factor
< MPT_FAST
) {
5351 } else if ((factor
== MPT_FAST
) && width
) {
5354 } else if (factor
< MPT_SCSI
) {
5357 } else if ((factor
== MPT_SCSI
) && width
) {
5365 } else if (offset
) {
5367 if (factor
< MPT_ULTRA
)
5369 else if (factor
< MPT_FAST
)
5371 else if (factor
< MPT_SCSI
)
5382 dv
->max
.flags
|= MPT_TARGET_NO_NEGO_QAS
;
5383 dv
->max
.flags
&= ~MPT_TAPE_NEGO_IDP
;
5385 dv
->now
.width
= width
;
5386 dv
->now
.offset
= offset
;
5387 dv
->now
.factor
= factor
;
5388 dv
->now
.flags
= dv
->max
.flags
;
5390 pPage1
= (SCSIDevicePage1_t
*)pPage
;
5392 mptscsih_setDevicePage1Flags (width
, factor
, offset
, &val
,
5393 &configuration
, dv
->now
.flags
);
5394 dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n",
5395 id
, width
, offset
, factor
, dv
->now
.flags
, val
, configuration
));
5397 pPage1
->RequestedParameters
= le32_to_cpu(val
);
5398 pPage1
->Reserved
= 0;
5399 pPage1
->Configuration
= le32_to_cpu(configuration
);
5402 ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
5403 id
, dv
->now
.offset
, dv
->now
.factor
, dv
->now
.width
, val
, configuration
));
5407 ddvprintk((MYIOC_s_NOTE_FMT
5408 "Saving to Target structure: ", hd
->ioc
->name
));
5409 ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
5410 id
, dv
->now
.width
, dv
->now
.factor
, dv
->now
.offset
, dv
->now
.flags
));
5412 /* Save these values to target structures
5413 * or overwrite nvram (phys disks only).
5416 if ((hd
->Targets
)&&((pTarget
= hd
->Targets
[(int)id
]) != NULL
) && !pTarget
->raidVolume
) {
5417 pTarget
->maxWidth
= dv
->now
.width
;
5418 pTarget
->maxOffset
= dv
->now
.offset
;
5419 pTarget
->minSyncFactor
= dv
->now
.factor
;
5420 pTarget
->negoFlags
= dv
->now
.flags
;
5422 /* Preserv all flags, use
5423 * read-modify-write algorithm
5425 if (hd
->ioc
->spi_data
.nvram
) {
5426 data
= hd
->ioc
->spi_data
.nvram
[id
];
5429 data
&= ~MPT_NVRAM_WIDE_DISABLE
;
5431 data
|= MPT_NVRAM_WIDE_DISABLE
;
5433 if (!dv
->now
.offset
)
5436 data
&= ~MPT_NVRAM_SYNC_MASK
;
5437 data
|= (dv
->now
.factor
<< MPT_NVRAM_SYNC_SHIFT
) & MPT_NVRAM_SYNC_MASK
;
5439 hd
->ioc
->spi_data
.nvram
[id
] = data
;
5446 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5447 /* mptscsih_fillbuf - fill a buffer with a special data pattern
5448 * cleanup. For bus scan only.
5450 * @buffer: Pointer to data buffer to be filled.
5451 * @size: Number of bytes to fill
5452 * @index: Pattern index
5453 * @width: bus width, 0 (8 bits) or 1 (16 bits)
5456 mptscsih_fillbuf(char *buffer
, int size
, int index
, int width
)
5467 /* Pattern: 0000 FFFF 0000 FFFF
5469 for (ii
=0; ii
< size
; ii
++, ptr
++) {
5476 /* Pattern: 00 FF 00 FF
5478 for (ii
=0; ii
< size
; ii
++, ptr
++) {
5489 /* Pattern: 5555 AAAA 5555 AAAA 5555
5491 for (ii
=0; ii
< size
; ii
++, ptr
++) {
5498 /* Pattern: 55 AA 55 AA 55
5500 for (ii
=0; ii
< size
; ii
++, ptr
++) {
5510 /* Pattern: 00 01 02 03 04 05
5513 for (ii
=0; ii
< size
; ii
++, ptr
++)
5519 /* Wide Pattern: FFFE 0001 FFFD 0002
5520 * ... 4000 DFFF 8000 EFFF
5523 for (ii
=0; ii
< size
/2; ii
++) {
5524 /* Create the base pattern
5527 /* every 64 (0x40) bytes flip the pattern
5528 * since we fill 2 bytes / iteration,
5529 * test for ii = 0x20
5535 *ptr
= (char)( (val
& 0xFF00) >> 8);
5537 *ptr
= (char)(val
& 0xFF);
5542 *ptr
= (char)( (val
& 0xFF00) >> 8);
5544 *ptr
= (char)(val
& 0xFF);
5550 /* Narrow Pattern: FE 01 FD 02 FB 04
5551 * .. 7F 80 01 FE 02 FD ... 80 7F
5554 for (ii
=0; ii
< size
; ii
++, ptr
++) {
5555 /* Base pattern - first 32 bytes
5562 *ptr
= (char) (~(1 << byte
));
5565 /* Flip the pattern every 32 bytes
5574 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5576 EXPORT_SYMBOL(mptscsih_remove
);
5577 EXPORT_SYMBOL(mptscsih_shutdown
);
5579 EXPORT_SYMBOL(mptscsih_suspend
);
5580 EXPORT_SYMBOL(mptscsih_resume
);
5582 EXPORT_SYMBOL(mptscsih_proc_info
);
5583 EXPORT_SYMBOL(mptscsih_info
);
5584 EXPORT_SYMBOL(mptscsih_qcmd
);
5585 EXPORT_SYMBOL(mptscsih_slave_alloc
);
5586 EXPORT_SYMBOL(mptscsih_slave_destroy
);
5587 EXPORT_SYMBOL(mptscsih_slave_configure
);
5588 EXPORT_SYMBOL(mptscsih_abort
);
5589 EXPORT_SYMBOL(mptscsih_dev_reset
);
5590 EXPORT_SYMBOL(mptscsih_bus_reset
);
5591 EXPORT_SYMBOL(mptscsih_host_reset
);
5592 EXPORT_SYMBOL(mptscsih_bios_param
);
5593 EXPORT_SYMBOL(mptscsih_io_done
);
5594 EXPORT_SYMBOL(mptscsih_taskmgmt_complete
);
5595 EXPORT_SYMBOL(mptscsih_scandv_complete
);
5596 EXPORT_SYMBOL(mptscsih_event_process
);
5597 EXPORT_SYMBOL(mptscsih_ioc_reset
);
5598 EXPORT_SYMBOL(mptscsih_store_queue_depth
);
5599 EXPORT_SYMBOL(mptscsih_timer_expired
);
5601 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/