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