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