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