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