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