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