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