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