4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Emulex. All rights reserved.
24 * Use is subject to license terms.
31 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
32 EMLXS_MSG_DEF(EMLXS_DIAG_C
);
34 uint32_t emlxs_diag_pattern
[256] = {
36 0x80000000, 0x40000000, 0x20000000, 0x10000000,
37 0x08000000, 0x04000000, 0x02000000, 0x01000000,
38 0x00800000, 0x00400000, 0x00200000, 0x00100000,
39 0x00080000, 0x00040000, 0x00020000, 0x00010000,
40 0x00008000, 0x00004000, 0x00002000, 0x00001000,
41 0x00000800, 0x00000400, 0x00000200, 0x00000100,
42 0x00000080, 0x00000040, 0x00000020, 0x00000010,
43 0x00000008, 0x00000004, 0x00000002, 0x00000001,
46 0x7fffffff, 0xbfffffff, 0xdfffffff, 0xefffffff,
47 0xf7ffffff, 0xfbffffff, 0xfdffffff, 0xfeffffff,
48 0xff7fffff, 0xffbfffff, 0xffdfffff, 0xffefffff,
49 0xfff7ffff, 0xfffbffff, 0xfffdffff, 0xfffeffff,
50 0xffff7fff, 0xffffbfff, 0xffffdfff, 0xffffefff,
51 0xfffff7ff, 0xfffffbff, 0xfffffdff, 0xfffffeff,
52 0xffffff7f, 0xffffffbf, 0xffffffdf, 0xffffffef,
53 0xfffffff7, 0xfffffffb, 0xfffffffd, 0xfffffffe,
56 0x00000000, 0x00000000, 0x00000000, 0x00000000,
57 0x00000000, 0x00000000, 0x00000000, 0x00000000,
58 0x00000000, 0x00000000, 0x00000000, 0x00000000,
59 0x00000000, 0x00000000, 0x00000000, 0x00000000,
60 0x00000000, 0x00000000, 0x00000000, 0x00000000,
61 0x00000000, 0x00000000, 0x00000000, 0x00000000,
62 0x00000000, 0x00000000, 0x00000000, 0x00000000,
63 0x00000000, 0x00000000, 0x00000000, 0x00000000,
66 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
67 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
68 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
69 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
70 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
71 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
72 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
73 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
76 0x55555555, 0x55555555, 0x55555555, 0x55555555,
77 0x55555555, 0x55555555, 0x55555555, 0x55555555,
78 0x55555555, 0x55555555, 0x55555555, 0x55555555,
79 0x55555555, 0x55555555, 0x55555555, 0x55555555,
80 0x55555555, 0x55555555, 0x55555555, 0x55555555,
81 0x55555555, 0x55555555, 0x55555555, 0x55555555,
82 0x55555555, 0x55555555, 0x55555555, 0x55555555,
83 0x55555555, 0x55555555, 0x55555555, 0x55555555,
86 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
87 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
88 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
89 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
90 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
91 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
92 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
93 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
96 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
97 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
98 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
99 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
100 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
101 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
102 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
103 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
106 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
107 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
108 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
109 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
110 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
111 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
112 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
113 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5
117 /* Default pkt callback routine */
119 emlxs_diag_pkt_callback(fc_packet_t
*pkt
)
121 emlxs_port_t
*port
= (emlxs_port_t
*)pkt
->pkt_ulp_private
;
123 /* Set the completed flag and wake up sleeping threads */
124 mutex_enter(&EMLXS_PKT_LOCK
);
125 pkt
->pkt_tran_flags
|= FC_TRAN_COMPLETED
;
126 cv_broadcast(&EMLXS_PKT_CV
);
127 mutex_exit(&EMLXS_PKT_LOCK
);
131 } /* emlxs_diag_pkt_callback() */
135 emlxs_diag_echo_run(emlxs_port_t
*port
, uint32_t did
, uint32_t pattern
)
137 emlxs_hba_t
*hba
= HBA
;
139 uint32_t rval
= FC_SUCCESS
;
145 char *pattern_buffer
;
156 /* Check if device is ready */
157 if ((hba
->state
< FC_LINK_UP
) || (port
->did
== 0)) {
158 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_diag_error_msg
,
159 "ECHO: HBA not ready.");
161 return (FC_TRAN_BUSY
);
164 /* Check for the host node */
165 ndlp
= emlxs_node_find_did(port
, port
->did
);
167 if (!ndlp
|| !ndlp
->nlp_active
) {
168 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_diag_error_msg
,
169 "ECHO: HBA not ready.");
171 return (FC_TRAN_BUSY
);
176 /* Prepare ECHO pkt */
177 if (!(pkt
= emlxs_pkt_alloc(port
, sizeof (uint32_t) + length
,
178 sizeof (uint32_t) + length
, 0, KM_NOSLEEP
))) {
179 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_diag_error_msg
,
180 "ECHO: Unable to allocate packet. size=%x",
181 sizeof (uint32_t) + length
);
186 /* pkt initialization */
187 pkt
->pkt_tran_type
= FC_PKT_EXCHANGE
;
188 pkt
->pkt_timeout
= 60;
190 /* Build the fc header */
191 pkt
->pkt_cmd_fhdr
.d_id
= did
;
192 pkt
->pkt_cmd_fhdr
.r_ctl
= R_CTL_EXTENDED_SVC
| R_CTL_UNSOL_CONTROL
;
193 pkt
->pkt_cmd_fhdr
.s_id
= port
->did
;
194 pkt
->pkt_cmd_fhdr
.type
= FC_TYPE_EXTENDED_LS
;
195 pkt
->pkt_cmd_fhdr
.f_ctl
=
196 F_CTL_FIRST_SEQ
| F_CTL_SEQ_INITIATIVE
| F_CTL_END_SEQ
;
197 pkt
->pkt_cmd_fhdr
.seq_id
= 0;
198 pkt
->pkt_cmd_fhdr
.df_ctl
= 0;
199 pkt
->pkt_cmd_fhdr
.seq_cnt
= 0;
200 pkt
->pkt_cmd_fhdr
.ox_id
= 0xffff;
201 pkt
->pkt_cmd_fhdr
.rx_id
= 0xffff;
202 pkt
->pkt_cmd_fhdr
.ro
= 0;
203 pkt
->pkt_comp
= emlxs_diag_pkt_callback
;
205 /* Build the command */
206 els
= (ELS_PKT
*) pkt
->pkt_cmd
;
208 pattern_buffer
= (char *)els
->un
.pad
;
211 /* Fill the transmit buffer with the pattern */
212 lptr
= (uint32_t *)pattern_buffer
;
214 for (i
= 0; i
< length
; i
+= 4) {
218 /* Program the default echo pattern */
219 bzero(pattern_buffer
, length
);
220 (void) sprintf(pattern_buffer
, "Emulex. We network storage. "
221 "Emulex. We network storage. Emulex. We network storage. "
222 "Emulex. We network storage.");
226 if ((rval
= emlxs_pkt_send(pkt
, 1)) != FC_SUCCESS
) {
227 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_diag_error_msg
,
228 "ECHO: Packet send failed.");
233 /* Wait for ECHO completion */
234 mutex_enter(&EMLXS_PKT_LOCK
);
235 timeout
= emlxs_timeout(hba
, (pkt
->pkt_timeout
+ 15));
237 while ((pkt_ret
!= -1) && !(pkt
->pkt_tran_flags
& FC_TRAN_COMPLETED
)) {
239 cv_timedwait(&EMLXS_PKT_CV
, &EMLXS_PKT_LOCK
, timeout
);
242 mutex_exit(&EMLXS_PKT_LOCK
);
245 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_echo_failed_msg
,
246 "Packet timed out.");
251 if (pkt
->pkt_state
!= FC_PKT_SUCCESS
) {
252 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_echo_failed_msg
,
255 rval
= FC_TRANSPORT_ERROR
;
259 /* Check response payload */
260 pkt_resp
= (uint8_t *)pkt
->pkt_resp
+ 4;
261 pat
= (uint8_t *)pattern_buffer
;
264 for (i
= 0; i
< length
; i
++, pkt_resp
++, pat
++) {
265 if (*pkt_resp
!= *pat
) {
266 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_echo_failed_msg
,
267 "Data miscompare. did=%06x length=%d. Offset %d "
268 "value %02x should be %02x.", did
, length
, i
,
271 rval
= EMLXS_TEST_FAILED
;
277 if (rval
== FC_SUCCESS
) {
278 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_echo_complete_msg
,
279 "did=%06x length=%d pattern=%02x,%02x,%02x,%02x...",
280 did
, length
, pattern_buffer
[0] & 0xff,
281 pattern_buffer
[1] & 0xff, pattern_buffer
[2] & 0xff,
282 pattern_buffer
[3] & 0xff);
287 /* Free the echo pkt */
292 } /* emlxs_diag_echo_run() */
296 emlxs_diag_biu_run(emlxs_hba_t
*hba
, uint32_t pattern
)
298 emlxs_port_t
*port
= &PPORT
;
305 int32_t rval
= FC_SUCCESS
;
311 /* Check if device is ready */
312 if (hba
->state
< FC_LINK_DOWN
) {
313 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_diag_error_msg
,
314 "BIU: HBA not ready.");
316 return (FC_TRAN_BUSY
);
320 * Get a buffer which will be used for the mailbox command
322 if ((mbq
= (MAILBOXQ
*) emlxs_mem_get(hba
, MEM_MBOX
, 1)) == 0) {
323 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_diag_error_msg
,
324 "BIU: Mailbox allocation failed.");
331 * Setup and issue mailbox RUN BIU DIAG command Setup test buffers
333 if (((mp
= (MATCHMAP
*) emlxs_mem_get(hba
, MEM_BUF
, 1)) == 0) ||
334 ((mp1
= (MATCHMAP
*) emlxs_mem_get(hba
, MEM_BUF
, 1)) == 0)) {
335 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_diag_error_msg
,
336 "BIU: Buffer allocation failed.");
343 /* Fill the transmit buffer with the pattern */
344 lptr
= (uint32_t *)mp
->virt
;
346 for (i
= 0; i
< MEM_ELSBUF_SIZE
; i
+= 4) {
350 /* Copy the default pattern into the trasmit buffer */
351 bcopy((caddr_t
)&emlxs_diag_pattern
[0], (caddr_t
)mp
->virt
,
354 EMLXS_MPDATA_SYNC(mp
->dma_handle
, 0, MEM_ELSBUF_SIZE
,
355 DDI_DMA_SYNC_FORDEV
);
357 bzero(mp1
->virt
, MEM_ELSBUF_SIZE
);
358 EMLXS_MPDATA_SYNC(mp1
->dma_handle
, 0, MEM_ELSBUF_SIZE
,
359 DDI_DMA_SYNC_FORDEV
);
361 /* Create the biu diag request */
362 (void) emlxs_mb_run_biu_diag(hba
, mbq
, mp
->phys
, mp1
->phys
);
364 rval
= EMLXS_SLI_ISSUE_MBOX_CMD(hba
, mbq
, MBX_WAIT
, 60);
366 if (rval
== MBX_TIMEOUT
) {
367 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_biu_failed_msg
,
368 "BUI diagnostic timed out.");
370 rval
= EMLXS_TEST_FAILED
;
374 EMLXS_MPDATA_SYNC(mp1
->dma_handle
, 0, MEM_ELSBUF_SIZE
,
375 DDI_DMA_SYNC_FORKERNEL
);
380 for (i
= 0; i
< MEM_ELSBUF_SIZE
; i
++, outptr
++, inptr
++) {
381 if (*outptr
!= *inptr
) {
382 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_biu_failed_msg
,
383 "Data miscompare. Offset %d value %02x should "
384 "be %02x.", i
, *inptr
, *outptr
);
386 rval
= EMLXS_TEST_FAILED
;
391 /* Wait half second before returning */
392 delay(drv_usectohz(500000));
395 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_biu_complete_msg
, "Status Good.");
401 if (emlxs_fm_check_dma_handle(hba
, mp
->dma_handle
)
403 EMLXS_MSGF(EMLXS_CONTEXT
,
404 &emlxs_invalid_dma_handle_msg
,
405 "emlxs_diag_biu_run: hdl=%p",
407 rval
= EMLXS_TEST_FAILED
;
409 #endif /* FMA_SUPPORT */
410 emlxs_mem_put(hba
, MEM_BUF
, (void *)mp
);
414 if (emlxs_fm_check_dma_handle(hba
, mp1
->dma_handle
)
416 EMLXS_MSGF(EMLXS_CONTEXT
,
417 &emlxs_invalid_dma_handle_msg
,
418 "emlxs_diag_biu_run: hdl=%p",
420 rval
= EMLXS_TEST_FAILED
;
422 #endif /* FMA_SUPPORT */
423 emlxs_mem_put(hba
, MEM_BUF
, (void *)mp1
);
426 emlxs_mem_put(hba
, MEM_MBOX
, (void *)mbq
);
431 } /* emlxs_diag_biu_run() */
435 emlxs_diag_post_run(emlxs_hba_t
*hba
)
437 emlxs_port_t
*port
= &PPORT
;
438 uint32_t rval
= FC_SUCCESS
;
440 if (hba
->flag
& (FC_OFFLINE_MODE
| FC_OFFLINING_MODE
)) {
441 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_diag_error_msg
,
442 "POST: HBA shutdown.");
444 return (FC_TRAN_BUSY
);
447 /* Take board offline */
448 if ((rval
= emlxs_offline(hba
))) {
449 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_post_failed_msg
,
450 "Unable to take adapter offline.");
455 /* Restart the adapter */
456 rval
= EMLXS_SLI_HBA_RESET(hba
, 1, 1, 0);
461 (void) emlxs_online(hba
);
463 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_post_complete_msg
,
472 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_post_failed_msg
,
473 "HBA reset failed.");
482 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_diag_error_msg
,
483 "HBA busy. Quiece and retry.");
485 rval
= FC_STATEC_BUSY
;
493 } /* emlxs_diag_post_run() */