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