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