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-2010 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/version.h> 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 helpfull 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_mappping"; 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_ioc_pg8 - obtain ioc page 8 688 * @ioc: per adapter object 689 * @mpi_reply: reply mf payload returned from firmware 690 * @config_page: contents of the config page 691 * Context: sleep. 692 * 693 * Returns 0 for success, non-zero for failure. 694 */ 695int 696mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, 697 Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page) 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_IOC; 706 mpi_request.Header.PageNumber = 8; 707 mpi_request.Header.PageVersion = MPI2_IOCPAGE8_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, 717 sizeof(*config_page)); 718 out: 719 return r; 720} 721 722/** 723 * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0 724 * @ioc: per adapter object 725 * @mpi_reply: reply mf payload returned from firmware 726 * @config_page: contents of the config page 727 * @form: GET_NEXT_HANDLE or HANDLE 728 * @handle: device handle 729 * Context: sleep. 730 * 731 * Returns 0 for success, non-zero for failure. 732 */ 733int 734mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 735 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle) 736{ 737 Mpi2ConfigRequest_t mpi_request; 738 int r; 739 740 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 741 mpi_request.Function = MPI2_FUNCTION_CONFIG; 742 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 743 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 744 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 745 mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 746 mpi_request.Header.PageNumber = 0; 747 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 748 r = _config_request(ioc, &mpi_request, mpi_reply, 749 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 750 if (r) 751 goto out; 752 753 mpi_request.PageAddress = cpu_to_le32(form | handle); 754 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 755 r = _config_request(ioc, &mpi_request, mpi_reply, 756 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 757 sizeof(*config_page)); 758 out: 759 return r; 760} 761 762/** 763 * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1 764 * @ioc: per adapter object 765 * @mpi_reply: reply mf payload returned from firmware 766 * @config_page: contents of the config page 767 * @form: GET_NEXT_HANDLE or HANDLE 768 * @handle: device handle 769 * Context: sleep. 770 * 771 * Returns 0 for success, non-zero for failure. 772 */ 773int 774mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 775 *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle) 776{ 777 Mpi2ConfigRequest_t mpi_request; 778 int r; 779 780 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 781 mpi_request.Function = MPI2_FUNCTION_CONFIG; 782 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 783 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 784 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 785 mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION; 786 mpi_request.Header.PageNumber = 1; 787 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 788 r = _config_request(ioc, &mpi_request, mpi_reply, 789 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 790 if (r) 791 goto out; 792 793 mpi_request.PageAddress = cpu_to_le32(form | handle); 794 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 795 r = _config_request(ioc, &mpi_request, mpi_reply, 796 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 797 sizeof(*config_page)); 798 out: 799 return r; 800} 801 802/** 803 * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host 804 * @ioc: per adapter object 805 * @num_phys: pointer returned with the number of phys 806 * Context: sleep. 807 * 808 * Returns 0 for success, non-zero for failure. 809 */ 810int 811mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) 812{ 813 Mpi2ConfigRequest_t mpi_request; 814 int r; 815 u16 ioc_status; 816 Mpi2ConfigReply_t mpi_reply; 817 Mpi2SasIOUnitPage0_t config_page; 818 819 *num_phys = 0; 820 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 821 mpi_request.Function = MPI2_FUNCTION_CONFIG; 822 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 823 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 824 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 825 mpi_request.Header.PageNumber = 0; 826 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; 827 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 828 r = _config_request(ioc, &mpi_request, &mpi_reply, 829 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 830 if (r) 831 goto out; 832 833 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 834 r = _config_request(ioc, &mpi_request, &mpi_reply, 835 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, 836 sizeof(Mpi2SasIOUnitPage0_t)); 837 if (!r) { 838 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & 839 MPI2_IOCSTATUS_MASK; 840 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) 841 *num_phys = config_page.NumPhys; 842 } 843 out: 844 return r; 845} 846 847/** 848 * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0 849 * @ioc: per adapter object 850 * @mpi_reply: reply mf payload returned from firmware 851 * @config_page: contents of the config page 852 * @sz: size of buffer passed in config_page 853 * Context: sleep. 854 * 855 * Calling function should call config_get_number_hba_phys prior to 856 * this function, so enough memory is allocated for config_page. 857 * 858 * Returns 0 for success, non-zero for failure. 859 */ 860int 861mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 862 *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz) 863{ 864 Mpi2ConfigRequest_t mpi_request; 865 int r; 866 867 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 868 mpi_request.Function = MPI2_FUNCTION_CONFIG; 869 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 870 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 871 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 872 mpi_request.Header.PageNumber = 0; 873 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; 874 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 875 r = _config_request(ioc, &mpi_request, mpi_reply, 876 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 877 if (r) 878 goto out; 879 880 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 881 r = _config_request(ioc, &mpi_request, mpi_reply, 882 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 883 out: 884 return r; 885} 886 887/** 888 * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1 889 * @ioc: per adapter object 890 * @mpi_reply: reply mf payload returned from firmware 891 * @config_page: contents of the config page 892 * @sz: size of buffer passed in config_page 893 * Context: sleep. 894 * 895 * Calling function should call config_get_number_hba_phys prior to 896 * this function, so enough memory is allocated for config_page. 897 * 898 * Returns 0 for success, non-zero for failure. 899 */ 900int 901mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 902 *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz) 903{ 904 Mpi2ConfigRequest_t mpi_request; 905 int r; 906 907 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 908 mpi_request.Function = MPI2_FUNCTION_CONFIG; 909 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 910 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 911 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 912 mpi_request.Header.PageNumber = 1; 913 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; 914 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 915 r = _config_request(ioc, &mpi_request, mpi_reply, 916 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 917 if (r) 918 goto out; 919 920 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 921 r = _config_request(ioc, &mpi_request, mpi_reply, 922 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 923 out: 924 return r; 925} 926 927/** 928 * mpt2sas_config_set_sas_iounit_pg1 - send sas iounit page 1 929 * @ioc: per adapter object 930 * @mpi_reply: reply mf payload returned from firmware 931 * @config_page: contents of the config page 932 * @sz: size of buffer passed in config_page 933 * Context: sleep. 934 * 935 * Calling function should call config_get_number_hba_phys prior to 936 * this function, so enough memory is allocated for config_page. 937 * 938 * Returns 0 for success, non-zero for failure. 939 */ 940int 941mpt2sas_config_set_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 942 *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz) 943{ 944 Mpi2ConfigRequest_t mpi_request; 945 int r; 946 947 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 948 mpi_request.Function = MPI2_FUNCTION_CONFIG; 949 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 950 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 951 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 952 mpi_request.Header.PageNumber = 1; 953 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; 954 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 955 r = _config_request(ioc, &mpi_request, mpi_reply, 956 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 957 if (r) 958 goto out; 959 960 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; 961 _config_request(ioc, &mpi_request, mpi_reply, 962 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 963 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 964 r = _config_request(ioc, &mpi_request, mpi_reply, 965 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 966 out: 967 return r; 968} 969 970/** 971 * mpt2sas_config_get_expander_pg0 - obtain expander page 0 972 * @ioc: per adapter object 973 * @mpi_reply: reply mf payload returned from firmware 974 * @config_page: contents of the config page 975 * @form: GET_NEXT_HANDLE or HANDLE 976 * @handle: expander handle 977 * Context: sleep. 978 * 979 * Returns 0 for success, non-zero for failure. 980 */ 981int 982mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 983 *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle) 984{ 985 Mpi2ConfigRequest_t mpi_request; 986 int r; 987 988 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 989 mpi_request.Function = MPI2_FUNCTION_CONFIG; 990 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 991 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 992 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; 993 mpi_request.Header.PageNumber = 0; 994 mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION; 995 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 996 r = _config_request(ioc, &mpi_request, mpi_reply, 997 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 998 if (r) 999 goto out; 1000 1001 mpi_request.PageAddress = cpu_to_le32(form | handle); 1002 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1003 r = _config_request(ioc, &mpi_request, mpi_reply, 1004 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1005 sizeof(*config_page)); 1006 out: 1007 return r; 1008} 1009 1010/** 1011 * mpt2sas_config_get_expander_pg1 - obtain expander page 1 1012 * @ioc: per adapter object 1013 * @mpi_reply: reply mf payload returned from firmware 1014 * @config_page: contents of the config page 1015 * @phy_number: phy number 1016 * @handle: expander handle 1017 * Context: sleep. 1018 * 1019 * Returns 0 for success, non-zero for failure. 1020 */ 1021int 1022mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1023 *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, 1024 u16 handle) 1025{ 1026 Mpi2ConfigRequest_t mpi_request; 1027 int r; 1028 1029 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1030 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1031 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1032 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1033 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; 1034 mpi_request.Header.PageNumber = 1; 1035 mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION; 1036 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 1037 r = _config_request(ioc, &mpi_request, mpi_reply, 1038 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1039 if (r) 1040 goto out; 1041 1042 mpi_request.PageAddress = 1043 cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM | 1044 (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle); 1045 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1046 r = _config_request(ioc, &mpi_request, mpi_reply, 1047 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1048 sizeof(*config_page)); 1049 out: 1050 return r; 1051} 1052 1053/** 1054 * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0 1055 * @ioc: per adapter object 1056 * @mpi_reply: reply mf payload returned from firmware 1057 * @config_page: contents of the config page 1058 * @form: GET_NEXT_HANDLE or HANDLE 1059 * @handle: expander handle 1060 * Context: sleep. 1061 * 1062 * Returns 0 for success, non-zero for failure. 1063 */ 1064int 1065mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1066 *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle) 1067{ 1068 Mpi2ConfigRequest_t mpi_request; 1069 int r; 1070 1071 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1072 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1073 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1074 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1075 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE; 1076 mpi_request.Header.PageNumber = 0; 1077 mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION; 1078 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 1079 r = _config_request(ioc, &mpi_request, mpi_reply, 1080 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1081 if (r) 1082 goto out; 1083 1084 mpi_request.PageAddress = cpu_to_le32(form | handle); 1085 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1086 r = _config_request(ioc, &mpi_request, mpi_reply, 1087 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1088 sizeof(*config_page)); 1089 out: 1090 return r; 1091} 1092 1093/** 1094 * mpt2sas_config_get_phy_pg0 - obtain phy page 0 1095 * @ioc: per adapter object 1096 * @mpi_reply: reply mf payload returned from firmware 1097 * @config_page: contents of the config page 1098 * @phy_number: phy number 1099 * Context: sleep. 1100 * 1101 * Returns 0 for success, non-zero for failure. 1102 */ 1103int 1104mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1105 *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number) 1106{ 1107 Mpi2ConfigRequest_t mpi_request; 1108 int r; 1109 1110 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1111 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1112 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1113 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1114 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; 1115 mpi_request.Header.PageNumber = 0; 1116 mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION; 1117 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 1118 r = _config_request(ioc, &mpi_request, mpi_reply, 1119 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1120 if (r) 1121 goto out; 1122 1123 mpi_request.PageAddress = 1124 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); 1125 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1126 r = _config_request(ioc, &mpi_request, mpi_reply, 1127 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1128 sizeof(*config_page)); 1129 out: 1130 return r; 1131} 1132 1133/** 1134 * mpt2sas_config_get_phy_pg1 - obtain phy page 1 1135 * @ioc: per adapter object 1136 * @mpi_reply: reply mf payload returned from firmware 1137 * @config_page: contents of the config page 1138 * @phy_number: phy number 1139 * Context: sleep. 1140 * 1141 * Returns 0 for success, non-zero for failure. 1142 */ 1143int 1144mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1145 *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number) 1146{ 1147 Mpi2ConfigRequest_t mpi_request; 1148 int r; 1149 1150 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1151 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1152 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1153 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1154 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; 1155 mpi_request.Header.PageNumber = 1; 1156 mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION; 1157 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 1158 r = _config_request(ioc, &mpi_request, mpi_reply, 1159 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1160 if (r) 1161 goto out; 1162 1163 mpi_request.PageAddress = 1164 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); 1165 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1166 r = _config_request(ioc, &mpi_request, mpi_reply, 1167 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1168 sizeof(*config_page)); 1169 out: 1170 return r; 1171} 1172 1173/** 1174 * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1 1175 * @ioc: per adapter object 1176 * @mpi_reply: reply mf payload returned from firmware 1177 * @config_page: contents of the config page 1178 * @form: GET_NEXT_HANDLE or HANDLE 1179 * @handle: volume handle 1180 * Context: sleep. 1181 * 1182 * Returns 0 for success, non-zero for failure. 1183 */ 1184int 1185mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, 1186 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, 1187 u32 handle) 1188{ 1189 Mpi2ConfigRequest_t mpi_request; 1190 int r; 1191 1192 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1193 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1194 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1195 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1196 mpi_request.Header.PageNumber = 1; 1197 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; 1198 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 1199 r = _config_request(ioc, &mpi_request, mpi_reply, 1200 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1201 if (r) 1202 goto out; 1203 1204 mpi_request.PageAddress = cpu_to_le32(form | handle); 1205 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1206 r = _config_request(ioc, &mpi_request, mpi_reply, 1207 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1208 sizeof(*config_page)); 1209 out: 1210 return r; 1211} 1212 1213/** 1214 * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume 1215 * @ioc: per adapter object 1216 * @handle: volume handle 1217 * @num_pds: returns pds count 1218 * Context: sleep. 1219 * 1220 * Returns 0 for success, non-zero for failure. 1221 */ 1222int 1223mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, 1224 u8 *num_pds) 1225{ 1226 Mpi2ConfigRequest_t mpi_request; 1227 Mpi2RaidVolPage0_t config_page; 1228 Mpi2ConfigReply_t mpi_reply; 1229 int r; 1230 u16 ioc_status; 1231 1232 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1233 *num_pds = 0; 1234 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1235 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1236 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1237 mpi_request.Header.PageNumber = 0; 1238 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1239 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 1240 r = _config_request(ioc, &mpi_request, &mpi_reply, 1241 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1242 if (r) 1243 goto out; 1244 1245 mpi_request.PageAddress = 1246 cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle); 1247 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1248 r = _config_request(ioc, &mpi_request, &mpi_reply, 1249 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, 1250 sizeof(Mpi2RaidVolPage0_t)); 1251 if (!r) { 1252 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & 1253 MPI2_IOCSTATUS_MASK; 1254 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) 1255 *num_pds = config_page.NumPhysDisks; 1256 } 1257 1258 out: 1259 return r; 1260} 1261 1262/** 1263 * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0 1264 * @ioc: per adapter object 1265 * @mpi_reply: reply mf payload returned from firmware 1266 * @config_page: contents of the config page 1267 * @form: GET_NEXT_HANDLE or HANDLE 1268 * @handle: volume handle 1269 * @sz: size of buffer passed in config_page 1270 * Context: sleep. 1271 * 1272 * Returns 0 for success, non-zero for failure. 1273 */ 1274int 1275mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, 1276 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, 1277 u32 handle, u16 sz) 1278{ 1279 Mpi2ConfigRequest_t mpi_request; 1280 int r; 1281 1282 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1283 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1284 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1285 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1286 mpi_request.Header.PageNumber = 0; 1287 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1288 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 1289 r = _config_request(ioc, &mpi_request, mpi_reply, 1290 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1291 if (r) 1292 goto out; 1293 1294 mpi_request.PageAddress = cpu_to_le32(form | handle); 1295 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1296 r = _config_request(ioc, &mpi_request, mpi_reply, 1297 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); 1298 out: 1299 return r; 1300} 1301 1302/** 1303 * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0 1304 * @ioc: per adapter object 1305 * @mpi_reply: reply mf payload returned from firmware 1306 * @config_page: contents of the config page 1307 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE 1308 * @form_specific: specific to the form 1309 * Context: sleep. 1310 * 1311 * Returns 0 for success, non-zero for failure. 1312 */ 1313int 1314mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1315 *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, 1316 u32 form_specific) 1317{ 1318 Mpi2ConfigRequest_t mpi_request; 1319 int r; 1320 1321 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1322 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1323 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1324 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1325 mpi_request.Header.PageNumber = 0; 1326 mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; 1327 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 1328 r = _config_request(ioc, &mpi_request, mpi_reply, 1329 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1330 if (r) 1331 goto out; 1332 1333 mpi_request.PageAddress = cpu_to_le32(form | form_specific); 1334 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1335 r = _config_request(ioc, &mpi_request, mpi_reply, 1336 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1337 sizeof(*config_page)); 1338 out: 1339 return r; 1340} 1341 1342/** 1343 * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components 1344 * @ioc: per adapter object 1345 * @pd_handle: phys disk handle 1346 * @volume_handle: volume handle 1347 * Context: sleep. 1348 * 1349 * Returns 0 for success, non-zero for failure. 1350 */ 1351int 1352mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, 1353 u16 *volume_handle) 1354{ 1355 Mpi2RaidConfigurationPage0_t *config_page = NULL; 1356 Mpi2ConfigRequest_t mpi_request; 1357 Mpi2ConfigReply_t mpi_reply; 1358 int r, i, config_page_sz; 1359 u16 ioc_status; 1360 1361 *volume_handle = 0; 1362 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1363 mpi_request.Function = MPI2_FUNCTION_CONFIG; 1364 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1365 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1366 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG; 1367 mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION; 1368 mpi_request.Header.PageNumber = 0; 1369 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); 1370 r = _config_request(ioc, &mpi_request, &mpi_reply, 1371 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1372 if (r) 1373 goto out; 1374 1375 mpi_request.PageAddress = 1376 cpu_to_le32(MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG); 1377 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1378 config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4); 1379 config_page = kmalloc(config_page_sz, GFP_KERNEL); 1380 if (!config_page) 1381 goto out; 1382 r = _config_request(ioc, &mpi_request, &mpi_reply, 1383 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1384 config_page_sz); 1385 if (r) 1386 goto out; 1387 1388 r = -1; 1389 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; 1390 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) 1391 goto out; 1392 for (i = 0; i < config_page->NumElements; i++) { 1393 if ((le16_to_cpu(config_page->ConfigElement[i].ElementFlags) & 1394 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE) != 1395 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT) 1396 continue; 1397 if (le16_to_cpu(config_page->ConfigElement[i]. 1398 PhysDiskDevHandle) == pd_handle) { 1399 *volume_handle = le16_to_cpu(config_page-> 1400 ConfigElement[i].VolDevHandle); 1401 r = 0; 1402 goto out; 1403 } 1404 } 1405 out: 1406 kfree(config_page); 1407 return r; 1408} 1409 1410/** 1411 * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle 1412 * @ioc: per adapter object 1413 * @volume_handle: volume handle 1414 * @wwid: volume wwid 1415 * Context: sleep. 1416 * 1417 * Returns 0 for success, non-zero for failure. 1418 */ 1419int 1420mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle, 1421 u64 *wwid) 1422{ 1423 Mpi2ConfigReply_t mpi_reply; 1424 Mpi2RaidVolPage1_t raid_vol_pg1; 1425 1426 *wwid = 0; 1427 if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, 1428 &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, 1429 volume_handle))) { 1430 *wwid = le64_to_cpu(raid_vol_pg1.WWID); 1431 return 0; 1432 } else 1433 return -1; 1434} 1435