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