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