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