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