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 for (i = 0; i < mr_sas_node->num_phys; i++) { 1359 if ((mr_sas_node->phy[i].remote_identify.sas_address != 1360 mr_sas_port->remote_identify.sas_address) || 1361 (mr_sas_node->phy[i].hba_port != hba_port)) 1362 continue; 1363 list_add_tail(&mr_sas_node->phy[i].port_siblings, 1364 &mr_sas_port->phy_list); 1365 mr_sas_port->num_phys++; 1366 mr_sas_port->phy_mask |= (1 << i); 1367 } 1368 1369 if (!mr_sas_port->num_phys) { 1370 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1371 __FILE__, __LINE__, __func__); 1372 goto out_fail; 1373 } 1374 1375 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1; 1376 1377 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { 1378 tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc, 1379 mr_sas_port->remote_identify.sas_address, 1380 mr_sas_port->hba_port); 1381 1382 if (!tgtdev) { 1383 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1384 __FILE__, __LINE__, __func__); 1385 goto out_fail; 1386 } 1387 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1; 1388 } 1389 1390 if (!mr_sas_node->parent_dev) { 1391 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1392 __FILE__, __LINE__, __func__); 1393 goto out_fail; 1394 } 1395 1396 port = sas_port_alloc_num(mr_sas_node->parent_dev); 1397 if ((sas_port_add(port))) { 1398 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1399 __FILE__, __LINE__, __func__); 1400 goto out_fail; 1401 } 1402 1403 list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list, 1404 port_siblings) { 1405 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) 1406 dev_info(&port->dev, 1407 "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n", 1408 handle, (unsigned long long) 1409 mr_sas_port->remote_identify.sas_address, 1410 mr_sas_phy->phy_id); 1411 sas_port_add_phy(port, mr_sas_phy->phy); 1412 mr_sas_phy->phy_belongs_to_port = 1; 1413 mr_sas_phy->hba_port = hba_port; 1414 } 1415 1416 mr_sas_port->port = port; 1417 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { 1418 rphy = sas_end_device_alloc(port); 1419 tgtdev->dev_spec.sas_sata_inf.rphy = rphy; 1420 } else { 1421 rphy = sas_expander_alloc(port, 1422 mr_sas_port->remote_identify.device_type); 1423 } 1424 rphy->identify = mr_sas_port->remote_identify; 1425 1426 if (mrioc->current_event) 1427 mrioc->current_event->pending_at_sml = 1; 1428 1429 if ((sas_rphy_add(rphy))) { 1430 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1431 __FILE__, __LINE__, __func__); 1432 } 1433 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) { 1434 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0; 1435 tgtdev->dev_spec.sas_sata_inf.sas_transport_attached = 1; 1436 mpi3mr_tgtdev_put(tgtdev); 1437 } 1438 1439 dev_info(&rphy->dev, 1440 "%s: added: handle(0x%04x), sas_address(0x%016llx)\n", 1441 __func__, handle, (unsigned long long) 1442 mr_sas_port->remote_identify.sas_address); 1443 1444 mr_sas_port->rphy = rphy; 1445 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1446 list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list); 1447 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1448 1449 if (mrioc->current_event) { 1450 mrioc->current_event->pending_at_sml = 0; 1451 if (mrioc->current_event->discard) 1452 mpi3mr_print_device_event_notice(mrioc, true); 1453 } 1454 1455 /* fill in report manufacture */ 1456 if (mr_sas_port->remote_identify.device_type == 1457 SAS_EDGE_EXPANDER_DEVICE || 1458 mr_sas_port->remote_identify.device_type == 1459 SAS_FANOUT_EXPANDER_DEVICE) 1460 mpi3mr_report_manufacture(mrioc, 1461 mr_sas_port->remote_identify.sas_address, 1462 rphy_to_expander_device(rphy), hba_port->port_id); 1463 1464 return mr_sas_port; 1465 1466 out_fail: 1467 list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list, 1468 port_siblings) 1469 list_del(&mr_sas_phy->port_siblings); 1470 kfree(mr_sas_port); 1471 return NULL; 1472 } 1473 1474 /** 1475 * mpi3mr_sas_port_remove - remove port from the list 1476 * @mrioc: Adapter instance reference 1477 * @sas_address: SAS address of attached device 1478 * @sas_address_parent: SAS address of parent expander or host 1479 * @hba_port: HBA port entry 1480 * 1481 * Removing object and freeing associated memory from the 1482 * sas_port_list. 1483 * 1484 * Return: None 1485 */ 1486 static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address, 1487 u64 sas_address_parent, struct mpi3mr_hba_port *hba_port) 1488 { 1489 int i; 1490 unsigned long flags; 1491 struct mpi3mr_sas_port *mr_sas_port, *next; 1492 struct mpi3mr_sas_node *mr_sas_node; 1493 u8 found = 0; 1494 struct mpi3mr_sas_phy *mr_sas_phy, *next_phy; 1495 struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL; 1496 1497 if (!hba_port) 1498 return; 1499 1500 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1501 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc, 1502 sas_address_parent, hba_port); 1503 if (!mr_sas_node) { 1504 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1505 return; 1506 } 1507 list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list, 1508 port_list) { 1509 if (mr_sas_port->remote_identify.sas_address != sas_address) 1510 continue; 1511 if (mr_sas_port->hba_port != hba_port) 1512 continue; 1513 found = 1; 1514 list_del(&mr_sas_port->port_list); 1515 goto out; 1516 } 1517 1518 out: 1519 if (!found) { 1520 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1521 return; 1522 } 1523 1524 if (mr_sas_node->host_node) { 1525 list_for_each_entry_safe(srch_port, hba_port_next, 1526 &mrioc->hba_port_table_list, list) { 1527 if (srch_port != hba_port) 1528 continue; 1529 ioc_info(mrioc, 1530 "removing hba_port entry: %p port: %d from hba_port list\n", 1531 srch_port, srch_port->port_id); 1532 list_del(&hba_port->list); 1533 kfree(hba_port); 1534 break; 1535 } 1536 } 1537 1538 for (i = 0; i < mr_sas_node->num_phys; i++) { 1539 if (mr_sas_node->phy[i].remote_identify.sas_address == 1540 sas_address) 1541 memset(&mr_sas_node->phy[i].remote_identify, 0, 1542 sizeof(struct sas_identify)); 1543 } 1544 1545 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1546 1547 if (mrioc->current_event) 1548 mrioc->current_event->pending_at_sml = 1; 1549 1550 list_for_each_entry_safe(mr_sas_phy, next_phy, 1551 &mr_sas_port->phy_list, port_siblings) { 1552 if ((!mrioc->stop_drv_processing) && 1553 (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)) 1554 dev_info(&mr_sas_port->port->dev, 1555 "remove: sas_address(0x%016llx), phy(%d)\n", 1556 (unsigned long long) 1557 mr_sas_port->remote_identify.sas_address, 1558 mr_sas_phy->phy_id); 1559 mr_sas_phy->phy_belongs_to_port = 0; 1560 if (!mrioc->stop_drv_processing) 1561 sas_port_delete_phy(mr_sas_port->port, 1562 mr_sas_phy->phy); 1563 list_del(&mr_sas_phy->port_siblings); 1564 } 1565 if (!mrioc->stop_drv_processing) 1566 sas_port_delete(mr_sas_port->port); 1567 ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n", 1568 __func__, (unsigned long long)sas_address); 1569 1570 if (mrioc->current_event) { 1571 mrioc->current_event->pending_at_sml = 0; 1572 if (mrioc->current_event->discard) 1573 mpi3mr_print_device_event_notice(mrioc, false); 1574 } 1575 1576 kfree(mr_sas_port); 1577 } 1578 1579 /** 1580 * struct host_port - host port details 1581 * @sas_address: SAS Address of the attached device 1582 * @phy_mask: phy mask of host port 1583 * @handle: Device Handle of attached device 1584 * @iounit_port_id: port ID 1585 * @used: host port is already matched with sas port from sas_port_list 1586 * @lowest_phy: lowest phy ID of host port 1587 */ 1588 struct host_port { 1589 u64 sas_address; 1590 u32 phy_mask; 1591 u16 handle; 1592 u8 iounit_port_id; 1593 u8 used; 1594 u8 lowest_phy; 1595 }; 1596 1597 /** 1598 * mpi3mr_update_mr_sas_port - update sas port objects during reset 1599 * @mrioc: Adapter instance reference 1600 * @h_port: host_port object 1601 * @mr_sas_port: sas_port objects which needs to be updated 1602 * 1603 * Update the port ID of sas port object. Also add the phys if new phys got 1604 * added to current sas port and remove the phys if some phys are moved 1605 * out of the current sas port. 1606 * 1607 * Return: Nothing. 1608 */ 1609 static void 1610 mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port, 1611 struct mpi3mr_sas_port *mr_sas_port) 1612 { 1613 struct mpi3mr_sas_phy *mr_sas_phy; 1614 u32 phy_mask_xor; 1615 u64 phys_to_be_added, phys_to_be_removed; 1616 int i; 1617 1618 h_port->used = 1; 1619 mr_sas_port->marked_responding = 1; 1620 1621 dev_info(&mr_sas_port->port->dev, 1622 "sas_address(0x%016llx), old: port_id %d phy_mask 0x%x, new: port_id %d phy_mask:0x%x\n", 1623 mr_sas_port->remote_identify.sas_address, 1624 mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask, 1625 h_port->iounit_port_id, h_port->phy_mask); 1626 1627 mr_sas_port->hba_port->port_id = h_port->iounit_port_id; 1628 mr_sas_port->hba_port->flags &= ~MPI3MR_HBA_PORT_FLAG_DIRTY; 1629 1630 /* Get the newly added phys bit map & removed phys bit map */ 1631 phy_mask_xor = mr_sas_port->phy_mask ^ h_port->phy_mask; 1632 phys_to_be_added = h_port->phy_mask & phy_mask_xor; 1633 phys_to_be_removed = mr_sas_port->phy_mask & phy_mask_xor; 1634 1635 /* 1636 * Register these new phys to current mr_sas_port's port. 1637 * if these phys are previously registered with another port 1638 * then delete these phys from that port first. 1639 */ 1640 for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u32)) { 1641 mr_sas_phy = &mrioc->sas_hba.phy[i]; 1642 if (mr_sas_phy->phy_belongs_to_port) 1643 mpi3mr_del_phy_from_an_existing_port(mrioc, 1644 &mrioc->sas_hba, mr_sas_phy); 1645 mpi3mr_add_phy_to_an_existing_port(mrioc, 1646 &mrioc->sas_hba, mr_sas_phy, 1647 mr_sas_port->remote_identify.sas_address, 1648 mr_sas_port->hba_port); 1649 } 1650 1651 /* Delete the phys which are not part of current mr_sas_port's port. */ 1652 for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u32)) { 1653 mr_sas_phy = &mrioc->sas_hba.phy[i]; 1654 if (mr_sas_phy->phy_belongs_to_port) 1655 mpi3mr_del_phy_from_an_existing_port(mrioc, 1656 &mrioc->sas_hba, mr_sas_phy); 1657 } 1658 } 1659 1660 /** 1661 * mpi3mr_refresh_sas_ports - update host's sas ports during reset 1662 * @mrioc: Adapter instance reference 1663 * 1664 * Update the host's sas ports during reset by checking whether 1665 * sas ports are still intact or not. Add/remove phys if any hba 1666 * phys are (moved in)/(moved out) of sas port. Also update 1667 * io_unit_port if it got changed during reset. 1668 * 1669 * Return: Nothing. 1670 */ 1671 void 1672 mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc) 1673 { 1674 struct host_port h_port[32]; 1675 int i, j, found, host_port_count = 0, port_idx; 1676 u16 sz, attached_handle, ioc_status; 1677 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; 1678 struct mpi3_device_page0 dev_pg0; 1679 struct mpi3_device0_sas_sata_format *sasinf; 1680 struct mpi3mr_sas_port *mr_sas_port; 1681 1682 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + 1683 (mrioc->sas_hba.num_phys * 1684 sizeof(struct mpi3_sas_io_unit0_phy_data)); 1685 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); 1686 if (!sas_io_unit_pg0) 1687 return; 1688 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { 1689 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1690 __FILE__, __LINE__, __func__); 1691 goto out; 1692 } 1693 1694 /* Create a new expander port table */ 1695 for (i = 0; i < mrioc->sas_hba.num_phys; i++) { 1696 attached_handle = le16_to_cpu( 1697 sas_io_unit_pg0->phy_data[i].attached_dev_handle); 1698 if (!attached_handle) 1699 continue; 1700 found = 0; 1701 for (j = 0; j < host_port_count; j++) { 1702 if (h_port[j].handle == attached_handle) { 1703 h_port[j].phy_mask |= (1 << i); 1704 found = 1; 1705 break; 1706 } 1707 } 1708 if (found) 1709 continue; 1710 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0, 1711 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, 1712 attached_handle))) { 1713 dprint_reset(mrioc, 1714 "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n", 1715 attached_handle, __FILE__, __LINE__, __func__); 1716 continue; 1717 } 1718 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 1719 dprint_reset(mrioc, 1720 "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n", 1721 ioc_status, attached_handle, 1722 __FILE__, __LINE__, __func__); 1723 continue; 1724 } 1725 sasinf = &dev_pg0.device_specific.sas_sata_format; 1726 1727 port_idx = host_port_count; 1728 h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address); 1729 h_port[port_idx].handle = attached_handle; 1730 h_port[port_idx].phy_mask = (1 << i); 1731 h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port; 1732 h_port[port_idx].lowest_phy = sasinf->phy_num; 1733 h_port[port_idx].used = 0; 1734 host_port_count++; 1735 } 1736 1737 if (!host_port_count) 1738 goto out; 1739 1740 if (mrioc->logging_level & MPI3_DEBUG_RESET) { 1741 ioc_info(mrioc, "Host port details before reset\n"); 1742 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, 1743 port_list) { 1744 ioc_info(mrioc, 1745 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n", 1746 mr_sas_port->hba_port->port_id, 1747 mr_sas_port->remote_identify.sas_address, 1748 mr_sas_port->phy_mask, mr_sas_port->lowest_phy); 1749 } 1750 mr_sas_port = NULL; 1751 ioc_info(mrioc, "Host port details after reset\n"); 1752 for (i = 0; i < host_port_count; i++) { 1753 ioc_info(mrioc, 1754 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n", 1755 h_port[i].iounit_port_id, h_port[i].sas_address, 1756 h_port[i].phy_mask, h_port[i].lowest_phy); 1757 } 1758 } 1759 1760 /* mark all host sas port entries as dirty */ 1761 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, 1762 port_list) { 1763 mr_sas_port->marked_responding = 0; 1764 mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY; 1765 } 1766 1767 /* First check for matching lowest phy */ 1768 for (i = 0; i < host_port_count; i++) { 1769 mr_sas_port = NULL; 1770 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, 1771 port_list) { 1772 if (mr_sas_port->marked_responding) 1773 continue; 1774 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address) 1775 continue; 1776 if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) { 1777 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port); 1778 break; 1779 } 1780 } 1781 } 1782 1783 /* In case if lowest phy is got enabled or disabled during reset */ 1784 for (i = 0; i < host_port_count; i++) { 1785 if (h_port[i].used) 1786 continue; 1787 mr_sas_port = NULL; 1788 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, 1789 port_list) { 1790 if (mr_sas_port->marked_responding) 1791 continue; 1792 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address) 1793 continue; 1794 if (h_port[i].phy_mask & mr_sas_port->phy_mask) { 1795 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port); 1796 break; 1797 } 1798 } 1799 } 1800 1801 /* In case if expander cable is removed & connected to another HBA port during reset */ 1802 for (i = 0; i < host_port_count; i++) { 1803 if (h_port[i].used) 1804 continue; 1805 mr_sas_port = NULL; 1806 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, 1807 port_list) { 1808 if (mr_sas_port->marked_responding) 1809 continue; 1810 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address) 1811 continue; 1812 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port); 1813 break; 1814 } 1815 } 1816 out: 1817 kfree(sas_io_unit_pg0); 1818 } 1819 1820 /** 1821 * mpi3mr_refresh_expanders - Refresh expander device exposure 1822 * @mrioc: Adapter instance reference 1823 * 1824 * This is executed post controller reset to identify any 1825 * missing expander devices during reset and remove from the upper layers 1826 * or expose any newly detected expander device to the upper layers. 1827 * 1828 * Return: Nothing. 1829 */ 1830 void 1831 mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc) 1832 { 1833 struct mpi3mr_sas_node *sas_expander, *sas_expander_next; 1834 struct mpi3_sas_expander_page0 expander_pg0; 1835 u16 ioc_status, handle; 1836 u64 sas_address; 1837 int i; 1838 unsigned long flags; 1839 struct mpi3mr_hba_port *hba_port; 1840 1841 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1842 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) { 1843 sas_expander->non_responding = 1; 1844 } 1845 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1846 1847 sas_expander = NULL; 1848 1849 handle = 0xffff; 1850 1851 /* Search for responding expander devices and add them if they are newly got added */ 1852 while (true) { 1853 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0, 1854 sizeof(struct mpi3_sas_expander_page0), 1855 MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) { 1856 dprint_reset(mrioc, 1857 "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n", 1858 handle, __FILE__, __LINE__, __func__); 1859 break; 1860 } 1861 1862 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 1863 dprint_reset(mrioc, 1864 "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n", 1865 ioc_status, handle, __FILE__, __LINE__, __func__); 1866 break; 1867 } 1868 1869 handle = le16_to_cpu(expander_pg0.dev_handle); 1870 sas_address = le64_to_cpu(expander_pg0.sas_address); 1871 hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port); 1872 1873 if (!hba_port) { 1874 mpi3mr_sas_host_refresh(mrioc); 1875 mpi3mr_expander_add(mrioc, handle); 1876 continue; 1877 } 1878 1879 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1880 sas_expander = 1881 mpi3mr_expander_find_by_sas_address(mrioc, 1882 sas_address, hba_port); 1883 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1884 1885 if (!sas_expander) { 1886 mpi3mr_sas_host_refresh(mrioc); 1887 mpi3mr_expander_add(mrioc, handle); 1888 continue; 1889 } 1890 1891 sas_expander->non_responding = 0; 1892 if (sas_expander->handle == handle) 1893 continue; 1894 1895 sas_expander->handle = handle; 1896 for (i = 0 ; i < sas_expander->num_phys ; i++) 1897 sas_expander->phy[i].handle = handle; 1898 } 1899 1900 /* 1901 * Delete non responding expander devices and the corresponding 1902 * hba_port if the non responding expander device's parent device 1903 * is a host node. 1904 */ 1905 sas_expander = NULL; 1906 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1907 list_for_each_entry_safe_reverse(sas_expander, sas_expander_next, 1908 &mrioc->sas_expander_list, list) { 1909 if (sas_expander->non_responding) { 1910 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1911 mpi3mr_expander_node_remove(mrioc, sas_expander); 1912 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1913 } 1914 } 1915 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1916 } 1917 1918 /** 1919 * mpi3mr_expander_node_add - insert an expander to the list. 1920 * @mrioc: Adapter instance reference 1921 * @sas_expander: Expander sas node 1922 * Context: This function will acquire sas_node_lock. 1923 * 1924 * Adding new object to the ioc->sas_expander_list. 1925 * 1926 * Return: None. 1927 */ 1928 static void mpi3mr_expander_node_add(struct mpi3mr_ioc *mrioc, 1929 struct mpi3mr_sas_node *sas_expander) 1930 { 1931 unsigned long flags; 1932 1933 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 1934 list_add_tail(&sas_expander->list, &mrioc->sas_expander_list); 1935 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 1936 } 1937 1938 /** 1939 * mpi3mr_expander_add - Create expander object 1940 * @mrioc: Adapter instance reference 1941 * @handle: Expander firmware device handle 1942 * 1943 * This function creating expander object, stored in 1944 * sas_expander_list and expose it to the SAS transport 1945 * layer. 1946 * 1947 * Return: 0 for success, non-zero for failure. 1948 */ 1949 int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle) 1950 { 1951 struct mpi3mr_sas_node *sas_expander; 1952 struct mpi3mr_enclosure_node *enclosure_dev; 1953 struct mpi3_sas_expander_page0 expander_pg0; 1954 struct mpi3_sas_expander_page1 expander_pg1; 1955 u16 ioc_status, parent_handle, temp_handle; 1956 u64 sas_address, sas_address_parent = 0; 1957 int i; 1958 unsigned long flags; 1959 u8 port_id, link_rate; 1960 struct mpi3mr_sas_port *mr_sas_port = NULL; 1961 struct mpi3mr_hba_port *hba_port; 1962 u32 phynum_handle; 1963 int rc = 0; 1964 1965 if (!handle) 1966 return -1; 1967 1968 if (mrioc->reset_in_progress) 1969 return -1; 1970 1971 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0, 1972 sizeof(expander_pg0), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE, handle))) { 1973 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1974 __FILE__, __LINE__, __func__); 1975 return -1; 1976 } 1977 1978 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 1979 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1980 __FILE__, __LINE__, __func__); 1981 return -1; 1982 } 1983 1984 parent_handle = le16_to_cpu(expander_pg0.parent_dev_handle); 1985 if (mpi3mr_get_sas_address(mrioc, parent_handle, &sas_address_parent) 1986 != 0) { 1987 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1988 __FILE__, __LINE__, __func__); 1989 return -1; 1990 } 1991 1992 port_id = expander_pg0.io_unit_port; 1993 hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id); 1994 if (!hba_port) { 1995 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 1996 __FILE__, __LINE__, __func__); 1997 return -1; 1998 } 1999 2000 if (sas_address_parent != mrioc->sas_hba.sas_address) { 2001 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 2002 sas_expander = 2003 mpi3mr_expander_find_by_sas_address(mrioc, 2004 sas_address_parent, hba_port); 2005 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 2006 if (!sas_expander) { 2007 rc = mpi3mr_expander_add(mrioc, parent_handle); 2008 if (rc != 0) 2009 return rc; 2010 } else { 2011 /* 2012 * When there is a parent expander present, update it's 2013 * phys where child expander is connected with the link 2014 * speed, attached dev handle and sas address. 2015 */ 2016 for (i = 0 ; i < sas_expander->num_phys ; i++) { 2017 phynum_handle = 2018 (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | 2019 parent_handle; 2020 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, 2021 &ioc_status, &expander_pg1, 2022 sizeof(expander_pg1), 2023 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM, 2024 phynum_handle)) { 2025 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2026 __FILE__, __LINE__, __func__); 2027 rc = -1; 2028 return rc; 2029 } 2030 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2031 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2032 __FILE__, __LINE__, __func__); 2033 rc = -1; 2034 return rc; 2035 } 2036 temp_handle = le16_to_cpu( 2037 expander_pg1.attached_dev_handle); 2038 if (temp_handle != handle) 2039 continue; 2040 link_rate = (expander_pg1.negotiated_link_rate & 2041 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> 2042 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT; 2043 mpi3mr_update_links(mrioc, sas_address_parent, 2044 handle, i, link_rate, hba_port); 2045 } 2046 } 2047 } 2048 2049 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 2050 sas_address = le64_to_cpu(expander_pg0.sas_address); 2051 sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, 2052 sas_address, hba_port); 2053 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 2054 2055 if (sas_expander) 2056 return 0; 2057 2058 sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node), 2059 GFP_KERNEL); 2060 if (!sas_expander) 2061 return -ENOMEM; 2062 2063 sas_expander->handle = handle; 2064 sas_expander->num_phys = expander_pg0.num_phys; 2065 sas_expander->sas_address_parent = sas_address_parent; 2066 sas_expander->sas_address = sas_address; 2067 sas_expander->hba_port = hba_port; 2068 2069 ioc_info(mrioc, 2070 "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", 2071 handle, parent_handle, (unsigned long long) 2072 sas_expander->sas_address, sas_expander->num_phys); 2073 2074 if (!sas_expander->num_phys) { 2075 rc = -1; 2076 goto out_fail; 2077 } 2078 sas_expander->phy = kcalloc(sas_expander->num_phys, 2079 sizeof(struct mpi3mr_sas_phy), GFP_KERNEL); 2080 if (!sas_expander->phy) { 2081 rc = -1; 2082 goto out_fail; 2083 } 2084 2085 INIT_LIST_HEAD(&sas_expander->sas_port_list); 2086 mr_sas_port = mpi3mr_sas_port_add(mrioc, handle, sas_address_parent, 2087 sas_expander->hba_port); 2088 if (!mr_sas_port) { 2089 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2090 __FILE__, __LINE__, __func__); 2091 rc = -1; 2092 goto out_fail; 2093 } 2094 sas_expander->parent_dev = &mr_sas_port->rphy->dev; 2095 sas_expander->rphy = mr_sas_port->rphy; 2096 2097 for (i = 0 ; i < sas_expander->num_phys ; i++) { 2098 phynum_handle = (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | 2099 handle; 2100 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status, 2101 &expander_pg1, sizeof(expander_pg1), 2102 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM, 2103 phynum_handle)) { 2104 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2105 __FILE__, __LINE__, __func__); 2106 rc = -1; 2107 goto out_fail; 2108 } 2109 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2110 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2111 __FILE__, __LINE__, __func__); 2112 rc = -1; 2113 goto out_fail; 2114 } 2115 2116 sas_expander->phy[i].handle = handle; 2117 sas_expander->phy[i].phy_id = i; 2118 sas_expander->phy[i].hba_port = hba_port; 2119 2120 if ((mpi3mr_add_expander_phy(mrioc, &sas_expander->phy[i], 2121 expander_pg1, sas_expander->parent_dev))) { 2122 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2123 __FILE__, __LINE__, __func__); 2124 rc = -1; 2125 goto out_fail; 2126 } 2127 } 2128 2129 if (sas_expander->enclosure_handle) { 2130 enclosure_dev = 2131 mpi3mr_enclosure_find_by_handle(mrioc, 2132 sas_expander->enclosure_handle); 2133 if (enclosure_dev) 2134 sas_expander->enclosure_logical_id = le64_to_cpu( 2135 enclosure_dev->pg0.enclosure_logical_id); 2136 } 2137 2138 mpi3mr_expander_node_add(mrioc, sas_expander); 2139 return 0; 2140 2141 out_fail: 2142 2143 if (mr_sas_port) 2144 mpi3mr_sas_port_remove(mrioc, 2145 sas_expander->sas_address, 2146 sas_address_parent, sas_expander->hba_port); 2147 kfree(sas_expander->phy); 2148 kfree(sas_expander); 2149 return rc; 2150 } 2151 2152 /** 2153 * mpi3mr_expander_node_remove - recursive removal of expander. 2154 * @mrioc: Adapter instance reference 2155 * @sas_expander: Expander device object 2156 * 2157 * Removes expander object and freeing associated memory from 2158 * the sas_expander_list and removes the same from SAS TL, if 2159 * one of the attached device is an expander then it recursively 2160 * removes the expander device too. 2161 * 2162 * Return nothing. 2163 */ 2164 void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc, 2165 struct mpi3mr_sas_node *sas_expander) 2166 { 2167 struct mpi3mr_sas_port *mr_sas_port, *next; 2168 unsigned long flags; 2169 u8 port_id; 2170 2171 /* remove sibling ports attached to this expander */ 2172 list_for_each_entry_safe(mr_sas_port, next, 2173 &sas_expander->sas_port_list, port_list) { 2174 if (mrioc->reset_in_progress) 2175 return; 2176 if (mr_sas_port->remote_identify.device_type == 2177 SAS_END_DEVICE) 2178 mpi3mr_remove_device_by_sas_address(mrioc, 2179 mr_sas_port->remote_identify.sas_address, 2180 mr_sas_port->hba_port); 2181 else if (mr_sas_port->remote_identify.device_type == 2182 SAS_EDGE_EXPANDER_DEVICE || 2183 mr_sas_port->remote_identify.device_type == 2184 SAS_FANOUT_EXPANDER_DEVICE) 2185 mpi3mr_expander_remove(mrioc, 2186 mr_sas_port->remote_identify.sas_address, 2187 mr_sas_port->hba_port); 2188 } 2189 2190 port_id = sas_expander->hba_port->port_id; 2191 mpi3mr_sas_port_remove(mrioc, sas_expander->sas_address, 2192 sas_expander->sas_address_parent, sas_expander->hba_port); 2193 2194 ioc_info(mrioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n", 2195 sas_expander->handle, (unsigned long long) 2196 sas_expander->sas_address, port_id); 2197 2198 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 2199 list_del(&sas_expander->list); 2200 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 2201 2202 kfree(sas_expander->phy); 2203 kfree(sas_expander); 2204 } 2205 2206 /** 2207 * mpi3mr_expander_remove - Remove expander object 2208 * @mrioc: Adapter instance reference 2209 * @sas_address: Remove expander sas_address 2210 * @hba_port: HBA port reference 2211 * 2212 * This function remove expander object, stored in 2213 * mrioc->sas_expander_list and removes it from the SAS TL by 2214 * calling mpi3mr_expander_node_remove(). 2215 * 2216 * Return: None 2217 */ 2218 void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address, 2219 struct mpi3mr_hba_port *hba_port) 2220 { 2221 struct mpi3mr_sas_node *sas_expander; 2222 unsigned long flags; 2223 2224 if (mrioc->reset_in_progress) 2225 return; 2226 2227 if (!hba_port) 2228 return; 2229 2230 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 2231 sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, sas_address, 2232 hba_port); 2233 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 2234 if (sas_expander) 2235 mpi3mr_expander_node_remove(mrioc, sas_expander); 2236 2237 } 2238 2239 /** 2240 * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate 2241 * @mrioc: Adapter instance reference 2242 * @tgtdev: Target device 2243 * 2244 * This function identifies whether the target device is 2245 * attached directly or through expander and issues sas phy 2246 * page0 or expander phy page1 and gets the link rate, if there 2247 * is any failure in reading the pages then this returns link 2248 * rate of 1.5. 2249 * 2250 * Return: logical link rate. 2251 */ 2252 static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc, 2253 struct mpi3mr_tgt_dev *tgtdev) 2254 { 2255 u8 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5, phy_number; 2256 struct mpi3_sas_expander_page1 expander_pg1; 2257 struct mpi3_sas_phy_page0 phy_pg0; 2258 u32 phynum_handle; 2259 u16 ioc_status; 2260 2261 phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id; 2262 if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) { 2263 phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) 2264 | tgtdev->parent_handle); 2265 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status, 2266 &expander_pg1, sizeof(expander_pg1), 2267 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM, 2268 phynum_handle)) { 2269 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2270 __FILE__, __LINE__, __func__); 2271 goto out; 2272 } 2273 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2274 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2275 __FILE__, __LINE__, __func__); 2276 goto out; 2277 } 2278 link_rate = (expander_pg1.negotiated_link_rate & 2279 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> 2280 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT; 2281 goto out; 2282 } 2283 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0, 2284 sizeof(struct mpi3_sas_phy_page0), 2285 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy_number)) { 2286 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2287 __FILE__, __LINE__, __func__); 2288 goto out; 2289 } 2290 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2291 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2292 __FILE__, __LINE__, __func__); 2293 goto out; 2294 } 2295 link_rate = (phy_pg0.negotiated_link_rate & 2296 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> 2297 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT; 2298 out: 2299 return link_rate; 2300 } 2301 2302 /** 2303 * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL 2304 * @mrioc: Adapter instance reference 2305 * @tgtdev: Target device 2306 * 2307 * This function exposes the target device after 2308 * preparing host_phy, setting up link rate etc. 2309 * 2310 * Return: 0 on success, non-zero for failure. 2311 */ 2312 int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc, 2313 struct mpi3mr_tgt_dev *tgtdev) 2314 { 2315 int retval = 0; 2316 u8 link_rate, parent_phy_number; 2317 u64 sas_address_parent, sas_address; 2318 struct mpi3mr_hba_port *hba_port; 2319 u8 port_id; 2320 2321 if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) || 2322 !mrioc->sas_transport_enabled) 2323 return -1; 2324 2325 sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address; 2326 if (!mrioc->sas_hba.num_phys) 2327 mpi3mr_sas_host_add(mrioc); 2328 else 2329 mpi3mr_sas_host_refresh(mrioc); 2330 2331 if (mpi3mr_get_sas_address(mrioc, tgtdev->parent_handle, 2332 &sas_address_parent) != 0) { 2333 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2334 __FILE__, __LINE__, __func__); 2335 return -1; 2336 } 2337 tgtdev->dev_spec.sas_sata_inf.sas_address_parent = sas_address_parent; 2338 2339 parent_phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id; 2340 port_id = tgtdev->io_unit_port; 2341 2342 hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id); 2343 if (!hba_port) { 2344 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2345 __FILE__, __LINE__, __func__); 2346 return -1; 2347 } 2348 tgtdev->dev_spec.sas_sata_inf.hba_port = hba_port; 2349 2350 link_rate = mpi3mr_get_sas_negotiated_logical_linkrate(mrioc, tgtdev); 2351 2352 mpi3mr_update_links(mrioc, sas_address_parent, tgtdev->dev_handle, 2353 parent_phy_number, link_rate, hba_port); 2354 2355 tgtdev->host_exposed = 1; 2356 if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle, 2357 sas_address_parent, hba_port)) { 2358 retval = -1; 2359 } else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) { 2360 mpi3mr_sas_port_remove(mrioc, sas_address, 2361 sas_address_parent, hba_port); 2362 retval = -1; 2363 } 2364 if (retval) { 2365 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL; 2366 tgtdev->host_exposed = 0; 2367 } 2368 return retval; 2369 } 2370 2371 /** 2372 * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL 2373 * @mrioc: Adapter instance reference 2374 * @tgtdev: Target device 2375 * 2376 * This function removes the target device 2377 * 2378 * Return: None. 2379 */ 2380 void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc, 2381 struct mpi3mr_tgt_dev *tgtdev) 2382 { 2383 u64 sas_address_parent, sas_address; 2384 struct mpi3mr_hba_port *hba_port; 2385 2386 if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) || 2387 !mrioc->sas_transport_enabled) 2388 return; 2389 2390 hba_port = tgtdev->dev_spec.sas_sata_inf.hba_port; 2391 sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address; 2392 sas_address_parent = tgtdev->dev_spec.sas_sata_inf.sas_address_parent; 2393 mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent, 2394 hba_port); 2395 tgtdev->host_exposed = 0; 2396 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL; 2397 } 2398 2399 /** 2400 * mpi3mr_get_port_id_by_sas_phy - Get port ID of the given phy 2401 * @phy: SAS transport layer phy object 2402 * 2403 * Return: Port number for valid ID else 0xFFFF 2404 */ 2405 static inline u8 mpi3mr_get_port_id_by_sas_phy(struct sas_phy *phy) 2406 { 2407 u8 port_id = 0xFF; 2408 struct mpi3mr_hba_port *hba_port = phy->hostdata; 2409 2410 if (hba_port) 2411 port_id = hba_port->port_id; 2412 2413 return port_id; 2414 } 2415 2416 /** 2417 * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy 2418 * 2419 * @mrioc: Adapter instance reference 2420 * @rphy: SAS transport layer remote phy object 2421 * 2422 * Retrieves HBA port number in which the device pointed by the 2423 * rphy object is attached with. 2424 * 2425 * Return: Valid port number on success else OxFFFF. 2426 */ 2427 static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy *rphy) 2428 { 2429 struct mpi3mr_sas_node *sas_expander; 2430 struct mpi3mr_tgt_dev *tgtdev; 2431 unsigned long flags; 2432 u8 port_id = 0xFF; 2433 2434 if (!rphy) 2435 return port_id; 2436 2437 if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || 2438 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) { 2439 spin_lock_irqsave(&mrioc->sas_node_lock, flags); 2440 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, 2441 list) { 2442 if (sas_expander->rphy == rphy) { 2443 port_id = sas_expander->hba_port->port_id; 2444 break; 2445 } 2446 } 2447 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags); 2448 } else if (rphy->identify.device_type == SAS_END_DEVICE) { 2449 spin_lock_irqsave(&mrioc->tgtdev_lock, flags); 2450 2451 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc, 2452 rphy->identify.sas_address, rphy); 2453 if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) { 2454 port_id = 2455 tgtdev->dev_spec.sas_sata_inf.hba_port->port_id; 2456 mpi3mr_tgtdev_put(tgtdev); 2457 } 2458 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); 2459 } 2460 return port_id; 2461 } 2462 2463 static inline struct mpi3mr_ioc *phy_to_mrioc(struct sas_phy *phy) 2464 { 2465 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 2466 2467 return shost_priv(shost); 2468 } 2469 2470 static inline struct mpi3mr_ioc *rphy_to_mrioc(struct sas_rphy *rphy) 2471 { 2472 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 2473 2474 return shost_priv(shost); 2475 } 2476 2477 /* report phy error log structure */ 2478 struct phy_error_log_request { 2479 u8 smp_frame_type; /* 0x40 */ 2480 u8 function; /* 0x11 */ 2481 u8 allocated_response_length; 2482 u8 request_length; /* 02 */ 2483 u8 reserved_1[5]; 2484 u8 phy_identifier; 2485 u8 reserved_2[2]; 2486 }; 2487 2488 /* report phy error log reply structure */ 2489 struct phy_error_log_reply { 2490 u8 smp_frame_type; /* 0x41 */ 2491 u8 function; /* 0x11 */ 2492 u8 function_result; 2493 u8 response_length; 2494 __be16 expander_change_count; 2495 u8 reserved_1[3]; 2496 u8 phy_identifier; 2497 u8 reserved_2[2]; 2498 __be32 invalid_dword; 2499 __be32 running_disparity_error; 2500 __be32 loss_of_dword_sync; 2501 __be32 phy_reset_problem; 2502 }; 2503 2504 2505 /** 2506 * mpi3mr_get_expander_phy_error_log - return expander counters: 2507 * @mrioc: Adapter instance reference 2508 * @phy: The SAS transport layer phy object 2509 * 2510 * Return: 0 for success, non-zero for failure. 2511 * 2512 */ 2513 static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc, 2514 struct sas_phy *phy) 2515 { 2516 struct mpi3_smp_passthrough_request mpi_request; 2517 struct mpi3_smp_passthrough_reply mpi_reply; 2518 struct phy_error_log_request *phy_error_log_request; 2519 struct phy_error_log_reply *phy_error_log_reply; 2520 int rc; 2521 void *psge; 2522 void *data_out = NULL; 2523 dma_addr_t data_out_dma, data_in_dma; 2524 u32 data_out_sz, data_in_sz, sz; 2525 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST; 2526 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request); 2527 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply); 2528 u16 ioc_status; 2529 2530 if (mrioc->reset_in_progress) { 2531 ioc_err(mrioc, "%s: host reset in progress!\n", __func__); 2532 return -EFAULT; 2533 } 2534 2535 data_out_sz = sizeof(struct phy_error_log_request); 2536 data_in_sz = sizeof(struct phy_error_log_reply); 2537 sz = data_out_sz + data_in_sz; 2538 data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma, 2539 GFP_KERNEL); 2540 if (!data_out) { 2541 rc = -ENOMEM; 2542 goto out; 2543 } 2544 2545 data_in_dma = data_out_dma + data_out_sz; 2546 phy_error_log_reply = data_out + data_out_sz; 2547 2548 rc = -EINVAL; 2549 memset(data_out, 0, sz); 2550 phy_error_log_request = data_out; 2551 phy_error_log_request->smp_frame_type = 0x40; 2552 phy_error_log_request->function = 0x11; 2553 phy_error_log_request->request_length = 2; 2554 phy_error_log_request->allocated_response_length = 0; 2555 phy_error_log_request->phy_identifier = phy->number; 2556 2557 memset(&mpi_request, 0, request_sz); 2558 memset(&mpi_reply, 0, reply_sz); 2559 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS); 2560 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH; 2561 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy); 2562 mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address); 2563 2564 psge = &mpi_request.request_sge; 2565 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma); 2566 2567 psge = &mpi_request.response_sge; 2568 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma); 2569 2570 dprint_transport_info(mrioc, 2571 "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n", 2572 (unsigned long long)phy->identify.sas_address, phy->number); 2573 2574 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz, 2575 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) 2576 goto out; 2577 2578 dprint_transport_info(mrioc, 2579 "phy error log SMP request completed with ioc_status(0x%04x)\n", 2580 ioc_status); 2581 2582 if (ioc_status == MPI3_IOCSTATUS_SUCCESS) { 2583 dprint_transport_info(mrioc, 2584 "phy error log - reply data transfer size(%d)\n", 2585 le16_to_cpu(mpi_reply.response_data_length)); 2586 2587 if (le16_to_cpu(mpi_reply.response_data_length) != 2588 sizeof(struct phy_error_log_reply)) 2589 goto out; 2590 2591 dprint_transport_info(mrioc, 2592 "phy error log - function_result(%d)\n", 2593 phy_error_log_reply->function_result); 2594 2595 phy->invalid_dword_count = 2596 be32_to_cpu(phy_error_log_reply->invalid_dword); 2597 phy->running_disparity_error_count = 2598 be32_to_cpu(phy_error_log_reply->running_disparity_error); 2599 phy->loss_of_dword_sync_count = 2600 be32_to_cpu(phy_error_log_reply->loss_of_dword_sync); 2601 phy->phy_reset_problem_count = 2602 be32_to_cpu(phy_error_log_reply->phy_reset_problem); 2603 rc = 0; 2604 } 2605 2606 out: 2607 if (data_out) 2608 dma_free_coherent(&mrioc->pdev->dev, sz, data_out, 2609 data_out_dma); 2610 2611 return rc; 2612 } 2613 2614 /** 2615 * mpi3mr_transport_get_linkerrors - return phy error counters 2616 * @phy: The SAS transport layer phy object 2617 * 2618 * This function retrieves the phy error log information of the 2619 * HBA or expander for which the phy belongs to 2620 * 2621 * Return: 0 for success, non-zero for failure. 2622 */ 2623 static int mpi3mr_transport_get_linkerrors(struct sas_phy *phy) 2624 { 2625 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy); 2626 struct mpi3_sas_phy_page1 phy_pg1; 2627 int rc = 0; 2628 u16 ioc_status; 2629 2630 rc = mpi3mr_parent_present(mrioc, phy); 2631 if (rc) 2632 return rc; 2633 2634 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) 2635 return mpi3mr_get_expander_phy_error_log(mrioc, phy); 2636 2637 memset(&phy_pg1, 0, sizeof(struct mpi3_sas_phy_page1)); 2638 /* get hba phy error logs */ 2639 if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc, &ioc_status, &phy_pg1, 2640 sizeof(struct mpi3_sas_phy_page1), 2641 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number))) { 2642 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2643 __FILE__, __LINE__, __func__); 2644 return -ENXIO; 2645 } 2646 2647 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { 2648 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2649 __FILE__, __LINE__, __func__); 2650 return -ENXIO; 2651 } 2652 phy->invalid_dword_count = le32_to_cpu(phy_pg1.invalid_dword_count); 2653 phy->running_disparity_error_count = 2654 le32_to_cpu(phy_pg1.running_disparity_error_count); 2655 phy->loss_of_dword_sync_count = 2656 le32_to_cpu(phy_pg1.loss_dword_synch_count); 2657 phy->phy_reset_problem_count = 2658 le32_to_cpu(phy_pg1.phy_reset_problem_count); 2659 return 0; 2660 } 2661 2662 /** 2663 * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID 2664 * @rphy: The SAS transport layer remote phy object 2665 * @identifier: Enclosure identifier to be returned 2666 * 2667 * Returns the enclosure id for the device pointed by the remote 2668 * phy object. 2669 * 2670 * Return: 0 on success or -ENXIO 2671 */ 2672 static int 2673 mpi3mr_transport_get_enclosure_identifier(struct sas_rphy *rphy, 2674 u64 *identifier) 2675 { 2676 struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy); 2677 struct mpi3mr_tgt_dev *tgtdev = NULL; 2678 unsigned long flags; 2679 int rc; 2680 2681 spin_lock_irqsave(&mrioc->tgtdev_lock, flags); 2682 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc, 2683 rphy->identify.sas_address, rphy); 2684 if (tgtdev) { 2685 *identifier = 2686 tgtdev->enclosure_logical_id; 2687 rc = 0; 2688 mpi3mr_tgtdev_put(tgtdev); 2689 } else { 2690 *identifier = 0; 2691 rc = -ENXIO; 2692 } 2693 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); 2694 2695 return rc; 2696 } 2697 2698 /** 2699 * mpi3mr_transport_get_bay_identifier - Get bay ID 2700 * @rphy: The SAS transport layer remote phy object 2701 * 2702 * Returns the slot id for the device pointed by the remote phy 2703 * object. 2704 * 2705 * Return: Valid slot ID on success or -ENXIO 2706 */ 2707 static int 2708 mpi3mr_transport_get_bay_identifier(struct sas_rphy *rphy) 2709 { 2710 struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy); 2711 struct mpi3mr_tgt_dev *tgtdev = NULL; 2712 unsigned long flags; 2713 int rc; 2714 2715 spin_lock_irqsave(&mrioc->tgtdev_lock, flags); 2716 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc, 2717 rphy->identify.sas_address, rphy); 2718 if (tgtdev) { 2719 rc = tgtdev->slot; 2720 mpi3mr_tgtdev_put(tgtdev); 2721 } else 2722 rc = -ENXIO; 2723 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); 2724 2725 return rc; 2726 } 2727 2728 /* phy control request structure */ 2729 struct phy_control_request { 2730 u8 smp_frame_type; /* 0x40 */ 2731 u8 function; /* 0x91 */ 2732 u8 allocated_response_length; 2733 u8 request_length; /* 0x09 */ 2734 u16 expander_change_count; 2735 u8 reserved_1[3]; 2736 u8 phy_identifier; 2737 u8 phy_operation; 2738 u8 reserved_2[13]; 2739 u64 attached_device_name; 2740 u8 programmed_min_physical_link_rate; 2741 u8 programmed_max_physical_link_rate; 2742 u8 reserved_3[6]; 2743 }; 2744 2745 /* phy control reply structure */ 2746 struct phy_control_reply { 2747 u8 smp_frame_type; /* 0x41 */ 2748 u8 function; /* 0x11 */ 2749 u8 function_result; 2750 u8 response_length; 2751 }; 2752 2753 #define SMP_PHY_CONTROL_LINK_RESET (0x01) 2754 #define SMP_PHY_CONTROL_HARD_RESET (0x02) 2755 #define SMP_PHY_CONTROL_DISABLE (0x03) 2756 2757 /** 2758 * mpi3mr_expander_phy_control - expander phy control 2759 * @mrioc: Adapter instance reference 2760 * @phy: The SAS transport layer phy object 2761 * @phy_operation: The phy operation to be executed 2762 * 2763 * Issues SMP passthru phy control request to execute a specific 2764 * phy operation for a given expander device. 2765 * 2766 * Return: 0 for success, non-zero for failure. 2767 */ 2768 static int 2769 mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc, 2770 struct sas_phy *phy, u8 phy_operation) 2771 { 2772 struct mpi3_smp_passthrough_request mpi_request; 2773 struct mpi3_smp_passthrough_reply mpi_reply; 2774 struct phy_control_request *phy_control_request; 2775 struct phy_control_reply *phy_control_reply; 2776 int rc; 2777 void *psge; 2778 void *data_out = NULL; 2779 dma_addr_t data_out_dma; 2780 dma_addr_t data_in_dma; 2781 size_t data_in_sz; 2782 size_t data_out_sz; 2783 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST; 2784 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request); 2785 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply); 2786 u16 ioc_status; 2787 u16 sz; 2788 2789 if (mrioc->reset_in_progress) { 2790 ioc_err(mrioc, "%s: host reset in progress!\n", __func__); 2791 return -EFAULT; 2792 } 2793 2794 data_out_sz = sizeof(struct phy_control_request); 2795 data_in_sz = sizeof(struct phy_control_reply); 2796 sz = data_out_sz + data_in_sz; 2797 data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma, 2798 GFP_KERNEL); 2799 if (!data_out) { 2800 rc = -ENOMEM; 2801 goto out; 2802 } 2803 2804 data_in_dma = data_out_dma + data_out_sz; 2805 phy_control_reply = data_out + data_out_sz; 2806 2807 rc = -EINVAL; 2808 memset(data_out, 0, sz); 2809 2810 phy_control_request = data_out; 2811 phy_control_request->smp_frame_type = 0x40; 2812 phy_control_request->function = 0x91; 2813 phy_control_request->request_length = 9; 2814 phy_control_request->allocated_response_length = 0; 2815 phy_control_request->phy_identifier = phy->number; 2816 phy_control_request->phy_operation = phy_operation; 2817 phy_control_request->programmed_min_physical_link_rate = 2818 phy->minimum_linkrate << 4; 2819 phy_control_request->programmed_max_physical_link_rate = 2820 phy->maximum_linkrate << 4; 2821 2822 memset(&mpi_request, 0, request_sz); 2823 memset(&mpi_reply, 0, reply_sz); 2824 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS); 2825 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH; 2826 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy); 2827 mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address); 2828 2829 psge = &mpi_request.request_sge; 2830 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma); 2831 2832 psge = &mpi_request.response_sge; 2833 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma); 2834 2835 dprint_transport_info(mrioc, 2836 "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n", 2837 (unsigned long long)phy->identify.sas_address, phy->number, 2838 phy_operation); 2839 2840 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz, 2841 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) 2842 goto out; 2843 2844 dprint_transport_info(mrioc, 2845 "phy control SMP request completed with ioc_status(0x%04x)\n", 2846 ioc_status); 2847 2848 if (ioc_status == MPI3_IOCSTATUS_SUCCESS) { 2849 dprint_transport_info(mrioc, 2850 "phy control - reply data transfer size(%d)\n", 2851 le16_to_cpu(mpi_reply.response_data_length)); 2852 2853 if (le16_to_cpu(mpi_reply.response_data_length) != 2854 sizeof(struct phy_control_reply)) 2855 goto out; 2856 dprint_transport_info(mrioc, 2857 "phy control - function_result(%d)\n", 2858 phy_control_reply->function_result); 2859 rc = 0; 2860 } 2861 out: 2862 if (data_out) 2863 dma_free_coherent(&mrioc->pdev->dev, sz, data_out, 2864 data_out_dma); 2865 2866 return rc; 2867 } 2868 2869 /** 2870 * mpi3mr_transport_phy_reset - Reset a given phy 2871 * @phy: The SAS transport layer phy object 2872 * @hard_reset: Flag to indicate the type of reset 2873 * 2874 * Return: 0 for success, non-zero for failure. 2875 */ 2876 static int 2877 mpi3mr_transport_phy_reset(struct sas_phy *phy, int hard_reset) 2878 { 2879 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy); 2880 struct mpi3_iounit_control_request mpi_request; 2881 struct mpi3_iounit_control_reply mpi_reply; 2882 u16 request_sz = sizeof(struct mpi3_iounit_control_request); 2883 u16 reply_sz = sizeof(struct mpi3_iounit_control_reply); 2884 int rc = 0; 2885 u16 ioc_status; 2886 2887 rc = mpi3mr_parent_present(mrioc, phy); 2888 if (rc) 2889 return rc; 2890 2891 /* handle expander phys */ 2892 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) 2893 return mpi3mr_expander_phy_control(mrioc, phy, 2894 (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET : 2895 SMP_PHY_CONTROL_LINK_RESET); 2896 2897 /* handle hba phys */ 2898 memset(&mpi_request, 0, request_sz); 2899 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS); 2900 mpi_request.function = MPI3_FUNCTION_IO_UNIT_CONTROL; 2901 mpi_request.operation = MPI3_CTRL_OP_SAS_PHY_CONTROL; 2902 mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX] = 2903 (hard_reset ? MPI3_CTRL_ACTION_HARD_RESET : 2904 MPI3_CTRL_ACTION_LINK_RESET); 2905 mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX] = 2906 phy->number; 2907 2908 dprint_transport_info(mrioc, 2909 "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n", 2910 (unsigned long long)phy->identify.sas_address, phy->number, 2911 hard_reset); 2912 2913 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz, 2914 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) { 2915 rc = -EAGAIN; 2916 goto out; 2917 } 2918 2919 dprint_transport_info(mrioc, 2920 "phy reset request completed with ioc_status(0x%04x)\n", 2921 ioc_status); 2922 out: 2923 return rc; 2924 } 2925 2926 /** 2927 * mpi3mr_transport_phy_enable - enable/disable phys 2928 * @phy: The SAS transport layer phy object 2929 * @enable: flag to enable/disable, enable phy when true 2930 * 2931 * This function enables/disables a given by executing required 2932 * configuration page changes or expander phy control command 2933 * 2934 * Return: 0 for success, non-zero for failure. 2935 */ 2936 static int 2937 mpi3mr_transport_phy_enable(struct sas_phy *phy, int enable) 2938 { 2939 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy); 2940 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; 2941 struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL; 2942 u16 sz; 2943 int rc = 0; 2944 int i, discovery_active; 2945 2946 rc = mpi3mr_parent_present(mrioc, phy); 2947 if (rc) 2948 return rc; 2949 2950 /* handle expander phys */ 2951 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) 2952 return mpi3mr_expander_phy_control(mrioc, phy, 2953 (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET : 2954 SMP_PHY_CONTROL_DISABLE); 2955 2956 /* handle hba phys */ 2957 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) + 2958 (mrioc->sas_hba.num_phys * 2959 sizeof(struct mpi3_sas_io_unit0_phy_data)); 2960 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); 2961 if (!sas_io_unit_pg0) { 2962 rc = -ENOMEM; 2963 goto out; 2964 } 2965 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { 2966 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2967 __FILE__, __LINE__, __func__); 2968 rc = -ENXIO; 2969 goto out; 2970 } 2971 2972 /* unable to enable/disable phys when discovery is active */ 2973 for (i = 0, discovery_active = 0; i < mrioc->sas_hba.num_phys ; i++) { 2974 if (sas_io_unit_pg0->phy_data[i].port_flags & 2975 MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS) { 2976 ioc_err(mrioc, 2977 "discovery is active on port = %d, phy = %d\n" 2978 "\tunable to enable/disable phys, try again later!\n", 2979 sas_io_unit_pg0->phy_data[i].io_unit_port, i); 2980 discovery_active = 1; 2981 } 2982 } 2983 2984 if (discovery_active) { 2985 rc = -EAGAIN; 2986 goto out; 2987 } 2988 2989 if ((sas_io_unit_pg0->phy_data[phy->number].phy_flags & 2990 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY | 2991 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))) { 2992 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 2993 __FILE__, __LINE__, __func__); 2994 rc = -ENXIO; 2995 goto out; 2996 } 2997 2998 /* read sas_iounit page 1 */ 2999 sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) + 3000 (mrioc->sas_hba.num_phys * 3001 sizeof(struct mpi3_sas_io_unit1_phy_data)); 3002 sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL); 3003 if (!sas_io_unit_pg1) { 3004 rc = -ENOMEM; 3005 goto out; 3006 } 3007 3008 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) { 3009 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 3010 __FILE__, __LINE__, __func__); 3011 rc = -ENXIO; 3012 goto out; 3013 } 3014 3015 if (enable) 3016 sas_io_unit_pg1->phy_data[phy->number].phy_flags 3017 &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; 3018 else 3019 sas_io_unit_pg1->phy_data[phy->number].phy_flags 3020 |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; 3021 3022 mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz); 3023 3024 /* link reset */ 3025 if (enable) 3026 mpi3mr_transport_phy_reset(phy, 0); 3027 3028 out: 3029 kfree(sas_io_unit_pg1); 3030 kfree(sas_io_unit_pg0); 3031 return rc; 3032 } 3033 3034 /** 3035 * mpi3mr_transport_phy_speed - set phy min/max speed 3036 * @phy: The SAS transport later phy object 3037 * @rates: Rates defined as in sas_phy_linkrates 3038 * 3039 * This function sets the link rates given in the rates 3040 * argument to the given phy by executing required configuration 3041 * page changes or expander phy control command 3042 * 3043 * Return: 0 for success, non-zero for failure. 3044 */ 3045 static int 3046 mpi3mr_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) 3047 { 3048 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy); 3049 struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL; 3050 struct mpi3_sas_phy_page0 phy_pg0; 3051 u16 sz, ioc_status; 3052 int rc = 0; 3053 3054 rc = mpi3mr_parent_present(mrioc, phy); 3055 if (rc) 3056 return rc; 3057 3058 if (!rates->minimum_linkrate) 3059 rates->minimum_linkrate = phy->minimum_linkrate; 3060 else if (rates->minimum_linkrate < phy->minimum_linkrate_hw) 3061 rates->minimum_linkrate = phy->minimum_linkrate_hw; 3062 3063 if (!rates->maximum_linkrate) 3064 rates->maximum_linkrate = phy->maximum_linkrate; 3065 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw) 3066 rates->maximum_linkrate = phy->maximum_linkrate_hw; 3067 3068 /* handle expander phys */ 3069 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) { 3070 phy->minimum_linkrate = rates->minimum_linkrate; 3071 phy->maximum_linkrate = rates->maximum_linkrate; 3072 return mpi3mr_expander_phy_control(mrioc, phy, 3073 SMP_PHY_CONTROL_LINK_RESET); 3074 } 3075 3076 /* handle hba phys */ 3077 sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) + 3078 (mrioc->sas_hba.num_phys * 3079 sizeof(struct mpi3_sas_io_unit1_phy_data)); 3080 sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL); 3081 if (!sas_io_unit_pg1) { 3082 rc = -ENOMEM; 3083 goto out; 3084 } 3085 3086 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) { 3087 ioc_err(mrioc, "failure at %s:%d/%s()!\n", 3088 __FILE__, __LINE__, __func__); 3089 rc = -ENXIO; 3090 goto out; 3091 } 3092 3093 sas_io_unit_pg1->phy_data[phy->number].max_min_link_rate = 3094 (rates->minimum_linkrate + (rates->maximum_linkrate << 4)); 3095 3096 if (mpi3mr_cfg_set_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 /* link reset */ 3104 mpi3mr_transport_phy_reset(phy, 0); 3105 3106 /* read phy page 0, then update the rates in the sas transport phy */ 3107 if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0, 3108 sizeof(struct mpi3_sas_phy_page0), 3109 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number) && 3110 (ioc_status == MPI3_IOCSTATUS_SUCCESS)) { 3111 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate( 3112 phy_pg0.programmed_link_rate & 3113 MPI3_SAS_PRATE_MIN_RATE_MASK); 3114 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate( 3115 phy_pg0.programmed_link_rate >> 4); 3116 phy->negotiated_linkrate = 3117 mpi3mr_convert_phy_link_rate( 3118 (phy_pg0.negotiated_link_rate & 3119 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) 3120 >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT); 3121 } 3122 3123 out: 3124 kfree(sas_io_unit_pg1); 3125 return rc; 3126 } 3127 3128 /** 3129 * mpi3mr_map_smp_buffer - map BSG dma buffer 3130 * @dev: Generic device reference 3131 * @buf: BSG buffer pointer 3132 * @dma_addr: Physical address holder 3133 * @dma_len: Mapped DMA buffer length. 3134 * @p: Virtual address holder 3135 * 3136 * This function maps the DMAable buffer 3137 * 3138 * Return: 0 on success, non-zero on failure 3139 */ 3140 static int 3141 mpi3mr_map_smp_buffer(struct device *dev, struct bsg_buffer *buf, 3142 dma_addr_t *dma_addr, size_t *dma_len, void **p) 3143 { 3144 /* Check if the request is split across multiple segments */ 3145 if (buf->sg_cnt > 1) { 3146 *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr, 3147 GFP_KERNEL); 3148 if (!*p) 3149 return -ENOMEM; 3150 *dma_len = buf->payload_len; 3151 } else { 3152 if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL)) 3153 return -ENOMEM; 3154 *dma_addr = sg_dma_address(buf->sg_list); 3155 *dma_len = sg_dma_len(buf->sg_list); 3156 *p = NULL; 3157 } 3158 3159 return 0; 3160 } 3161 3162 /** 3163 * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer 3164 * @dev: Generic device reference 3165 * @buf: BSG buffer pointer 3166 * @dma_addr: Physical address to be unmapped 3167 * @p: Virtual address 3168 * 3169 * This function unmaps the DMAable buffer 3170 */ 3171 static void 3172 mpi3mr_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf, 3173 dma_addr_t dma_addr, void *p) 3174 { 3175 if (p) 3176 dma_free_coherent(dev, buf->payload_len, p, dma_addr); 3177 else 3178 dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL); 3179 } 3180 3181 /** 3182 * mpi3mr_transport_smp_handler - handler for smp passthru 3183 * @job: BSG job reference 3184 * @shost: SCSI host object reference 3185 * @rphy: SAS transport rphy object pointing the expander 3186 * 3187 * This is used primarily by smp utils for sending the SMP 3188 * commands to the expanders attached to the controller 3189 */ 3190 static void 3191 mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost, 3192 struct sas_rphy *rphy) 3193 { 3194 struct mpi3mr_ioc *mrioc = shost_priv(shost); 3195 struct mpi3_smp_passthrough_request mpi_request; 3196 struct mpi3_smp_passthrough_reply mpi_reply; 3197 int rc; 3198 void *psge; 3199 dma_addr_t dma_addr_in; 3200 dma_addr_t dma_addr_out; 3201 void *addr_in = NULL; 3202 void *addr_out = NULL; 3203 size_t dma_len_in; 3204 size_t dma_len_out; 3205 unsigned int reslen = 0; 3206 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request); 3207 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply); 3208 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST; 3209 u16 ioc_status; 3210 3211 if (mrioc->reset_in_progress) { 3212 ioc_err(mrioc, "%s: host reset in progress!\n", __func__); 3213 rc = -EFAULT; 3214 goto out; 3215 } 3216 3217 rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload, 3218 &dma_addr_out, &dma_len_out, &addr_out); 3219 if (rc) 3220 goto out; 3221 3222 if (addr_out) 3223 sg_copy_to_buffer(job->request_payload.sg_list, 3224 job->request_payload.sg_cnt, addr_out, 3225 job->request_payload.payload_len); 3226 3227 rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->reply_payload, 3228 &dma_addr_in, &dma_len_in, &addr_in); 3229 if (rc) 3230 goto unmap_out; 3231 3232 memset(&mpi_request, 0, request_sz); 3233 memset(&mpi_reply, 0, reply_sz); 3234 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS); 3235 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH; 3236 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_rphy(mrioc, rphy); 3237 mpi_request.sas_address = ((rphy) ? 3238 cpu_to_le64(rphy->identify.sas_address) : 3239 cpu_to_le64(mrioc->sas_hba.sas_address)); 3240 psge = &mpi_request.request_sge; 3241 mpi3mr_add_sg_single(psge, sgl_flags, dma_len_out - 4, dma_addr_out); 3242 3243 psge = &mpi_request.response_sge; 3244 mpi3mr_add_sg_single(psge, sgl_flags, dma_len_in - 4, dma_addr_in); 3245 3246 dprint_transport_info(mrioc, "sending SMP request\n"); 3247 3248 rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz, 3249 &mpi_reply, reply_sz, 3250 MPI3MR_INTADMCMD_TIMEOUT, &ioc_status); 3251 if (rc) 3252 goto unmap_in; 3253 3254 dprint_transport_info(mrioc, 3255 "SMP request completed with ioc_status(0x%04x)\n", ioc_status); 3256 3257 dprint_transport_info(mrioc, 3258 "SMP request - reply data transfer size(%d)\n", 3259 le16_to_cpu(mpi_reply.response_data_length)); 3260 3261 memcpy(job->reply, &mpi_reply, reply_sz); 3262 job->reply_len = reply_sz; 3263 reslen = le16_to_cpu(mpi_reply.response_data_length); 3264 3265 if (addr_in) 3266 sg_copy_from_buffer(job->reply_payload.sg_list, 3267 job->reply_payload.sg_cnt, addr_in, 3268 job->reply_payload.payload_len); 3269 3270 rc = 0; 3271 unmap_in: 3272 mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->reply_payload, 3273 dma_addr_in, addr_in); 3274 unmap_out: 3275 mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->request_payload, 3276 dma_addr_out, addr_out); 3277 out: 3278 bsg_job_done(job, rc, reslen); 3279 } 3280 3281 struct sas_function_template mpi3mr_transport_functions = { 3282 .get_linkerrors = mpi3mr_transport_get_linkerrors, 3283 .get_enclosure_identifier = mpi3mr_transport_get_enclosure_identifier, 3284 .get_bay_identifier = mpi3mr_transport_get_bay_identifier, 3285 .phy_reset = mpi3mr_transport_phy_reset, 3286 .phy_enable = mpi3mr_transport_phy_enable, 3287 .set_phy_speed = mpi3mr_transport_phy_speed, 3288 .smp_handler = mpi3mr_transport_smp_handler, 3289 }; 3290 3291 struct scsi_transport_template *mpi3mr_transport_template; 3292