2 * Copyright (c) 2011 LSI Corp.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * LSI MPT-Fusion Host Adapter FreeBSD
28 * $FreeBSD: src/sys/dev/mps/mps_config.c,v 1.1 2012/01/26 18:17:21 ken Exp $
31 /* TODO Move headers to mpsvar */
32 #include <sys/types.h>
33 #include <sys/param.h>
35 #include <sys/mutex.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/kthread.h>
40 #include <sys/taskqueue.h>
42 #include <sys/endian.h>
43 #include <sys/sysctl.h>
44 #include <sys/eventhandler.h>
46 #include <dev/raid/mps/mpi/mpi2_type.h>
47 #include <dev/raid/mps/mpi/mpi2.h>
48 #include <dev/raid/mps/mpi/mpi2_ioc.h>
49 #include <dev/raid/mps/mpi/mpi2_sas.h>
50 #include <dev/raid/mps/mpi/mpi2_cnfg.h>
51 #include <dev/raid/mps/mpi/mpi2_init.h>
52 #include <dev/raid/mps/mpi/mpi2_tool.h>
53 #include <dev/raid/mps/mps_ioctl.h>
54 #include <dev/raid/mps/mpsvar.h>
57 * mps_config_get_ioc_pg8 - obtain ioc page 8
58 * @sc: per adapter object
59 * @mpi_reply: reply mf payload returned from firmware
60 * @config_page: contents of the config page
63 * Returns 0 for success, non-zero for failure.
66 mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
67 Mpi2IOCPage8_t *config_page)
69 MPI2_CONFIG_REQUEST *request;
70 MPI2_CONFIG_REPLY *reply;
71 struct mps_command *cm;
72 MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
76 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
78 if ((cm = mps_alloc_command(sc)) == NULL) {
79 kprintf("%s: command alloc failed @ line %d\n", __func__,
84 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
85 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
86 request->Function = MPI2_FUNCTION_CONFIG;
87 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
88 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
89 request->Header.PageNumber = 8;
90 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
91 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
93 error = mps_request_polled(sc, cm);
94 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
95 if (error || (reply == NULL)) {
97 /* If the poll returns error then we need to do diag reset */
98 kprintf("%s: poll for header completed with error %d",
103 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
104 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
105 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
107 /* If the poll returns error then we need to do diag reset */
108 kprintf("%s: header read with error; iocstatus = 0x%x\n",
109 __func__, ioc_status);
113 /* We have to do free and alloc for the reply-free and reply-post
114 * counters to match - Need to review the reply FIFO handling.
116 mps_free_command(sc, cm);
118 if ((cm = mps_alloc_command(sc)) == NULL) {
119 kprintf("%s: command alloc failed @ line %d\n", __func__,
124 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
125 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
126 request->Function = MPI2_FUNCTION_CONFIG;
127 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
128 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
129 request->Header.PageNumber = 8;
130 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
131 request->Header.PageLength = mpi_reply->Header.PageLength;
132 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
133 cm->cm_sge = &request->PageBufferSGE;
134 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
135 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
136 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
137 page = kmalloc((cm->cm_length), M_MPT2, M_ZERO | M_INTWAIT);
139 kprintf("%s: page alloc failed\n", __func__);
144 error = mps_request_polled(sc, cm);
145 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
146 if (error || (reply == NULL)) {
148 /* If the poll returns error then we need to do diag reset */
149 kprintf("%s: poll for page completed with error %d",
154 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
155 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
156 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
158 /* If the poll returns error then we need to do diag reset */
159 kprintf("%s: page read with error; iocstatus = 0x%x\n",
160 __func__, ioc_status);
164 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
169 mps_free_command(sc, cm);
174 * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
175 * accordingly. Currently, this page does not need to return to caller.
176 * @sc: per adapter object
177 * @mpi_reply: reply mf payload returned from firmware
180 * Returns 0 for success, non-zero for failure.
183 mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
185 MPI2_CONFIG_REQUEST *request;
186 MPI2_CONFIG_REPLY *reply;
187 struct mps_command *cm;
188 pMpi2ManufacturingPagePS_t page = NULL;
190 uint8_t OEM_Value = 0;
194 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
196 if ((cm = mps_alloc_command(sc)) == NULL) {
197 kprintf("%s: command alloc failed @ line %d\n", __func__,
202 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
203 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
204 request->Function = MPI2_FUNCTION_CONFIG;
205 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
206 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
207 request->Header.PageNumber = 10;
208 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
209 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
211 error = mps_request_polled(sc, cm);
212 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
213 if (error || (reply == NULL)) {
215 /* If the poll returns error then we need to do diag reset */
216 kprintf("%s: poll for header completed with error %d",
221 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
222 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
223 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
225 /* If the poll returns error then we need to do diag reset */
226 kprintf("%s: header read with error; iocstatus = 0x%x\n",
227 __func__, ioc_status);
231 /* We have to do free and alloc for the reply-free and reply-post
232 * counters to match - Need to review the reply FIFO handling.
234 mps_free_command(sc, cm);
236 if ((cm = mps_alloc_command(sc)) == NULL) {
237 kprintf("%s: command alloc failed @ line %d\n", __func__,
242 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
243 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
244 request->Function = MPI2_FUNCTION_CONFIG;
245 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
246 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
247 request->Header.PageNumber = 10;
248 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
249 request->Header.PageLength = mpi_reply->Header.PageLength;
250 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
251 cm->cm_sge = &request->PageBufferSGE;
252 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
253 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
254 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
255 page = kmalloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_INTWAIT);
257 kprintf("%s: page alloc failed\n", __func__);
262 error = mps_request_polled(sc, cm);
263 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
264 if (error || (reply == NULL)) {
266 /* If the poll returns error then we need to do diag reset */
267 kprintf("%s: poll for page completed with error %d",
272 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
273 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
274 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
276 /* If the poll returns error then we need to do diag reset */
277 kprintf("%s: page read with error; iocstatus = 0x%x\n",
278 __func__, ioc_status);
284 * If OEM ID is unknown, fail the request.
286 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
287 OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
288 if (OEM_Value != MPS_WD_LSI_OEM) {
289 mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
290 "(0x%x)\n", OEM_Value);
296 * Set the phys disks hide/expose value.
298 pPS_info = &page->ProductSpecificInfo;
299 sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
300 sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
301 if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
302 (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
303 (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
304 mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
305 "hide/expose: 0x%x\n", sc->WD_hide_expose);
313 mps_free_command(sc, cm);
318 * mps_base_static_config_pages - static start of day config pages.
319 * @sc: per adapter object
324 mps_base_static_config_pages(struct mps_softc *sc)
326 Mpi2ConfigReply_t mpi_reply;
330 while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
333 /* We need to Handle this situation */
341 * mps_wd_config_pages - get info required to support WarpDrive. This needs to
342 * be called after discovery is complete to guarentee that IR info is there.
343 * @sc: per adapter object
348 mps_wd_config_pages(struct mps_softc *sc)
350 Mpi2ConfigReply_t mpi_reply;
351 pMpi2RaidVolPage0_t raid_vol_pg0 = NULL;
352 Mpi2RaidPhysDiskPage0_t phys_disk_pg0;
353 pMpi2RaidVol0PhysDisk_t pRVPD;
354 uint32_t stripe_size, phys_disk_page_address;
356 uint8_t index, stripe_exp = 0, block_exp = 0;
359 * Get the WD settings from manufacturing page 10 if using a WD HBA.
360 * This will be used to determine if phys disks should always be
361 * hidden, hidden only if part of a WD volume, or never hidden. Also,
362 * get the WD RAID Volume info and fail if volume does not exist or if
363 * volume does not meet the requirements for a WD volume. No retry
364 * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD
365 * Valid flag if Volume info fails.
367 sc->WD_valid_config = FALSE;
368 if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
369 if (mps_config_get_man_pg10(sc, &mpi_reply)) {
370 mps_dprint(sc, MPS_FAULT,
371 "mps_config_get_man_pg10 failed! Using 0 (Hide "
372 "Always) for WarpDrive hide/expose value.\n");
373 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
377 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
379 raid_vol_pg0 = kmalloc(sizeof(Mpi2RaidVolPage0_t) +
380 (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
381 M_MPT2, M_ZERO | M_INTWAIT);
383 kprintf("%s: page alloc failed\n", __func__);
387 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
389 mps_dprint(sc, MPS_INFO,
390 "mps_config_get_raid_volume_pg0 failed! Assuming "
391 "WarpDrive IT mode.\n");
396 * Check for valid WD configuration:
397 * volume type is RAID0
398 * number of phys disks in the volume is no more than 8
400 if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
401 (raid_vol_pg0->NumPhysDisks > 8)) {
402 mps_dprint(sc, MPS_FAULT,
403 "Invalid WarpDrive configuration. Direct Drive I/O "
404 "will not be used.\n");
409 * Save the WD RAID data to be used during WD I/O.
411 sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
412 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
413 sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
414 sc->DD_dev_handle = raid_vol_pg0->DevHandle;
415 sc->DD_stripe_size = raid_vol_pg0->StripeSize;
416 sc->DD_block_size = raid_vol_pg0->BlockSize;
419 * Find power of 2 of stripe size and set this as the exponent.
420 * Fail if stripe size is 0.
422 stripe_size = raid_vol_pg0->StripeSize;
423 for (index = 0; index < 32; index++) {
430 mps_dprint(sc, MPS_FAULT,
431 "RAID Volume's stripe size is 0. Direct Drive I/O "
432 "will not be used.\n");
435 sc->DD_stripe_exponent = stripe_exp;
438 * Find power of 2 of block size and set this as the exponent.
439 * Fail if block size is 0.
441 block_size = raid_vol_pg0->BlockSize;
442 for (index = 0; index < 16; index++) {
449 mps_dprint(sc, MPS_FAULT,
450 "RAID Volume's block size is 0. Direct Drive I/O "
451 "will not be used.\n");
454 sc->DD_block_exponent = block_exp;
457 * Loop through all of the volume's Phys Disks to map the phys
458 * disk number into the columm map. This is used during Direct
459 * Drive I/O to send the request to the correct SSD.
461 pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
462 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
463 sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
469 * Get second RAID Volume Page0 using previous handle. This
470 * page should not exist. If it does, must not proceed with WD
473 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
474 raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
475 if (mpi_reply.IOCStatus !=
476 MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
477 mps_dprint(sc, MPS_FAULT,
478 "Multiple RAID Volume Page0! Direct Drive "
479 "I/O will not be used.\n");
483 mps_dprint(sc, MPS_FAULT,
484 "Multiple volumes! Direct Drive I/O will not be "
490 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
492 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
493 phys_disk_page_address =
494 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
495 sc->DD_column_map[index].phys_disk_num;
496 if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
497 &phys_disk_pg0, phys_disk_page_address)) {
498 mps_dprint(sc, MPS_FAULT,
499 "mps_config_get_raid_pd_pg0 failed! Direct "
500 "Drive I/O will not be used.\n");
503 if (phys_disk_pg0.DevHandle == 0xFFFF) {
504 mps_dprint(sc, MPS_FAULT,
505 "Invalid Phys Disk DevHandle! Direct Drive "
506 "I/O will not be used.\n");
509 sc->DD_column_map[index].dev_handle =
510 phys_disk_pg0.DevHandle;
512 sc->WD_valid_config = TRUE;
515 kfree(raid_vol_pg0, M_MPT2);
520 * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
521 * @sc: per adapter object
522 * @mpi_reply: reply mf payload returned from firmware
523 * @config_page: contents of the config page
524 * @sz: size of buffer passed in config_page
527 * Returns 0 for success, non-zero for failure.
530 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
531 Mpi2DriverMappingPage0_t *config_page, u16 sz)
533 MPI2_CONFIG_REQUEST *request;
534 MPI2_CONFIG_REPLY *reply;
535 struct mps_command *cm;
536 Mpi2DriverMappingPage0_t *page = NULL;
540 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
542 memset(config_page, 0, sz);
543 if ((cm = mps_alloc_command(sc)) == NULL) {
544 kprintf("%s: command alloc failed @ line %d\n", __func__,
549 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
550 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
551 request->Function = MPI2_FUNCTION_CONFIG;
552 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
553 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
554 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
555 request->Header.PageNumber = 0;
556 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
557 request->PageAddress = sc->max_dpm_entries <<
558 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
559 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
561 error = mps_request_polled(sc, cm);
562 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
563 if (error || (reply == NULL)) {
565 /* If the poll returns error then we need to do diag reset */
566 kprintf("%s: poll for header completed with error %d",
571 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
572 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
573 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
575 /* If the poll returns error then we need to do diag reset */
576 kprintf("%s: header read with error; iocstatus = 0x%x\n",
577 __func__, ioc_status);
581 /* We have to do free and alloc for the reply-free and reply-post
582 * counters to match - Need to review the reply FIFO handling.
584 mps_free_command(sc, cm);
586 if ((cm = mps_alloc_command(sc)) == NULL) {
587 kprintf("%s: command alloc failed @ line %d\n", __func__,
592 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
593 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
594 request->Function = MPI2_FUNCTION_CONFIG;
595 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
596 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
597 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
598 request->Header.PageNumber = 0;
599 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
600 request->PageAddress = sc->max_dpm_entries <<
601 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
602 request->ExtPageLength = mpi_reply->ExtPageLength;
603 cm->cm_length = le16toh(request->ExtPageLength) * 4;
604 cm->cm_sge = &request->PageBufferSGE;
605 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
606 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
607 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
608 page = kmalloc(cm->cm_length, M_MPT2, M_ZERO|M_INTWAIT);
610 kprintf("%s: page alloc failed\n", __func__);
615 error = mps_request_polled(sc, cm);
616 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
617 if (error || (reply == NULL)) {
619 /* If the poll returns error then we need to do diag reset */
620 kprintf("%s: poll for page completed with error %d",
625 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
626 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
627 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
629 /* If the poll returns error then we need to do diag reset */
630 kprintf("%s: page read with error; iocstatus = 0x%x\n",
631 __func__, ioc_status);
635 bcopy(page, config_page, MIN(cm->cm_length, sz));
639 mps_free_command(sc, cm);
644 * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
645 * @sc: per adapter object
646 * @mpi_reply: reply mf payload returned from firmware
647 * @config_page: contents of the config page
648 * @entry_idx: entry index in DPM Page0 to be modified
651 * Returns 0 for success, non-zero for failure.
654 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
655 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
657 MPI2_CONFIG_REQUEST *request;
658 MPI2_CONFIG_REPLY *reply;
659 struct mps_command *cm;
660 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
664 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
666 if ((cm = mps_alloc_command(sc)) == NULL) {
667 kprintf("%s: command alloc failed @ line %d\n", __func__,
672 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
673 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
674 request->Function = MPI2_FUNCTION_CONFIG;
675 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
676 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
677 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
678 request->Header.PageNumber = 0;
679 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
680 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
681 request->PageAddress |= htole16(entry_idx);
682 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
684 error = mps_request_polled(sc, cm);
685 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
686 if (error || (reply == NULL)) {
688 /* If the poll returns error then we need to do diag reset */
689 kprintf("%s: poll for header completed with error %d",
694 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
695 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
696 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
698 /* If the poll returns error then we need to do diag reset */
699 kprintf("%s: header read with error; iocstatus = 0x%x\n",
700 __func__, ioc_status);
704 /* We have to do free and alloc for the reply-free and reply-post
705 * counters to match - Need to review the reply FIFO handling.
707 mps_free_command(sc, cm);
709 if ((cm = mps_alloc_command(sc)) == NULL) {
710 kprintf("%s: command alloc failed @ line %d\n", __func__,
715 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
716 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
717 request->Function = MPI2_FUNCTION_CONFIG;
718 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
719 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
720 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
721 request->Header.PageNumber = 0;
722 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
723 request->ExtPageLength = mpi_reply->ExtPageLength;
724 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
725 request->PageAddress |= htole16(entry_idx);
726 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
727 cm->cm_sge = &request->PageBufferSGE;
728 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
729 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
730 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
731 page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
733 kprintf("%s: page alloc failed\n", __func__);
737 bcopy(config_page, page, MIN(cm->cm_length,
738 (sizeof(Mpi2DriverMappingPage0_t))));
740 error = mps_request_polled(sc, cm);
741 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
742 if (error || (reply == NULL)) {
744 /* If the poll returns error then we need to do diag reset */
745 kprintf("%s: poll for page completed with error %d",
750 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
751 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
752 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
754 /* If the poll returns error then we need to do diag reset */
755 kprintf("%s: page written with error; iocstatus = 0x%x\n",
756 __func__, ioc_status);
763 mps_free_command(sc, cm);
768 * mps_config_get_sas_device_pg0 - obtain sas device page 0
769 * @sc: per adapter object
770 * @mpi_reply: reply mf payload returned from firmware
771 * @config_page: contents of the config page
772 * @form: GET_NEXT_HANDLE or HANDLE
773 * @handle: device handle
776 * Returns 0 for success, non-zero for failure.
779 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
780 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
782 MPI2_CONFIG_REQUEST *request;
783 MPI2_CONFIG_REPLY *reply;
784 struct mps_command *cm;
785 Mpi2SasDevicePage0_t *page = NULL;
789 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
791 if ((cm = mps_alloc_command(sc)) == NULL) {
792 kprintf("%s: command alloc failed @ line %d\n", __func__,
797 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
798 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
799 request->Function = MPI2_FUNCTION_CONFIG;
800 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
801 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
802 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
803 request->Header.PageNumber = 0;
804 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
805 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
807 error = mps_request_polled(sc, cm);
808 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
809 if (error || (reply == NULL)) {
811 /* If the poll returns error then we need to do diag reset */
812 kprintf("%s: poll for header completed with error %d",
817 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
818 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
819 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
821 /* If the poll returns error then we need to do diag reset */
822 kprintf("%s: header read with error; iocstatus = 0x%x\n",
823 __func__, ioc_status);
827 /* We have to do free and alloc for the reply-free and reply-post
828 * counters to match - Need to review the reply FIFO handling.
830 mps_free_command(sc, cm);
832 if ((cm = mps_alloc_command(sc)) == NULL) {
833 kprintf("%s: command alloc failed @ line %d\n", __func__,
838 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
839 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
840 request->Function = MPI2_FUNCTION_CONFIG;
841 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
842 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
843 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
844 request->Header.PageNumber = 0;
845 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
846 request->ExtPageLength = mpi_reply->ExtPageLength;
847 request->PageAddress = htole32(form | handle);
848 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
849 cm->cm_sge = &request->PageBufferSGE;
850 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
851 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
852 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
853 page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
855 kprintf("%s: page alloc failed\n", __func__);
861 error = mps_request_polled(sc, cm);
862 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
863 if (error || (reply == NULL)) {
865 /* If the poll returns error then we need to do diag reset */
866 kprintf("%s: poll for page completed with error %d",
871 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
872 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
873 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
875 /* If the poll returns error then we need to do diag reset */
876 kprintf("%s: page read with error; iocstatus = 0x%x\n",
877 __func__, ioc_status);
881 bcopy(page, config_page, MIN(cm->cm_length,
882 sizeof(Mpi2SasDevicePage0_t)));
886 mps_free_command(sc, cm);
891 * mps_config_get_bios_pg3 - obtain BIOS page 3
892 * @sc: per adapter object
893 * @mpi_reply: reply mf payload returned from firmware
894 * @config_page: contents of the config page
897 * Returns 0 for success, non-zero for failure.
900 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
901 Mpi2BiosPage3_t *config_page)
903 MPI2_CONFIG_REQUEST *request;
904 MPI2_CONFIG_REPLY *reply;
905 struct mps_command *cm;
906 Mpi2BiosPage3_t *page = NULL;
910 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
912 if ((cm = mps_alloc_command(sc)) == NULL) {
913 kprintf("%s: command alloc failed @ line %d\n", __func__,
918 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
919 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
920 request->Function = MPI2_FUNCTION_CONFIG;
921 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
922 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
923 request->Header.PageNumber = 3;
924 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
925 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
927 error = mps_request_polled(sc, cm);
928 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
929 if (error || (reply == NULL)) {
931 /* If the poll returns error then we need to do diag reset */
932 kprintf("%s: poll for header completed with error %d",
937 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
938 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
939 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
941 /* If the poll returns error then we need to do diag reset */
942 kprintf("%s: header read with error; iocstatus = 0x%x\n",
943 __func__, ioc_status);
947 /* We have to do free and alloc for the reply-free and reply-post
948 * counters to match - Need to review the reply FIFO handling.
950 mps_free_command(sc, cm);
952 if ((cm = mps_alloc_command(sc)) == NULL) {
953 kprintf("%s: command alloc failed @ line %d\n", __func__,
958 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
959 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
960 request->Function = MPI2_FUNCTION_CONFIG;
961 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
962 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
963 request->Header.PageNumber = 3;
964 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
965 request->Header.PageLength = mpi_reply->Header.PageLength;
966 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
967 cm->cm_sge = &request->PageBufferSGE;
968 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
969 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
970 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
971 page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
973 kprintf("%s: page alloc failed\n", __func__);
979 error = mps_request_polled(sc, cm);
980 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
981 if (error || (reply == NULL)) {
983 /* If the poll returns error then we need to do diag reset */
984 kprintf("%s: poll for page completed with error %d",
989 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
990 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
991 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
993 /* If the poll returns error then we need to do diag reset */
994 kprintf("%s: page read with error; iocstatus = 0x%x\n",
995 __func__, ioc_status);
999 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1001 kfree(page, M_MPT2);
1003 mps_free_command(sc, cm);
1008 * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1009 * @sc: per adapter object
1010 * @mpi_reply: reply mf payload returned from firmware
1011 * @config_page: contents of the config page
1012 * @page_address: form and handle value used to get page
1015 * Returns 0 for success, non-zero for failure.
1018 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1019 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1021 MPI2_CONFIG_REQUEST *request;
1022 MPI2_CONFIG_REPLY *reply;
1023 struct mps_command *cm;
1024 Mpi2RaidVolPage0_t *page = NULL;
1028 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1030 if ((cm = mps_alloc_command(sc)) == NULL) {
1031 kprintf("%s: command alloc failed @ line %d\n", __func__,
1036 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1037 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1038 request->Function = MPI2_FUNCTION_CONFIG;
1039 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1040 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1041 request->Header.PageNumber = 0;
1042 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1043 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1045 error = mps_request_polled(sc, cm);
1046 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1047 if (error || (reply == NULL)) {
1049 /* If the poll returns error then we need to do diag reset */
1050 kprintf("%s: poll for header completed with error %d",
1055 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1056 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1057 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1059 /* If the poll returns error then we need to do diag reset */
1060 kprintf("%s: header read with error; iocstatus = 0x%x\n",
1061 __func__, ioc_status);
1065 /* We have to do free and alloc for the reply-free and reply-post
1066 * counters to match - Need to review the reply FIFO handling.
1068 mps_free_command(sc, cm);
1070 if ((cm = mps_alloc_command(sc)) == NULL) {
1071 kprintf("%s: command alloc failed @ line %d\n", __func__,
1076 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1077 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1078 request->Function = MPI2_FUNCTION_CONFIG;
1079 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1080 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1081 request->Header.PageNumber = 0;
1082 request->Header.PageLength = mpi_reply->Header.PageLength;
1083 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1084 request->PageAddress = page_address;
1085 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1086 cm->cm_sge = &request->PageBufferSGE;
1087 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1088 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1089 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1090 page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
1092 kprintf("%s: page alloc failed\n", __func__);
1098 error = mps_request_polled(sc, cm);
1099 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1100 if (error || (reply == NULL)) {
1102 /* If the poll returns error then we need to do diag reset */
1103 kprintf("%s: poll for page completed with error %d",
1108 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1109 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1110 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1112 /* If the poll returns error then we need to do diag reset */
1113 kprintf("%s: page read with error; iocstatus = 0x%x\n",
1114 __func__, ioc_status);
1118 bcopy(page, config_page, cm->cm_length);
1120 kfree(page, M_MPT2);
1122 mps_free_command(sc, cm);
1127 * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1128 * @sc: per adapter object
1129 * @mpi_reply: reply mf payload returned from firmware
1130 * @config_page: contents of the config page
1131 * @form: GET_NEXT_HANDLE or HANDLE
1132 * @handle: volume handle
1135 * Returns 0 for success, non-zero for failure.
1138 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1139 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1141 MPI2_CONFIG_REQUEST *request;
1142 MPI2_CONFIG_REPLY *reply;
1143 struct mps_command *cm;
1144 Mpi2RaidVolPage1_t *page = NULL;
1148 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1150 if ((cm = mps_alloc_command(sc)) == NULL) {
1151 kprintf("%s: command alloc failed @ line %d\n", __func__,
1156 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1157 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1158 request->Function = MPI2_FUNCTION_CONFIG;
1159 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1160 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1161 request->Header.PageNumber = 1;
1162 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1163 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1165 error = mps_request_polled(sc, cm);
1166 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1167 if (error || (reply == NULL)) {
1169 /* If the poll returns error then we need to do diag reset */
1170 kprintf("%s: poll for header completed with error %d",
1175 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1176 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1177 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1179 /* If the poll returns error then we need to do diag reset */
1180 kprintf("%s: header read with error; iocstatus = 0x%x\n",
1181 __func__, ioc_status);
1185 /* We have to do free and alloc for the reply-free and reply-post
1186 * counters to match - Need to review the reply FIFO handling.
1188 mps_free_command(sc, cm);
1190 if ((cm = mps_alloc_command(sc)) == NULL) {
1191 kprintf("%s: command alloc failed @ line %d\n", __func__,
1196 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1197 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1198 request->Function = MPI2_FUNCTION_CONFIG;
1199 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1200 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1201 request->Header.PageNumber = 1;
1202 request->Header.PageLength = mpi_reply->Header.PageLength;
1203 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1204 request->PageAddress = htole32(form | handle);
1205 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1206 cm->cm_sge = &request->PageBufferSGE;
1207 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1208 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1209 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1210 page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
1212 kprintf("%s: page alloc failed\n", __func__);
1218 error = mps_request_polled(sc, cm);
1219 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1220 if (error || (reply == NULL)) {
1222 /* If the poll returns error then we need to do diag reset */
1223 kprintf("%s: poll for page completed with error %d",
1228 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1229 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1230 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1232 /* If the poll returns error then we need to do diag reset */
1233 kprintf("%s: page read with error; iocstatus = 0x%x\n",
1234 __func__, ioc_status);
1238 bcopy(page, config_page, MIN(cm->cm_length,
1239 sizeof(Mpi2RaidVolPage1_t)));
1241 kfree(page, M_MPT2);
1243 mps_free_command(sc, cm);
1248 * mps_config_get_volume_wwid - returns wwid given the volume handle
1249 * @sc: per adapter object
1250 * @volume_handle: volume handle
1251 * @wwid: volume wwid
1254 * Returns 0 for success, non-zero for failure.
1257 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1259 Mpi2ConfigReply_t mpi_reply;
1260 Mpi2RaidVolPage1_t raid_vol_pg1;
1263 if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1264 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1265 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1266 raid_vol_pg1.WWID.Low);
1273 * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1274 * @sc: per adapter object
1275 * @mpi_reply: reply mf payload returned from firmware
1276 * @config_page: contents of the config page
1277 * @page_address: form and handle value used to get page
1280 * Returns 0 for success, non-zero for failure.
1283 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1284 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1286 MPI2_CONFIG_REQUEST *request;
1287 MPI2_CONFIG_REPLY *reply;
1288 struct mps_command *cm;
1289 Mpi2RaidPhysDiskPage0_t *page = NULL;
1293 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1295 if ((cm = mps_alloc_command(sc)) == NULL) {
1296 kprintf("%s: command alloc failed @ line %d\n", __func__,
1301 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1302 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1303 request->Function = MPI2_FUNCTION_CONFIG;
1304 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1305 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1306 request->Header.PageNumber = 0;
1307 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1308 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1310 error = mps_request_polled(sc, cm);
1311 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1312 if (error || (reply == NULL)) {
1314 /* If the poll returns error then we need to do diag reset */
1315 kprintf("%s: poll for header completed with error %d",
1320 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1321 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1322 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1324 /* If the poll returns error then we need to do diag reset */
1325 kprintf("%s: header read with error; iocstatus = 0x%x\n",
1326 __func__, ioc_status);
1330 /* We have to do free and alloc for the reply-free and reply-post
1331 * counters to match - Need to review the reply FIFO handling.
1333 mps_free_command(sc, cm);
1335 if ((cm = mps_alloc_command(sc)) == NULL) {
1336 kprintf("%s: command alloc failed @ line %d\n", __func__,
1341 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1342 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1343 request->Function = MPI2_FUNCTION_CONFIG;
1344 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1345 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1346 request->Header.PageNumber = 0;
1347 request->Header.PageLength = mpi_reply->Header.PageLength;
1348 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1349 request->PageAddress = page_address;
1350 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1351 cm->cm_sge = &request->PageBufferSGE;
1352 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1353 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1354 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1355 page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
1357 kprintf("%s: page alloc failed\n", __func__);
1363 error = mps_request_polled(sc, cm);
1364 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1365 if (error || (reply == NULL)) {
1367 /* If the poll returns error then we need to do diag reset */
1368 kprintf("%s: poll for page completed with error %d",
1373 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1374 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1375 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1377 /* If the poll returns error then we need to do diag reset */
1378 kprintf("%s: page read with error; iocstatus = 0x%x\n",
1379 __func__, ioc_status);
1383 bcopy(page, config_page, MIN(cm->cm_length,
1384 sizeof(Mpi2RaidPhysDiskPage0_t)));
1386 kfree(page, M_MPT2);
1388 mps_free_command(sc, cm);