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 ioc->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 * mpt3sas_config_get_ioc_pg1 - obtain ioc page 1 954 * @ioc: per adapter object 955 * @mpi_reply: reply mf payload returned from firmware 956 * @config_page: contents of the config page 957 * Context: sleep. 958 * 959 * Return: 0 for success, non-zero for failure. 960 */ 961 int 962 mpt3sas_config_get_ioc_pg1(struct MPT3SAS_ADAPTER *ioc, 963 Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page) 964 { 965 Mpi2ConfigRequest_t mpi_request; 966 int r; 967 968 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 969 mpi_request.Function = MPI2_FUNCTION_CONFIG; 970 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 971 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 972 mpi_request.Header.PageNumber = 1; 973 mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 974 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 975 r = _config_request(ioc, &mpi_request, mpi_reply, 976 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 977 if (r) 978 goto out; 979 980 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 981 r = _config_request(ioc, &mpi_request, mpi_reply, 982 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 983 sizeof(*config_page)); 984 out: 985 return r; 986 } 987 988 /** 989 * mpt3sas_config_set_ioc_pg1 - modify ioc page 1 990 * @ioc: per adapter object 991 * @mpi_reply: reply mf payload returned from firmware 992 * @config_page: contents of the config page 993 * Context: sleep. 994 * 995 * Return: 0 for success, non-zero for failure. 996 */ 997 int 998 mpt3sas_config_set_ioc_pg1(struct MPT3SAS_ADAPTER *ioc, 999 Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page) 1000 { 1001 Mpi2ConfigRequest_t mpi_request; 1002 int r; 1003 1004 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1005 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1006 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1007 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 1008 mpi_request.Header.PageNumber = 1; 1009 mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 1010 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1011 r = _config_request(ioc, &mpi_request, mpi_reply, 1012 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1013 if (r) 1014 goto out; 1015 1016 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; 1017 r = _config_request(ioc, &mpi_request, mpi_reply, 1018 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1019 sizeof(*config_page)); 1020 out: 1021 return r; 1022 } 1023 1024 /** 1025 * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0 1026 * @ioc: per adapter object 1027 * @mpi_reply: reply mf payload returned from firmware 1028 * @config_page: contents of the config page 1029 * @form: GET_NEXT_HANDLE or HANDLE 1030 * @handle: device handle 1031 * Context: sleep. 1032 * 1033 * Return: 0 for success, non-zero for failure. 1034 */ 1035 int 1036 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc, 1037 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page, 1038 u32 form, u32 handle) 1039 { 1040 Mpi2ConfigRequest_t mpi_request; 1041 int r; 1042 1043 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1044 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1045 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1046 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1047 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 1048 mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 1049 mpi_request.Header.PageNumber = 0; 1050 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1051 r = _config_request(ioc, &mpi_request, mpi_reply, 1052 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1053 if (r) 1054 goto out; 1055 1056 mpi_request.PageAddress = cpu_to_le32(form | handle); 1057 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1058 r = _config_request(ioc, &mpi_request, mpi_reply, 1059 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1060 sizeof(*config_page)); 1061 out: 1062 return r; 1063 } 1064 1065 /** 1066 * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1 1067 * @ioc: per adapter object 1068 * @mpi_reply: reply mf payload returned from firmware 1069 * @config_page: contents of the config page 1070 * @form: GET_NEXT_HANDLE or HANDLE 1071 * @handle: device handle 1072 * Context: sleep. 1073 * 1074 * Return: 0 for success, non-zero for failure. 1075 */ 1076 int 1077 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc, 1078 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page, 1079 u32 form, u32 handle) 1080 { 1081 Mpi2ConfigRequest_t mpi_request; 1082 int r; 1083 1084 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1085 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1086 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1087 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1088 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 1089 mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION; 1090 mpi_request.Header.PageNumber = 1; 1091 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1092 r = _config_request(ioc, &mpi_request, mpi_reply, 1093 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1094 if (r) 1095 goto out; 1096 1097 mpi_request.PageAddress = cpu_to_le32(form | handle); 1098 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1099 r = _config_request(ioc, &mpi_request, mpi_reply, 1100 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1101 sizeof(*config_page)); 1102 out: 1103 return r; 1104 } 1105 1106 /** 1107 * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0 1108 * @ioc: per adapter object 1109 * @mpi_reply: reply mf payload returned from firmware 1110 * @config_page: contents of the config page 1111 * @form: GET_NEXT_HANDLE or HANDLE 1112 * @handle: device handle 1113 * Context: sleep. 1114 * 1115 * Return: 0 for success, non-zero for failure. 1116 */ 1117 int 1118 mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc, 1119 Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, 1120 u32 form, u32 handle) 1121 { 1122 Mpi2ConfigRequest_t mpi_request; 1123 int r; 1124 1125 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1126 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1127 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1128 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1129 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 1130 mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION; 1131 mpi_request.Header.PageNumber = 0; 1132 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1133 r = _config_request(ioc, &mpi_request, mpi_reply, 1134 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1135 if (r) 1136 goto out; 1137 1138 mpi_request.PageAddress = cpu_to_le32(form | handle); 1139 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1140 r = _config_request(ioc, &mpi_request, mpi_reply, 1141 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1142 sizeof(*config_page)); 1143 out: 1144 return r; 1145 } 1146 1147 /** 1148 * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2 1149 * @ioc: per adapter object 1150 * @mpi_reply: reply mf payload returned from firmware 1151 * @config_page: contents of the config page 1152 * @form: GET_NEXT_HANDLE or HANDLE 1153 * @handle: device handle 1154 * Context: sleep. 1155 * 1156 * Return: 0 for success, non-zero for failure. 1157 */ 1158 int 1159 mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc, 1160 Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, 1161 u32 form, u32 handle) 1162 { 1163 Mpi2ConfigRequest_t mpi_request; 1164 int r; 1165 1166 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1167 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1168 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1169 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1170 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 1171 mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION; 1172 mpi_request.Header.PageNumber = 2; 1173 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1174 r = _config_request(ioc, &mpi_request, mpi_reply, 1175 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1176 if (r) 1177 goto out; 1178 1179 mpi_request.PageAddress = cpu_to_le32(form | handle); 1180 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1181 r = _config_request(ioc, &mpi_request, mpi_reply, 1182 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1183 sizeof(*config_page)); 1184 out: 1185 return r; 1186 } 1187 1188 /** 1189 * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host 1190 * @ioc: per adapter object 1191 * @num_phys: pointer returned with the number of phys 1192 * Context: sleep. 1193 * 1194 * Return: 0 for success, non-zero for failure. 1195 */ 1196 int 1197 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys) 1198 { 1199 Mpi2ConfigRequest_t mpi_request; 1200 int r; 1201 u16 ioc_status; 1202 Mpi2ConfigReply_t mpi_reply; 1203 Mpi2SasIOUnitPage0_t config_page; 1204 1205 *num_phys = 0; 1206 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1207 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1208 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1209 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1210 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 1211 mpi_request.Header.PageNumber = 0; 1212 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; 1213 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1214 r = _config_request(ioc, &mpi_request, &mpi_reply, 1215 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1216 if (r) 1217 goto out; 1218 1219 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1220 r = _config_request(ioc, &mpi_request, &mpi_reply, 1221 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, 1222 sizeof(Mpi2SasIOUnitPage0_t)); 1223 if (!r) { 1224 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & 1225 MPI2_IOCSTATUS_MASK; 1226 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) 1227 *num_phys = config_page.NumPhys; 1228 } 1229 out: 1230 return r; 1231 } 1232 1233 /** 1234 * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0 1235 * @ioc: per adapter object 1236 * @mpi_reply: reply mf payload returned from firmware 1237 * @config_page: contents of the config page 1238 * @sz: size of buffer passed in config_page 1239 * Context: sleep. 1240 * 1241 * Calling function should call config_get_number_hba_phys prior to 1242 * this function, so enough memory is allocated for config_page. 1243 * 1244 * Return: 0 for success, non-zero for failure. 1245 */ 1246 int 1247 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, 1248 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, 1249 u16 sz) 1250 { 1251 Mpi2ConfigRequest_t mpi_request; 1252 int r; 1253 1254 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1255 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1256 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1257 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1258 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 1259 mpi_request.Header.PageNumber = 0; 1260 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; 1261 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1262 r = _config_request(ioc, &mpi_request, mpi_reply, 1263 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1264 if (r) 1265 goto out; 1266 1267 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1268 r = _config_request(ioc, &mpi_request, mpi_reply, 1269 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1270 out: 1271 return r; 1272 } 1273 1274 /** 1275 * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1 1276 * @ioc: per adapter object 1277 * @mpi_reply: reply mf payload returned from firmware 1278 * @config_page: contents of the config page 1279 * @sz: size of buffer passed in config_page 1280 * Context: sleep. 1281 * 1282 * Calling function should call config_get_number_hba_phys prior to 1283 * this function, so enough memory is allocated for config_page. 1284 * 1285 * Return: 0 for success, non-zero for failure. 1286 */ 1287 int 1288 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, 1289 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, 1290 u16 sz) 1291 { 1292 Mpi2ConfigRequest_t mpi_request; 1293 int r; 1294 1295 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1296 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1297 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1298 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1299 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 1300 mpi_request.Header.PageNumber = 1; 1301 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; 1302 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1303 r = _config_request(ioc, &mpi_request, mpi_reply, 1304 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1305 if (r) 1306 goto out; 1307 1308 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1309 r = _config_request(ioc, &mpi_request, mpi_reply, 1310 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1311 out: 1312 return r; 1313 } 1314 1315 /** 1316 * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1 1317 * @ioc: per adapter object 1318 * @mpi_reply: reply mf payload returned from firmware 1319 * @config_page: contents of the config page 1320 * @sz: size of buffer passed in config_page 1321 * Context: sleep. 1322 * 1323 * Calling function should call config_get_number_hba_phys prior to 1324 * this function, so enough memory is allocated for config_page. 1325 * 1326 * Return: 0 for success, non-zero for failure. 1327 */ 1328 int 1329 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, 1330 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, 1331 u16 sz) 1332 { 1333 Mpi2ConfigRequest_t mpi_request; 1334 int r; 1335 1336 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1337 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1338 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1339 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1340 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 1341 mpi_request.Header.PageNumber = 1; 1342 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; 1343 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1344 r = _config_request(ioc, &mpi_request, mpi_reply, 1345 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1346 if (r) 1347 goto out; 1348 1349 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; 1350 _config_request(ioc, &mpi_request, mpi_reply, 1351 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1352 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 1353 r = _config_request(ioc, &mpi_request, mpi_reply, 1354 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1355 out: 1356 return r; 1357 } 1358 1359 /** 1360 * mpt3sas_config_get_expander_pg0 - obtain expander page 0 1361 * @ioc: per adapter object 1362 * @mpi_reply: reply mf payload returned from firmware 1363 * @config_page: contents of the config page 1364 * @form: GET_NEXT_HANDLE or HANDLE 1365 * @handle: expander handle 1366 * Context: sleep. 1367 * 1368 * Return: 0 for success, non-zero for failure. 1369 */ 1370 int 1371 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1372 *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle) 1373 { 1374 Mpi2ConfigRequest_t mpi_request; 1375 int r; 1376 1377 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1378 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1379 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1380 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1381 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; 1382 mpi_request.Header.PageNumber = 0; 1383 mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION; 1384 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1385 r = _config_request(ioc, &mpi_request, mpi_reply, 1386 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1387 if (r) 1388 goto out; 1389 1390 mpi_request.PageAddress = cpu_to_le32(form | handle); 1391 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1392 r = _config_request(ioc, &mpi_request, mpi_reply, 1393 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1394 sizeof(*config_page)); 1395 out: 1396 return r; 1397 } 1398 1399 /** 1400 * mpt3sas_config_get_expander_pg1 - obtain expander page 1 1401 * @ioc: per adapter object 1402 * @mpi_reply: reply mf payload returned from firmware 1403 * @config_page: contents of the config page 1404 * @phy_number: phy number 1405 * @handle: expander handle 1406 * Context: sleep. 1407 * 1408 * Return: 0 for success, non-zero for failure. 1409 */ 1410 int 1411 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1412 *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, 1413 u16 handle) 1414 { 1415 Mpi2ConfigRequest_t mpi_request; 1416 int r; 1417 1418 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1419 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1420 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1421 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1422 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; 1423 mpi_request.Header.PageNumber = 1; 1424 mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION; 1425 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1426 r = _config_request(ioc, &mpi_request, mpi_reply, 1427 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1428 if (r) 1429 goto out; 1430 1431 mpi_request.PageAddress = 1432 cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM | 1433 (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle); 1434 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1435 r = _config_request(ioc, &mpi_request, mpi_reply, 1436 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1437 sizeof(*config_page)); 1438 out: 1439 return r; 1440 } 1441 1442 /** 1443 * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0 1444 * @ioc: per adapter object 1445 * @mpi_reply: reply mf payload returned from firmware 1446 * @config_page: contents of the config page 1447 * @form: GET_NEXT_HANDLE or HANDLE 1448 * @handle: expander handle 1449 * Context: sleep. 1450 * 1451 * Return: 0 for success, non-zero for failure. 1452 */ 1453 int 1454 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1455 *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle) 1456 { 1457 Mpi2ConfigRequest_t mpi_request; 1458 int r; 1459 1460 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1461 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1462 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1463 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1464 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE; 1465 mpi_request.Header.PageNumber = 0; 1466 mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION; 1467 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1468 r = _config_request(ioc, &mpi_request, mpi_reply, 1469 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1470 if (r) 1471 goto out; 1472 1473 mpi_request.PageAddress = cpu_to_le32(form | handle); 1474 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1475 r = _config_request(ioc, &mpi_request, mpi_reply, 1476 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1477 sizeof(*config_page)); 1478 out: 1479 return r; 1480 } 1481 1482 /** 1483 * mpt3sas_config_get_phy_pg0 - obtain phy page 0 1484 * @ioc: per adapter object 1485 * @mpi_reply: reply mf payload returned from firmware 1486 * @config_page: contents of the config page 1487 * @phy_number: phy number 1488 * Context: sleep. 1489 * 1490 * Return: 0 for success, non-zero for failure. 1491 */ 1492 int 1493 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1494 *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number) 1495 { 1496 Mpi2ConfigRequest_t mpi_request; 1497 int r; 1498 1499 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1500 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1501 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1502 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1503 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; 1504 mpi_request.Header.PageNumber = 0; 1505 mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION; 1506 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1507 r = _config_request(ioc, &mpi_request, mpi_reply, 1508 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1509 if (r) 1510 goto out; 1511 1512 mpi_request.PageAddress = 1513 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); 1514 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1515 r = _config_request(ioc, &mpi_request, mpi_reply, 1516 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1517 sizeof(*config_page)); 1518 out: 1519 return r; 1520 } 1521 1522 /** 1523 * mpt3sas_config_get_phy_pg1 - obtain phy page 1 1524 * @ioc: per adapter object 1525 * @mpi_reply: reply mf payload returned from firmware 1526 * @config_page: contents of the config page 1527 * @phy_number: phy number 1528 * Context: sleep. 1529 * 1530 * Return: 0 for success, non-zero for failure. 1531 */ 1532 int 1533 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1534 *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number) 1535 { 1536 Mpi2ConfigRequest_t mpi_request; 1537 int r; 1538 1539 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1540 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1541 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1542 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1543 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; 1544 mpi_request.Header.PageNumber = 1; 1545 mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION; 1546 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1547 r = _config_request(ioc, &mpi_request, mpi_reply, 1548 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1549 if (r) 1550 goto out; 1551 1552 mpi_request.PageAddress = 1553 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); 1554 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1555 r = _config_request(ioc, &mpi_request, mpi_reply, 1556 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1557 sizeof(*config_page)); 1558 out: 1559 return r; 1560 } 1561 1562 /** 1563 * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1 1564 * @ioc: per adapter object 1565 * @mpi_reply: reply mf payload returned from firmware 1566 * @config_page: contents of the config page 1567 * @form: GET_NEXT_HANDLE or HANDLE 1568 * @handle: volume handle 1569 * Context: sleep. 1570 * 1571 * Return: 0 for success, non-zero for failure. 1572 */ 1573 int 1574 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc, 1575 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, 1576 u32 handle) 1577 { 1578 Mpi2ConfigRequest_t mpi_request; 1579 int r; 1580 1581 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1582 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1583 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1584 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1585 mpi_request.Header.PageNumber = 1; 1586 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; 1587 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1588 r = _config_request(ioc, &mpi_request, mpi_reply, 1589 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1590 if (r) 1591 goto out; 1592 1593 mpi_request.PageAddress = cpu_to_le32(form | handle); 1594 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1595 r = _config_request(ioc, &mpi_request, mpi_reply, 1596 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1597 sizeof(*config_page)); 1598 out: 1599 return r; 1600 } 1601 1602 /** 1603 * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume 1604 * @ioc: per adapter object 1605 * @handle: volume handle 1606 * @num_pds: returns pds count 1607 * Context: sleep. 1608 * 1609 * Return: 0 for success, non-zero for failure. 1610 */ 1611 int 1612 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle, 1613 u8 *num_pds) 1614 { 1615 Mpi2ConfigRequest_t mpi_request; 1616 Mpi2RaidVolPage0_t config_page; 1617 Mpi2ConfigReply_t mpi_reply; 1618 int r; 1619 u16 ioc_status; 1620 1621 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1622 *num_pds = 0; 1623 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1624 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1625 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1626 mpi_request.Header.PageNumber = 0; 1627 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1628 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1629 r = _config_request(ioc, &mpi_request, &mpi_reply, 1630 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1631 if (r) 1632 goto out; 1633 1634 mpi_request.PageAddress = 1635 cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle); 1636 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1637 r = _config_request(ioc, &mpi_request, &mpi_reply, 1638 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, 1639 sizeof(Mpi2RaidVolPage0_t)); 1640 if (!r) { 1641 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & 1642 MPI2_IOCSTATUS_MASK; 1643 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) 1644 *num_pds = config_page.NumPhysDisks; 1645 } 1646 1647 out: 1648 return r; 1649 } 1650 1651 /** 1652 * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0 1653 * @ioc: per adapter object 1654 * @mpi_reply: reply mf payload returned from firmware 1655 * @config_page: contents of the config page 1656 * @form: GET_NEXT_HANDLE or HANDLE 1657 * @handle: volume handle 1658 * @sz: size of buffer passed in config_page 1659 * Context: sleep. 1660 * 1661 * Return: 0 for success, non-zero for failure. 1662 */ 1663 int 1664 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc, 1665 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, 1666 u32 handle, u16 sz) 1667 { 1668 Mpi2ConfigRequest_t mpi_request; 1669 int r; 1670 1671 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1672 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1673 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1674 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1675 mpi_request.Header.PageNumber = 0; 1676 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1677 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1678 r = _config_request(ioc, &mpi_request, mpi_reply, 1679 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1680 if (r) 1681 goto out; 1682 1683 mpi_request.PageAddress = cpu_to_le32(form | handle); 1684 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1685 r = _config_request(ioc, &mpi_request, mpi_reply, 1686 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1687 out: 1688 return r; 1689 } 1690 1691 /** 1692 * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0 1693 * @ioc: per adapter object 1694 * @mpi_reply: reply mf payload returned from firmware 1695 * @config_page: contents of the config page 1696 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE 1697 * @form_specific: specific to the form 1698 * Context: sleep. 1699 * 1700 * Return: 0 for success, non-zero for failure. 1701 */ 1702 int 1703 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1704 *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, 1705 u32 form_specific) 1706 { 1707 Mpi2ConfigRequest_t mpi_request; 1708 int r; 1709 1710 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1711 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1712 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1713 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1714 mpi_request.Header.PageNumber = 0; 1715 mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; 1716 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1717 r = _config_request(ioc, &mpi_request, mpi_reply, 1718 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1719 if (r) 1720 goto out; 1721 1722 mpi_request.PageAddress = cpu_to_le32(form | form_specific); 1723 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1724 r = _config_request(ioc, &mpi_request, mpi_reply, 1725 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1726 sizeof(*config_page)); 1727 out: 1728 return r; 1729 } 1730 1731 /** 1732 * mpt3sas_config_get_volume_handle - returns volume handle for give hidden 1733 * raid components 1734 * @ioc: per adapter object 1735 * @pd_handle: phys disk handle 1736 * @volume_handle: volume handle 1737 * Context: sleep. 1738 * 1739 * Return: 0 for success, non-zero for failure. 1740 */ 1741 int 1742 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle, 1743 u16 *volume_handle) 1744 { 1745 Mpi2RaidConfigurationPage0_t *config_page = NULL; 1746 Mpi2ConfigRequest_t mpi_request; 1747 Mpi2ConfigReply_t mpi_reply; 1748 int r, i, config_page_sz; 1749 u16 ioc_status; 1750 int config_num; 1751 u16 element_type; 1752 u16 phys_disk_dev_handle; 1753 1754 *volume_handle = 0; 1755 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1756 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1757 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1758 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1759 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG; 1760 mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION; 1761 mpi_request.Header.PageNumber = 0; 1762 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1763 r = _config_request(ioc, &mpi_request, &mpi_reply, 1764 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1765 if (r) 1766 goto out; 1767 1768 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1769 config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4); 1770 config_page = kmalloc(config_page_sz, GFP_KERNEL); 1771 if (!config_page) { 1772 r = -1; 1773 goto out; 1774 } 1775 1776 config_num = 0xff; 1777 while (1) { 1778 mpi_request.PageAddress = cpu_to_le32(config_num + 1779 MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM); 1780 r = _config_request(ioc, &mpi_request, &mpi_reply, 1781 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1782 config_page_sz); 1783 if (r) 1784 goto out; 1785 r = -1; 1786 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & 1787 MPI2_IOCSTATUS_MASK; 1788 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) 1789 goto out; 1790 for (i = 0; i < config_page->NumElements; i++) { 1791 element_type = le16_to_cpu(config_page-> 1792 ConfigElement[i].ElementFlags) & 1793 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; 1794 if (element_type == 1795 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT || 1796 element_type == 1797 MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) { 1798 phys_disk_dev_handle = 1799 le16_to_cpu(config_page->ConfigElement[i]. 1800 PhysDiskDevHandle); 1801 if (phys_disk_dev_handle == pd_handle) { 1802 *volume_handle = 1803 le16_to_cpu(config_page-> 1804 ConfigElement[i].VolDevHandle); 1805 r = 0; 1806 goto out; 1807 } 1808 } else if (element_type == 1809 MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) { 1810 *volume_handle = 0; 1811 r = 0; 1812 goto out; 1813 } 1814 } 1815 config_num = config_page->ConfigNum; 1816 } 1817 out: 1818 kfree(config_page); 1819 return r; 1820 } 1821 1822 /** 1823 * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle 1824 * @ioc: per adapter object 1825 * @volume_handle: volume handle 1826 * @wwid: volume wwid 1827 * Context: sleep. 1828 * 1829 * Return: 0 for success, non-zero for failure. 1830 */ 1831 int 1832 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle, 1833 u64 *wwid) 1834 { 1835 Mpi2ConfigReply_t mpi_reply; 1836 Mpi2RaidVolPage1_t raid_vol_pg1; 1837 1838 *wwid = 0; 1839 if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, 1840 &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, 1841 volume_handle))) { 1842 *wwid = le64_to_cpu(raid_vol_pg1.WWID); 1843 return 0; 1844 } else 1845 return -1; 1846 } 1847