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