1 /*
2 * CDDL HEADER START
3 *
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.
7 *
8 * You can obtain a copy of the license at
9 * http://www.opensource.org/licenses/cddl1.txt.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2004-2012 Emulex. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <emlxs.h>
28
29
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_DIAG_C);
32
33 uint32_t emlxs_diag_pattern[256] = {
34 /* Walking ones */
35 0x80000000, 0x40000000, 0x20000000, 0x10000000,
36 0x08000000, 0x04000000, 0x02000000, 0x01000000,
37 0x00800000, 0x00400000, 0x00200000, 0x00100000,
38 0x00080000, 0x00040000, 0x00020000, 0x00010000,
39 0x00008000, 0x00004000, 0x00002000, 0x00001000,
40 0x00000800, 0x00000400, 0x00000200, 0x00000100,
41 0x00000080, 0x00000040, 0x00000020, 0x00000010,
42 0x00000008, 0x00000004, 0x00000002, 0x00000001,
43
44 /* Walking zeros */
45 0x7fffffff, 0xbfffffff, 0xdfffffff, 0xefffffff,
46 0xf7ffffff, 0xfbffffff, 0xfdffffff, 0xfeffffff,
47 0xff7fffff, 0xffbfffff, 0xffdfffff, 0xffefffff,
48 0xfff7ffff, 0xfffbffff, 0xfffdffff, 0xfffeffff,
49 0xffff7fff, 0xffffbfff, 0xffffdfff, 0xffffefff,
50 0xfffff7ff, 0xfffffbff, 0xfffffdff, 0xfffffeff,
51 0xffffff7f, 0xffffffbf, 0xffffffdf, 0xffffffef,
52 0xfffffff7, 0xfffffffb, 0xfffffffd, 0xfffffffe,
53
54 /* all zeros */
55 0x00000000, 0x00000000, 0x00000000, 0x00000000,
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
64 /* all ones */
65 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
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
74 /* all 5's */
75 0x55555555, 0x55555555, 0x55555555, 0x55555555,
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
84 /* all a's */
85 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
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
94 /* all 5a's */
95 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
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
104 /* all a5's */
105 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
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 };
114
115
116 /* Default pkt callback routine */
117 static void
emlxs_diag_pkt_callback(fc_packet_t * pkt)118 emlxs_diag_pkt_callback(fc_packet_t *pkt)
119 {
120 emlxs_port_t *port = (emlxs_port_t *)pkt->pkt_ulp_private;
121
122 /* Set the completed flag and wake up sleeping threads */
123 mutex_enter(&EMLXS_PKT_LOCK);
124 pkt->pkt_tran_flags |= FC_TRAN_COMPLETED;
125 cv_broadcast(&EMLXS_PKT_CV);
126 mutex_exit(&EMLXS_PKT_LOCK);
127
128 return;
129
130 } /* emlxs_diag_pkt_callback() */
131
132
133 extern uint32_t
emlxs_diag_echo_run(emlxs_port_t * port,uint32_t did,uint32_t pattern)134 emlxs_diag_echo_run(emlxs_port_t *port, uint32_t did, uint32_t pattern)
135 {
136 emlxs_hba_t *hba = HBA;
137 uint32_t i = 0;
138 uint32_t rval = FC_SUCCESS;
139 int32_t pkt_ret;
140 fc_packet_t *pkt;
141 ELS_PKT *els;
142 clock_t timeout;
143 uint8_t *pkt_resp;
144 char *pattern_buffer;
145 uint32_t length;
146 uint32_t *lptr;
147 NODELIST *ndlp;
148 uint8_t *pat;
149
150 /* Check did */
151 if (did == 0) {
152 did = port->did;
153 }
154
155 /* Check if device is ready */
156 if ((hba->state < FC_LINK_UP) || (port->did == 0)) {
157 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
158 "ECHO: HBA not ready.");
159
160 return (FC_TRAN_BUSY);
161 }
162
163 /* Check for the host node */
164 ndlp = emlxs_node_find_did(port, port->did, 1);
165
166 if (!ndlp || !ndlp->nlp_active) {
167 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
168 "ECHO: HBA not ready.");
169
170 return (FC_TRAN_BUSY);
171 }
172
173 length = 124;
174
175 /* Prepare ECHO pkt */
176 if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) + length,
177 sizeof (uint32_t) + length, 0, KM_NOSLEEP))) {
178 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
179 "ECHO: Unable to allocate packet. size=%x",
180 sizeof (uint32_t) + length);
181
182 return (FC_NOMEM);
183 }
184
185 /* pkt initialization */
186 pkt->pkt_tran_type = FC_PKT_EXCHANGE;
187 pkt->pkt_timeout = 60;
188
189 /* Build the fc header */
190 pkt->pkt_cmd_fhdr.d_id = did;
191 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_EXTENDED_SVC | R_CTL_UNSOL_CONTROL;
192 pkt->pkt_cmd_fhdr.s_id = port->did;
193 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
194 pkt->pkt_cmd_fhdr.f_ctl =
195 F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE | F_CTL_END_SEQ;
196 pkt->pkt_cmd_fhdr.seq_id = 0;
197 pkt->pkt_cmd_fhdr.df_ctl = 0;
198 pkt->pkt_cmd_fhdr.seq_cnt = 0;
199 pkt->pkt_cmd_fhdr.ox_id = 0xffff;
200 pkt->pkt_cmd_fhdr.rx_id = 0xffff;
201 pkt->pkt_cmd_fhdr.ro = 0;
202 pkt->pkt_comp = emlxs_diag_pkt_callback;
203
204 /* Build the command */
205 els = (ELS_PKT *) pkt->pkt_cmd;
206 els->elsCode = 0x10;
207 pattern_buffer = (char *)els->un.pad;
208
209 if (pattern) {
210 /* Fill the transmit buffer with the pattern */
211 lptr = (uint32_t *)pattern_buffer;
212
213 for (i = 0; i < length; i += 4) {
214 *lptr++ = pattern;
215 }
216 } else {
217 /* Program the default echo pattern */
218 bzero(pattern_buffer, length);
219 (void) snprintf(pattern_buffer, length,
220 "Emulex. We network storage. Emulex. We network storage. "
221 "Emulex. We network storage. Emulex. We network storage.");
222 }
223
224 /* Send ECHO pkt */
225 if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
226 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
227 "ECHO: Packet send failed.");
228
229 goto done;
230 }
231
232 /* Wait for ECHO completion */
233 mutex_enter(&EMLXS_PKT_LOCK);
234 timeout = emlxs_timeout(hba, (pkt->pkt_timeout + 15));
235 pkt_ret = 0;
236 while ((pkt_ret != -1) && !(pkt->pkt_tran_flags & FC_TRAN_COMPLETED)) {
237 pkt_ret =
238 cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK, timeout);
239
240 }
241 mutex_exit(&EMLXS_PKT_LOCK);
242
243 if (pkt_ret == -1) {
244 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_echo_failed_msg,
245 "Packet timed out.");
246
247 return (FC_ABORTED);
248 }
249
250 if (pkt->pkt_state != FC_PKT_SUCCESS) {
251 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_echo_failed_msg,
252 "Transport error.");
253
254 rval = FC_TRANSPORT_ERROR;
255 goto done;
256 }
257
258 /* Check response payload */
259 pkt_resp = (uint8_t *)pkt->pkt_resp + 4;
260 pat = (uint8_t *)pattern_buffer;
261 rval = FC_SUCCESS;
262
263 for (i = 0; i < length; i++, pkt_resp++, pat++) {
264 if (*pkt_resp != *pat) {
265 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_echo_failed_msg,
266 "Data miscompare. did=%06x length=%d. Offset %d "
267 "value %02x should be %02x.", did, length, i,
268 *pkt_resp, *pat);
269
270 rval = EMLXS_TEST_FAILED;
271
272 break;
273 }
274 }
275
276 if (rval == FC_SUCCESS) {
277 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_echo_complete_msg,
278 "did=%06x length=%d pattern=%02x,%02x,%02x,%02x...",
279 did, length, pattern_buffer[0] & 0xff,
280 pattern_buffer[1] & 0xff, pattern_buffer[2] & 0xff,
281 pattern_buffer[3] & 0xff);
282 }
283
284 done:
285
286 /* Free the echo pkt */
287 emlxs_pkt_free(pkt);
288
289 return (rval);
290
291 } /* emlxs_diag_echo_run() */
292
293
294 extern uint32_t
emlxs_diag_biu_run(emlxs_hba_t * hba,uint32_t pattern)295 emlxs_diag_biu_run(emlxs_hba_t *hba, uint32_t pattern)
296 {
297 emlxs_port_t *port = &PPORT;
298 MAILBOXQ *mbq = NULL;
299 MATCHMAP *mp = NULL;
300 MATCHMAP *mp1 = NULL;
301 uint32_t i;
302 uint8_t *inptr;
303 uint8_t *outptr;
304 int32_t rval = FC_SUCCESS;
305 uint32_t *lptr;
306
307 /* Check if device is ready */
308 if (hba->state < FC_LINK_DOWN) {
309 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
310 "BIU: HBA not ready.");
311
312 return (FC_TRAN_BUSY);
313 }
314
315 /*
316 * Get a buffer which will be used for the mailbox command
317 */
318 if ((mbq = (MAILBOXQ *) emlxs_mem_get(hba, MEM_MBOX)) == 0) {
319 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
320 "BIU: Mailbox allocation failed.");
321
322 rval = FC_NOMEM;
323 goto done;
324 }
325
326 /*
327 * Setup and issue mailbox RUN BIU DIAG command Setup test buffers
328 */
329 if (((mp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BUF)) == 0) ||
330 ((mp1 = (MATCHMAP *) emlxs_mem_get(hba, MEM_BUF)) == 0)) {
331 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
332 "BIU: Buffer allocation failed.");
333
334 rval = FC_NOMEM;
335 goto done;
336 }
337
338 if (pattern) {
339 /* Fill the transmit buffer with the pattern */
340 lptr = (uint32_t *)mp->virt;
341
342 for (i = 0; i < MEM_ELSBUF_SIZE; i += 4) {
343 *lptr++ = pattern;
344 }
345 } else {
346 /* Copy the default pattern into the trasmit buffer */
347 bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt,
348 MEM_ELSBUF_SIZE);
349 }
350 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, MEM_ELSBUF_SIZE,
351 DDI_DMA_SYNC_FORDEV);
352
353 bzero(mp1->virt, MEM_ELSBUF_SIZE);
354 EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
355 DDI_DMA_SYNC_FORDEV);
356
357 /* Create the biu diag request */
358 (void) emlxs_mb_run_biu_diag(hba, mbq, mp->phys, mp1->phys);
359
360 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 60);
361
362 if (rval == MBX_TIMEOUT) {
363 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_biu_failed_msg,
364 "BUI diagnostic timed out.");
365
366 rval = EMLXS_TEST_FAILED;
367 goto done;
368 }
369
370 EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
371 DDI_DMA_SYNC_FORKERNEL);
372
373 outptr = mp->virt;
374 inptr = mp1->virt;
375
376 for (i = 0; i < MEM_ELSBUF_SIZE; i++, outptr++, inptr++) {
377 if (*outptr != *inptr) {
378 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_biu_failed_msg,
379 "Data miscompare. Offset %d value %02x should "
380 "be %02x.", i, *inptr, *outptr);
381
382 rval = EMLXS_TEST_FAILED;
383 goto done;
384 }
385 }
386
387 /* Wait half second before returning */
388 delay(drv_usectohz(500000));
389 rval = FC_SUCCESS;
390
391 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_biu_complete_msg, "Status Good.");
392
393 done:
394
395 if (mp) {
396 #ifdef FMA_SUPPORT
397 if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
398 != DDI_FM_OK) {
399 EMLXS_MSGF(EMLXS_CONTEXT,
400 &emlxs_invalid_dma_handle_msg,
401 "diag_biu_run: hdl=%p",
402 mp->dma_handle);
403 rval = EMLXS_TEST_FAILED;
404 }
405 #endif /* FMA_SUPPORT */
406 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
407 }
408 if (mp1) {
409 #ifdef FMA_SUPPORT
410 if (emlxs_fm_check_dma_handle(hba, mp1->dma_handle)
411 != DDI_FM_OK) {
412 EMLXS_MSGF(EMLXS_CONTEXT,
413 &emlxs_invalid_dma_handle_msg,
414 "diag_biu_run: hdl=%p",
415 mp1->dma_handle);
416 rval = EMLXS_TEST_FAILED;
417 }
418 #endif /* FMA_SUPPORT */
419 emlxs_mem_put(hba, MEM_BUF, (void *)mp1);
420 }
421 if (mbq) {
422 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
423 }
424
425 return (rval);
426
427 } /* emlxs_diag_biu_run() */
428
429
430 extern uint32_t
emlxs_diag_post_run(emlxs_hba_t * hba)431 emlxs_diag_post_run(emlxs_hba_t *hba)
432 {
433 emlxs_port_t *port = &PPORT;
434 uint32_t rval = FC_SUCCESS;
435
436 if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
437 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
438 "POST: HBA shutdown.");
439
440 return (FC_TRAN_BUSY);
441 }
442
443 /* Take board offline */
444 if ((rval = emlxs_offline(hba, 0))) {
445 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_post_failed_msg,
446 "Unable to take adapter offline.");
447
448 rval = FC_RESETFAIL;
449 }
450
451 /* Restart the adapter */
452 rval = EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
453
454 switch (rval) {
455 case 0:
456
457 (void) emlxs_online(hba);
458
459 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_post_complete_msg,
460 "Status good.");
461
462 rval = FC_SUCCESS;
463
464 break;
465
466 case 1: /* failed */
467
468 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_post_failed_msg,
469 "HBA reset failed.");
470
471 rval = FC_RESETFAIL;
472
473 break;
474
475
476 case 2: /* failed */
477
478 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
479 "HBA busy. Quiece and retry.");
480
481 rval = FC_STATEC_BUSY;
482
483 break;
484
485 }
486
487 return (rval);
488
489 } /* emlxs_diag_post_run() */
490