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