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