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