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