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