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