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