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