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