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