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