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
;
1001 if (hd
->Targets
!= NULL
) {
1003 * Free pointer array.
1009 dprintk((MYIOC_s_INFO_FMT
1010 "Free'd ScsiLookup (%d) memory\n",
1011 hd
->ioc
->name
, sz1
));
1013 if (hd
->info_kbuf
!= NULL
)
1014 kfree(hd
->info_kbuf
);
1016 /* NULL the Scsi_Host pointer
1020 scsi_host_put(host
);
1026 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1028 * mptscsih_shutdown - reboot notifier
1032 mptscsih_shutdown(struct device
* dev
)
1034 MPT_ADAPTER
*ioc
= pci_get_drvdata(to_pci_dev(dev
));
1035 struct Scsi_Host
*host
= ioc
->sh
;
1041 hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
1043 /* Flush the cache of this adapter
1046 mptscsih_synchronize_cache(hd
, 0);
1051 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1053 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1058 mptscsih_suspend(struct pci_dev
*pdev
, pm_message_t state
)
1060 mptscsih_shutdown(&pdev
->dev
);
1061 return mpt_suspend(pdev
,state
);
1064 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1066 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1071 mptscsih_resume(struct pci_dev
*pdev
)
1073 MPT_ADAPTER
*ioc
= pci_get_drvdata(pdev
);
1074 struct Scsi_Host
*host
= ioc
->sh
;
1082 hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
1086 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1088 unsigned long lflags
;
1089 spin_lock_irqsave(&dvtaskQ_lock
, lflags
);
1090 if (!dvtaskQ_active
) {
1092 spin_unlock_irqrestore(&dvtaskQ_lock
, lflags
);
1093 INIT_WORK(&dvTaskQ_task
,
1094 mptscsih_domainValidation
, (void *) hd
);
1095 schedule_work(&dvTaskQ_task
);
1097 spin_unlock_irqrestore(&dvtaskQ_lock
, lflags
);
1106 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1108 * mptscsih_info - Return information about MPT adapter
1109 * @SChost: Pointer to Scsi_Host structure
1111 * (linux scsi_host_template.info routine)
1113 * Returns pointer to buffer where information was written.
1116 mptscsih_info(struct Scsi_Host
*SChost
)
1121 h
= (MPT_SCSI_HOST
*)SChost
->hostdata
;
1124 if (h
->info_kbuf
== NULL
)
1125 if ((h
->info_kbuf
= kmalloc(0x1000 /* 4Kb */, GFP_KERNEL
)) == NULL
)
1126 return h
->info_kbuf
;
1127 h
->info_kbuf
[0] = '\0';
1129 mpt_print_ioc_summary(h
->ioc
, h
->info_kbuf
, &size
, 0, 0);
1130 h
->info_kbuf
[size
-1] = '\0';
1133 return h
->info_kbuf
;
1144 mptscsih_copy_mem_info(struct info_str
*info
, char *data
, int len
)
1146 if (info
->pos
+ len
> info
->length
)
1147 len
= info
->length
- info
->pos
;
1149 if (info
->pos
+ len
< info
->offset
) {
1154 if (info
->pos
< info
->offset
) {
1155 data
+= (info
->offset
- info
->pos
);
1156 len
-= (info
->offset
- info
->pos
);
1160 memcpy(info
->buffer
+ info
->pos
, data
, len
);
1166 mptscsih_copy_info(struct info_str
*info
, char *fmt
, ...)
1172 va_start(args
, fmt
);
1173 len
= vsprintf(buf
, fmt
, args
);
1176 mptscsih_copy_mem_info(info
, buf
, len
);
1181 mptscsih_host_info(MPT_ADAPTER
*ioc
, char *pbuf
, off_t offset
, int len
)
1183 struct info_str info
;
1187 info
.offset
= offset
;
1190 mptscsih_copy_info(&info
, "%s: %s, ", ioc
->name
, ioc
->prod_name
);
1191 mptscsih_copy_info(&info
, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING
, ioc
->facts
.FWVersion
.Word
);
1192 mptscsih_copy_info(&info
, "Ports=%d, ", ioc
->facts
.NumberOfPorts
);
1193 mptscsih_copy_info(&info
, "MaxQ=%d\n", ioc
->req_depth
);
1195 return ((info
.pos
> info
.offset
) ? info
.pos
- info
.offset
: 0);
1198 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1200 * mptscsih_proc_info - Return information about MPT adapter
1202 * (linux scsi_host_template.info routine)
1204 * buffer: if write, user data; if read, buffer for user
1205 * length: if write, return length;
1206 * offset: if write, 0; if read, the current offset into the buffer from
1207 * the previous read.
1208 * hostno: scsi host number
1209 * func: if write = 1; if read = 0
1212 mptscsih_proc_info(struct Scsi_Host
*host
, char *buffer
, char **start
, off_t offset
,
1213 int length
, int func
)
1215 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
1216 MPT_ADAPTER
*ioc
= hd
->ioc
;
1221 * write is not supported
1227 size
= mptscsih_host_info(ioc
, buffer
, offset
, length
);
1233 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1234 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1236 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1238 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1239 * @SCpnt: Pointer to scsi_cmnd structure
1240 * @done: Pointer SCSI mid-layer IO completion function
1242 * (linux scsi_host_template.queuecommand routine)
1243 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1244 * from a linux scsi_cmnd request and send it to the IOC.
1246 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1249 mptscsih_qcmd(struct scsi_cmnd
*SCpnt
, void (*done
)(struct scsi_cmnd
*))
1253 SCSIIORequest_t
*pScsiReq
;
1254 VirtDevice
*pTarget
;
1264 hd
= (MPT_SCSI_HOST
*) SCpnt
->device
->host
->hostdata
;
1265 target
= SCpnt
->device
->id
;
1266 lun
= SCpnt
->device
->lun
;
1267 SCpnt
->scsi_done
= done
;
1269 pTarget
= hd
->Targets
[target
];
1271 dmfprintk((MYIOC_s_INFO_FMT
"qcmd: SCpnt=%p, done()=%p\n",
1272 (hd
&& hd
->ioc
) ? hd
->ioc
->name
: "ioc?", SCpnt
, done
));
1274 if (hd
->resetPending
) {
1275 dtmprintk((MYIOC_s_WARN_FMT
"qcmd: SCpnt=%p timeout + 60HZ\n",
1276 (hd
&& hd
->ioc
) ? hd
->ioc
->name
: "ioc?", SCpnt
));
1277 return SCSI_MLQUEUE_HOST_BUSY
;
1281 * Put together a MPT SCSI request...
1283 if ((mf
= mpt_get_msg_frame(hd
->ioc
->DoneCtx
, hd
->ioc
)) == NULL
) {
1284 dprintk((MYIOC_s_WARN_FMT
"QueueCmd, no msg frames!!\n",
1286 return SCSI_MLQUEUE_HOST_BUSY
;
1289 pScsiReq
= (SCSIIORequest_t
*) mf
;
1291 my_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
1293 ADD_INDEX_LOG(my_idx
);
1295 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1296 * Seems we may receive a buffer (datalen>0) even when there
1297 * will be no data transfer! GRRRRR...
1299 if (SCpnt
->sc_data_direction
== DMA_FROM_DEVICE
) {
1300 datalen
= SCpnt
->request_bufflen
;
1301 scsidir
= MPI_SCSIIO_CONTROL_READ
; /* DATA IN (host<--ioc<--dev) */
1302 } else if (SCpnt
->sc_data_direction
== DMA_TO_DEVICE
) {
1303 datalen
= SCpnt
->request_bufflen
;
1304 scsidir
= MPI_SCSIIO_CONTROL_WRITE
; /* DATA OUT (host-->ioc-->dev) */
1307 scsidir
= MPI_SCSIIO_CONTROL_NODATATRANSFER
;
1310 /* Default to untagged. Once a target structure has been allocated,
1311 * use the Inquiry data to determine if device supports tagged.
1314 && (pTarget
->tflags
& MPT_TARGET_FLAGS_Q_YES
)
1315 && (SCpnt
->device
->tagged_supported
)) {
1316 scsictl
= scsidir
| MPI_SCSIIO_CONTROL_SIMPLEQ
;
1318 scsictl
= scsidir
| MPI_SCSIIO_CONTROL_UNTAGGED
;
1321 /* Use the above information to set up the message frame
1323 pScsiReq
->TargetID
= (u8
) target
;
1324 pScsiReq
->Bus
= (u8
) SCpnt
->device
->channel
;
1325 pScsiReq
->ChainOffset
= 0;
1326 pScsiReq
->Function
= MPI_FUNCTION_SCSI_IO_REQUEST
;
1327 pScsiReq
->CDBLength
= SCpnt
->cmd_len
;
1328 pScsiReq
->SenseBufferLength
= MPT_SENSE_BUFFER_SIZE
;
1329 pScsiReq
->Reserved
= 0;
1330 pScsiReq
->MsgFlags
= mpt_msg_flags();
1331 pScsiReq
->LUN
[0] = 0;
1332 pScsiReq
->LUN
[1] = lun
;
1333 pScsiReq
->LUN
[2] = 0;
1334 pScsiReq
->LUN
[3] = 0;
1335 pScsiReq
->LUN
[4] = 0;
1336 pScsiReq
->LUN
[5] = 0;
1337 pScsiReq
->LUN
[6] = 0;
1338 pScsiReq
->LUN
[7] = 0;
1339 pScsiReq
->Control
= cpu_to_le32(scsictl
);
1342 * Write SCSI CDB into the message
1344 cmd_len
= SCpnt
->cmd_len
;
1345 for (ii
=0; ii
< cmd_len
; ii
++)
1346 pScsiReq
->CDB
[ii
] = SCpnt
->cmnd
[ii
];
1348 for (ii
=cmd_len
; ii
< 16; ii
++)
1349 pScsiReq
->CDB
[ii
] = 0;
1352 pScsiReq
->DataLength
= cpu_to_le32(datalen
);
1354 /* SenseBuffer low address */
1355 pScsiReq
->SenseBufferLowAddr
= cpu_to_le32(hd
->ioc
->sense_buf_low_dma
1356 + (my_idx
* MPT_SENSE_BUFFER_ALLOC
));
1358 /* Now add the SG list
1359 * Always have a SGE even if null length.
1362 /* Add a NULL SGE */
1363 mptscsih_add_sge((char *)&pScsiReq
->SGL
, MPT_SGE_FLAGS_SSIMPLE_READ
| 0,
1366 /* Add a 32 or 64 bit SGE */
1367 if (mptscsih_AddSGE(hd
->ioc
, SCpnt
, pScsiReq
, my_idx
) != SUCCESS
)
1371 hd
->ScsiLookup
[my_idx
] = SCpnt
;
1372 SCpnt
->host_scribble
= NULL
;
1374 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1375 if (hd
->ioc
->bus_type
== SCSI
) {
1376 int dvStatus
= hd
->ioc
->spi_data
.dvStatus
[target
];
1379 if (dvStatus
|| hd
->ioc
->spi_data
.forceDv
) {
1381 if ((dvStatus
& MPT_SCSICFG_NEED_DV
) ||
1382 (hd
->ioc
->spi_data
.forceDv
& MPT_SCSICFG_NEED_DV
)) {
1383 unsigned long lflags
;
1384 /* Schedule DV if necessary */
1385 spin_lock_irqsave(&dvtaskQ_lock
, lflags
);
1386 if (!dvtaskQ_active
) {
1388 spin_unlock_irqrestore(&dvtaskQ_lock
, lflags
);
1389 INIT_WORK(&dvTaskQ_task
, mptscsih_domainValidation
, (void *) hd
);
1391 schedule_work(&dvTaskQ_task
);
1393 spin_unlock_irqrestore(&dvtaskQ_lock
, lflags
);
1395 hd
->ioc
->spi_data
.forceDv
&= ~MPT_SCSICFG_NEED_DV
;
1398 /* Trying to do DV to this target, extend timeout.
1399 * Wait to issue until flag is clear
1401 if (dvStatus
& MPT_SCSICFG_DV_PENDING
) {
1402 mod_timer(&SCpnt
->eh_timeout
, jiffies
+ 40 * HZ
);
1406 /* Set the DV flags.
1408 if (dvStatus
& MPT_SCSICFG_DV_NOT_DONE
)
1409 mptscsih_set_dvflags(hd
, pScsiReq
);
1417 mpt_put_msg_frame(hd
->ioc
->DoneCtx
, hd
->ioc
, mf
);
1418 dmfprintk((MYIOC_s_INFO_FMT
"Issued SCSI cmd (%p) mf=%p idx=%d\n",
1419 hd
->ioc
->name
, SCpnt
, mf
, my_idx
));
1420 DBG_DUMP_REQUEST_FRAME(mf
)
1424 mptscsih_freeChainBuffers(hd
->ioc
, my_idx
);
1425 mpt_free_msg_frame(hd
->ioc
, mf
);
1426 return SCSI_MLQUEUE_HOST_BUSY
;
1429 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1431 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1432 * with a SCSI IO request
1433 * @hd: Pointer to the MPT_SCSI_HOST instance
1434 * @req_idx: Index of the SCSI IO request frame.
1436 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1440 mptscsih_freeChainBuffers(MPT_ADAPTER
*ioc
, int req_idx
)
1442 MPT_FRAME_HDR
*chain
;
1443 unsigned long flags
;
1447 /* Get the first chain index and reset
1450 chain_idx
= ioc
->ReqToChain
[req_idx
];
1451 ioc
->ReqToChain
[req_idx
] = MPT_HOST_NO_CHAIN
;
1453 while (chain_idx
!= MPT_HOST_NO_CHAIN
) {
1455 /* Save the next chain buffer index */
1456 next
= ioc
->ChainToChain
[chain_idx
];
1458 /* Free this chain buffer and reset
1461 ioc
->ChainToChain
[chain_idx
] = MPT_HOST_NO_CHAIN
;
1463 chain
= (MPT_FRAME_HDR
*) (ioc
->ChainBuffer
1464 + (chain_idx
* ioc
->req_sz
));
1466 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
1467 list_add_tail(&chain
->u
.frame
.linkage
.list
, &ioc
->FreeChainQ
);
1468 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
1470 dmfprintk((MYIOC_s_INFO_FMT
"FreeChainBuffers (index %d)\n",
1471 ioc
->name
, chain_idx
));
1479 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1484 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1486 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1487 * Fall through to mpt_HardResetHandler if: not operational, too many
1488 * failed TM requests or handshake failure.
1490 * @ioc: Pointer to MPT_ADAPTER structure
1491 * @type: Task Management type
1492 * @target: Logical Target ID for reset (if appropriate)
1493 * @lun: Logical Unit for reset (if appropriate)
1494 * @ctx2abort: Context for the task to be aborted (if appropriate)
1496 * Remark: Currently invoked from a non-interrupt thread (_bh).
1498 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1501 * Returns 0 for SUCCESS or -1 if FAILED.
1504 mptscsih_TMHandler(MPT_SCSI_HOST
*hd
, u8 type
, u8 channel
, u8 target
, u8 lun
, int ctx2abort
, ulong timeout
)
1510 unsigned long flags
;
1512 /* If FW is being reloaded currently, return success to
1513 * the calling function.
1520 printk(KERN_ERR MYNAM
" TMHandler" " NULL ioc!\n");
1523 dtmprintk((MYIOC_s_INFO_FMT
"TMHandler Entered!\n", ioc
->name
));
1525 // SJR - CHECKME - Can we avoid this here?
1526 // (mpt_HardResetHandler has this check...)
1527 spin_lock_irqsave(&ioc
->diagLock
, flags
);
1528 if ((ioc
->diagPending
) || (ioc
->alt_ioc
&& ioc
->alt_ioc
->diagPending
)) {
1529 spin_unlock_irqrestore(&ioc
->diagLock
, flags
);
1532 spin_unlock_irqrestore(&ioc
->diagLock
, flags
);
1534 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1535 * If we time out and not bus reset, then we return a FAILED status to the caller.
1536 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1537 * successful. Otherwise, reload the FW.
1539 if (mptscsih_tm_pending_wait(hd
) == FAILED
) {
1540 if (type
== MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK
) {
1541 dtmprintk((KERN_WARNING MYNAM
": %s: TMHandler abort: "
1542 "Timed out waiting for last TM (%d) to complete! \n",
1543 hd
->ioc
->name
, hd
->tmPending
));
1545 } else if (type
== MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET
) {
1546 dtmprintk((KERN_WARNING MYNAM
": %s: TMHandler target reset: "
1547 "Timed out waiting for last TM (%d) to complete! \n",
1548 hd
->ioc
->name
, hd
->tmPending
));
1550 } else if (type
== MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
) {
1551 dtmprintk((KERN_WARNING MYNAM
": %s: TMHandler bus reset: "
1552 "Timed out waiting for last TM (%d) to complete! \n",
1553 hd
->ioc
->name
, hd
->tmPending
));
1554 if (hd
->tmPending
& (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
))
1560 spin_lock_irqsave(&hd
->ioc
->FreeQlock
, flags
);
1561 hd
->tmPending
|= (1 << type
);
1562 spin_unlock_irqrestore(&hd
->ioc
->FreeQlock
, flags
);
1567 ioc_raw_state
= mpt_GetIocState(hd
->ioc
, 0);
1569 #ifdef MPT_DEBUG_RESET
1570 if ((ioc_raw_state
& MPI_IOC_STATE_MASK
) != MPI_IOC_STATE_OPERATIONAL
) {
1571 printk(MYIOC_s_WARN_FMT
1572 "TM Handler: IOC Not operational(0x%x)!\n",
1573 hd
->ioc
->name
, ioc_raw_state
);
1577 if (doTask
&& ((ioc_raw_state
& MPI_IOC_STATE_MASK
) == MPI_IOC_STATE_OPERATIONAL
)
1578 && !(ioc_raw_state
& MPI_DOORBELL_ACTIVE
)) {
1580 /* Isse the Task Mgmt request.
1582 if (hd
->hard_resets
< -1)
1584 rc
= mptscsih_IssueTaskMgmt(hd
, type
, channel
, target
, lun
, ctx2abort
, timeout
);
1586 printk(MYIOC_s_INFO_FMT
"Issue of TaskMgmt failed!\n", hd
->ioc
->name
);
1588 dtmprintk((MYIOC_s_INFO_FMT
"Issue of TaskMgmt Successful!\n", hd
->ioc
->name
));
1592 /* Only fall through to the HRH if this is a bus reset
1594 if ((type
== MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
) && (rc
||
1595 ioc
->reload_fw
|| (ioc
->alt_ioc
&& ioc
->alt_ioc
->reload_fw
))) {
1596 dtmprintk((MYIOC_s_INFO_FMT
"Calling HardReset! \n",
1598 rc
= mpt_HardResetHandler(hd
->ioc
, CAN_SLEEP
);
1601 dtmprintk((MYIOC_s_INFO_FMT
"TMHandler rc = %d!\n", hd
->ioc
->name
, rc
));
1607 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1609 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1610 * @hd: Pointer to MPT_SCSI_HOST structure
1611 * @type: Task Management type
1612 * @target: Logical Target ID for reset (if appropriate)
1613 * @lun: Logical Unit for reset (if appropriate)
1614 * @ctx2abort: Context for the task to be aborted (if appropriate)
1616 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1617 * or a non-interrupt thread. In the former, must not call schedule().
1619 * Not all fields are meaningfull for all task types.
1621 * Returns 0 for SUCCESS, -999 for "no msg frames",
1622 * else other non-zero value returned.
1625 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST
*hd
, u8 type
, u8 channel
, u8 target
, u8 lun
, int ctx2abort
, ulong timeout
)
1628 SCSITaskMgmt_t
*pScsiTm
;
1632 /* Return Fail to calling function if no message frames available.
1634 if ((mf
= mpt_get_msg_frame(hd
->ioc
->TaskCtx
, hd
->ioc
)) == NULL
) {
1635 dfailprintk((MYIOC_s_ERR_FMT
"IssueTaskMgmt, no msg frames!!\n",
1640 dtmprintk((MYIOC_s_INFO_FMT
"IssueTaskMgmt request @ %p\n",
1641 hd
->ioc
->name
, mf
));
1643 /* Format the Request
1645 pScsiTm
= (SCSITaskMgmt_t
*) mf
;
1646 pScsiTm
->TargetID
= target
;
1647 pScsiTm
->Bus
= channel
;
1648 pScsiTm
->ChainOffset
= 0;
1649 pScsiTm
->Function
= MPI_FUNCTION_SCSI_TASK_MGMT
;
1651 pScsiTm
->Reserved
= 0;
1652 pScsiTm
->TaskType
= type
;
1653 pScsiTm
->Reserved1
= 0;
1654 pScsiTm
->MsgFlags
= (type
== MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
)
1655 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION
: 0;
1657 for (ii
= 0; ii
< 8; ii
++) {
1658 pScsiTm
->LUN
[ii
] = 0;
1660 pScsiTm
->LUN
[1] = lun
;
1662 for (ii
=0; ii
< 7; ii
++)
1663 pScsiTm
->Reserved2
[ii
] = 0;
1665 pScsiTm
->TaskMsgContext
= ctx2abort
;
1667 dtmprintk((MYIOC_s_INFO_FMT
1668 "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1669 hd
->ioc
->name
, ctx2abort
, type
));
1671 DBG_DUMP_TM_REQUEST_FRAME((u32
*)pScsiTm
);
1673 if ((retval
= mpt_send_handshake_request(hd
->ioc
->TaskCtx
, hd
->ioc
,
1674 sizeof(SCSITaskMgmt_t
), (u32
*)pScsiTm
,
1676 dfailprintk((MYIOC_s_ERR_FMT
"_send_handshake FAILED!"
1677 " (hd %p, ioc %p, mf %p) \n", hd
->ioc
->name
, hd
,
1679 mpt_free_msg_frame(hd
->ioc
, mf
);
1683 if(mptscsih_tm_wait_for_completion(hd
, timeout
) == FAILED
) {
1684 dfailprintk((MYIOC_s_ERR_FMT
"_wait_for_completion FAILED!"
1685 " (hd %p, ioc %p, mf %p) \n", hd
->ioc
->name
, hd
,
1687 mpt_free_msg_frame(hd
->ioc
, mf
);
1688 dtmprintk((MYIOC_s_INFO_FMT
"Calling HardReset! \n",
1690 retval
= mpt_HardResetHandler(hd
->ioc
, CAN_SLEEP
);
1696 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1698 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1699 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1701 * (linux scsi_host_template.eh_abort_handler routine)
1703 * Returns SUCCESS or FAILED.
1706 mptscsih_abort(struct scsi_cmnd
* SCpnt
)
1713 spinlock_t
*host_lock
= SCpnt
->device
->host
->host_lock
;
1715 /* If we can't locate our host adapter structure, return FAILED status.
1717 if ((hd
= (MPT_SCSI_HOST
*) SCpnt
->device
->host
->hostdata
) == NULL
) {
1718 SCpnt
->result
= DID_RESET
<< 16;
1719 SCpnt
->scsi_done(SCpnt
);
1720 dfailprintk((KERN_WARNING MYNAM
": mptscsih_abort: "
1721 "Can't locate host! (sc=%p)\n",
1727 if (hd
->resetPending
)
1730 printk(KERN_WARNING MYNAM
": %s: >> Attempting task abort! (sc=%p)\n",
1731 hd
->ioc
->name
, SCpnt
);
1733 if (hd
->timeouts
< -1)
1736 /* Find this command
1738 if ((scpnt_idx
= SCPNT_TO_LOOKUP_IDX(SCpnt
)) < 0) {
1739 /* Cmd not found in ScsiLookup.
1742 SCpnt
->result
= DID_RESET
<< 16;
1743 dtmprintk((KERN_WARNING MYNAM
": %s: mptscsih_abort: "
1744 "Command not in the active list! (sc=%p)\n",
1745 hd
->ioc
->name
, SCpnt
));
1749 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1750 * (the IO to be ABORT'd)
1752 * NOTE: Since we do not byteswap MsgContext, we do not
1753 * swap it here either. It is an opaque cookie to
1754 * the controller, so it does not matter. -DaveM
1756 mf
= MPT_INDEX_2_MFPTR(hd
->ioc
, scpnt_idx
);
1757 ctx2abort
= mf
->u
.frame
.hwhdr
.msgctxu
.MsgContext
;
1759 hd
->abortSCpnt
= SCpnt
;
1761 spin_unlock_irq(host_lock
);
1762 if (mptscsih_TMHandler(hd
, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK
,
1763 SCpnt
->device
->channel
, SCpnt
->device
->id
, SCpnt
->device
->lun
,
1764 ctx2abort
, 2 /* 2 second timeout */)
1767 /* The TM request failed and the subsequent FW-reload failed!
1770 printk(MYIOC_s_WARN_FMT
"Error issuing abort task! (sc=%p)\n",
1771 hd
->ioc
->name
, SCpnt
);
1773 /* We must clear our pending flag before clearing our state.
1776 hd
->tmState
= TM_STATE_NONE
;
1778 spin_lock_irq(host_lock
);
1780 /* Unmap the DMA buffers, if any. */
1781 if (SCpnt
->use_sg
) {
1782 pci_unmap_sg(ioc
->pcidev
, (struct scatterlist
*) SCpnt
->request_buffer
,
1783 SCpnt
->use_sg
, SCpnt
->sc_data_direction
);
1784 } else if (SCpnt
->request_bufflen
) {
1785 pci_unmap_single(ioc
->pcidev
, SCpnt
->SCp
.dma_handle
,
1786 SCpnt
->request_bufflen
, SCpnt
->sc_data_direction
);
1788 hd
->ScsiLookup
[scpnt_idx
] = NULL
;
1789 SCpnt
->result
= DID_RESET
<< 16;
1790 SCpnt
->scsi_done(SCpnt
); /* Issue the command callback */
1791 mptscsih_freeChainBuffers(ioc
, scpnt_idx
);
1792 mpt_free_msg_frame(ioc
, mf
);
1795 spin_lock_irq(host_lock
);
1799 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1801 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1802 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1804 * (linux scsi_host_template.eh_dev_reset_handler routine)
1806 * Returns SUCCESS or FAILED.
1809 mptscsih_dev_reset(struct scsi_cmnd
* SCpnt
)
1812 spinlock_t
*host_lock
= SCpnt
->device
->host
->host_lock
;
1814 /* If we can't locate our host adapter structure, return FAILED status.
1816 if ((hd
= (MPT_SCSI_HOST
*) SCpnt
->device
->host
->hostdata
) == NULL
){
1817 dtmprintk((KERN_WARNING MYNAM
": mptscsih_dev_reset: "
1818 "Can't locate host! (sc=%p)\n",
1823 if (hd
->resetPending
)
1826 printk(KERN_WARNING MYNAM
": %s: >> Attempting target reset! (sc=%p)\n",
1827 hd
->ioc
->name
, SCpnt
);
1829 spin_unlock_irq(host_lock
);
1830 if (mptscsih_TMHandler(hd
, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET
,
1831 SCpnt
->device
->channel
, SCpnt
->device
->id
,
1832 0, 0, 5 /* 5 second timeout */)
1834 /* The TM request failed and the subsequent FW-reload failed!
1837 printk(MYIOC_s_WARN_FMT
"Error processing TaskMgmt request (sc=%p)\n",
1838 hd
->ioc
->name
, SCpnt
);
1840 hd
->tmState
= TM_STATE_NONE
;
1841 spin_lock_irq(host_lock
);
1844 spin_lock_irq(host_lock
);
1849 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1851 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1852 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1854 * (linux scsi_host_template.eh_bus_reset_handler routine)
1856 * Returns SUCCESS or FAILED.
1859 mptscsih_bus_reset(struct scsi_cmnd
* SCpnt
)
1862 spinlock_t
*host_lock
= SCpnt
->device
->host
->host_lock
;
1864 /* If we can't locate our host adapter structure, return FAILED status.
1866 if ((hd
= (MPT_SCSI_HOST
*) SCpnt
->device
->host
->hostdata
) == NULL
){
1867 dtmprintk((KERN_WARNING MYNAM
": mptscsih_bus_reset: "
1868 "Can't locate host! (sc=%p)\n",
1873 printk(KERN_WARNING MYNAM
": %s: >> Attempting bus reset! (sc=%p)\n",
1874 hd
->ioc
->name
, SCpnt
);
1876 if (hd
->timeouts
< -1)
1879 /* We are now ready to execute the task management request. */
1880 spin_unlock_irq(host_lock
);
1881 if (mptscsih_TMHandler(hd
, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
,
1882 SCpnt
->device
->channel
, 0, 0, 0, 5 /* 5 second timeout */)
1885 /* The TM request failed and the subsequent FW-reload failed!
1888 printk(MYIOC_s_WARN_FMT
1889 "Error processing TaskMgmt request (sc=%p)\n",
1890 hd
->ioc
->name
, SCpnt
);
1892 hd
->tmState
= TM_STATE_NONE
;
1893 spin_lock_irq(host_lock
);
1896 spin_lock_irq(host_lock
);
1900 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1902 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
1904 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1906 * (linux scsi_host_template.eh_host_reset_handler routine)
1908 * Returns SUCCESS or FAILED.
1911 mptscsih_host_reset(struct scsi_cmnd
*SCpnt
)
1914 int status
= SUCCESS
;
1915 spinlock_t
*host_lock
= SCpnt
->device
->host
->host_lock
;
1917 /* If we can't locate the host to reset, then we failed. */
1918 if ((hd
= (MPT_SCSI_HOST
*) SCpnt
->device
->host
->hostdata
) == NULL
){
1919 dtmprintk( ( KERN_WARNING MYNAM
": mptscsih_host_reset: "
1920 "Can't locate host! (sc=%p)\n",
1925 printk(KERN_WARNING MYNAM
": %s: >> Attempting host reset! (sc=%p)\n",
1926 hd
->ioc
->name
, SCpnt
);
1928 /* If our attempts to reset the host failed, then return a failed
1929 * status. The host will be taken off line by the SCSI mid-layer.
1931 spin_unlock_irq(host_lock
);
1932 if (mpt_HardResetHandler(hd
->ioc
, CAN_SLEEP
) < 0){
1935 /* Make sure TM pending is cleared and TM state is set to
1939 hd
->tmState
= TM_STATE_NONE
;
1941 spin_lock_irq(host_lock
);
1944 dtmprintk( ( KERN_WARNING MYNAM
": mptscsih_host_reset: "
1946 (status
== SUCCESS
) ? "SUCCESS" : "FAILED" ) );
1951 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1953 * mptscsih_tm_pending_wait - wait for pending task management request to
1955 * @hd: Pointer to MPT host structure.
1957 * Returns {SUCCESS,FAILED}.
1960 mptscsih_tm_pending_wait(MPT_SCSI_HOST
* hd
)
1962 unsigned long flags
;
1963 int loop_count
= 4 * 10; /* Wait 10 seconds */
1964 int status
= FAILED
;
1967 spin_lock_irqsave(&hd
->ioc
->FreeQlock
, flags
);
1968 if (hd
->tmState
== TM_STATE_NONE
) {
1969 hd
->tmState
= TM_STATE_IN_PROGRESS
;
1972 spin_unlock_irqrestore(&hd
->ioc
->FreeQlock
, flags
);
1975 spin_unlock_irqrestore(&hd
->ioc
->FreeQlock
, flags
);
1977 } while (--loop_count
);
1982 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1984 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1985 * @hd: Pointer to MPT host structure.
1987 * Returns {SUCCESS,FAILED}.
1990 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST
* hd
, ulong timeout
)
1992 unsigned long flags
;
1993 int loop_count
= 4 * timeout
;
1994 int status
= FAILED
;
1997 spin_lock_irqsave(&hd
->ioc
->FreeQlock
, flags
);
1998 if(hd
->tmPending
== 0) {
2000 spin_unlock_irqrestore(&hd
->ioc
->FreeQlock
, flags
);
2003 spin_unlock_irqrestore(&hd
->ioc
->FreeQlock
, flags
);
2004 msleep_interruptible(250);
2005 } while (--loop_count
);
2010 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2012 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2013 * @ioc: Pointer to MPT_ADAPTER structure
2014 * @mf: Pointer to SCSI task mgmt request frame
2015 * @mr: Pointer to SCSI task mgmt reply frame
2017 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2018 * of any SCSI task management request.
2019 * This routine is registered with the MPT (base) driver at driver
2020 * load/init time via the mpt_register() API call.
2022 * Returns 1 indicating alloc'd request frame ptr should be freed.
2025 mptscsih_taskmgmt_complete(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
, MPT_FRAME_HDR
*mr
)
2027 SCSITaskMgmtReply_t
*pScsiTmReply
;
2028 SCSITaskMgmt_t
*pScsiTmReq
;
2030 unsigned long flags
;
2034 dtmprintk((MYIOC_s_WARN_FMT
"TaskMgmt completed (mf=%p,mr=%p)\n",
2035 ioc
->name
, mf
, mr
));
2037 /* Depending on the thread, a timer is activated for
2038 * the TM request. Delete this timer on completion of TM.
2039 * Decrement count of outstanding TM requests.
2041 hd
= (MPT_SCSI_HOST
*)ioc
->sh
->hostdata
;
2043 dtmprintk((MYIOC_s_WARN_FMT
"TaskMgmt Complete: NULL Scsi Host Ptr\n",
2049 dtmprintk((MYIOC_s_WARN_FMT
"ERROR! TaskMgmt Reply: NULL Request %p\n",
2053 pScsiTmReply
= (SCSITaskMgmtReply_t
*)mr
;
2054 pScsiTmReq
= (SCSITaskMgmt_t
*)mf
;
2056 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2057 tmType
= pScsiTmReq
->TaskType
;
2059 dtmprintk((MYIOC_s_WARN_FMT
" TaskType = %d, TerminationCount=%d\n",
2060 ioc
->name
, tmType
, le32_to_cpu(pScsiTmReply
->TerminationCount
)));
2061 DBG_DUMP_TM_REPLY_FRAME((u32
*)pScsiTmReply
);
2063 iocstatus
= le16_to_cpu(pScsiTmReply
->IOCStatus
) & MPI_IOCSTATUS_MASK
;
2064 dtmprintk((MYIOC_s_WARN_FMT
" SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2065 ioc
->name
, tmType
, iocstatus
, le32_to_cpu(pScsiTmReply
->IOCLogInfo
)));
2066 /* Error? (anything non-zero?) */
2069 /* clear flags and continue.
2071 if (tmType
== MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK
)
2072 hd
->abortSCpnt
= NULL
;
2074 /* If an internal command is present
2075 * or the TM failed - reload the FW.
2076 * FC FW may respond FAILED to an ABORT
2078 if (tmType
== MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS
) {
2080 (iocstatus
== MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED
)) {
2081 if (mpt_HardResetHandler(ioc
, NO_SLEEP
) < 0) {
2082 printk((KERN_WARNING
2083 " Firmware Reload FAILED!!\n"));
2088 dtmprintk((MYIOC_s_WARN_FMT
" TaskMgmt SUCCESS\n", ioc
->name
));
2090 hd
->abortSCpnt
= NULL
;
2095 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
2097 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
2098 hd
->tmState
= TM_STATE_NONE
;
2103 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2105 * This is anyones guess quite frankly.
2108 mptscsih_bios_param(struct scsi_device
* sdev
, struct block_device
*bdev
,
2109 sector_t capacity
, int geom
[])
2119 dummy
= heads
* sectors
;
2120 cylinders
= capacity
;
2121 sector_div(cylinders
,dummy
);
2124 * Handle extended translation size for logical drives
2127 if ((ulong
)capacity
>= 0x200000) {
2130 dummy
= heads
* sectors
;
2131 cylinders
= capacity
;
2132 sector_div(cylinders
,dummy
);
2138 geom
[2] = cylinders
;
2140 dprintk((KERN_NOTICE
2141 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2142 sdev
->id
, sdev
->lun
,sdev
->channel
,(int)cylinders
,heads
,sectors
));
2147 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2149 * OS entry point to allow host driver to alloc memory
2150 * for each scsi device. Called once per device the bus scan.
2151 * Return non-zero if allocation fails.
2152 * Init memory once per id (not LUN).
2155 mptscsih_slave_alloc(struct scsi_device
*device
)
2157 struct Scsi_Host
*host
= device
->host
;
2158 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
2160 uint target
= device
->id
;
2165 if ((vdev
= hd
->Targets
[target
]) != NULL
)
2168 vdev
= kmalloc(sizeof(VirtDevice
), GFP_KERNEL
);
2170 printk(MYIOC_s_ERR_FMT
"slave_alloc kmalloc(%zd) FAILED!\n",
2171 hd
->ioc
->name
, sizeof(VirtDevice
));
2175 memset(vdev
, 0, sizeof(VirtDevice
));
2176 vdev
->tflags
= MPT_TARGET_FLAGS_Q_YES
;
2177 vdev
->ioc_id
= hd
->ioc
->id
;
2178 vdev
->target_id
= device
->id
;
2179 vdev
->bus_id
= device
->channel
;
2180 vdev
->raidVolume
= 0;
2181 hd
->Targets
[device
->id
] = vdev
;
2182 if (hd
->ioc
->bus_type
== SCSI
) {
2183 if (hd
->ioc
->spi_data
.isRaid
& (1 << device
->id
)) {
2184 vdev
->raidVolume
= 1;
2185 ddvtprintk((KERN_INFO
2186 "RAID Volume @ id %d\n", device
->id
));
2189 vdev
->tflags
|= MPT_TARGET_FLAGS_VALID_INQUIRY
;
2198 mptscsih_is_raid_volume(MPT_SCSI_HOST
*hd
, uint id
)
2202 if (!hd
->ioc
->spi_data
.isRaid
|| !hd
->ioc
->spi_data
.pIocPg3
)
2205 for (i
= 0; i
< hd
->ioc
->spi_data
.pIocPg3
->NumPhysDisks
; i
++) {
2206 if (id
== hd
->ioc
->spi_data
.pIocPg3
->PhysDisk
[i
].PhysDiskID
)
2214 * OS entry point to allow for host driver to free allocated memory
2215 * Called if no device present or device being unloaded
2218 mptscsih_slave_destroy(struct scsi_device
*device
)
2220 struct Scsi_Host
*host
= device
->host
;
2221 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
2223 uint target
= device
->id
;
2224 uint lun
= device
->lun
;
2229 mptscsih_search_running_cmds(hd
, target
, lun
);
2231 vdev
= hd
->Targets
[target
];
2232 vdev
->luns
[0] &= ~(1 << lun
);
2233 if (--vdev
->num_luns
)
2236 kfree(hd
->Targets
[target
]);
2237 hd
->Targets
[target
] = NULL
;
2239 if (hd
->ioc
->bus_type
== SCSI
) {
2240 if (mptscsih_is_raid_volume(hd
, target
)) {
2241 hd
->ioc
->spi_data
.forceDv
|= MPT_SCSICFG_RELOAD_IOC_PG3
;
2243 hd
->ioc
->spi_data
.dvStatus
[target
] =
2244 MPT_SCSICFG_NEGOTIATE
;
2246 if (!hd
->negoNvram
) {
2247 hd
->ioc
->spi_data
.dvStatus
[target
] |=
2248 MPT_SCSICFG_DV_NOT_DONE
;
2255 mptscsih_set_queue_depth(struct scsi_device
*device
, MPT_SCSI_HOST
*hd
,
2256 VirtDevice
*pTarget
, int qdepth
)
2261 if (hd
->ioc
->bus_type
== SCSI
) {
2262 if (pTarget
->tflags
& MPT_TARGET_FLAGS_VALID_INQUIRY
) {
2263 if (!(pTarget
->tflags
& MPT_TARGET_FLAGS_Q_YES
))
2265 else if (((pTarget
->inq_data
[0] & 0x1f) == 0x00) &&
2266 (pTarget
->minSyncFactor
<= MPT_ULTRA160
))
2267 max_depth
= MPT_SCSI_CMD_PER_DEV_HIGH
;
2269 max_depth
= MPT_SCSI_CMD_PER_DEV_LOW
;
2271 /* error case - No Inq. Data */
2275 max_depth
= MPT_SCSI_CMD_PER_DEV_HIGH
;
2277 if (qdepth
> max_depth
)
2282 tagged
= MSG_SIMPLE_TAG
;
2284 scsi_adjust_queue_depth(device
, tagged
, qdepth
);
2289 * OS entry point to adjust the queue_depths on a per-device basis.
2290 * Called once per device the bus scan. Use it to force the queue_depth
2291 * member to 1 if a device does not support Q tags.
2292 * Return non-zero if fails.
2295 mptscsih_slave_configure(struct scsi_device
*device
)
2297 struct Scsi_Host
*sh
= device
->host
;
2298 VirtDevice
*pTarget
;
2299 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*)sh
->hostdata
;
2301 if ((hd
== NULL
) || (hd
->Targets
== NULL
)) {
2305 dsprintk((MYIOC_s_INFO_FMT
2306 "device @ %p, id=%d, LUN=%d, channel=%d\n",
2307 hd
->ioc
->name
, device
, device
->id
, device
->lun
, device
->channel
));
2308 dsprintk((MYIOC_s_INFO_FMT
2309 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2310 hd
->ioc
->name
, device
->sdtr
, device
->wdtr
,
2311 device
->ppr
, device
->inquiry_len
));
2313 if (device
->id
> sh
->max_id
) {
2314 /* error case, should never happen */
2315 scsi_adjust_queue_depth(device
, 0, 1);
2316 goto slave_configure_exit
;
2319 pTarget
= hd
->Targets
[device
->id
];
2321 if (pTarget
== NULL
) {
2322 /* Driver doesn't know about this device.
2323 * Kernel may generate a "Dummy Lun 0" which
2324 * may become a real Lun if a
2325 * "scsi add-single-device" command is executed
2326 * while the driver is active (hot-plug a
2327 * device). LSI Raid controllers need
2328 * queue_depth set to DEV_HIGH for this reason.
2330 scsi_adjust_queue_depth(device
, MSG_SIMPLE_TAG
,
2331 MPT_SCSI_CMD_PER_DEV_HIGH
);
2332 goto slave_configure_exit
;
2335 mptscsih_initTarget(hd
, device
->channel
, device
->id
, device
->lun
,
2336 device
->inquiry
, device
->inquiry_len
);
2337 mptscsih_set_queue_depth(device
, hd
, pTarget
, MPT_SCSI_CMD_PER_DEV_HIGH
);
2339 dsprintk((MYIOC_s_INFO_FMT
2340 "Queue depth=%d, tflags=%x\n",
2341 hd
->ioc
->name
, device
->queue_depth
, pTarget
->tflags
));
2343 dsprintk((MYIOC_s_INFO_FMT
2344 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2345 hd
->ioc
->name
, pTarget
->negoFlags
, pTarget
->maxOffset
, pTarget
->minSyncFactor
));
2347 slave_configure_exit
:
2349 dsprintk((MYIOC_s_INFO_FMT
2350 "tagged %d, simple %d, ordered %d\n",
2351 hd
->ioc
->name
,device
->tagged_supported
, device
->simple_tags
,
2352 device
->ordered_tags
));
2358 mptscsih_store_queue_depth(struct device
*dev
, const char *buf
, size_t count
)
2361 struct scsi_device
*sdev
= to_scsi_device(dev
);
2362 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*) sdev
->host
->hostdata
;
2363 VirtDevice
*pTarget
;
2365 depth
= simple_strtoul(buf
, NULL
, 0);
2368 pTarget
= hd
->Targets
[sdev
->id
];
2369 if (pTarget
== NULL
)
2371 mptscsih_set_queue_depth(sdev
, (MPT_SCSI_HOST
*) sdev
->host
->hostdata
,
2376 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2378 * Private routines...
2381 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2382 /* Utility function to copy sense data from the scsi_cmnd buffer
2383 * to the FC and SCSI target structures.
2387 mptscsih_copy_sense_data(struct scsi_cmnd
*sc
, MPT_SCSI_HOST
*hd
, MPT_FRAME_HDR
*mf
, SCSIIOReply_t
*pScsiReply
)
2390 SCSIIORequest_t
*pReq
;
2391 u32 sense_count
= le32_to_cpu(pScsiReply
->SenseCount
);
2394 /* Get target structure
2396 pReq
= (SCSIIORequest_t
*) mf
;
2397 index
= (int) pReq
->TargetID
;
2398 target
= hd
->Targets
[index
];
2404 /* Copy the sense received into the scsi command block. */
2405 req_index
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
2406 sense_data
= ((u8
*)hd
->ioc
->sense_buf_pool
+ (req_index
* MPT_SENSE_BUFFER_ALLOC
));
2407 memcpy(sc
->sense_buffer
, sense_data
, SNS_LEN(sc
));
2409 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2411 if ((hd
->ioc
->events
) && (hd
->ioc
->eventTypes
& (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE
))) {
2412 if ((sense_data
[12] == 0x5D) && (target
->raidVolume
== 0)) {
2414 MPT_ADAPTER
*ioc
= hd
->ioc
;
2416 idx
= ioc
->eventContext
% ioc
->eventLogSize
;
2417 ioc
->events
[idx
].event
= MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE
;
2418 ioc
->events
[idx
].eventContext
= ioc
->eventContext
;
2420 ioc
->events
[idx
].data
[0] = (pReq
->LUN
[1] << 24) ||
2421 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA
<< 16) ||
2422 (pReq
->Bus
<< 8) || pReq
->TargetID
;
2424 ioc
->events
[idx
].data
[1] = (sense_data
[13] << 8) || sense_data
[12];
2426 ioc
->eventContext
++;
2430 dprintk((MYIOC_s_INFO_FMT
"Hmmm... SenseData len=0! (?)\n",
2436 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd
*sc
)
2441 hd
= (MPT_SCSI_HOST
*) sc
->device
->host
->hostdata
;
2443 for (i
= 0; i
< hd
->ioc
->req_depth
; i
++) {
2444 if (hd
->ScsiLookup
[i
] == sc
) {
2452 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2454 mptscsih_ioc_reset(MPT_ADAPTER
*ioc
, int reset_phase
)
2457 unsigned long flags
;
2459 dtmprintk((KERN_WARNING MYNAM
2460 ": IOC %s_reset routed to SCSI host driver!\n",
2461 reset_phase
==MPT_IOC_SETUP_RESET
? "setup" : (
2462 reset_phase
==MPT_IOC_PRE_RESET
? "pre" : "post")));
2464 /* If a FW reload request arrives after base installed but
2465 * before all scsi hosts have been attached, then an alt_ioc
2466 * may have a NULL sh pointer.
2468 if ((ioc
->sh
== NULL
) || (ioc
->sh
->hostdata
== NULL
))
2471 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
2473 if (reset_phase
== MPT_IOC_SETUP_RESET
) {
2474 dtmprintk((MYIOC_s_WARN_FMT
"Setup-Diag Reset\n", ioc
->name
));
2477 * 1. Set Hard Reset Pending Flag
2478 * All new commands go to doneQ
2480 hd
->resetPending
= 1;
2482 } else if (reset_phase
== MPT_IOC_PRE_RESET
) {
2483 dtmprintk((MYIOC_s_WARN_FMT
"Pre-Diag Reset\n", ioc
->name
));
2485 /* 2. Flush running commands
2486 * Clean ScsiLookup (and associated memory)
2490 /* 2b. Reply to OS all known outstanding I/O commands.
2492 mptscsih_flush_running_cmds(hd
);
2494 /* 2c. If there was an internal command that
2495 * has not completed, configuration or io request,
2496 * free these resources.
2499 del_timer(&hd
->timer
);
2500 mpt_free_msg_frame(ioc
, hd
->cmdPtr
);
2503 dtmprintk((MYIOC_s_WARN_FMT
"Pre-Reset complete.\n", ioc
->name
));
2506 dtmprintk((MYIOC_s_WARN_FMT
"Post-Diag Reset\n", ioc
->name
));
2508 /* Once a FW reload begins, all new OS commands are
2509 * redirected to the doneQ w/ a reset status.
2510 * Init all control structures.
2513 /* ScsiLookup initialization
2517 for (ii
=0; ii
< hd
->ioc
->req_depth
; ii
++)
2518 hd
->ScsiLookup
[ii
] = NULL
;
2521 /* 2. Chain Buffer initialization
2524 /* 4. Renegotiate to all devices, if SCSI
2526 if (ioc
->bus_type
== SCSI
) {
2527 dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
2528 mptscsih_writeSDP1(hd
, 0, 0, MPT_SCSICFG_ALL_IDS
| MPT_SCSICFG_USE_NVRAM
);
2531 /* 5. Enable new commands to be posted
2533 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
2535 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
2536 hd
->resetPending
= 0;
2537 hd
->tmState
= TM_STATE_NONE
;
2539 /* 6. If there was an internal command,
2540 * wake this process up.
2544 * Wake up the original calling thread
2546 hd
->pLocal
= &hd
->localReply
;
2547 hd
->pLocal
->completion
= MPT_SCANDV_DID_RESET
;
2548 hd
->scandv_wait_done
= 1;
2549 wake_up(&hd
->scandv_waitq
);
2553 /* 7. Set flag to force DV and re-read IOC Page 3
2555 if (ioc
->bus_type
== SCSI
) {
2556 ioc
->spi_data
.forceDv
= MPT_SCSICFG_NEED_DV
| MPT_SCSICFG_RELOAD_IOC_PG3
;
2557 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
2560 dtmprintk((MYIOC_s_WARN_FMT
"Post-Reset complete.\n", ioc
->name
));
2564 return 1; /* currently means nothing really */
2567 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2569 mptscsih_event_process(MPT_ADAPTER
*ioc
, EventNotificationReply_t
*pEvReply
)
2572 u8 event
= le32_to_cpu(pEvReply
->Event
) & 0xFF;
2574 devtprintk((MYIOC_s_INFO_FMT
"MPT event (=%02Xh) routed to SCSI host driver!\n",
2578 case MPI_EVENT_UNIT_ATTENTION
: /* 03 */
2581 case MPI_EVENT_IOC_BUS_RESET
: /* 04 */
2582 case MPI_EVENT_EXT_BUS_RESET
: /* 05 */
2585 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
2586 if (hd
&& (ioc
->bus_type
== SCSI
) && (hd
->soft_resets
< -1))
2590 case MPI_EVENT_LOGOUT
: /* 09 */
2595 * CHECKME! Don't think we need to do
2596 * anything for these, but...
2598 case MPI_EVENT_RESCAN
: /* 06 */
2599 case MPI_EVENT_LINK_STATUS_CHANGE
: /* 07 */
2600 case MPI_EVENT_LOOP_STATE_CHANGE
: /* 08 */
2602 * CHECKME! Falling thru...
2606 case MPI_EVENT_INTEGRATED_RAID
: /* 0B */
2607 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2608 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
2609 * if DV disabled. Need to check for target mode.
2613 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
2615 if (hd
&& (ioc
->bus_type
== SCSI
) && (hd
->negoNvram
== 0)) {
2617 Ioc3PhysDisk_t
*pPDisk
;
2622 reason
= (le32_to_cpu(pEvReply
->Data
[0]) & 0x00FF0000) >> 16;
2623 if (reason
== MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED
) {
2624 /* New or replaced disk.
2625 * Set DV flag and schedule DV.
2627 pSpi
= &ioc
->spi_data
;
2628 physDiskNum
= (le32_to_cpu(pEvReply
->Data
[0]) & 0xFF000000) >> 24;
2629 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum
));
2630 if (pSpi
->pIocPg3
) {
2631 pPDisk
= pSpi
->pIocPg3
->PhysDisk
;
2632 numPDisk
=pSpi
->pIocPg3
->NumPhysDisks
;
2635 if (physDiskNum
== pPDisk
->PhysDiskNum
) {
2636 pSpi
->dvStatus
[pPDisk
->PhysDiskID
] = (MPT_SCSICFG_NEED_DV
| MPT_SCSICFG_DV_NOT_DONE
);
2637 pSpi
->forceDv
= MPT_SCSICFG_NEED_DV
;
2638 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk
->PhysDiskID
));
2645 if (numPDisk
== 0) {
2646 /* The physical disk that needs DV was not found
2647 * in the stored IOC Page 3. The driver must reload
2648 * this page. DV routine will set the NEED_DV flag for
2649 * all phys disks that have DV_NOT_DONE set.
2651 pSpi
->forceDv
= MPT_SCSICFG_NEED_DV
| MPT_SCSICFG_RELOAD_IOC_PG3
;
2652 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum
));
2659 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
2660 printk("Raid Event RF: ");
2662 u32
*m
= (u32
*)pEvReply
;
2664 int n
= (int)pEvReply
->MsgLength
;
2665 for (ii
=6; ii
< n
; ii
++)
2666 printk(" %08x", le32_to_cpu(m
[ii
]));
2672 case MPI_EVENT_NONE
: /* 00 */
2673 case MPI_EVENT_LOG_DATA
: /* 01 */
2674 case MPI_EVENT_STATE_CHANGE
: /* 02 */
2675 case MPI_EVENT_EVENT_CHANGE
: /* 0A */
2677 dprintk((KERN_INFO
" Ignoring event (=%02Xh)\n", event
));
2681 return 1; /* currently means nothing really */
2684 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2686 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2687 * @hd: Pointer to MPT_SCSI_HOST structure
2688 * @bus_id: Bus number (?)
2689 * @target_id: SCSI target id
2691 * @data: Pointer to data
2692 * @dlen: Number of INQUIRY bytes
2694 * NOTE: It's only SAFE to call this routine if data points to
2695 * sane & valid STANDARD INQUIRY data!
2697 * Allocate and initialize memory for this target.
2698 * Save inquiry data.
2702 mptscsih_initTarget(MPT_SCSI_HOST
*hd
, int bus_id
, int target_id
, u8 lun
, char *data
, int dlen
)
2704 int indexed_lun
, lun_index
;
2709 dinitprintk((MYIOC_s_INFO_FMT
"initTarget bus=%d id=%d lun=%d hd=%p\n",
2710 hd
->ioc
->name
, bus_id
, target_id
, lun
, hd
));
2713 * If the peripheral qualifier filter is enabled then if the target reports a 0x1
2714 * (i.e. The targer is capable of supporting the specified peripheral device type
2715 * on this logical unit; however, the physical device is not currently connected
2716 * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
2717 * capable of supporting a physical device on this logical unit). This is to work
2718 * around a bug in th emid-layer in some distributions in which the mid-layer will
2719 * continue to try to communicate to the LUN and evntually create a dummy LUN.
2721 if (hd
->mpt_pq_filter
&& dlen
&& (data
[0] & 0xE0))
2724 /* Is LUN supported? If so, upper 2 bits will be 0
2725 * in first byte of inquiry data.
2730 if ((vdev
= hd
->Targets
[target_id
]) == NULL
) {
2734 lun_index
= (lun
>> 5); /* 32 luns per lun_index */
2735 indexed_lun
= (lun
% 32);
2736 vdev
->luns
[lun_index
] |= (1 << indexed_lun
);
2738 if (hd
->ioc
->bus_type
== SCSI
) {
2739 if ((data
[0] == TYPE_PROCESSOR
) && (hd
->ioc
->spi_data
.Saf_Te
)) {
2740 /* Treat all Processors as SAF-TE if
2741 * command line option is set */
2742 vdev
->tflags
|= MPT_TARGET_FLAGS_SAF_TE_ISSUED
;
2743 mptscsih_writeIOCPage4(hd
, target_id
, bus_id
);
2744 }else if ((data
[0] == TYPE_PROCESSOR
) &&
2745 !(vdev
->tflags
& MPT_TARGET_FLAGS_SAF_TE_ISSUED
)) {
2747 vdev
->tflags
|= MPT_TARGET_FLAGS_VALID_INQUIRY
;
2748 if ( data
[44] == 'S' &&
2754 vdev
->tflags
|= MPT_TARGET_FLAGS_SAF_TE_ISSUED
;
2755 mptscsih_writeIOCPage4(hd
, target_id
, bus_id
);
2759 if (!(vdev
->tflags
& MPT_TARGET_FLAGS_VALID_INQUIRY
)) {
2761 memcpy (vdev
->inq_data
, data
, 8);
2763 memcpy (vdev
->inq_data
, data
, dlen
);
2766 /* If have not done DV, set the DV flag.
2768 pSpi
= &hd
->ioc
->spi_data
;
2769 if ((data
[0] == TYPE_TAPE
) || (data
[0] == TYPE_PROCESSOR
)) {
2770 if (pSpi
->dvStatus
[target_id
] & MPT_SCSICFG_DV_NOT_DONE
)
2771 pSpi
->dvStatus
[target_id
] |= MPT_SCSICFG_NEED_DV
;
2774 vdev
->tflags
|= MPT_TARGET_FLAGS_VALID_INQUIRY
;
2777 data_56
= 0x0F; /* Default to full capabilities if Inq data length is < 57 */
2779 if ( (!(vdev
->tflags
& MPT_TARGET_FLAGS_VALID_56
))) {
2780 /* Update the target capabilities
2783 vdev
->tflags
|= MPT_TARGET_FLAGS_VALID_56
;
2786 mptscsih_setTargetNegoParms(hd
, vdev
, data_56
);
2788 /* Initial Inquiry may not request enough data bytes to
2789 * obtain byte 57. DV will; if target doesn't return
2790 * at least 57 bytes, data[56] will be zero. */
2792 if ( (!(vdev
->tflags
& MPT_TARGET_FLAGS_VALID_56
))) {
2793 /* Update the target capabilities
2796 vdev
->tflags
|= MPT_TARGET_FLAGS_VALID_56
;
2797 mptscsih_setTargetNegoParms(hd
, vdev
, data_56
);
2804 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2806 * Update the target negotiation parameters based on the
2807 * the Inquiry data, adapter capabilities, and NVRAM settings.
2811 mptscsih_setTargetNegoParms(MPT_SCSI_HOST
*hd
, VirtDevice
*target
, char byte56
)
2813 ScsiCfgData
*pspi_data
= &hd
->ioc
->spi_data
;
2814 int id
= (int) target
->target_id
;
2818 u8 width
= MPT_NARROW
;
2819 u8 factor
= MPT_ASYNC
;
2821 u8 version
, nfactor
;
2824 target
->negoFlags
= pspi_data
->noQas
;
2826 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
2827 * support. If available, default QAS to off and allow enabling.
2828 * If not available, default QAS to on, turn off for non-disks.
2831 /* Set flags based on Inquiry data
2833 version
= target
->inq_data
[2] & 0x07;
2836 factor
= MPT_ULTRA2
;
2837 offset
= pspi_data
->maxSyncOffset
;
2838 target
->tflags
&= ~MPT_TARGET_FLAGS_Q_YES
;
2840 if (target
->inq_data
[7] & 0x20) {
2844 if (target
->inq_data
[7] & 0x10) {
2845 factor
= pspi_data
->minSyncFactor
;
2846 if (target
->tflags
& MPT_TARGET_FLAGS_VALID_56
) {
2847 /* bits 2 & 3 show Clocking support */
2848 if ((byte56
& 0x0C) == 0)
2849 factor
= MPT_ULTRA2
;
2851 if ((byte56
& 0x03) == 0)
2852 factor
= MPT_ULTRA160
;
2854 factor
= MPT_ULTRA320
;
2857 ddvtprintk((KERN_INFO
"Enabling QAS due to byte56=%02x on id=%d!\n", byte56
, id
));
2860 if (target
->inq_data
[0] == TYPE_TAPE
) {
2862 target
->negoFlags
|= MPT_TAPE_NEGO_IDP
;
2867 ddvtprintk((KERN_INFO
"Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id
));
2871 offset
= pspi_data
->maxSyncOffset
;
2873 /* If RAID, never disable QAS
2874 * else if non RAID, do not disable
2875 * QAS if bit 1 is set
2876 * bit 1 QAS support, non-raid only
2879 if (target
->raidVolume
== 1) {
2888 if ( (target
->inq_data
[7] & 0x02) == 0) {
2889 target
->tflags
&= ~MPT_TARGET_FLAGS_Q_YES
;
2892 /* Update tflags based on NVRAM settings. (SCSI only)
2894 if (pspi_data
->nvram
&& (pspi_data
->nvram
[id
] != MPT_HOST_NVRAM_INVALID
)) {
2895 nvram
= pspi_data
->nvram
[id
];
2896 nfactor
= (nvram
& MPT_NVRAM_SYNC_MASK
) >> 8;
2899 width
= nvram
& MPT_NVRAM_WIDE_DISABLE
? 0 : 1;
2902 /* Ensure factor is set to the
2903 * maximum of: adapter, nvram, inquiry
2906 if (nfactor
< pspi_data
->minSyncFactor
)
2907 nfactor
= pspi_data
->minSyncFactor
;
2909 factor
= max(factor
, nfactor
);
2910 if (factor
== MPT_ASYNC
)
2921 /* Make sure data is consistent
2923 if ((!width
) && (factor
< MPT_ULTRA2
)) {
2924 factor
= MPT_ULTRA2
;
2927 /* Save the data to the target structure.
2929 target
->minSyncFactor
= factor
;
2930 target
->maxOffset
= offset
;
2931 target
->maxWidth
= width
;
2933 target
->tflags
|= MPT_TARGET_FLAGS_VALID_NEGO
;
2935 /* Disable unused features.
2938 target
->negoFlags
|= MPT_TARGET_NO_NEGO_WIDE
;
2941 target
->negoFlags
|= MPT_TARGET_NO_NEGO_SYNC
;
2943 if ( factor
> MPT_ULTRA320
)
2946 /* GEM, processor WORKAROUND
2948 if ((target
->inq_data
[0] == TYPE_PROCESSOR
) || (target
->inq_data
[0] > 0x08)) {
2949 target
->negoFlags
|= (MPT_TARGET_NO_NEGO_WIDE
| MPT_TARGET_NO_NEGO_SYNC
);
2950 pspi_data
->dvStatus
[id
] |= MPT_SCSICFG_BLK_NEGO
;
2952 if (noQas
&& (pspi_data
->noQas
== 0)) {
2953 pspi_data
->noQas
|= MPT_TARGET_NO_NEGO_QAS
;
2954 target
->negoFlags
|= MPT_TARGET_NO_NEGO_QAS
;
2956 /* Disable QAS in a mixed configuration case
2959 ddvtprintk((KERN_INFO
"Disabling QAS due to noQas=%02x on id=%d!\n", noQas
, id
));
2960 for (ii
= 0; ii
< id
; ii
++) {
2961 if ( (vdev
= hd
->Targets
[ii
]) ) {
2962 vdev
->negoFlags
|= MPT_TARGET_NO_NEGO_QAS
;
2963 mptscsih_writeSDP1(hd
, 0, ii
, vdev
->negoFlags
);
2969 /* Write SDP1 on this I/O to this target */
2970 if (pspi_data
->dvStatus
[id
] & MPT_SCSICFG_NEGOTIATE
) {
2971 ddvtprintk((KERN_INFO
"MPT_SCSICFG_NEGOTIATE on id=%d!\n", id
));
2972 mptscsih_writeSDP1(hd
, 0, id
, hd
->negoNvram
);
2973 pspi_data
->dvStatus
[id
] &= ~MPT_SCSICFG_NEGOTIATE
;
2974 } else if (pspi_data
->dvStatus
[id
] & MPT_SCSICFG_BLK_NEGO
) {
2975 ddvtprintk((KERN_INFO
"MPT_SCSICFG_BLK_NEGO on id=%d!\n", id
));
2976 mptscsih_writeSDP1(hd
, 0, id
, MPT_SCSICFG_BLK_NEGO
);
2977 pspi_data
->dvStatus
[id
] &= ~MPT_SCSICFG_BLK_NEGO
;
2981 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2982 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
2983 * Else set the NEED_DV flag after Read Capacity Issued (disks)
2984 * or Mode Sense (cdroms).
2986 * Tapes, initTarget will set this flag on completion of Inquiry command.
2987 * Called only if DV_NOT_DONE flag is set
2990 mptscsih_set_dvflags(MPT_SCSI_HOST
*hd
, SCSIIORequest_t
*pReq
)
2995 ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
2996 pReq
->TargetID
, pReq
->LUN
[1], hd
->negoNvram
, pReq
->CDB
[0]));
2998 if ((pReq
->LUN
[1] != 0) || (hd
->negoNvram
!= 0))
3003 if ((cmd
== READ_CAPACITY
) || (cmd
== MODE_SENSE
)) {
3004 pSpi
= &hd
->ioc
->spi_data
;
3005 if ((pSpi
->isRaid
& (1 << pReq
->TargetID
)) && pSpi
->pIocPg3
) {
3006 /* Set NEED_DV for all hidden disks
3008 Ioc3PhysDisk_t
*pPDisk
= pSpi
->pIocPg3
->PhysDisk
;
3009 int numPDisk
= pSpi
->pIocPg3
->NumPhysDisks
;
3012 pSpi
->dvStatus
[pPDisk
->PhysDiskID
] |= MPT_SCSICFG_NEED_DV
;
3013 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk
->PhysDiskID
));
3018 pSpi
->dvStatus
[pReq
->TargetID
] |= MPT_SCSICFG_NEED_DV
;
3019 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq
->TargetID
));
3023 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3025 * If no Target, bus reset on 1st I/O. Set the flag to
3026 * prevent any future negotiations to this device.
3029 mptscsih_no_negotiate(MPT_SCSI_HOST
*hd
, int target_id
)
3032 if ((hd
->Targets
) && (hd
->Targets
[target_id
] == NULL
))
3033 hd
->ioc
->spi_data
.dvStatus
[target_id
] |= MPT_SCSICFG_BLK_NEGO
;
3038 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3040 * SCSI Config Page functionality ...
3042 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3043 /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
3044 * based on width, factor and offset parameters.
3046 * @factor: sync factor
3047 * @offset: sync offset
3048 * @requestedPtr: pointer to requested values (updated)
3049 * @configurationPtr: pointer to configuration values (updated)
3050 * @flags: flags to block WDTR or SDTR negotiation
3054 * Remark: Called by writeSDP1 and _dv_params
3057 mptscsih_setDevicePage1Flags (u8 width
, u8 factor
, u8 offset
, int *requestedPtr
, int *configurationPtr
, u8 flags
)
3059 u8 nowide
= flags
& MPT_TARGET_NO_NEGO_WIDE
;
3060 u8 nosync
= flags
& MPT_TARGET_NO_NEGO_SYNC
;
3062 *configurationPtr
= 0;
3063 *requestedPtr
= width
? MPI_SCSIDEVPAGE1_RP_WIDE
: 0;
3064 *requestedPtr
|= (offset
<< 16) | (factor
<< 8);
3066 if (width
&& offset
&& !nowide
&& !nosync
) {
3067 if (factor
< MPT_ULTRA160
) {
3068 *requestedPtr
|= (MPI_SCSIDEVPAGE1_RP_IU
+ MPI_SCSIDEVPAGE1_RP_DT
);
3069 if ((flags
& MPT_TARGET_NO_NEGO_QAS
) == 0)
3070 *requestedPtr
|= MPI_SCSIDEVPAGE1_RP_QAS
;
3071 if (flags
& MPT_TAPE_NEGO_IDP
)
3072 *requestedPtr
|= 0x08000000;
3073 } else if (factor
< MPT_ULTRA2
) {
3074 *requestedPtr
|= MPI_SCSIDEVPAGE1_RP_DT
;
3079 *configurationPtr
|= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED
;
3082 *configurationPtr
|= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED
;
3087 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3088 /* mptscsih_writeSDP1 - write SCSI Device Page 1
3089 * @hd: Pointer to a SCSI Host Strucutre
3090 * @portnum: IOC port number
3091 * @target_id: writeSDP1 for single ID
3092 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
3094 * Return: -EFAULT if read of config page header fails
3097 * Remark: If a target has been found, the settings from the
3098 * target structure are used, else the device is set
3101 * Remark: Called during init and after a FW reload.
3102 * Remark: We do not wait for a return, write pages sequentially.
3105 mptscsih_writeSDP1(MPT_SCSI_HOST
*hd
, int portnum
, int target_id
, int flags
)
3107 MPT_ADAPTER
*ioc
= hd
->ioc
;
3109 SCSIDevicePage1_t
*pData
;
3110 VirtDevice
*pTarget
;
3115 u32 requested
, configuration
, flagsLength
;
3117 int id
= 0, maxid
= 0;
3123 u8 maxwidth
, maxoffset
, maxfactor
;
3125 if (ioc
->spi_data
.sdp1length
== 0)
3128 if (flags
& MPT_SCSICFG_ALL_IDS
) {
3130 maxid
= ioc
->sh
->max_id
- 1;
3131 } else if (ioc
->sh
) {
3133 maxid
= min_t(int, id
, ioc
->sh
->max_id
- 1);
3136 for (; id
<= maxid
; id
++) {
3138 if (id
== ioc
->pfacts
[portnum
].PortSCSIID
)
3141 /* Use NVRAM to get adapter and target maximums
3142 * Data over-riden by target structure information, if present
3144 maxwidth
= ioc
->spi_data
.maxBusWidth
;
3145 maxoffset
= ioc
->spi_data
.maxSyncOffset
;
3146 maxfactor
= ioc
->spi_data
.minSyncFactor
;
3147 if (ioc
->spi_data
.nvram
&& (ioc
->spi_data
.nvram
[id
] != MPT_HOST_NVRAM_INVALID
)) {
3148 nvram
= ioc
->spi_data
.nvram
[id
];
3151 maxwidth
= nvram
& MPT_NVRAM_WIDE_DISABLE
? 0 : 1;
3153 if (maxoffset
> 0) {
3154 maxfactor
= (nvram
& MPT_NVRAM_SYNC_MASK
) >> 8;
3155 if (maxfactor
== 0) {
3157 maxfactor
= MPT_ASYNC
;
3159 } else if (maxfactor
< ioc
->spi_data
.minSyncFactor
) {
3160 maxfactor
= ioc
->spi_data
.minSyncFactor
;
3163 maxfactor
= MPT_ASYNC
;
3166 /* Set the negotiation flags.
3168 negoFlags
= ioc
->spi_data
.noQas
;
3170 negoFlags
|= MPT_TARGET_NO_NEGO_WIDE
;
3173 negoFlags
|= MPT_TARGET_NO_NEGO_SYNC
;
3175 if (flags
& MPT_SCSICFG_USE_NVRAM
) {
3184 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
3187 /* If id is not a raid volume, get the updated
3188 * transmission settings from the target structure.
3190 if (hd
->Targets
&& (pTarget
= hd
->Targets
[id
]) && !pTarget
->raidVolume
) {
3191 width
= pTarget
->maxWidth
;
3192 factor
= pTarget
->minSyncFactor
;
3193 offset
= pTarget
->maxOffset
;
3194 negoFlags
= pTarget
->negoFlags
;
3197 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3198 /* Force to async and narrow if DV has not been executed
3201 if ((hd
->ioc
->spi_data
.dvStatus
[id
] & MPT_SCSICFG_DV_NOT_DONE
) != 0) {
3208 if (flags
& MPT_SCSICFG_BLK_NEGO
)
3209 negoFlags
= MPT_TARGET_NO_NEGO_WIDE
| MPT_TARGET_NO_NEGO_SYNC
;
3211 mptscsih_setDevicePage1Flags(width
, factor
, offset
,
3212 &requested
, &configuration
, negoFlags
);
3213 dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
3214 target_id
, width
, factor
, offset
, negoFlags
, requested
, configuration
));
3216 /* Get a MF for this command.
3218 if ((mf
= mpt_get_msg_frame(ioc
->DoneCtx
, ioc
)) == NULL
) {
3219 dprintk((MYIOC_s_WARN_FMT
"write SDP1: no msg frames!\n",
3224 ddvprintk((MYIOC_s_INFO_FMT
"WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
3225 hd
->ioc
->name
, mf
, id
, requested
, configuration
));
3228 /* Set the request and the data pointers.
3229 * Request takes: 36 bytes (32 bit SGE)
3230 * SCSI Device Page 1 requires 16 bytes
3231 * 40 + 16 <= size of SCSI IO Request = 56 bytes
3232 * and MF size >= 64 bytes.
3233 * Place data at end of MF.
3235 pReq
= (Config_t
*)mf
;
3237 req_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
3238 frameOffset
= ioc
->req_sz
- sizeof(SCSIDevicePage1_t
);
3240 pData
= (SCSIDevicePage1_t
*)((u8
*) mf
+ frameOffset
);
3241 dataDma
= ioc
->req_frames_dma
+ (req_idx
* ioc
->req_sz
) + frameOffset
;
3243 /* Complete the request frame (same for all requests).
3245 pReq
->Action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
3247 pReq
->ChainOffset
= 0;
3248 pReq
->Function
= MPI_FUNCTION_CONFIG
;
3249 pReq
->ExtPageLength
= 0;
3250 pReq
->ExtPageType
= 0;
3252 for (ii
=0; ii
< 8; ii
++) {
3253 pReq
->Reserved2
[ii
] = 0;
3255 pReq
->Header
.PageVersion
= ioc
->spi_data
.sdp1version
;
3256 pReq
->Header
.PageLength
= ioc
->spi_data
.sdp1length
;
3257 pReq
->Header
.PageNumber
= 1;
3258 pReq
->Header
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_DEVICE
;
3259 pReq
->PageAddress
= cpu_to_le32(id
| (bus
<< 8 ));
3261 /* Add a SGE to the config request.
3263 flagsLength
= MPT_SGE_FLAGS_SSIMPLE_WRITE
| ioc
->spi_data
.sdp1length
* 4;
3265 mpt_add_sge((char *)&pReq
->PageBufferSGE
, flagsLength
, dataDma
);
3267 /* Set up the common data portion
3269 pData
->Header
.PageVersion
= pReq
->Header
.PageVersion
;
3270 pData
->Header
.PageLength
= pReq
->Header
.PageLength
;
3271 pData
->Header
.PageNumber
= pReq
->Header
.PageNumber
;
3272 pData
->Header
.PageType
= pReq
->Header
.PageType
;
3273 pData
->RequestedParameters
= cpu_to_le32(requested
);
3274 pData
->Reserved
= 0;
3275 pData
->Configuration
= cpu_to_le32(configuration
);
3277 dprintk((MYIOC_s_INFO_FMT
3278 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
3279 ioc
->name
, id
, (id
| (bus
<<8)),
3280 requested
, configuration
));
3282 mpt_put_msg_frame(ioc
->DoneCtx
, ioc
, mf
);
3288 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3289 /* mptscsih_writeIOCPage4 - write IOC Page 4
3290 * @hd: Pointer to a SCSI Host Structure
3291 * @target_id: write IOC Page4 for this ID & Bus
3293 * Return: -EAGAIN if unable to obtain a Message Frame
3296 * Remark: We do not wait for a return, write pages sequentially.
3299 mptscsih_writeIOCPage4(MPT_SCSI_HOST
*hd
, int target_id
, int bus
)
3301 MPT_ADAPTER
*ioc
= hd
->ioc
;
3303 IOCPage4_t
*IOCPage4Ptr
;
3311 /* Get a MF for this command.
3313 if ((mf
= mpt_get_msg_frame(ioc
->DoneCtx
, ioc
)) == NULL
) {
3314 dprintk((MYIOC_s_WARN_FMT
"writeIOCPage4 : no msg frames!\n",
3319 /* Set the request and the data pointers.
3320 * Place data at end of MF.
3322 pReq
= (Config_t
*)mf
;
3324 req_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
3325 frameOffset
= ioc
->req_sz
- sizeof(IOCPage4_t
);
3327 /* Complete the request frame (same for all requests).
3329 pReq
->Action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
3331 pReq
->ChainOffset
= 0;
3332 pReq
->Function
= MPI_FUNCTION_CONFIG
;
3333 pReq
->ExtPageLength
= 0;
3334 pReq
->ExtPageType
= 0;
3336 for (ii
=0; ii
< 8; ii
++) {
3337 pReq
->Reserved2
[ii
] = 0;
3340 IOCPage4Ptr
= ioc
->spi_data
.pIocPg4
;
3341 dataDma
= ioc
->spi_data
.IocPg4_dma
;
3342 ii
= IOCPage4Ptr
->ActiveSEP
++;
3343 IOCPage4Ptr
->SEP
[ii
].SEPTargetID
= target_id
;
3344 IOCPage4Ptr
->SEP
[ii
].SEPBus
= bus
;
3345 pReq
->Header
= IOCPage4Ptr
->Header
;
3346 pReq
->PageAddress
= cpu_to_le32(target_id
| (bus
<< 8 ));
3348 /* Add a SGE to the config request.
3350 flagsLength
= MPT_SGE_FLAGS_SSIMPLE_WRITE
|
3351 (IOCPage4Ptr
->Header
.PageLength
+ ii
) * 4;
3353 mpt_add_sge((char *)&pReq
->PageBufferSGE
, flagsLength
, dataDma
);
3355 dinitprintk((MYIOC_s_INFO_FMT
3356 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
3357 ioc
->name
, IOCPage4Ptr
->MaxSEP
, IOCPage4Ptr
->ActiveSEP
, target_id
, bus
));
3359 mpt_put_msg_frame(ioc
->DoneCtx
, ioc
, mf
);
3364 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3366 * Bus Scan and Domain Validation functionality ...
3369 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3371 * mptscsih_scandv_complete - Scan and DV callback routine registered
3372 * to Fustion MPT (base) driver.
3374 * @ioc: Pointer to MPT_ADAPTER structure
3375 * @mf: Pointer to original MPT request frame
3376 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
3378 * This routine is called from mpt.c::mpt_interrupt() at the completion
3379 * of any SCSI IO request.
3380 * This routine is registered with the Fusion MPT (base) driver at driver
3381 * load/init time via the mpt_register() API call.
3383 * Returns 1 indicating alloc'd request frame ptr should be freed.
3385 * Remark: Sets a completion code and (possibly) saves sense data
3386 * in the IOC member localReply structure.
3387 * Used ONLY for DV and other internal commands.
3390 mptscsih_scandv_complete(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*mf
, MPT_FRAME_HDR
*mr
)
3393 SCSIIORequest_t
*pReq
;
3397 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
3400 (mf
>= MPT_INDEX_2_MFPTR(ioc
, ioc
->req_depth
))) {
3401 printk(MYIOC_s_ERR_FMT
3402 "ScanDvComplete, %s req frame ptr! (=%p)\n",
3403 ioc
->name
, mf
?"BAD":"NULL", (void *) mf
);
3407 del_timer(&hd
->timer
);
3408 req_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
3409 hd
->ScsiLookup
[req_idx
] = NULL
;
3410 pReq
= (SCSIIORequest_t
*) mf
;
3412 if (mf
!= hd
->cmdPtr
) {
3413 printk(MYIOC_s_WARN_FMT
"ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3414 hd
->ioc
->name
, (void *)mf
, (void *) hd
->cmdPtr
, req_idx
);
3418 ddvprintk((MYIOC_s_INFO_FMT
"ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3419 hd
->ioc
->name
, mf
, mr
, req_idx
));
3421 hd
->pLocal
= &hd
->localReply
;
3422 hd
->pLocal
->scsiStatus
= 0;
3424 /* If target struct exists, clear sense valid flag.
3427 completionCode
= MPT_SCANDV_GOOD
;
3429 SCSIIOReply_t
*pReply
;
3433 pReply
= (SCSIIOReply_t
*) mr
;
3435 status
= le16_to_cpu(pReply
->IOCStatus
) & MPI_IOCSTATUS_MASK
;
3436 scsi_status
= pReply
->SCSIStatus
;
3438 ddvtprintk((KERN_NOTICE
" IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3439 status
, pReply
->SCSIState
, scsi_status
,
3440 le32_to_cpu(pReply
->IOCLogInfo
)));
3444 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE
: /* 0x0043 */
3445 completionCode
= MPT_SCANDV_SELECTION_TIMEOUT
;
3448 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR
: /* 0x0046 */
3449 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED
: /* 0x0048 */
3450 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED
: /* 0x004B */
3451 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED
: /* 0x004C */
3452 completionCode
= MPT_SCANDV_DID_RESET
;
3455 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN
: /* 0x0045 */
3456 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR
: /* 0x0040 */
3457 case MPI_IOCSTATUS_SUCCESS
: /* 0x0000 */
3458 if (pReply
->Function
== MPI_FUNCTION_CONFIG
) {
3459 ConfigReply_t
*pr
= (ConfigReply_t
*)mr
;
3460 completionCode
= MPT_SCANDV_GOOD
;
3461 hd
->pLocal
->header
.PageVersion
= pr
->Header
.PageVersion
;
3462 hd
->pLocal
->header
.PageLength
= pr
->Header
.PageLength
;
3463 hd
->pLocal
->header
.PageNumber
= pr
->Header
.PageNumber
;
3464 hd
->pLocal
->header
.PageType
= pr
->Header
.PageType
;
3466 } else if (pReply
->Function
== MPI_FUNCTION_RAID_ACTION
) {
3467 /* If the RAID Volume request is successful,
3468 * return GOOD, else indicate that
3469 * some type of error occurred.
3471 MpiRaidActionReply_t
*pr
= (MpiRaidActionReply_t
*)mr
;
3472 if (pr
->ActionStatus
== MPI_RAID_ACTION_ASTATUS_SUCCESS
)
3473 completionCode
= MPT_SCANDV_GOOD
;
3475 completionCode
= MPT_SCANDV_SOME_ERROR
;
3477 } else if (pReply
->SCSIState
& MPI_SCSI_STATE_AUTOSENSE_VALID
) {
3481 /* save sense data in global structure
3483 completionCode
= MPT_SCANDV_SENSE
;
3484 hd
->pLocal
->scsiStatus
= scsi_status
;
3485 sense_data
= ((u8
*)hd
->ioc
->sense_buf_pool
+
3486 (req_idx
* MPT_SENSE_BUFFER_ALLOC
));
3488 sz
= min_t(int, pReq
->SenseBufferLength
,
3489 SCSI_STD_SENSE_BYTES
);
3490 memcpy(hd
->pLocal
->sense
, sense_data
, sz
);
3492 ddvprintk((KERN_NOTICE
" Check Condition, sense ptr %p\n",
3494 } else if (pReply
->SCSIState
& MPI_SCSI_STATE_AUTOSENSE_FAILED
) {
3495 if (pReq
->CDB
[0] == INQUIRY
)
3496 completionCode
= MPT_SCANDV_ISSUE_SENSE
;
3498 completionCode
= MPT_SCANDV_DID_RESET
;
3500 else if (pReply
->SCSIState
& MPI_SCSI_STATE_NO_SCSI_STATUS
)
3501 completionCode
= MPT_SCANDV_DID_RESET
;
3502 else if (pReply
->SCSIState
& MPI_SCSI_STATE_TERMINATED
)
3503 completionCode
= MPT_SCANDV_DID_RESET
;
3505 completionCode
= MPT_SCANDV_GOOD
;
3506 hd
->pLocal
->scsiStatus
= scsi_status
;
3510 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR
: /* 0x0047 */
3511 if (pReply
->SCSIState
& MPI_SCSI_STATE_TERMINATED
)
3512 completionCode
= MPT_SCANDV_DID_RESET
;
3514 completionCode
= MPT_SCANDV_SOME_ERROR
;
3518 completionCode
= MPT_SCANDV_SOME_ERROR
;
3521 } /* switch(status) */
3523 ddvtprintk((KERN_NOTICE
" completionCode set to %08xh\n",
3525 } /* end of address reply case */
3527 hd
->pLocal
->completion
= completionCode
;
3529 /* MF and RF are freed in mpt_interrupt
3532 /* Free Chain buffers (will never chain) in scan or dv */
3533 //mptscsih_freeChainBuffers(ioc, req_idx);
3536 * Wake up the original calling thread
3538 hd
->scandv_wait_done
= 1;
3539 wake_up(&hd
->scandv_waitq
);
3544 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3545 /* mptscsih_timer_expired - Call back for timer process.
3546 * Used only for dv functionality.
3547 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3551 mptscsih_timer_expired(unsigned long data
)
3553 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*) data
;
3555 ddvprintk((MYIOC_s_WARN_FMT
"Timer Expired! Cmd %p\n", hd
->ioc
->name
, hd
->cmdPtr
));
3558 MPIHeader_t
*cmd
= (MPIHeader_t
*)hd
->cmdPtr
;
3560 if (cmd
->Function
== MPI_FUNCTION_SCSI_IO_REQUEST
) {
3561 /* Desire to issue a task management request here.
3562 * TM requests MUST be single threaded.
3563 * If old eh code and no TM current, issue request.
3564 * If new eh code, do nothing. Wait for OS cmd timeout
3567 ddvtprintk((MYIOC_s_NOTE_FMT
"DV Cmd Timeout: NoOp\n", hd
->ioc
->name
));
3569 /* Perform a FW reload */
3570 if (mpt_HardResetHandler(hd
->ioc
, NO_SLEEP
) < 0) {
3571 printk(MYIOC_s_WARN_FMT
"Firmware Reload FAILED!\n", hd
->ioc
->name
);
3575 /* This should NEVER happen */
3576 printk(MYIOC_s_WARN_FMT
"Null cmdPtr!!!!\n", hd
->ioc
->name
);
3579 /* No more processing.
3580 * TM call will generate an interrupt for SCSI TM Management.
3581 * The FW will reply to all outstanding commands, callback will finish cleanup.
3582 * Hard reset clean-up will free all resources.
3584 ddvprintk((MYIOC_s_WARN_FMT
"Timer Expired Complete!\n", hd
->ioc
->name
));
3589 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3590 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3591 /* mptscsih_do_raid - Format and Issue a RAID volume request message.
3592 * @hd: Pointer to scsi host structure
3593 * @action: What do be done.
3594 * @id: Logical target id.
3595 * @bus: Target locations bus.
3597 * Returns: < 0 on a fatal error
3600 * Remark: Wait to return until reply processed by the ISR.
3603 mptscsih_do_raid(MPT_SCSI_HOST
*hd
, u8 action
, INTERNAL_CMD
*io
)
3605 MpiRaidActionRequest_t
*pReq
;
3609 in_isr
= in_interrupt();
3611 dprintk((MYIOC_s_WARN_FMT
"Internal raid request not allowed in ISR context!\n",
3616 /* Get and Populate a free Frame
3618 if ((mf
= mpt_get_msg_frame(hd
->ioc
->InternalCtx
, hd
->ioc
)) == NULL
) {
3619 ddvprintk((MYIOC_s_WARN_FMT
"_do_raid: no msg frames!\n",
3623 pReq
= (MpiRaidActionRequest_t
*)mf
;
3624 pReq
->Action
= action
;
3625 pReq
->Reserved1
= 0;
3626 pReq
->ChainOffset
= 0;
3627 pReq
->Function
= MPI_FUNCTION_RAID_ACTION
;
3628 pReq
->VolumeID
= io
->id
;
3629 pReq
->VolumeBus
= io
->bus
;
3630 pReq
->PhysDiskNum
= io
->physDiskNum
;
3632 pReq
->Reserved2
= 0;
3633 pReq
->ActionDataWord
= 0; /* Reserved for this action */
3634 //pReq->ActionDataSGE = 0;
3636 mpt_add_sge((char *)&pReq
->ActionDataSGE
,
3637 MPT_SGE_FLAGS_SSIMPLE_READ
| 0, (dma_addr_t
) -1);
3639 ddvprintk((MYIOC_s_INFO_FMT
"RAID Volume action %x id %d\n",
3640 hd
->ioc
->name
, action
, io
->id
));
3643 hd
->timer
.expires
= jiffies
+ HZ
*10; /* 10 second timeout */
3644 hd
->scandv_wait_done
= 0;
3646 /* Save cmd pointer, for resource free if timeout or
3651 add_timer(&hd
->timer
);
3652 mpt_put_msg_frame(hd
->ioc
->InternalCtx
, hd
->ioc
, mf
);
3653 wait_event(hd
->scandv_waitq
, hd
->scandv_wait_done
);
3655 if ((hd
->pLocal
== NULL
) || (hd
->pLocal
->completion
!= MPT_SCANDV_GOOD
))
3660 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
3662 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3664 * mptscsih_do_cmd - Do internal command.
3665 * @hd: MPT_SCSI_HOST pointer
3666 * @io: INTERNAL_CMD pointer.
3668 * Issue the specified internally generated command and do command
3669 * specific cleanup. For bus scan / DV only.
3670 * NOTES: If command is Inquiry and status is good,
3671 * initialize a target structure, save the data
3673 * Remark: Single threaded access only.
3676 * < 0 if an illegal command or no resources
3680 * > 0 if command complete but some type of completion error.
3683 mptscsih_do_cmd(MPT_SCSI_HOST
*hd
, INTERNAL_CMD
*io
)
3686 SCSIIORequest_t
*pScsiReq
;
3687 SCSIIORequest_t ReqCopy
;
3688 int my_idx
, ii
, dir
;
3692 char CDB
[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3695 in_isr
= in_interrupt();
3697 dprintk((MYIOC_s_WARN_FMT
"Internal SCSI IO request not allowed in ISR context!\n",
3703 /* Set command specific information
3708 dir
= MPI_SCSIIO_CONTROL_READ
;
3714 case TEST_UNIT_READY
:
3716 dir
= MPI_SCSIIO_CONTROL_READ
;
3722 dir
= MPI_SCSIIO_CONTROL_READ
;
3724 CDB
[4] = 1; /*Spin up the disk */
3732 dir
= MPI_SCSIIO_CONTROL_READ
;
3738 dir
= MPI_SCSIIO_CONTROL_READ
;
3740 if (io
->flags
& MPT_ICFLAG_ECHO
) {
3746 if (io
->flags
& MPT_ICFLAG_BUF_CAP
) {
3749 CDB
[6] = (io
->size
>> 16) & 0xFF;
3750 CDB
[7] = (io
->size
>> 8) & 0xFF;
3751 CDB
[8] = io
->size
& 0xFF;
3757 dir
= MPI_SCSIIO_CONTROL_WRITE
;
3759 if (io
->flags
& MPT_ICFLAG_ECHO
) {
3764 CDB
[6] = (io
->size
>> 16) & 0xFF;
3765 CDB
[7] = (io
->size
>> 8) & 0xFF;
3766 CDB
[8] = io
->size
& 0xFF;
3772 dir
= MPI_SCSIIO_CONTROL_READ
;
3779 dir
= MPI_SCSIIO_CONTROL_READ
;
3784 case SYNCHRONIZE_CACHE
:
3786 dir
= MPI_SCSIIO_CONTROL_READ
;
3788 // CDB[1] = 0x02; /* set immediate bit */
3797 /* Get and Populate a free Frame
3799 if ((mf
= mpt_get_msg_frame(hd
->ioc
->InternalCtx
, hd
->ioc
)) == NULL
) {
3800 ddvprintk((MYIOC_s_WARN_FMT
"No msg frames!\n",
3805 pScsiReq
= (SCSIIORequest_t
*) mf
;
3807 /* Get the request index */
3808 my_idx
= le16_to_cpu(mf
->u
.frame
.hwhdr
.msgctxu
.fld
.req_idx
);
3809 ADD_INDEX_LOG(my_idx
); /* for debug */
3811 if (io
->flags
& MPT_ICFLAG_PHYS_DISK
) {
3812 pScsiReq
->TargetID
= io
->physDiskNum
;
3814 pScsiReq
->ChainOffset
= 0;
3815 pScsiReq
->Function
= MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH
;
3817 pScsiReq
->TargetID
= io
->id
;
3818 pScsiReq
->Bus
= io
->bus
;
3819 pScsiReq
->ChainOffset
= 0;
3820 pScsiReq
->Function
= MPI_FUNCTION_SCSI_IO_REQUEST
;
3823 pScsiReq
->CDBLength
= cmdLen
;
3824 pScsiReq
->SenseBufferLength
= MPT_SENSE_BUFFER_SIZE
;
3826 pScsiReq
->Reserved
= 0;
3828 pScsiReq
->MsgFlags
= mpt_msg_flags();
3829 /* MsgContext set in mpt_get_msg_fram call */
3831 for (ii
=0; ii
< 8; ii
++)
3832 pScsiReq
->LUN
[ii
] = 0;
3833 pScsiReq
->LUN
[1] = io
->lun
;
3835 if (io
->flags
& MPT_ICFLAG_TAGGED_CMD
)
3836 pScsiReq
->Control
= cpu_to_le32(dir
| MPI_SCSIIO_CONTROL_SIMPLEQ
);
3838 pScsiReq
->Control
= cpu_to_le32(dir
| MPI_SCSIIO_CONTROL_UNTAGGED
);
3840 if (cmd
== REQUEST_SENSE
) {
3841 pScsiReq
->Control
= cpu_to_le32(dir
| MPI_SCSIIO_CONTROL_UNTAGGED
);
3842 ddvprintk((MYIOC_s_INFO_FMT
"Untagged! 0x%2x\n",
3843 hd
->ioc
->name
, cmd
));
3846 for (ii
=0; ii
< 16; ii
++)
3847 pScsiReq
->CDB
[ii
] = CDB
[ii
];
3849 pScsiReq
->DataLength
= cpu_to_le32(io
->size
);
3850 pScsiReq
->SenseBufferLowAddr
= cpu_to_le32(hd
->ioc
->sense_buf_low_dma
3851 + (my_idx
* MPT_SENSE_BUFFER_ALLOC
));
3853 ddvprintk((MYIOC_s_INFO_FMT
"Sending Command 0x%x for (%d:%d:%d)\n",
3854 hd
->ioc
->name
, cmd
, io
->bus
, io
->id
, io
->lun
));
3856 if (dir
== MPI_SCSIIO_CONTROL_READ
) {
3857 mpt_add_sge((char *) &pScsiReq
->SGL
,
3858 MPT_SGE_FLAGS_SSIMPLE_READ
| io
->size
,
3861 mpt_add_sge((char *) &pScsiReq
->SGL
,
3862 MPT_SGE_FLAGS_SSIMPLE_WRITE
| io
->size
,
3866 /* The ISR will free the request frame, but we need
3867 * the information to initialize the target. Duplicate.
3869 memcpy(&ReqCopy
, pScsiReq
, sizeof(SCSIIORequest_t
));
3871 /* Issue this command after:
3874 * Wait until the reply has been received
3875 * ScsiScanDvCtx callback function will
3877 * set scandv_wait_done and call wake_up
3880 hd
->timer
.expires
= jiffies
+ HZ
*cmdTimeout
;
3881 hd
->scandv_wait_done
= 0;
3883 /* Save cmd pointer, for resource free if timeout or
3888 add_timer(&hd
->timer
);
3889 mpt_put_msg_frame(hd
->ioc
->InternalCtx
, hd
->ioc
, mf
);
3890 wait_event(hd
->scandv_waitq
, hd
->scandv_wait_done
);
3893 rc
= hd
->pLocal
->completion
;
3894 hd
->pLocal
->skip
= 0;
3896 /* Always set fatal error codes in some cases.
3898 if (rc
== MPT_SCANDV_SELECTION_TIMEOUT
)
3900 else if (rc
== MPT_SCANDV_SOME_ERROR
)
3904 /* This should never happen. */
3905 ddvprintk((MYIOC_s_INFO_FMT
"_do_cmd: Null pLocal!!!\n",
3912 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3914 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3915 * @hd: Pointer to MPT_SCSI_HOST structure
3916 * @portnum: IOC port number
3918 * Uses the ISR, but with special processing.
3919 * MUST be single-threaded.
3921 * Return: 0 on completion
3924 mptscsih_synchronize_cache(MPT_SCSI_HOST
*hd
, int portnum
)
3926 MPT_ADAPTER
*ioc
= hd
->ioc
;
3927 VirtDevice
*pTarget
;
3928 SCSIDevicePage1_t
*pcfg1Data
= NULL
;
3931 dma_addr_t cfg1_dma_addr
= -1;
3932 ConfigPageHeader_t header1
;
3936 int indexed_lun
, lun_index
;
3937 int hostId
= ioc
->pfacts
[portnum
].PortSCSIID
;
3939 int requested
, configuration
, data
;
3943 max_id
= ioc
->sh
->max_id
- 1;
3945 /* Following parameters will not change
3948 iocmd
.cmd
= SYNCHRONIZE_CACHE
;
3950 iocmd
.physDiskNum
= -1;
3952 iocmd
.data_dma
= -1;
3954 iocmd
.rsvd
= iocmd
.rsvd2
= 0;
3958 if (hd
->Targets
== NULL
)
3966 /* Write SDP1 for all SCSI devices
3967 * Alloc memory and set up config buffer
3969 if (ioc
->bus_type
== SCSI
) {
3970 if (ioc
->spi_data
.sdp1length
> 0) {
3971 pcfg1Data
= (SCSIDevicePage1_t
*)pci_alloc_consistent(ioc
->pcidev
,
3972 ioc
->spi_data
.sdp1length
* 4, &cfg1_dma_addr
);
3974 if (pcfg1Data
!= NULL
) {
3976 header1
.PageVersion
= ioc
->spi_data
.sdp1version
;
3977 header1
.PageLength
= ioc
->spi_data
.sdp1length
;
3978 header1
.PageNumber
= 1;
3979 header1
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_DEVICE
;
3981 cfg
.physAddr
= cfg1_dma_addr
;
3982 cfg
.action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
3989 /* loop through all devices on this port
3991 while (bus
< MPT_MAX_BUS
) {
3994 pTarget
= hd
->Targets
[(int)id
];
3998 /* Set the negotiation flags */
3999 if (pTarget
&& (pTarget
= hd
->Targets
[id
]) && !pTarget
->raidVolume
) {
4000 flags
= pTarget
->negoFlags
;
4002 flags
= hd
->ioc
->spi_data
.noQas
;
4003 if (hd
->ioc
->spi_data
.nvram
&& (hd
->ioc
->spi_data
.nvram
[id
] != MPT_HOST_NVRAM_INVALID
)) {
4004 data
= hd
->ioc
->spi_data
.nvram
[id
];
4006 if (data
& MPT_NVRAM_WIDE_DISABLE
)
4007 flags
|= MPT_TARGET_NO_NEGO_WIDE
;
4009 factor
= (data
& MPT_NVRAM_SYNC_MASK
) >> MPT_NVRAM_SYNC_SHIFT
;
4010 if ((factor
== 0) || (factor
== MPT_ASYNC
))
4011 flags
|= MPT_TARGET_NO_NEGO_SYNC
;
4015 /* Force to async, narrow */
4016 mptscsih_setDevicePage1Flags(0, MPT_ASYNC
, 0, &requested
,
4017 &configuration
, flags
);
4018 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
4019 "offset=0 negoFlags=%x request=%x config=%x\n",
4020 id
, flags
, requested
, configuration
));
4021 pcfg1Data
->RequestedParameters
= le32_to_cpu(requested
);
4022 pcfg1Data
->Reserved
= 0;
4023 pcfg1Data
->Configuration
= le32_to_cpu(configuration
);
4024 cfg
.pageAddr
= (bus
<<8) | id
;
4025 mpt_config(hd
->ioc
, &cfg
);
4028 /* If target Ptr NULL or if this target is NOT a disk, skip.
4030 if ((pTarget
) && (pTarget
->tflags
& MPT_TARGET_FLAGS_Q_YES
)){
4031 for (lun
=0; lun
<= MPT_LAST_LUN
; lun
++) {
4032 /* If LUN present, issue the command
4034 lun_index
= (lun
>> 5); /* 32 luns per lun_index */
4035 indexed_lun
= (lun
% 32);
4036 if (pTarget
->luns
[lun_index
] & (1<<indexed_lun
)) {
4038 (void) mptscsih_do_cmd(hd
, &iocmd
);
4043 /* get next relevant device */
4056 pci_free_consistent(ioc
->pcidev
, header1
.PageLength
* 4, pcfg1Data
, cfg1_dma_addr
);
4062 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4063 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4065 * mptscsih_domainValidation - Top level handler for domain validation.
4066 * @hd: Pointer to MPT_SCSI_HOST structure.
4068 * Uses the ISR, but with special processing.
4069 * Called from schedule, should not be in interrupt mode.
4070 * While thread alive, do dv for all devices needing dv
4075 mptscsih_domainValidation(void *arg
)
4079 unsigned long flags
;
4080 int id
, maxid
, dvStatus
, did
;
4083 spin_lock_irqsave(&dvtaskQ_lock
, flags
);
4085 if (dvtaskQ_release
) {
4087 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4090 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4092 /* For this ioc, loop through all devices and do dv to each device.
4093 * When complete with this ioc, search through the ioc list, and
4094 * for each scsi ioc found, do dv for all devices. Exit when no
4100 list_for_each_entry(ioc
, &ioc_list
, list
) {
4101 spin_lock_irqsave(&dvtaskQ_lock
, flags
);
4102 if (dvtaskQ_release
) {
4104 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4107 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4111 /* DV only to SCSI adapters */
4112 if (ioc
->bus_type
!= SCSI
)
4115 /* Make sure everything looks ok */
4116 if (ioc
->sh
== NULL
)
4119 hd
= (MPT_SCSI_HOST
*) ioc
->sh
->hostdata
;
4123 if ((ioc
->spi_data
.forceDv
& MPT_SCSICFG_RELOAD_IOC_PG3
) != 0) {
4124 mpt_read_ioc_pg_3(ioc
);
4125 if (ioc
->spi_data
.pIocPg3
) {
4126 Ioc3PhysDisk_t
*pPDisk
= ioc
->spi_data
.pIocPg3
->PhysDisk
;
4127 int numPDisk
= ioc
->spi_data
.pIocPg3
->NumPhysDisks
;
4130 if (ioc
->spi_data
.dvStatus
[pPDisk
->PhysDiskID
] & MPT_SCSICFG_DV_NOT_DONE
)
4131 ioc
->spi_data
.dvStatus
[pPDisk
->PhysDiskID
] |= MPT_SCSICFG_NEED_DV
;
4137 ioc
->spi_data
.forceDv
&= ~MPT_SCSICFG_RELOAD_IOC_PG3
;
4140 maxid
= min_t(int, ioc
->sh
->max_id
, MPT_MAX_SCSI_DEVICES
);
4142 for (id
= 0; id
< maxid
; id
++) {
4143 spin_lock_irqsave(&dvtaskQ_lock
, flags
);
4144 if (dvtaskQ_release
) {
4146 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4149 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4150 dvStatus
= hd
->ioc
->spi_data
.dvStatus
[id
];
4152 if (dvStatus
& MPT_SCSICFG_NEED_DV
) {
4154 hd
->ioc
->spi_data
.dvStatus
[id
] |= MPT_SCSICFG_DV_PENDING
;
4155 hd
->ioc
->spi_data
.dvStatus
[id
] &= ~MPT_SCSICFG_NEED_DV
;
4159 /* If hidden phys disk, block IO's to all
4161 * else, process normally
4163 isPhysDisk
= mptscsih_is_phys_disk(ioc
, id
);
4165 for (ii
=0; ii
< MPT_MAX_SCSI_DEVICES
; ii
++) {
4166 if (hd
->ioc
->spi_data
.isRaid
& (1 << ii
)) {
4167 hd
->ioc
->spi_data
.dvStatus
[ii
] |= MPT_SCSICFG_DV_PENDING
;
4172 if (mptscsih_doDv(hd
, 0, id
) == 1) {
4173 /* Untagged device was busy, try again
4175 hd
->ioc
->spi_data
.dvStatus
[id
] |= MPT_SCSICFG_NEED_DV
;
4176 hd
->ioc
->spi_data
.dvStatus
[id
] &= ~MPT_SCSICFG_DV_PENDING
;
4178 /* DV is complete. Clear flags.
4180 hd
->ioc
->spi_data
.dvStatus
[id
] &= ~(MPT_SCSICFG_DV_NOT_DONE
| MPT_SCSICFG_DV_PENDING
);
4184 for (ii
=0; ii
< MPT_MAX_SCSI_DEVICES
; ii
++) {
4185 if (hd
->ioc
->spi_data
.isRaid
& (1 << ii
)) {
4186 hd
->ioc
->spi_data
.dvStatus
[ii
] &= ~MPT_SCSICFG_DV_PENDING
;
4191 if (hd
->ioc
->spi_data
.noQas
)
4192 mptscsih_qas_check(hd
, id
);
4198 spin_lock_irqsave(&dvtaskQ_lock
, flags
);
4200 spin_unlock_irqrestore(&dvtaskQ_lock
, flags
);
4205 /* Search IOC page 3 to determine if this is hidden physical disk
4208 mptscsih_is_phys_disk(MPT_ADAPTER
*ioc
, int id
)
4210 if (ioc
->spi_data
.pIocPg3
) {
4211 Ioc3PhysDisk_t
*pPDisk
= ioc
->spi_data
.pIocPg3
->PhysDisk
;
4212 int numPDisk
= ioc
->spi_data
.pIocPg3
->NumPhysDisks
;
4215 if (pPDisk
->PhysDiskID
== id
) {
4225 /* Write SDP1 if no QAS has been enabled
4228 mptscsih_qas_check(MPT_SCSI_HOST
*hd
, int id
)
4230 VirtDevice
*pTarget
;
4233 if (hd
->Targets
== NULL
)
4236 for (ii
=0; ii
< MPT_MAX_SCSI_DEVICES
; ii
++) {
4240 if ((hd
->ioc
->spi_data
.dvStatus
[ii
] & MPT_SCSICFG_DV_NOT_DONE
) != 0)
4243 pTarget
= hd
->Targets
[ii
];
4245 if ((pTarget
!= NULL
) && (!pTarget
->raidVolume
)) {
4246 if ((pTarget
->negoFlags
& hd
->ioc
->spi_data
.noQas
) == 0) {
4247 pTarget
->negoFlags
|= hd
->ioc
->spi_data
.noQas
;
4248 dnegoprintk(("writeSDP1: id=%d flags=0\n", id
));
4249 mptscsih_writeSDP1(hd
, 0, ii
, 0);
4252 if (mptscsih_is_phys_disk(hd
->ioc
, ii
) == 1) {
4253 dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id
));
4254 mptscsih_writeSDP1(hd
, 0, ii
, MPT_SCSICFG_USE_NVRAM
);
4263 #define MPT_GET_NVRAM_VALS 0x01
4264 #define MPT_UPDATE_MAX 0x02
4265 #define MPT_SET_MAX 0x04
4266 #define MPT_SET_MIN 0x08
4267 #define MPT_FALLBACK 0x10
4268 #define MPT_SAVE 0x20
4270 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4272 * mptscsih_doDv - Perform domain validation to a target.
4273 * @hd: Pointer to MPT_SCSI_HOST structure.
4274 * @portnum: IOC port number.
4275 * @target: Physical ID of this target
4277 * Uses the ISR, but with special processing.
4278 * MUST be single-threaded.
4279 * Test will exit if target is at async & narrow.
4284 mptscsih_doDv(MPT_SCSI_HOST
*hd
, int bus_number
, int id
)
4286 MPT_ADAPTER
*ioc
= hd
->ioc
;
4287 VirtDevice
*pTarget
;
4288 SCSIDevicePage1_t
*pcfg1Data
;
4289 SCSIDevicePage0_t
*pcfg0Data
;
4293 dma_addr_t dvbuf_dma
= -1;
4294 dma_addr_t buf1_dma
= -1;
4295 dma_addr_t buf2_dma
= -1;
4296 dma_addr_t cfg1_dma_addr
= -1;
4297 dma_addr_t cfg0_dma_addr
= -1;
4298 ConfigPageHeader_t header1
;
4299 ConfigPageHeader_t header0
;
4306 int dataBufSize
= 0;
4307 int echoBufSize
= 0;
4312 int nfactor
= MPT_ULTRA320
;
4314 char doFallback
= 0;
4319 if (ioc
->spi_data
.sdp1length
== 0)
4322 if (ioc
->spi_data
.sdp0length
== 0)
4325 /* If multiple buses are used, require that the initiator
4326 * id be the same on all buses.
4328 if (id
== ioc
->pfacts
[0].PortSCSIID
)
4332 bus
= (u8
) bus_number
;
4333 ddvtprintk((MYIOC_s_NOTE_FMT
4334 "DV started: bus=%d, id=%d dv @ %p\n",
4335 ioc
->name
, bus
, id
, &dv
));
4337 /* Prep DV structure
4339 memset (&dv
, 0, sizeof(DVPARAMETERS
));
4342 /* Populate tmax with the current maximum
4343 * transfer parameters for this target.
4344 * Exit if narrow and async.
4346 dv
.cmd
= MPT_GET_NVRAM_VALS
;
4347 mptscsih_dv_parms(hd
, &dv
, NULL
);
4349 /* Prep SCSI IO structure
4355 iocmd
.physDiskNum
= -1;
4356 iocmd
.rsvd
= iocmd
.rsvd2
= 0;
4358 pTarget
= hd
->Targets
[id
];
4360 /* Use tagged commands if possible.
4363 if (pTarget
->tflags
& MPT_TARGET_FLAGS_Q_YES
)
4364 iocmd
.flags
|= MPT_ICFLAG_TAGGED_CMD
;
4366 if (hd
->ioc
->facts
.FWVersion
.Word
< 0x01000600)
4369 if ((hd
->ioc
->facts
.FWVersion
.Word
>= 0x01010000) &&
4370 (hd
->ioc
->facts
.FWVersion
.Word
< 0x01010B00))
4375 /* Prep cfg structure
4377 cfg
.pageAddr
= (bus
<<8) | id
;
4382 header0
.PageVersion
= ioc
->spi_data
.sdp0version
;
4383 header0
.PageLength
= ioc
->spi_data
.sdp0length
;
4384 header0
.PageNumber
= 0;
4385 header0
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_DEVICE
;
4389 header1
.PageVersion
= ioc
->spi_data
.sdp1version
;
4390 header1
.PageLength
= ioc
->spi_data
.sdp1length
;
4391 header1
.PageNumber
= 1;
4392 header1
.PageType
= MPI_CONFIG_PAGETYPE_SCSI_DEVICE
;
4394 if (header0
.PageLength
& 1)
4395 dv_alloc
= (header0
.PageLength
* 4) + 4;
4397 dv_alloc
+= (2048 + (header1
.PageLength
* 4));
4399 pDvBuf
= pci_alloc_consistent(ioc
->pcidev
, dv_alloc
, &dvbuf_dma
);
4404 pbuf1
= (u8
*)pDvBuf
;
4405 buf1_dma
= dvbuf_dma
;
4408 pbuf2
= (u8
*) (pDvBuf
+ sz
);
4409 buf2_dma
= dvbuf_dma
+ sz
;
4412 pcfg0Data
= (SCSIDevicePage0_t
*) (pDvBuf
+ sz
);
4413 cfg0_dma_addr
= dvbuf_dma
+ sz
;
4414 sz
+= header0
.PageLength
* 4;
4418 if (header0
.PageLength
& 1)
4421 pcfg1Data
= (SCSIDevicePage1_t
*) (pDvBuf
+ sz
);
4422 cfg1_dma_addr
= dvbuf_dma
+ sz
;
4424 /* Skip this ID? Set cfg.hdr to force config page write
4427 ScsiCfgData
*pspi_data
= &hd
->ioc
->spi_data
;
4428 if (pspi_data
->nvram
&& (pspi_data
->nvram
[id
] != MPT_HOST_NVRAM_INVALID
)) {
4429 /* Set the factor from nvram */
4430 nfactor
= (pspi_data
->nvram
[id
] & MPT_NVRAM_SYNC_MASK
) >> 8;
4431 if (nfactor
< pspi_data
->minSyncFactor
)
4432 nfactor
= pspi_data
->minSyncFactor
;
4434 if (!(pspi_data
->nvram
[id
] & MPT_NVRAM_ID_SCAN_ENABLE
) ||
4435 (pspi_data
->PortFlags
== MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV
) ) {
4437 ddvprintk((MYIOC_s_NOTE_FMT
"DV Skipped: bus, id, lun (%d, %d, %d)\n",
4438 ioc
->name
, bus
, id
, lun
));
4440 dv
.cmd
= MPT_SET_MAX
;
4441 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
4444 /* Save the final negotiated settings to
4445 * SCSI device page 1.
4447 cfg
.physAddr
= cfg1_dma_addr
;
4448 cfg
.action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
4450 mpt_config(hd
->ioc
, &cfg
);
4456 /* Finish iocmd inititialization - hidden or visible disk? */
4457 if (ioc
->spi_data
.pIocPg3
) {
4458 /* Search IOC page 3 for matching id
4460 Ioc3PhysDisk_t
*pPDisk
= ioc
->spi_data
.pIocPg3
->PhysDisk
;
4461 int numPDisk
= ioc
->spi_data
.pIocPg3
->NumPhysDisks
;
4464 if (pPDisk
->PhysDiskID
== id
) {
4466 iocmd
.flags
|= MPT_ICFLAG_PHYS_DISK
;
4467 iocmd
.physDiskNum
= pPDisk
->PhysDiskNum
;
4471 if (mptscsih_do_raid(hd
, MPI_RAID_ACTION_QUIESCE_PHYS_IO
, &iocmd
) < 0) {
4472 ddvprintk((MYIOC_s_ERR_FMT
"RAID Queisce FAILED!\n", ioc
->name
));
4482 /* RAID Volume ID's may double for a physical device. If RAID but
4483 * not a physical ID as well, skip DV.
4485 if ((hd
->ioc
->spi_data
.isRaid
& (1 << id
)) && !(iocmd
.flags
& MPT_ICFLAG_PHYS_DISK
))
4490 * Async & Narrow - Inquiry
4491 * Async & Narrow - Inquiry
4492 * Maximum transfer rate - Inquiry
4494 * If compare, test complete.
4495 * If miscompare and first pass, repeat
4496 * If miscompare and not first pass, fall back and repeat
4500 sz
= SCSI_MAX_INQUIRY_BYTES
;
4501 rc
= MPT_SCANDV_GOOD
;
4503 ddvprintk((MYIOC_s_NOTE_FMT
"DV: Start Basic test on id=%d\n", ioc
->name
, id
));
4505 dv
.cmd
= MPT_SET_MIN
;
4506 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
4509 cfg
.physAddr
= cfg1_dma_addr
;
4510 cfg
.action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
4512 if (mpt_config(hd
->ioc
, &cfg
) != 0)
4515 /* Wide - narrow - wide workaround case
4517 if ((rc
== MPT_SCANDV_ISSUE_SENSE
) && dv
.max
.width
) {
4518 /* Send an untagged command to reset disk Qs corrupted
4519 * when a parity error occurs on a Request Sense.
4521 if ((hd
->ioc
->facts
.FWVersion
.Word
>= 0x01000600) ||
4522 ((hd
->ioc
->facts
.FWVersion
.Word
>= 0x01010000) &&
4523 (hd
->ioc
->facts
.FWVersion
.Word
< 0x01010B00)) ) {
4525 iocmd
.cmd
= REQUEST_SENSE
;
4526 iocmd
.data_dma
= buf1_dma
;
4529 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4532 if (hd
->pLocal
== NULL
)
4534 rc
= hd
->pLocal
->completion
;
4535 if ((rc
== MPT_SCANDV_GOOD
) || (rc
== MPT_SCANDV_SENSE
)) {
4545 iocmd
.cmd
= INQUIRY
;
4546 iocmd
.data_dma
= buf1_dma
;
4549 memset(pbuf1
, 0x00, sz
);
4550 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4553 if (hd
->pLocal
== NULL
)
4555 rc
= hd
->pLocal
->completion
;
4556 if (rc
== MPT_SCANDV_GOOD
) {
4557 if (hd
->pLocal
->scsiStatus
== SAM_STAT_BUSY
) {
4558 if ((iocmd
.flags
& MPT_ICFLAG_TAGGED_CMD
) == 0)
4565 } else if (rc
== MPT_SCANDV_SENSE
) {
4568 /* If first command doesn't complete
4569 * with a good status or with a check condition,
4576 /* Reset the size for disks
4578 inq0
= (*pbuf1
) & 0x1F;
4579 if ((inq0
== 0) && pTarget
&& !pTarget
->raidVolume
) {
4584 /* Another GEM workaround. Check peripheral device type,
4585 * if PROCESSOR, quit DV.
4587 if (inq0
== TYPE_PROCESSOR
) {
4588 mptscsih_initTarget(hd
,
4600 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4604 if ((pTarget
->maxWidth
== 1) && (pTarget
->maxOffset
) && (nfactor
< 0x0A)
4605 && (pTarget
->minSyncFactor
> 0x09)) {
4606 if ((pbuf1
[56] & 0x04) == 0)
4608 else if ((pbuf1
[56] & 0x01) == 1) {
4609 pTarget
->minSyncFactor
=
4610 nfactor
> MPT_ULTRA320
? nfactor
: MPT_ULTRA320
;
4612 pTarget
->minSyncFactor
=
4613 nfactor
> MPT_ULTRA160
? nfactor
: MPT_ULTRA160
;
4616 dv
.max
.factor
= pTarget
->minSyncFactor
;
4618 if ((pbuf1
[56] & 0x02) == 0) {
4619 pTarget
->negoFlags
|= MPT_TARGET_NO_NEGO_QAS
;
4620 hd
->ioc
->spi_data
.noQas
= MPT_TARGET_NO_NEGO_QAS
;
4621 ddvprintk((MYIOC_s_NOTE_FMT
4622 "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
4623 ioc
->name
, id
, pbuf1
[56]));
4629 dv
.cmd
= MPT_FALLBACK
;
4631 dv
.cmd
= MPT_SET_MAX
;
4633 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
4634 if (mpt_config(hd
->ioc
, &cfg
) != 0)
4637 if ((!dv
.now
.width
) && (!dv
.now
.offset
))
4640 iocmd
.cmd
= INQUIRY
;
4641 iocmd
.data_dma
= buf2_dma
;
4644 memset(pbuf2
, 0x00, sz
);
4645 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4647 else if (hd
->pLocal
== NULL
)
4650 /* Save the return code.
4651 * If this is the first pass,
4652 * read SCSI Device Page 0
4653 * and update the target max parameters.
4655 rc
= hd
->pLocal
->completion
;
4657 if (rc
== MPT_SCANDV_GOOD
) {
4663 cfg
.physAddr
= cfg0_dma_addr
;
4664 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
4667 if (mpt_config(hd
->ioc
, &cfg
) != 0)
4670 sdp0_info
= le32_to_cpu(pcfg0Data
->Information
) & 0x0E;
4671 sdp0_nego
= (le32_to_cpu(pcfg0Data
->NegotiatedParameters
) & 0xFF00 ) >> 8;
4673 /* Quantum and Fujitsu workarounds.
4674 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
4675 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
4676 * Resetart with a request for U160.
4678 if ((dv
.now
.factor
== MPT_ULTRA320
) && (sdp0_nego
== MPT_ULTRA2
)) {
4681 dv
.cmd
= MPT_UPDATE_MAX
;
4682 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg0Data
);
4683 /* Update the SCSI device page 1 area
4685 pcfg1Data
->RequestedParameters
= pcfg0Data
->NegotiatedParameters
;
4690 /* Quantum workaround. Restart this test will the fallback
4693 if (doFallback
== 0) {
4694 if (memcmp(pbuf1
, pbuf2
, sz
) != 0) {
4698 ddvprintk((MYIOC_s_NOTE_FMT
4699 "DV:Inquiry compared id=%d, calling initTarget\n", ioc
->name
, id
));
4700 hd
->ioc
->spi_data
.dvStatus
[id
] &= ~MPT_SCSICFG_DV_NOT_DONE
;
4701 mptscsih_initTarget(hd
,
4707 break; /* test complete */
4712 } else if (rc
== MPT_SCANDV_ISSUE_SENSE
)
4713 doFallback
= 1; /* set fallback flag */
4714 else if ((rc
== MPT_SCANDV_DID_RESET
) ||
4715 (rc
== MPT_SCANDV_SENSE
) ||
4716 (rc
== MPT_SCANDV_FALLBACK
))
4717 doFallback
= 1; /* set fallback flag */
4724 ddvprintk((MYIOC_s_NOTE_FMT
"DV: Basic test on id=%d completed OK.\n", ioc
->name
, id
));
4726 if (ioc
->spi_data
.mpt_dv
== 0)
4729 inq0
= (*pbuf1
) & 0x1F;
4731 /* Continue only for disks
4736 if ( ioc
->spi_data
.PortFlags
== MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY
)
4739 /* Start the Enhanced Test.
4740 * 0) issue TUR to clear out check conditions
4741 * 1) read capacity of echo (regular) buffer
4743 * 3) do write-read-compare data pattern test
4745 * 5) update nego parms to target struct
4748 cfg
.physAddr
= cfg1_dma_addr
;
4749 cfg
.action
= MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
;
4752 iocmd
.cmd
= TEST_UNIT_READY
;
4753 iocmd
.data_dma
= -1;
4758 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4761 if (hd
->pLocal
== NULL
)
4764 rc
= hd
->pLocal
->completion
;
4765 if (rc
== MPT_SCANDV_GOOD
)
4767 else if (rc
== MPT_SCANDV_SENSE
) {
4768 u8 skey
= hd
->pLocal
->sense
[2] & 0x0F;
4769 u8 asc
= hd
->pLocal
->sense
[12];
4770 u8 ascq
= hd
->pLocal
->sense
[13];
4771 ddvprintk((MYIOC_s_INFO_FMT
4772 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4773 ioc
->name
, skey
, asc
, ascq
));
4775 if (skey
== UNIT_ATTENTION
)
4776 notDone
++; /* repeat */
4777 else if ((skey
== NOT_READY
) &&
4778 (asc
== 0x04)&&(ascq
== 0x01)) {
4779 /* wait then repeat */
4782 } else if ((skey
== NOT_READY
) && (asc
== 0x3A)) {
4783 /* no medium, try read test anyway */
4786 /* All other errors are fatal.
4788 ddvprintk((MYIOC_s_INFO_FMT
"DV: fatal error.",
4796 iocmd
.cmd
= READ_BUFFER
;
4797 iocmd
.data_dma
= buf1_dma
;
4800 iocmd
.flags
|= MPT_ICFLAG_BUF_CAP
;
4804 for (patt
= 0; patt
< 2; patt
++) {
4806 iocmd
.flags
|= MPT_ICFLAG_ECHO
;
4808 iocmd
.flags
&= ~MPT_ICFLAG_ECHO
;
4814 /* If not ready after 8 trials,
4815 * give up on this device.
4820 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4822 else if (hd
->pLocal
== NULL
)
4825 rc
= hd
->pLocal
->completion
;
4826 ddvprintk(("ReadBuffer Comp Code %d", rc
));
4827 ddvprintk((" buff: %0x %0x %0x %0x\n",
4828 pbuf1
[0], pbuf1
[1], pbuf1
[2], pbuf1
[3]));
4830 if (rc
== MPT_SCANDV_GOOD
) {
4832 if (iocmd
.flags
& MPT_ICFLAG_ECHO
) {
4833 bufsize
= ((pbuf1
[2] & 0x1F) <<8) | pbuf1
[3];
4835 bufsize
= pbuf1
[1]<<16 | pbuf1
[2]<<8 | pbuf1
[3];
4837 } else if (rc
== MPT_SCANDV_SENSE
) {
4838 u8 skey
= hd
->pLocal
->sense
[2] & 0x0F;
4839 u8 asc
= hd
->pLocal
->sense
[12];
4840 u8 ascq
= hd
->pLocal
->sense
[13];
4841 ddvprintk((MYIOC_s_INFO_FMT
4842 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4843 ioc
->name
, skey
, asc
, ascq
));
4844 if (skey
== ILLEGAL_REQUEST
) {
4846 } else if (skey
== UNIT_ATTENTION
) {
4847 notDone
++; /* repeat */
4848 } else if ((skey
== NOT_READY
) &&
4849 (asc
== 0x04)&&(ascq
== 0x01)) {
4850 /* wait then repeat */
4854 /* All other errors are fatal.
4856 ddvprintk((MYIOC_s_INFO_FMT
"DV: fatal error.",
4861 /* All other errors are fatal
4868 if (iocmd
.flags
& MPT_ICFLAG_ECHO
)
4869 echoBufSize
= bufsize
;
4871 dataBufSize
= bufsize
;
4874 iocmd
.flags
&= ~MPT_ICFLAG_BUF_CAP
;
4876 /* Use echo buffers if possible,
4877 * Exit if both buffers are 0.
4879 if (echoBufSize
> 0) {
4880 iocmd
.flags
|= MPT_ICFLAG_ECHO
;
4881 if (dataBufSize
> 0)
4882 bufsize
= min(echoBufSize
, dataBufSize
);
4884 bufsize
= echoBufSize
;
4885 } else if (dataBufSize
== 0)
4888 ddvprintk((MYIOC_s_INFO_FMT
"%s Buffer Capacity %d\n", ioc
->name
,
4889 (iocmd
.flags
& MPT_ICFLAG_ECHO
) ? "Echo" : " ", bufsize
));
4891 /* Data buffers for write-read-compare test max 1K.
4893 sz
= min(bufsize
, 1024);
4896 * On first pass, always issue a reserve.
4897 * On additional loops, only if a reset has occurred.
4898 * iocmd.flags indicates if echo or regular buffer
4900 for (patt
= 0; patt
< 4; patt
++) {
4901 ddvprintk(("Pattern %d\n", patt
));
4902 if ((iocmd
.flags
& MPT_ICFLAG_RESERVED
) && (iocmd
.flags
& MPT_ICFLAG_DID_RESET
)) {
4903 iocmd
.cmd
= TEST_UNIT_READY
;
4904 iocmd
.data_dma
= -1;
4907 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4910 iocmd
.cmd
= RELEASE
;
4911 iocmd
.data_dma
= -1;
4914 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4916 else if (hd
->pLocal
== NULL
)
4919 rc
= hd
->pLocal
->completion
;
4920 ddvprintk(("Release rc %d\n", rc
));
4921 if (rc
== MPT_SCANDV_GOOD
)
4922 iocmd
.flags
&= ~MPT_ICFLAG_RESERVED
;
4926 iocmd
.flags
&= ~MPT_ICFLAG_RESERVED
;
4928 iocmd
.flags
&= ~MPT_ICFLAG_DID_RESET
;
4931 while (repeat
&& (!(iocmd
.flags
& MPT_ICFLAG_RESERVED
))) {
4932 iocmd
.cmd
= RESERVE
;
4933 iocmd
.data_dma
= -1;
4936 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4938 else if (hd
->pLocal
== NULL
)
4941 rc
= hd
->pLocal
->completion
;
4942 if (rc
== MPT_SCANDV_GOOD
) {
4943 iocmd
.flags
|= MPT_ICFLAG_RESERVED
;
4944 } else if (rc
== MPT_SCANDV_SENSE
) {
4945 /* Wait if coming ready
4947 u8 skey
= hd
->pLocal
->sense
[2] & 0x0F;
4948 u8 asc
= hd
->pLocal
->sense
[12];
4949 u8 ascq
= hd
->pLocal
->sense
[13];
4950 ddvprintk((MYIOC_s_INFO_FMT
4951 "DV: Reserve Failed: ", ioc
->name
));
4952 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4955 if ((skey
== NOT_READY
) && (asc
== 0x04)&&
4957 /* wait then repeat */
4961 ddvprintk((MYIOC_s_INFO_FMT
4962 "DV: Reserved Failed.", ioc
->name
));
4966 ddvprintk((MYIOC_s_INFO_FMT
"DV: Reserved Failed.",
4973 mptscsih_fillbuf(pbuf1
, sz
, patt
, 1);
4974 iocmd
.cmd
= WRITE_BUFFER
;
4975 iocmd
.data_dma
= buf1_dma
;
4978 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
4980 else if (hd
->pLocal
== NULL
)
4983 rc
= hd
->pLocal
->completion
;
4984 if (rc
== MPT_SCANDV_GOOD
)
4985 ; /* Issue read buffer */
4986 else if (rc
== MPT_SCANDV_DID_RESET
) {
4987 /* If using echo buffers, reset to data buffers.
4988 * Else do Fallback and restart
4989 * this test (re-issue reserve
4990 * because of bus reset).
4992 if ((iocmd
.flags
& MPT_ICFLAG_ECHO
) && (dataBufSize
>= bufsize
)) {
4993 iocmd
.flags
&= ~MPT_ICFLAG_ECHO
;
4995 dv
.cmd
= MPT_FALLBACK
;
4996 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
4998 if (mpt_config(hd
->ioc
, &cfg
) != 0)
5001 if ((!dv
.now
.width
) && (!dv
.now
.offset
))
5005 iocmd
.flags
|= MPT_ICFLAG_DID_RESET
;
5008 } else if (rc
== MPT_SCANDV_SENSE
) {
5009 /* Restart data test if UA, else quit.
5011 u8 skey
= hd
->pLocal
->sense
[2] & 0x0F;
5012 ddvprintk((MYIOC_s_INFO_FMT
5013 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc
->name
, skey
,
5014 hd
->pLocal
->sense
[12], hd
->pLocal
->sense
[13]));
5015 if (skey
== UNIT_ATTENTION
) {
5018 } else if (skey
== ILLEGAL_REQUEST
) {
5019 if (iocmd
.flags
& MPT_ICFLAG_ECHO
) {
5020 if (dataBufSize
>= bufsize
) {
5021 iocmd
.flags
&= ~MPT_ICFLAG_ECHO
;
5036 iocmd
.cmd
= READ_BUFFER
;
5037 iocmd
.data_dma
= buf2_dma
;
5040 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
5042 else if (hd
->pLocal
== NULL
)
5045 rc
= hd
->pLocal
->completion
;
5046 if (rc
== MPT_SCANDV_GOOD
) {
5047 /* If buffers compare,
5048 * go to next pattern,
5049 * else, do a fallback and restart
5050 * data transfer test.
5052 if (memcmp (pbuf1
, pbuf2
, sz
) == 0) {
5053 ; /* goto next pattern */
5055 /* Miscompare with Echo buffer, go to data buffer,
5056 * if that buffer exists.
5057 * Miscompare with Data buffer, check first 4 bytes,
5058 * some devices return capacity. Exit in this case.
5060 if (iocmd
.flags
& MPT_ICFLAG_ECHO
) {
5061 if (dataBufSize
>= bufsize
)
5062 iocmd
.flags
&= ~MPT_ICFLAG_ECHO
;
5066 if (dataBufSize
== (pbuf2
[1]<<16 | pbuf2
[2]<<8 | pbuf2
[3])) {
5067 /* Argh. Device returning wrong data.
5068 * Quit DV for this device.
5073 /* Had an actual miscompare. Slow down.*/
5074 dv
.cmd
= MPT_FALLBACK
;
5075 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
5077 if (mpt_config(hd
->ioc
, &cfg
) != 0)
5080 if ((!dv
.now
.width
) && (!dv
.now
.offset
))
5087 } else if (rc
== MPT_SCANDV_DID_RESET
) {
5088 /* Do Fallback and restart
5089 * this test (re-issue reserve
5090 * because of bus reset).
5092 dv
.cmd
= MPT_FALLBACK
;
5093 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
5095 if (mpt_config(hd
->ioc
, &cfg
) != 0)
5098 if ((!dv
.now
.width
) && (!dv
.now
.offset
))
5101 iocmd
.flags
|= MPT_ICFLAG_DID_RESET
;
5104 } else if (rc
== MPT_SCANDV_SENSE
) {
5105 /* Restart data test if UA, else quit.
5107 u8 skey
= hd
->pLocal
->sense
[2] & 0x0F;
5108 ddvprintk((MYIOC_s_INFO_FMT
5109 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc
->name
, skey
,
5110 hd
->pLocal
->sense
[12], hd
->pLocal
->sense
[13]));
5111 if (skey
== UNIT_ATTENTION
) {
5123 } /* --- end of patt loop ---- */
5126 if (iocmd
.flags
& MPT_ICFLAG_RESERVED
) {
5127 iocmd
.cmd
= RELEASE
;
5128 iocmd
.data_dma
= -1;
5131 if (mptscsih_do_cmd(hd
, &iocmd
) < 0)
5132 printk(MYIOC_s_INFO_FMT
"DV: Release failed. id %d",
5134 else if (hd
->pLocal
) {
5135 if (hd
->pLocal
->completion
== MPT_SCANDV_GOOD
)
5136 iocmd
.flags
&= ~MPT_ICFLAG_RESERVED
;
5138 printk(MYIOC_s_INFO_FMT
"DV: Release failed. id %d",
5144 /* Set if cfg1_dma_addr contents is valid
5146 if ((cfg
.hdr
!= NULL
) && (retcode
== 0)){
5147 /* If disk, not U320, disable QAS
5149 if ((inq0
== 0) && (dv
.now
.factor
> MPT_ULTRA320
)) {
5150 hd
->ioc
->spi_data
.noQas
= MPT_TARGET_NO_NEGO_QAS
;
5151 ddvprintk((MYIOC_s_NOTE_FMT
5152 "noQas set due to id=%d has factor=%x\n", ioc
->name
, id
, dv
.now
.factor
));
5156 mptscsih_dv_parms(hd
, &dv
, (void *)pcfg1Data
);
5158 /* Double writes to SDP1 can cause problems,
5159 * skip save of the final negotiated settings to
5160 * SCSI device page 1.
5163 cfg.physAddr = cfg1_dma_addr;
5164 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5166 mpt_config(hd->ioc, &cfg);
5170 /* If this is a RAID Passthrough, enable internal IOs
5172 if (iocmd
.flags
& MPT_ICFLAG_PHYS_DISK
) {
5173 if (mptscsih_do_raid(hd
, MPI_RAID_ACTION_ENABLE_PHYS_IO
, &iocmd
) < 0)
5174 ddvprintk((MYIOC_s_ERR_FMT
"RAID Enable FAILED!\n", ioc
->name
));
5177 /* Done with the DV scan of the current target
5180 pci_free_consistent(ioc
->pcidev
, dv_alloc
, pDvBuf
, dvbuf_dma
);
5182 ddvtprintk((MYIOC_s_INFO_FMT
"DV Done id=%d\n",
5188 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5189 /* mptscsih_dv_parms - perform a variety of operations on the
5190 * parameters used for negotiation.
5191 * @hd: Pointer to a SCSI host.
5192 * @dv: Pointer to a structure that contains the maximum and current
5193 * negotiated parameters.
5196 mptscsih_dv_parms(MPT_SCSI_HOST
*hd
, DVPARAMETERS
*dv
,void *pPage
)
5198 VirtDevice
*pTarget
;
5199 SCSIDevicePage0_t
*pPage0
;
5200 SCSIDevicePage1_t
*pPage1
;
5201 int val
= 0, data
, configuration
;
5210 case MPT_GET_NVRAM_VALS
:
5211 ddvprintk((MYIOC_s_NOTE_FMT
"Getting NVRAM: ",
5213 /* Get the NVRAM values and save in tmax
5214 * If not an LVD bus, the adapter minSyncFactor has been
5215 * already throttled back.
5217 if ((hd
->Targets
)&&((pTarget
= hd
->Targets
[(int)id
]) != NULL
) && !pTarget
->raidVolume
) {
5218 width
= pTarget
->maxWidth
;
5219 offset
= pTarget
->maxOffset
;
5220 factor
= pTarget
->minSyncFactor
;
5221 negoFlags
= pTarget
->negoFlags
;
5223 if (hd
->ioc
->spi_data
.nvram
&& (hd
->ioc
->spi_data
.nvram
[id
] != MPT_HOST_NVRAM_INVALID
)) {
5224 data
= hd
->ioc
->spi_data
.nvram
[id
];
5225 width
= data
& MPT_NVRAM_WIDE_DISABLE
? 0 : 1;
5226 if ((offset
= hd
->ioc
->spi_data
.maxSyncOffset
) == 0)
5229 factor
= (data
& MPT_NVRAM_SYNC_MASK
) >> MPT_NVRAM_SYNC_SHIFT
;
5230 if ((factor
== 0) || (factor
== MPT_ASYNC
)){
5241 /* Set the negotiation flags */
5242 negoFlags
= hd
->ioc
->spi_data
.noQas
;
5244 negoFlags
|= MPT_TARGET_NO_NEGO_WIDE
;
5247 negoFlags
|= MPT_TARGET_NO_NEGO_SYNC
;
5250 /* limit by adapter capabilities */
5251 width
= min(width
, hd
->ioc
->spi_data
.maxBusWidth
);
5252 offset
= min(offset
, hd
->ioc
->spi_data
.maxSyncOffset
);
5253 factor
= max(factor
, hd
->ioc
->spi_data
.minSyncFactor
);
5255 /* Check Consistency */
5256 if (offset
&& (factor
< MPT_ULTRA2
) && !width
)
5257 factor
= MPT_ULTRA2
;
5259 dv
->max
.width
= width
;
5260 dv
->max
.offset
= offset
;
5261 dv
->max
.factor
= factor
;
5262 dv
->max
.flags
= negoFlags
;
5263 ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
5264 id
, width
, factor
, offset
, negoFlags
));
5267 case MPT_UPDATE_MAX
:
5268 ddvprintk((MYIOC_s_NOTE_FMT
5269 "Updating with SDP0 Data: ", hd
->ioc
->name
));
5270 /* Update tmax values with those from Device Page 0.*/
5271 pPage0
= (SCSIDevicePage0_t
*) pPage
;
5273 val
= cpu_to_le32(pPage0
->NegotiatedParameters
);
5274 dv
->max
.width
= val
& MPI_SCSIDEVPAGE0_NP_WIDE
? 1 : 0;
5275 dv
->max
.offset
= (val
&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK
) >> 16;
5276 dv
->max
.factor
= (val
&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK
) >> 8;
5279 dv
->now
.width
= dv
->max
.width
;
5280 dv
->now
.offset
= dv
->max
.offset
;
5281 dv
->now
.factor
= dv
->max
.factor
;
5282 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
5283 id
, dv
->now
.width
, dv
->now
.factor
, dv
->now
.offset
, dv
->now
.flags
));
5287 ddvprintk((MYIOC_s_NOTE_FMT
"Setting Max: ",
5289 /* Set current to the max values. Update the config page.*/
5290 dv
->now
.width
= dv
->max
.width
;
5291 dv
->now
.offset
= dv
->max
.offset
;
5292 dv
->now
.factor
= dv
->max
.factor
;
5293 dv
->now
.flags
= dv
->max
.flags
;
5295 pPage1
= (SCSIDevicePage1_t
*)pPage
;
5297 mptscsih_setDevicePage1Flags (dv
->now
.width
, dv
->now
.factor
,
5298 dv
->now
.offset
, &val
, &configuration
, dv
->now
.flags
);
5299 dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5300 id
, dv
->now
.width
, dv
->now
.factor
, dv
->now
.offset
, dv
->now
.flags
, val
, configuration
));
5301 pPage1
->RequestedParameters
= le32_to_cpu(val
);
5302 pPage1
->Reserved
= 0;
5303 pPage1
->Configuration
= le32_to_cpu(configuration
);
5306 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n",
5307 id
, dv
->now
.width
, dv
->now
.factor
, dv
->now
.offset
, dv
->now
.flags
, val
, configuration
));
5311 ddvprintk((MYIOC_s_NOTE_FMT
"Setting Min: ",
5313 /* Set page to asynchronous and narrow
5314 * Do not update now, breaks fallback routine. */
5318 negoFlags
= dv
->max
.flags
;
5320 pPage1
= (SCSIDevicePage1_t
*)pPage
;
5322 mptscsih_setDevicePage1Flags (width
, factor
,
5323 offset
, &val
, &configuration
, negoFlags
);
5324 dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5325 id
, width
, factor
, offset
, negoFlags
, val
, configuration
));
5326 pPage1
->RequestedParameters
= le32_to_cpu(val
);
5327 pPage1
->Reserved
= 0;
5328 pPage1
->Configuration
= le32_to_cpu(configuration
);
5330 ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
5331 id
, width
, factor
, offset
, val
, configuration
, negoFlags
));
5335 ddvprintk((MYIOC_s_NOTE_FMT
5336 "Fallback: Start: offset %d, factor %x, width %d \n",
5337 hd
->ioc
->name
, dv
->now
.offset
,
5338 dv
->now
.factor
, dv
->now
.width
));
5339 width
= dv
->now
.width
;
5340 offset
= dv
->now
.offset
;
5341 factor
= dv
->now
.factor
;
5342 if ((offset
) && (dv
->max
.width
)) {
5343 if (factor
< MPT_ULTRA160
)
5344 factor
= MPT_ULTRA160
;
5345 else if (factor
< MPT_ULTRA2
) {
5346 factor
= MPT_ULTRA2
;
5348 } else if ((factor
== MPT_ULTRA2
) && width
) {
5349 factor
= MPT_ULTRA2
;
5351 } else if (factor
< MPT_ULTRA
) {
5354 } else if ((factor
== MPT_ULTRA
) && width
) {
5356 } else if (factor
< MPT_FAST
) {
5359 } else if ((factor
== MPT_FAST
) && width
) {
5362 } else if (factor
< MPT_SCSI
) {
5365 } else if ((factor
== MPT_SCSI
) && width
) {
5373 } else if (offset
) {
5375 if (factor
< MPT_ULTRA
)
5377 else if (factor
< MPT_FAST
)
5379 else if (factor
< MPT_SCSI
)
5390 dv
->max
.flags
|= MPT_TARGET_NO_NEGO_QAS
;
5391 dv
->max
.flags
&= ~MPT_TAPE_NEGO_IDP
;
5393 dv
->now
.width
= width
;
5394 dv
->now
.offset
= offset
;
5395 dv
->now
.factor
= factor
;
5396 dv
->now
.flags
= dv
->max
.flags
;
5398 pPage1
= (SCSIDevicePage1_t
*)pPage
;
5400 mptscsih_setDevicePage1Flags (width
, factor
, offset
, &val
,
5401 &configuration
, dv
->now
.flags
);
5402 dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n",
5403 id
, width
, offset
, factor
, dv
->now
.flags
, val
, configuration
));
5405 pPage1
->RequestedParameters
= le32_to_cpu(val
);
5406 pPage1
->Reserved
= 0;
5407 pPage1
->Configuration
= le32_to_cpu(configuration
);
5410 ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
5411 id
, dv
->now
.offset
, dv
->now
.factor
, dv
->now
.width
, val
, configuration
));
5415 ddvprintk((MYIOC_s_NOTE_FMT
5416 "Saving to Target structure: ", hd
->ioc
->name
));
5417 ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
5418 id
, dv
->now
.width
, dv
->now
.factor
, dv
->now
.offset
, dv
->now
.flags
));
5420 /* Save these values to target structures
5421 * or overwrite nvram (phys disks only).
5424 if ((hd
->Targets
)&&((pTarget
= hd
->Targets
[(int)id
]) != NULL
) && !pTarget
->raidVolume
) {
5425 pTarget
->maxWidth
= dv
->now
.width
;
5426 pTarget
->maxOffset
= dv
->now
.offset
;
5427 pTarget
->minSyncFactor
= dv
->now
.factor
;
5428 pTarget
->negoFlags
= dv
->now
.flags
;
5430 /* Preserv all flags, use
5431 * read-modify-write algorithm
5433 if (hd
->ioc
->spi_data
.nvram
) {
5434 data
= hd
->ioc
->spi_data
.nvram
[id
];
5437 data
&= ~MPT_NVRAM_WIDE_DISABLE
;
5439 data
|= MPT_NVRAM_WIDE_DISABLE
;
5441 if (!dv
->now
.offset
)
5444 data
&= ~MPT_NVRAM_SYNC_MASK
;
5445 data
|= (dv
->now
.factor
<< MPT_NVRAM_SYNC_SHIFT
) & MPT_NVRAM_SYNC_MASK
;
5447 hd
->ioc
->spi_data
.nvram
[id
] = data
;
5454 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5455 /* mptscsih_fillbuf - fill a buffer with a special data pattern
5456 * cleanup. For bus scan only.
5458 * @buffer: Pointer to data buffer to be filled.
5459 * @size: Number of bytes to fill
5460 * @index: Pattern index
5461 * @width: bus width, 0 (8 bits) or 1 (16 bits)
5464 mptscsih_fillbuf(char *buffer
, int size
, int index
, int width
)
5475 /* Pattern: 0000 FFFF 0000 FFFF
5477 for (ii
=0; ii
< size
; ii
++, ptr
++) {
5484 /* Pattern: 00 FF 00 FF
5486 for (ii
=0; ii
< size
; ii
++, ptr
++) {
5497 /* Pattern: 5555 AAAA 5555 AAAA 5555
5499 for (ii
=0; ii
< size
; ii
++, ptr
++) {
5506 /* Pattern: 55 AA 55 AA 55
5508 for (ii
=0; ii
< size
; ii
++, ptr
++) {
5518 /* Pattern: 00 01 02 03 04 05
5521 for (ii
=0; ii
< size
; ii
++, ptr
++)
5527 /* Wide Pattern: FFFE 0001 FFFD 0002
5528 * ... 4000 DFFF 8000 EFFF
5531 for (ii
=0; ii
< size
/2; ii
++) {
5532 /* Create the base pattern
5535 /* every 64 (0x40) bytes flip the pattern
5536 * since we fill 2 bytes / iteration,
5537 * test for ii = 0x20
5543 *ptr
= (char)( (val
& 0xFF00) >> 8);
5545 *ptr
= (char)(val
& 0xFF);
5550 *ptr
= (char)( (val
& 0xFF00) >> 8);
5552 *ptr
= (char)(val
& 0xFF);
5558 /* Narrow Pattern: FE 01 FD 02 FB 04
5559 * .. 7F 80 01 FE 02 FD ... 80 7F
5562 for (ii
=0; ii
< size
; ii
++, ptr
++) {
5563 /* Base pattern - first 32 bytes
5570 *ptr
= (char) (~(1 << byte
));
5573 /* Flip the pattern every 32 bytes
5582 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5584 EXPORT_SYMBOL(mptscsih_remove
);
5585 EXPORT_SYMBOL(mptscsih_shutdown
);
5587 EXPORT_SYMBOL(mptscsih_suspend
);
5588 EXPORT_SYMBOL(mptscsih_resume
);
5590 EXPORT_SYMBOL(mptscsih_proc_info
);
5591 EXPORT_SYMBOL(mptscsih_info
);
5592 EXPORT_SYMBOL(mptscsih_qcmd
);
5593 EXPORT_SYMBOL(mptscsih_slave_alloc
);
5594 EXPORT_SYMBOL(mptscsih_slave_destroy
);
5595 EXPORT_SYMBOL(mptscsih_slave_configure
);
5596 EXPORT_SYMBOL(mptscsih_abort
);
5597 EXPORT_SYMBOL(mptscsih_dev_reset
);
5598 EXPORT_SYMBOL(mptscsih_bus_reset
);
5599 EXPORT_SYMBOL(mptscsih_host_reset
);
5600 EXPORT_SYMBOL(mptscsih_bios_param
);
5601 EXPORT_SYMBOL(mptscsih_io_done
);
5602 EXPORT_SYMBOL(mptscsih_taskmgmt_complete
);
5603 EXPORT_SYMBOL(mptscsih_scandv_complete
);
5604 EXPORT_SYMBOL(mptscsih_event_process
);
5605 EXPORT_SYMBOL(mptscsih_ioc_reset
);
5606 EXPORT_SYMBOL(mptscsih_store_queue_depth
);
5607 EXPORT_SYMBOL(mptscsih_timer_expired
);
5609 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/