1 /* 2 * This module provides common API for accessing firmware configuration pages 3 * 4 * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c 5 * Copyright (C) 2012-2014 LSI Corporation 6 * Copyright (C) 2013-2014 Avago Technologies 7 * (mailto: MPT-FusionLinux.pdl@avagotech.com) 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * as published by the Free Software Foundation; either version 2 12 * of the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * NO WARRANTY 20 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR 21 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT 22 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 23 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is 24 * solely responsible for determining the appropriateness of using and 25 * distributing the Program and assumes all risks associated with its 26 * exercise of rights under this Agreement, including but not limited to 27 * the risks and costs of program errors, damage to or loss of data, 28 * programs or equipment, and unavailability or interruption of operations. 29 30 * DISCLAIMER OF LIABILITY 31 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY 32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND 34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 36 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED 37 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES 38 39 * You should have received a copy of the GNU General Public License 40 * along with this program; if not, write to the Free Software 41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 42 * USA. 43 */ 44 45 #include <linux/module.h> 46 #include <linux/kernel.h> 47 #include <linux/init.h> 48 #include <linux/errno.h> 49 #include <linux/blkdev.h> 50 #include <linux/sched.h> 51 #include <linux/workqueue.h> 52 #include <linux/delay.h> 53 #include <linux/pci.h> 54 55 #include "mpt3sas_base.h" 56 57 /* local definitions */ 58 59 /* Timeout for config page request (in seconds) */ 60 #define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15 61 62 /* Common sgl flags for READING a config page. */ 63 #define MPT3_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ 64 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ 65 | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT) 66 67 /* Common sgl flags for WRITING a config page. */ 68 #define MPT3_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ 69 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ 70 | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \ 71 << MPI2_SGE_FLAGS_SHIFT) 72 73 /** 74 * struct config_request - obtain dma memory via routine 75 * @sz: size 76 * @page: virt pointer 77 * @page_dma: phys pointer 78 * 79 */ 80 struct config_request { 81 u16 sz; 82 void *page; 83 dma_addr_t page_dma; 84 }; 85 86 /** 87 * _config_display_some_debug - debug routine 88 * @ioc: per adapter object 89 * @smid: system request message index 90 * @calling_function_name: string pass from calling function 91 * @mpi_reply: reply message frame 92 * Context: none. 93 * 94 * Function for displaying debug info helpful when debugging issues 95 * in this module. 96 */ 97 static void 98 _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, 99 char *calling_function_name, MPI2DefaultReply_t *mpi_reply) 100 { 101 Mpi2ConfigRequest_t *mpi_request; 102 char *desc = NULL; 103 104 if (!(ioc->logging_level & MPT_DEBUG_CONFIG)) 105 return; 106 107 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); 108 switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) { 109 case MPI2_CONFIG_PAGETYPE_IO_UNIT: 110 desc = "io_unit"; 111 break; 112 case MPI2_CONFIG_PAGETYPE_IOC: 113 desc = "ioc"; 114 break; 115 case MPI2_CONFIG_PAGETYPE_BIOS: 116 desc = "bios"; 117 break; 118 case MPI2_CONFIG_PAGETYPE_RAID_VOLUME: 119 desc = "raid_volume"; 120 break; 121 case MPI2_CONFIG_PAGETYPE_MANUFACTURING: 122 desc = "manufaucturing"; 123 break; 124 case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK: 125 desc = "physdisk"; 126 break; 127 case MPI2_CONFIG_PAGETYPE_EXTENDED: 128 switch (mpi_request->ExtPageType) { 129 case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT: 130 desc = "sas_io_unit"; 131 break; 132 case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER: 133 desc = "sas_expander"; 134 break; 135 case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE: 136 desc = "sas_device"; 137 break; 138 case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY: 139 desc = "sas_phy"; 140 break; 141 case MPI2_CONFIG_EXTPAGETYPE_LOG: 142 desc = "log"; 143 break; 144 case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE: 145 desc = "enclosure"; 146 break; 147 case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG: 148 desc = "raid_config"; 149 break; 150 case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING: 151 desc = "driver_mapping"; 152 break; 153 case MPI2_CONFIG_EXTPAGETYPE_SAS_PORT: 154 desc = "sas_port"; 155 break; 156 case MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING: 157 desc = "ext_manufacturing"; 158 break; 159 case MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT: 160 desc = "pcie_io_unit"; 161 break; 162 case MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH: 163 desc = "pcie_switch"; 164 break; 165 case MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE: 166 desc = "pcie_device"; 167 break; 168 case MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK: 169 desc = "pcie_link"; 170 break; 171 } 172 break; 173 } 174 175 if (!desc) 176 return; 177 178 pr_info(MPT3SAS_FMT 179 "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n", 180 ioc->name, calling_function_name, desc, 181 mpi_request->Header.PageNumber, mpi_request->Action, 182 le32_to_cpu(mpi_request->PageAddress), smid); 183 184 if (!mpi_reply) 185 return; 186 187 if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) 188 pr_info(MPT3SAS_FMT 189 "\tiocstatus(0x%04x), loginfo(0x%08x)\n", 190 ioc->name, le16_to_cpu(mpi_reply->IOCStatus), 191 le32_to_cpu(mpi_reply->IOCLogInfo)); 192 } 193 194 /** 195 * _config_alloc_config_dma_memory - obtain physical memory 196 * @ioc: per adapter object 197 * @mem: struct config_request 198 * 199 * A wrapper for obtaining dma-able memory for config page request. 200 * 201 * Returns 0 for success, non-zero for failure. 202 */ 203 static int 204 _config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc, 205 struct config_request *mem) 206 { 207 int r = 0; 208 209 if (mem->sz > ioc->config_page_sz) { 210 mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz, 211 &mem->page_dma, GFP_KERNEL); 212 if (!mem->page) { 213 pr_err(MPT3SAS_FMT 214 "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n", 215 ioc->name, __func__, mem->sz); 216 r = -ENOMEM; 217 } 218 } else { /* use tmp buffer if less than 512 bytes */ 219 mem->page = ioc->config_page; 220 mem->page_dma = ioc->config_page_dma; 221 } 222 return r; 223 } 224 225 /** 226 * _config_free_config_dma_memory - wrapper to free the memory 227 * @ioc: per adapter object 228 * @mem: struct config_request 229 * 230 * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory. 231 * 232 * Returns 0 for success, non-zero for failure. 233 */ 234 static void 235 _config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc, 236 struct config_request *mem) 237 { 238 if (mem->sz > ioc->config_page_sz) 239 dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page, 240 mem->page_dma); 241 } 242 243 /** 244 * mpt3sas_config_done - config page completion routine 245 * @ioc: per adapter object 246 * @smid: system request message index 247 * @msix_index: MSIX table index supplied by the OS 248 * @reply: reply message frame(lower 32bit addr) 249 * Context: none. 250 * 251 * The callback handler when using _config_request. 252 * 253 * Return 1 meaning mf should be freed from _base_interrupt 254 * 0 means the mf is freed from this function. 255 */ 256 u8 257 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, 258 u32 reply) 259 { 260 MPI2DefaultReply_t *mpi_reply; 261 262 if (ioc->config_cmds.status == MPT3_CMD_NOT_USED) 263 return 1; 264 if (ioc->config_cmds.smid != smid) 265 return 1; 266 ioc->config_cmds.status |= MPT3_CMD_COMPLETE; 267 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); 268 if (mpi_reply) { 269 ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID; 270 memcpy(ioc->config_cmds.reply, mpi_reply, 271 mpi_reply->MsgLength*4); 272 } 273 ioc->config_cmds.status &= ~MPT3_CMD_PENDING; 274 _config_display_some_debug(ioc, smid, "config_done", mpi_reply); 275 ioc->config_cmds.smid = USHRT_MAX; 276 complete(&ioc->config_cmds.done); 277 return 1; 278 } 279 280 /** 281 * _config_request - main routine for sending config page requests 282 * @ioc: per adapter object 283 * @mpi_request: request message frame 284 * @mpi_reply: reply mf payload returned from firmware 285 * @timeout: timeout in seconds 286 * @config_page: contents of the config page 287 * @config_page_sz: size of config page 288 * Context: sleep 289 * 290 * A generic API for config page requests to firmware. 291 * 292 * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling 293 * this API. 294 * 295 * The callback index is set inside `ioc->config_cb_idx. 296 * 297 * Returns 0 for success, non-zero for failure. 298 */ 299 static int 300 _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t 301 *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout, 302 void *config_page, u16 config_page_sz) 303 { 304 u16 smid; 305 u32 ioc_state; 306 Mpi2ConfigRequest_t *config_request; 307 int r; 308 u8 retry_count, issue_host_reset = 0; 309 u16 wait_state_count; 310 struct config_request mem; 311 u32 ioc_status = UINT_MAX; 312 313 mutex_lock(&ioc->config_cmds.mutex); 314 if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) { 315 pr_err(MPT3SAS_FMT "%s: config_cmd in use\n", 316 ioc->name, __func__); 317 mutex_unlock(&ioc->config_cmds.mutex); 318 return -EAGAIN; 319 } 320 321 retry_count = 0; 322 memset(&mem, 0, sizeof(struct config_request)); 323 324 mpi_request->VF_ID = 0; /* TODO */ 325 mpi_request->VP_ID = 0; 326 327 if (config_page) { 328 mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion; 329 mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber; 330 mpi_request->Header.PageType = mpi_reply->Header.PageType; 331 mpi_request->Header.PageLength = mpi_reply->Header.PageLength; 332 mpi_request->ExtPageLength = mpi_reply->ExtPageLength; 333 mpi_request->ExtPageType = mpi_reply->ExtPageType; 334 if (mpi_request->Header.PageLength) 335 mem.sz = mpi_request->Header.PageLength * 4; 336 else 337 mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; 338 r = _config_alloc_config_dma_memory(ioc, &mem); 339 if (r != 0) 340 goto out; 341 if (mpi_request->Action == 342 MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT || 343 mpi_request->Action == 344 MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) { 345 ioc->base_add_sg_single(&mpi_request->PageBufferSGE, 346 MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz, 347 mem.page_dma); 348 memcpy(mem.page, config_page, min_t(u16, mem.sz, 349 config_page_sz)); 350 } else { 351 memset(config_page, 0, config_page_sz); 352 ioc->base_add_sg_single(&mpi_request->PageBufferSGE, 353 MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma); 354 memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz)); 355 } 356 } 357 358 retry_config: 359 if (retry_count) { 360 if (retry_count > 2) { /* attempt only 2 retries */ 361 r = -EFAULT; 362 goto free_mem; 363 } 364 pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n", 365 ioc->name, __func__, retry_count); 366 } 367 wait_state_count = 0; 368 ioc_state = mpt3sas_base_get_iocstate(ioc, 1); 369 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { 370 if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) { 371 pr_err(MPT3SAS_FMT 372 "%s: failed due to ioc not operational\n", 373 ioc->name, __func__); 374 ioc->config_cmds.status = MPT3_CMD_NOT_USED; 375 r = -EFAULT; 376 goto free_mem; 377 } 378 ssleep(1); 379 ioc_state = mpt3sas_base_get_iocstate(ioc, 1); 380 pr_info(MPT3SAS_FMT 381 "%s: waiting for operational state(count=%d)\n", 382 ioc->name, __func__, wait_state_count); 383 } 384 if (wait_state_count) 385 pr_info(MPT3SAS_FMT "%s: ioc is operational\n", 386 ioc->name, __func__); 387 388 smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx); 389 if (!smid) { 390 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", 391 ioc->name, __func__); 392 ioc->config_cmds.status = MPT3_CMD_NOT_USED; 393 r = -EAGAIN; 394 goto free_mem; 395 } 396 397 r = 0; 398 memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t)); 399 ioc->config_cmds.status = MPT3_CMD_PENDING; 400 config_request = mpt3sas_base_get_msg_frame(ioc, smid); 401 ioc->config_cmds.smid = smid; 402 memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); 403 _config_display_some_debug(ioc, smid, "config_request", NULL); 404 init_completion(&ioc->config_cmds.done); 405 ioc->put_smid_default(ioc, smid); 406 wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ); 407 if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) { 408 pr_err(MPT3SAS_FMT "%s: timeout\n", 409 ioc->name, __func__); 410 _debug_dump_mf(mpi_request, 411 sizeof(Mpi2ConfigRequest_t)/4); 412 retry_count++; 413 if (ioc->config_cmds.smid == smid) 414 mpt3sas_base_free_smid(ioc, smid); 415 if ((ioc->shost_recovery) || (ioc->config_cmds.status & 416 MPT3_CMD_RESET) || ioc->pci_error_recovery) 417 goto retry_config; 418 issue_host_reset = 1; 419 r = -EFAULT; 420 goto free_mem; 421 } 422 423 if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) { 424 memcpy(mpi_reply, ioc->config_cmds.reply, 425 sizeof(Mpi2ConfigReply_t)); 426 427 /* Reply Frame Sanity Checks to workaround FW issues */ 428 if ((mpi_request->Header.PageType & 0xF) != 429 (mpi_reply->Header.PageType & 0xF)) { 430 _debug_dump_mf(mpi_request, ioc->request_sz/4); 431 _debug_dump_reply(mpi_reply, ioc->request_sz/4); 432 panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \ 433 " mpi_reply mismatch: Requested PageType(0x%02x)" \ 434 " Reply PageType(0x%02x)\n", \ 435 ioc->name, __func__, 436 (mpi_request->Header.PageType & 0xF), 437 (mpi_reply->Header.PageType & 0xF)); 438 } 439 440 if (((mpi_request->Header.PageType & 0xF) == 441 MPI2_CONFIG_PAGETYPE_EXTENDED) && 442 mpi_request->ExtPageType != mpi_reply->ExtPageType) { 443 _debug_dump_mf(mpi_request, ioc->request_sz/4); 444 _debug_dump_reply(mpi_reply, ioc->request_sz/4); 445 panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \ 446 " mpi_reply mismatch: Requested ExtPageType(0x%02x)" 447 " Reply ExtPageType(0x%02x)\n", 448 ioc->name, __func__, mpi_request->ExtPageType, 449 mpi_reply->ExtPageType); 450 } 451 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) 452 & MPI2_IOCSTATUS_MASK; 453 } 454 455 if (retry_count) 456 pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \ 457 ioc->name, __func__, retry_count); 458 459 if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) && 460 config_page && mpi_request->Action == 461 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) { 462 u8 *p = (u8 *)mem.page; 463 464 /* Config Page Sanity Checks to workaround FW issues */ 465 if (p) { 466 if ((mpi_request->Header.PageType & 0xF) != 467 (p[3] & 0xF)) { 468 _debug_dump_mf(mpi_request, ioc->request_sz/4); 469 _debug_dump_reply(mpi_reply, ioc->request_sz/4); 470 _debug_dump_config(p, min_t(u16, mem.sz, 471 config_page_sz)/4); 472 panic(KERN_WARNING MPT3SAS_FMT 473 "%s: Firmware BUG:" \ 474 " config page mismatch:" 475 " Requested PageType(0x%02x)" 476 " Reply PageType(0x%02x)\n", 477 ioc->name, __func__, 478 (mpi_request->Header.PageType & 0xF), 479 (p[3] & 0xF)); 480 } 481 482 if (((mpi_request->Header.PageType & 0xF) == 483 MPI2_CONFIG_PAGETYPE_EXTENDED) && 484 (mpi_request->ExtPageType != p[6])) { 485 _debug_dump_mf(mpi_request, ioc->request_sz/4); 486 _debug_dump_reply(mpi_reply, ioc->request_sz/4); 487 _debug_dump_config(p, min_t(u16, mem.sz, 488 config_page_sz)/4); 489 panic(KERN_WARNING MPT3SAS_FMT 490 "%s: Firmware BUG:" \ 491 " config page mismatch:" 492 " Requested ExtPageType(0x%02x)" 493 " Reply ExtPageType(0x%02x)\n", 494 ioc->name, __func__, 495 mpi_request->ExtPageType, p[6]); 496 } 497 } 498 memcpy(config_page, mem.page, min_t(u16, mem.sz, 499 config_page_sz)); 500 } 501 502 free_mem: 503 if (config_page) 504 _config_free_config_dma_memory(ioc, &mem); 505 out: 506 ioc->config_cmds.status = MPT3_CMD_NOT_USED; 507 mutex_unlock(&ioc->config_cmds.mutex); 508 509 if (issue_host_reset) 510 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); 511 return r; 512 } 513 514 /** 515 * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0 516 * @ioc: per adapter object 517 * @mpi_reply: reply mf payload returned from firmware 518 * @config_page: contents of the config page 519 * Context: sleep. 520 * 521 * Returns 0 for success, non-zero for failure. 522 */ 523 int 524 mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc, 525 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page) 526 { 527 Mpi2ConfigRequest_t mpi_request; 528 int r; 529 530 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 531 mpi_request.Function = MPI2_FUNCTION_CONFIG; 532 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 533 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 534 mpi_request.Header.PageNumber = 0; 535 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; 536 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 537 r = _config_request(ioc, &mpi_request, mpi_reply, 538 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 539 if (r) 540 goto out; 541 542 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 543 r = _config_request(ioc, &mpi_request, mpi_reply, 544 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 545 sizeof(*config_page)); 546 out: 547 return r; 548 } 549 550 /** 551 * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7 552 * @ioc: per adapter object 553 * @mpi_reply: reply mf payload returned from firmware 554 * @config_page: contents of the config page 555 * @sz: size of buffer passed in config_page 556 * Context: sleep. 557 * 558 * Returns 0 for success, non-zero for failure. 559 */ 560 int 561 mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc, 562 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page, 563 u16 sz) 564 { 565 Mpi2ConfigRequest_t mpi_request; 566 int r; 567 568 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 569 mpi_request.Function = MPI2_FUNCTION_CONFIG; 570 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 571 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 572 mpi_request.Header.PageNumber = 7; 573 mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION; 574 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 575 r = _config_request(ioc, &mpi_request, mpi_reply, 576 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 577 if (r) 578 goto out; 579 580 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 581 r = _config_request(ioc, &mpi_request, mpi_reply, 582 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 583 sz); 584 out: 585 return r; 586 } 587 588 /** 589 * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10 590 * @ioc: per adapter object 591 * @mpi_reply: reply mf payload returned from firmware 592 * @config_page: contents of the config page 593 * Context: sleep. 594 * 595 * Returns 0 for success, non-zero for failure. 596 */ 597 int 598 mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc, 599 Mpi2ConfigReply_t *mpi_reply, 600 struct Mpi2ManufacturingPage10_t *config_page) 601 { 602 Mpi2ConfigRequest_t mpi_request; 603 int r; 604 605 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 606 mpi_request.Function = MPI2_FUNCTION_CONFIG; 607 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 608 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 609 mpi_request.Header.PageNumber = 10; 610 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; 611 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 612 r = _config_request(ioc, &mpi_request, mpi_reply, 613 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 614 if (r) 615 goto out; 616 617 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 618 r = _config_request(ioc, &mpi_request, mpi_reply, 619 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 620 sizeof(*config_page)); 621 out: 622 return r; 623 } 624 625 /** 626 * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11 627 * @ioc: per adapter object 628 * @mpi_reply: reply mf payload returned from firmware 629 * @config_page: contents of the config page 630 * Context: sleep. 631 * 632 * Returns 0 for success, non-zero for failure. 633 */ 634 int 635 mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, 636 Mpi2ConfigReply_t *mpi_reply, 637 struct Mpi2ManufacturingPage11_t *config_page) 638 { 639 Mpi2ConfigRequest_t mpi_request; 640 int r; 641 642 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 643 mpi_request.Function = MPI2_FUNCTION_CONFIG; 644 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 645 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 646 mpi_request.Header.PageNumber = 11; 647 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; 648 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 649 r = _config_request(ioc, &mpi_request, mpi_reply, 650 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 651 if (r) 652 goto out; 653 654 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 655 r = _config_request(ioc, &mpi_request, mpi_reply, 656 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 657 sizeof(*config_page)); 658 out: 659 return r; 660 } 661 662 /** 663 * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11 664 * @ioc: per adapter object 665 * @mpi_reply: reply mf payload returned from firmware 666 * @config_page: contents of the config page 667 * Context: sleep. 668 * 669 * Returns 0 for success, non-zero for failure. 670 */ 671 int 672 mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, 673 Mpi2ConfigReply_t *mpi_reply, 674 struct Mpi2ManufacturingPage11_t *config_page) 675 { 676 Mpi2ConfigRequest_t mpi_request; 677 int r; 678 679 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 680 mpi_request.Function = MPI2_FUNCTION_CONFIG; 681 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 682 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 683 mpi_request.Header.PageNumber = 11; 684 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; 685 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 686 r = _config_request(ioc, &mpi_request, mpi_reply, 687 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 688 if (r) 689 goto out; 690 691 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; 692 r = _config_request(ioc, &mpi_request, mpi_reply, 693 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 694 sizeof(*config_page)); 695 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 696 r = _config_request(ioc, &mpi_request, mpi_reply, 697 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 698 sizeof(*config_page)); 699 out: 700 return r; 701 } 702 703 /** 704 * mpt3sas_config_get_bios_pg2 - obtain bios page 2 705 * @ioc: per adapter object 706 * @mpi_reply: reply mf payload returned from firmware 707 * @config_page: contents of the config page 708 * Context: sleep. 709 * 710 * Returns 0 for success, non-zero for failure. 711 */ 712 int 713 mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc, 714 Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page) 715 { 716 Mpi2ConfigRequest_t mpi_request; 717 int r; 718 719 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 720 mpi_request.Function = MPI2_FUNCTION_CONFIG; 721 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 722 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 723 mpi_request.Header.PageNumber = 2; 724 mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION; 725 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 726 r = _config_request(ioc, &mpi_request, mpi_reply, 727 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 728 if (r) 729 goto out; 730 731 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 732 r = _config_request(ioc, &mpi_request, mpi_reply, 733 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 734 sizeof(*config_page)); 735 out: 736 return r; 737 } 738 739 /** 740 * mpt3sas_config_get_bios_pg3 - obtain bios page 3 741 * @ioc: per adapter object 742 * @mpi_reply: reply mf payload returned from firmware 743 * @config_page: contents of the config page 744 * Context: sleep. 745 * 746 * Returns 0 for success, non-zero for failure. 747 */ 748 int 749 mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 750 *mpi_reply, Mpi2BiosPage3_t *config_page) 751 { 752 Mpi2ConfigRequest_t mpi_request; 753 int r; 754 755 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 756 mpi_request.Function = MPI2_FUNCTION_CONFIG; 757 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 758 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 759 mpi_request.Header.PageNumber = 3; 760 mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 761 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 762 r = _config_request(ioc, &mpi_request, mpi_reply, 763 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 764 if (r) 765 goto out; 766 767 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 768 r = _config_request(ioc, &mpi_request, mpi_reply, 769 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 770 sizeof(*config_page)); 771 out: 772 return r; 773 } 774 775 /** 776 * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0 777 * @ioc: per adapter object 778 * @mpi_reply: reply mf payload returned from firmware 779 * @config_page: contents of the config page 780 * Context: sleep. 781 * 782 * Returns 0 for success, non-zero for failure. 783 */ 784 int 785 mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, 786 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page) 787 { 788 Mpi2ConfigRequest_t mpi_request; 789 int r; 790 791 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 792 mpi_request.Function = MPI2_FUNCTION_CONFIG; 793 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 794 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 795 mpi_request.Header.PageNumber = 0; 796 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION; 797 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 798 r = _config_request(ioc, &mpi_request, mpi_reply, 799 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 800 if (r) 801 goto out; 802 803 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 804 r = _config_request(ioc, &mpi_request, mpi_reply, 805 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 806 sizeof(*config_page)); 807 out: 808 return r; 809 } 810 811 /** 812 * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1 813 * @ioc: per adapter object 814 * @mpi_reply: reply mf payload returned from firmware 815 * @config_page: contents of the config page 816 * Context: sleep. 817 * 818 * Returns 0 for success, non-zero for failure. 819 */ 820 int 821 mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, 822 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) 823 { 824 Mpi2ConfigRequest_t mpi_request; 825 int r; 826 827 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 828 mpi_request.Function = MPI2_FUNCTION_CONFIG; 829 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 830 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 831 mpi_request.Header.PageNumber = 1; 832 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; 833 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 834 r = _config_request(ioc, &mpi_request, mpi_reply, 835 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 836 if (r) 837 goto out; 838 839 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 840 r = _config_request(ioc, &mpi_request, mpi_reply, 841 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 842 sizeof(*config_page)); 843 out: 844 return r; 845 } 846 847 /** 848 * mpt3sas_config_set_iounit_pg1 - set iounit page 1 849 * @ioc: per adapter object 850 * @mpi_reply: reply mf payload returned from firmware 851 * @config_page: contents of the config page 852 * Context: sleep. 853 * 854 * Returns 0 for success, non-zero for failure. 855 */ 856 int 857 mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, 858 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) 859 { 860 Mpi2ConfigRequest_t mpi_request; 861 int r; 862 863 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 864 mpi_request.Function = MPI2_FUNCTION_CONFIG; 865 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 866 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 867 mpi_request.Header.PageNumber = 1; 868 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; 869 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 870 r = _config_request(ioc, &mpi_request, mpi_reply, 871 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 872 if (r) 873 goto out; 874 875 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; 876 r = _config_request(ioc, &mpi_request, mpi_reply, 877 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 878 sizeof(*config_page)); 879 out: 880 return r; 881 } 882 883 /** 884 * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3 885 * @ioc: per adapter object 886 * @mpi_reply: reply mf payload returned from firmware 887 * @config_page: contents of the config page 888 * @sz: size of buffer passed in config_page 889 * Context: sleep. 890 * 891 * Returns 0 for success, non-zero for failure. 892 */ 893 int 894 mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc, 895 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz) 896 { 897 Mpi2ConfigRequest_t mpi_request; 898 int r; 899 900 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 901 mpi_request.Function = MPI2_FUNCTION_CONFIG; 902 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 903 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 904 mpi_request.Header.PageNumber = 3; 905 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION; 906 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 907 r = _config_request(ioc, &mpi_request, mpi_reply, 908 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 909 if (r) 910 goto out; 911 912 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 913 r = _config_request(ioc, &mpi_request, mpi_reply, 914 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 915 out: 916 return r; 917 } 918 919 /** 920 * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8 921 * @ioc: per adapter object 922 * @mpi_reply: reply mf payload returned from firmware 923 * @config_page: contents of the config page 924 * Context: sleep. 925 * 926 * Returns 0 for success, non-zero for failure. 927 */ 928 int 929 mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc, 930 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page) 931 { 932 Mpi2ConfigRequest_t mpi_request; 933 int r; 934 935 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 936 mpi_request.Function = MPI2_FUNCTION_CONFIG; 937 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 938 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 939 mpi_request.Header.PageNumber = 8; 940 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION; 941 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 942 r = _config_request(ioc, &mpi_request, mpi_reply, 943 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 944 if (r) 945 goto out; 946 947 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 948 r = _config_request(ioc, &mpi_request, mpi_reply, 949 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 950 sizeof(*config_page)); 951 out: 952 return r; 953 } 954 955 /** 956 * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8 957 * @ioc: per adapter object 958 * @mpi_reply: reply mf payload returned from firmware 959 * @config_page: contents of the config page 960 * Context: sleep. 961 * 962 * Returns 0 for success, non-zero for failure. 963 */ 964 int 965 mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc, 966 Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page) 967 { 968 Mpi2ConfigRequest_t mpi_request; 969 int r; 970 971 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 972 mpi_request.Function = MPI2_FUNCTION_CONFIG; 973 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 974 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 975 mpi_request.Header.PageNumber = 8; 976 mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 977 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 978 r = _config_request(ioc, &mpi_request, mpi_reply, 979 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 980 if (r) 981 goto out; 982 983 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 984 r = _config_request(ioc, &mpi_request, mpi_reply, 985 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 986 sizeof(*config_page)); 987 out: 988 return r; 989 } 990 991 /** 992 * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0 993 * @ioc: per adapter object 994 * @mpi_reply: reply mf payload returned from firmware 995 * @config_page: contents of the config page 996 * @form: GET_NEXT_HANDLE or HANDLE 997 * @handle: device handle 998 * Context: sleep. 999 * 1000 * Returns 0 for success, non-zero for failure. 1001 */ 1002 int 1003 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc, 1004 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page, 1005 u32 form, u32 handle) 1006 { 1007 Mpi2ConfigRequest_t mpi_request; 1008 int r; 1009 1010 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1011 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1012 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1013 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1014 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 1015 mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 1016 mpi_request.Header.PageNumber = 0; 1017 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1018 r = _config_request(ioc, &mpi_request, mpi_reply, 1019 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1020 if (r) 1021 goto out; 1022 1023 mpi_request.PageAddress = cpu_to_le32(form | handle); 1024 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1025 r = _config_request(ioc, &mpi_request, mpi_reply, 1026 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1027 sizeof(*config_page)); 1028 out: 1029 return r; 1030 } 1031 1032 /** 1033 * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1 1034 * @ioc: per adapter object 1035 * @mpi_reply: reply mf payload returned from firmware 1036 * @config_page: contents of the config page 1037 * @form: GET_NEXT_HANDLE or HANDLE 1038 * @handle: device handle 1039 * Context: sleep. 1040 * 1041 * Returns 0 for success, non-zero for failure. 1042 */ 1043 int 1044 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc, 1045 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page, 1046 u32 form, u32 handle) 1047 { 1048 Mpi2ConfigRequest_t mpi_request; 1049 int r; 1050 1051 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1052 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1053 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1054 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1055 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 1056 mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION; 1057 mpi_request.Header.PageNumber = 1; 1058 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1059 r = _config_request(ioc, &mpi_request, mpi_reply, 1060 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1061 if (r) 1062 goto out; 1063 1064 mpi_request.PageAddress = cpu_to_le32(form | handle); 1065 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1066 r = _config_request(ioc, &mpi_request, mpi_reply, 1067 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1068 sizeof(*config_page)); 1069 out: 1070 return r; 1071 } 1072 1073 /** 1074 * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0 1075 * @ioc: per adapter object 1076 * @mpi_reply: reply mf payload returned from firmware 1077 * @config_page: contents of the config page 1078 * @form: GET_NEXT_HANDLE or HANDLE 1079 * @handle: device handle 1080 * Context: sleep. 1081 * 1082 * Returns 0 for success, non-zero for failure. 1083 */ 1084 int 1085 mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc, 1086 Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, 1087 u32 form, u32 handle) 1088 { 1089 Mpi2ConfigRequest_t mpi_request; 1090 int r; 1091 1092 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1093 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1094 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1095 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1096 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 1097 mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION; 1098 mpi_request.Header.PageNumber = 0; 1099 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1100 r = _config_request(ioc, &mpi_request, mpi_reply, 1101 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1102 if (r) 1103 goto out; 1104 1105 mpi_request.PageAddress = cpu_to_le32(form | handle); 1106 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1107 r = _config_request(ioc, &mpi_request, mpi_reply, 1108 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1109 sizeof(*config_page)); 1110 out: 1111 return r; 1112 } 1113 1114 /** 1115 * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2 1116 * @ioc: per adapter object 1117 * @mpi_reply: reply mf payload returned from firmware 1118 * @config_page: contents of the config page 1119 * @form: GET_NEXT_HANDLE or HANDLE 1120 * @handle: device handle 1121 * Context: sleep. 1122 * 1123 * Returns 0 for success, non-zero for failure. 1124 */ 1125 int 1126 mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc, 1127 Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, 1128 u32 form, u32 handle) 1129 { 1130 Mpi2ConfigRequest_t mpi_request; 1131 int r; 1132 1133 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1134 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1135 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1136 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1137 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 1138 mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION; 1139 mpi_request.Header.PageNumber = 2; 1140 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1141 r = _config_request(ioc, &mpi_request, mpi_reply, 1142 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1143 if (r) 1144 goto out; 1145 1146 mpi_request.PageAddress = cpu_to_le32(form | handle); 1147 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1148 r = _config_request(ioc, &mpi_request, mpi_reply, 1149 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1150 sizeof(*config_page)); 1151 out: 1152 return r; 1153 } 1154 1155 /** 1156 * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host 1157 * @ioc: per adapter object 1158 * @num_phys: pointer returned with the number of phys 1159 * Context: sleep. 1160 * 1161 * Returns 0 for success, non-zero for failure. 1162 */ 1163 int 1164 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys) 1165 { 1166 Mpi2ConfigRequest_t mpi_request; 1167 int r; 1168 u16 ioc_status; 1169 Mpi2ConfigReply_t mpi_reply; 1170 Mpi2SasIOUnitPage0_t config_page; 1171 1172 *num_phys = 0; 1173 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1174 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1175 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1176 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1177 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 1178 mpi_request.Header.PageNumber = 0; 1179 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; 1180 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1181 r = _config_request(ioc, &mpi_request, &mpi_reply, 1182 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1183 if (r) 1184 goto out; 1185 1186 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1187 r = _config_request(ioc, &mpi_request, &mpi_reply, 1188 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, 1189 sizeof(Mpi2SasIOUnitPage0_t)); 1190 if (!r) { 1191 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & 1192 MPI2_IOCSTATUS_MASK; 1193 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) 1194 *num_phys = config_page.NumPhys; 1195 } 1196 out: 1197 return r; 1198 } 1199 1200 /** 1201 * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0 1202 * @ioc: per adapter object 1203 * @mpi_reply: reply mf payload returned from firmware 1204 * @config_page: contents of the config page 1205 * @sz: size of buffer passed in config_page 1206 * Context: sleep. 1207 * 1208 * Calling function should call config_get_number_hba_phys prior to 1209 * this function, so enough memory is allocated for config_page. 1210 * 1211 * Returns 0 for success, non-zero for failure. 1212 */ 1213 int 1214 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, 1215 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, 1216 u16 sz) 1217 { 1218 Mpi2ConfigRequest_t mpi_request; 1219 int r; 1220 1221 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1222 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1223 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1224 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1225 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 1226 mpi_request.Header.PageNumber = 0; 1227 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; 1228 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1229 r = _config_request(ioc, &mpi_request, mpi_reply, 1230 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1231 if (r) 1232 goto out; 1233 1234 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1235 r = _config_request(ioc, &mpi_request, mpi_reply, 1236 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1237 out: 1238 return r; 1239 } 1240 1241 /** 1242 * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1 1243 * @ioc: per adapter object 1244 * @mpi_reply: reply mf payload returned from firmware 1245 * @config_page: contents of the config page 1246 * @sz: size of buffer passed in config_page 1247 * Context: sleep. 1248 * 1249 * Calling function should call config_get_number_hba_phys prior to 1250 * this function, so enough memory is allocated for config_page. 1251 * 1252 * Returns 0 for success, non-zero for failure. 1253 */ 1254 int 1255 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, 1256 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, 1257 u16 sz) 1258 { 1259 Mpi2ConfigRequest_t mpi_request; 1260 int r; 1261 1262 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1263 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1264 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1265 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1266 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 1267 mpi_request.Header.PageNumber = 1; 1268 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; 1269 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1270 r = _config_request(ioc, &mpi_request, mpi_reply, 1271 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1272 if (r) 1273 goto out; 1274 1275 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1276 r = _config_request(ioc, &mpi_request, mpi_reply, 1277 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1278 out: 1279 return r; 1280 } 1281 1282 /** 1283 * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1 1284 * @ioc: per adapter object 1285 * @mpi_reply: reply mf payload returned from firmware 1286 * @config_page: contents of the config page 1287 * @sz: size of buffer passed in config_page 1288 * Context: sleep. 1289 * 1290 * Calling function should call config_get_number_hba_phys prior to 1291 * this function, so enough memory is allocated for config_page. 1292 * 1293 * Returns 0 for success, non-zero for failure. 1294 */ 1295 int 1296 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, 1297 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, 1298 u16 sz) 1299 { 1300 Mpi2ConfigRequest_t mpi_request; 1301 int r; 1302 1303 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1304 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1305 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1306 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1307 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 1308 mpi_request.Header.PageNumber = 1; 1309 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; 1310 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1311 r = _config_request(ioc, &mpi_request, mpi_reply, 1312 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1313 if (r) 1314 goto out; 1315 1316 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; 1317 _config_request(ioc, &mpi_request, mpi_reply, 1318 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1319 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 1320 r = _config_request(ioc, &mpi_request, mpi_reply, 1321 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1322 out: 1323 return r; 1324 } 1325 1326 /** 1327 * mpt3sas_config_get_expander_pg0 - obtain expander page 0 1328 * @ioc: per adapter object 1329 * @mpi_reply: reply mf payload returned from firmware 1330 * @config_page: contents of the config page 1331 * @form: GET_NEXT_HANDLE or HANDLE 1332 * @handle: expander handle 1333 * Context: sleep. 1334 * 1335 * Returns 0 for success, non-zero for failure. 1336 */ 1337 int 1338 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1339 *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle) 1340 { 1341 Mpi2ConfigRequest_t mpi_request; 1342 int r; 1343 1344 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1345 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1346 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1347 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1348 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; 1349 mpi_request.Header.PageNumber = 0; 1350 mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION; 1351 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1352 r = _config_request(ioc, &mpi_request, mpi_reply, 1353 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1354 if (r) 1355 goto out; 1356 1357 mpi_request.PageAddress = cpu_to_le32(form | handle); 1358 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1359 r = _config_request(ioc, &mpi_request, mpi_reply, 1360 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1361 sizeof(*config_page)); 1362 out: 1363 return r; 1364 } 1365 1366 /** 1367 * mpt3sas_config_get_expander_pg1 - obtain expander page 1 1368 * @ioc: per adapter object 1369 * @mpi_reply: reply mf payload returned from firmware 1370 * @config_page: contents of the config page 1371 * @phy_number: phy number 1372 * @handle: expander handle 1373 * Context: sleep. 1374 * 1375 * Returns 0 for success, non-zero for failure. 1376 */ 1377 int 1378 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1379 *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, 1380 u16 handle) 1381 { 1382 Mpi2ConfigRequest_t mpi_request; 1383 int r; 1384 1385 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1386 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1387 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1388 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1389 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; 1390 mpi_request.Header.PageNumber = 1; 1391 mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION; 1392 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1393 r = _config_request(ioc, &mpi_request, mpi_reply, 1394 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1395 if (r) 1396 goto out; 1397 1398 mpi_request.PageAddress = 1399 cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM | 1400 (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle); 1401 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1402 r = _config_request(ioc, &mpi_request, mpi_reply, 1403 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1404 sizeof(*config_page)); 1405 out: 1406 return r; 1407 } 1408 1409 /** 1410 * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0 1411 * @ioc: per adapter object 1412 * @mpi_reply: reply mf payload returned from firmware 1413 * @config_page: contents of the config page 1414 * @form: GET_NEXT_HANDLE or HANDLE 1415 * @handle: expander handle 1416 * Context: sleep. 1417 * 1418 * Returns 0 for success, non-zero for failure. 1419 */ 1420 int 1421 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1422 *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle) 1423 { 1424 Mpi2ConfigRequest_t mpi_request; 1425 int r; 1426 1427 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1428 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1429 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1430 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1431 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE; 1432 mpi_request.Header.PageNumber = 0; 1433 mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION; 1434 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1435 r = _config_request(ioc, &mpi_request, mpi_reply, 1436 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1437 if (r) 1438 goto out; 1439 1440 mpi_request.PageAddress = cpu_to_le32(form | handle); 1441 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1442 r = _config_request(ioc, &mpi_request, mpi_reply, 1443 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1444 sizeof(*config_page)); 1445 out: 1446 return r; 1447 } 1448 1449 /** 1450 * mpt3sas_config_get_phy_pg0 - obtain phy page 0 1451 * @ioc: per adapter object 1452 * @mpi_reply: reply mf payload returned from firmware 1453 * @config_page: contents of the config page 1454 * @phy_number: phy number 1455 * Context: sleep. 1456 * 1457 * Returns 0 for success, non-zero for failure. 1458 */ 1459 int 1460 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1461 *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number) 1462 { 1463 Mpi2ConfigRequest_t mpi_request; 1464 int r; 1465 1466 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1467 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1468 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1469 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1470 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; 1471 mpi_request.Header.PageNumber = 0; 1472 mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION; 1473 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1474 r = _config_request(ioc, &mpi_request, mpi_reply, 1475 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1476 if (r) 1477 goto out; 1478 1479 mpi_request.PageAddress = 1480 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); 1481 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1482 r = _config_request(ioc, &mpi_request, mpi_reply, 1483 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1484 sizeof(*config_page)); 1485 out: 1486 return r; 1487 } 1488 1489 /** 1490 * mpt3sas_config_get_phy_pg1 - obtain phy page 1 1491 * @ioc: per adapter object 1492 * @mpi_reply: reply mf payload returned from firmware 1493 * @config_page: contents of the config page 1494 * @phy_number: phy number 1495 * Context: sleep. 1496 * 1497 * Returns 0 for success, non-zero for failure. 1498 */ 1499 int 1500 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1501 *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number) 1502 { 1503 Mpi2ConfigRequest_t mpi_request; 1504 int r; 1505 1506 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1507 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1508 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1509 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1510 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; 1511 mpi_request.Header.PageNumber = 1; 1512 mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION; 1513 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1514 r = _config_request(ioc, &mpi_request, mpi_reply, 1515 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1516 if (r) 1517 goto out; 1518 1519 mpi_request.PageAddress = 1520 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); 1521 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1522 r = _config_request(ioc, &mpi_request, mpi_reply, 1523 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1524 sizeof(*config_page)); 1525 out: 1526 return r; 1527 } 1528 1529 /** 1530 * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1 1531 * @ioc: per adapter object 1532 * @mpi_reply: reply mf payload returned from firmware 1533 * @config_page: contents of the config page 1534 * @form: GET_NEXT_HANDLE or HANDLE 1535 * @handle: volume handle 1536 * Context: sleep. 1537 * 1538 * Returns 0 for success, non-zero for failure. 1539 */ 1540 int 1541 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc, 1542 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, 1543 u32 handle) 1544 { 1545 Mpi2ConfigRequest_t mpi_request; 1546 int r; 1547 1548 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1549 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1550 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1551 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1552 mpi_request.Header.PageNumber = 1; 1553 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; 1554 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1555 r = _config_request(ioc, &mpi_request, mpi_reply, 1556 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1557 if (r) 1558 goto out; 1559 1560 mpi_request.PageAddress = cpu_to_le32(form | handle); 1561 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1562 r = _config_request(ioc, &mpi_request, mpi_reply, 1563 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1564 sizeof(*config_page)); 1565 out: 1566 return r; 1567 } 1568 1569 /** 1570 * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume 1571 * @ioc: per adapter object 1572 * @handle: volume handle 1573 * @num_pds: returns pds count 1574 * Context: sleep. 1575 * 1576 * Returns 0 for success, non-zero for failure. 1577 */ 1578 int 1579 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle, 1580 u8 *num_pds) 1581 { 1582 Mpi2ConfigRequest_t mpi_request; 1583 Mpi2RaidVolPage0_t config_page; 1584 Mpi2ConfigReply_t mpi_reply; 1585 int r; 1586 u16 ioc_status; 1587 1588 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1589 *num_pds = 0; 1590 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1591 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1592 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1593 mpi_request.Header.PageNumber = 0; 1594 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1595 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1596 r = _config_request(ioc, &mpi_request, &mpi_reply, 1597 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1598 if (r) 1599 goto out; 1600 1601 mpi_request.PageAddress = 1602 cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle); 1603 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1604 r = _config_request(ioc, &mpi_request, &mpi_reply, 1605 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, 1606 sizeof(Mpi2RaidVolPage0_t)); 1607 if (!r) { 1608 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & 1609 MPI2_IOCSTATUS_MASK; 1610 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) 1611 *num_pds = config_page.NumPhysDisks; 1612 } 1613 1614 out: 1615 return r; 1616 } 1617 1618 /** 1619 * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0 1620 * @ioc: per adapter object 1621 * @mpi_reply: reply mf payload returned from firmware 1622 * @config_page: contents of the config page 1623 * @form: GET_NEXT_HANDLE or HANDLE 1624 * @handle: volume handle 1625 * @sz: size of buffer passed in config_page 1626 * Context: sleep. 1627 * 1628 * Returns 0 for success, non-zero for failure. 1629 */ 1630 int 1631 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc, 1632 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, 1633 u32 handle, u16 sz) 1634 { 1635 Mpi2ConfigRequest_t mpi_request; 1636 int r; 1637 1638 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1639 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1640 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1641 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1642 mpi_request.Header.PageNumber = 0; 1643 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1644 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1645 r = _config_request(ioc, &mpi_request, mpi_reply, 1646 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1647 if (r) 1648 goto out; 1649 1650 mpi_request.PageAddress = cpu_to_le32(form | handle); 1651 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1652 r = _config_request(ioc, &mpi_request, mpi_reply, 1653 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1654 out: 1655 return r; 1656 } 1657 1658 /** 1659 * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0 1660 * @ioc: per adapter object 1661 * @mpi_reply: reply mf payload returned from firmware 1662 * @config_page: contents of the config page 1663 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE 1664 * @form_specific: specific to the form 1665 * Context: sleep. 1666 * 1667 * Returns 0 for success, non-zero for failure. 1668 */ 1669 int 1670 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1671 *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, 1672 u32 form_specific) 1673 { 1674 Mpi2ConfigRequest_t mpi_request; 1675 int r; 1676 1677 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1678 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1679 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1680 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1681 mpi_request.Header.PageNumber = 0; 1682 mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; 1683 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1684 r = _config_request(ioc, &mpi_request, mpi_reply, 1685 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1686 if (r) 1687 goto out; 1688 1689 mpi_request.PageAddress = cpu_to_le32(form | form_specific); 1690 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1691 r = _config_request(ioc, &mpi_request, mpi_reply, 1692 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1693 sizeof(*config_page)); 1694 out: 1695 return r; 1696 } 1697 1698 /** 1699 * mpt3sas_config_get_volume_handle - returns volume handle for give hidden 1700 * raid components 1701 * @ioc: per adapter object 1702 * @pd_handle: phys disk handle 1703 * @volume_handle: volume handle 1704 * Context: sleep. 1705 * 1706 * Returns 0 for success, non-zero for failure. 1707 */ 1708 int 1709 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle, 1710 u16 *volume_handle) 1711 { 1712 Mpi2RaidConfigurationPage0_t *config_page = NULL; 1713 Mpi2ConfigRequest_t mpi_request; 1714 Mpi2ConfigReply_t mpi_reply; 1715 int r, i, config_page_sz; 1716 u16 ioc_status; 1717 int config_num; 1718 u16 element_type; 1719 u16 phys_disk_dev_handle; 1720 1721 *volume_handle = 0; 1722 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1723 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1724 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1725 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1726 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG; 1727 mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION; 1728 mpi_request.Header.PageNumber = 0; 1729 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1730 r = _config_request(ioc, &mpi_request, &mpi_reply, 1731 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1732 if (r) 1733 goto out; 1734 1735 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1736 config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4); 1737 config_page = kmalloc(config_page_sz, GFP_KERNEL); 1738 if (!config_page) { 1739 r = -1; 1740 goto out; 1741 } 1742 1743 config_num = 0xff; 1744 while (1) { 1745 mpi_request.PageAddress = cpu_to_le32(config_num + 1746 MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM); 1747 r = _config_request(ioc, &mpi_request, &mpi_reply, 1748 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1749 config_page_sz); 1750 if (r) 1751 goto out; 1752 r = -1; 1753 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & 1754 MPI2_IOCSTATUS_MASK; 1755 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) 1756 goto out; 1757 for (i = 0; i < config_page->NumElements; i++) { 1758 element_type = le16_to_cpu(config_page-> 1759 ConfigElement[i].ElementFlags) & 1760 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; 1761 if (element_type == 1762 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT || 1763 element_type == 1764 MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) { 1765 phys_disk_dev_handle = 1766 le16_to_cpu(config_page->ConfigElement[i]. 1767 PhysDiskDevHandle); 1768 if (phys_disk_dev_handle == pd_handle) { 1769 *volume_handle = 1770 le16_to_cpu(config_page-> 1771 ConfigElement[i].VolDevHandle); 1772 r = 0; 1773 goto out; 1774 } 1775 } else if (element_type == 1776 MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) { 1777 *volume_handle = 0; 1778 r = 0; 1779 goto out; 1780 } 1781 } 1782 config_num = config_page->ConfigNum; 1783 } 1784 out: 1785 kfree(config_page); 1786 return r; 1787 } 1788 1789 /** 1790 * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle 1791 * @ioc: per adapter object 1792 * @volume_handle: volume handle 1793 * @wwid: volume wwid 1794 * Context: sleep. 1795 * 1796 * Returns 0 for success, non-zero for failure. 1797 */ 1798 int 1799 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle, 1800 u64 *wwid) 1801 { 1802 Mpi2ConfigReply_t mpi_reply; 1803 Mpi2RaidVolPage1_t raid_vol_pg1; 1804 1805 *wwid = 0; 1806 if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, 1807 &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, 1808 volume_handle))) { 1809 *wwid = le64_to_cpu(raid_vol_pg1.WWID); 1810 return 0; 1811 } else 1812 return -1; 1813 } 1814