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 guarantee 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 ((le16toh(mpi_reply.IOCStatus) & 503 MPI2_IOCSTATUS_MASK) != 504 MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) { 505 mps_dprint(sc, MPS_FAULT, 506 "Multiple RAID Volume Page0! Direct Drive " 507 "I/O will not be used.\n"); 508 goto out; 509 } 510 } else { 511 mps_dprint(sc, MPS_FAULT, 512 "Multiple volumes! Direct Drive I/O will not be " 513 "used.\n"); 514 goto out; 515 } 516 517 /* 518 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume. 519 */ 520 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 521 phys_disk_page_address = 522 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM + 523 sc->DD_column_map[index].phys_disk_num; 524 if (mps_config_get_raid_pd_pg0(sc, &mpi_reply, 525 &phys_disk_pg0, phys_disk_page_address)) { 526 mps_dprint(sc, MPS_FAULT, 527 "mps_config_get_raid_pd_pg0 failed! Direct " 528 "Drive I/O will not be used.\n"); 529 goto out; 530 } 531 if (phys_disk_pg0.DevHandle == 0xFFFF) { 532 mps_dprint(sc, MPS_FAULT, 533 "Invalid Phys Disk DevHandle! Direct Drive " 534 "I/O will not be used.\n"); 535 goto out; 536 } 537 sc->DD_column_map[index].dev_handle = 538 phys_disk_pg0.DevHandle; 539 } 540 sc->WD_valid_config = TRUE; 541 out: 542 if (raid_vol_pg0) 543 free(raid_vol_pg0, M_MPT2); 544 } 545 } 546 547 /** 548 * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0 549 * @sc: per adapter object 550 * @mpi_reply: reply mf payload returned from firmware 551 * @config_page: contents of the config page 552 * @sz: size of buffer passed in config_page 553 * Context: sleep. 554 * 555 * Returns 0 for success, non-zero for failure. 556 */ 557 int 558 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 559 Mpi2DriverMappingPage0_t *config_page, u16 sz) 560 { 561 MPI2_CONFIG_REQUEST *request; 562 MPI2_CONFIG_REPLY *reply; 563 struct mps_command *cm; 564 Mpi2DriverMappingPage0_t *page = NULL; 565 int error = 0; 566 u16 ioc_status; 567 568 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 569 570 memset(config_page, 0, sz); 571 if ((cm = mps_alloc_command(sc)) == NULL) { 572 printf("%s: command alloc failed @ line %d\n", __func__, 573 __LINE__); 574 error = EBUSY; 575 goto out; 576 } 577 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 578 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 579 request->Function = MPI2_FUNCTION_CONFIG; 580 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 581 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 582 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 583 request->Header.PageNumber = 0; 584 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 585 request->PageAddress = sc->max_dpm_entries << 586 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 587 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 588 cm->cm_data = NULL; 589 error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 590 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 591 if (error || (reply == NULL)) { 592 /* FIXME */ 593 /* 594 * If the request returns an error then we need to do a diag 595 * reset 596 */ 597 printf("%s: request for header completed with error %d", 598 __func__, error); 599 error = ENXIO; 600 goto out; 601 } 602 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 603 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 604 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 605 /* FIXME */ 606 /* 607 * If the request returns an error then we need to do a diag 608 * reset 609 */ 610 printf("%s: header read with error; iocstatus = 0x%x\n", 611 __func__, ioc_status); 612 error = ENXIO; 613 goto out; 614 } 615 /* We have to do free and alloc for the reply-free and reply-post 616 * counters to match - Need to review the reply FIFO handling. 617 */ 618 mps_free_command(sc, cm); 619 620 if ((cm = mps_alloc_command(sc)) == NULL) { 621 printf("%s: command alloc failed @ line %d\n", __func__, 622 __LINE__); 623 error = EBUSY; 624 goto out; 625 } 626 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 627 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 628 request->Function = MPI2_FUNCTION_CONFIG; 629 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM; 630 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 631 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 632 request->Header.PageNumber = 0; 633 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 634 request->PageAddress = sc->max_dpm_entries << 635 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 636 request->ExtPageLength = mpi_reply->ExtPageLength; 637 cm->cm_length = le16toh(request->ExtPageLength) * 4; 638 cm->cm_sge = &request->PageBufferSGE; 639 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 640 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 641 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 642 page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT); 643 if (!page) { 644 printf("%s: page alloc failed\n", __func__); 645 error = ENOMEM; 646 goto out; 647 } 648 cm->cm_data = page; 649 error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 650 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 651 if (error || (reply == NULL)) { 652 /* FIXME */ 653 /* 654 * If the request returns an error then we need to do a diag 655 * reset 656 */ 657 printf("%s: request for page completed with error %d", 658 __func__, error); 659 error = ENXIO; 660 goto out; 661 } 662 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 663 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 664 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 665 /* FIXME */ 666 /* 667 * If the request returns an error then we need to do a diag 668 * reset 669 */ 670 printf("%s: page read with error; iocstatus = 0x%x\n", 671 __func__, ioc_status); 672 error = ENXIO; 673 goto out; 674 } 675 bcopy(page, config_page, MIN(cm->cm_length, sz)); 676 out: 677 free(page, M_MPT2); 678 if (cm) 679 mps_free_command(sc, cm); 680 return (error); 681 } 682 683 /** 684 * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0 685 * @sc: per adapter object 686 * @mpi_reply: reply mf payload returned from firmware 687 * @config_page: contents of the config page 688 * @entry_idx: entry index in DPM Page0 to be modified 689 * Context: sleep. 690 * 691 * Returns 0 for success, non-zero for failure. 692 */ 693 694 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 695 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx) 696 { 697 MPI2_CONFIG_REQUEST *request; 698 MPI2_CONFIG_REPLY *reply; 699 struct mps_command *cm; 700 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 701 int error = 0; 702 u16 ioc_status; 703 704 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 705 706 if ((cm = mps_alloc_command(sc)) == NULL) { 707 printf("%s: command alloc failed @ line %d\n", __func__, 708 __LINE__); 709 error = EBUSY; 710 goto out; 711 } 712 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 713 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 714 request->Function = MPI2_FUNCTION_CONFIG; 715 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 716 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 717 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 718 request->Header.PageNumber = 0; 719 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 720 /* We can remove below two lines ????*/ 721 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 722 request->PageAddress |= htole16(entry_idx); 723 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 724 cm->cm_data = NULL; 725 error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 726 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 727 if (error || (reply == NULL)) { 728 /* FIXME */ 729 /* 730 * If the request returns an error then we need to do a diag 731 * reset 732 */ 733 printf("%s: request for header completed with error %d", 734 __func__, error); 735 error = ENXIO; 736 goto out; 737 } 738 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 739 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 740 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 741 /* FIXME */ 742 /* 743 * If the request returns an error then we need to do a diag 744 * reset 745 */ 746 printf("%s: header read with error; iocstatus = 0x%x\n", 747 __func__, ioc_status); 748 error = ENXIO; 749 goto out; 750 } 751 /* We have to do free and alloc for the reply-free and reply-post 752 * counters to match - Need to review the reply FIFO handling. 753 */ 754 mps_free_command(sc, cm); 755 756 if ((cm = mps_alloc_command(sc)) == NULL) { 757 printf("%s: command alloc failed @ line %d\n", __func__, 758 __LINE__); 759 error = EBUSY; 760 goto out; 761 } 762 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 763 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 764 request->Function = MPI2_FUNCTION_CONFIG; 765 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 766 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 767 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 768 request->Header.PageNumber = 0; 769 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 770 request->ExtPageLength = mpi_reply->ExtPageLength; 771 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 772 request->PageAddress |= htole16(entry_idx); 773 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 774 cm->cm_sge = &request->PageBufferSGE; 775 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 776 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT; 777 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 778 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 779 if (!page) { 780 printf("%s: page alloc failed\n", __func__); 781 error = ENOMEM; 782 goto out; 783 } 784 bcopy(config_page, page, MIN(cm->cm_length, 785 (sizeof(Mpi2DriverMappingPage0_t)))); 786 cm->cm_data = page; 787 error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 788 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 789 if (error || (reply == NULL)) { 790 /* FIXME */ 791 /* 792 * If the request returns an error then we need to do a diag 793 * reset 794 */ 795 printf("%s: request to write page completed with error %d", 796 __func__, error); 797 error = ENXIO; 798 goto out; 799 } 800 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 801 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 802 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 803 /* FIXME */ 804 /* 805 * If the request returns an error then we need to do a diag 806 * reset 807 */ 808 printf("%s: page written with error; iocstatus = 0x%x\n", 809 __func__, ioc_status); 810 error = ENXIO; 811 goto out; 812 } 813 out: 814 free(page, M_MPT2); 815 if (cm) 816 mps_free_command(sc, cm); 817 return (error); 818 } 819 820 /** 821 * mps_config_get_sas_device_pg0 - obtain sas device page 0 822 * @sc: per adapter object 823 * @mpi_reply: reply mf payload returned from firmware 824 * @config_page: contents of the config page 825 * @form: GET_NEXT_HANDLE or HANDLE 826 * @handle: device handle 827 * Context: sleep. 828 * 829 * Returns 0 for success, non-zero for failure. 830 */ 831 int 832 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 833 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) 834 { 835 MPI2_CONFIG_REQUEST *request; 836 MPI2_CONFIG_REPLY *reply; 837 struct mps_command *cm; 838 Mpi2SasDevicePage0_t *page = NULL; 839 int error = 0; 840 u16 ioc_status; 841 842 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 843 844 if ((cm = mps_alloc_command(sc)) == NULL) { 845 printf("%s: command alloc failed @ line %d\n", __func__, 846 __LINE__); 847 error = EBUSY; 848 goto out; 849 } 850 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 851 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 852 request->Function = MPI2_FUNCTION_CONFIG; 853 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 854 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 855 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 856 request->Header.PageNumber = 0; 857 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 858 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 859 cm->cm_data = NULL; 860 error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 861 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 862 if (error || (reply == NULL)) { 863 /* FIXME */ 864 /* 865 * If the request returns an error then we need to do a diag 866 * reset 867 */ 868 printf("%s: request for header completed with error %d", 869 __func__, error); 870 error = ENXIO; 871 goto out; 872 } 873 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 874 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 875 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 876 /* FIXME */ 877 /* 878 * If the request returns an error then we need to do a diag 879 * reset 880 */ 881 printf("%s: header read with error; iocstatus = 0x%x\n", 882 __func__, ioc_status); 883 error = ENXIO; 884 goto out; 885 } 886 /* We have to do free and alloc for the reply-free and reply-post 887 * counters to match - Need to review the reply FIFO handling. 888 */ 889 mps_free_command(sc, cm); 890 891 if ((cm = mps_alloc_command(sc)) == NULL) { 892 printf("%s: command alloc failed @ line %d\n", __func__, 893 __LINE__); 894 error = EBUSY; 895 goto out; 896 } 897 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 898 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 899 request->Function = MPI2_FUNCTION_CONFIG; 900 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 901 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 902 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 903 request->Header.PageNumber = 0; 904 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 905 request->ExtPageLength = mpi_reply->ExtPageLength; 906 request->PageAddress = htole32(form | handle); 907 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 908 cm->cm_sge = &request->PageBufferSGE; 909 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 910 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 911 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 912 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 913 if (!page) { 914 printf("%s: page alloc failed\n", __func__); 915 error = ENOMEM; 916 goto out; 917 } 918 cm->cm_data = page; 919 920 error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 921 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 922 if (error || (reply == NULL)) { 923 /* FIXME */ 924 /* 925 * If the request returns an error then we need to do a diag 926 * reset 927 */ 928 printf("%s: request for page completed with error %d", 929 __func__, error); 930 error = ENXIO; 931 goto out; 932 } 933 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 934 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 935 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 936 /* FIXME */ 937 /* 938 * If the request returns an error then we need to do a diag 939 * reset 940 */ 941 printf("%s: page read with error; iocstatus = 0x%x\n", 942 __func__, ioc_status); 943 error = ENXIO; 944 goto out; 945 } 946 bcopy(page, config_page, MIN(cm->cm_length, 947 sizeof(Mpi2SasDevicePage0_t))); 948 out: 949 free(page, M_MPT2); 950 if (cm) 951 mps_free_command(sc, cm); 952 return (error); 953 } 954 955 /** 956 * mps_config_get_bios_pg3 - obtain BIOS page 3 957 * @sc: per adapter object 958 * @mpi_reply: reply mf payload returned from firmware 959 * @config_page: contents of the config page 960 * Context: sleep. 961 * 962 * Returns 0 for success, non-zero for failure. 963 */ 964 int 965 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 966 Mpi2BiosPage3_t *config_page) 967 { 968 MPI2_CONFIG_REQUEST *request; 969 MPI2_CONFIG_REPLY *reply; 970 struct mps_command *cm; 971 Mpi2BiosPage3_t *page = NULL; 972 int error = 0; 973 u16 ioc_status; 974 975 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 976 977 if ((cm = mps_alloc_command(sc)) == NULL) { 978 printf("%s: command alloc failed @ line %d\n", __func__, 979 __LINE__); 980 error = EBUSY; 981 goto out; 982 } 983 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 984 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 985 request->Function = MPI2_FUNCTION_CONFIG; 986 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 987 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 988 request->Header.PageNumber = 3; 989 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 990 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 991 cm->cm_data = NULL; 992 error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 993 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 994 if (error || (reply == NULL)) { 995 /* FIXME */ 996 /* 997 * If the request returns an error then we need to do a diag 998 * reset 999 */ 1000 printf("%s: request for header completed with error %d", 1001 __func__, error); 1002 error = ENXIO; 1003 goto out; 1004 } 1005 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1006 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1007 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1008 /* FIXME */ 1009 /* 1010 * If the request returns an error then we need to do a diag 1011 * reset 1012 */ 1013 printf("%s: header read with error; iocstatus = 0x%x\n", 1014 __func__, ioc_status); 1015 error = ENXIO; 1016 goto out; 1017 } 1018 /* We have to do free and alloc for the reply-free and reply-post 1019 * counters to match - Need to review the reply FIFO handling. 1020 */ 1021 mps_free_command(sc, cm); 1022 1023 if ((cm = mps_alloc_command(sc)) == NULL) { 1024 printf("%s: command alloc failed @ line %d\n", __func__, 1025 __LINE__); 1026 error = EBUSY; 1027 goto out; 1028 } 1029 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1030 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1031 request->Function = MPI2_FUNCTION_CONFIG; 1032 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1033 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1034 request->Header.PageNumber = 3; 1035 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 1036 request->Header.PageLength = mpi_reply->Header.PageLength; 1037 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1038 cm->cm_sge = &request->PageBufferSGE; 1039 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1040 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1041 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1042 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1043 if (!page) { 1044 printf("%s: page alloc failed\n", __func__); 1045 error = ENOMEM; 1046 goto out; 1047 } 1048 cm->cm_data = page; 1049 1050 error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1051 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1052 if (error || (reply == NULL)) { 1053 /* FIXME */ 1054 /* 1055 * If the request returns an error then we need to do a diag 1056 * reset 1057 */ 1058 printf("%s: request for page completed with error %d", 1059 __func__, error); 1060 error = ENXIO; 1061 goto out; 1062 } 1063 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1064 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1065 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1066 /* FIXME */ 1067 /* 1068 * If the request returns an error then we need to do a diag 1069 * reset 1070 */ 1071 printf("%s: page read with error; iocstatus = 0x%x\n", 1072 __func__, ioc_status); 1073 error = ENXIO; 1074 goto out; 1075 } 1076 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t))); 1077 out: 1078 free(page, M_MPT2); 1079 if (cm) 1080 mps_free_command(sc, cm); 1081 return (error); 1082 } 1083 1084 /** 1085 * mps_config_get_raid_volume_pg0 - obtain raid volume page 0 1086 * @sc: per adapter object 1087 * @mpi_reply: reply mf payload returned from firmware 1088 * @config_page: contents of the config page 1089 * @page_address: form and handle value used to get page 1090 * Context: sleep. 1091 * 1092 * Returns 0 for success, non-zero for failure. 1093 */ 1094 int 1095 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 1096 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) 1097 { 1098 MPI2_CONFIG_REQUEST *request; 1099 MPI2_CONFIG_REPLY *reply; 1100 struct mps_command *cm; 1101 Mpi2RaidVolPage0_t *page = NULL; 1102 int error = 0; 1103 u16 ioc_status; 1104 1105 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1106 1107 if ((cm = mps_alloc_command(sc)) == NULL) { 1108 printf("%s: command alloc failed @ line %d\n", __func__, 1109 __LINE__); 1110 error = EBUSY; 1111 goto out; 1112 } 1113 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1114 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1115 request->Function = MPI2_FUNCTION_CONFIG; 1116 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1117 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1118 request->Header.PageNumber = 0; 1119 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1120 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1121 cm->cm_data = NULL; 1122 1123 /* 1124 * This page must be polled because the IOC isn't ready yet when this 1125 * page is needed. 1126 */ 1127 error = mps_wait_command(sc, cm, 60, 0); 1128 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1129 if (error || (reply == NULL)) { 1130 /* FIXME */ 1131 /* If the poll returns error then we need to do diag reset */ 1132 printf("%s: poll for header completed with error %d", 1133 __func__, error); 1134 error = ENXIO; 1135 goto out; 1136 } 1137 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1138 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1139 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1140 /* FIXME */ 1141 /* If the poll returns error then we need to do diag reset */ 1142 printf("%s: header read with error; iocstatus = 0x%x\n", 1143 __func__, ioc_status); 1144 error = ENXIO; 1145 goto out; 1146 } 1147 /* We have to do free and alloc for the reply-free and reply-post 1148 * counters to match - Need to review the reply FIFO handling. 1149 */ 1150 mps_free_command(sc, cm); 1151 1152 if ((cm = mps_alloc_command(sc)) == NULL) { 1153 printf("%s: command alloc failed @ line %d\n", __func__, 1154 __LINE__); 1155 error = EBUSY; 1156 goto out; 1157 } 1158 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1159 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1160 request->Function = MPI2_FUNCTION_CONFIG; 1161 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1162 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1163 request->Header.PageNumber = 0; 1164 request->Header.PageLength = mpi_reply->Header.PageLength; 1165 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1166 request->PageAddress = page_address; 1167 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1168 cm->cm_sge = &request->PageBufferSGE; 1169 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1170 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1171 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1172 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1173 if (!page) { 1174 printf("%s: page alloc failed\n", __func__); 1175 error = ENOMEM; 1176 goto out; 1177 } 1178 cm->cm_data = page; 1179 1180 /* 1181 * This page must be polled because the IOC isn't ready yet when this 1182 * page is needed. 1183 */ 1184 error = mps_wait_command(sc, cm, 60, 0); 1185 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1186 if (error || (reply == NULL)) { 1187 /* FIXME */ 1188 /* If the poll returns error then we need to do diag reset */ 1189 printf("%s: poll for page completed with error %d", 1190 __func__, error); 1191 error = ENXIO; 1192 goto out; 1193 } 1194 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1195 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1196 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1197 /* FIXME */ 1198 /* If the poll returns error then we need to do diag reset */ 1199 printf("%s: page read with error; iocstatus = 0x%x\n", 1200 __func__, ioc_status); 1201 error = ENXIO; 1202 goto out; 1203 } 1204 bcopy(page, config_page, cm->cm_length); 1205 out: 1206 free(page, M_MPT2); 1207 if (cm) 1208 mps_free_command(sc, cm); 1209 return (error); 1210 } 1211 1212 /** 1213 * mps_config_get_raid_volume_pg1 - obtain raid volume page 1 1214 * @sc: per adapter object 1215 * @mpi_reply: reply mf payload returned from firmware 1216 * @config_page: contents of the config page 1217 * @form: GET_NEXT_HANDLE or HANDLE 1218 * @handle: volume handle 1219 * Context: sleep. 1220 * 1221 * Returns 0 for success, non-zero for failure. 1222 */ 1223 int 1224 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t 1225 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) 1226 { 1227 MPI2_CONFIG_REQUEST *request; 1228 MPI2_CONFIG_REPLY *reply; 1229 struct mps_command *cm; 1230 Mpi2RaidVolPage1_t *page = NULL; 1231 int error = 0; 1232 u16 ioc_status; 1233 1234 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1235 1236 if ((cm = mps_alloc_command(sc)) == NULL) { 1237 printf("%s: command alloc failed @ line %d\n", __func__, 1238 __LINE__); 1239 error = EBUSY; 1240 goto out; 1241 } 1242 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1243 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1244 request->Function = MPI2_FUNCTION_CONFIG; 1245 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1246 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1247 request->Header.PageNumber = 1; 1248 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; 1249 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1250 cm->cm_data = NULL; 1251 error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1252 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1253 if (error || (reply == NULL)) { 1254 /* FIXME */ 1255 /* 1256 * If the request returns an error then we need to do a diag 1257 * reset 1258 */ 1259 printf("%s: request for header completed with error %d", 1260 __func__, error); 1261 error = ENXIO; 1262 goto out; 1263 } 1264 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1265 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1266 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1267 /* FIXME */ 1268 /* 1269 * If the request returns an error then we need to do a diag 1270 * reset 1271 */ 1272 printf("%s: header read with error; iocstatus = 0x%x\n", 1273 __func__, ioc_status); 1274 error = ENXIO; 1275 goto out; 1276 } 1277 /* We have to do free and alloc for the reply-free and reply-post 1278 * counters to match - Need to review the reply FIFO handling. 1279 */ 1280 mps_free_command(sc, cm); 1281 1282 if ((cm = mps_alloc_command(sc)) == NULL) { 1283 printf("%s: command alloc failed @ line %d\n", __func__, 1284 __LINE__); 1285 error = EBUSY; 1286 goto out; 1287 } 1288 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1289 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1290 request->Function = MPI2_FUNCTION_CONFIG; 1291 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1292 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1293 request->Header.PageNumber = 1; 1294 request->Header.PageLength = mpi_reply->Header.PageLength; 1295 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1296 request->PageAddress = htole32(form | handle); 1297 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1298 cm->cm_sge = &request->PageBufferSGE; 1299 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1300 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1301 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1302 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1303 if (!page) { 1304 printf("%s: page alloc failed\n", __func__); 1305 error = ENOMEM; 1306 goto out; 1307 } 1308 cm->cm_data = page; 1309 1310 error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1311 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1312 if (error || (reply == NULL)) { 1313 /* FIXME */ 1314 /* 1315 * If the request returns an error then we need to do a diag 1316 * reset 1317 */ 1318 printf("%s: request for page completed with error %d", 1319 __func__, error); 1320 error = ENXIO; 1321 goto out; 1322 } 1323 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1324 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1325 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1326 /* FIXME */ 1327 /* 1328 * If the request returns an error then we need to do a diag 1329 * reset 1330 */ 1331 printf("%s: page read with error; iocstatus = 0x%x\n", 1332 __func__, ioc_status); 1333 error = ENXIO; 1334 goto out; 1335 } 1336 bcopy(page, config_page, MIN(cm->cm_length, 1337 sizeof(Mpi2RaidVolPage1_t))); 1338 out: 1339 free(page, M_MPT2); 1340 if (cm) 1341 mps_free_command(sc, cm); 1342 return (error); 1343 } 1344 1345 /** 1346 * mps_config_get_volume_wwid - returns wwid given the volume handle 1347 * @sc: per adapter object 1348 * @volume_handle: volume handle 1349 * @wwid: volume wwid 1350 * Context: sleep. 1351 * 1352 * Returns 0 for success, non-zero for failure. 1353 */ 1354 int 1355 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid) 1356 { 1357 Mpi2ConfigReply_t mpi_reply; 1358 Mpi2RaidVolPage1_t raid_vol_pg1; 1359 1360 *wwid = 0; 1361 if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1, 1362 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) { 1363 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 | 1364 raid_vol_pg1.WWID.Low); 1365 return 0; 1366 } else 1367 return -1; 1368 } 1369 1370 /** 1371 * mps_config_get_pd_pg0 - obtain raid phys disk page 0 1372 * @sc: per adapter object 1373 * @mpi_reply: reply mf payload returned from firmware 1374 * @config_page: contents of the config page 1375 * @page_address: form and handle value used to get page 1376 * Context: sleep. 1377 * 1378 * Returns 0 for success, non-zero for failure. 1379 */ 1380 int 1381 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1382 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) 1383 { 1384 MPI2_CONFIG_REQUEST *request; 1385 MPI2_CONFIG_REPLY *reply; 1386 struct mps_command *cm; 1387 Mpi2RaidPhysDiskPage0_t *page = NULL; 1388 int error = 0; 1389 u16 ioc_status; 1390 1391 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1392 1393 if ((cm = mps_alloc_command(sc)) == NULL) { 1394 printf("%s: command alloc failed @ line %d\n", __func__, 1395 __LINE__); 1396 error = EBUSY; 1397 goto out; 1398 } 1399 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1400 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1401 request->Function = MPI2_FUNCTION_CONFIG; 1402 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1403 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1404 request->Header.PageNumber = 0; 1405 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; 1406 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1407 cm->cm_data = NULL; 1408 1409 /* 1410 * This page must be polled because the IOC isn't ready yet when this 1411 * page is needed. 1412 */ 1413 error = mps_wait_command(sc, cm, 60, 0); 1414 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1415 if (error || (reply == NULL)) { 1416 /* FIXME */ 1417 /* If the poll returns error then we need to do diag reset */ 1418 printf("%s: poll for header completed with error %d", 1419 __func__, error); 1420 error = ENXIO; 1421 goto out; 1422 } 1423 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1424 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1425 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1426 /* FIXME */ 1427 /* If the poll returns error then we need to do diag reset */ 1428 printf("%s: header read with error; iocstatus = 0x%x\n", 1429 __func__, ioc_status); 1430 error = ENXIO; 1431 goto out; 1432 } 1433 /* We have to do free and alloc for the reply-free and reply-post 1434 * counters to match - Need to review the reply FIFO handling. 1435 */ 1436 mps_free_command(sc, cm); 1437 1438 if ((cm = mps_alloc_command(sc)) == NULL) { 1439 printf("%s: command alloc failed @ line %d\n", __func__, 1440 __LINE__); 1441 error = EBUSY; 1442 goto out; 1443 } 1444 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1445 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1446 request->Function = MPI2_FUNCTION_CONFIG; 1447 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1448 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1449 request->Header.PageNumber = 0; 1450 request->Header.PageLength = mpi_reply->Header.PageLength; 1451 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1452 request->PageAddress = page_address; 1453 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1454 cm->cm_sge = &request->PageBufferSGE; 1455 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1456 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1457 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1458 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1459 if (!page) { 1460 printf("%s: page alloc failed\n", __func__); 1461 error = ENOMEM; 1462 goto out; 1463 } 1464 cm->cm_data = page; 1465 1466 /* 1467 * This page must be polled because the IOC isn't ready yet when this 1468 * page is needed. 1469 */ 1470 error = mps_wait_command(sc, cm, 60, 0); 1471 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1472 if (error || (reply == NULL)) { 1473 /* FIXME */ 1474 /* If the poll returns error then we need to do diag reset */ 1475 printf("%s: poll for page completed with error %d", 1476 __func__, error); 1477 error = ENXIO; 1478 goto out; 1479 } 1480 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1481 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1482 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1483 /* FIXME */ 1484 /* If the poll returns error then we need to do diag reset */ 1485 printf("%s: page read with error; iocstatus = 0x%x\n", 1486 __func__, ioc_status); 1487 error = ENXIO; 1488 goto out; 1489 } 1490 bcopy(page, config_page, MIN(cm->cm_length, 1491 sizeof(Mpi2RaidPhysDiskPage0_t))); 1492 out: 1493 free(page, M_MPT2); 1494 if (cm) 1495 mps_free_command(sc, cm); 1496 return (error); 1497 } 1498