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 = 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 = 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 /* We can remove below two lines ????*/
688 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
689 request->PageAddress |= htole16(entry_idx);
690 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
691 cm->cm_data = NULL;
692 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
693 if (cm != NULL)
694 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
695 if (error || (reply == NULL)) {
696 /* FIXME */
697 /*
698 * If the request returns an error then we need to do a diag
699 * reset
700 */
701 printf("%s: request for header completed with error %d\n",
702 __func__, error);
703 error = ENXIO;
704 goto out;
705 }
706 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
707 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
708 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
709 /* FIXME */
710 /*
711 * If the request returns an error then we need to do a diag
712 * reset
713 */
714 printf("%s: header read with error; iocstatus = 0x%x\n",
715 __func__, ioc_status);
716 error = ENXIO;
717 goto out;
718 }
719 /* We have to do free and alloc for the reply-free and reply-post
720 * counters to match - Need to review the reply FIFO handling.
721 */
722 mpr_free_command(sc, cm);
723
724 if ((cm = mpr_alloc_command(sc)) == NULL) {
725 printf("%s: command alloc failed @ line %d\n", __func__,
726 __LINE__);
727 error = EBUSY;
728 goto out;
729 }
730 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
731 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
732 request->Function = MPI2_FUNCTION_CONFIG;
733 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
734 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
735 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
736 request->Header.PageNumber = 0;
737 request->Header.PageVersion = mpi_reply->Header.PageVersion;
738 request->ExtPageLength = mpi_reply->ExtPageLength;
739 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
740 request->PageAddress |= htole16(entry_idx);
741 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
742 cm->cm_sge = &request->PageBufferSGE;
743 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
744 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT;
745 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
746 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
747 if (!page) {
748 printf("%s: page alloc failed\n", __func__);
749 error = ENOMEM;
750 goto out;
751 }
752 bcopy(config_page, page, MIN(cm->cm_length,
753 (sizeof(Mpi2DriverMappingPage0_t))));
754 cm->cm_data = page;
755 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
756 if (cm != NULL)
757 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
758 if (error || (reply == NULL)) {
759 /* FIXME */
760 /*
761 * If the request returns an error then we need to do a diag
762 * reset
763 */
764 printf("%s: request to write page completed with error %d\n",
765 __func__, error);
766 error = ENXIO;
767 goto out;
768 }
769 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
770 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
771 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
772 /* FIXME */
773 /*
774 * If the request returns an error then we need to do a diag
775 * reset
776 */
777 printf("%s: page written with error; iocstatus = 0x%x\n",
778 __func__, ioc_status);
779 error = ENXIO;
780 goto out;
781 }
782 out:
783 free(page, M_MPR);
784 if (cm)
785 mpr_free_command(sc, cm);
786 return (error);
787 }
788
789 /**
790 * mpr_config_get_sas_device_pg0 - obtain sas device page 0
791 * @sc: per adapter object
792 * @mpi_reply: reply mf payload returned from firmware
793 * @config_page: contents of the config page
794 * @form: GET_NEXT_HANDLE or HANDLE
795 * @handle: device handle
796 * Context: sleep.
797 *
798 * Returns 0 for success, non-zero for failure.
799 */
800 int
mpr_config_get_sas_device_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2SasDevicePage0_t * config_page,u32 form,u16 handle)801 mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
802 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
803 {
804 MPI2_CONFIG_REQUEST *request;
805 MPI2_CONFIG_REPLY *reply;
806 struct mpr_command *cm;
807 Mpi2SasDevicePage0_t *page = NULL;
808 int error = 0;
809 u16 ioc_status;
810
811 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
812
813 if ((cm = mpr_alloc_command(sc)) == NULL) {
814 printf("%s: command alloc failed @ line %d\n", __func__,
815 __LINE__);
816 error = EBUSY;
817 goto out;
818 }
819 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
820 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
821 request->Function = MPI2_FUNCTION_CONFIG;
822 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
823 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
824 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
825 request->Header.PageNumber = 0;
826 request->ExtPageLength = request->Header.PageVersion = 0;
827 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
828 cm->cm_data = NULL;
829 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
830 if (cm != NULL)
831 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
832 if (error || (reply == NULL)) {
833 /* FIXME */
834 /*
835 * If the request returns an error then we need to do a diag
836 * reset
837 */
838 printf("%s: request for header completed with error %d\n",
839 __func__, error);
840 error = ENXIO;
841 goto out;
842 }
843 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
844 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
845 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
846 /* FIXME */
847 /*
848 * If the request returns an error then we need to do a diag
849 * reset
850 */
851 printf("%s: header read with error; iocstatus = 0x%x\n",
852 __func__, ioc_status);
853 error = ENXIO;
854 goto out;
855 }
856 /* We have to do free and alloc for the reply-free and reply-post
857 * counters to match - Need to review the reply FIFO handling.
858 */
859 mpr_free_command(sc, cm);
860
861 if ((cm = mpr_alloc_command(sc)) == NULL) {
862 printf("%s: command alloc failed @ line %d\n", __func__,
863 __LINE__);
864 error = EBUSY;
865 goto out;
866 }
867 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
868 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
869 request->Function = MPI2_FUNCTION_CONFIG;
870 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
871 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
872 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
873 request->Header.PageNumber = 0;
874 request->Header.PageVersion = mpi_reply->Header.PageVersion;
875 request->ExtPageLength = mpi_reply->ExtPageLength;
876 request->PageAddress = htole32(form | handle);
877 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
878 cm->cm_sge = &request->PageBufferSGE;
879 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
880 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
881 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
882 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
883 if (!page) {
884 printf("%s: page alloc failed\n", __func__);
885 error = ENOMEM;
886 goto out;
887 }
888 cm->cm_data = page;
889
890 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
891 if (cm != NULL)
892 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
893 if (error || (reply == NULL)) {
894 /* FIXME */
895 /*
896 * If the request returns an error then we need to do a diag
897 * reset
898 */
899 printf("%s: request for page completed with error %d\n",
900 __func__, error);
901 error = ENXIO;
902 goto out;
903 }
904 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
905 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
906 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
907 /* FIXME */
908 /*
909 * If the request returns an error then we need to do a diag
910 * reset
911 */
912 printf("%s: page read with error; iocstatus = 0x%x\n",
913 __func__, ioc_status);
914 error = ENXIO;
915 goto out;
916 }
917 bcopy(page, config_page, MIN(cm->cm_length,
918 sizeof(Mpi2SasDevicePage0_t)));
919 out:
920 free(page, M_MPR);
921 if (cm)
922 mpr_free_command(sc, cm);
923 return (error);
924 }
925
926 /**
927 * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0
928 * @sc: per adapter object
929 * @mpi_reply: reply mf payload returned from firmware
930 * @config_page: contents of the config page
931 * @form: GET_NEXT_HANDLE or HANDLE
932 * @handle: device handle
933 * Context: sleep.
934 *
935 * Returns 0 for success, non-zero for failure.
936 */
937 int
mpr_config_get_pcie_device_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi26PCIeDevicePage0_t * config_page,u32 form,u16 handle)938 mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
939 *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle)
940 {
941 MPI2_CONFIG_REQUEST *request;
942 MPI2_CONFIG_REPLY *reply;
943 struct mpr_command *cm;
944 Mpi26PCIeDevicePage0_t *page = NULL;
945 int error = 0;
946 u16 ioc_status;
947
948 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
949
950 if ((cm = mpr_alloc_command(sc)) == NULL) {
951 printf("%s: command alloc failed @ line %d\n", __func__,
952 __LINE__);
953 error = EBUSY;
954 goto out;
955 }
956 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
957 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
958 request->Function = MPI2_FUNCTION_CONFIG;
959 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
960 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
961 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
962 request->Header.PageNumber = 0;
963 request->ExtPageLength = request->Header.PageVersion = 0;
964 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
965 cm->cm_data = NULL;
966 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
967 if (cm != NULL)
968 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
969 if (error || (reply == NULL)) {
970 /* FIXME */
971 /*
972 * If the request returns an error then we need to do a diag
973 * reset
974 */
975 printf("%s: request for header completed with error %d\n",
976 __func__, error);
977 error = ENXIO;
978 goto out;
979 }
980 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
981 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
982 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
983 /* FIXME */
984 /*
985 * If the request returns an error then we need to do a diag
986 * reset
987 */
988 printf("%s: header read with error; iocstatus = 0x%x\n",
989 __func__, ioc_status);
990 error = ENXIO;
991 goto out;
992 }
993 /* We have to do free and alloc for the reply-free and reply-post
994 * counters to match - Need to review the reply FIFO handling.
995 */
996 mpr_free_command(sc, cm);
997
998 if ((cm = mpr_alloc_command(sc)) == NULL) {
999 printf("%s: command alloc failed @ line %d\n", __func__,
1000 __LINE__);
1001 error = EBUSY;
1002 goto out;
1003 }
1004 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1005 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1006 request->Function = MPI2_FUNCTION_CONFIG;
1007 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1008 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1009 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1010 request->Header.PageNumber = 0;
1011 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1012 request->ExtPageLength = mpi_reply->ExtPageLength;
1013 request->PageAddress = htole32(form | handle);
1014 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
1015 cm->cm_sge = &request->PageBufferSGE;
1016 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1017 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1018 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1019 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1020 if (!page) {
1021 printf("%s: page alloc failed\n", __func__);
1022 error = ENOMEM;
1023 goto out;
1024 }
1025 cm->cm_data = page;
1026
1027 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1028 if (cm != NULL)
1029 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1030 if (error || (reply == NULL)) {
1031 /* FIXME */
1032 /*
1033 * If the request returns an error then we need to do a diag
1034 * reset
1035 */
1036 printf("%s: request for page completed with error %d\n",
1037 __func__, error);
1038 error = ENXIO;
1039 goto out;
1040 }
1041 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1042 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1043 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1044 /* FIXME */
1045 /*
1046 * If the request returns an error then we need to do a diag
1047 * reset
1048 */
1049 printf("%s: page read with error; iocstatus = 0x%x\n",
1050 __func__, ioc_status);
1051 error = ENXIO;
1052 goto out;
1053 }
1054 bcopy(page, config_page, MIN(cm->cm_length,
1055 sizeof(Mpi26PCIeDevicePage0_t)));
1056 out:
1057 free(page, M_MPR);
1058 if (cm)
1059 mpr_free_command(sc, cm);
1060 return (error);
1061 }
1062
1063 /**
1064 * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2
1065 * @sc: per adapter object
1066 * @mpi_reply: reply mf payload returned from firmware
1067 * @config_page: contents of the config page
1068 * @form: GET_NEXT_HANDLE or HANDLE
1069 * @handle: device handle
1070 * Context: sleep.
1071 *
1072 * Returns 0 for success, non-zero for failure.
1073 */
1074 int
mpr_config_get_pcie_device_pg2(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi26PCIeDevicePage2_t * config_page,u32 form,u16 handle)1075 mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t
1076 *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle)
1077 {
1078 MPI2_CONFIG_REQUEST *request;
1079 MPI2_CONFIG_REPLY *reply;
1080 struct mpr_command *cm;
1081 Mpi26PCIeDevicePage2_t *page = NULL;
1082 int error = 0;
1083 u16 ioc_status;
1084
1085 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1086
1087 if ((cm = mpr_alloc_command(sc)) == NULL) {
1088 printf("%s: command alloc failed @ line %d\n", __func__,
1089 __LINE__);
1090 error = EBUSY;
1091 goto out;
1092 }
1093 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1094 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1095 request->Function = MPI2_FUNCTION_CONFIG;
1096 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1097 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1098 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1099 request->Header.PageNumber = 2;
1100 request->ExtPageLength = request->Header.PageVersion = 0;
1101 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1102 cm->cm_data = NULL;
1103 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1104 if (cm != NULL)
1105 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1106 if (error || (reply == NULL)) {
1107 /* FIXME */
1108 /*
1109 * If the request returns an error then we need to do a diag
1110 * reset
1111 */
1112 printf("%s: request for header completed with error %d\n",
1113 __func__, error);
1114 error = ENXIO;
1115 goto out;
1116 }
1117 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1118 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1119 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1120 /* FIXME */
1121 /*
1122 * If the request returns an error then we need to do a diag
1123 * reset
1124 */
1125 printf("%s: header read with error; iocstatus = 0x%x\n",
1126 __func__, ioc_status);
1127 error = ENXIO;
1128 goto out;
1129 }
1130 /* We have to do free and alloc for the reply-free and reply-post
1131 * counters to match - Need to review the reply FIFO handling.
1132 */
1133 mpr_free_command(sc, cm);
1134
1135 if ((cm = mpr_alloc_command(sc)) == NULL) {
1136 printf("%s: command alloc failed @ line %d\n", __func__,
1137 __LINE__);
1138 error = EBUSY;
1139 goto out;
1140 }
1141 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1142 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1143 request->Function = MPI2_FUNCTION_CONFIG;
1144 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1145 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1146 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1147 request->Header.PageNumber = 2;
1148 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1149 request->ExtPageLength = mpi_reply->ExtPageLength;
1150 request->PageAddress = htole32(form | handle);
1151 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
1152 cm->cm_sge = &request->PageBufferSGE;
1153 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1154 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1155 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1156 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1157 if (!page) {
1158 printf("%s: page alloc failed\n", __func__);
1159 error = ENOMEM;
1160 goto out;
1161 }
1162 cm->cm_data = page;
1163
1164 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1165 if (cm != NULL)
1166 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1167 if (error || (reply == NULL)) {
1168 /* FIXME */
1169 /*
1170 * If the request returns an error then we need to do a diag
1171 * reset
1172 */
1173 printf("%s: request for page completed with error %d\n",
1174 __func__, error);
1175 error = ENXIO;
1176 goto out;
1177 }
1178 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1179 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1180 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1181 /* FIXME */
1182 /*
1183 * If the request returns an error then we need to do a diag
1184 * reset
1185 */
1186 printf("%s: page read with error; iocstatus = 0x%x\n",
1187 __func__, ioc_status);
1188 error = ENXIO;
1189 goto out;
1190 }
1191 bcopy(page, config_page, MIN(cm->cm_length,
1192 sizeof(Mpi26PCIeDevicePage2_t)));
1193 out:
1194 free(page, M_MPR);
1195 if (cm)
1196 mpr_free_command(sc, cm);
1197 return (error);
1198 }
1199
1200 /**
1201 * mpr_config_get_bios_pg3 - obtain BIOS page 3
1202 * @sc: per adapter object
1203 * @mpi_reply: reply mf payload returned from firmware
1204 * @config_page: contents of the config page
1205 * Context: sleep.
1206 *
1207 * Returns 0 for success, non-zero for failure.
1208 */
1209 int
mpr_config_get_bios_pg3(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2BiosPage3_t * config_page)1210 mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1211 Mpi2BiosPage3_t *config_page)
1212 {
1213 MPI2_CONFIG_REQUEST *request;
1214 MPI2_CONFIG_REPLY *reply;
1215 struct mpr_command *cm;
1216 Mpi2BiosPage3_t *page = NULL;
1217 int error = 0;
1218 u16 ioc_status;
1219
1220 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1221
1222 if ((cm = mpr_alloc_command(sc)) == NULL) {
1223 printf("%s: command alloc failed @ line %d\n", __func__,
1224 __LINE__);
1225 error = EBUSY;
1226 goto out;
1227 }
1228 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1229 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1230 request->Function = MPI2_FUNCTION_CONFIG;
1231 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1232 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1233 request->Header.PageNumber = 3;
1234 request->Header.PageLength = request->Header.PageVersion = 0;
1235 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1236 cm->cm_data = NULL;
1237 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1238 if (cm != NULL)
1239 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1240 if (error || (reply == NULL)) {
1241 /* FIXME */
1242 /*
1243 * If the request returns an error then we need to do a diag
1244 * reset
1245 */
1246 printf("%s: request for header completed with error %d\n",
1247 __func__, error);
1248 error = ENXIO;
1249 goto out;
1250 }
1251 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1252 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1253 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1254 /* FIXME */
1255 /*
1256 * If the request returns an error then we need to do a diag
1257 * reset
1258 */
1259 printf("%s: header read with error; iocstatus = 0x%x\n",
1260 __func__, ioc_status);
1261 error = ENXIO;
1262 goto out;
1263 }
1264 /* We have to do free and alloc for the reply-free and reply-post
1265 * counters to match - Need to review the reply FIFO handling.
1266 */
1267 mpr_free_command(sc, cm);
1268
1269 if ((cm = mpr_alloc_command(sc)) == NULL) {
1270 printf("%s: command alloc failed @ line %d\n", __func__,
1271 __LINE__);
1272 error = EBUSY;
1273 goto out;
1274 }
1275 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1276 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1277 request->Function = MPI2_FUNCTION_CONFIG;
1278 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1279 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1280 request->Header.PageNumber = 3;
1281 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1282 request->Header.PageLength = mpi_reply->Header.PageLength;
1283 cm->cm_length = mpi_reply->Header.PageLength * 4;
1284 cm->cm_sge = &request->PageBufferSGE;
1285 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1286 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1287 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1288 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1289 if (!page) {
1290 printf("%s: page alloc failed\n", __func__);
1291 error = ENOMEM;
1292 goto out;
1293 }
1294 cm->cm_data = page;
1295
1296 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1297 if (cm != NULL)
1298 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1299 if (error || (reply == NULL)) {
1300 /* FIXME */
1301 /*
1302 * If the request returns an error then we need to do a diag
1303 * reset
1304 */
1305 printf("%s: request for page completed with error %d\n",
1306 __func__, error);
1307 error = ENXIO;
1308 goto out;
1309 }
1310 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1311 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1312 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1313 /* FIXME */
1314 /*
1315 * If the request returns an error then we need to do a diag
1316 * reset
1317 */
1318 printf("%s: page read with error; iocstatus = 0x%x\n",
1319 __func__, ioc_status);
1320 error = ENXIO;
1321 goto out;
1322 }
1323 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1324 out:
1325 free(page, M_MPR);
1326 if (cm)
1327 mpr_free_command(sc, cm);
1328 return (error);
1329 }
1330
1331 /**
1332 * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0
1333 * @sc: per adapter object
1334 * @mpi_reply: reply mf payload returned from firmware
1335 * @config_page: contents of the config page
1336 * @page_address: form and handle value used to get page
1337 * Context: sleep.
1338 *
1339 * Returns 0 for success, non-zero for failure.
1340 */
1341 int
mpr_config_get_raid_volume_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage0_t * config_page,u32 page_address)1342 mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
1343 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1344 {
1345 MPI2_CONFIG_REQUEST *request;
1346 MPI2_CONFIG_REPLY *reply = NULL;
1347 struct mpr_command *cm;
1348 Mpi2RaidVolPage0_t *page = NULL;
1349 int error = 0;
1350 u16 ioc_status;
1351
1352 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1353
1354 if ((cm = mpr_alloc_command(sc)) == NULL) {
1355 printf("%s: command alloc failed @ line %d\n", __func__,
1356 __LINE__);
1357 error = EBUSY;
1358 goto out;
1359 }
1360 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1361 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1362 request->Function = MPI2_FUNCTION_CONFIG;
1363 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1364 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1365 request->Header.PageNumber = 0;
1366 request->Header.PageLength = request->Header.PageVersion = 0;
1367 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1368 cm->cm_data = NULL;
1369
1370 /*
1371 * This page must be polled because the IOC isn't ready yet when this
1372 * page is needed.
1373 */
1374 error = mpr_request_polled(sc, &cm);
1375 if (cm != NULL)
1376 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1377 if (error || (reply == NULL)) {
1378 /* FIXME */
1379 /* If the poll returns error then we need to do diag reset */
1380 printf("%s: poll for header completed with error %d\n",
1381 __func__, error);
1382 error = ENXIO;
1383 goto out;
1384 }
1385 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1386 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1387 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1388 /* FIXME */
1389 /* If the poll returns error then we need to do diag reset */
1390 printf("%s: header read with error; iocstatus = 0x%x\n",
1391 __func__, ioc_status);
1392 error = ENXIO;
1393 goto out;
1394 }
1395 /* We have to do free and alloc for the reply-free and reply-post
1396 * counters to match - Need to review the reply FIFO handling.
1397 */
1398 mpr_free_command(sc, cm);
1399
1400 if ((cm = mpr_alloc_command(sc)) == NULL) {
1401 printf("%s: command alloc failed @ line %d\n", __func__,
1402 __LINE__);
1403 error = EBUSY;
1404 goto out;
1405 }
1406 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1407 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1408 request->Function = MPI2_FUNCTION_CONFIG;
1409 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1410 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1411 request->Header.PageNumber = 0;
1412 request->Header.PageLength = mpi_reply->Header.PageLength;
1413 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1414 request->PageAddress = page_address;
1415 cm->cm_length = mpi_reply->Header.PageLength * 4;
1416 cm->cm_sge = &request->PageBufferSGE;
1417 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1418 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1419 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1420 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1421 if (!page) {
1422 printf("%s: page alloc failed\n", __func__);
1423 error = ENOMEM;
1424 goto out;
1425 }
1426 cm->cm_data = page;
1427
1428 /*
1429 * This page must be polled because the IOC isn't ready yet when this
1430 * page is needed.
1431 */
1432 error = mpr_request_polled(sc, &cm);
1433 if (cm != NULL)
1434 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1435 if (error || (reply == NULL)) {
1436 /* FIXME */
1437 /* If the poll returns error then we need to do diag reset */
1438 printf("%s: poll for page completed with error %d\n",
1439 __func__, error);
1440 error = ENXIO;
1441 goto out;
1442 }
1443 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1444 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1445 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1446 /* FIXME */
1447 /* If the poll returns error then we need to do diag reset */
1448 printf("%s: page read with error; iocstatus = 0x%x\n",
1449 __func__, ioc_status);
1450 error = ENXIO;
1451 goto out;
1452 }
1453 bcopy(page, config_page, cm->cm_length);
1454 out:
1455 free(page, M_MPR);
1456 if (cm)
1457 mpr_free_command(sc, cm);
1458 return (error);
1459 }
1460
1461 /**
1462 * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1
1463 * @sc: per adapter object
1464 * @mpi_reply: reply mf payload returned from firmware
1465 * @config_page: contents of the config page
1466 * @form: GET_NEXT_HANDLE or HANDLE
1467 * @handle: volume handle
1468 * Context: sleep.
1469 *
1470 * Returns 0 for success, non-zero for failure.
1471 */
1472 int
mpr_config_get_raid_volume_pg1(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage1_t * config_page,u32 form,u16 handle)1473 mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
1474 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1475 {
1476 MPI2_CONFIG_REQUEST *request;
1477 MPI2_CONFIG_REPLY *reply;
1478 struct mpr_command *cm;
1479 Mpi2RaidVolPage1_t *page = NULL;
1480 int error = 0;
1481 u16 ioc_status;
1482
1483 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1484
1485 if ((cm = mpr_alloc_command(sc)) == NULL) {
1486 printf("%s: command alloc failed @ line %d\n", __func__,
1487 __LINE__);
1488 error = EBUSY;
1489 goto out;
1490 }
1491 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1492 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1493 request->Function = MPI2_FUNCTION_CONFIG;
1494 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1495 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1496 request->Header.PageNumber = 1;
1497 request->Header.PageLength = request->Header.PageVersion = 0;
1498 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1499 cm->cm_data = NULL;
1500 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1501 if (cm != NULL)
1502 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1503 if (error || (reply == NULL)) {
1504 /* FIXME */
1505 /*
1506 * If the request returns an error then we need to do a diag
1507 * reset
1508 */
1509 printf("%s: request for header completed with error %d\n",
1510 __func__, error);
1511 error = ENXIO;
1512 goto out;
1513 }
1514 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1515 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1516 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1517 /* FIXME */
1518 /*
1519 * If the request returns an error then we need to do a diag
1520 * reset
1521 */
1522 printf("%s: header read with error; iocstatus = 0x%x\n",
1523 __func__, ioc_status);
1524 error = ENXIO;
1525 goto out;
1526 }
1527 /* We have to do free and alloc for the reply-free and reply-post
1528 * counters to match - Need to review the reply FIFO handling.
1529 */
1530 mpr_free_command(sc, cm);
1531
1532 if ((cm = mpr_alloc_command(sc)) == NULL) {
1533 printf("%s: command alloc failed @ line %d\n", __func__,
1534 __LINE__);
1535 error = EBUSY;
1536 goto out;
1537 }
1538 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1539 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1540 request->Function = MPI2_FUNCTION_CONFIG;
1541 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1542 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1543 request->Header.PageNumber = 1;
1544 request->Header.PageLength = mpi_reply->Header.PageLength;
1545 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1546 request->PageAddress = htole32(form | handle);
1547 cm->cm_length = mpi_reply->Header.PageLength * 4;
1548 cm->cm_sge = &request->PageBufferSGE;
1549 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1550 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1551 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1552 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1553 if (!page) {
1554 printf("%s: page alloc failed\n", __func__);
1555 error = ENOMEM;
1556 goto out;
1557 }
1558 cm->cm_data = page;
1559
1560 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1561 if (cm != NULL)
1562 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1563 if (error || (reply == NULL)) {
1564 /* FIXME */
1565 /*
1566 * If the request returns an error then we need to do a diag
1567 * reset
1568 */
1569 printf("%s: request for page completed with error %d\n",
1570 __func__, error);
1571 error = ENXIO;
1572 goto out;
1573 }
1574 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1575 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1576 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1577 /* FIXME */
1578 /*
1579 * If the request returns an error then we need to do a diag
1580 * reset
1581 */
1582 printf("%s: page read with error; iocstatus = 0x%x\n",
1583 __func__, ioc_status);
1584 error = ENXIO;
1585 goto out;
1586 }
1587 bcopy(page, config_page, MIN(cm->cm_length,
1588 sizeof(Mpi2RaidVolPage1_t)));
1589 out:
1590 free(page, M_MPR);
1591 if (cm)
1592 mpr_free_command(sc, cm);
1593 return (error);
1594 }
1595
1596 /**
1597 * mpr_config_get_volume_wwid - returns wwid given the volume handle
1598 * @sc: per adapter object
1599 * @volume_handle: volume handle
1600 * @wwid: volume wwid
1601 * Context: sleep.
1602 *
1603 * Returns 0 for success, non-zero for failure.
1604 */
1605 int
mpr_config_get_volume_wwid(struct mpr_softc * sc,u16 volume_handle,u64 * wwid)1606 mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid)
1607 {
1608 Mpi2ConfigReply_t mpi_reply;
1609 Mpi2RaidVolPage1_t raid_vol_pg1;
1610
1611 *wwid = 0;
1612 if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1613 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1614 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1615 raid_vol_pg1.WWID.Low);
1616 return 0;
1617 } else
1618 return -1;
1619 }
1620
1621 /**
1622 * mpr_config_get_pd_pg0 - obtain raid phys disk page 0
1623 * @sc: per adapter object
1624 * @mpi_reply: reply mf payload returned from firmware
1625 * @config_page: contents of the config page
1626 * @page_address: form and handle value used to get page
1627 * Context: sleep.
1628 *
1629 * Returns 0 for success, non-zero for failure.
1630 */
1631 int
mpr_config_get_raid_pd_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidPhysDiskPage0_t * config_page,u32 page_address)1632 mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1633 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1634 {
1635 MPI2_CONFIG_REQUEST *request;
1636 MPI2_CONFIG_REPLY *reply = NULL;
1637 struct mpr_command *cm;
1638 Mpi2RaidPhysDiskPage0_t *page = NULL;
1639 int error = 0;
1640 u16 ioc_status;
1641
1642 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1643
1644 if ((cm = mpr_alloc_command(sc)) == NULL) {
1645 printf("%s: command alloc failed @ line %d\n", __func__,
1646 __LINE__);
1647 error = EBUSY;
1648 goto out;
1649 }
1650 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1651 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1652 request->Function = MPI2_FUNCTION_CONFIG;
1653 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1654 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1655 request->Header.PageNumber = 0;
1656 request->Header.PageLength = request->Header.PageVersion = 0;
1657 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1658 cm->cm_data = NULL;
1659
1660 /*
1661 * This page must be polled because the IOC isn't ready yet when this
1662 * page is needed.
1663 */
1664 error = mpr_request_polled(sc, &cm);
1665 if (cm != NULL)
1666 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1667 if (error || (reply == NULL)) {
1668 /* FIXME */
1669 /* If the poll returns error then we need to do diag reset */
1670 printf("%s: poll for header completed with error %d\n",
1671 __func__, error);
1672 error = ENXIO;
1673 goto out;
1674 }
1675 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1676 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1677 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1678 /* FIXME */
1679 /* If the poll returns error then we need to do diag reset */
1680 printf("%s: header read with error; iocstatus = 0x%x\n",
1681 __func__, ioc_status);
1682 error = ENXIO;
1683 goto out;
1684 }
1685 /* We have to do free and alloc for the reply-free and reply-post
1686 * counters to match - Need to review the reply FIFO handling.
1687 */
1688 mpr_free_command(sc, cm);
1689
1690 if ((cm = mpr_alloc_command(sc)) == NULL) {
1691 printf("%s: command alloc failed @ line %d\n", __func__,
1692 __LINE__);
1693 error = EBUSY;
1694 goto out;
1695 }
1696 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1697 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1698 request->Function = MPI2_FUNCTION_CONFIG;
1699 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1700 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1701 request->Header.PageNumber = 0;
1702 request->Header.PageLength = mpi_reply->Header.PageLength;
1703 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1704 request->PageAddress = page_address;
1705 cm->cm_length = mpi_reply->Header.PageLength * 4;
1706 cm->cm_sge = &request->PageBufferSGE;
1707 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1708 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1709 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1710 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1711 if (!page) {
1712 printf("%s: page alloc failed\n", __func__);
1713 error = ENOMEM;
1714 goto out;
1715 }
1716 cm->cm_data = page;
1717
1718 /*
1719 * This page must be polled because the IOC isn't ready yet when this
1720 * page is needed.
1721 */
1722 error = mpr_request_polled(sc, &cm);
1723 if (cm != NULL)
1724 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1725 if (error || (reply == NULL)) {
1726 /* FIXME */
1727 /* If the poll returns error then we need to do diag reset */
1728 printf("%s: poll for page completed with error %d\n",
1729 __func__, error);
1730 error = ENXIO;
1731 goto out;
1732 }
1733 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1734 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1735 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1736 /* FIXME */
1737 /* If the poll returns error then we need to do diag reset */
1738 printf("%s: page read with error; iocstatus = 0x%x\n",
1739 __func__, ioc_status);
1740 error = ENXIO;
1741 goto out;
1742 }
1743 bcopy(page, config_page, MIN(cm->cm_length,
1744 sizeof(Mpi2RaidPhysDiskPage0_t)));
1745 out:
1746 free(page, M_MPR);
1747 if (cm)
1748 mpr_free_command(sc, cm);
1749 return (error);
1750 }
1751