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