1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Driver for Broadcom MPI3 Storage Controllers 4 * 5 * Copyright (C) 2017-2023 Broadcom Inc. 6 * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com) 7 * 8 */ 9 10 #include <linux/vmalloc.h> 11 12 #include "mpi3mr.h" 13 14 /** 15 * mpi3mr_post_transport_req - Issue transport requests and wait 16 * @mrioc: Adapter instance reference 17 * @request: Properly populated MPI3 request 18 * @request_sz: Size of the MPI3 request 19 * @reply: Pointer to return MPI3 reply 20 * @reply_sz: Size of the MPI3 reply buffer 21 * @timeout: Timeout in seconds 22 * @ioc_status: Pointer to return ioc status 23 * 24 * A generic function for posting MPI3 requests from the SAS 25 * transport layer that uses transport command infrastructure. 26 * This blocks for the completion of request for timeout seconds 27 * and if the request times out this function faults the 28 * controller with proper reason code. 29 * 30 * On successful completion of the request this function returns 31 * appropriate ioc status from the firmware back to the caller. 32 * 33 * Return: 0 on success, non-zero on failure. 34 */ 35 static int mpi3mr_post_transport_req(struct mpi3mr_ioc *mrioc, void *request, 36 u16 request_sz, void *reply, u16 reply_sz, int timeout, 37 u16 *ioc_status) 38 { 39 int retval = 0; 40 41 mutex_lock(&mrioc->transport_cmds.mutex); 42 if (mrioc->transport_cmds.state & MPI3MR_CMD_PENDING) { 43 retval = -1; 44 ioc_err(mrioc, "sending transport request failed due to command in use\n"); 45 mutex_unlock(&mrioc->transport_cmds.mutex); 46 goto out; 47 } 48 mrioc->transport_cmds.state = MPI3MR_CMD_PENDING; 49 mrioc->transport_cmds.is_waiting = 1; 50 mrioc->transport_cmds.callback = NULL; 51 mrioc->transport_cmds.ioc_status = 0; 52 mrioc->transport_cmds.ioc_loginfo = 0; 53 54 init_completion(&mrioc->transport_cmds.done); 55 dprint_cfg_info(mrioc, "posting transport request\n"); 56 if (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO) 57 dprint_dump(request, request_sz, "transport_req"); 58 retval = mpi3mr_admin_request_post(mrioc, request, request_sz, 1); 59 if (retval) { 60 ioc_err(mrioc, "posting transport request failed\n"); 61 goto out_unlock; 62 } 63 wait_for_completion_timeout(&mrioc->transport_cmds.done, 64 (timeout * HZ)); 65 if (!(mrioc->transport_cmds.state & MPI3MR_CMD_COMPLETE)) { 66 mpi3mr_check_rh_fault_ioc(mrioc, 67 MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT); 68 ioc_err(mrioc, "transport request timed out\n"); 69 retval = -1; 70 goto out_unlock; 71 } 72 *ioc_status = mrioc->transport_cmds.ioc_status & 73 MPI3_IOCSTATUS_STATUS_MASK; 74 if ((*ioc_status) != MPI3_IOCSTATUS_SUCCESS) 75 dprint_transport_err(mrioc, 76 "transport request returned with ioc_status(0x%04x), log_info(0x%08x)\n", 77 *ioc_status, mrioc->transport_cmds.ioc_loginfo); 78 79 if ((reply) && (mrioc->transport_cmds.state & MPI3MR_CMD_REPLY_VALID)) 80 memcpy((u8 *)reply, mrioc->transport_cmds.reply, reply_sz); 81 82 out_unlock: 83 mrioc->transport_cmds.state = MPI3MR_CMD_NOTUSED; 84 mutex_unlock(&mrioc->transport_cmds.mutex); 85 86 out: 87 return retval; 88 } 89 90 /* report manufacture request structure */ 91 struct rep_manu_request { 92 u8 smp_frame_type; 93 u8 function; 94 u8 reserved; 95 u8 request_length; 96 }; 97 98 /* report manufacture reply structure */ 99 struct rep_manu_reply { 100 u8 smp_frame_type; /* 0x41 */ 101 u8 function; /* 0x01 */ 102 u8 function_result; 103 u8 response_length; 104 u16 expander_change_count; 105 u8 reserved0[2]; 106 u8 sas_format; 107 u8 reserved2[3]; 108 u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN] __nonstring; 109 u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN] __nonstring; 110 u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN] __nonstring; 111 u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN] __nonstring; 112 u16 component_id; 113 u8 component_revision_id; 114 u8 reserved3; 115 u8 vendor_specific[8]; 116 }; 117 118 /** 119 * mpi3mr_report_manufacture - obtain SMP report_manufacture 120 * @mrioc: Adapter instance reference 121 * @sas_address: SAS address of the expander device 122 * @edev: SAS transport layer sas_expander_device object 123 * @port_id: ID of the HBA port 124 * 125 * Fills in the sas_expander_device with manufacturing info. 126 * 127 * Return: 0 for success, non-zero for failure. 128 */ 129 static int mpi3mr_report_manufacture(struct mpi3mr_ioc *mrioc, 130 u64 sas_address, struct sas_expander_device *edev, u8 port_id) 131 { 132 struct mpi3_smp_passthrough_request mpi_request; 133 struct mpi3_smp_passthrough_reply mpi_reply; 134 struct rep_manu_reply *manufacture_reply; 135 struct rep_manu_request *manufacture_request; 136 int rc = 0; 137 void *psge; 138 void *data_out = NULL; 139 dma_addr_t data_out_dma; 140 dma_addr_t data_in_dma; 141 size_t data_in_sz; 142 size_t data_out_sz; 143 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST; 144 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request); 145 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply); 146 u16 ioc_status; 147 u8 *tmp; 148 149 if (mrioc->reset_in_progress) { 150 ioc_err(mrioc, "%s: host reset in progress!\n", __func__); 151 return -EFAULT; 152 } 153 154 if (mrioc->pci_err_recovery) { 155 ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__); 156 return -EFAULT; 157 } 158 159 data_out_sz = sizeof(struct rep_manu_request); 160 data_in_sz = sizeof(struct rep_manu_reply); 161 data_out = dma_alloc_coherent(&mrioc->pdev->dev, 162 data_out_sz + data_in_sz, &data_out_dma, GFP_KERNEL); 163 if (!data_out) { 164 rc = -ENOMEM; 165 goto out; 166 } 167 168 data_in_dma = data_out_dma + data_out_sz; 169 manufacture_reply = data_out + data_out_sz; 170 171 manufacture_request = data_out; 172 manufacture_request->smp_frame_type = 0x40; 173 manufacture_request->function = 1; 174 manufacture_request->reserved = 0; 175 manufacture_request->request_length = 0; 176 177 memset(&mpi_request, 0, request_sz); 178 memset(&mpi_reply, 0, reply_sz); 179 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS); 180 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH; 181 mpi_request.io_unit_port = (u8) port_id; 182 mpi_request.sas_address = cpu_to_le64(sas_address); 183 184 psge = &mpi_request.request_sge; 185 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma); 186 187 psge = &mpi_request.response_sge; 188 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma); 189 190 dprint_transport_info(mrioc, 191 "sending report manufacturer SMP request to sas_address(0x%016llx), port(%d)\n", 192 (unsigned long long)sas_address, port_id); 193 194 rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz, 195 &mpi_reply, reply_sz, 196 MPI3MR_INTADMCMD_TIMEOUT, &ioc_status); 197 if (rc) 198 goto out; 199 200 dprint_transport_info(mrioc, 201 "report manufacturer SMP request completed with ioc_status(0x%04x)\n", 202 ioc_status); 203 204 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 205 rc = -EINVAL; 206 goto out; 207 } 208 209 dprint_transport_info(mrioc, 210 "report manufacturer - reply data transfer size(%d)\n", 211 le16_to_cpu(mpi_reply.response_data_length)); 212 213 if (le16_to_cpu(mpi_reply.response_data_length) != 214 sizeof(struct rep_manu_reply)) { 215 rc = -EINVAL; 216 goto out; 217 } 218 219 memtostr(edev->vendor_id, manufacture_reply->vendor_id); 220 memtostr(edev->product_id, manufacture_reply->product_id); 221 memtostr(edev->product_rev, manufacture_reply->product_rev); 222 edev->level = manufacture_reply->sas_format & 1; 223 if (edev->level) { 224 memtostr(edev->component_vendor_id, 225 manufacture_reply->component_vendor_id); 226 tmp = (u8 *)&manufacture_reply->component_id; 227 edev->component_id = tmp[0] << 8 | tmp[1]; 228 edev->component_revision_id = 229 manufacture_reply->component_revision_id; 230 } 231 232 out: 233 if (data_out) 234 dma_free_coherent(&mrioc->pdev->dev, data_out_sz + data_in_sz, 235 data_out, data_out_dma); 236 237 return rc; 238 } 239 240 /** 241 * __mpi3mr_expander_find_by_handle - expander search by handle 242 * @mrioc: Adapter instance reference 243 * @handle: Firmware device handle of the expander 244 * 245 * Context: The caller should acquire sas_node_lock 246 * 247 * This searches for expander device based on handle, then 248 * returns the sas_node object. 249 * 250 * Return: Expander sas_node object reference or NULL 251 */ 252 struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc 253 *mrioc, u16 handle) 254 { 255 struct mpi3mr_sas_node *sas_expander, *r; 256 257 r = NULL; 258 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) { 259 if (sas_expander->handle != handle) 260 continue; 261 r = sas_expander; 262 goto out; 263 } 264 out: 265 return r; 266 } 267 268 /** 269 * mpi3mr_is_expander_device - if device is an expander 270 * @device_info: Bitfield providing information about the device 271 * 272 * Return: 1 if the device is expander device, else 0. 273 */ 274 u8 mpi3mr_is_expander_device(u16 device_info) 275 { 276 if ((device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) == 277 MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER) 278 return 1; 279 else 280 return 0; 281 } 282 283 /** 284 * mpi3mr_get_sas_address - retrieve sas_address for handle 285 * @mrioc: Adapter instance reference 286 * @handle: Firmware device handle 287 * @sas_address: Address to hold sas address 288 * 289 * This function issues device page0 read for a given device 290 * handle and gets the SAS address and return it back 291 * 292 * Return: 0 for success, non-zero for failure 293 */ 294 static int mpi3mr_get_sas_address(struct mpi3mr_ioc *mrioc, u16 handle, 295 u64 *sas_address) 296 { 297 struct mpi3_device_page0 dev_pg0; 298 u16 ioc_status; 299 struct mpi3_device0_sas_sata_format *sasinf; 300 301 *sas_address = 0; 302 303 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0, 304 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, 305 handle))) { 306 ioc_err(mrioc, "%s: device page0 read failed\n", __func__); 307 return -ENXIO; 308 } 309 310 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 311 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n", 312 handle, ioc_status, __FILE__, __LINE__, __func__); 313 return -ENXIO; 314 } 315 316 if (le16_to_cpu(dev_pg0.flags) & 317 MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE) 318 *sas_address = mrioc->sas_hba.sas_address; 319 else if (dev_pg0.device_form == MPI3_DEVICE_DEVFORM_SAS_SATA) { 320 sasinf = &dev_pg0.device_specific.sas_sata_format; 321 *sas_address = le64_to_cpu(sasinf->sas_address); 322 } else { 323 ioc_err(mrioc, "%s: device_form(%d) is not SAS_SATA\n", 324 __func__, dev_pg0.device_form); 325 return -ENXIO; 326 } 327 return 0; 328 } 329 330 /** 331 * __mpi3mr_get_tgtdev_by_addr - target device search 332 * @mrioc: Adapter instance reference 333 * @sas_address: SAS address of the device 334 * @hba_port: HBA port entry 335 * 336 * This searches for target device from sas address and hba port 337 * pointer then return mpi3mr_tgt_dev object. 338 * 339 * Return: Valid tget_dev or NULL 340 */ 341 static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc, 342 u64 sas_address, struct mpi3mr_hba_port *hba_port) 343 { 344 struct mpi3mr_tgt_dev *tgtdev; 345 346 assert_spin_locked(&mrioc->tgtdev_lock); 347 348 list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) 349 if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) && 350 (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address) 351 && (tgtdev->dev_spec.sas_sata_inf.hba_port == hba_port)) 352 goto found_device; 353 return NULL; 354 found_device: 355 mpi3mr_tgtdev_get(tgtdev); 356 return tgtdev; 357 } 358 359 /** 360 * mpi3mr_get_tgtdev_by_addr - target device search 361 * @mrioc: Adapter instance reference 362 * @sas_address: SAS address of the device 363 * @hba_port: HBA port entry 364 * 365 * This searches for target device from sas address and hba port 366 * pointer then return mpi3mr_tgt_dev object. 367 * 368 * Context: This function will acquire tgtdev_lock and will 369 * release before returning the mpi3mr_tgt_dev object. 370 * 371 * Return: Valid tget_dev or NULL 372 */ 373 static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc, 374 u64 sas_address, struct mpi3mr_hba_port *hba_port) 375 { 376 struct mpi3mr_tgt_dev *tgtdev = NULL; 377 unsigned long flags; 378 379 if (!hba_port) 380 goto out; 381 382 spin_lock_irqsave(&mrioc->tgtdev_lock, flags); 383 tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc, sas_address, hba_port); 384 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); 385 386 out: 387 return tgtdev; 388 } 389 390 /** 391 * mpi3mr_remove_device_by_sas_address - remove the device 392 * @mrioc: Adapter instance reference 393 * @sas_address: SAS address of the device 394 * @hba_port: HBA port entry 395 * 396 * This searches for target device using sas address and hba 397 * port pointer then removes it from the OS. 398 * 399 * Return: None 400 */ 401 static void mpi3mr_remove_device_by_sas_address(struct mpi3mr_ioc *mrioc, 402 u64 sas_address, struct mpi3mr_hba_port *hba_port) 403 { 404 struct mpi3mr_tgt_dev *tgtdev = NULL; 405 unsigned long flags; 406 u8 was_on_tgtdev_list = 0; 407 408 if (!hba_port) 409 return; 410 411 spin_lock_irqsave(&mrioc->tgtdev_lock, flags); 412 tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc, 413 sas_address, hba_port); 414 if (tgtdev) { 415 if (!list_empty(&tgtdev->list)) { 416 was_on_tgtdev_list = 1; 417 if (tgtdev->state == MPI3MR_DEV_REMOVE_HS_STARTED) { 418 list_del_init(&tgtdev->list); 419 mpi3mr_tgtdev_put(tgtdev); 420 } 421 } 422 } 423 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); 424 if (was_on_tgtdev_list) { 425 if (tgtdev->host_exposed) 426 mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); 427 mpi3mr_tgtdev_put(tgtdev); 428 } 429 } 430 431 /** 432 * __mpi3mr_get_tgtdev_by_addr_and_rphy - target device search 433 * @mrioc: Adapter instance reference 434 * @sas_address: SAS address of the device 435 * @rphy: SAS transport layer rphy object 436 * 437 * This searches for target device from sas address and rphy 438 * pointer then return mpi3mr_tgt_dev object. 439 * 440 * Return: Valid tget_dev or NULL 441 */ 442 struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr_and_rphy( 443 struct mpi3mr_ioc *mrioc, u64 sas_address, struct sas_rphy *rphy) 444 { 445 struct mpi3mr_tgt_dev *tgtdev; 446 447 assert_spin_locked(&mrioc->tgtdev_lock); 448 449 list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) 450 if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) && 451 (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address) 452 && (tgtdev->dev_spec.sas_sata_inf.rphy == rphy)) 453 goto found_device; 454 return NULL; 455 found_device: 456 mpi3mr_tgtdev_get(tgtdev); 457 return tgtdev; 458 } 459 460 /** 461 * mpi3mr_expander_find_by_sas_address - sas expander search 462 * @mrioc: Adapter instance reference 463 * @sas_address: SAS address of expander 464 * @hba_port: HBA port entry 465 * 466 * Return: A valid SAS expander node or NULL. 467 * 468 */ 469 static struct mpi3mr_sas_node *mpi3mr_expander_find_by_sas_address( 470 struct mpi3mr_ioc *mrioc, u64 sas_address, 471 struct mpi3mr_hba_port *hba_port) 472 { 473 struct mpi3mr_sas_node *sas_expander, *r = NULL; 474 475 if (!hba_port) 476 goto out; 477 478 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) { 479 if ((sas_expander->sas_address != sas_address) || 480 (sas_expander->hba_port != hba_port)) 481 continue; 482 r = sas_expander; 483 goto out; 484 } 485 out: 486 return r; 487 } 488 489 /** 490 * __mpi3mr_sas_node_find_by_sas_address - sas node search 491 * @mrioc: Adapter instance reference 492 * @sas_address: SAS address of expander or sas host 493 * @hba_port: HBA port entry 494 * Context: Caller should acquire mrioc->sas_node_lock. 495 * 496 * If the SAS address indicates the device is direct attached to 497 * the controller (controller's SAS address) then the SAS node 498 * associated with the controller is returned back else the SAS 499 * address and hba port are used to identify the exact expander 500 * and the associated sas_node object is returned. If there is 501 * no match NULL is returned. 502 * 503 * Return: A valid SAS node or NULL. 504 * 505 */ 506 static struct mpi3mr_sas_node *__mpi3mr_sas_node_find_by_sas_address( 507 struct mpi3mr_ioc *mrioc, u64 sas_address, 508 struct mpi3mr_hba_port *hba_port) 509 { 510 511 if (mrioc->sas_hba.sas_address == sas_address) 512 return &mrioc->sas_hba; 513 return mpi3mr_expander_find_by_sas_address(mrioc, sas_address, 514 hba_port); 515 } 516 517 /** 518 * mpi3mr_parent_present - Is parent present for a phy 519 * @mrioc: Adapter instance reference 520 * @phy: SAS transport layer phy object 521 * 522 * Return: 0 if parent is present else non-zero 523 */ 524 static int mpi3mr_parent_present(struct mpi3mr_ioc *mrioc, struct sas_phy *phy) 525 { 526 unsigned long flags; 527 struct mpi3mr_hba_port *hba_port = phy->hostdata; 528 529 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 530 if (__mpi3mr_sas_node_find_by_sas_address(mrioc, 531 phy->identify.sas_address, 532 hba_port) == NULL) { 533 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 534 return -1; 535 } 536 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 537 return 0; 538 } 539 540 /** 541 * mpi3mr_convert_phy_link_rate - 542 * @link_rate: link rate as defined in the MPI header 543 * 544 * Convert link_rate from mpi format into sas_transport layer 545 * form. 546 * 547 * Return: A valid SAS transport layer defined link rate 548 */ 549 static enum sas_linkrate mpi3mr_convert_phy_link_rate(u8 link_rate) 550 { 551 enum sas_linkrate rc; 552 553 switch (link_rate) { 554 case MPI3_SAS_NEG_LINK_RATE_1_5: 555 rc = SAS_LINK_RATE_1_5_GBPS; 556 break; 557 case MPI3_SAS_NEG_LINK_RATE_3_0: 558 rc = SAS_LINK_RATE_3_0_GBPS; 559 break; 560 case MPI3_SAS_NEG_LINK_RATE_6_0: 561 rc = SAS_LINK_RATE_6_0_GBPS; 562 break; 563 case MPI3_SAS_NEG_LINK_RATE_12_0: 564 rc = SAS_LINK_RATE_12_0_GBPS; 565 break; 566 case MPI3_SAS_NEG_LINK_RATE_22_5: 567 rc = SAS_LINK_RATE_22_5_GBPS; 568 break; 569 case MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED: 570 rc = SAS_PHY_DISABLED; 571 break; 572 case MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED: 573 rc = SAS_LINK_RATE_FAILED; 574 break; 575 case MPI3_SAS_NEG_LINK_RATE_PORT_SELECTOR: 576 rc = SAS_SATA_PORT_SELECTOR; 577 break; 578 case MPI3_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS: 579 rc = SAS_PHY_RESET_IN_PROGRESS; 580 break; 581 case MPI3_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE: 582 case MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE: 583 default: 584 rc = SAS_LINK_RATE_UNKNOWN; 585 break; 586 } 587 return rc; 588 } 589 590 /** 591 * mpi3mr_delete_sas_phy - Remove a single phy from port 592 * @mrioc: Adapter instance reference 593 * @mr_sas_port: Internal Port object 594 * @mr_sas_phy: Internal Phy object 595 * @host_node: Flag to indicate this is a host_node 596 * 597 * Return: None. 598 */ 599 static void mpi3mr_delete_sas_phy(struct mpi3mr_ioc *mrioc, 600 struct mpi3mr_sas_port *mr_sas_port, 601 struct mpi3mr_sas_phy *mr_sas_phy, u8 host_node) 602 { 603 u64 sas_address = mr_sas_port->remote_identify.sas_address; 604 605 dev_info(&mr_sas_phy->phy->dev, 606 "remove: sas_address(0x%016llx), phy(%d)\n", 607 (unsigned long long) sas_address, mr_sas_phy->phy_id); 608 609 list_del(&mr_sas_phy->port_siblings); 610 mr_sas_port->num_phys--; 611 612 if (host_node) { 613 mr_sas_port->phy_mask &= ~(1 << mr_sas_phy->phy_id); 614 615 if (mr_sas_port->lowest_phy == mr_sas_phy->phy_id) 616 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1; 617 } 618 sas_port_delete_phy(mr_sas_port->port, mr_sas_phy->phy); 619 mr_sas_phy->phy_belongs_to_port = 0; 620 } 621 622 /** 623 * mpi3mr_add_sas_phy - Adding a single phy to a port 624 * @mrioc: Adapter instance reference 625 * @mr_sas_port: Internal Port object 626 * @mr_sas_phy: Internal Phy object 627 * @host_node: Flag to indicate this is a host_node 628 * 629 * Return: None. 630 */ 631 static void mpi3mr_add_sas_phy(struct mpi3mr_ioc *mrioc, 632 struct mpi3mr_sas_port *mr_sas_port, 633 struct mpi3mr_sas_phy *mr_sas_phy, u8 host_node) 634 { 635 u64 sas_address = mr_sas_port->remote_identify.sas_address; 636 637 dev_info(&mr_sas_phy->phy->dev, 638 "add: sas_address(0x%016llx), phy(%d)\n", (unsigned long long) 639 sas_address, mr_sas_phy->phy_id); 640 641 list_add_tail(&mr_sas_phy->port_siblings, &mr_sas_port->phy_list); 642 mr_sas_port->num_phys++; 643 if (host_node) { 644 mr_sas_port->phy_mask |= (1 << mr_sas_phy->phy_id); 645 646 if (mr_sas_phy->phy_id < mr_sas_port->lowest_phy) 647 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1; 648 } 649 sas_port_add_phy(mr_sas_port->port, mr_sas_phy->phy); 650 mr_sas_phy->phy_belongs_to_port = 1; 651 } 652 653 /** 654 * mpi3mr_add_phy_to_an_existing_port - add phy to existing port 655 * @mrioc: Adapter instance reference 656 * @mr_sas_node: Internal sas node object (expander or host) 657 * @mr_sas_phy: Internal Phy object * 658 * @sas_address: SAS address of device/expander were phy needs 659 * to be added to 660 * @hba_port: HBA port entry 661 * 662 * Return: None. 663 */ 664 static void mpi3mr_add_phy_to_an_existing_port(struct mpi3mr_ioc *mrioc, 665 struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy, 666 u64 sas_address, struct mpi3mr_hba_port *hba_port) 667 { 668 struct mpi3mr_sas_port *mr_sas_port; 669 struct mpi3mr_sas_phy *srch_phy; 670 671 if (mr_sas_phy->phy_belongs_to_port == 1) 672 return; 673 674 if (!hba_port) 675 return; 676 677 list_for_each_entry(mr_sas_port, &mr_sas_node->sas_port_list, 678 port_list) { 679 if (mr_sas_port->remote_identify.sas_address != 680 sas_address) 681 continue; 682 if (mr_sas_port->hba_port != hba_port) 683 continue; 684 list_for_each_entry(srch_phy, &mr_sas_port->phy_list, 685 port_siblings) { 686 if (srch_phy == mr_sas_phy) 687 return; 688 } 689 mpi3mr_add_sas_phy(mrioc, mr_sas_port, mr_sas_phy, mr_sas_node->host_node); 690 return; 691 } 692 } 693 694 /** 695 * mpi3mr_delete_sas_port - helper function to removing a port 696 * @mrioc: Adapter instance reference 697 * @mr_sas_port: Internal Port object 698 * 699 * Return: None. 700 */ 701 static void mpi3mr_delete_sas_port(struct mpi3mr_ioc *mrioc, 702 struct mpi3mr_sas_port *mr_sas_port) 703 { 704 u64 sas_address = mr_sas_port->remote_identify.sas_address; 705 struct mpi3mr_hba_port *hba_port = mr_sas_port->hba_port; 706 enum sas_device_type device_type = 707 mr_sas_port->remote_identify.device_type; 708 709 dev_info(&mr_sas_port->port->dev, 710 "remove: sas_address(0x%016llx)\n", 711 (unsigned long long) sas_address); 712 713 if (device_type == SAS_END_DEVICE) 714 mpi3mr_remove_device_by_sas_address(mrioc, sas_address, 715 hba_port); 716 717 else if (device_type == SAS_EDGE_EXPANDER_DEVICE || 718 device_type == SAS_FANOUT_EXPANDER_DEVICE) 719 mpi3mr_expander_remove(mrioc, sas_address, hba_port); 720 } 721 722 /** 723 * mpi3mr_del_phy_from_an_existing_port - del phy from a port 724 * @mrioc: Adapter instance reference 725 * @mr_sas_node: Internal sas node object (expander or host) 726 * @mr_sas_phy: Internal Phy object 727 * 728 * Return: None. 729 */ 730 static void mpi3mr_del_phy_from_an_existing_port(struct mpi3mr_ioc *mrioc, 731 struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy) 732 { 733 struct mpi3mr_sas_port *mr_sas_port, *next; 734 struct mpi3mr_sas_phy *srch_phy; 735 736 if (mr_sas_phy->phy_belongs_to_port == 0) 737 return; 738 739 list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list, 740 port_list) { 741 list_for_each_entry(srch_phy, &mr_sas_port->phy_list, 742 port_siblings) { 743 if (srch_phy != mr_sas_phy) 744 continue; 745 if ((mr_sas_port->num_phys == 1) && 746 !mrioc->reset_in_progress) 747 mpi3mr_delete_sas_port(mrioc, mr_sas_port); 748 else 749 mpi3mr_delete_sas_phy(mrioc, mr_sas_port, 750 mr_sas_phy, mr_sas_node->host_node); 751 return; 752 } 753 } 754 } 755 756 /** 757 * mpi3mr_sas_port_sanity_check - sanity check while adding port 758 * @mrioc: Adapter instance reference 759 * @mr_sas_node: Internal sas node object (expander or host) 760 * @sas_address: SAS address of device/expander 761 * @hba_port: HBA port entry 762 * 763 * Verifies whether the Phys attached to a device with the given 764 * SAS address already belongs to an existing sas port if so 765 * will remove those phys from the sas port 766 * 767 * Return: None. 768 */ 769 static void mpi3mr_sas_port_sanity_check(struct mpi3mr_ioc *mrioc, 770 struct mpi3mr_sas_node *mr_sas_node, u64 sas_address, 771 struct mpi3mr_hba_port *hba_port) 772 { 773 int i; 774 775 for (i = 0; i < mr_sas_node->num_phys; i++) { 776 if ((mr_sas_node->phy[i].remote_identify.sas_address != 777 sas_address) || (mr_sas_node->phy[i].hba_port != hba_port)) 778 continue; 779 if (mr_sas_node->phy[i].phy_belongs_to_port == 1) 780 mpi3mr_del_phy_from_an_existing_port(mrioc, 781 mr_sas_node, &mr_sas_node->phy[i]); 782 } 783 } 784 785 /** 786 * mpi3mr_set_identify - set identify for phys and end devices 787 * @mrioc: Adapter instance reference 788 * @handle: Firmware device handle 789 * @identify: SAS transport layer's identify info 790 * 791 * Populates sas identify info for a specific device. 792 * 793 * Return: 0 for success, non-zero for failure. 794 */ 795 static int mpi3mr_set_identify(struct mpi3mr_ioc *mrioc, u16 handle, 796 struct sas_identify *identify) 797 { 798 799 struct mpi3_device_page0 device_pg0; 800 struct mpi3_device0_sas_sata_format *sasinf; 801 u16 device_info; 802 u16 ioc_status; 803 804 if (mrioc->reset_in_progress) { 805 ioc_err(mrioc, "%s: host reset in progress!\n", __func__); 806 return -EFAULT; 807 } 808 809 if (mrioc->pci_err_recovery) { 810 ioc_err(mrioc, "%s: pci error recovery in progress!\n", 811 __func__); 812 return -EFAULT; 813 } 814 815 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &device_pg0, 816 sizeof(device_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, handle))) { 817 ioc_err(mrioc, "%s: device page0 read failed\n", __func__); 818 return -ENXIO; 819 } 820 821 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 822 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n", 823 handle, ioc_status, __FILE__, __LINE__, __func__); 824 return -EIO; 825 } 826 827 memset(identify, 0, sizeof(struct sas_identify)); 828 sasinf = &device_pg0.device_specific.sas_sata_format; 829 device_info = le16_to_cpu(sasinf->device_info); 830 831 /* sas_address */ 832 identify->sas_address = le64_to_cpu(sasinf->sas_address); 833 834 /* phy number of the parent device this device is linked to */ 835 identify->phy_identifier = sasinf->phy_num; 836 837 /* device_type */ 838 switch (device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) { 839 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE: 840 identify->device_type = SAS_PHY_UNUSED; 841 break; 842 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE: 843 identify->device_type = SAS_END_DEVICE; 844 break; 845 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER: 846 identify->device_type = SAS_EDGE_EXPANDER_DEVICE; 847 break; 848 } 849 850 /* initiator_port_protocols */ 851 if (device_info & MPI3_SAS_DEVICE_INFO_SSP_INITIATOR) 852 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP; 853 /* MPI3.0 doesn't have define for SATA INIT so setting both here*/ 854 if (device_info & MPI3_SAS_DEVICE_INFO_STP_INITIATOR) 855 identify->initiator_port_protocols |= (SAS_PROTOCOL_STP | 856 SAS_PROTOCOL_SATA); 857 if (device_info & MPI3_SAS_DEVICE_INFO_SMP_INITIATOR) 858 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP; 859 860 /* target_port_protocols */ 861 if (device_info & MPI3_SAS_DEVICE_INFO_SSP_TARGET) 862 identify->target_port_protocols |= SAS_PROTOCOL_SSP; 863 /* MPI3.0 doesn't have define for STP Target so setting both here*/ 864 if (device_info & MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET) 865 identify->target_port_protocols |= (SAS_PROTOCOL_STP | 866 SAS_PROTOCOL_SATA); 867 if (device_info & MPI3_SAS_DEVICE_INFO_SMP_TARGET) 868 identify->target_port_protocols |= SAS_PROTOCOL_SMP; 869 return 0; 870 } 871 872 /** 873 * mpi3mr_add_host_phy - report sas_host phy to SAS transport 874 * @mrioc: Adapter instance reference 875 * @mr_sas_phy: Internal Phy object 876 * @phy_pg0: SAS phy page 0 877 * @parent_dev: Prent device class object 878 * 879 * Return: 0 for success, non-zero for failure. 880 */ 881 static int mpi3mr_add_host_phy(struct mpi3mr_ioc *mrioc, 882 struct mpi3mr_sas_phy *mr_sas_phy, struct mpi3_sas_phy_page0 phy_pg0, 883 struct device *parent_dev) 884 { 885 struct sas_phy *phy; 886 int phy_index = mr_sas_phy->phy_id; 887 888 889 INIT_LIST_HEAD(&mr_sas_phy->port_siblings); 890 phy = sas_phy_alloc(parent_dev, phy_index); 891 if (!phy) { 892 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 893 __FILE__, __LINE__, __func__); 894 return -1; 895 } 896 if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle, 897 &mr_sas_phy->identify))) { 898 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 899 __FILE__, __LINE__, __func__); 900 sas_phy_free(phy); 901 return -1; 902 } 903 phy->identify = mr_sas_phy->identify; 904 mr_sas_phy->attached_handle = le16_to_cpu(phy_pg0.attached_dev_handle); 905 if (mr_sas_phy->attached_handle) 906 mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle, 907 &mr_sas_phy->remote_identify); 908 phy->identify.phy_identifier = mr_sas_phy->phy_id; 909 phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate( 910 (phy_pg0.negotiated_link_rate & 911 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> 912 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT); 913 phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate( 914 phy_pg0.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK); 915 phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate( 916 phy_pg0.hw_link_rate >> 4); 917 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate( 918 phy_pg0.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK); 919 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate( 920 phy_pg0.programmed_link_rate >> 4); 921 phy->hostdata = mr_sas_phy->hba_port; 922 923 if ((sas_phy_add(phy))) { 924 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 925 __FILE__, __LINE__, __func__); 926 sas_phy_free(phy); 927 return -1; 928 } 929 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) 930 dev_info(&phy->dev, 931 "add: handle(0x%04x), sas_address(0x%016llx)\n" 932 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n", 933 mr_sas_phy->handle, (unsigned long long) 934 mr_sas_phy->identify.sas_address, 935 mr_sas_phy->attached_handle, 936 (unsigned long long) 937 mr_sas_phy->remote_identify.sas_address); 938 mr_sas_phy->phy = phy; 939 return 0; 940 } 941 942 /** 943 * mpi3mr_add_expander_phy - report expander phy to transport 944 * @mrioc: Adapter instance reference 945 * @mr_sas_phy: Internal Phy object 946 * @expander_pg1: SAS Expander page 1 947 * @parent_dev: Parent device class object 948 * 949 * Return: 0 for success, non-zero for failure. 950 */ 951 static int mpi3mr_add_expander_phy(struct mpi3mr_ioc *mrioc, 952 struct mpi3mr_sas_phy *mr_sas_phy, 953 struct mpi3_sas_expander_page1 expander_pg1, 954 struct device *parent_dev) 955 { 956 struct sas_phy *phy; 957 int phy_index = mr_sas_phy->phy_id; 958 959 INIT_LIST_HEAD(&mr_sas_phy->port_siblings); 960 phy = sas_phy_alloc(parent_dev, phy_index); 961 if (!phy) { 962 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 963 __FILE__, __LINE__, __func__); 964 return -1; 965 } 966 if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle, 967 &mr_sas_phy->identify))) { 968 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 969 __FILE__, __LINE__, __func__); 970 sas_phy_free(phy); 971 return -1; 972 } 973 phy->identify = mr_sas_phy->identify; 974 mr_sas_phy->attached_handle = 975 le16_to_cpu(expander_pg1.attached_dev_handle); 976 if (mr_sas_phy->attached_handle) 977 mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle, 978 &mr_sas_phy->remote_identify); 979 phy->identify.phy_identifier = mr_sas_phy->phy_id; 980 phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate( 981 (expander_pg1.negotiated_link_rate & 982 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> 983 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT); 984 phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate( 985 expander_pg1.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK); 986 phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate( 987 expander_pg1.hw_link_rate >> 4); 988 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate( 989 expander_pg1.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK); 990 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate( 991 expander_pg1.programmed_link_rate >> 4); 992 phy->hostdata = mr_sas_phy->hba_port; 993 994 if ((sas_phy_add(phy))) { 995 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 996 __FILE__, __LINE__, __func__); 997 sas_phy_free(phy); 998 return -1; 999 } 1000 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) 1001 dev_info(&phy->dev, 1002 "add: handle(0x%04x), sas_address(0x%016llx)\n" 1003 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n", 1004 mr_sas_phy->handle, (unsigned long long) 1005 mr_sas_phy->identify.sas_address, 1006 mr_sas_phy->attached_handle, 1007 (unsigned long long) 1008 mr_sas_phy->remote_identify.sas_address); 1009 mr_sas_phy->phy = phy; 1010 return 0; 1011 } 1012 1013 /** 1014 * mpi3mr_alloc_hba_port - alloc hba port object 1015 * @mrioc: Adapter instance reference 1016 * @port_id: Port number 1017 * 1018 * Alloc memory for hba port object. 1019 */ 1020 static struct mpi3mr_hba_port * 1021 mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id) 1022 { 1023 struct mpi3mr_hba_port *hba_port; 1024 1025 hba_port = kzalloc(sizeof(struct mpi3mr_hba_port), 1026 GFP_KERNEL); 1027 if (!hba_port) 1028 return NULL; 1029 hba_port->port_id = port_id; 1030 ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n", 1031 hba_port, hba_port->port_id); 1032 if (mrioc->reset_in_progress || 1033 mrioc->pci_err_recovery) 1034 hba_port->flags = MPI3MR_HBA_PORT_FLAG_NEW; 1035 list_add_tail(&hba_port->list, &mrioc->hba_port_table_list); 1036 return hba_port; 1037 } 1038 1039 /** 1040 * mpi3mr_get_hba_port_by_id - find hba port by id 1041 * @mrioc: Adapter instance reference 1042 * @port_id: Port ID to search 1043 * 1044 * Return: mpi3mr_hba_port reference for the matched port 1045 */ 1046 1047 struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc, 1048 u8 port_id) 1049 { 1050 struct mpi3mr_hba_port *port, *port_next; 1051 1052 list_for_each_entry_safe(port, port_next, 1053 &mrioc->hba_port_table_list, list) { 1054 if (port->port_id != port_id) 1055 continue; 1056 if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY) 1057 continue; 1058 return port; 1059 } 1060 1061 return NULL; 1062 } 1063 1064 /** 1065 * mpi3mr_update_links - refreshing SAS phy link changes 1066 * @mrioc: Adapter instance reference 1067 * @sas_address_parent: SAS address of parent expander or host 1068 * @handle: Firmware device handle of attached device 1069 * @phy_number: Phy number 1070 * @link_rate: New link rate 1071 * @hba_port: HBA port entry 1072 * 1073 * Return: None. 1074 */ 1075 void mpi3mr_update_links(struct mpi3mr_ioc *mrioc, 1076 u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate, 1077 struct mpi3mr_hba_port *hba_port) 1078 { 1079 unsigned long flags; 1080 struct mpi3mr_sas_node *mr_sas_node; 1081 struct mpi3mr_sas_phy *mr_sas_phy; 1082 1083 if (mrioc->reset_in_progress || mrioc->pci_err_recovery) 1084 return; 1085 1086 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1087 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc, 1088 sas_address_parent, hba_port); 1089 if (!mr_sas_node) { 1090 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1091 return; 1092 } 1093 1094 mr_sas_phy = &mr_sas_node->phy[phy_number]; 1095 mr_sas_phy->attached_handle = handle; 1096 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1097 if (handle && (link_rate >= MPI3_SAS_NEG_LINK_RATE_1_5)) { 1098 mpi3mr_set_identify(mrioc, handle, 1099 &mr_sas_phy->remote_identify); 1100 mpi3mr_add_phy_to_an_existing_port(mrioc, mr_sas_node, 1101 mr_sas_phy, mr_sas_phy->remote_identify.sas_address, 1102 hba_port); 1103 } else 1104 memset(&mr_sas_phy->remote_identify, 0, sizeof(struct 1105 sas_identify)); 1106 1107 if (mr_sas_phy->phy) 1108 mr_sas_phy->phy->negotiated_linkrate = 1109 mpi3mr_convert_phy_link_rate(link_rate); 1110 1111 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) 1112 dev_info(&mr_sas_phy->phy->dev, 1113 "refresh: parent sas_address(0x%016llx),\n" 1114 "\tlink_rate(0x%02x), phy(%d)\n" 1115 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n", 1116 (unsigned long long)sas_address_parent, 1117 link_rate, phy_number, handle, (unsigned long long) 1118 mr_sas_phy->remote_identify.sas_address); 1119 } 1120 1121 /** 1122 * mpi3mr_sas_host_refresh - refreshing sas host object contents 1123 * @mrioc: Adapter instance reference 1124 * 1125 * This function refreshes the controllers phy information and 1126 * updates the SAS transport layer with updated information, 1127 * this is executed for each device addition or device info 1128 * change events 1129 * 1130 * Return: None. 1131 */ 1132 void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc) 1133 { 1134 int i; 1135 u8 link_rate; 1136 u16 sz, port_id, attached_handle; 1137 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; 1138 1139 dprint_transport_info(mrioc, 1140 "updating handles for sas_host(0x%016llx)\n", 1141 (unsigned long long)mrioc->sas_hba.sas_address); 1142 1143 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + 1144 (mrioc->sas_hba.num_phys * 1145 sizeof(struct mpi3_sas_io_unit0_phy_data)); 1146 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); 1147 if (!sas_io_unit_pg0) 1148 return; 1149 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { 1150 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1151 __FILE__, __LINE__, __func__); 1152 goto out; 1153 } 1154 1155 mrioc->sas_hba.handle = 0; 1156 for (i = 0; i < mrioc->sas_hba.num_phys; i++) { 1157 if (sas_io_unit_pg0->phy_data[i].phy_flags & 1158 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY | 1159 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY)) 1160 continue; 1161 link_rate = 1162 sas_io_unit_pg0->phy_data[i].negotiated_link_rate >> 4; 1163 if (!mrioc->sas_hba.handle) 1164 mrioc->sas_hba.handle = le16_to_cpu( 1165 sas_io_unit_pg0->phy_data[i].controller_dev_handle); 1166 port_id = sas_io_unit_pg0->phy_data[i].io_unit_port; 1167 if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id))) 1168 if (!mpi3mr_alloc_hba_port(mrioc, port_id)) 1169 goto out; 1170 1171 mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle; 1172 attached_handle = le16_to_cpu( 1173 sas_io_unit_pg0->phy_data[i].attached_dev_handle); 1174 if (attached_handle && link_rate < MPI3_SAS_NEG_LINK_RATE_1_5) 1175 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5; 1176 mrioc->sas_hba.phy[i].hba_port = 1177 mpi3mr_get_hba_port_by_id(mrioc, port_id); 1178 mpi3mr_update_links(mrioc, mrioc->sas_hba.sas_address, 1179 attached_handle, i, link_rate, 1180 mrioc->sas_hba.phy[i].hba_port); 1181 } 1182 out: 1183 kfree(sas_io_unit_pg0); 1184 } 1185 1186 /** 1187 * mpi3mr_sas_host_add - create sas host object 1188 * @mrioc: Adapter instance reference 1189 * 1190 * This function creates the controllers phy information and 1191 * updates the SAS transport layer with updated information, 1192 * this is executed for first device addition or device info 1193 * change event. 1194 * 1195 * Return: None. 1196 */ 1197 void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc) 1198 { 1199 int i; 1200 u16 sz, num_phys = 1, port_id, ioc_status; 1201 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; 1202 struct mpi3_sas_phy_page0 phy_pg0; 1203 struct mpi3_device_page0 dev_pg0; 1204 struct mpi3_enclosure_page0 encl_pg0; 1205 struct mpi3_device0_sas_sata_format *sasinf; 1206 1207 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + 1208 (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data)); 1209 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); 1210 if (!sas_io_unit_pg0) 1211 return; 1212 1213 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { 1214 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1215 __FILE__, __LINE__, __func__); 1216 goto out; 1217 } 1218 num_phys = sas_io_unit_pg0->num_phys; 1219 kfree(sas_io_unit_pg0); 1220 1221 mrioc->sas_hba.host_node = 1; 1222 INIT_LIST_HEAD(&mrioc->sas_hba.sas_port_list); 1223 mrioc->sas_hba.parent_dev = &mrioc->shost->shost_gendev; 1224 mrioc->sas_hba.phy = kcalloc(num_phys, 1225 sizeof(struct mpi3mr_sas_phy), GFP_KERNEL); 1226 if (!mrioc->sas_hba.phy) 1227 return; 1228 1229 mrioc->sas_hba.num_phys = num_phys; 1230 1231 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + 1232 (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data)); 1233 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); 1234 if (!sas_io_unit_pg0) 1235 return; 1236 1237 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { 1238 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1239 __FILE__, __LINE__, __func__); 1240 goto out; 1241 } 1242 1243 mrioc->sas_hba.handle = 0; 1244 for (i = 0; i < mrioc->sas_hba.num_phys; i++) { 1245 if (sas_io_unit_pg0->phy_data[i].phy_flags & 1246 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY | 1247 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY)) 1248 continue; 1249 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0, 1250 sizeof(struct mpi3_sas_phy_page0), 1251 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, i)) { 1252 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1253 __FILE__, __LINE__, __func__); 1254 goto out; 1255 } 1256 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 1257 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1258 __FILE__, __LINE__, __func__); 1259 goto out; 1260 } 1261 1262 if (!mrioc->sas_hba.handle) 1263 mrioc->sas_hba.handle = le16_to_cpu( 1264 sas_io_unit_pg0->phy_data[i].controller_dev_handle); 1265 port_id = sas_io_unit_pg0->phy_data[i].io_unit_port; 1266 1267 if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id))) 1268 if (!mpi3mr_alloc_hba_port(mrioc, port_id)) 1269 goto out; 1270 1271 mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle; 1272 mrioc->sas_hba.phy[i].phy_id = i; 1273 mrioc->sas_hba.phy[i].hba_port = 1274 mpi3mr_get_hba_port_by_id(mrioc, port_id); 1275 mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i], 1276 phy_pg0, mrioc->sas_hba.parent_dev); 1277 } 1278 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0, 1279 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, 1280 mrioc->sas_hba.handle))) { 1281 ioc_err(mrioc, "%s: device page0 read failed\n", __func__); 1282 goto out; 1283 } 1284 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 1285 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n", 1286 mrioc->sas_hba.handle, ioc_status, __FILE__, __LINE__, 1287 __func__); 1288 goto out; 1289 } 1290 mrioc->sas_hba.enclosure_handle = 1291 le16_to_cpu(dev_pg0.enclosure_handle); 1292 sasinf = &dev_pg0.device_specific.sas_sata_format; 1293 mrioc->sas_hba.sas_address = 1294 le64_to_cpu(sasinf->sas_address); 1295 ioc_info(mrioc, 1296 "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n", 1297 mrioc->sas_hba.handle, 1298 (unsigned long long) mrioc->sas_hba.sas_address, 1299 mrioc->sas_hba.num_phys); 1300 1301 if (mrioc->sas_hba.enclosure_handle) { 1302 if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc, &ioc_status, 1303 &encl_pg0, sizeof(encl_pg0), 1304 MPI3_ENCLOS_PGAD_FORM_HANDLE, 1305 mrioc->sas_hba.enclosure_handle)) && 1306 (ioc_status == MPI3_IOCSTATUS_SUCCESS)) 1307 mrioc->sas_hba.enclosure_logical_id = 1308 le64_to_cpu(encl_pg0.enclosure_logical_id); 1309 } 1310 1311 out: 1312 kfree(sas_io_unit_pg0); 1313 } 1314 1315 /** 1316 * mpi3mr_sas_port_add - Expose the SAS device to the SAS TL 1317 * @mrioc: Adapter instance reference 1318 * @handle: Firmware device handle of the attached device 1319 * @sas_address_parent: sas address of parent expander or host 1320 * @hba_port: HBA port entry 1321 * 1322 * This function creates a new sas port object for the given end 1323 * device matching sas address and hba_port and adds it to the 1324 * sas_node's sas_port_list and expose the attached sas device 1325 * to the SAS transport layer through sas_rphy_add. 1326 * 1327 * Returns a valid mpi3mr_sas_port reference or NULL. 1328 */ 1329 static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc, 1330 u16 handle, u64 sas_address_parent, struct mpi3mr_hba_port *hba_port) 1331 { 1332 struct mpi3mr_sas_phy *mr_sas_phy, *next; 1333 struct mpi3mr_sas_port *mr_sas_port; 1334 unsigned long flags; 1335 struct mpi3mr_sas_node *mr_sas_node; 1336 struct sas_rphy *rphy; 1337 struct mpi3mr_tgt_dev *tgtdev = NULL; 1338 int i; 1339 struct sas_port *port; 1340 1341 if (!hba_port) { 1342 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1343 __FILE__, __LINE__, __func__); 1344 return NULL; 1345 } 1346 1347 mr_sas_port = kzalloc(sizeof(struct mpi3mr_sas_port), GFP_KERNEL); 1348 if (!mr_sas_port) 1349 return NULL; 1350 1351 INIT_LIST_HEAD(&mr_sas_port->port_list); 1352 INIT_LIST_HEAD(&mr_sas_port->phy_list); 1353 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1354 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc, 1355 sas_address_parent, hba_port); 1356 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1357 1358 if (!mr_sas_node) { 1359 ioc_err(mrioc, "%s:could not find parent sas_address(0x%016llx)!\n", 1360 __func__, (unsigned long long)sas_address_parent); 1361 goto out_fail; 1362 } 1363 1364 if ((mpi3mr_set_identify(mrioc, handle, 1365 &mr_sas_port->remote_identify))) { 1366 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1367 __FILE__, __LINE__, __func__); 1368 goto out_fail; 1369 } 1370 1371 if (mr_sas_port->remote_identify.device_type == SAS_PHY_UNUSED) { 1372 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1373 __FILE__, __LINE__, __func__); 1374 goto out_fail; 1375 } 1376 1377 mr_sas_port->hba_port = hba_port; 1378 mpi3mr_sas_port_sanity_check(mrioc, mr_sas_node, 1379 mr_sas_port->remote_identify.sas_address, hba_port); 1380 1381 if (mr_sas_node->host_node && mr_sas_node->num_phys >= 1382 sizeof(mr_sas_port->phy_mask) * 8) 1383 ioc_info(mrioc, "max port count %u could be too high\n", 1384 mr_sas_node->num_phys); 1385 1386 for (i = 0; i < mr_sas_node->num_phys; i++) { 1387 if ((mr_sas_node->phy[i].remote_identify.sas_address != 1388 mr_sas_port->remote_identify.sas_address) || 1389 (mr_sas_node->phy[i].hba_port != hba_port)) 1390 continue; 1391 1392 if (mr_sas_node->host_node && (i >= sizeof(mr_sas_port->phy_mask) * 8)) { 1393 ioc_warn(mrioc, "skipping port %u, max allowed value is %zu\n", 1394 i, sizeof(mr_sas_port->phy_mask) * 8); 1395 goto out_fail; 1396 } 1397 list_add_tail(&mr_sas_node->phy[i].port_siblings, 1398 &mr_sas_port->phy_list); 1399 mr_sas_port->num_phys++; 1400 if (mr_sas_node->host_node) 1401 mr_sas_port->phy_mask |= (1 << i); 1402 } 1403 1404 if (!mr_sas_port->num_phys) { 1405 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1406 __FILE__, __LINE__, __func__); 1407 goto out_fail; 1408 } 1409 1410 if (mr_sas_node->host_node) 1411 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1; 1412 1413 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { 1414 tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc, 1415 mr_sas_port->remote_identify.sas_address, 1416 mr_sas_port->hba_port); 1417 1418 if (!tgtdev) { 1419 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1420 __FILE__, __LINE__, __func__); 1421 goto out_fail; 1422 } 1423 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1; 1424 } 1425 1426 if (!mr_sas_node->parent_dev) { 1427 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1428 __FILE__, __LINE__, __func__); 1429 goto out_fail; 1430 } 1431 1432 port = sas_port_alloc_num(mr_sas_node->parent_dev); 1433 if ((sas_port_add(port))) { 1434 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1435 __FILE__, __LINE__, __func__); 1436 goto out_fail; 1437 } 1438 1439 list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list, 1440 port_siblings) { 1441 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) 1442 dev_info(&port->dev, 1443 "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n", 1444 handle, (unsigned long long) 1445 mr_sas_port->remote_identify.sas_address, 1446 mr_sas_phy->phy_id); 1447 sas_port_add_phy(port, mr_sas_phy->phy); 1448 mr_sas_phy->phy_belongs_to_port = 1; 1449 mr_sas_phy->hba_port = hba_port; 1450 } 1451 1452 mr_sas_port->port = port; 1453 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { 1454 rphy = sas_end_device_alloc(port); 1455 tgtdev->dev_spec.sas_sata_inf.rphy = rphy; 1456 } else { 1457 rphy = sas_expander_alloc(port, 1458 mr_sas_port->remote_identify.device_type); 1459 } 1460 rphy->identify = mr_sas_port->remote_identify; 1461 1462 if (mrioc->current_event) 1463 mrioc->current_event->pending_at_sml = 1; 1464 1465 if ((sas_rphy_add(rphy))) { 1466 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1467 __FILE__, __LINE__, __func__); 1468 } 1469 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { 1470 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0; 1471 tgtdev->dev_spec.sas_sata_inf.sas_transport_attached = 1; 1472 mpi3mr_tgtdev_put(tgtdev); 1473 } 1474 1475 dev_info(&rphy->dev, 1476 "%s: added: handle(0x%04x), sas_address(0x%016llx)\n", 1477 __func__, handle, (unsigned long long) 1478 mr_sas_port->remote_identify.sas_address); 1479 1480 mr_sas_port->rphy = rphy; 1481 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1482 list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list); 1483 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1484 1485 if (mrioc->current_event) { 1486 mrioc->current_event->pending_at_sml = 0; 1487 if (mrioc->current_event->discard) 1488 mpi3mr_print_device_event_notice(mrioc, true); 1489 } 1490 1491 /* fill in report manufacture */ 1492 if (mr_sas_port->remote_identify.device_type == 1493 SAS_EDGE_EXPANDER_DEVICE || 1494 mr_sas_port->remote_identify.device_type == 1495 SAS_FANOUT_EXPANDER_DEVICE) 1496 mpi3mr_report_manufacture(mrioc, 1497 mr_sas_port->remote_identify.sas_address, 1498 rphy_to_expander_device(rphy), hba_port->port_id); 1499 1500 return mr_sas_port; 1501 1502 out_fail: 1503 list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list, 1504 port_siblings) 1505 list_del(&mr_sas_phy->port_siblings); 1506 kfree(mr_sas_port); 1507 return NULL; 1508 } 1509 1510 /** 1511 * mpi3mr_sas_port_remove - remove port from the list 1512 * @mrioc: Adapter instance reference 1513 * @sas_address: SAS address of attached device 1514 * @sas_address_parent: SAS address of parent expander or host 1515 * @hba_port: HBA port entry 1516 * 1517 * Removing object and freeing associated memory from the 1518 * sas_port_list. 1519 * 1520 * Return: None 1521 */ 1522 static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address, 1523 u64 sas_address_parent, struct mpi3mr_hba_port *hba_port) 1524 { 1525 int i; 1526 unsigned long flags; 1527 struct mpi3mr_sas_port *mr_sas_port, *next; 1528 struct mpi3mr_sas_node *mr_sas_node; 1529 u8 found = 0; 1530 struct mpi3mr_sas_phy *mr_sas_phy, *next_phy; 1531 struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL; 1532 1533 if (!hba_port) 1534 return; 1535 1536 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1537 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc, 1538 sas_address_parent, hba_port); 1539 if (!mr_sas_node) { 1540 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1541 return; 1542 } 1543 list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list, 1544 port_list) { 1545 if (mr_sas_port->remote_identify.sas_address != sas_address) 1546 continue; 1547 if (mr_sas_port->hba_port != hba_port) 1548 continue; 1549 found = 1; 1550 list_del(&mr_sas_port->port_list); 1551 goto out; 1552 } 1553 1554 out: 1555 if (!found) { 1556 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1557 return; 1558 } 1559 1560 if (mr_sas_node->host_node) { 1561 list_for_each_entry_safe(srch_port, hba_port_next, 1562 &mrioc->hba_port_table_list, list) { 1563 if (srch_port != hba_port) 1564 continue; 1565 ioc_info(mrioc, 1566 "removing hba_port entry: %p port: %d from hba_port list\n", 1567 srch_port, srch_port->port_id); 1568 list_del(&hba_port->list); 1569 kfree(hba_port); 1570 break; 1571 } 1572 } 1573 1574 for (i = 0; i < mr_sas_node->num_phys; i++) { 1575 if (mr_sas_node->phy[i].remote_identify.sas_address == 1576 sas_address) 1577 memset(&mr_sas_node->phy[i].remote_identify, 0, 1578 sizeof(struct sas_identify)); 1579 } 1580 1581 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1582 1583 if (mrioc->current_event) 1584 mrioc->current_event->pending_at_sml = 1; 1585 1586 list_for_each_entry_safe(mr_sas_phy, next_phy, 1587 &mr_sas_port->phy_list, port_siblings) { 1588 if ((!mrioc->stop_drv_processing) && 1589 (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) 1590 dev_info(&mr_sas_port->port->dev, 1591 "remove: sas_address(0x%016llx), phy(%d)\n", 1592 (unsigned long long) 1593 mr_sas_port->remote_identify.sas_address, 1594 mr_sas_phy->phy_id); 1595 mr_sas_phy->phy_belongs_to_port = 0; 1596 if (!mrioc->stop_drv_processing) 1597 sas_port_delete_phy(mr_sas_port->port, 1598 mr_sas_phy->phy); 1599 list_del(&mr_sas_phy->port_siblings); 1600 } 1601 if (!mrioc->stop_drv_processing) 1602 sas_port_delete(mr_sas_port->port); 1603 ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n", 1604 __func__, (unsigned long long)sas_address); 1605 1606 if (mrioc->current_event) { 1607 mrioc->current_event->pending_at_sml = 0; 1608 if (mrioc->current_event->discard) 1609 mpi3mr_print_device_event_notice(mrioc, false); 1610 } 1611 1612 kfree(mr_sas_port); 1613 } 1614 1615 /** 1616 * struct host_port - host port details 1617 * @sas_address: SAS Address of the attached device 1618 * @phy_mask: phy mask of host port 1619 * @handle: Device Handle of attached device 1620 * @iounit_port_id: port ID 1621 * @used: host port is already matched with sas port from sas_port_list 1622 * @lowest_phy: lowest phy ID of host port 1623 */ 1624 struct host_port { 1625 u64 sas_address; 1626 u64 phy_mask; 1627 u16 handle; 1628 u8 iounit_port_id; 1629 u8 used; 1630 u8 lowest_phy; 1631 }; 1632 1633 /** 1634 * mpi3mr_update_mr_sas_port - update sas port objects during reset 1635 * @mrioc: Adapter instance reference 1636 * @h_port: host_port object 1637 * @mr_sas_port: sas_port objects which needs to be updated 1638 * 1639 * Update the port ID of sas port object. Also add the phys if new phys got 1640 * added to current sas port and remove the phys if some phys are moved 1641 * out of the current sas port. 1642 * 1643 * Return: Nothing. 1644 */ 1645 static void 1646 mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port, 1647 struct mpi3mr_sas_port *mr_sas_port) 1648 { 1649 struct mpi3mr_sas_phy *mr_sas_phy; 1650 u64 phy_mask_xor; 1651 u64 phys_to_be_added, phys_to_be_removed; 1652 int i; 1653 1654 h_port->used = 1; 1655 mr_sas_port->marked_responding = 1; 1656 1657 dev_info(&mr_sas_port->port->dev, 1658 "sas_address(0x%016llx), old: port_id %d phy_mask 0x%llx, new: port_id %d phy_mask:0x%llx\n", 1659 mr_sas_port->remote_identify.sas_address, 1660 mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask, 1661 h_port->iounit_port_id, h_port->phy_mask); 1662 1663 mr_sas_port->hba_port->port_id = h_port->iounit_port_id; 1664 mr_sas_port->hba_port->flags &= ~MPI3MR_HBA_PORT_FLAG_DIRTY; 1665 1666 /* Get the newly added phys bit map & removed phys bit map */ 1667 phy_mask_xor = mr_sas_port->phy_mask ^ h_port->phy_mask; 1668 phys_to_be_added = h_port->phy_mask & phy_mask_xor; 1669 phys_to_be_removed = mr_sas_port->phy_mask & phy_mask_xor; 1670 1671 /* 1672 * Register these new phys to current mr_sas_port's port. 1673 * if these phys are previously registered with another port 1674 * then delete these phys from that port first. 1675 */ 1676 for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u64)) { 1677 mr_sas_phy = &mrioc->sas_hba.phy[i]; 1678 if (mr_sas_phy->phy_belongs_to_port) 1679 mpi3mr_del_phy_from_an_existing_port(mrioc, 1680 &mrioc->sas_hba, mr_sas_phy); 1681 mpi3mr_add_phy_to_an_existing_port(mrioc, 1682 &mrioc->sas_hba, mr_sas_phy, 1683 mr_sas_port->remote_identify.sas_address, 1684 mr_sas_port->hba_port); 1685 } 1686 1687 /* Delete the phys which are not part of current mr_sas_port's port. */ 1688 for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u64)) { 1689 mr_sas_phy = &mrioc->sas_hba.phy[i]; 1690 if (mr_sas_phy->phy_belongs_to_port) 1691 mpi3mr_del_phy_from_an_existing_port(mrioc, 1692 &mrioc->sas_hba, mr_sas_phy); 1693 } 1694 } 1695 1696 /** 1697 * mpi3mr_refresh_sas_ports - update host's sas ports during reset 1698 * @mrioc: Adapter instance reference 1699 * 1700 * Update the host's sas ports during reset by checking whether 1701 * sas ports are still intact or not. Add/remove phys if any hba 1702 * phys are (moved in)/(moved out) of sas port. Also update 1703 * io_unit_port if it got changed during reset. 1704 * 1705 * Return: Nothing. 1706 */ 1707 void 1708 mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc) 1709 { 1710 struct host_port *h_port = NULL; 1711 int i, j, found, host_port_count = 0, port_idx; 1712 u16 sz, attached_handle, ioc_status; 1713 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; 1714 struct mpi3_device_page0 dev_pg0; 1715 struct mpi3_device0_sas_sata_format *sasinf; 1716 struct mpi3mr_sas_port *mr_sas_port; 1717 1718 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + 1719 (mrioc->sas_hba.num_phys * 1720 sizeof(struct mpi3_sas_io_unit0_phy_data)); 1721 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); 1722 if (!sas_io_unit_pg0) 1723 return; 1724 h_port = kcalloc(64, sizeof(struct host_port), GFP_KERNEL); 1725 if (!h_port) 1726 goto out; 1727 1728 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { 1729 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1730 __FILE__, __LINE__, __func__); 1731 goto out; 1732 } 1733 1734 /* Create a new expander port table */ 1735 for (i = 0; i < mrioc->sas_hba.num_phys; i++) { 1736 attached_handle = le16_to_cpu( 1737 sas_io_unit_pg0->phy_data[i].attached_dev_handle); 1738 if (!attached_handle) 1739 continue; 1740 found = 0; 1741 for (j = 0; j < host_port_count; j++) { 1742 if (h_port[j].handle == attached_handle) { 1743 h_port[j].phy_mask |= (1 << i); 1744 found = 1; 1745 break; 1746 } 1747 } 1748 if (found) 1749 continue; 1750 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0, 1751 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, 1752 attached_handle))) { 1753 dprint_reset(mrioc, 1754 "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n", 1755 attached_handle, __FILE__, __LINE__, __func__); 1756 continue; 1757 } 1758 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 1759 dprint_reset(mrioc, 1760 "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n", 1761 ioc_status, attached_handle, 1762 __FILE__, __LINE__, __func__); 1763 continue; 1764 } 1765 sasinf = &dev_pg0.device_specific.sas_sata_format; 1766 1767 port_idx = host_port_count; 1768 h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address); 1769 h_port[port_idx].handle = attached_handle; 1770 h_port[port_idx].phy_mask = (1 << i); 1771 h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port; 1772 h_port[port_idx].lowest_phy = sasinf->phy_num; 1773 h_port[port_idx].used = 0; 1774 host_port_count++; 1775 } 1776 1777 if (!host_port_count) 1778 goto out; 1779 1780 if (mrioc->logging_level & MPI3_DEBUG_RESET) { 1781 ioc_info(mrioc, "Host port details before reset\n"); 1782 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, 1783 port_list) { 1784 ioc_info(mrioc, 1785 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n", 1786 mr_sas_port->hba_port->port_id, 1787 mr_sas_port->remote_identify.sas_address, 1788 mr_sas_port->phy_mask, mr_sas_port->lowest_phy); 1789 } 1790 mr_sas_port = NULL; 1791 ioc_info(mrioc, "Host port details after reset\n"); 1792 for (i = 0; i < host_port_count; i++) { 1793 ioc_info(mrioc, 1794 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n", 1795 h_port[i].iounit_port_id, h_port[i].sas_address, 1796 h_port[i].phy_mask, h_port[i].lowest_phy); 1797 } 1798 } 1799 1800 /* mark all host sas port entries as dirty */ 1801 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, 1802 port_list) { 1803 mr_sas_port->marked_responding = 0; 1804 mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY; 1805 } 1806 1807 /* First check for matching lowest phy */ 1808 for (i = 0; i < host_port_count; i++) { 1809 mr_sas_port = NULL; 1810 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, 1811 port_list) { 1812 if (mr_sas_port->marked_responding) 1813 continue; 1814 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address) 1815 continue; 1816 if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) { 1817 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port); 1818 break; 1819 } 1820 } 1821 } 1822 1823 /* In case if lowest phy is got enabled or disabled during reset */ 1824 for (i = 0; i < host_port_count; i++) { 1825 if (h_port[i].used) 1826 continue; 1827 mr_sas_port = NULL; 1828 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, 1829 port_list) { 1830 if (mr_sas_port->marked_responding) 1831 continue; 1832 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address) 1833 continue; 1834 if (h_port[i].phy_mask & mr_sas_port->phy_mask) { 1835 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port); 1836 break; 1837 } 1838 } 1839 } 1840 1841 /* In case if expander cable is removed & connected to another HBA port during reset */ 1842 for (i = 0; i < host_port_count; i++) { 1843 if (h_port[i].used) 1844 continue; 1845 mr_sas_port = NULL; 1846 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, 1847 port_list) { 1848 if (mr_sas_port->marked_responding) 1849 continue; 1850 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address) 1851 continue; 1852 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port); 1853 break; 1854 } 1855 } 1856 out: 1857 kfree(h_port); 1858 kfree(sas_io_unit_pg0); 1859 } 1860 1861 /** 1862 * mpi3mr_refresh_expanders - Refresh expander device exposure 1863 * @mrioc: Adapter instance reference 1864 * 1865 * This is executed post controller reset to identify any 1866 * missing expander devices during reset and remove from the upper layers 1867 * or expose any newly detected expander device to the upper layers. 1868 * 1869 * Return: Nothing. 1870 */ 1871 void 1872 mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc) 1873 { 1874 struct mpi3mr_sas_node *sas_expander, *sas_expander_next; 1875 struct mpi3_sas_expander_page0 expander_pg0; 1876 u16 ioc_status, handle; 1877 u64 sas_address; 1878 int i; 1879 unsigned long flags; 1880 struct mpi3mr_hba_port *hba_port; 1881 1882 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1883 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) { 1884 sas_expander->non_responding = 1; 1885 } 1886 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1887 1888 sas_expander = NULL; 1889 1890 handle = 0xffff; 1891 1892 /* Search for responding expander devices and add them if they are newly got added */ 1893 while (true) { 1894 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0, 1895 sizeof(struct mpi3_sas_expander_page0), 1896 MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) { 1897 dprint_reset(mrioc, 1898 "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n", 1899 handle, __FILE__, __LINE__, __func__); 1900 break; 1901 } 1902 1903 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 1904 dprint_reset(mrioc, 1905 "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n", 1906 ioc_status, handle, __FILE__, __LINE__, __func__); 1907 break; 1908 } 1909 1910 handle = le16_to_cpu(expander_pg0.dev_handle); 1911 sas_address = le64_to_cpu(expander_pg0.sas_address); 1912 hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port); 1913 1914 if (!hba_port) { 1915 mpi3mr_sas_host_refresh(mrioc); 1916 mpi3mr_expander_add(mrioc, handle); 1917 continue; 1918 } 1919 1920 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1921 sas_expander = 1922 mpi3mr_expander_find_by_sas_address(mrioc, 1923 sas_address, hba_port); 1924 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1925 1926 if (!sas_expander) { 1927 mpi3mr_sas_host_refresh(mrioc); 1928 mpi3mr_expander_add(mrioc, handle); 1929 continue; 1930 } 1931 1932 sas_expander->non_responding = 0; 1933 if (sas_expander->handle == handle) 1934 continue; 1935 1936 sas_expander->handle = handle; 1937 for (i = 0 ; i < sas_expander->num_phys ; i++) 1938 sas_expander->phy[i].handle = handle; 1939 } 1940 1941 /* 1942 * Delete non responding expander devices and the corresponding 1943 * hba_port if the non responding expander device's parent device 1944 * is a host node. 1945 */ 1946 sas_expander = NULL; 1947 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1948 list_for_each_entry_safe_reverse(sas_expander, sas_expander_next, 1949 &mrioc->sas_expander_list, list) { 1950 if (sas_expander->non_responding) { 1951 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1952 mpi3mr_expander_node_remove(mrioc, sas_expander); 1953 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1954 } 1955 } 1956 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1957 } 1958 1959 /** 1960 * mpi3mr_expander_node_add - insert an expander to the list. 1961 * @mrioc: Adapter instance reference 1962 * @sas_expander: Expander sas node 1963 * Context: This function will acquire sas_node_lock. 1964 * 1965 * Adding new object to the ioc->sas_expander_list. 1966 * 1967 * Return: None. 1968 */ 1969 static void mpi3mr_expander_node_add(struct mpi3mr_ioc *mrioc, 1970 struct mpi3mr_sas_node *sas_expander) 1971 { 1972 unsigned long flags; 1973 1974 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1975 list_add_tail(&sas_expander->list, &mrioc->sas_expander_list); 1976 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1977 } 1978 1979 /** 1980 * mpi3mr_expander_add - Create expander object 1981 * @mrioc: Adapter instance reference 1982 * @handle: Expander firmware device handle 1983 * 1984 * This function creating expander object, stored in 1985 * sas_expander_list and expose it to the SAS transport 1986 * layer. 1987 * 1988 * Return: 0 for success, non-zero for failure. 1989 */ 1990 int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle) 1991 { 1992 struct mpi3mr_sas_node *sas_expander; 1993 struct mpi3mr_enclosure_node *enclosure_dev; 1994 struct mpi3_sas_expander_page0 expander_pg0; 1995 struct mpi3_sas_expander_page1 expander_pg1; 1996 u16 ioc_status, parent_handle, temp_handle; 1997 u64 sas_address, sas_address_parent = 0; 1998 int i; 1999 unsigned long flags; 2000 u8 port_id, link_rate; 2001 struct mpi3mr_sas_port *mr_sas_port = NULL; 2002 struct mpi3mr_hba_port *hba_port; 2003 u32 phynum_handle; 2004 int rc = 0; 2005 2006 if (!handle) 2007 return -1; 2008 2009 if (mrioc->reset_in_progress || mrioc->pci_err_recovery) 2010 return -1; 2011 2012 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0, 2013 sizeof(expander_pg0), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE, handle))) { 2014 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2015 __FILE__, __LINE__, __func__); 2016 return -1; 2017 } 2018 2019 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2020 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2021 __FILE__, __LINE__, __func__); 2022 return -1; 2023 } 2024 2025 parent_handle = le16_to_cpu(expander_pg0.parent_dev_handle); 2026 if (mpi3mr_get_sas_address(mrioc, parent_handle, &sas_address_parent) 2027 != 0) { 2028 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2029 __FILE__, __LINE__, __func__); 2030 return -1; 2031 } 2032 2033 port_id = expander_pg0.io_unit_port; 2034 hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id); 2035 if (!hba_port) { 2036 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2037 __FILE__, __LINE__, __func__); 2038 return -1; 2039 } 2040 2041 if (sas_address_parent != mrioc->sas_hba.sas_address) { 2042 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 2043 sas_expander = 2044 mpi3mr_expander_find_by_sas_address(mrioc, 2045 sas_address_parent, hba_port); 2046 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 2047 if (!sas_expander) { 2048 rc = mpi3mr_expander_add(mrioc, parent_handle); 2049 if (rc != 0) 2050 return rc; 2051 } else { 2052 /* 2053 * When there is a parent expander present, update it's 2054 * phys where child expander is connected with the link 2055 * speed, attached dev handle and sas address. 2056 */ 2057 for (i = 0 ; i < sas_expander->num_phys ; i++) { 2058 phynum_handle = 2059 (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | 2060 parent_handle; 2061 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, 2062 &ioc_status, &expander_pg1, 2063 sizeof(expander_pg1), 2064 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM, 2065 phynum_handle)) { 2066 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2067 __FILE__, __LINE__, __func__); 2068 rc = -1; 2069 return rc; 2070 } 2071 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2072 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2073 __FILE__, __LINE__, __func__); 2074 rc = -1; 2075 return rc; 2076 } 2077 temp_handle = le16_to_cpu( 2078 expander_pg1.attached_dev_handle); 2079 if (temp_handle != handle) 2080 continue; 2081 link_rate = (expander_pg1.negotiated_link_rate & 2082 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> 2083 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT; 2084 if (link_rate < MPI3_SAS_NEG_LINK_RATE_1_5) 2085 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5; 2086 mpi3mr_update_links(mrioc, sas_address_parent, 2087 handle, i, link_rate, hba_port); 2088 } 2089 } 2090 } 2091 2092 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 2093 sas_address = le64_to_cpu(expander_pg0.sas_address); 2094 sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, 2095 sas_address, hba_port); 2096 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 2097 2098 if (sas_expander) 2099 return 0; 2100 2101 sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node), 2102 GFP_KERNEL); 2103 if (!sas_expander) 2104 return -ENOMEM; 2105 2106 sas_expander->handle = handle; 2107 sas_expander->num_phys = expander_pg0.num_phys; 2108 sas_expander->sas_address_parent = sas_address_parent; 2109 sas_expander->sas_address = sas_address; 2110 sas_expander->hba_port = hba_port; 2111 2112 ioc_info(mrioc, 2113 "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", 2114 handle, parent_handle, (unsigned long long) 2115 sas_expander->sas_address, sas_expander->num_phys); 2116 2117 if (!sas_expander->num_phys) { 2118 rc = -1; 2119 goto out_fail; 2120 } 2121 sas_expander->phy = kcalloc(sas_expander->num_phys, 2122 sizeof(struct mpi3mr_sas_phy), GFP_KERNEL); 2123 if (!sas_expander->phy) { 2124 rc = -1; 2125 goto out_fail; 2126 } 2127 2128 INIT_LIST_HEAD(&sas_expander->sas_port_list); 2129 mr_sas_port = mpi3mr_sas_port_add(mrioc, handle, sas_address_parent, 2130 sas_expander->hba_port); 2131 if (!mr_sas_port) { 2132 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2133 __FILE__, __LINE__, __func__); 2134 rc = -1; 2135 goto out_fail; 2136 } 2137 sas_expander->parent_dev = &mr_sas_port->rphy->dev; 2138 sas_expander->rphy = mr_sas_port->rphy; 2139 2140 for (i = 0 ; i < sas_expander->num_phys ; i++) { 2141 phynum_handle = (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | 2142 handle; 2143 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status, 2144 &expander_pg1, sizeof(expander_pg1), 2145 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM, 2146 phynum_handle)) { 2147 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2148 __FILE__, __LINE__, __func__); 2149 rc = -1; 2150 goto out_fail; 2151 } 2152 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2153 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2154 __FILE__, __LINE__, __func__); 2155 rc = -1; 2156 goto out_fail; 2157 } 2158 2159 sas_expander->phy[i].handle = handle; 2160 sas_expander->phy[i].phy_id = i; 2161 sas_expander->phy[i].hba_port = hba_port; 2162 2163 if ((mpi3mr_add_expander_phy(mrioc, &sas_expander->phy[i], 2164 expander_pg1, sas_expander->parent_dev))) { 2165 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2166 __FILE__, __LINE__, __func__); 2167 rc = -1; 2168 goto out_fail; 2169 } 2170 } 2171 2172 if (sas_expander->enclosure_handle) { 2173 enclosure_dev = 2174 mpi3mr_enclosure_find_by_handle(mrioc, 2175 sas_expander->enclosure_handle); 2176 if (enclosure_dev) 2177 sas_expander->enclosure_logical_id = le64_to_cpu( 2178 enclosure_dev->pg0.enclosure_logical_id); 2179 } 2180 2181 mpi3mr_expander_node_add(mrioc, sas_expander); 2182 return 0; 2183 2184 out_fail: 2185 2186 if (mr_sas_port) 2187 mpi3mr_sas_port_remove(mrioc, 2188 sas_expander->sas_address, 2189 sas_address_parent, sas_expander->hba_port); 2190 kfree(sas_expander->phy); 2191 kfree(sas_expander); 2192 return rc; 2193 } 2194 2195 /** 2196 * mpi3mr_expander_node_remove - recursive removal of expander. 2197 * @mrioc: Adapter instance reference 2198 * @sas_expander: Expander device object 2199 * 2200 * Removes expander object and freeing associated memory from 2201 * the sas_expander_list and removes the same from SAS TL, if 2202 * one of the attached device is an expander then it recursively 2203 * removes the expander device too. 2204 * 2205 * Return nothing. 2206 */ 2207 void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc, 2208 struct mpi3mr_sas_node *sas_expander) 2209 { 2210 struct mpi3mr_sas_port *mr_sas_port, *next; 2211 unsigned long flags; 2212 u8 port_id; 2213 2214 /* remove sibling ports attached to this expander */ 2215 list_for_each_entry_safe(mr_sas_port, next, 2216 &sas_expander->sas_port_list, port_list) { 2217 if (mrioc->reset_in_progress || mrioc->pci_err_recovery) 2218 return; 2219 if (mr_sas_port->remote_identify.device_type == 2220 SAS_END_DEVICE) 2221 mpi3mr_remove_device_by_sas_address(mrioc, 2222 mr_sas_port->remote_identify.sas_address, 2223 mr_sas_port->hba_port); 2224 else if (mr_sas_port->remote_identify.device_type == 2225 SAS_EDGE_EXPANDER_DEVICE || 2226 mr_sas_port->remote_identify.device_type == 2227 SAS_FANOUT_EXPANDER_DEVICE) 2228 mpi3mr_expander_remove(mrioc, 2229 mr_sas_port->remote_identify.sas_address, 2230 mr_sas_port->hba_port); 2231 } 2232 2233 port_id = sas_expander->hba_port->port_id; 2234 mpi3mr_sas_port_remove(mrioc, sas_expander->sas_address, 2235 sas_expander->sas_address_parent, sas_expander->hba_port); 2236 2237 ioc_info(mrioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n", 2238 sas_expander->handle, (unsigned long long) 2239 sas_expander->sas_address, port_id); 2240 2241 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 2242 list_del(&sas_expander->list); 2243 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 2244 2245 kfree(sas_expander->phy); 2246 kfree(sas_expander); 2247 } 2248 2249 /** 2250 * mpi3mr_expander_remove - Remove expander object 2251 * @mrioc: Adapter instance reference 2252 * @sas_address: Remove expander sas_address 2253 * @hba_port: HBA port reference 2254 * 2255 * This function remove expander object, stored in 2256 * mrioc->sas_expander_list and removes it from the SAS TL by 2257 * calling mpi3mr_expander_node_remove(). 2258 * 2259 * Return: None 2260 */ 2261 void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address, 2262 struct mpi3mr_hba_port *hba_port) 2263 { 2264 struct mpi3mr_sas_node *sas_expander; 2265 unsigned long flags; 2266 2267 if (mrioc->reset_in_progress || mrioc->pci_err_recovery) 2268 return; 2269 2270 if (!hba_port) 2271 return; 2272 2273 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 2274 sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, sas_address, 2275 hba_port); 2276 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 2277 if (sas_expander) 2278 mpi3mr_expander_node_remove(mrioc, sas_expander); 2279 2280 } 2281 2282 /** 2283 * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate 2284 * @mrioc: Adapter instance reference 2285 * @tgtdev: Target device 2286 * 2287 * This function identifies whether the target device is 2288 * attached directly or through expander and issues sas phy 2289 * page0 or expander phy page1 and gets the link rate, if there 2290 * is any failure in reading the pages then this returns link 2291 * rate of 1.5. 2292 * 2293 * Return: logical link rate. 2294 */ 2295 static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc, 2296 struct mpi3mr_tgt_dev *tgtdev) 2297 { 2298 u8 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5, phy_number; 2299 struct mpi3_sas_expander_page1 expander_pg1; 2300 struct mpi3_sas_phy_page0 phy_pg0; 2301 u32 phynum_handle; 2302 u16 ioc_status; 2303 2304 phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id; 2305 if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) { 2306 phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) 2307 | tgtdev->parent_handle); 2308 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status, 2309 &expander_pg1, sizeof(expander_pg1), 2310 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM, 2311 phynum_handle)) { 2312 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2313 __FILE__, __LINE__, __func__); 2314 goto out; 2315 } 2316 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2317 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2318 __FILE__, __LINE__, __func__); 2319 goto out; 2320 } 2321 link_rate = (expander_pg1.negotiated_link_rate & 2322 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> 2323 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT; 2324 goto out; 2325 } 2326 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0, 2327 sizeof(struct mpi3_sas_phy_page0), 2328 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy_number)) { 2329 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2330 __FILE__, __LINE__, __func__); 2331 goto out; 2332 } 2333 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2334 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2335 __FILE__, __LINE__, __func__); 2336 goto out; 2337 } 2338 link_rate = (phy_pg0.negotiated_link_rate & 2339 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> 2340 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT; 2341 out: 2342 return link_rate; 2343 } 2344 2345 /** 2346 * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL 2347 * @mrioc: Adapter instance reference 2348 * @tgtdev: Target device 2349 * 2350 * This function exposes the target device after 2351 * preparing host_phy, setting up link rate etc. 2352 * 2353 * Return: 0 on success, non-zero for failure. 2354 */ 2355 int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc, 2356 struct mpi3mr_tgt_dev *tgtdev) 2357 { 2358 int retval = 0; 2359 u8 link_rate, parent_phy_number; 2360 u64 sas_address_parent, sas_address; 2361 struct mpi3mr_hba_port *hba_port; 2362 u8 port_id; 2363 2364 if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) || 2365 !mrioc->sas_transport_enabled) 2366 return -1; 2367 2368 sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address; 2369 if (!mrioc->sas_hba.num_phys) 2370 mpi3mr_sas_host_add(mrioc); 2371 else 2372 mpi3mr_sas_host_refresh(mrioc); 2373 2374 if (mpi3mr_get_sas_address(mrioc, tgtdev->parent_handle, 2375 &sas_address_parent) != 0) { 2376 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2377 __FILE__, __LINE__, __func__); 2378 return -1; 2379 } 2380 tgtdev->dev_spec.sas_sata_inf.sas_address_parent = sas_address_parent; 2381 2382 parent_phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id; 2383 port_id = tgtdev->io_unit_port; 2384 2385 hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id); 2386 if (!hba_port) { 2387 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2388 __FILE__, __LINE__, __func__); 2389 return -1; 2390 } 2391 tgtdev->dev_spec.sas_sata_inf.hba_port = hba_port; 2392 2393 link_rate = mpi3mr_get_sas_negotiated_logical_linkrate(mrioc, tgtdev); 2394 2395 if (link_rate < MPI3_SAS_NEG_LINK_RATE_1_5) 2396 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5; 2397 2398 mpi3mr_update_links(mrioc, sas_address_parent, tgtdev->dev_handle, 2399 parent_phy_number, link_rate, hba_port); 2400 2401 tgtdev->host_exposed = 1; 2402 if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle, 2403 sas_address_parent, hba_port)) { 2404 retval = -1; 2405 } else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) { 2406 mpi3mr_sas_port_remove(mrioc, sas_address, 2407 sas_address_parent, hba_port); 2408 retval = -1; 2409 } 2410 if (retval) { 2411 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL; 2412 tgtdev->host_exposed = 0; 2413 } 2414 return retval; 2415 } 2416 2417 /** 2418 * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL 2419 * @mrioc: Adapter instance reference 2420 * @tgtdev: Target device 2421 * 2422 * This function removes the target device 2423 * 2424 * Return: None. 2425 */ 2426 void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc, 2427 struct mpi3mr_tgt_dev *tgtdev) 2428 { 2429 u64 sas_address_parent, sas_address; 2430 struct mpi3mr_hba_port *hba_port; 2431 2432 if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) || 2433 !mrioc->sas_transport_enabled) 2434 return; 2435 2436 hba_port = tgtdev->dev_spec.sas_sata_inf.hba_port; 2437 sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address; 2438 sas_address_parent = tgtdev->dev_spec.sas_sata_inf.sas_address_parent; 2439 mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent, 2440 hba_port); 2441 tgtdev->host_exposed = 0; 2442 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL; 2443 } 2444 2445 /** 2446 * mpi3mr_get_port_id_by_sas_phy - Get port ID of the given phy 2447 * @phy: SAS transport layer phy object 2448 * 2449 * Return: Port number for valid ID else 0xFFFF 2450 */ 2451 static inline u8 mpi3mr_get_port_id_by_sas_phy(struct sas_phy *phy) 2452 { 2453 u8 port_id = 0xFF; 2454 struct mpi3mr_hba_port *hba_port = phy->hostdata; 2455 2456 if (hba_port) 2457 port_id = hba_port->port_id; 2458 2459 return port_id; 2460 } 2461 2462 /** 2463 * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy 2464 * 2465 * @mrioc: Adapter instance reference 2466 * @rphy: SAS transport layer remote phy object 2467 * 2468 * Retrieves HBA port number in which the device pointed by the 2469 * rphy object is attached with. 2470 * 2471 * Return: Valid port number on success else OxFFFF. 2472 */ 2473 static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy *rphy) 2474 { 2475 struct mpi3mr_sas_node *sas_expander; 2476 struct mpi3mr_tgt_dev *tgtdev; 2477 unsigned long flags; 2478 u8 port_id = 0xFF; 2479 2480 if (!rphy) 2481 return port_id; 2482 2483 if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || 2484 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) { 2485 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 2486 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, 2487 list) { 2488 if (sas_expander->rphy == rphy) { 2489 port_id = sas_expander->hba_port->port_id; 2490 break; 2491 } 2492 } 2493 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 2494 } else if (rphy->identify.device_type == SAS_END_DEVICE) { 2495 spin_lock_irqsave(&mrioc->tgtdev_lock, flags); 2496 2497 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc, 2498 rphy->identify.sas_address, rphy); 2499 if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) { 2500 port_id = 2501 tgtdev->dev_spec.sas_sata_inf.hba_port->port_id; 2502 mpi3mr_tgtdev_put(tgtdev); 2503 } 2504 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); 2505 } 2506 return port_id; 2507 } 2508 2509 static inline struct mpi3mr_ioc *phy_to_mrioc(struct sas_phy *phy) 2510 { 2511 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 2512 2513 return shost_priv(shost); 2514 } 2515 2516 static inline struct mpi3mr_ioc *rphy_to_mrioc(struct sas_rphy *rphy) 2517 { 2518 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 2519 2520 return shost_priv(shost); 2521 } 2522 2523 /* report phy error log structure */ 2524 struct phy_error_log_request { 2525 u8 smp_frame_type; /* 0x40 */ 2526 u8 function; /* 0x11 */ 2527 u8 allocated_response_length; 2528 u8 request_length; /* 02 */ 2529 u8 reserved_1[5]; 2530 u8 phy_identifier; 2531 u8 reserved_2[2]; 2532 }; 2533 2534 /* report phy error log reply structure */ 2535 struct phy_error_log_reply { 2536 u8 smp_frame_type; /* 0x41 */ 2537 u8 function; /* 0x11 */ 2538 u8 function_result; 2539 u8 response_length; 2540 __be16 expander_change_count; 2541 u8 reserved_1[3]; 2542 u8 phy_identifier; 2543 u8 reserved_2[2]; 2544 __be32 invalid_dword; 2545 __be32 running_disparity_error; 2546 __be32 loss_of_dword_sync; 2547 __be32 phy_reset_problem; 2548 }; 2549 2550 2551 /** 2552 * mpi3mr_get_expander_phy_error_log - return expander counters: 2553 * @mrioc: Adapter instance reference 2554 * @phy: The SAS transport layer phy object 2555 * 2556 * Return: 0 for success, non-zero for failure. 2557 * 2558 */ 2559 static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc, 2560 struct sas_phy *phy) 2561 { 2562 struct mpi3_smp_passthrough_request mpi_request; 2563 struct mpi3_smp_passthrough_reply mpi_reply; 2564 struct phy_error_log_request *phy_error_log_request; 2565 struct phy_error_log_reply *phy_error_log_reply; 2566 int rc; 2567 void *psge; 2568 void *data_out = NULL; 2569 dma_addr_t data_out_dma, data_in_dma; 2570 u32 data_out_sz, data_in_sz, sz; 2571 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST; 2572 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request); 2573 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply); 2574 u16 ioc_status; 2575 2576 if (mrioc->reset_in_progress) { 2577 ioc_err(mrioc, "%s: host reset in progress!\n", __func__); 2578 return -EFAULT; 2579 } 2580 2581 if (mrioc->pci_err_recovery) { 2582 ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__); 2583 return -EFAULT; 2584 } 2585 2586 data_out_sz = sizeof(struct phy_error_log_request); 2587 data_in_sz = sizeof(struct phy_error_log_reply); 2588 sz = data_out_sz + data_in_sz; 2589 data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma, 2590 GFP_KERNEL); 2591 if (!data_out) { 2592 rc = -ENOMEM; 2593 goto out; 2594 } 2595 2596 data_in_dma = data_out_dma + data_out_sz; 2597 phy_error_log_reply = data_out + data_out_sz; 2598 2599 rc = -EINVAL; 2600 memset(data_out, 0, sz); 2601 phy_error_log_request = data_out; 2602 phy_error_log_request->smp_frame_type = 0x40; 2603 phy_error_log_request->function = 0x11; 2604 phy_error_log_request->request_length = 2; 2605 phy_error_log_request->allocated_response_length = 0; 2606 phy_error_log_request->phy_identifier = phy->number; 2607 2608 memset(&mpi_request, 0, request_sz); 2609 memset(&mpi_reply, 0, reply_sz); 2610 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS); 2611 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH; 2612 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy); 2613 mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address); 2614 2615 psge = &mpi_request.request_sge; 2616 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma); 2617 2618 psge = &mpi_request.response_sge; 2619 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma); 2620 2621 dprint_transport_info(mrioc, 2622 "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n", 2623 (unsigned long long)phy->identify.sas_address, phy->number); 2624 2625 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz, 2626 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) 2627 goto out; 2628 2629 dprint_transport_info(mrioc, 2630 "phy error log SMP request completed with ioc_status(0x%04x)\n", 2631 ioc_status); 2632 2633 if (ioc_status == MPI3_IOCSTATUS_SUCCESS) { 2634 dprint_transport_info(mrioc, 2635 "phy error log - reply data transfer size(%d)\n", 2636 le16_to_cpu(mpi_reply.response_data_length)); 2637 2638 if (le16_to_cpu(mpi_reply.response_data_length) != 2639 sizeof(struct phy_error_log_reply)) 2640 goto out; 2641 2642 dprint_transport_info(mrioc, 2643 "phy error log - function_result(%d)\n", 2644 phy_error_log_reply->function_result); 2645 2646 phy->invalid_dword_count = 2647 be32_to_cpu(phy_error_log_reply->invalid_dword); 2648 phy->running_disparity_error_count = 2649 be32_to_cpu(phy_error_log_reply->running_disparity_error); 2650 phy->loss_of_dword_sync_count = 2651 be32_to_cpu(phy_error_log_reply->loss_of_dword_sync); 2652 phy->phy_reset_problem_count = 2653 be32_to_cpu(phy_error_log_reply->phy_reset_problem); 2654 rc = 0; 2655 } 2656 2657 out: 2658 if (data_out) 2659 dma_free_coherent(&mrioc->pdev->dev, sz, data_out, 2660 data_out_dma); 2661 2662 return rc; 2663 } 2664 2665 /** 2666 * mpi3mr_transport_get_linkerrors - return phy error counters 2667 * @phy: The SAS transport layer phy object 2668 * 2669 * This function retrieves the phy error log information of the 2670 * HBA or expander for which the phy belongs to 2671 * 2672 * Return: 0 for success, non-zero for failure. 2673 */ 2674 static int mpi3mr_transport_get_linkerrors(struct sas_phy *phy) 2675 { 2676 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy); 2677 struct mpi3_sas_phy_page1 phy_pg1; 2678 int rc = 0; 2679 u16 ioc_status; 2680 2681 rc = mpi3mr_parent_present(mrioc, phy); 2682 if (rc) 2683 return rc; 2684 2685 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) 2686 return mpi3mr_get_expander_phy_error_log(mrioc, phy); 2687 2688 memset(&phy_pg1, 0, sizeof(struct mpi3_sas_phy_page1)); 2689 /* get hba phy error logs */ 2690 if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc, &ioc_status, &phy_pg1, 2691 sizeof(struct mpi3_sas_phy_page1), 2692 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number))) { 2693 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2694 __FILE__, __LINE__, __func__); 2695 return -ENXIO; 2696 } 2697 2698 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2699 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2700 __FILE__, __LINE__, __func__); 2701 return -ENXIO; 2702 } 2703 phy->invalid_dword_count = le32_to_cpu(phy_pg1.invalid_dword_count); 2704 phy->running_disparity_error_count = 2705 le32_to_cpu(phy_pg1.running_disparity_error_count); 2706 phy->loss_of_dword_sync_count = 2707 le32_to_cpu(phy_pg1.loss_dword_synch_count); 2708 phy->phy_reset_problem_count = 2709 le32_to_cpu(phy_pg1.phy_reset_problem_count); 2710 return 0; 2711 } 2712 2713 /** 2714 * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID 2715 * @rphy: The SAS transport layer remote phy object 2716 * @identifier: Enclosure identifier to be returned 2717 * 2718 * Returns the enclosure id for the device pointed by the remote 2719 * phy object. 2720 * 2721 * Return: 0 on success or -ENXIO 2722 */ 2723 static int 2724 mpi3mr_transport_get_enclosure_identifier(struct sas_rphy *rphy, 2725 u64 *identifier) 2726 { 2727 struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy); 2728 struct mpi3mr_tgt_dev *tgtdev = NULL; 2729 unsigned long flags; 2730 int rc; 2731 2732 spin_lock_irqsave(&mrioc->tgtdev_lock, flags); 2733 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc, 2734 rphy->identify.sas_address, rphy); 2735 if (tgtdev) { 2736 *identifier = 2737 tgtdev->enclosure_logical_id; 2738 rc = 0; 2739 mpi3mr_tgtdev_put(tgtdev); 2740 } else { 2741 *identifier = 0; 2742 rc = -ENXIO; 2743 } 2744 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); 2745 2746 return rc; 2747 } 2748 2749 /** 2750 * mpi3mr_transport_get_bay_identifier - Get bay ID 2751 * @rphy: The SAS transport layer remote phy object 2752 * 2753 * Returns the slot id for the device pointed by the remote phy 2754 * object. 2755 * 2756 * Return: Valid slot ID on success or -ENXIO 2757 */ 2758 static int 2759 mpi3mr_transport_get_bay_identifier(struct sas_rphy *rphy) 2760 { 2761 struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy); 2762 struct mpi3mr_tgt_dev *tgtdev = NULL; 2763 unsigned long flags; 2764 int rc; 2765 2766 spin_lock_irqsave(&mrioc->tgtdev_lock, flags); 2767 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc, 2768 rphy->identify.sas_address, rphy); 2769 if (tgtdev) { 2770 rc = tgtdev->slot; 2771 mpi3mr_tgtdev_put(tgtdev); 2772 } else 2773 rc = -ENXIO; 2774 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); 2775 2776 return rc; 2777 } 2778 2779 /* phy control request structure */ 2780 struct phy_control_request { 2781 u8 smp_frame_type; /* 0x40 */ 2782 u8 function; /* 0x91 */ 2783 u8 allocated_response_length; 2784 u8 request_length; /* 0x09 */ 2785 u16 expander_change_count; 2786 u8 reserved_1[3]; 2787 u8 phy_identifier; 2788 u8 phy_operation; 2789 u8 reserved_2[13]; 2790 u64 attached_device_name; 2791 u8 programmed_min_physical_link_rate; 2792 u8 programmed_max_physical_link_rate; 2793 u8 reserved_3[6]; 2794 }; 2795 2796 /* phy control reply structure */ 2797 struct phy_control_reply { 2798 u8 smp_frame_type; /* 0x41 */ 2799 u8 function; /* 0x11 */ 2800 u8 function_result; 2801 u8 response_length; 2802 }; 2803 2804 #define SMP_PHY_CONTROL_LINK_RESET (0x01) 2805 #define SMP_PHY_CONTROL_HARD_RESET (0x02) 2806 #define SMP_PHY_CONTROL_DISABLE (0x03) 2807 2808 /** 2809 * mpi3mr_expander_phy_control - expander phy control 2810 * @mrioc: Adapter instance reference 2811 * @phy: The SAS transport layer phy object 2812 * @phy_operation: The phy operation to be executed 2813 * 2814 * Issues SMP passthru phy control request to execute a specific 2815 * phy operation for a given expander device. 2816 * 2817 * Return: 0 for success, non-zero for failure. 2818 */ 2819 static int 2820 mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc, 2821 struct sas_phy *phy, u8 phy_operation) 2822 { 2823 struct mpi3_smp_passthrough_request mpi_request; 2824 struct mpi3_smp_passthrough_reply mpi_reply; 2825 struct phy_control_request *phy_control_request; 2826 struct phy_control_reply *phy_control_reply; 2827 int rc; 2828 void *psge; 2829 void *data_out = NULL; 2830 dma_addr_t data_out_dma; 2831 dma_addr_t data_in_dma; 2832 size_t data_in_sz; 2833 size_t data_out_sz; 2834 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST; 2835 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request); 2836 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply); 2837 u16 ioc_status; 2838 u16 sz; 2839 2840 if (mrioc->reset_in_progress) { 2841 ioc_err(mrioc, "%s: host reset in progress!\n", __func__); 2842 return -EFAULT; 2843 } 2844 2845 if (mrioc->pci_err_recovery) { 2846 ioc_err(mrioc, "%s: pci error recovery in progress!\n", 2847 __func__); 2848 return -EFAULT; 2849 } 2850 2851 data_out_sz = sizeof(struct phy_control_request); 2852 data_in_sz = sizeof(struct phy_control_reply); 2853 sz = data_out_sz + data_in_sz; 2854 data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma, 2855 GFP_KERNEL); 2856 if (!data_out) { 2857 rc = -ENOMEM; 2858 goto out; 2859 } 2860 2861 data_in_dma = data_out_dma + data_out_sz; 2862 phy_control_reply = data_out + data_out_sz; 2863 2864 rc = -EINVAL; 2865 memset(data_out, 0, sz); 2866 2867 phy_control_request = data_out; 2868 phy_control_request->smp_frame_type = 0x40; 2869 phy_control_request->function = 0x91; 2870 phy_control_request->request_length = 9; 2871 phy_control_request->allocated_response_length = 0; 2872 phy_control_request->phy_identifier = phy->number; 2873 phy_control_request->phy_operation = phy_operation; 2874 phy_control_request->programmed_min_physical_link_rate = 2875 phy->minimum_linkrate << 4; 2876 phy_control_request->programmed_max_physical_link_rate = 2877 phy->maximum_linkrate << 4; 2878 2879 memset(&mpi_request, 0, request_sz); 2880 memset(&mpi_reply, 0, reply_sz); 2881 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS); 2882 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH; 2883 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy); 2884 mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address); 2885 2886 psge = &mpi_request.request_sge; 2887 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma); 2888 2889 psge = &mpi_request.response_sge; 2890 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma); 2891 2892 dprint_transport_info(mrioc, 2893 "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n", 2894 (unsigned long long)phy->identify.sas_address, phy->number, 2895 phy_operation); 2896 2897 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz, 2898 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) 2899 goto out; 2900 2901 dprint_transport_info(mrioc, 2902 "phy control SMP request completed with ioc_status(0x%04x)\n", 2903 ioc_status); 2904 2905 if (ioc_status == MPI3_IOCSTATUS_SUCCESS) { 2906 dprint_transport_info(mrioc, 2907 "phy control - reply data transfer size(%d)\n", 2908 le16_to_cpu(mpi_reply.response_data_length)); 2909 2910 if (le16_to_cpu(mpi_reply.response_data_length) != 2911 sizeof(struct phy_control_reply)) 2912 goto out; 2913 dprint_transport_info(mrioc, 2914 "phy control - function_result(%d)\n", 2915 phy_control_reply->function_result); 2916 rc = 0; 2917 } 2918 out: 2919 if (data_out) 2920 dma_free_coherent(&mrioc->pdev->dev, sz, data_out, 2921 data_out_dma); 2922 2923 return rc; 2924 } 2925 2926 /** 2927 * mpi3mr_transport_phy_reset - Reset a given phy 2928 * @phy: The SAS transport layer phy object 2929 * @hard_reset: Flag to indicate the type of reset 2930 * 2931 * Return: 0 for success, non-zero for failure. 2932 */ 2933 static int 2934 mpi3mr_transport_phy_reset(struct sas_phy *phy, int hard_reset) 2935 { 2936 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy); 2937 struct mpi3_iounit_control_request mpi_request; 2938 struct mpi3_iounit_control_reply mpi_reply; 2939 u16 request_sz = sizeof(struct mpi3_iounit_control_request); 2940 u16 reply_sz = sizeof(struct mpi3_iounit_control_reply); 2941 int rc = 0; 2942 u16 ioc_status; 2943 2944 rc = mpi3mr_parent_present(mrioc, phy); 2945 if (rc) 2946 return rc; 2947 2948 /* handle expander phys */ 2949 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) 2950 return mpi3mr_expander_phy_control(mrioc, phy, 2951 (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET : 2952 SMP_PHY_CONTROL_LINK_RESET); 2953 2954 /* handle hba phys */ 2955 memset(&mpi_request, 0, request_sz); 2956 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS); 2957 mpi_request.function = MPI3_FUNCTION_IO_UNIT_CONTROL; 2958 mpi_request.operation = MPI3_CTRL_OP_SAS_PHY_CONTROL; 2959 mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX] = 2960 (hard_reset ? MPI3_CTRL_ACTION_HARD_RESET : 2961 MPI3_CTRL_ACTION_LINK_RESET); 2962 mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX] = 2963 phy->number; 2964 2965 dprint_transport_info(mrioc, 2966 "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n", 2967 (unsigned long long)phy->identify.sas_address, phy->number, 2968 hard_reset); 2969 2970 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz, 2971 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) { 2972 rc = -EAGAIN; 2973 goto out; 2974 } 2975 2976 dprint_transport_info(mrioc, 2977 "phy reset request completed with ioc_status(0x%04x)\n", 2978 ioc_status); 2979 out: 2980 return rc; 2981 } 2982 2983 /** 2984 * mpi3mr_transport_phy_enable - enable/disable phys 2985 * @phy: The SAS transport layer phy object 2986 * @enable: flag to enable/disable, enable phy when true 2987 * 2988 * This function enables/disables a given by executing required 2989 * configuration page changes or expander phy control command 2990 * 2991 * Return: 0 for success, non-zero for failure. 2992 */ 2993 static int 2994 mpi3mr_transport_phy_enable(struct sas_phy *phy, int enable) 2995 { 2996 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy); 2997 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; 2998 struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL; 2999 u16 sz; 3000 int rc = 0; 3001 int i, discovery_active; 3002 3003 rc = mpi3mr_parent_present(mrioc, phy); 3004 if (rc) 3005 return rc; 3006 3007 /* handle expander phys */ 3008 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) 3009 return mpi3mr_expander_phy_control(mrioc, phy, 3010 (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET : 3011 SMP_PHY_CONTROL_DISABLE); 3012 3013 /* handle hba phys */ 3014 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + 3015 (mrioc->sas_hba.num_phys * 3016 sizeof(struct mpi3_sas_io_unit0_phy_data)); 3017 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); 3018 if (!sas_io_unit_pg0) { 3019 rc = -ENOMEM; 3020 goto out; 3021 } 3022 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { 3023 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 3024 __FILE__, __LINE__, __func__); 3025 rc = -ENXIO; 3026 goto out; 3027 } 3028 3029 /* unable to enable/disable phys when discovery is active */ 3030 for (i = 0, discovery_active = 0; i < mrioc->sas_hba.num_phys ; i++) { 3031 if (sas_io_unit_pg0->phy_data[i].port_flags & 3032 MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS) { 3033 ioc_err(mrioc, 3034 "discovery is active on port = %d, phy = %d\n" 3035 "\tunable to enable/disable phys, try again later!\n", 3036 sas_io_unit_pg0->phy_data[i].io_unit_port, i); 3037 discovery_active = 1; 3038 } 3039 } 3040 3041 if (discovery_active) { 3042 rc = -EAGAIN; 3043 goto out; 3044 } 3045 3046 if ((sas_io_unit_pg0->phy_data[phy->number].phy_flags & 3047 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY | 3048 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))) { 3049 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 3050 __FILE__, __LINE__, __func__); 3051 rc = -ENXIO; 3052 goto out; 3053 } 3054 3055 /* read sas_iounit page 1 */ 3056 sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) + 3057 (mrioc->sas_hba.num_phys * 3058 sizeof(struct mpi3_sas_io_unit1_phy_data)); 3059 sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL); 3060 if (!sas_io_unit_pg1) { 3061 rc = -ENOMEM; 3062 goto out; 3063 } 3064 3065 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) { 3066 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 3067 __FILE__, __LINE__, __func__); 3068 rc = -ENXIO; 3069 goto out; 3070 } 3071 3072 if (enable) 3073 sas_io_unit_pg1->phy_data[phy->number].phy_flags 3074 &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; 3075 else 3076 sas_io_unit_pg1->phy_data[phy->number].phy_flags 3077 |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; 3078 3079 mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz); 3080 3081 /* link reset */ 3082 if (enable) 3083 mpi3mr_transport_phy_reset(phy, 0); 3084 3085 out: 3086 kfree(sas_io_unit_pg1); 3087 kfree(sas_io_unit_pg0); 3088 return rc; 3089 } 3090 3091 /** 3092 * mpi3mr_transport_phy_speed - set phy min/max speed 3093 * @phy: The SAS transport later phy object 3094 * @rates: Rates defined as in sas_phy_linkrates 3095 * 3096 * This function sets the link rates given in the rates 3097 * argument to the given phy by executing required configuration 3098 * page changes or expander phy control command 3099 * 3100 * Return: 0 for success, non-zero for failure. 3101 */ 3102 static int 3103 mpi3mr_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) 3104 { 3105 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy); 3106 struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL; 3107 struct mpi3_sas_phy_page0 phy_pg0; 3108 u16 sz, ioc_status; 3109 int rc = 0; 3110 3111 rc = mpi3mr_parent_present(mrioc, phy); 3112 if (rc) 3113 return rc; 3114 3115 if (!rates->minimum_linkrate) 3116 rates->minimum_linkrate = phy->minimum_linkrate; 3117 else if (rates->minimum_linkrate < phy->minimum_linkrate_hw) 3118 rates->minimum_linkrate = phy->minimum_linkrate_hw; 3119 3120 if (!rates->maximum_linkrate) 3121 rates->maximum_linkrate = phy->maximum_linkrate; 3122 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw) 3123 rates->maximum_linkrate = phy->maximum_linkrate_hw; 3124 3125 /* handle expander phys */ 3126 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) { 3127 phy->minimum_linkrate = rates->minimum_linkrate; 3128 phy->maximum_linkrate = rates->maximum_linkrate; 3129 return mpi3mr_expander_phy_control(mrioc, phy, 3130 SMP_PHY_CONTROL_LINK_RESET); 3131 } 3132 3133 /* handle hba phys */ 3134 sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) + 3135 (mrioc->sas_hba.num_phys * 3136 sizeof(struct mpi3_sas_io_unit1_phy_data)); 3137 sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL); 3138 if (!sas_io_unit_pg1) { 3139 rc = -ENOMEM; 3140 goto out; 3141 } 3142 3143 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) { 3144 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 3145 __FILE__, __LINE__, __func__); 3146 rc = -ENXIO; 3147 goto out; 3148 } 3149 3150 sas_io_unit_pg1->phy_data[phy->number].max_min_link_rate = 3151 (rates->minimum_linkrate + (rates->maximum_linkrate << 4)); 3152 3153 if (mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) { 3154 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 3155 __FILE__, __LINE__, __func__); 3156 rc = -ENXIO; 3157 goto out; 3158 } 3159 3160 /* link reset */ 3161 mpi3mr_transport_phy_reset(phy, 0); 3162 3163 /* read phy page 0, then update the rates in the sas transport phy */ 3164 if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0, 3165 sizeof(struct mpi3_sas_phy_page0), 3166 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number) && 3167 (ioc_status == MPI3_IOCSTATUS_SUCCESS)) { 3168 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate( 3169 phy_pg0.programmed_link_rate & 3170 MPI3_SAS_PRATE_MIN_RATE_MASK); 3171 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate( 3172 phy_pg0.programmed_link_rate >> 4); 3173 phy->negotiated_linkrate = 3174 mpi3mr_convert_phy_link_rate( 3175 (phy_pg0.negotiated_link_rate & 3176 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) 3177 >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT); 3178 } 3179 3180 out: 3181 kfree(sas_io_unit_pg1); 3182 return rc; 3183 } 3184 3185 /** 3186 * mpi3mr_map_smp_buffer - map BSG dma buffer 3187 * @dev: Generic device reference 3188 * @buf: BSG buffer pointer 3189 * @dma_addr: Physical address holder 3190 * @dma_len: Mapped DMA buffer length. 3191 * @p: Virtual address holder 3192 * 3193 * This function maps the DMAable buffer 3194 * 3195 * Return: 0 on success, non-zero on failure 3196 */ 3197 static int 3198 mpi3mr_map_smp_buffer(struct device *dev, struct bsg_buffer *buf, 3199 dma_addr_t *dma_addr, size_t *dma_len, void **p) 3200 { 3201 /* Check if the request is split across multiple segments */ 3202 if (buf->sg_cnt > 1) { 3203 *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr, 3204 GFP_KERNEL); 3205 if (!*p) 3206 return -ENOMEM; 3207 *dma_len = buf->payload_len; 3208 } else { 3209 if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL)) 3210 return -ENOMEM; 3211 *dma_addr = sg_dma_address(buf->sg_list); 3212 *dma_len = sg_dma_len(buf->sg_list); 3213 *p = NULL; 3214 } 3215 3216 return 0; 3217 } 3218 3219 /** 3220 * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer 3221 * @dev: Generic device reference 3222 * @buf: BSG buffer pointer 3223 * @dma_addr: Physical address to be unmapped 3224 * @p: Virtual address 3225 * 3226 * This function unmaps the DMAable buffer 3227 */ 3228 static void 3229 mpi3mr_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf, 3230 dma_addr_t dma_addr, void *p) 3231 { 3232 if (p) 3233 dma_free_coherent(dev, buf->payload_len, p, dma_addr); 3234 else 3235 dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL); 3236 } 3237 3238 /** 3239 * mpi3mr_transport_smp_handler - handler for smp passthru 3240 * @job: BSG job reference 3241 * @shost: SCSI host object reference 3242 * @rphy: SAS transport rphy object pointing the expander 3243 * 3244 * This is used primarily by smp utils for sending the SMP 3245 * commands to the expanders attached to the controller 3246 */ 3247 static void 3248 mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost, 3249 struct sas_rphy *rphy) 3250 { 3251 struct mpi3mr_ioc *mrioc = shost_priv(shost); 3252 struct mpi3_smp_passthrough_request mpi_request; 3253 struct mpi3_smp_passthrough_reply mpi_reply; 3254 int rc; 3255 void *psge; 3256 dma_addr_t dma_addr_in; 3257 dma_addr_t dma_addr_out; 3258 void *addr_in = NULL; 3259 void *addr_out = NULL; 3260 size_t dma_len_in; 3261 size_t dma_len_out; 3262 unsigned int reslen = 0; 3263 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request); 3264 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply); 3265 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST; 3266 u16 ioc_status; 3267 3268 if (mrioc->reset_in_progress) { 3269 ioc_err(mrioc, "%s: host reset in progress!\n", __func__); 3270 rc = -EFAULT; 3271 goto out; 3272 } 3273 3274 if (mrioc->pci_err_recovery) { 3275 ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__); 3276 rc = -EFAULT; 3277 goto out; 3278 } 3279 3280 rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload, 3281 &dma_addr_out, &dma_len_out, &addr_out); 3282 if (rc) 3283 goto out; 3284 3285 if (addr_out) 3286 sg_copy_to_buffer(job->request_payload.sg_list, 3287 job->request_payload.sg_cnt, addr_out, 3288 job->request_payload.payload_len); 3289 3290 rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->reply_payload, 3291 &dma_addr_in, &dma_len_in, &addr_in); 3292 if (rc) 3293 goto unmap_out; 3294 3295 memset(&mpi_request, 0, request_sz); 3296 memset(&mpi_reply, 0, reply_sz); 3297 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS); 3298 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH; 3299 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_rphy(mrioc, rphy); 3300 mpi_request.sas_address = ((rphy) ? 3301 cpu_to_le64(rphy->identify.sas_address) : 3302 cpu_to_le64(mrioc->sas_hba.sas_address)); 3303 psge = &mpi_request.request_sge; 3304 mpi3mr_add_sg_single(psge, sgl_flags, dma_len_out - 4, dma_addr_out); 3305 3306 psge = &mpi_request.response_sge; 3307 mpi3mr_add_sg_single(psge, sgl_flags, dma_len_in - 4, dma_addr_in); 3308 3309 dprint_transport_info(mrioc, "sending SMP request\n"); 3310 3311 rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz, 3312 &mpi_reply, reply_sz, 3313 MPI3MR_INTADMCMD_TIMEOUT, &ioc_status); 3314 if (rc) 3315 goto unmap_in; 3316 3317 dprint_transport_info(mrioc, 3318 "SMP request completed with ioc_status(0x%04x)\n", ioc_status); 3319 3320 dprint_transport_info(mrioc, 3321 "SMP request - reply data transfer size(%d)\n", 3322 le16_to_cpu(mpi_reply.response_data_length)); 3323 3324 memcpy(job->reply, &mpi_reply, reply_sz); 3325 job->reply_len = reply_sz; 3326 reslen = le16_to_cpu(mpi_reply.response_data_length); 3327 3328 if (addr_in) 3329 sg_copy_from_buffer(job->reply_payload.sg_list, 3330 job->reply_payload.sg_cnt, addr_in, 3331 job->reply_payload.payload_len); 3332 3333 rc = 0; 3334 unmap_in: 3335 mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->reply_payload, 3336 dma_addr_in, addr_in); 3337 unmap_out: 3338 mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->request_payload, 3339 dma_addr_out, addr_out); 3340 out: 3341 bsg_job_done(job, rc, reslen); 3342 } 3343 3344 struct sas_function_template mpi3mr_transport_functions = { 3345 .get_linkerrors = mpi3mr_transport_get_linkerrors, 3346 .get_enclosure_identifier = mpi3mr_transport_get_enclosure_identifier, 3347 .get_bay_identifier = mpi3mr_transport_get_bay_identifier, 3348 .phy_reset = mpi3mr_transport_phy_reset, 3349 .phy_enable = mpi3mr_transport_phy_enable, 3350 .set_phy_speed = mpi3mr_transport_phy_speed, 3351 .smp_handler = mpi3mr_transport_smp_handler, 3352 }; 3353 3354 struct scsi_transport_template *mpi3mr_transport_template; 3355