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