1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2011-2015 LSI Corp.
5 * Copyright (c) 2013-2015 Avago Technologies
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
30 */
31
32 #include <sys/cdefs.h>
33 /* TODO Move headers to mpsvar */
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/mps/mpi/mpi2_type.h>
51 #include <dev/mps/mpi/mpi2.h>
52 #include <dev/mps/mpi/mpi2_ioc.h>
53 #include <dev/mps/mpi/mpi2_sas.h>
54 #include <dev/mps/mpi/mpi2_cnfg.h>
55 #include <dev/mps/mpi/mpi2_init.h>
56 #include <dev/mps/mpi/mpi2_tool.h>
57 #include <dev/mps/mps_ioctl.h>
58 #include <dev/mps/mpsvar.h>
59
60 /**
61 * mps_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
mps_config_get_ioc_pg8(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2IOCPage8_t * config_page)70 mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
71 Mpi2IOCPage8_t *config_page)
72 {
73 MPI2_CONFIG_REQUEST *request;
74 MPI2_CONFIG_REPLY *reply = NULL;
75 struct mps_command *cm;
76 MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
77 int error = 0;
78 u16 ioc_status;
79
80 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
81
82 if ((cm = mps_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 = mps_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 mps_free_command(sc, cm);
128
129 if ((cm = mps_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 = MPI2_IOCPAGE8_PAGEVERSION;
142 request->Header.PageLength = mpi_reply->Header.PageLength;
143 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
144 cm->cm_sge = &request->PageBufferSGE;
145 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
146 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
147 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
148 page = malloc((cm->cm_length), M_MPT2, 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 = mps_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_MPT2);
187 if (cm)
188 mps_free_command(sc, cm);
189 return (error);
190 }
191
192 /**
193 * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
194 * accordingly. Currently, this page does not need to return to caller.
195 * @sc: per adapter object
196 * @mpi_reply: reply mf payload returned from firmware
197 * Context: sleep.
198 *
199 * Returns 0 for success, non-zero for failure.
200 */
201 int
mps_config_get_man_pg10(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply)202 mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
203 {
204 MPI2_CONFIG_REQUEST *request;
205 MPI2_CONFIG_REPLY *reply = NULL;
206 struct mps_command *cm;
207 pMpi2ManufacturingPagePS_t page = NULL;
208 uint32_t *pPS_info;
209 uint8_t OEM_Value = 0;
210 int error = 0;
211 u16 ioc_status;
212
213 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
214
215 if ((cm = mps_alloc_command(sc)) == NULL) {
216 printf("%s: command alloc failed @ line %d\n", __func__,
217 __LINE__);
218 error = EBUSY;
219 goto out;
220 }
221 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
222 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
223 request->Function = MPI2_FUNCTION_CONFIG;
224 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
225 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
226 request->Header.PageNumber = 10;
227 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
228 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
229 cm->cm_data = NULL;
230
231 /*
232 * This page must be polled because the IOC isn't ready yet when this
233 * page is needed.
234 */
235 error = mps_wait_command(sc, &cm, 60, 0);
236 if (cm != NULL)
237 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
238 if (error || (reply == NULL)) {
239 /* FIXME */
240 /* If the poll returns error then we need to do diag reset */
241 printf("%s: poll for header completed with error %d\n",
242 __func__, error);
243 error = ENXIO;
244 goto out;
245 }
246 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
247 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
248 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
249 /* FIXME */
250 /* If the poll returns error then we need to do diag reset */
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 mps_free_command(sc, cm);
260
261 if ((cm = mps_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_MANUFACTURING;
272 request->Header.PageNumber = 10;
273 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
274 request->Header.PageLength = mpi_reply->Header.PageLength;
275 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
276 cm->cm_sge = &request->PageBufferSGE;
277 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
278 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
279 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
280 page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, 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 /*
289 * This page must be polled because the IOC isn't ready yet when this
290 * page is needed.
291 */
292 error = mps_wait_command(sc, &cm, 60, 0);
293 if (cm != NULL)
294 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
295 if (error || (reply == NULL)) {
296 /* FIXME */
297 /* If the poll returns error then we need to do diag reset */
298 printf("%s: poll for page completed with error %d\n",
299 __func__, error);
300 error = ENXIO;
301 goto out;
302 }
303 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
304 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
305 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
306 /* FIXME */
307 /* If the poll returns error then we need to do diag reset */
308 printf("%s: page read with error; iocstatus = 0x%x\n",
309 __func__, ioc_status);
310 error = ENXIO;
311 goto out;
312 }
313
314 /*
315 * If OEM ID is unknown, fail the request.
316 */
317 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
318 OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
319 if (OEM_Value != MPS_WD_LSI_OEM) {
320 mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
321 "(0x%x)\n", OEM_Value);
322 error = ENXIO;
323 goto out;
324 }
325
326 /*
327 * Set the phys disks hide/expose value.
328 */
329 pPS_info = &page->ProductSpecificInfo;
330 sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
331 sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
332 if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
333 (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
334 (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
335 mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
336 "hide/expose: 0x%x\n", sc->WD_hide_expose);
337 error = ENXIO;
338 goto out;
339 }
340
341 out:
342 free(page, M_MPT2);
343 if (cm)
344 mps_free_command(sc, cm);
345 return (error);
346 }
347
348 /**
349 * mps_base_static_config_pages - static start of day config pages.
350 * @sc: per adapter object
351 *
352 * Return nothing.
353 */
354 void
mps_base_static_config_pages(struct mps_softc * sc)355 mps_base_static_config_pages(struct mps_softc *sc)
356 {
357 Mpi2ConfigReply_t mpi_reply;
358 int retry;
359
360 retry = 0;
361 while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
362 retry++;
363 if (retry > 5) {
364 /* We need to Handle this situation */
365 /*FIXME*/
366 break;
367 }
368 }
369 }
370
371 /**
372 * mps_wd_config_pages - get info required to support WarpDrive. This needs to
373 * be called after discovery is complete to guarantee that IR info is there.
374 * @sc: per adapter object
375 *
376 * Return nothing.
377 */
378 void
mps_wd_config_pages(struct mps_softc * sc)379 mps_wd_config_pages(struct mps_softc *sc)
380 {
381 Mpi2ConfigReply_t mpi_reply;
382 pMpi2RaidVolPage0_t raid_vol_pg0 = NULL;
383 Mpi2RaidPhysDiskPage0_t phys_disk_pg0;
384 pMpi2RaidVol0PhysDisk_t pRVPD;
385 uint32_t stripe_size, phys_disk_page_address;
386 uint16_t block_size;
387 uint8_t index, stripe_exp = 0, block_exp = 0;
388
389 /*
390 * Get the WD settings from manufacturing page 10 if using a WD HBA.
391 * This will be used to determine if phys disks should always be
392 * hidden, hidden only if part of a WD volume, or never hidden. Also,
393 * get the WD RAID Volume info and fail if volume does not exist or if
394 * volume does not meet the requirements for a WD volume. No retry
395 * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD
396 * Valid flag if Volume info fails.
397 */
398 sc->WD_valid_config = FALSE;
399 if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
400 if (mps_config_get_man_pg10(sc, &mpi_reply)) {
401 mps_dprint(sc, MPS_FAULT,
402 "mps_config_get_man_pg10 failed! Using 0 (Hide "
403 "Always) for WarpDrive hide/expose value.\n");
404 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
405 }
406
407 /*
408 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
409 */
410 raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) +
411 (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
412 M_MPT2, M_ZERO | M_NOWAIT);
413 if (!raid_vol_pg0) {
414 printf("%s: page alloc failed\n", __func__);
415 goto out;
416 }
417
418 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
419 0x0000FFFF)) {
420 mps_dprint(sc, MPS_INFO,
421 "mps_config_get_raid_volume_pg0 failed! Assuming "
422 "WarpDrive IT mode.\n");
423 goto out;
424 }
425
426 /*
427 * Check for valid WD configuration:
428 * volume type is RAID0
429 * number of phys disks in the volume is no more than 8
430 */
431 if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
432 (raid_vol_pg0->NumPhysDisks > 8)) {
433 mps_dprint(sc, MPS_FAULT,
434 "Invalid WarpDrive configuration. Direct Drive I/O "
435 "will not be used.\n");
436 goto out;
437 }
438
439 /*
440 * Save the WD RAID data to be used during WD I/O.
441 */
442 sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
443 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
444 sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
445 sc->DD_dev_handle = raid_vol_pg0->DevHandle;
446 sc->DD_stripe_size = raid_vol_pg0->StripeSize;
447 sc->DD_block_size = raid_vol_pg0->BlockSize;
448
449 /*
450 * Find power of 2 of stripe size and set this as the exponent.
451 * Fail if stripe size is 0.
452 */
453 stripe_size = raid_vol_pg0->StripeSize;
454 for (index = 0; index < 32; index++) {
455 if (stripe_size & 1)
456 break;
457 stripe_exp++;
458 stripe_size >>= 1;
459 }
460 if (index == 32) {
461 mps_dprint(sc, MPS_FAULT,
462 "RAID Volume's stripe size is 0. Direct Drive I/O "
463 "will not be used.\n");
464 goto out;
465 }
466 sc->DD_stripe_exponent = stripe_exp;
467
468 /*
469 * Find power of 2 of block size and set this as the exponent.
470 * Fail if block size is 0.
471 */
472 block_size = raid_vol_pg0->BlockSize;
473 for (index = 0; index < 16; index++) {
474 if (block_size & 1)
475 break;
476 block_exp++;
477 block_size >>= 1;
478 }
479 if (index == 16) {
480 mps_dprint(sc, MPS_FAULT,
481 "RAID Volume's block size is 0. Direct Drive I/O "
482 "will not be used.\n");
483 goto out;
484 }
485 sc->DD_block_exponent = block_exp;
486
487 /*
488 * Loop through all of the volume's Phys Disks to map the phys
489 * disk number into the columm map. This is used during Direct
490 * Drive I/O to send the request to the correct SSD.
491 */
492 pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
493 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
494 sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
495 pRVPD->PhysDiskNum;
496 pRVPD++;
497 }
498
499 /*
500 * Get second RAID Volume Page0 using previous handle. This
501 * page should not exist. If it does, must not proceed with WD
502 * handling.
503 */
504 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
505 raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
506 if ((le16toh(mpi_reply.IOCStatus) &
507 MPI2_IOCSTATUS_MASK) !=
508 MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
509 mps_dprint(sc, MPS_FAULT,
510 "Multiple RAID Volume Page0! Direct Drive "
511 "I/O will not be used.\n");
512 goto out;
513 }
514 } else {
515 mps_dprint(sc, MPS_FAULT,
516 "Multiple volumes! Direct Drive I/O will not be "
517 "used.\n");
518 goto out;
519 }
520
521 /*
522 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
523 */
524 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
525 phys_disk_page_address =
526 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
527 sc->DD_column_map[index].phys_disk_num;
528 if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
529 &phys_disk_pg0, phys_disk_page_address)) {
530 mps_dprint(sc, MPS_FAULT,
531 "mps_config_get_raid_pd_pg0 failed! Direct "
532 "Drive I/O will not be used.\n");
533 goto out;
534 }
535 if (phys_disk_pg0.DevHandle == 0xFFFF) {
536 mps_dprint(sc, MPS_FAULT,
537 "Invalid Phys Disk DevHandle! Direct Drive "
538 "I/O will not be used.\n");
539 goto out;
540 }
541 sc->DD_column_map[index].dev_handle =
542 phys_disk_pg0.DevHandle;
543 }
544 sc->WD_valid_config = TRUE;
545 out:
546 if (raid_vol_pg0)
547 free(raid_vol_pg0, M_MPT2);
548 }
549 }
550
551 /**
552 * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
553 * @sc: per adapter object
554 * @mpi_reply: reply mf payload returned from firmware
555 * @config_page: contents of the config page
556 * @sz: size of buffer passed in config_page
557 * Context: sleep.
558 *
559 * Returns 0 for success, non-zero for failure.
560 */
561 int
mps_config_get_dpm_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 sz)562 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
563 Mpi2DriverMappingPage0_t *config_page, u16 sz)
564 {
565 MPI2_CONFIG_REQUEST *request;
566 MPI2_CONFIG_REPLY *reply = NULL;
567 struct mps_command *cm;
568 Mpi2DriverMappingPage0_t *page = NULL;
569 int error = 0;
570 u16 ioc_status;
571
572 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
573
574 memset(config_page, 0, sz);
575 if ((cm = mps_alloc_command(sc)) == NULL) {
576 printf("%s: command alloc failed @ line %d\n", __func__,
577 __LINE__);
578 error = EBUSY;
579 goto out;
580 }
581 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
582 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
583 request->Function = MPI2_FUNCTION_CONFIG;
584 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
585 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
586 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
587 request->Header.PageNumber = 0;
588 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
589 request->PageAddress = sc->max_dpm_entries <<
590 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
591 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
592 cm->cm_data = NULL;
593 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
594 if (cm != NULL)
595 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
596 if (error || (reply == NULL)) {
597 /* FIXME */
598 /*
599 * If the request returns an error then we need to do a diag
600 * reset
601 */
602 printf("%s: request for header completed with error %d\n",
603 __func__, error);
604 error = ENXIO;
605 goto out;
606 }
607 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
608 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
609 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
610 /* FIXME */
611 /*
612 * If the request returns an error then we need to do a diag
613 * reset
614 */
615 printf("%s: header read with error; iocstatus = 0x%x\n",
616 __func__, ioc_status);
617 error = ENXIO;
618 goto out;
619 }
620 /* We have to do free and alloc for the reply-free and reply-post
621 * counters to match - Need to review the reply FIFO handling.
622 */
623 mps_free_command(sc, cm);
624
625 if ((cm = mps_alloc_command(sc)) == NULL) {
626 printf("%s: command alloc failed @ line %d\n", __func__,
627 __LINE__);
628 error = EBUSY;
629 goto out;
630 }
631 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
632 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
633 request->Function = MPI2_FUNCTION_CONFIG;
634 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
635 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
636 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
637 request->Header.PageNumber = 0;
638 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
639 request->PageAddress = sc->max_dpm_entries <<
640 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
641 request->ExtPageLength = mpi_reply->ExtPageLength;
642 cm->cm_length = le16toh(request->ExtPageLength) * 4;
643 cm->cm_sge = &request->PageBufferSGE;
644 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
645 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
646 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
647 page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT);
648 if (!page) {
649 printf("%s: page alloc failed\n", __func__);
650 error = ENOMEM;
651 goto out;
652 }
653 cm->cm_data = page;
654 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
655 if (cm != NULL)
656 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
657 if (error || (reply == NULL)) {
658 /* FIXME */
659 /*
660 * If the request returns an error then we need to do a diag
661 * reset
662 */
663 printf("%s: request for page completed with error %d\n",
664 __func__, error);
665 error = ENXIO;
666 goto out;
667 }
668 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
669 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
670 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
671 /* FIXME */
672 /*
673 * If the request returns an error then we need to do a diag
674 * reset
675 */
676 printf("%s: page read with error; iocstatus = 0x%x\n",
677 __func__, ioc_status);
678 error = ENXIO;
679 goto out;
680 }
681 bcopy(page, config_page, MIN(cm->cm_length, sz));
682 out:
683 free(page, M_MPT2);
684 if (cm)
685 mps_free_command(sc, cm);
686 return (error);
687 }
688
689 /**
690 * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
691 * @sc: per adapter object
692 * @mpi_reply: reply mf payload returned from firmware
693 * @config_page: contents of the config page
694 * @entry_idx: entry index in DPM Page0 to be modified
695 * Context: sleep.
696 *
697 * Returns 0 for success, non-zero for failure.
698 */
699
mps_config_set_dpm_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 entry_idx)700 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
701 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
702 {
703 MPI2_CONFIG_REQUEST *request;
704 MPI2_CONFIG_REPLY *reply = NULL;
705 struct mps_command *cm;
706 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
707 int error = 0;
708 u16 ioc_status;
709
710 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
711
712 if ((cm = mps_alloc_command(sc)) == NULL) {
713 printf("%s: command alloc failed @ line %d\n", __func__,
714 __LINE__);
715 error = EBUSY;
716 goto out;
717 }
718 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
719 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
720 request->Function = MPI2_FUNCTION_CONFIG;
721 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
722 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
723 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
724 request->Header.PageNumber = 0;
725 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
726 /* We can remove below two lines ????*/
727 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
728 request->PageAddress |= htole16(entry_idx);
729 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
730 cm->cm_data = NULL;
731 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
732 if (cm != NULL)
733 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
734 if (error || (reply == NULL)) {
735 /* FIXME */
736 /*
737 * If the request returns an error then we need to do a diag
738 * reset
739 */
740 printf("%s: request for header completed with error %d\n",
741 __func__, error);
742 error = ENXIO;
743 goto out;
744 }
745 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
746 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
747 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
748 /* FIXME */
749 /*
750 * If the request returns an error then we need to do a diag
751 * reset
752 */
753 printf("%s: header read with error; iocstatus = 0x%x\n",
754 __func__, ioc_status);
755 error = ENXIO;
756 goto out;
757 }
758 /* We have to do free and alloc for the reply-free and reply-post
759 * counters to match - Need to review the reply FIFO handling.
760 */
761 mps_free_command(sc, cm);
762
763 if ((cm = mps_alloc_command(sc)) == NULL) {
764 printf("%s: command alloc failed @ line %d\n", __func__,
765 __LINE__);
766 error = EBUSY;
767 goto out;
768 }
769 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
770 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
771 request->Function = MPI2_FUNCTION_CONFIG;
772 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
773 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
774 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
775 request->Header.PageNumber = 0;
776 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
777 request->ExtPageLength = mpi_reply->ExtPageLength;
778 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
779 request->PageAddress |= htole16(entry_idx);
780 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
781 cm->cm_sge = &request->PageBufferSGE;
782 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
783 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
784 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
785 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
786 if (!page) {
787 printf("%s: page alloc failed\n", __func__);
788 error = ENOMEM;
789 goto out;
790 }
791 bcopy(config_page, page, MIN(cm->cm_length,
792 (sizeof(Mpi2DriverMappingPage0_t))));
793 cm->cm_data = page;
794 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
795 if (cm != NULL)
796 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
797 if (error || (reply == NULL)) {
798 /* FIXME */
799 /*
800 * If the request returns an error then we need to do a diag
801 * reset
802 */
803 printf("%s: request to write page completed with error %d\n",
804 __func__, error);
805 error = ENXIO;
806 goto out;
807 }
808 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
809 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
810 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
811 /* FIXME */
812 /*
813 * If the request returns an error then we need to do a diag
814 * reset
815 */
816 printf("%s: page written with error; iocstatus = 0x%x\n",
817 __func__, ioc_status);
818 error = ENXIO;
819 goto out;
820 }
821 out:
822 free(page, M_MPT2);
823 if (cm)
824 mps_free_command(sc, cm);
825 return (error);
826 }
827
828 /**
829 * mps_config_get_sas_device_pg0 - obtain sas device page 0
830 * @sc: per adapter object
831 * @mpi_reply: reply mf payload returned from firmware
832 * @config_page: contents of the config page
833 * @form: GET_NEXT_HANDLE or HANDLE
834 * @handle: device handle
835 * Context: sleep.
836 *
837 * Returns 0 for success, non-zero for failure.
838 */
839 int
mps_config_get_sas_device_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2SasDevicePage0_t * config_page,u32 form,u16 handle)840 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
841 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
842 {
843 MPI2_CONFIG_REQUEST *request;
844 MPI2_CONFIG_REPLY *reply = NULL;
845 struct mps_command *cm;
846 Mpi2SasDevicePage0_t *page = NULL;
847 int error = 0;
848 u16 ioc_status;
849
850 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
851
852 if ((cm = mps_alloc_command(sc)) == NULL) {
853 printf("%s: command alloc failed @ line %d\n", __func__,
854 __LINE__);
855 error = EBUSY;
856 goto out;
857 }
858 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
859 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
860 request->Function = MPI2_FUNCTION_CONFIG;
861 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
862 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
863 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
864 request->Header.PageNumber = 0;
865 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
866 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
867 cm->cm_data = NULL;
868 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
869 if (cm != NULL)
870 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
871 if (error || (reply == NULL)) {
872 /* FIXME */
873 /*
874 * If the request returns an error then we need to do a diag
875 * reset
876 */
877 printf("%s: request for header completed with error %d\n",
878 __func__, error);
879 error = ENXIO;
880 goto out;
881 }
882 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
883 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
884 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
885 /* FIXME */
886 /*
887 * If the request returns an error then we need to do a diag
888 * reset
889 */
890 printf("%s: header read with error; iocstatus = 0x%x\n",
891 __func__, ioc_status);
892 error = ENXIO;
893 goto out;
894 }
895 /* We have to do free and alloc for the reply-free and reply-post
896 * counters to match - Need to review the reply FIFO handling.
897 */
898 mps_free_command(sc, cm);
899
900 if ((cm = mps_alloc_command(sc)) == NULL) {
901 printf("%s: command alloc failed @ line %d\n", __func__,
902 __LINE__);
903 error = EBUSY;
904 goto out;
905 }
906 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
907 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
908 request->Function = MPI2_FUNCTION_CONFIG;
909 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
910 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
911 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
912 request->Header.PageNumber = 0;
913 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
914 request->ExtPageLength = mpi_reply->ExtPageLength;
915 request->PageAddress = htole32(form | handle);
916 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
917 cm->cm_sge = &request->PageBufferSGE;
918 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
919 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
920 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
921 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
922 if (!page) {
923 printf("%s: page alloc failed\n", __func__);
924 error = ENOMEM;
925 goto out;
926 }
927 cm->cm_data = page;
928
929 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
930 if (cm != NULL)
931 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
932 if (error || (reply == NULL)) {
933 /* FIXME */
934 /*
935 * If the request returns an error then we need to do a diag
936 * reset
937 */
938 printf("%s: request for page completed with error %d\n",
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 /*
948 * If the request returns an error then we need to do a diag
949 * reset
950 */
951 printf("%s: page read with error; iocstatus = 0x%x\n",
952 __func__, ioc_status);
953 error = ENXIO;
954 goto out;
955 }
956 bcopy(page, config_page, MIN(cm->cm_length,
957 sizeof(Mpi2SasDevicePage0_t)));
958 out:
959 free(page, M_MPT2);
960 if (cm)
961 mps_free_command(sc, cm);
962 return (error);
963 }
964
965 /**
966 * mps_config_get_bios_pg3 - obtain BIOS page 3
967 * @sc: per adapter object
968 * @mpi_reply: reply mf payload returned from firmware
969 * @config_page: contents of the config page
970 * Context: sleep.
971 *
972 * Returns 0 for success, non-zero for failure.
973 */
974 int
mps_config_get_bios_pg3(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2BiosPage3_t * config_page)975 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
976 Mpi2BiosPage3_t *config_page)
977 {
978 MPI2_CONFIG_REQUEST *request;
979 MPI2_CONFIG_REPLY *reply = NULL;
980 struct mps_command *cm;
981 Mpi2BiosPage3_t *page = NULL;
982 int error = 0;
983 u16 ioc_status;
984
985 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
986
987 if ((cm = mps_alloc_command(sc)) == NULL) {
988 printf("%s: command alloc failed @ line %d\n", __func__,
989 __LINE__);
990 error = EBUSY;
991 goto out;
992 }
993 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
994 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
995 request->Function = MPI2_FUNCTION_CONFIG;
996 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
997 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
998 request->Header.PageNumber = 3;
999 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1000 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1001 cm->cm_data = NULL;
1002 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1003 if (cm != NULL)
1004 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1005 if (error || (reply == NULL)) {
1006 /* FIXME */
1007 /*
1008 * If the request returns an error then we need to do a diag
1009 * reset
1010 */
1011 printf("%s: request for header completed with error %d\n",
1012 __func__, error);
1013 error = ENXIO;
1014 goto out;
1015 }
1016 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1017 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1018 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1019 /* FIXME */
1020 /*
1021 * If the request returns an error then we need to do a diag
1022 * reset
1023 */
1024 printf("%s: header read with error; iocstatus = 0x%x\n",
1025 __func__, ioc_status);
1026 error = ENXIO;
1027 goto out;
1028 }
1029 /* We have to do free and alloc for the reply-free and reply-post
1030 * counters to match - Need to review the reply FIFO handling.
1031 */
1032 mps_free_command(sc, cm);
1033
1034 if ((cm = mps_alloc_command(sc)) == NULL) {
1035 printf("%s: command alloc failed @ line %d\n", __func__,
1036 __LINE__);
1037 error = EBUSY;
1038 goto out;
1039 }
1040 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1041 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1042 request->Function = MPI2_FUNCTION_CONFIG;
1043 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1044 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1045 request->Header.PageNumber = 3;
1046 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1047 request->Header.PageLength = mpi_reply->Header.PageLength;
1048 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1049 cm->cm_sge = &request->PageBufferSGE;
1050 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1051 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1052 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1053 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1054 if (!page) {
1055 printf("%s: page alloc failed\n", __func__);
1056 error = ENOMEM;
1057 goto out;
1058 }
1059 cm->cm_data = page;
1060
1061 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1062 if (cm != NULL)
1063 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1064 if (error || (reply == NULL)) {
1065 /* FIXME */
1066 /*
1067 * If the request returns an error then we need to do a diag
1068 * reset
1069 */
1070 printf("%s: request for page completed with error %d\n",
1071 __func__, error);
1072 error = ENXIO;
1073 goto out;
1074 }
1075 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1076 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1077 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1078 /* FIXME */
1079 /*
1080 * If the request returns an error then we need to do a diag
1081 * reset
1082 */
1083 printf("%s: page read with error; iocstatus = 0x%x\n",
1084 __func__, ioc_status);
1085 error = ENXIO;
1086 goto out;
1087 }
1088 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1089 out:
1090 free(page, M_MPT2);
1091 if (cm)
1092 mps_free_command(sc, cm);
1093 return (error);
1094 }
1095
1096 /**
1097 * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1098 * @sc: per adapter object
1099 * @mpi_reply: reply mf payload returned from firmware
1100 * @config_page: contents of the config page
1101 * @page_address: form and handle value used to get page
1102 * Context: sleep.
1103 *
1104 * Returns 0 for success, non-zero for failure.
1105 */
1106 int
mps_config_get_raid_volume_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage0_t * config_page,u32 page_address)1107 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1108 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1109 {
1110 MPI2_CONFIG_REQUEST *request;
1111 MPI2_CONFIG_REPLY *reply = NULL;
1112 struct mps_command *cm;
1113 Mpi2RaidVolPage0_t *page = NULL;
1114 int error = 0;
1115 u16 ioc_status;
1116
1117 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1118
1119 if ((cm = mps_alloc_command(sc)) == NULL) {
1120 printf("%s: command alloc failed @ line %d\n", __func__,
1121 __LINE__);
1122 error = EBUSY;
1123 goto out;
1124 }
1125 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1126 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1127 request->Function = MPI2_FUNCTION_CONFIG;
1128 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1129 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1130 request->Header.PageNumber = 0;
1131 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1132 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1133 cm->cm_data = NULL;
1134
1135 /*
1136 * This page must be polled because the IOC isn't ready yet when this
1137 * page is needed.
1138 */
1139 error = mps_wait_command(sc, &cm, 60, 0);
1140 if (cm != NULL)
1141 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1142 if (error || (reply == NULL)) {
1143 /* FIXME */
1144 /* If the poll returns error then we need to do diag reset */
1145 printf("%s: poll for header completed with error %d\n",
1146 __func__, error);
1147 error = ENXIO;
1148 goto out;
1149 }
1150 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1151 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1152 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1153 /* FIXME */
1154 /* If the poll returns error then we need to do diag reset */
1155 printf("%s: header read with error; iocstatus = 0x%x\n",
1156 __func__, ioc_status);
1157 error = ENXIO;
1158 goto out;
1159 }
1160 /* We have to do free and alloc for the reply-free and reply-post
1161 * counters to match - Need to review the reply FIFO handling.
1162 */
1163 mps_free_command(sc, cm);
1164
1165 if ((cm = mps_alloc_command(sc)) == NULL) {
1166 printf("%s: command alloc failed @ line %d\n", __func__,
1167 __LINE__);
1168 error = EBUSY;
1169 goto out;
1170 }
1171 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1172 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1173 request->Function = MPI2_FUNCTION_CONFIG;
1174 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1175 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1176 request->Header.PageNumber = 0;
1177 request->Header.PageLength = mpi_reply->Header.PageLength;
1178 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1179 request->PageAddress = page_address;
1180 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1181 cm->cm_sge = &request->PageBufferSGE;
1182 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1183 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1184 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1185 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1186 if (!page) {
1187 printf("%s: page alloc failed\n", __func__);
1188 error = ENOMEM;
1189 goto out;
1190 }
1191 cm->cm_data = page;
1192
1193 /*
1194 * This page must be polled because the IOC isn't ready yet when this
1195 * page is needed.
1196 */
1197 error = mps_wait_command(sc, &cm, 60, 0);
1198 if (cm != NULL)
1199 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1200 if (error || (reply == NULL)) {
1201 /* FIXME */
1202 /* If the poll returns error then we need to do diag reset */
1203 printf("%s: poll for page completed with error %d\n",
1204 __func__, error);
1205 error = ENXIO;
1206 goto out;
1207 }
1208 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1209 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1210 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1211 /* FIXME */
1212 /* If the poll returns error then we need to do diag reset */
1213 printf("%s: page read with error; iocstatus = 0x%x\n",
1214 __func__, ioc_status);
1215 error = ENXIO;
1216 goto out;
1217 }
1218 bcopy(page, config_page, cm->cm_length);
1219 out:
1220 free(page, M_MPT2);
1221 if (cm)
1222 mps_free_command(sc, cm);
1223 return (error);
1224 }
1225
1226 /**
1227 * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1228 * @sc: per adapter object
1229 * @mpi_reply: reply mf payload returned from firmware
1230 * @config_page: contents of the config page
1231 * @form: GET_NEXT_HANDLE or HANDLE
1232 * @handle: volume handle
1233 * Context: sleep.
1234 *
1235 * Returns 0 for success, non-zero for failure.
1236 */
1237 int
mps_config_get_raid_volume_pg1(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage1_t * config_page,u32 form,u16 handle)1238 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1239 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1240 {
1241 MPI2_CONFIG_REQUEST *request;
1242 MPI2_CONFIG_REPLY *reply = NULL;
1243 struct mps_command *cm;
1244 Mpi2RaidVolPage1_t *page = NULL;
1245 int error = 0;
1246 u16 ioc_status;
1247
1248 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1249
1250 if ((cm = mps_alloc_command(sc)) == NULL) {
1251 printf("%s: command alloc failed @ line %d\n", __func__,
1252 __LINE__);
1253 error = EBUSY;
1254 goto out;
1255 }
1256 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1257 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1258 request->Function = MPI2_FUNCTION_CONFIG;
1259 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1260 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1261 request->Header.PageNumber = 1;
1262 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1263 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1264 cm->cm_data = NULL;
1265 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1266 if (cm != NULL)
1267 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1268 if (error || (reply == NULL)) {
1269 /* FIXME */
1270 /*
1271 * If the request returns an error then we need to do a diag
1272 * reset
1273 */
1274 printf("%s: request for header completed with error %d\n",
1275 __func__, error);
1276 error = ENXIO;
1277 goto out;
1278 }
1279 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1280 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1281 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1282 /* FIXME */
1283 /*
1284 * If the request returns an error then we need to do a diag
1285 * reset
1286 */
1287 printf("%s: header read with error; iocstatus = 0x%x\n",
1288 __func__, ioc_status);
1289 error = ENXIO;
1290 goto out;
1291 }
1292 /* We have to do free and alloc for the reply-free and reply-post
1293 * counters to match - Need to review the reply FIFO handling.
1294 */
1295 mps_free_command(sc, cm);
1296
1297 if ((cm = mps_alloc_command(sc)) == NULL) {
1298 printf("%s: command alloc failed @ line %d\n", __func__,
1299 __LINE__);
1300 error = EBUSY;
1301 goto out;
1302 }
1303 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1304 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1305 request->Function = MPI2_FUNCTION_CONFIG;
1306 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1307 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1308 request->Header.PageNumber = 1;
1309 request->Header.PageLength = mpi_reply->Header.PageLength;
1310 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1311 request->PageAddress = htole32(form | handle);
1312 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1313 cm->cm_sge = &request->PageBufferSGE;
1314 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1315 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1316 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1317 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1318 if (!page) {
1319 printf("%s: page alloc failed\n", __func__);
1320 error = ENOMEM;
1321 goto out;
1322 }
1323 cm->cm_data = page;
1324
1325 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1326 if (cm != NULL)
1327 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1328 if (error || (reply == NULL)) {
1329 /* FIXME */
1330 /*
1331 * If the request returns an error then we need to do a diag
1332 * reset
1333 */
1334 printf("%s: request for page completed with error %d\n",
1335 __func__, error);
1336 error = ENXIO;
1337 goto out;
1338 }
1339 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1340 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1341 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1342 /* FIXME */
1343 /*
1344 * If the request returns an error then we need to do a diag
1345 * reset
1346 */
1347 printf("%s: page read with error; iocstatus = 0x%x\n",
1348 __func__, ioc_status);
1349 error = ENXIO;
1350 goto out;
1351 }
1352 bcopy(page, config_page, MIN(cm->cm_length,
1353 sizeof(Mpi2RaidVolPage1_t)));
1354 out:
1355 free(page, M_MPT2);
1356 if (cm)
1357 mps_free_command(sc, cm);
1358 return (error);
1359 }
1360
1361 /**
1362 * mps_config_get_volume_wwid - returns wwid given the volume handle
1363 * @sc: per adapter object
1364 * @volume_handle: volume handle
1365 * @wwid: volume wwid
1366 * Context: sleep.
1367 *
1368 * Returns 0 for success, non-zero for failure.
1369 */
1370 int
mps_config_get_volume_wwid(struct mps_softc * sc,u16 volume_handle,u64 * wwid)1371 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1372 {
1373 Mpi2ConfigReply_t mpi_reply;
1374 Mpi2RaidVolPage1_t raid_vol_pg1;
1375
1376 *wwid = 0;
1377 if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1378 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1379 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1380 raid_vol_pg1.WWID.Low);
1381 return 0;
1382 } else
1383 return -1;
1384 }
1385
1386 /**
1387 * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1388 * @sc: per adapter object
1389 * @mpi_reply: reply mf payload returned from firmware
1390 * @config_page: contents of the config page
1391 * @page_address: form and handle value used to get page
1392 * Context: sleep.
1393 *
1394 * Returns 0 for success, non-zero for failure.
1395 */
1396 int
mps_config_get_raid_pd_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidPhysDiskPage0_t * config_page,u32 page_address)1397 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1398 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1399 {
1400 MPI2_CONFIG_REQUEST *request;
1401 MPI2_CONFIG_REPLY *reply = NULL;
1402 struct mps_command *cm;
1403 Mpi2RaidPhysDiskPage0_t *page = NULL;
1404 int error = 0;
1405 u16 ioc_status;
1406
1407 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1408
1409 if ((cm = mps_alloc_command(sc)) == NULL) {
1410 printf("%s: command alloc failed @ line %d\n", __func__,
1411 __LINE__);
1412 error = EBUSY;
1413 goto out;
1414 }
1415 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1416 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1417 request->Function = MPI2_FUNCTION_CONFIG;
1418 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1419 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1420 request->Header.PageNumber = 0;
1421 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1422 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1423 cm->cm_data = NULL;
1424
1425 /*
1426 * This page must be polled because the IOC isn't ready yet when this
1427 * page is needed.
1428 */
1429 error = mps_wait_command(sc, &cm, 60, 0);
1430 if (cm != NULL)
1431 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1432 if (error || (reply == NULL)) {
1433 /* FIXME */
1434 /* If the poll returns error then we need to do diag reset */
1435 printf("%s: poll for header completed with error %d\n",
1436 __func__, error);
1437 error = ENXIO;
1438 goto out;
1439 }
1440 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1441 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1442 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1443 /* FIXME */
1444 /* If the poll returns error then we need to do diag reset */
1445 printf("%s: header read with error; iocstatus = 0x%x\n",
1446 __func__, ioc_status);
1447 error = ENXIO;
1448 goto out;
1449 }
1450 /* We have to do free and alloc for the reply-free and reply-post
1451 * counters to match - Need to review the reply FIFO handling.
1452 */
1453 mps_free_command(sc, cm);
1454
1455 if ((cm = mps_alloc_command(sc)) == NULL) {
1456 printf("%s: command alloc failed @ line %d\n", __func__,
1457 __LINE__);
1458 error = EBUSY;
1459 goto out;
1460 }
1461 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1462 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1463 request->Function = MPI2_FUNCTION_CONFIG;
1464 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1465 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1466 request->Header.PageNumber = 0;
1467 request->Header.PageLength = mpi_reply->Header.PageLength;
1468 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1469 request->PageAddress = page_address;
1470 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1471 cm->cm_sge = &request->PageBufferSGE;
1472 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1473 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1474 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1475 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1476 if (!page) {
1477 printf("%s: page alloc failed\n", __func__);
1478 error = ENOMEM;
1479 goto out;
1480 }
1481 cm->cm_data = page;
1482
1483 /*
1484 * This page must be polled because the IOC isn't ready yet when this
1485 * page is needed.
1486 */
1487 error = mps_wait_command(sc, &cm, 60, 0);
1488 if (cm != NULL)
1489 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1490 if (error || (reply == NULL)) {
1491 /* FIXME */
1492 /* If the poll returns error then we need to do diag reset */
1493 printf("%s: poll for page completed with error %d\n",
1494 __func__, error);
1495 error = ENXIO;
1496 goto out;
1497 }
1498 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1499 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1500 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1501 /* FIXME */
1502 /* If the poll returns error then we need to do diag reset */
1503 printf("%s: page read with error; iocstatus = 0x%x\n",
1504 __func__, ioc_status);
1505 error = ENXIO;
1506 goto out;
1507 }
1508 bcopy(page, config_page, MIN(cm->cm_length,
1509 sizeof(Mpi2RaidPhysDiskPage0_t)));
1510 out:
1511 free(page, M_MPT2);
1512 if (cm)
1513 mps_free_command(sc, cm);
1514 return (error);
1515 }
1516