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