1 /*-
2 * Copyright (c) 2011-2015 LSI Corp.
3 * Copyright (c) 2013-2015 Avago Technologies
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 /* TODO Move headers to mprvar */
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/lock.h>
37 #include <sys/mutex.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/kthread.h>
42 #include <sys/taskqueue.h>
43 #include <sys/bus.h>
44 #include <sys/endian.h>
45 #include <sys/sysctl.h>
46 #include <sys/eventhandler.h>
47 #include <sys/uio.h>
48 #include <machine/bus.h>
49 #include <machine/resource.h>
50 #include <dev/mpr/mpi/mpi2_type.h>
51 #include <dev/mpr/mpi/mpi2.h>
52 #include <dev/mpr/mpi/mpi2_ioc.h>
53 #include <dev/mpr/mpi/mpi2_sas.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.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
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 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
99 if (error || (reply == NULL)) {
100 /* FIXME */
101 /*
102 * If the request returns an error then we need to do a diag
103 * reset
104 */
105 printf("%s: request for header completed with error %d",
106 __func__, error);
107 error = ENXIO;
108 goto out;
109 }
110 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
111 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
112 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
113 /* FIXME */
114 /*
115 * If the request returns an error then we need to do a diag
116 * reset
117 */
118 printf("%s: header read with error; iocstatus = 0x%x\n",
119 __func__, ioc_status);
120 error = ENXIO;
121 goto out;
122 }
123 /* We have to do free and alloc for the reply-free and reply-post
124 * counters to match - Need to review the reply FIFO handling.
125 */
126 mpr_free_command(sc, cm);
127
128 if ((cm = mpr_alloc_command(sc)) == NULL) {
129 printf("%s: command alloc failed @ line %d\n", __func__,
130 __LINE__);
131 error = EBUSY;
132 goto out;
133 }
134 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
135 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
136 request->Function = MPI2_FUNCTION_CONFIG;
137 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
138 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
139 request->Header.PageNumber = 8;
140 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
141 request->Header.PageLength = mpi_reply->Header.PageLength;
142 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
143 cm->cm_sge = &request->PageBufferSGE;
144 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
145 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
146 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
147 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
148 if (!page) {
149 printf("%s: page alloc failed\n", __func__);
150 error = ENOMEM;
151 goto out;
152 }
153 cm->cm_data = page;
154
155 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
156 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
157 if (error || (reply == NULL)) {
158 /* FIXME */
159 /*
160 * If the request returns an error then we need to do a diag
161 * reset
162 */
163 printf("%s: request for page completed with error %d",
164 __func__, error);
165 error = ENXIO;
166 goto out;
167 }
168 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
169 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
170 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
171 /* FIXME */
172 /*
173 * If the request returns an error then we need to do a diag
174 * reset
175 */
176 printf("%s: page read with error; iocstatus = 0x%x\n",
177 __func__, ioc_status);
178 error = ENXIO;
179 goto out;
180 }
181 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
182
183 out:
184 free(page, M_MPR);
185 if (cm)
186 mpr_free_command(sc, cm);
187 return (error);
188 }
189
190 /**
191 * mpr_config_get_iounit_pg8 - obtain iounit page 8
192 * @sc: per adapter object
193 * @mpi_reply: reply mf payload returned from firmware
194 * @config_page: contents of the config page
195 * Context: sleep.
196 *
197 * Returns 0 for success, non-zero for failure.
198 */
199 int
mpr_config_get_iounit_pg8(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2IOUnitPage8_t * config_page)200 mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
201 Mpi2IOUnitPage8_t *config_page)
202 {
203 MPI2_CONFIG_REQUEST *request;
204 MPI2_CONFIG_REPLY *reply;
205 struct mpr_command *cm;
206 MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL;
207 int error = 0;
208 u16 ioc_status;
209
210 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
211
212 if ((cm = mpr_alloc_command(sc)) == NULL) {
213 printf("%s: command alloc failed @ line %d\n", __func__,
214 __LINE__);
215 error = EBUSY;
216 goto out;
217 }
218 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
219 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
220 request->Function = MPI2_FUNCTION_CONFIG;
221 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
222 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
223 request->Header.PageNumber = 8;
224 request->Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
225 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
226 cm->cm_data = NULL;
227 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
228 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
229 if (error || (reply == NULL)) {
230 /* FIXME */
231 /*
232 * If the request returns an error then we need to do a diag
233 * reset
234 */
235 printf("%s: request for header completed with error %d",
236 __func__, error);
237 error = ENXIO;
238 goto out;
239 }
240 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
241 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
242 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
243 /* FIXME */
244 /*
245 * If the request returns an error then we need to do a diag
246 * reset
247 */
248 printf("%s: header read with error; iocstatus = 0x%x\n",
249 __func__, ioc_status);
250 error = ENXIO;
251 goto out;
252 }
253 /* We have to do free and alloc for the reply-free and reply-post
254 * counters to match - Need to review the reply FIFO handling.
255 */
256 mpr_free_command(sc, cm);
257
258 if ((cm = mpr_alloc_command(sc)) == NULL) {
259 printf("%s: command alloc failed @ line %d\n", __func__,
260 __LINE__);
261 error = EBUSY;
262 goto out;
263 }
264 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
265 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
266 request->Function = MPI2_FUNCTION_CONFIG;
267 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
268 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
269 request->Header.PageNumber = 8;
270 request->Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
271 request->Header.PageLength = mpi_reply->Header.PageLength;
272 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
273 cm->cm_sge = &request->PageBufferSGE;
274 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
275 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
276 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
277 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
278 if (!page) {
279 printf("%s: page alloc failed\n", __func__);
280 error = ENOMEM;
281 goto out;
282 }
283 cm->cm_data = page;
284
285 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
286 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
287 if (error || (reply == NULL)) {
288 /* FIXME */
289 /*
290 * If the request returns an error then we need to do a diag
291 * reset
292 */
293 printf("%s: request for page completed with error %d",
294 __func__, error);
295 error = ENXIO;
296 goto out;
297 }
298 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
299 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
300 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
301 /* FIXME */
302 /*
303 * If the request returns an error then we need to do a diag
304 * reset
305 */
306 printf("%s: page read with error; iocstatus = 0x%x\n",
307 __func__, ioc_status);
308 error = ENXIO;
309 goto out;
310 }
311 bcopy(page, config_page, MIN(cm->cm_length,
312 (sizeof(Mpi2IOUnitPage8_t))));
313
314 out:
315 free(page, M_MPR);
316 if (cm)
317 mpr_free_command(sc, cm);
318 return (error);
319 }
320
321 /**
322 * mpr_base_static_config_pages - static start of day config pages.
323 * @sc: per adapter object
324 *
325 * Return nothing.
326 */
327 void
mpr_base_static_config_pages(struct mpr_softc * sc)328 mpr_base_static_config_pages(struct mpr_softc *sc)
329 {
330 Mpi2ConfigReply_t mpi_reply;
331 int retry;
332
333 retry = 0;
334 while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
335 retry++;
336 if (retry > 5) {
337 /* We need to Handle this situation */
338 /*FIXME*/
339 break;
340 }
341 }
342 retry = 0;
343 while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) {
344 retry++;
345 if (retry > 5) {
346 /* We need to Handle this situation */
347 /*FIXME*/
348 break;
349 }
350 }
351 }
352
353 /**
354 * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0
355 * @sc: per adapter object
356 * @mpi_reply: reply mf payload returned from firmware
357 * @config_page: contents of the config page
358 * @sz: size of buffer passed in config_page
359 * Context: sleep.
360 *
361 * Returns 0 for success, non-zero for failure.
362 */
363 int
mpr_config_get_dpm_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 sz)364 mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
365 Mpi2DriverMappingPage0_t *config_page, u16 sz)
366 {
367 MPI2_CONFIG_REQUEST *request;
368 MPI2_CONFIG_REPLY *reply;
369 struct mpr_command *cm;
370 Mpi2DriverMappingPage0_t *page = NULL;
371 int error = 0;
372 u16 ioc_status;
373
374 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
375
376 memset(config_page, 0, sz);
377 if ((cm = mpr_alloc_command(sc)) == NULL) {
378 printf("%s: command alloc failed @ line %d\n", __func__,
379 __LINE__);
380 error = EBUSY;
381 goto out;
382 }
383 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
384 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
385 request->Function = MPI2_FUNCTION_CONFIG;
386 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
387 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
388 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
389 request->Header.PageNumber = 0;
390 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
391 request->PageAddress = sc->max_dpm_entries <<
392 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
393 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
394 cm->cm_data = NULL;
395 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
396 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
397 if (error || (reply == NULL)) {
398 /* FIXME */
399 /*
400 * If the request returns an error then we need to do a diag
401 * reset
402 */
403 printf("%s: request for header completed with error %d",
404 __func__, error);
405 error = ENXIO;
406 goto out;
407 }
408 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
409 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
410 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
411 /* FIXME */
412 /*
413 * If the request returns an error then we need to do a diag
414 * reset
415 */
416 printf("%s: header read with error; iocstatus = 0x%x\n",
417 __func__, ioc_status);
418 error = ENXIO;
419 goto out;
420 }
421 /* We have to do free and alloc for the reply-free and reply-post
422 * counters to match - Need to review the reply FIFO handling.
423 */
424 mpr_free_command(sc, cm);
425
426 if ((cm = mpr_alloc_command(sc)) == NULL) {
427 printf("%s: command alloc failed @ line %d\n", __func__,
428 __LINE__);
429 error = EBUSY;
430 goto out;
431 }
432 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
433 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
434 request->Function = MPI2_FUNCTION_CONFIG;
435 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
436 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
437 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
438 request->Header.PageNumber = 0;
439 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
440 request->PageAddress = sc->max_dpm_entries <<
441 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
442 request->ExtPageLength = mpi_reply->ExtPageLength;
443 cm->cm_length = le16toh(request->ExtPageLength) * 4;
444 cm->cm_sge = &request->PageBufferSGE;
445 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
446 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
447 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
448 page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT);
449 if (!page) {
450 printf("%s: page alloc failed\n", __func__);
451 error = ENOMEM;
452 goto out;
453 }
454 cm->cm_data = page;
455 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
456 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
457 if (error || (reply == NULL)) {
458 /* FIXME */
459 /*
460 * If the request returns an error then we need to do a diag
461 * reset
462 */
463 printf("%s: request for page completed with error %d",
464 __func__, error);
465 error = ENXIO;
466 goto out;
467 }
468 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
469 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
470 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
471 /* FIXME */
472 /*
473 * If the request returns an error then we need to do a diag
474 * reset
475 */
476 printf("%s: page read with error; iocstatus = 0x%x\n",
477 __func__, ioc_status);
478 error = ENXIO;
479 goto out;
480 }
481 bcopy(page, config_page, MIN(cm->cm_length, sz));
482 out:
483 free(page, M_MPR);
484 if (cm)
485 mpr_free_command(sc, cm);
486 return (error);
487 }
488
489 /**
490 * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
491 * @sc: per adapter object
492 * @mpi_reply: reply mf payload returned from firmware
493 * @config_page: contents of the config page
494 * @entry_idx: entry index in DPM Page0 to be modified
495 * Context: sleep.
496 *
497 * Returns 0 for success, non-zero for failure.
498 */
499
mpr_config_set_dpm_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 entry_idx)500 int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
501 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
502 {
503 MPI2_CONFIG_REQUEST *request;
504 MPI2_CONFIG_REPLY *reply;
505 struct mpr_command *cm;
506 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
507 int error = 0;
508 u16 ioc_status;
509
510 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
511
512 if ((cm = mpr_alloc_command(sc)) == NULL) {
513 printf("%s: command alloc failed @ line %d\n", __func__,
514 __LINE__);
515 error = EBUSY;
516 goto out;
517 }
518 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
519 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
520 request->Function = MPI2_FUNCTION_CONFIG;
521 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
522 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
523 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
524 request->Header.PageNumber = 0;
525 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
526 /* We can remove below two lines ????*/
527 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
528 request->PageAddress |= htole16(entry_idx);
529 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
530 cm->cm_data = NULL;
531 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
532 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
533 if (error || (reply == NULL)) {
534 /* FIXME */
535 /*
536 * If the request returns an error then we need to do a diag
537 * reset
538 */
539 printf("%s: request for header completed with error %d",
540 __func__, error);
541 error = ENXIO;
542 goto out;
543 }
544 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
545 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
546 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
547 /* FIXME */
548 /*
549 * If the request returns an error then we need to do a diag
550 * reset
551 */
552 printf("%s: header read with error; iocstatus = 0x%x\n",
553 __func__, ioc_status);
554 error = ENXIO;
555 goto out;
556 }
557 /* We have to do free and alloc for the reply-free and reply-post
558 * counters to match - Need to review the reply FIFO handling.
559 */
560 mpr_free_command(sc, cm);
561
562 if ((cm = mpr_alloc_command(sc)) == NULL) {
563 printf("%s: command alloc failed @ line %d\n", __func__,
564 __LINE__);
565 error = EBUSY;
566 goto out;
567 }
568 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
569 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
570 request->Function = MPI2_FUNCTION_CONFIG;
571 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
572 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
573 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
574 request->Header.PageNumber = 0;
575 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
576 request->ExtPageLength = mpi_reply->ExtPageLength;
577 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
578 request->PageAddress |= htole16(entry_idx);
579 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
580 cm->cm_sge = &request->PageBufferSGE;
581 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
582 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT;
583 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
584 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
585 if (!page) {
586 printf("%s: page alloc failed\n", __func__);
587 error = ENOMEM;
588 goto out;
589 }
590 bcopy(config_page, page, MIN(cm->cm_length,
591 (sizeof(Mpi2DriverMappingPage0_t))));
592 cm->cm_data = page;
593 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
594 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
595 if (error || (reply == NULL)) {
596 /* FIXME */
597 /*
598 * If the request returns an error then we need to do a diag
599 * reset
600 */
601 printf("%s: request to write page completed with error %d",
602 __func__, error);
603 error = ENXIO;
604 goto out;
605 }
606 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
607 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
608 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
609 /* FIXME */
610 /*
611 * If the request returns an error then we need to do a diag
612 * reset
613 */
614 printf("%s: page written with error; iocstatus = 0x%x\n",
615 __func__, ioc_status);
616 error = ENXIO;
617 goto out;
618 }
619 out:
620 free(page, M_MPR);
621 if (cm)
622 mpr_free_command(sc, cm);
623 return (error);
624 }
625
626 /**
627 * mpr_config_get_sas_device_pg0 - obtain sas device page 0
628 * @sc: per adapter object
629 * @mpi_reply: reply mf payload returned from firmware
630 * @config_page: contents of the config page
631 * @form: GET_NEXT_HANDLE or HANDLE
632 * @handle: device handle
633 * Context: sleep.
634 *
635 * Returns 0 for success, non-zero for failure.
636 */
637 int
mpr_config_get_sas_device_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2SasDevicePage0_t * config_page,u32 form,u16 handle)638 mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
639 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
640 {
641 MPI2_CONFIG_REQUEST *request;
642 MPI2_CONFIG_REPLY *reply;
643 struct mpr_command *cm;
644 Mpi2SasDevicePage0_t *page = NULL;
645 int error = 0;
646 u16 ioc_status;
647
648 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
649
650 if ((cm = mpr_alloc_command(sc)) == NULL) {
651 printf("%s: command alloc failed @ line %d\n", __func__,
652 __LINE__);
653 error = EBUSY;
654 goto out;
655 }
656 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
657 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
658 request->Function = MPI2_FUNCTION_CONFIG;
659 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
660 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
661 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
662 request->Header.PageNumber = 0;
663 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
664 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
665 cm->cm_data = NULL;
666 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
667 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
668 if (error || (reply == NULL)) {
669 /* FIXME */
670 /*
671 * If the request returns an error then we need to do a diag
672 * reset
673 */
674 printf("%s: request for header completed with error %d",
675 __func__, error);
676 error = ENXIO;
677 goto out;
678 }
679 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
680 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
681 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
682 /* FIXME */
683 /*
684 * If the request returns an error then we need to do a diag
685 * reset
686 */
687 printf("%s: header read with error; iocstatus = 0x%x\n",
688 __func__, ioc_status);
689 error = ENXIO;
690 goto out;
691 }
692 /* We have to do free and alloc for the reply-free and reply-post
693 * counters to match - Need to review the reply FIFO handling.
694 */
695 mpr_free_command(sc, cm);
696
697 if ((cm = mpr_alloc_command(sc)) == NULL) {
698 printf("%s: command alloc failed @ line %d\n", __func__,
699 __LINE__);
700 error = EBUSY;
701 goto out;
702 }
703 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
704 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
705 request->Function = MPI2_FUNCTION_CONFIG;
706 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
707 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
708 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
709 request->Header.PageNumber = 0;
710 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
711 request->ExtPageLength = mpi_reply->ExtPageLength;
712 request->PageAddress = htole32(form | handle);
713 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
714 cm->cm_sge = &request->PageBufferSGE;
715 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
716 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
717 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
718 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
719 if (!page) {
720 printf("%s: page alloc failed\n", __func__);
721 error = ENOMEM;
722 goto out;
723 }
724 cm->cm_data = page;
725
726 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
727 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
728 if (error || (reply == NULL)) {
729 /* FIXME */
730 /*
731 * If the request returns an error then we need to do a diag
732 * reset
733 */
734 printf("%s: request for page completed with error %d",
735 __func__, error);
736 error = ENXIO;
737 goto out;
738 }
739 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
740 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
741 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
742 /* FIXME */
743 /*
744 * If the request returns an error then we need to do a diag
745 * reset
746 */
747 printf("%s: page read with error; iocstatus = 0x%x\n",
748 __func__, ioc_status);
749 error = ENXIO;
750 goto out;
751 }
752 bcopy(page, config_page, MIN(cm->cm_length,
753 sizeof(Mpi2SasDevicePage0_t)));
754 out:
755 free(page, M_MPR);
756 if (cm)
757 mpr_free_command(sc, cm);
758 return (error);
759 }
760
761 /**
762 * mpr_config_get_bios_pg3 - obtain BIOS page 3
763 * @sc: per adapter object
764 * @mpi_reply: reply mf payload returned from firmware
765 * @config_page: contents of the config page
766 * Context: sleep.
767 *
768 * Returns 0 for success, non-zero for failure.
769 */
770 int
mpr_config_get_bios_pg3(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2BiosPage3_t * config_page)771 mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
772 Mpi2BiosPage3_t *config_page)
773 {
774 MPI2_CONFIG_REQUEST *request;
775 MPI2_CONFIG_REPLY *reply;
776 struct mpr_command *cm;
777 Mpi2BiosPage3_t *page = NULL;
778 int error = 0;
779 u16 ioc_status;
780
781 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
782
783 if ((cm = mpr_alloc_command(sc)) == NULL) {
784 printf("%s: command alloc failed @ line %d\n", __func__,
785 __LINE__);
786 error = EBUSY;
787 goto out;
788 }
789 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
790 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
791 request->Function = MPI2_FUNCTION_CONFIG;
792 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
793 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
794 request->Header.PageNumber = 3;
795 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
796 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
797 cm->cm_data = NULL;
798 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
799 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
800 if (error || (reply == NULL)) {
801 /* FIXME */
802 /*
803 * If the request returns an error then we need to do a diag
804 * reset
805 */
806 printf("%s: request for header completed with error %d",
807 __func__, error);
808 error = ENXIO;
809 goto out;
810 }
811 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
812 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
813 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
814 /* FIXME */
815 /*
816 * If the request returns an error then we need to do a diag
817 * reset
818 */
819 printf("%s: header read with error; iocstatus = 0x%x\n",
820 __func__, ioc_status);
821 error = ENXIO;
822 goto out;
823 }
824 /* We have to do free and alloc for the reply-free and reply-post
825 * counters to match - Need to review the reply FIFO handling.
826 */
827 mpr_free_command(sc, cm);
828
829 if ((cm = mpr_alloc_command(sc)) == NULL) {
830 printf("%s: command alloc failed @ line %d\n", __func__,
831 __LINE__);
832 error = EBUSY;
833 goto out;
834 }
835 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
836 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
837 request->Function = MPI2_FUNCTION_CONFIG;
838 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
839 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
840 request->Header.PageNumber = 3;
841 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
842 request->Header.PageLength = mpi_reply->Header.PageLength;
843 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
844 cm->cm_sge = &request->PageBufferSGE;
845 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
846 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
847 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
848 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
849 if (!page) {
850 printf("%s: page alloc failed\n", __func__);
851 error = ENOMEM;
852 goto out;
853 }
854 cm->cm_data = page;
855
856 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
857 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
858 if (error || (reply == NULL)) {
859 /* FIXME */
860 /*
861 * If the request returns an error then we need to do a diag
862 * reset
863 */
864 printf("%s: request for page completed with error %d",
865 __func__, error);
866 error = ENXIO;
867 goto out;
868 }
869 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
870 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
871 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
872 /* FIXME */
873 /*
874 * If the request returns an error then we need to do a diag
875 * reset
876 */
877 printf("%s: page read with error; iocstatus = 0x%x\n",
878 __func__, ioc_status);
879 error = ENXIO;
880 goto out;
881 }
882 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
883 out:
884 free(page, M_MPR);
885 if (cm)
886 mpr_free_command(sc, cm);
887 return (error);
888 }
889
890 /**
891 * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0
892 * @sc: per adapter object
893 * @mpi_reply: reply mf payload returned from firmware
894 * @config_page: contents of the config page
895 * @page_address: form and handle value used to get page
896 * Context: sleep.
897 *
898 * Returns 0 for success, non-zero for failure.
899 */
900 int
mpr_config_get_raid_volume_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage0_t * config_page,u32 page_address)901 mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
902 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
903 {
904 MPI2_CONFIG_REQUEST *request;
905 MPI2_CONFIG_REPLY *reply;
906 struct mpr_command *cm;
907 Mpi2RaidVolPage0_t *page = NULL;
908 int error = 0;
909 u16 ioc_status;
910
911 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
912
913 if ((cm = mpr_alloc_command(sc)) == NULL) {
914 printf("%s: command alloc failed @ line %d\n", __func__,
915 __LINE__);
916 error = EBUSY;
917 goto out;
918 }
919 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
920 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
921 request->Function = MPI2_FUNCTION_CONFIG;
922 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
923 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
924 request->Header.PageNumber = 0;
925 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
926 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
927 cm->cm_data = NULL;
928
929 /*
930 * This page must be polled because the IOC isn't ready yet when this
931 * page is needed.
932 */
933 error = mpr_request_polled(sc, cm);
934 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
935 if (error || (reply == NULL)) {
936 /* FIXME */
937 /* If the poll returns error then we need to do diag reset */
938 printf("%s: poll for header completed with error %d",
939 __func__, error);
940 error = ENXIO;
941 goto out;
942 }
943 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
944 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
945 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
946 /* FIXME */
947 /* If the poll returns error then we need to do diag reset */
948 printf("%s: header read with error; iocstatus = 0x%x\n",
949 __func__, ioc_status);
950 error = ENXIO;
951 goto out;
952 }
953 /* We have to do free and alloc for the reply-free and reply-post
954 * counters to match - Need to review the reply FIFO handling.
955 */
956 mpr_free_command(sc, cm);
957
958 if ((cm = mpr_alloc_command(sc)) == NULL) {
959 printf("%s: command alloc failed @ line %d\n", __func__,
960 __LINE__);
961 error = EBUSY;
962 goto out;
963 }
964 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
965 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
966 request->Function = MPI2_FUNCTION_CONFIG;
967 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
968 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
969 request->Header.PageNumber = 0;
970 request->Header.PageLength = mpi_reply->Header.PageLength;
971 request->Header.PageVersion = mpi_reply->Header.PageVersion;
972 request->PageAddress = page_address;
973 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
974 cm->cm_sge = &request->PageBufferSGE;
975 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
976 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
977 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
978 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
979 if (!page) {
980 printf("%s: page alloc failed\n", __func__);
981 error = ENOMEM;
982 goto out;
983 }
984 cm->cm_data = page;
985
986 /*
987 * This page must be polled because the IOC isn't ready yet when this
988 * page is needed.
989 */
990 error = mpr_request_polled(sc, cm);
991 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
992 if (error || (reply == NULL)) {
993 /* FIXME */
994 /* If the poll returns error then we need to do diag reset */
995 printf("%s: poll for page completed with error %d",
996 __func__, error);
997 error = ENXIO;
998 goto out;
999 }
1000 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1001 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1002 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1003 /* FIXME */
1004 /* If the poll returns error then we need to do diag reset */
1005 printf("%s: page read with error; iocstatus = 0x%x\n",
1006 __func__, ioc_status);
1007 error = ENXIO;
1008 goto out;
1009 }
1010 bcopy(page, config_page, cm->cm_length);
1011 out:
1012 free(page, M_MPR);
1013 if (cm)
1014 mpr_free_command(sc, cm);
1015 return (error);
1016 }
1017
1018 /**
1019 * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1
1020 * @sc: per adapter object
1021 * @mpi_reply: reply mf payload returned from firmware
1022 * @config_page: contents of the config page
1023 * @form: GET_NEXT_HANDLE or HANDLE
1024 * @handle: volume handle
1025 * Context: sleep.
1026 *
1027 * Returns 0 for success, non-zero for failure.
1028 */
1029 int
mpr_config_get_raid_volume_pg1(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage1_t * config_page,u32 form,u16 handle)1030 mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
1031 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1032 {
1033 MPI2_CONFIG_REQUEST *request;
1034 MPI2_CONFIG_REPLY *reply;
1035 struct mpr_command *cm;
1036 Mpi2RaidVolPage1_t *page = NULL;
1037 int error = 0;
1038 u16 ioc_status;
1039
1040 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1041
1042 if ((cm = mpr_alloc_command(sc)) == NULL) {
1043 printf("%s: command alloc failed @ line %d\n", __func__,
1044 __LINE__);
1045 error = EBUSY;
1046 goto out;
1047 }
1048 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1049 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1050 request->Function = MPI2_FUNCTION_CONFIG;
1051 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1052 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1053 request->Header.PageNumber = 1;
1054 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1055 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1056 cm->cm_data = NULL;
1057 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
1058 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1059 if (error || (reply == NULL)) {
1060 /* FIXME */
1061 /*
1062 * If the request returns an error then we need to do a diag
1063 * reset
1064 */
1065 printf("%s: request for header completed with error %d",
1066 __func__, error);
1067 error = ENXIO;
1068 goto out;
1069 }
1070 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1071 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1072 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1073 /* FIXME */
1074 /*
1075 * If the request returns an error then we need to do a diag
1076 * reset
1077 */
1078 printf("%s: header read with error; iocstatus = 0x%x\n",
1079 __func__, ioc_status);
1080 error = ENXIO;
1081 goto out;
1082 }
1083 /* We have to do free and alloc for the reply-free and reply-post
1084 * counters to match - Need to review the reply FIFO handling.
1085 */
1086 mpr_free_command(sc, cm);
1087
1088 if ((cm = mpr_alloc_command(sc)) == NULL) {
1089 printf("%s: command alloc failed @ line %d\n", __func__,
1090 __LINE__);
1091 error = EBUSY;
1092 goto out;
1093 }
1094 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1095 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1096 request->Function = MPI2_FUNCTION_CONFIG;
1097 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1098 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1099 request->Header.PageNumber = 1;
1100 request->Header.PageLength = mpi_reply->Header.PageLength;
1101 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1102 request->PageAddress = htole32(form | handle);
1103 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1104 cm->cm_sge = &request->PageBufferSGE;
1105 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1106 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1107 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1108 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1109 if (!page) {
1110 printf("%s: page alloc failed\n", __func__);
1111 error = ENOMEM;
1112 goto out;
1113 }
1114 cm->cm_data = page;
1115
1116 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
1117 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1118 if (error || (reply == NULL)) {
1119 /* FIXME */
1120 /*
1121 * If the request returns an error then we need to do a diag
1122 * reset
1123 */
1124 printf("%s: request for page completed with error %d",
1125 __func__, error);
1126 error = ENXIO;
1127 goto out;
1128 }
1129 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1130 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1131 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1132 /* FIXME */
1133 /*
1134 * If the request returns an error then we need to do a diag
1135 * reset
1136 */
1137 printf("%s: page read with error; iocstatus = 0x%x\n",
1138 __func__, ioc_status);
1139 error = ENXIO;
1140 goto out;
1141 }
1142 bcopy(page, config_page, MIN(cm->cm_length,
1143 sizeof(Mpi2RaidVolPage1_t)));
1144 out:
1145 free(page, M_MPR);
1146 if (cm)
1147 mpr_free_command(sc, cm);
1148 return (error);
1149 }
1150
1151 /**
1152 * mpr_config_get_volume_wwid - returns wwid given the volume handle
1153 * @sc: per adapter object
1154 * @volume_handle: volume handle
1155 * @wwid: volume wwid
1156 * Context: sleep.
1157 *
1158 * Returns 0 for success, non-zero for failure.
1159 */
1160 int
mpr_config_get_volume_wwid(struct mpr_softc * sc,u16 volume_handle,u64 * wwid)1161 mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid)
1162 {
1163 Mpi2ConfigReply_t mpi_reply;
1164 Mpi2RaidVolPage1_t raid_vol_pg1;
1165
1166 *wwid = 0;
1167 if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1168 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1169 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1170 raid_vol_pg1.WWID.Low);
1171 return 0;
1172 } else
1173 return -1;
1174 }
1175
1176 /**
1177 * mpr_config_get_pd_pg0 - obtain raid phys disk page 0
1178 * @sc: per adapter object
1179 * @mpi_reply: reply mf payload returned from firmware
1180 * @config_page: contents of the config page
1181 * @page_address: form and handle value used to get page
1182 * Context: sleep.
1183 *
1184 * Returns 0 for success, non-zero for failure.
1185 */
1186 int
mpr_config_get_raid_pd_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidPhysDiskPage0_t * config_page,u32 page_address)1187 mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1188 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1189 {
1190 MPI2_CONFIG_REQUEST *request;
1191 MPI2_CONFIG_REPLY *reply;
1192 struct mpr_command *cm;
1193 Mpi2RaidPhysDiskPage0_t *page = NULL;
1194 int error = 0;
1195 u16 ioc_status;
1196
1197 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1198
1199 if ((cm = mpr_alloc_command(sc)) == NULL) {
1200 printf("%s: command alloc failed @ line %d\n", __func__,
1201 __LINE__);
1202 error = EBUSY;
1203 goto out;
1204 }
1205 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1206 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1207 request->Function = MPI2_FUNCTION_CONFIG;
1208 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1209 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1210 request->Header.PageNumber = 0;
1211 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1212 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1213 cm->cm_data = NULL;
1214
1215 /*
1216 * This page must be polled because the IOC isn't ready yet when this
1217 * page is needed.
1218 */
1219 error = mpr_request_polled(sc, cm);
1220 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1221 if (error || (reply == NULL)) {
1222 /* FIXME */
1223 /* If the poll returns error then we need to do diag reset */
1224 printf("%s: poll for header completed with error %d",
1225 __func__, error);
1226 error = ENXIO;
1227 goto out;
1228 }
1229 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1230 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1231 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1232 /* FIXME */
1233 /* If the poll returns error then we need to do diag reset */
1234 printf("%s: header read with error; iocstatus = 0x%x\n",
1235 __func__, ioc_status);
1236 error = ENXIO;
1237 goto out;
1238 }
1239 /* We have to do free and alloc for the reply-free and reply-post
1240 * counters to match - Need to review the reply FIFO handling.
1241 */
1242 mpr_free_command(sc, cm);
1243
1244 if ((cm = mpr_alloc_command(sc)) == NULL) {
1245 printf("%s: command alloc failed @ line %d\n", __func__,
1246 __LINE__);
1247 error = EBUSY;
1248 goto out;
1249 }
1250 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1251 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1252 request->Function = MPI2_FUNCTION_CONFIG;
1253 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1254 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1255 request->Header.PageNumber = 0;
1256 request->Header.PageLength = mpi_reply->Header.PageLength;
1257 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1258 request->PageAddress = page_address;
1259 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1260 cm->cm_sge = &request->PageBufferSGE;
1261 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1262 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1263 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1264 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1265 if (!page) {
1266 printf("%s: page alloc failed\n", __func__);
1267 error = ENOMEM;
1268 goto out;
1269 }
1270 cm->cm_data = page;
1271
1272 /*
1273 * This page must be polled because the IOC isn't ready yet when this
1274 * page is needed.
1275 */
1276 error = mpr_request_polled(sc, cm);
1277 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1278 if (error || (reply == NULL)) {
1279 /* FIXME */
1280 /* If the poll returns error then we need to do diag reset */
1281 printf("%s: poll for page completed with error %d",
1282 __func__, error);
1283 error = ENXIO;
1284 goto out;
1285 }
1286 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1287 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1288 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1289 /* FIXME */
1290 /* If the poll returns error then we need to do diag reset */
1291 printf("%s: page read with error; iocstatus = 0x%x\n",
1292 __func__, ioc_status);
1293 error = ENXIO;
1294 goto out;
1295 }
1296 bcopy(page, config_page, MIN(cm->cm_length,
1297 sizeof(Mpi2RaidPhysDiskPage0_t)));
1298 out:
1299 free(page, M_MPR);
1300 if (cm)
1301 mpr_free_command(sc, cm);
1302 return (error);
1303 }
1304