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