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