1 /*-
2 * Copyright (c) 2011-2015 LSI Corp.
3 * Copyright (c) 2013-2016 Avago Technologies
4 * Copyright 2000-2020 Broadcom Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD
29 */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 /* TODO Move headers to mprvar */
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/lock.h>
38 #include <sys/mutex.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/kthread.h>
43 #include <sys/taskqueue.h>
44 #include <sys/bus.h>
45 #include <sys/endian.h>
46 #include <sys/sysctl.h>
47 #include <sys/eventhandler.h>
48 #include <sys/uio.h>
49 #include <machine/bus.h>
50 #include <machine/resource.h>
51 #include <dev/mpr/mpi/mpi2_type.h>
52 #include <dev/mpr/mpi/mpi2.h>
53 #include <dev/mpr/mpi/mpi2_ioc.h>
54 #include <dev/mpr/mpi/mpi2_sas.h>
55 #include <dev/mpr/mpi/mpi2_pci.h>
56 #include <dev/mpr/mpi/mpi2_cnfg.h>
57 #include <dev/mpr/mpi/mpi2_init.h>
58 #include <dev/mpr/mpi/mpi2_tool.h>
59 #include <dev/mpr/mpr_ioctl.h>
60 #include <dev/mpr/mprvar.h>
61
62 /**
63 * mpr_config_get_ioc_pg8 - obtain ioc page 8
64 * @sc: per adapter object
65 * @mpi_reply: reply mf payload returned from firmware
66 * @config_page: contents of the config page
67 * Context: sleep.
68 *
69 * Returns 0 for success, non-zero for failure.
70 */
71 int
72 mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
73 Mpi2IOCPage8_t *config_page)
74 {
75 MPI2_CONFIG_REQUEST *request;
76 MPI2_CONFIG_REPLY *reply;
77 struct mpr_command *cm;
78 MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
79 int error = 0;
80 u16 ioc_status;
81
82 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
83
84 if ((cm = mpr_alloc_command(sc)) == NULL) {
85 printf("%s: command alloc failed @ line %d\n", __func__,
86 __LINE__);
87 error = EBUSY;
88 goto out;
89 }
90 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
91 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
92 request->Function = MPI2_FUNCTION_CONFIG;
93 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
94 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
95 request->Header.PageNumber = 8;
96 request->Header.PageLength = request->Header.PageVersion = 0;
97 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
98 cm->cm_data = NULL;
99 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
100 if (cm != NULL)
101 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
102 if (error || (reply == NULL)) {
103 /* FIXME */
104 /*
105 * If the request returns an error then we need to do a diag
106 * reset
107 */
108 printf("%s: request for header completed with error %d",
109 __func__, error);
110 error = ENXIO;
111 goto out;
112 }
113 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
114 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
115 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
116 /* FIXME */
117 /*
118 * If the request returns an error then we need to do a diag
119 * reset
120 */
121 printf("%s: header read with error; iocstatus = 0x%x\n",
122 __func__, ioc_status);
123 error = ENXIO;
124 goto out;
125 }
126 /* We have to do free and alloc for the reply-free and reply-post
127 * counters to match - Need to review the reply FIFO handling.
128 */
129 mpr_free_command(sc, cm);
130
131 if ((cm = mpr_alloc_command(sc)) == NULL) {
132 printf("%s: command alloc failed @ line %d\n", __func__,
133 __LINE__);
134 error = EBUSY;
135 goto out;
136 }
137 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
138 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
139 request->Function = MPI2_FUNCTION_CONFIG;
140 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
141 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
142 request->Header.PageNumber = 8;
143 request->Header.PageVersion = mpi_reply->Header.PageVersion;
144 request->Header.PageLength = mpi_reply->Header.PageLength;
145 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
146 cm->cm_sge = &request->PageBufferSGE;
147 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
148 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
149 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
150 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
151 if (!page) {
152 printf("%s: page alloc failed\n", __func__);
153 error = ENOMEM;
154 goto out;
155 }
156 cm->cm_data = page;
157
158 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
159 if (cm != NULL)
160 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
161 if (error || (reply == NULL)) {
162 /* FIXME */
163 /*
164 * If the request returns an error then we need to do a diag
165 * reset
166 */
167 printf("%s: request for page completed with error %d",
168 __func__, error);
169 error = ENXIO;
170 goto out;
171 }
172 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
173 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
174 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
175 /* FIXME */
176 /*
177 * If the request returns an error then we need to do a diag
178 * reset
179 */
180 printf("%s: page read with error; iocstatus = 0x%x\n",
181 __func__, ioc_status);
182 error = ENXIO;
183 goto out;
184 }
185 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
186
187 out:
188 free(page, M_MPR);
189 if (cm)
190 mpr_free_command(sc, cm);
191 return (error);
192 }
193
194 /**
195 * mpr_config_get_iounit_pg8 - obtain iounit page 8
196 * @sc: per adapter object
197 * @mpi_reply: reply mf payload returned from firmware
198 * @config_page: contents of the config page
199 * Context: sleep.
200 *
201 * Returns 0 for success, non-zero for failure.
202 */
203 int
204 mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
205 Mpi2IOUnitPage8_t *config_page)
206 {
207 MPI2_CONFIG_REQUEST *request;
208 MPI2_CONFIG_REPLY *reply;
209 struct mpr_command *cm;
210 MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL;
211 int error = 0;
212 u16 ioc_status;
213
214 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
215
216 if ((cm = mpr_alloc_command(sc)) == NULL) {
217 printf("%s: command alloc failed @ line %d\n", __func__,
218 __LINE__);
219 error = EBUSY;
220 goto out;
221 }
222 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
223 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
224 request->Function = MPI2_FUNCTION_CONFIG;
225 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
226 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
227 request->Header.PageNumber = 8;
228 request->Header.PageLength = request->Header.PageVersion = 0;
229 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
230 cm->cm_data = NULL;
231 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
232 if (cm != NULL)
233 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
234 if (error || (reply == NULL)) {
235 /* FIXME */
236 /*
237 * If the request returns an error then we need to do a diag
238 * reset
239 */
240 printf("%s: request for header completed with error %d",
241 __func__, error);
242 error = ENXIO;
243 goto out;
244 }
245 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
246 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
247 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
248 /* FIXME */
249 /*
250 * If the request returns an error then we need to do a diag
251 * reset
252 */
253 printf("%s: header read with error; iocstatus = 0x%x\n",
254 __func__, ioc_status);
255 error = ENXIO;
256 goto out;
257 }
258 /* We have to do free and alloc for the reply-free and reply-post
259 * counters to match - Need to review the reply FIFO handling.
260 */
261 mpr_free_command(sc, cm);
262
263 if ((cm = mpr_alloc_command(sc)) == NULL) {
264 printf("%s: command alloc failed @ line %d\n", __func__,
265 __LINE__);
266 error = EBUSY;
267 goto out;
268 }
269 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
270 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
271 request->Function = MPI2_FUNCTION_CONFIG;
272 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
273 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
274 request->Header.PageNumber = 8;
275 request->Header.PageVersion = mpi_reply->Header.PageVersion;
276 request->Header.PageLength = mpi_reply->Header.PageLength;
277 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
278 cm->cm_sge = &request->PageBufferSGE;
279 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
280 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
281 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
282 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
283 if (!page) {
284 printf("%s: page alloc failed\n", __func__);
285 error = ENOMEM;
286 goto out;
287 }
288 cm->cm_data = page;
289
290 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
291 if (cm != NULL)
292 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
293 if (error || (reply == NULL)) {
294 /* FIXME */
295 /*
296 * If the request returns an error then we need to do a diag
297 * reset
298 */
299 printf("%s: request for page completed with error %d",
300 __func__, error);
301 error = ENXIO;
302 goto out;
303 }
304 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
305 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
306 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
307 /* FIXME */
308 /*
309 * If the request returns an error then we need to do a diag
310 * reset
311 */
312 printf("%s: page read with error; iocstatus = 0x%x\n",
313 __func__, ioc_status);
314 error = ENXIO;
315 goto out;
316 }
317 bcopy(page, config_page, MIN(cm->cm_length,
318 (sizeof(Mpi2IOUnitPage8_t))));
319
320 out:
321 free(page, M_MPR);
322 if (cm)
323 mpr_free_command(sc, cm);
324 return (error);
325 }
326
327 /**
328 * mpr_config_get_man_pg11 - obtain manufacturing page 11
329 * @sc: per adapter object
330 * @mpi_reply: reply mf payload returned from firmware
331 * @config_page: contents of the config page
332 * Context: sleep.
333 *
334 * Returns 0 for success, non-zero for failure.
335 */
336 int
337 mpr_config_get_man_pg11(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
338 Mpi2ManufacturingPage11_t *config_page)
339 {
340 MPI2_CONFIG_REQUEST *request;
341 MPI2_CONFIG_REPLY *reply;
342 struct mpr_command *cm;
343 MPI2_CONFIG_PAGE_MAN_11 *page = NULL;
344 int error = 0;
345 u16 ioc_status;
346
347 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
348
349 if ((cm = mpr_alloc_command(sc)) == NULL) {
350 printf("%s: command alloc failed @ line %d\n", __func__,
351 __LINE__);
352 error = EBUSY;
353 goto out;
354 }
355 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
356 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
357 request->Function = MPI2_FUNCTION_CONFIG;
358 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
359 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
360 request->Header.PageNumber = 11;
361 request->Header.PageLength = request->Header.PageVersion = 0;
362 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
363 cm->cm_data = NULL;
364 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
365 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
366 if (error || (reply == NULL)) {
367 /* FIXME */
368 /*
369 * If the request returns an error then we need to do a diag
370 * reset
371 */
372 printf("%s: request for header completed with error %d",
373 __func__, error);
374 error = ENXIO;
375 goto out;
376 }
377 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
378 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
379 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
380 /* FIXME */
381 /*
382 * If the request returns an error then we need to do a diag
383 * reset
384 */
385 printf("%s: header read with error; iocstatus = 0x%x\n",
386 __func__, ioc_status);
387 error = ENXIO;
388 goto out;
389 }
390 /* We have to do free and alloc for the reply-free and reply-post
391 * counters to match - Need to review the reply FIFO handling.
392 */
393 mpr_free_command(sc, cm);
394
395 if ((cm = mpr_alloc_command(sc)) == NULL) {
396 printf("%s: command alloc failed @ line %d\n", __func__,
397 __LINE__);
398 error = EBUSY;
399 goto out;
400 }
401 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
402 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
403 request->Function = MPI2_FUNCTION_CONFIG;
404 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
405 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
406 request->Header.PageNumber = 11;
407 request->Header.PageVersion = mpi_reply->Header.PageVersion;
408 request->Header.PageLength = mpi_reply->Header.PageLength;
409 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
410 cm->cm_sge = &request->PageBufferSGE;
411 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
412 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
413 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
414 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
415 if (!page) {
416 printf("%s: page alloc failed\n", __func__);
417 error = ENOMEM;
418 goto out;
419 }
420 cm->cm_data = page;
421
422 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
423 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
424 if (error || (reply == NULL)) {
425 /* FIXME */
426 /*
427 * If the request returns an error then we need to do a diag
428 * reset
429 */
430 printf("%s: request for page completed with error %d",
431 __func__, error);
432 error = ENXIO;
433 goto out;
434 }
435 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
436 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
437 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
438 /* FIXME */
439 /*
440 * If the request returns an error then we need to do a diag
441 * reset
442 */
443 printf("%s: page read with error; iocstatus = 0x%x\n",
444 __func__, ioc_status);
445 error = ENXIO;
446 goto out;
447 }
448 bcopy(page, config_page, MIN(cm->cm_length,
449 (sizeof(Mpi2ManufacturingPage11_t))));
450
451 out:
452 free(page, M_MPR);
453 if (cm)
454 mpr_free_command(sc, cm);
455 return (error);
456 }
457
458 /**
459 * mpr_base_static_config_pages - static start of day config pages.
460 * @sc: per adapter object
461 *
462 * Return nothing.
463 */
464 void
465 mpr_base_static_config_pages(struct mpr_softc *sc)
466 {
467 Mpi2ConfigReply_t mpi_reply;
468 Mpi2ManufacturingPage11_t man_pg11;
469 int retry, rc;
470
471 retry = 0;
472 while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
473 retry++;
474 if (retry > 5) {
475 /* We need to Handle this situation */
476 /*FIXME*/
477 break;
478 }
479 }
480 retry = 0;
481 while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) {
482 retry++;
483 if (retry > 5) {
484 /* We need to Handle this situation */
485 /*FIXME*/
486 break;
487 }
488 }
489 retry = 0;
490 while ((rc = mpr_config_get_man_pg11(sc, &mpi_reply, &man_pg11))) {
491 retry++;
492 if (retry > 5) {
493 /* We need to Handle this situation */
494 /*FIXME*/
495 break;
496 }
497 }
498
499 if (!rc) {
500 sc->custom_nvme_tm_handling = (le16toh(man_pg11.AddlFlags2) &
501 MPI2_MAN_PG11_ADDLFLAGS2_CUSTOM_TM_HANDLING_MASK);
502 sc->nvme_abort_timeout = man_pg11.NVMeAbortTO;
503
504 /* Minimum NVMe Abort timeout value should be 6 seconds &
505 * maximum value should be 60 seconds.
506 */
507 if (sc->nvme_abort_timeout < 6)
508 sc->nvme_abort_timeout = 6;
509 if (sc->nvme_abort_timeout > 60)
510 sc->nvme_abort_timeout = 60;
511 }
512 }
513
514 /**
515 * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0
516 * @sc: per adapter object
517 * @mpi_reply: reply mf payload returned from firmware
518 * @config_page: contents of the config page
519 * @sz: size of buffer passed in config_page
520 * Context: sleep.
521 *
522 * Returns 0 for success, non-zero for failure.
523 */
524 int
525 mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
526 Mpi2DriverMappingPage0_t *config_page, u16 sz)
527 {
528 MPI2_CONFIG_REQUEST *request;
529 MPI2_CONFIG_REPLY *reply;
530 struct mpr_command *cm;
531 Mpi2DriverMappingPage0_t *page = NULL;
532 int error = 0;
533 u16 ioc_status;
534
535 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
536
537 memset(config_page, 0, sz);
538 if ((cm = mpr_alloc_command(sc)) == NULL) {
539 printf("%s: command alloc failed @ line %d\n", __func__,
540 __LINE__);
541 error = EBUSY;
542 goto out;
543 }
544 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
545 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
546 request->Function = MPI2_FUNCTION_CONFIG;
547 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
548 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
549 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
550 request->Header.PageNumber = 0;
551 request->ExtPageLength = request->Header.PageVersion = 0;
552 request->PageAddress = sc->max_dpm_entries <<
553 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
554 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
555 cm->cm_data = NULL;
556 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
557 if (cm != NULL)
558 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
559 if (error || (reply == NULL)) {
560 /* FIXME */
561 /*
562 * If the request returns an error then we need to do a diag
563 * reset
564 */
565 printf("%s: request for header completed with error %d",
566 __func__, error);
567 error = ENXIO;
568 goto out;
569 }
570 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
571 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
572 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
573 /* FIXME */
574 /*
575 * If the request returns an error then we need to do a diag
576 * reset
577 */
578 printf("%s: header read with error; iocstatus = 0x%x\n",
579 __func__, ioc_status);
580 error = ENXIO;
581 goto out;
582 }
583 /* We have to do free and alloc for the reply-free and reply-post
584 * counters to match - Need to review the reply FIFO handling.
585 */
586 mpr_free_command(sc, cm);
587
588 if ((cm = mpr_alloc_command(sc)) == NULL) {
589 printf("%s: command alloc failed @ line %d\n", __func__,
590 __LINE__);
591 error = EBUSY;
592 goto out;
593 }
594 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
595 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
596 request->Function = MPI2_FUNCTION_CONFIG;
597 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
598 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
599 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
600 request->Header.PageNumber = 0;
601 request->Header.PageVersion = mpi_reply->Header.PageVersion;
602 request->PageAddress = sc->max_dpm_entries <<
603 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
604 request->ExtPageLength = mpi_reply->ExtPageLength;
605 cm->cm_length = le16toh(request->ExtPageLength) * 4;
606 cm->cm_sge = &request->PageBufferSGE;
607 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
608 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
609 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
610 page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT);
611 if (!page) {
612 printf("%s: page alloc failed\n", __func__);
613 error = ENOMEM;
614 goto out;
615 }
616 cm->cm_data = page;
617 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
618 if (cm != NULL)
619 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
620 if (error || (reply == NULL)) {
621 /* FIXME */
622 /*
623 * If the request returns an error then we need to do a diag
624 * reset
625 */
626 printf("%s: request for page completed with error %d",
627 __func__, error);
628 error = ENXIO;
629 goto out;
630 }
631 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
632 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
633 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
634 /* FIXME */
635 /*
636 * If the request returns an error then we need to do a diag
637 * reset
638 */
639 printf("%s: page read with error; iocstatus = 0x%x\n",
640 __func__, ioc_status);
641 error = ENXIO;
642 goto out;
643 }
644 bcopy(page, config_page, MIN(cm->cm_length, sz));
645 out:
646 free(page, M_MPR);
647 if (cm)
648 mpr_free_command(sc, cm);
649 return (error);
650 }
651
652 /**
653 * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
654 * @sc: per adapter object
655 * @mpi_reply: reply mf payload returned from firmware
656 * @config_page: contents of the config page
657 * @entry_idx: entry index in DPM Page0 to be modified
658 * Context: sleep.
659 *
660 * Returns 0 for success, non-zero for failure.
661 */
662
663 int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
664 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
665 {
666 MPI2_CONFIG_REQUEST *request;
667 MPI2_CONFIG_REPLY *reply;
668 struct mpr_command *cm;
669 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
670 int error = 0;
671 u16 ioc_status;
672
673 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
674
675 if ((cm = mpr_alloc_command(sc)) == NULL) {
676 printf("%s: command alloc failed @ line %d\n", __func__,
677 __LINE__);
678 error = EBUSY;
679 goto out;
680 }
681 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
682 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
683 request->Function = MPI2_FUNCTION_CONFIG;
684 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
685 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
686 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
687 request->Header.PageNumber = 0;
688 request->ExtPageLength = request->Header.PageVersion = 0;
689 /* We can remove below two lines ????*/
690 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
691 request->PageAddress |= htole16(entry_idx);
692 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
693 cm->cm_data = NULL;
694 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
695 if (cm != NULL)
696 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
697 if (error || (reply == NULL)) {
698 /* FIXME */
699 /*
700 * If the request returns an error then we need to do a diag
701 * reset
702 */
703 printf("%s: request for header completed with error %d",
704 __func__, error);
705 error = ENXIO;
706 goto out;
707 }
708 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
709 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
710 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
711 /* FIXME */
712 /*
713 * If the request returns an error then we need to do a diag
714 * reset
715 */
716 printf("%s: header read with error; iocstatus = 0x%x\n",
717 __func__, ioc_status);
718 error = ENXIO;
719 goto out;
720 }
721 /* We have to do free and alloc for the reply-free and reply-post
722 * counters to match - Need to review the reply FIFO handling.
723 */
724 mpr_free_command(sc, cm);
725
726 if ((cm = mpr_alloc_command(sc)) == NULL) {
727 printf("%s: command alloc failed @ line %d\n", __func__,
728 __LINE__);
729 error = EBUSY;
730 goto out;
731 }
732 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
733 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
734 request->Function = MPI2_FUNCTION_CONFIG;
735 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
736 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
737 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
738 request->Header.PageNumber = 0;
739 request->Header.PageVersion = mpi_reply->Header.PageVersion;
740 request->ExtPageLength = mpi_reply->ExtPageLength;
741 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
742 request->PageAddress |= htole16(entry_idx);
743 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
744 cm->cm_sge = &request->PageBufferSGE;
745 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
746 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT;
747 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
748 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
749 if (!page) {
750 printf("%s: page alloc failed\n", __func__);
751 error = ENOMEM;
752 goto out;
753 }
754 bcopy(config_page, page, MIN(cm->cm_length,
755 (sizeof(Mpi2DriverMappingPage0_t))));
756 cm->cm_data = page;
757 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
758 if (cm != NULL)
759 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
760 if (error || (reply == NULL)) {
761 /* FIXME */
762 /*
763 * If the request returns an error then we need to do a diag
764 * reset
765 */
766 printf("%s: request to write page completed with error %d",
767 __func__, error);
768 error = ENXIO;
769 goto out;
770 }
771 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
772 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
773 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
774 /* FIXME */
775 /*
776 * If the request returns an error then we need to do a diag
777 * reset
778 */
779 printf("%s: page written with error; iocstatus = 0x%x\n",
780 __func__, ioc_status);
781 error = ENXIO;
782 goto out;
783 }
784 out:
785 free(page, M_MPR);
786 if (cm)
787 mpr_free_command(sc, cm);
788 return (error);
789 }
790
791 /**
792 * mpr_config_get_sas_device_pg0 - obtain sas device page 0
793 * @sc: per adapter object
794 * @mpi_reply: reply mf payload returned from firmware
795 * @config_page: contents of the config page
796 * @form: GET_NEXT_HANDLE or HANDLE
797 * @handle: device handle
798 * Context: sleep.
799 *
800 * Returns 0 for success, non-zero for failure.
801 */
802 int
803 mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
804 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
805 {
806 MPI2_CONFIG_REQUEST *request;
807 MPI2_CONFIG_REPLY *reply;
808 struct mpr_command *cm;
809 Mpi2SasDevicePage0_t *page = NULL;
810 int error = 0;
811 u16 ioc_status;
812
813 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
814
815 if ((cm = mpr_alloc_command(sc)) == NULL) {
816 printf("%s: command alloc failed @ line %d\n", __func__,
817 __LINE__);
818 error = EBUSY;
819 goto out;
820 }
821 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
822 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
823 request->Function = MPI2_FUNCTION_CONFIG;
824 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
825 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
826 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
827 request->Header.PageNumber = 0;
828 request->ExtPageLength = request->Header.PageVersion = 0;
829 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
830 cm->cm_data = NULL;
831 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
832 if (cm != NULL)
833 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
834 if (error || (reply == NULL)) {
835 /* FIXME */
836 /*
837 * If the request returns an error then we need to do a diag
838 * reset
839 */
840 printf("%s: request for header completed with error %d",
841 __func__, error);
842 error = ENXIO;
843 goto out;
844 }
845 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
846 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
847 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
848 /* FIXME */
849 /*
850 * If the request returns an error then we need to do a diag
851 * reset
852 */
853 printf("%s: header read with error; iocstatus = 0x%x\n",
854 __func__, ioc_status);
855 error = ENXIO;
856 goto out;
857 }
858 /* We have to do free and alloc for the reply-free and reply-post
859 * counters to match - Need to review the reply FIFO handling.
860 */
861 mpr_free_command(sc, cm);
862
863 if ((cm = mpr_alloc_command(sc)) == NULL) {
864 printf("%s: command alloc failed @ line %d\n", __func__,
865 __LINE__);
866 error = EBUSY;
867 goto out;
868 }
869 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
870 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
871 request->Function = MPI2_FUNCTION_CONFIG;
872 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
873 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
874 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
875 request->Header.PageNumber = 0;
876 request->Header.PageVersion = mpi_reply->Header.PageVersion;
877 request->ExtPageLength = mpi_reply->ExtPageLength;
878 request->PageAddress = htole32(form | handle);
879 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
880 cm->cm_sge = &request->PageBufferSGE;
881 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
882 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
883 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
884 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
885 if (!page) {
886 printf("%s: page alloc failed\n", __func__);
887 error = ENOMEM;
888 goto out;
889 }
890 cm->cm_data = page;
891
892 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
893 if (cm != NULL)
894 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
895 if (error || (reply == NULL)) {
896 /* FIXME */
897 /*
898 * If the request returns an error then we need to do a diag
899 * reset
900 */
901 printf("%s: request for page completed with error %d",
902 __func__, error);
903 error = ENXIO;
904 goto out;
905 }
906 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
907 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
908 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
909 /* FIXME */
910 /*
911 * If the request returns an error then we need to do a diag
912 * reset
913 */
914 printf("%s: page read with error; iocstatus = 0x%x\n",
915 __func__, ioc_status);
916 error = ENXIO;
917 goto out;
918 }
919 bcopy(page, config_page, MIN(cm->cm_length,
920 sizeof(Mpi2SasDevicePage0_t)));
921 out:
922 free(page, M_MPR);
923 if (cm)
924 mpr_free_command(sc, cm);
925 return (error);
926 }
927
928 /**
929 * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0
930 * @sc: per adapter object
931 * @mpi_reply: reply mf payload returned from firmware
932 * @config_page: contents of the config page
933 * @form: GET_NEXT_HANDLE or HANDLE
934 * @handle: device handle
935 * Context: sleep.
936 *
937 * Returns 0 for success, non-zero for failure.
938 */
939 int
940 mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
941 *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle)
942 {
943 MPI2_CONFIG_REQUEST *request;
944 MPI2_CONFIG_REPLY *reply;
945 struct mpr_command *cm;
946 Mpi26PCIeDevicePage0_t *page = NULL;
947 int error = 0;
948 u16 ioc_status;
949
950 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
951
952 if ((cm = mpr_alloc_command(sc)) == NULL) {
953 printf("%s: command alloc failed @ line %d\n", __func__,
954 __LINE__);
955 error = EBUSY;
956 goto out;
957 }
958 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
959 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
960 request->Function = MPI2_FUNCTION_CONFIG;
961 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
962 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
963 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
964 request->Header.PageNumber = 0;
965 request->ExtPageLength = request->Header.PageVersion = 0;
966 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
967 cm->cm_data = NULL;
968 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
969 if (cm != NULL)
970 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
971 if (error || (reply == NULL)) {
972 /* FIXME */
973 /*
974 * If the request returns an error then we need to do a diag
975 * reset
976 */
977 printf("%s: request for header completed with error %d",
978 __func__, error);
979 error = ENXIO;
980 goto out;
981 }
982 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
983 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
984 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
985 /* FIXME */
986 /*
987 * If the request returns an error then we need to do a diag
988 * reset
989 */
990 printf("%s: header read with error; iocstatus = 0x%x\n",
991 __func__, ioc_status);
992 error = ENXIO;
993 goto out;
994 }
995 /* We have to do free and alloc for the reply-free and reply-post
996 * counters to match - Need to review the reply FIFO handling.
997 */
998 mpr_free_command(sc, cm);
999
1000 if ((cm = mpr_alloc_command(sc)) == NULL) {
1001 printf("%s: command alloc failed @ line %d\n", __func__,
1002 __LINE__);
1003 error = EBUSY;
1004 goto out;
1005 }
1006 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1007 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1008 request->Function = MPI2_FUNCTION_CONFIG;
1009 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1010 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1011 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1012 request->Header.PageNumber = 0;
1013 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1014 request->ExtPageLength = mpi_reply->ExtPageLength;
1015 request->PageAddress = htole32(form | handle);
1016 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
1017 cm->cm_sge = &request->PageBufferSGE;
1018 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1019 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1020 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1021 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1022 if (!page) {
1023 printf("%s: page alloc failed\n", __func__);
1024 error = ENOMEM;
1025 goto out;
1026 }
1027 cm->cm_data = page;
1028
1029 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1030 if (cm != NULL)
1031 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1032 if (error || (reply == NULL)) {
1033 /* FIXME */
1034 /*
1035 * If the request returns an error then we need to do a diag
1036 * reset
1037 */
1038 printf("%s: request for page completed with error %d",
1039 __func__, error);
1040 error = ENXIO;
1041 goto out;
1042 }
1043 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1044 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1045 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1046 /* FIXME */
1047 /*
1048 * If the request returns an error then we need to do a diag
1049 * reset
1050 */
1051 printf("%s: page read with error; iocstatus = 0x%x\n",
1052 __func__, ioc_status);
1053 error = ENXIO;
1054 goto out;
1055 }
1056 bcopy(page, config_page, MIN(cm->cm_length,
1057 sizeof(Mpi26PCIeDevicePage0_t)));
1058 out:
1059 free(page, M_MPR);
1060 if (cm)
1061 mpr_free_command(sc, cm);
1062 return (error);
1063 }
1064
1065 /**
1066 * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2
1067 * @sc: per adapter object
1068 * @mpi_reply: reply mf payload returned from firmware
1069 * @config_page: contents of the config page
1070 * @form: GET_NEXT_HANDLE or HANDLE
1071 * @handle: device handle
1072 * Context: sleep.
1073 *
1074 * Returns 0 for success, non-zero for failure.
1075 */
1076 int
1077 mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t
1078 *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle)
1079 {
1080 MPI2_CONFIG_REQUEST *request;
1081 MPI2_CONFIG_REPLY *reply;
1082 struct mpr_command *cm;
1083 Mpi26PCIeDevicePage2_t *page = NULL;
1084 int error = 0;
1085 u16 ioc_status;
1086
1087 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1088
1089 if ((cm = mpr_alloc_command(sc)) == NULL) {
1090 printf("%s: command alloc failed @ line %d\n", __func__,
1091 __LINE__);
1092 error = EBUSY;
1093 goto out;
1094 }
1095 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1096 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1097 request->Function = MPI2_FUNCTION_CONFIG;
1098 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1099 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1100 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1101 request->Header.PageNumber = 2;
1102 request->ExtPageLength = request->Header.PageVersion = 0;
1103 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1104 cm->cm_data = NULL;
1105 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1106 if (cm != NULL)
1107 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1108 if (error || (reply == NULL)) {
1109 /* FIXME */
1110 /*
1111 * If the request returns an error then we need to do a diag
1112 * reset
1113 */
1114 printf("%s: request for header completed with error %d",
1115 __func__, error);
1116 error = ENXIO;
1117 goto out;
1118 }
1119 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1120 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1121 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1122 /* FIXME */
1123 /*
1124 * If the request returns an error then we need to do a diag
1125 * reset
1126 */
1127 printf("%s: header read with error; iocstatus = 0x%x\n",
1128 __func__, ioc_status);
1129 error = ENXIO;
1130 goto out;
1131 }
1132 /* We have to do free and alloc for the reply-free and reply-post
1133 * counters to match - Need to review the reply FIFO handling.
1134 */
1135 mpr_free_command(sc, cm);
1136
1137 if ((cm = mpr_alloc_command(sc)) == NULL) {
1138 printf("%s: command alloc failed @ line %d\n", __func__,
1139 __LINE__);
1140 error = EBUSY;
1141 goto out;
1142 }
1143 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1144 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1145 request->Function = MPI2_FUNCTION_CONFIG;
1146 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1147 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1148 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1149 request->Header.PageNumber = 2;
1150 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1151 request->ExtPageLength = mpi_reply->ExtPageLength;
1152 request->PageAddress = htole32(form | handle);
1153 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
1154 cm->cm_sge = &request->PageBufferSGE;
1155 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1156 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1157 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1158 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1159 if (!page) {
1160 printf("%s: page alloc failed\n", __func__);
1161 error = ENOMEM;
1162 goto out;
1163 }
1164 cm->cm_data = page;
1165
1166 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1167 if (cm != NULL)
1168 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1169 if (error || (reply == NULL)) {
1170 /* FIXME */
1171 /*
1172 * If the request returns an error then we need to do a diag
1173 * reset
1174 */
1175 printf("%s: request for page completed with error %d",
1176 __func__, error);
1177 error = ENXIO;
1178 goto out;
1179 }
1180 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1181 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1182 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1183 /* FIXME */
1184 /*
1185 * If the request returns an error then we need to do a diag
1186 * reset
1187 */
1188 printf("%s: page read with error; iocstatus = 0x%x\n",
1189 __func__, ioc_status);
1190 error = ENXIO;
1191 goto out;
1192 }
1193 bcopy(page, config_page, MIN(cm->cm_length,
1194 sizeof(Mpi26PCIeDevicePage2_t)));
1195 out:
1196 free(page, M_MPR);
1197 if (cm)
1198 mpr_free_command(sc, cm);
1199 return (error);
1200 }
1201
1202 /**
1203 * mpr_config_get_bios_pg3 - obtain BIOS page 3
1204 * @sc: per adapter object
1205 * @mpi_reply: reply mf payload returned from firmware
1206 * @config_page: contents of the config page
1207 * Context: sleep.
1208 *
1209 * Returns 0 for success, non-zero for failure.
1210 */
1211 int
1212 mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1213 Mpi2BiosPage3_t *config_page)
1214 {
1215 MPI2_CONFIG_REQUEST *request;
1216 MPI2_CONFIG_REPLY *reply;
1217 struct mpr_command *cm;
1218 Mpi2BiosPage3_t *page = NULL;
1219 int error = 0;
1220 u16 ioc_status;
1221
1222 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1223
1224 if ((cm = mpr_alloc_command(sc)) == NULL) {
1225 printf("%s: command alloc failed @ line %d\n", __func__,
1226 __LINE__);
1227 error = EBUSY;
1228 goto out;
1229 }
1230 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1231 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1232 request->Function = MPI2_FUNCTION_CONFIG;
1233 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1234 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1235 request->Header.PageNumber = 3;
1236 request->Header.PageLength = request->Header.PageVersion = 0;
1237 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1238 cm->cm_data = NULL;
1239 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1240 if (cm != NULL)
1241 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1242 if (error || (reply == NULL)) {
1243 /* FIXME */
1244 /*
1245 * If the request returns an error then we need to do a diag
1246 * reset
1247 */
1248 printf("%s: request for header completed with error %d",
1249 __func__, error);
1250 error = ENXIO;
1251 goto out;
1252 }
1253 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1254 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1255 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1256 /* FIXME */
1257 /*
1258 * If the request returns an error then we need to do a diag
1259 * reset
1260 */
1261 printf("%s: header read with error; iocstatus = 0x%x\n",
1262 __func__, ioc_status);
1263 error = ENXIO;
1264 goto out;
1265 }
1266 /* We have to do free and alloc for the reply-free and reply-post
1267 * counters to match - Need to review the reply FIFO handling.
1268 */
1269 mpr_free_command(sc, cm);
1270
1271 if ((cm = mpr_alloc_command(sc)) == NULL) {
1272 printf("%s: command alloc failed @ line %d\n", __func__,
1273 __LINE__);
1274 error = EBUSY;
1275 goto out;
1276 }
1277 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1278 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1279 request->Function = MPI2_FUNCTION_CONFIG;
1280 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1281 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1282 request->Header.PageNumber = 3;
1283 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1284 request->Header.PageLength = mpi_reply->Header.PageLength;
1285 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1286 cm->cm_sge = &request->PageBufferSGE;
1287 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1288 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1289 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1290 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1291 if (!page) {
1292 printf("%s: page alloc failed\n", __func__);
1293 error = ENOMEM;
1294 goto out;
1295 }
1296 cm->cm_data = page;
1297
1298 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1299 if (cm != NULL)
1300 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1301 if (error || (reply == NULL)) {
1302 /* FIXME */
1303 /*
1304 * If the request returns an error then we need to do a diag
1305 * reset
1306 */
1307 printf("%s: request for page completed with error %d",
1308 __func__, error);
1309 error = ENXIO;
1310 goto out;
1311 }
1312 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1313 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1314 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1315 /* FIXME */
1316 /*
1317 * If the request returns an error then we need to do a diag
1318 * reset
1319 */
1320 printf("%s: page read with error; iocstatus = 0x%x\n",
1321 __func__, ioc_status);
1322 error = ENXIO;
1323 goto out;
1324 }
1325 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1326 out:
1327 free(page, M_MPR);
1328 if (cm)
1329 mpr_free_command(sc, cm);
1330 return (error);
1331 }
1332
1333 /**
1334 * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0
1335 * @sc: per adapter object
1336 * @mpi_reply: reply mf payload returned from firmware
1337 * @config_page: contents of the config page
1338 * @page_address: form and handle value used to get page
1339 * Context: sleep.
1340 *
1341 * Returns 0 for success, non-zero for failure.
1342 */
1343 int
1344 mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
1345 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1346 {
1347 MPI2_CONFIG_REQUEST *request;
1348 MPI2_CONFIG_REPLY *reply = NULL;
1349 struct mpr_command *cm;
1350 Mpi2RaidVolPage0_t *page = NULL;
1351 int error = 0;
1352 u16 ioc_status;
1353
1354 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1355
1356 if ((cm = mpr_alloc_command(sc)) == NULL) {
1357 printf("%s: command alloc failed @ line %d\n", __func__,
1358 __LINE__);
1359 error = EBUSY;
1360 goto out;
1361 }
1362 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1363 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1364 request->Function = MPI2_FUNCTION_CONFIG;
1365 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1366 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1367 request->Header.PageNumber = 0;
1368 request->Header.PageLength = request->Header.PageVersion = 0;
1369 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1370 cm->cm_data = NULL;
1371
1372 /*
1373 * This page must be polled because the IOC isn't ready yet when this
1374 * page is needed.
1375 */
1376 error = mpr_request_polled(sc, &cm);
1377 if (cm != NULL)
1378 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1379 if (error || (reply == NULL)) {
1380 /* FIXME */
1381 /* If the poll returns error then we need to do diag reset */
1382 printf("%s: poll for header completed with error %d",
1383 __func__, error);
1384 error = ENXIO;
1385 goto out;
1386 }
1387 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1388 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1389 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1390 /* FIXME */
1391 /* If the poll returns error then we need to do diag reset */
1392 printf("%s: header read with error; iocstatus = 0x%x\n",
1393 __func__, ioc_status);
1394 error = ENXIO;
1395 goto out;
1396 }
1397 /* We have to do free and alloc for the reply-free and reply-post
1398 * counters to match - Need to review the reply FIFO handling.
1399 */
1400 mpr_free_command(sc, cm);
1401
1402 if ((cm = mpr_alloc_command(sc)) == NULL) {
1403 printf("%s: command alloc failed @ line %d\n", __func__,
1404 __LINE__);
1405 error = EBUSY;
1406 goto out;
1407 }
1408 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1409 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1410 request->Function = MPI2_FUNCTION_CONFIG;
1411 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1412 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1413 request->Header.PageNumber = 0;
1414 request->Header.PageLength = mpi_reply->Header.PageLength;
1415 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1416 request->PageAddress = page_address;
1417 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1418 cm->cm_sge = &request->PageBufferSGE;
1419 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1420 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1421 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1422 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1423 if (!page) {
1424 printf("%s: page alloc failed\n", __func__);
1425 error = ENOMEM;
1426 goto out;
1427 }
1428 cm->cm_data = page;
1429
1430 /*
1431 * This page must be polled because the IOC isn't ready yet when this
1432 * page is needed.
1433 */
1434 error = mpr_request_polled(sc, &cm);
1435 if (cm != NULL)
1436 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1437 if (error || (reply == NULL)) {
1438 /* FIXME */
1439 /* If the poll returns error then we need to do diag reset */
1440 printf("%s: poll for page completed with error %d",
1441 __func__, error);
1442 error = ENXIO;
1443 goto out;
1444 }
1445 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1446 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1447 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1448 /* FIXME */
1449 /* If the poll returns error then we need to do diag reset */
1450 printf("%s: page read with error; iocstatus = 0x%x\n",
1451 __func__, ioc_status);
1452 error = ENXIO;
1453 goto out;
1454 }
1455 bcopy(page, config_page, cm->cm_length);
1456 out:
1457 free(page, M_MPR);
1458 if (cm)
1459 mpr_free_command(sc, cm);
1460 return (error);
1461 }
1462
1463 /**
1464 * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1
1465 * @sc: per adapter object
1466 * @mpi_reply: reply mf payload returned from firmware
1467 * @config_page: contents of the config page
1468 * @form: GET_NEXT_HANDLE or HANDLE
1469 * @handle: volume handle
1470 * Context: sleep.
1471 *
1472 * Returns 0 for success, non-zero for failure.
1473 */
1474 int
1475 mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
1476 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1477 {
1478 MPI2_CONFIG_REQUEST *request;
1479 MPI2_CONFIG_REPLY *reply;
1480 struct mpr_command *cm;
1481 Mpi2RaidVolPage1_t *page = NULL;
1482 int error = 0;
1483 u16 ioc_status;
1484
1485 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1486
1487 if ((cm = mpr_alloc_command(sc)) == NULL) {
1488 printf("%s: command alloc failed @ line %d\n", __func__,
1489 __LINE__);
1490 error = EBUSY;
1491 goto out;
1492 }
1493 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1494 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1495 request->Function = MPI2_FUNCTION_CONFIG;
1496 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1497 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1498 request->Header.PageNumber = 1;
1499 request->Header.PageLength = request->Header.PageVersion = 0;
1500 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1501 cm->cm_data = NULL;
1502 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1503 if (cm != NULL)
1504 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1505 if (error || (reply == NULL)) {
1506 /* FIXME */
1507 /*
1508 * If the request returns an error then we need to do a diag
1509 * reset
1510 */
1511 printf("%s: request for header completed with error %d",
1512 __func__, error);
1513 error = ENXIO;
1514 goto out;
1515 }
1516 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1517 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1518 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1519 /* FIXME */
1520 /*
1521 * If the request returns an error then we need to do a diag
1522 * reset
1523 */
1524 printf("%s: header read with error; iocstatus = 0x%x\n",
1525 __func__, ioc_status);
1526 error = ENXIO;
1527 goto out;
1528 }
1529 /* We have to do free and alloc for the reply-free and reply-post
1530 * counters to match - Need to review the reply FIFO handling.
1531 */
1532 mpr_free_command(sc, cm);
1533
1534 if ((cm = mpr_alloc_command(sc)) == NULL) {
1535 printf("%s: command alloc failed @ line %d\n", __func__,
1536 __LINE__);
1537 error = EBUSY;
1538 goto out;
1539 }
1540 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1541 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1542 request->Function = MPI2_FUNCTION_CONFIG;
1543 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1544 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1545 request->Header.PageNumber = 1;
1546 request->Header.PageLength = mpi_reply->Header.PageLength;
1547 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1548 request->PageAddress = htole32(form | handle);
1549 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1550 cm->cm_sge = &request->PageBufferSGE;
1551 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1552 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1553 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1554 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1555 if (!page) {
1556 printf("%s: page alloc failed\n", __func__);
1557 error = ENOMEM;
1558 goto out;
1559 }
1560 cm->cm_data = page;
1561
1562 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1563 if (cm != NULL)
1564 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1565 if (error || (reply == NULL)) {
1566 /* FIXME */
1567 /*
1568 * If the request returns an error then we need to do a diag
1569 * reset
1570 */
1571 printf("%s: request for page completed with error %d",
1572 __func__, error);
1573 error = ENXIO;
1574 goto out;
1575 }
1576 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1577 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1578 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1579 /* FIXME */
1580 /*
1581 * If the request returns an error then we need to do a diag
1582 * reset
1583 */
1584 printf("%s: page read with error; iocstatus = 0x%x\n",
1585 __func__, ioc_status);
1586 error = ENXIO;
1587 goto out;
1588 }
1589 bcopy(page, config_page, MIN(cm->cm_length,
1590 sizeof(Mpi2RaidVolPage1_t)));
1591 out:
1592 free(page, M_MPR);
1593 if (cm)
1594 mpr_free_command(sc, cm);
1595 return (error);
1596 }
1597
1598 /**
1599 * mpr_config_get_volume_wwid - returns wwid given the volume handle
1600 * @sc: per adapter object
1601 * @volume_handle: volume handle
1602 * @wwid: volume wwid
1603 * Context: sleep.
1604 *
1605 * Returns 0 for success, non-zero for failure.
1606 */
1607 int
1608 mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid)
1609 {
1610 Mpi2ConfigReply_t mpi_reply;
1611 Mpi2RaidVolPage1_t raid_vol_pg1;
1612
1613 *wwid = 0;
1614 if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1615 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1616 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1617 raid_vol_pg1.WWID.Low);
1618 return 0;
1619 } else
1620 return -1;
1621 }
1622
1623 /**
1624 * mpr_config_get_pd_pg0 - obtain raid phys disk page 0
1625 * @sc: per adapter object
1626 * @mpi_reply: reply mf payload returned from firmware
1627 * @config_page: contents of the config page
1628 * @page_address: form and handle value used to get page
1629 * Context: sleep.
1630 *
1631 * Returns 0 for success, non-zero for failure.
1632 */
1633 int
1634 mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1635 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1636 {
1637 MPI2_CONFIG_REQUEST *request;
1638 MPI2_CONFIG_REPLY *reply = NULL;
1639 struct mpr_command *cm;
1640 Mpi2RaidPhysDiskPage0_t *page = NULL;
1641 int error = 0;
1642 u16 ioc_status;
1643
1644 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1645
1646 if ((cm = mpr_alloc_command(sc)) == NULL) {
1647 printf("%s: command alloc failed @ line %d\n", __func__,
1648 __LINE__);
1649 error = EBUSY;
1650 goto out;
1651 }
1652 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1653 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1654 request->Function = MPI2_FUNCTION_CONFIG;
1655 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1656 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1657 request->Header.PageNumber = 0;
1658 request->Header.PageLength = request->Header.PageVersion = 0;
1659 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1660 cm->cm_data = NULL;
1661
1662 /*
1663 * This page must be polled because the IOC isn't ready yet when this
1664 * page is needed.
1665 */
1666 error = mpr_request_polled(sc, &cm);
1667 if (cm != NULL)
1668 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1669 if (error || (reply == NULL)) {
1670 /* FIXME */
1671 /* If the poll returns error then we need to do diag reset */
1672 printf("%s: poll for header completed with error %d",
1673 __func__, error);
1674 error = ENXIO;
1675 goto out;
1676 }
1677 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1678 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1679 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1680 /* FIXME */
1681 /* If the poll returns error then we need to do diag reset */
1682 printf("%s: header read with error; iocstatus = 0x%x\n",
1683 __func__, ioc_status);
1684 error = ENXIO;
1685 goto out;
1686 }
1687 /* We have to do free and alloc for the reply-free and reply-post
1688 * counters to match - Need to review the reply FIFO handling.
1689 */
1690 mpr_free_command(sc, cm);
1691
1692 if ((cm = mpr_alloc_command(sc)) == NULL) {
1693 printf("%s: command alloc failed @ line %d\n", __func__,
1694 __LINE__);
1695 error = EBUSY;
1696 goto out;
1697 }
1698 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1699 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1700 request->Function = MPI2_FUNCTION_CONFIG;
1701 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1702 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1703 request->Header.PageNumber = 0;
1704 request->Header.PageLength = mpi_reply->Header.PageLength;
1705 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1706 request->PageAddress = page_address;
1707 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1708 cm->cm_sge = &request->PageBufferSGE;
1709 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1710 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1711 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1712 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1713 if (!page) {
1714 printf("%s: page alloc failed\n", __func__);
1715 error = ENOMEM;
1716 goto out;
1717 }
1718 cm->cm_data = page;
1719
1720 /*
1721 * This page must be polled because the IOC isn't ready yet when this
1722 * page is needed.
1723 */
1724 error = mpr_request_polled(sc, &cm);
1725 if (cm != NULL)
1726 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1727 if (error || (reply == NULL)) {
1728 /* FIXME */
1729 /* If the poll returns error then we need to do diag reset */
1730 printf("%s: poll for page completed with error %d",
1731 __func__, error);
1732 error = ENXIO;
1733 goto out;
1734 }
1735 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1736 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1737 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1738 /* FIXME */
1739 /* If the poll returns error then we need to do diag reset */
1740 printf("%s: page read with error; iocstatus = 0x%x\n",
1741 __func__, ioc_status);
1742 error = ENXIO;
1743 goto out;
1744 }
1745 bcopy(page, config_page, MIN(cm->cm_length,
1746 sizeof(Mpi2RaidPhysDiskPage0_t)));
1747 out:
1748 free(page, M_MPR);
1749 if (cm)
1750 mpr_free_command(sc, cm);
1751 return (error);
1752 }
Cache object: 22d76aa6251af71268c407f40ee12e48
|