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