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