1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2026 LeapIO Tech Inc. 4 * 5 * LeapRAID storage and RAID controller driver. 6 */ 7 #include <scsi/scsi_host.h> 8 9 #include "leapraid_func.h" 10 11 static struct leapraid_topo_node *leapraid_transport_topo_node_by_sas_addr( 12 struct leapraid_adapter *adapter, 13 u64 sas_addr, 14 struct leapraid_card_port *card_port) 15 { 16 if (adapter->dev_topo.card.sas_address == sas_addr) 17 return &adapter->dev_topo.card; 18 19 return leapraid_exp_find_by_sas_address(adapter, sas_addr, card_port); 20 } 21 22 static u8 leapraid_get_port_id_by_expander(struct leapraid_adapter *adapter, 23 struct sas_rphy *rphy) 24 { 25 struct leapraid_topo_node *topo_node_exp; 26 unsigned long flags; 27 u8 port_id = 0xFF; 28 29 spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); 30 list_for_each_entry(topo_node_exp, &adapter->dev_topo.exp_list, list) { 31 if (topo_node_exp->rphy == rphy) { 32 port_id = topo_node_exp->card_port->port_id; 33 break; 34 } 35 } 36 spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); 37 38 return port_id; 39 } 40 41 static u8 leapraid_get_port_id_by_end_dev(struct leapraid_adapter *adapter, 42 struct sas_rphy *rphy) 43 { 44 struct leapraid_sas_dev *sas_dev; 45 unsigned long flags; 46 u8 port_id = 0xFF; 47 48 spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); 49 sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy( 50 adapter, 51 rphy->identify.sas_address, 52 rphy); 53 if (sas_dev) { 54 port_id = sas_dev->card_port->port_id; 55 leapraid_sdev_put(sas_dev); 56 } 57 spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); 58 59 return port_id; 60 } 61 62 static u8 leapraid_transport_get_port_id_by_rphy( 63 struct leapraid_adapter *adapter, 64 struct sas_rphy *rphy) 65 { 66 if (!rphy) 67 return 0xFF; 68 69 switch (rphy->identify.device_type) { 70 case SAS_EDGE_EXPANDER_DEVICE: 71 case SAS_FANOUT_EXPANDER_DEVICE: 72 return leapraid_get_port_id_by_expander(adapter, rphy); 73 case SAS_END_DEVICE: 74 return leapraid_get_port_id_by_end_dev(adapter, rphy); 75 default: 76 return 0xFF; 77 } 78 } 79 80 static enum sas_linkrate leapraid_transport_convert_phy_link_rate(u8 link_rate) 81 { 82 unsigned int i; 83 84 #define SAS_RATE_12G SAS_LINK_RATE_12_0_GBPS 85 86 const struct linkrate_map { 87 u8 in; 88 enum sas_linkrate out; 89 } linkrate_table[] = { 90 { 91 LEAPRAID_SAS_NEG_LINK_RATE_1_5, 92 SAS_LINK_RATE_1_5_GBPS 93 }, 94 { 95 LEAPRAID_SAS_NEG_LINK_RATE_3_0, 96 SAS_LINK_RATE_3_0_GBPS 97 }, 98 { 99 LEAPRAID_SAS_NEG_LINK_RATE_6_0, 100 SAS_LINK_RATE_6_0_GBPS 101 }, 102 { 103 LEAPRAID_SAS_NEG_LINK_RATE_12_0, 104 SAS_RATE_12G 105 }, 106 { 107 LEAPRAID_SAS_NEG_LINK_RATE_PHY_DISABLED, 108 SAS_PHY_DISABLED 109 }, 110 { 111 LEAPRAID_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED, 112 SAS_LINK_RATE_FAILED 113 }, 114 { 115 LEAPRAID_SAS_NEG_LINK_RATE_PORT_SELECTOR, 116 SAS_SATA_PORT_SELECTOR 117 }, 118 { 119 LEAPRAID_SAS_NEG_LINK_RATE_SMP_RESETTING, 120 SAS_LINK_RATE_UNKNOWN 121 }, 122 { 123 LEAPRAID_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE, 124 SAS_LINK_RATE_UNKNOWN 125 }, 126 { 127 LEAPRAID_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE, 128 SAS_LINK_RATE_UNKNOWN 129 }, 130 }; 131 132 for (i = 0; i < ARRAY_SIZE(linkrate_table); i++) 133 if (linkrate_table[i].in == link_rate) 134 return linkrate_table[i].out; 135 136 return SAS_LINK_RATE_UNKNOWN; 137 } 138 139 static void leapraid_set_identify_protocol_flags(u32 dev_info, 140 struct sas_identify *identify) 141 { 142 unsigned int i; 143 144 const struct protocol_mapping { 145 u32 mask; 146 u32 *target; 147 u32 protocol; 148 } mappings[] = { 149 { 150 LEAPRAID_DEVTYP_SSP_INIT, 151 &identify->initiator_port_protocols, 152 SAS_PROTOCOL_SSP 153 }, 154 { 155 LEAPRAID_DEVTYP_STP_INIT, 156 &identify->initiator_port_protocols, 157 SAS_PROTOCOL_STP 158 }, 159 { 160 LEAPRAID_DEVTYP_SMP_INIT, 161 &identify->initiator_port_protocols, 162 SAS_PROTOCOL_SMP 163 }, 164 { 165 LEAPRAID_DEVTYP_SATA_HOST, 166 &identify->initiator_port_protocols, 167 SAS_PROTOCOL_SATA 168 }, 169 { 170 LEAPRAID_DEVTYP_SSP_TGT, 171 &identify->target_port_protocols, 172 SAS_PROTOCOL_SSP 173 }, 174 { 175 LEAPRAID_DEVTYP_STP_TGT, 176 &identify->target_port_protocols, 177 SAS_PROTOCOL_STP 178 }, 179 { 180 LEAPRAID_DEVTYP_SMP_TGT, 181 &identify->target_port_protocols, 182 SAS_PROTOCOL_SMP 183 }, 184 { 185 LEAPRAID_DEVTYP_SATA_DEV, 186 &identify->target_port_protocols, 187 SAS_PROTOCOL_SATA 188 }, 189 }; 190 191 for (i = 0; i < ARRAY_SIZE(mappings); i++) 192 if (dev_info & mappings[i].mask && mappings[i].target) 193 *mappings[i].target |= mappings[i].protocol; 194 } 195 196 static int leapraid_transport_set_identify(struct leapraid_adapter *adapter, 197 u16 hdl, 198 struct sas_identify *identify) 199 { 200 union cfg_param_1 cfgp1 = {0}; 201 union cfg_param_2 cfgp2 = {0}; 202 struct leapraid_sas_dev_p0 sas_dev_pg0; 203 u32 dev_info; 204 205 if ((adapter->access_ctrl.shost_recovering && 206 !adapter->scan_dev_desc.driver_loading) || 207 adapter->access_ctrl.pcie_recovering) { 208 dev_warn(&adapter->pdev->dev, 209 "%s: Failed, shost_recovering=%d pcie_recovering=%d\n", 210 __func__, 211 adapter->access_ctrl.shost_recovering, 212 adapter->access_ctrl.pcie_recovering); 213 return -EFAULT; 214 } 215 216 cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL; 217 cfgp2.handle = hdl; 218 if (leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1, 219 cfgp2, GET_SAS_DEVICE_PG0)) 220 return -ENXIO; 221 222 memset(identify, 0, sizeof(struct sas_identify)); 223 dev_info = le32_to_cpu(sas_dev_pg0.dev_info); 224 identify->sas_address = le64_to_cpu(sas_dev_pg0.sas_address); 225 identify->phy_identifier = sas_dev_pg0.phy_num; 226 227 switch (dev_info & LEAPRAID_DEVTYP_MASK_DEV_TYPE) { 228 case LEAPRAID_DEVTYP_NO_DEV: 229 identify->device_type = SAS_PHY_UNUSED; 230 break; 231 case LEAPRAID_DEVTYP_END_DEV: 232 identify->device_type = SAS_END_DEVICE; 233 break; 234 case LEAPRAID_DEVTYP_EDGE_EXPANDER: 235 identify->device_type = SAS_EDGE_EXPANDER_DEVICE; 236 break; 237 case LEAPRAID_DEVTYP_FANOUT_EXPANDER: 238 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE; 239 break; 240 } 241 242 leapraid_set_identify_protocol_flags(dev_info, identify); 243 244 return 0; 245 } 246 247 static void leapraid_transport_exp_set_edev(struct leapraid_adapter *adapter, 248 void *data_out, 249 struct sas_expander_device *edev) 250 { 251 struct leapraid_smp_passthrough_rep *smp_passthrough_rep; 252 struct leapraid_rep_manu_reply *rep_manu_reply; 253 u8 *component_id; 254 255 smp_passthrough_rep = 256 (void *)&adapter->driver_cmds.transport_cmd.reply; 257 if (le16_to_cpu(smp_passthrough_rep->resp_data_len) != 258 sizeof(struct leapraid_rep_manu_reply)) 259 return; 260 261 rep_manu_reply = data_out + sizeof(struct leapraid_rep_manu_request); 262 263 memcpy(edev->vendor_id, rep_manu_reply->vendor_identification, 264 SAS_EXPANDER_VENDOR_ID_LEN); 265 edev->vendor_id[SAS_EXPANDER_VENDOR_ID_LEN] = '\0'; 266 267 memcpy(edev->product_id, rep_manu_reply->product_identification, 268 SAS_EXPANDER_PRODUCT_ID_LEN); 269 edev->product_id[SAS_EXPANDER_PRODUCT_ID_LEN] = '\0'; 270 271 memcpy(edev->product_rev, rep_manu_reply->product_revision_level, 272 SAS_EXPANDER_PRODUCT_REV_LEN); 273 edev->product_rev[SAS_EXPANDER_PRODUCT_REV_LEN] = '\0'; 274 275 edev->level = rep_manu_reply->sas_format & 1; 276 if (edev->level) { 277 memcpy(edev->component_vendor_id, 278 rep_manu_reply->comp_vendor_identification, 279 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN); 280 edev->component_vendor_id[ 281 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN] = '\0'; 282 283 component_id = (u8 *)&rep_manu_reply->component_id; 284 edev->component_id = component_id[0] << 8 | component_id[1]; 285 edev->component_revision_id = 286 rep_manu_reply->component_revision_level; 287 } 288 } 289 290 static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter, 291 u64 sas_address, 292 struct sas_expander_device *edev, 293 u8 port_id) 294 { 295 struct leapraid_smp_passthrough_req *smp_passthrough_req; 296 struct leapraid_rep_manu_request *rep_manu_request; 297 dma_addr_t h2c_dma_addr; 298 dma_addr_t c2h_dma_addr; 299 bool issue_reset = false; 300 void *data_out = NULL; 301 u16 inter_taskid; 302 size_t c2h_size; 303 size_t h2c_size; 304 void *psge; 305 int rc; 306 307 if (adapter->access_ctrl.shost_recovering || 308 adapter->access_ctrl.pcie_recovering) { 309 dev_warn(&adapter->pdev->dev, 310 "%s: Failed, shost_recovering=%d pcie_recovering=%d\n", 311 __func__, 312 adapter->access_ctrl.shost_recovering, 313 adapter->access_ctrl.pcie_recovering); 314 return -EFAULT; 315 } 316 317 mutex_lock(&adapter->driver_cmds.transport_cmd.mutex); 318 adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_PENDING; 319 rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, 320 __func__); 321 if (rc) 322 goto out_cleanup; 323 324 h2c_size = sizeof(struct leapraid_rep_manu_request); 325 c2h_size = sizeof(struct leapraid_rep_manu_reply); 326 data_out = dma_alloc_coherent(&adapter->pdev->dev, 327 h2c_size + c2h_size, 328 &h2c_dma_addr, 329 GFP_ATOMIC); 330 if (!data_out) { 331 rc = -ENOMEM; 332 goto out_cleanup; 333 } 334 335 rep_manu_request = data_out; 336 rep_manu_request->smp_frame_type = 337 SMP_REPORT_MANUFACTURER_INFORMATION_FRAME_TYPE; 338 rep_manu_request->function = SMP_REPORT_MANUFACTURER_INFORMATION_FUNC; 339 rep_manu_request->allocated_response_length = 0; 340 rep_manu_request->request_length = 0; 341 342 inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid; 343 smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid); 344 memset(smp_passthrough_req, 0, 345 sizeof(struct leapraid_smp_passthrough_req)); 346 smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH; 347 smp_passthrough_req->physical_port = port_id; 348 smp_passthrough_req->sas_address = cpu_to_le64(sas_address); 349 smp_passthrough_req->req_data_len = cpu_to_le16(h2c_size); 350 psge = &smp_passthrough_req->sgl; 351 c2h_dma_addr = h2c_dma_addr + sizeof(struct leapraid_rep_manu_request); 352 leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size, 353 c2h_dma_addr, c2h_size); 354 355 init_completion(&adapter->driver_cmds.transport_cmd.done); 356 leapraid_fire_task(adapter, inter_taskid); 357 wait_for_completion_timeout(&adapter->driver_cmds.transport_cmd.done, 358 LEAPRAID_TRANSPORT_CMD_TIMEOUT * HZ); 359 if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_DONE)) { 360 rc = -ETIMEDOUT; 361 dev_err(&adapter->pdev->dev, 362 "%s: SMP passthrough timeout, st=0x%x\n", 363 __func__, adapter->driver_cmds.transport_cmd.status); 364 leapraid_log_req_context(adapter, inter_taskid, 365 smp_passthrough_req); 366 if (!(adapter->driver_cmds.transport_cmd.status & 367 LEAPRAID_CMD_RESET)) 368 issue_reset = true; 369 370 goto hard_reset; 371 } 372 373 if (adapter->driver_cmds.transport_cmd.status & 374 LEAPRAID_CMD_REPLY_VALID) 375 leapraid_transport_exp_set_edev(adapter, data_out, edev); 376 377 hard_reset: 378 if (issue_reset) { 379 dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", 380 __func__, __LINE__); 381 rc = leapraid_hard_reset_handler(adapter, FULL_RESET); 382 } 383 out_cleanup: 384 adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_NOT_USED; 385 if (data_out) 386 dma_free_coherent(&adapter->pdev->dev, h2c_size + c2h_size, 387 data_out, h2c_dma_addr); 388 389 mutex_unlock(&adapter->driver_cmds.transport_cmd.mutex); 390 return rc; 391 } 392 393 static void leapraid_transport_del_port(struct leapraid_adapter *adapter, 394 struct leapraid_sas_port *sas_port) 395 { 396 dev_info(&sas_port->port->dev, 397 "Remove port: SAS addr=0x%016llx\n", 398 (unsigned long long)sas_port->remote_identify.sas_address); 399 switch (sas_port->remote_identify.device_type) { 400 case SAS_END_DEVICE: 401 leapraid_sas_dev_remove_by_sas_address( 402 adapter, 403 sas_port->remote_identify.sas_address, 404 sas_port->card_port); 405 break; 406 case SAS_EDGE_EXPANDER_DEVICE: 407 case SAS_FANOUT_EXPANDER_DEVICE: 408 leapraid_exp_rm(adapter, sas_port->remote_identify.sas_address, 409 sas_port->card_port); 410 break; 411 default: 412 break; 413 } 414 } 415 416 static void leapraid_transport_del_phy(struct leapraid_adapter *adapter, 417 struct leapraid_sas_port *sas_port, 418 struct leapraid_card_phy *card_phy) 419 { 420 dev_info(&card_phy->phy->dev, 421 "Remove PHY: SAS addr=0x%016llx, phy=%d\n", 422 (unsigned long long)sas_port->remote_identify.sas_address, 423 card_phy->phy_id); 424 list_del(&card_phy->port_siblings); 425 sas_port->phys_num--; 426 sas_port_delete_phy(sas_port->port, card_phy->phy); 427 card_phy->phy_is_assigned = 0; 428 } 429 430 static void leapraid_transport_add_phy(struct leapraid_adapter *adapter, 431 struct leapraid_sas_port *sas_port, 432 struct leapraid_card_phy *card_phy) 433 { 434 dev_info(&card_phy->phy->dev, 435 "Add PHY: SAS addr=0x%016llx, phy=%d\n", 436 (unsigned long long)sas_port->remote_identify.sas_address, 437 card_phy->phy_id); 438 list_add_tail(&card_phy->port_siblings, &sas_port->phy_list); 439 sas_port->phys_num++; 440 sas_port_add_phy(sas_port->port, card_phy->phy); 441 card_phy->phy_is_assigned = 1; 442 } 443 444 void leapraid_transport_attach_phy_to_port( 445 struct leapraid_adapter *adapter, 446 struct leapraid_topo_node *topo_node, 447 struct leapraid_card_phy *card_phy, 448 u64 sas_address, 449 struct leapraid_card_port *card_port) 450 { 451 struct leapraid_sas_port *sas_port; 452 struct leapraid_card_phy *card_phy_srch; 453 454 if (card_phy->phy_is_assigned) 455 return; 456 457 if (!card_port) 458 return; 459 460 list_for_each_entry(sas_port, &topo_node->sas_port_list, port_list) { 461 if (sas_port->remote_identify.sas_address != sas_address) 462 continue; 463 464 if (sas_port->card_port != card_port) 465 continue; 466 467 list_for_each_entry(card_phy_srch, &sas_port->phy_list, 468 port_siblings) { 469 if (card_phy_srch == card_phy) 470 return; 471 } 472 leapraid_transport_add_phy(adapter, sas_port, card_phy); 473 return; 474 } 475 } 476 477 void leapraid_transport_detach_phy_to_port( 478 struct leapraid_adapter *adapter, 479 struct leapraid_topo_node *topo_node, 480 struct leapraid_card_phy *target_card_phy) 481 { 482 struct leapraid_sas_port *sas_port, *sas_port_next; 483 struct leapraid_card_phy *cur_card_phy; 484 485 if (!target_card_phy->phy_is_assigned) 486 return; 487 488 list_for_each_entry_safe(sas_port, sas_port_next, 489 &topo_node->sas_port_list, port_list) { 490 list_for_each_entry(cur_card_phy, &sas_port->phy_list, 491 port_siblings) { 492 if (cur_card_phy != target_card_phy) 493 continue; 494 495 if (sas_port->phys_num == 1 && 496 !adapter->access_ctrl.shost_recovering) 497 leapraid_transport_del_port(adapter, sas_port); 498 else 499 leapraid_transport_del_phy(adapter, sas_port, 500 target_card_phy); 501 return; 502 } 503 } 504 } 505 506 static void leapraid_detach_phy_from_old_port( 507 struct leapraid_adapter *adapter, 508 struct leapraid_topo_node *topo_node, 509 u64 sas_address, 510 struct leapraid_card_port *card_port) 511 { 512 int i; 513 514 for (i = 0; i < topo_node->phys_num; i++) { 515 if (topo_node->card_phy[i].remote_identify.sas_address != 516 sas_address || 517 topo_node->card_phy[i].card_port != card_port) 518 continue; 519 if (topo_node->card_phy[i].phy_is_assigned) 520 leapraid_transport_detach_phy_to_port( 521 adapter, 522 topo_node, 523 &topo_node->card_phy[i]); 524 } 525 } 526 527 static struct leapraid_sas_port *leapraid_prepare_sas_port( 528 struct leapraid_adapter *adapter, 529 u16 handle, u64 sas_address, 530 struct leapraid_card_port *card_port, 531 struct leapraid_topo_node **out_topo_node) 532 { 533 struct leapraid_topo_node *topo_node; 534 struct leapraid_sas_port *sas_port; 535 unsigned long flags; 536 537 sas_port = kzalloc_obj(*sas_port); 538 if (!sas_port) { 539 dev_warn(&adapter->pdev->dev, 540 "%s: Failed alloc sas_port\n", __func__); 541 return NULL; 542 } 543 544 INIT_LIST_HEAD(&sas_port->port_list); 545 INIT_LIST_HEAD(&sas_port->phy_list); 546 547 spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); 548 topo_node = leapraid_transport_topo_node_by_sas_addr(adapter, 549 sas_address, 550 card_port); 551 spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); 552 553 if (!topo_node) { 554 dev_err(&adapter->pdev->dev, 555 "%s: Failed to locate parent for SAS 0x%016llx!\n", 556 __func__, sas_address); 557 goto out_cleanup; 558 } 559 560 if (leapraid_transport_set_identify(adapter, handle, 561 &sas_port->remote_identify)) 562 goto out_cleanup; 563 564 if (sas_port->remote_identify.device_type == SAS_PHY_UNUSED) { 565 dev_warn(&adapter->pdev->dev, 566 "%s: Failed, device type is SAS_PHY_UNUSED\n", 567 __func__); 568 goto out_cleanup; 569 } 570 571 sas_port->card_port = card_port; 572 *out_topo_node = topo_node; 573 574 return sas_port; 575 576 out_cleanup: 577 kfree(sas_port); 578 return NULL; 579 } 580 581 static int leapraid_bind_phys_and_vphy(struct leapraid_adapter *adapter, 582 struct leapraid_sas_port *sas_port, 583 struct leapraid_topo_node *topo_node, 584 struct leapraid_card_port *card_port, 585 struct leapraid_vphy **out_vphy) 586 { 587 struct leapraid_vphy *vphy = NULL; 588 int i; 589 590 for (i = 0; i < topo_node->phys_num; i++) { 591 if (topo_node->card_phy[i].remote_identify.sas_address != 592 sas_port->remote_identify.sas_address || 593 topo_node->card_phy[i].card_port != card_port) 594 continue; 595 596 list_add_tail(&topo_node->card_phy[i].port_siblings, 597 &sas_port->phy_list); 598 sas_port->phys_num++; 599 600 if (topo_node->hdl <= adapter->dev_topo.card.phys_num) { 601 if (!topo_node->card_phy[i].vphy) { 602 card_port->phy_mask |= BIT(i); 603 continue; 604 } 605 606 vphy = leapraid_get_vphy_by_phy(card_port, i); 607 if (!vphy) 608 return LEAPRAID_OPERATION_FAILED; 609 } 610 } 611 612 *out_vphy = vphy; 613 return sas_port->phys_num ? 0 : LEAPRAID_OPERATION_FAILED; 614 } 615 616 static struct sas_rphy *leapraid_create_and_register_rphy( 617 struct leapraid_adapter *adapter, 618 struct leapraid_sas_port *sas_port, 619 struct leapraid_topo_node *topo_node, 620 struct leapraid_card_port *card_port, 621 struct leapraid_vphy *vphy) 622 { 623 struct leapraid_sas_dev *sas_dev = NULL; 624 struct leapraid_card_phy *card_phy; 625 struct sas_port *port; 626 struct sas_rphy *rphy; 627 628 if (sas_port->remote_identify.device_type == SAS_END_DEVICE) { 629 sas_dev = leapraid_get_sas_dev_by_addr( 630 adapter, 631 sas_port->remote_identify.sas_address, 632 card_port); 633 if (!sas_dev) 634 return NULL; 635 sas_dev->pend_sas_rphy_add = 1; 636 } 637 638 if (!topo_node->parent_dev) { 639 dev_warn(&adapter->pdev->dev, 640 "%s: topo_node parent device is NULL\n", __func__); 641 goto cleanup_sas_dev; 642 } 643 644 port = sas_port_alloc_num(topo_node->parent_dev); 645 if (!port) { 646 dev_err(&adapter->pdev->dev, 647 "%s: Failed to allocate SAS port\n", __func__); 648 goto cleanup_sas_dev; 649 } 650 651 if (sas_port_add(port)) { 652 dev_err(&adapter->pdev->dev, 653 "%s: Failed to add SAS port\n", __func__); 654 goto out_delete_port; 655 } 656 657 list_for_each_entry(card_phy, &sas_port->phy_list, port_siblings) { 658 sas_port_add_phy(port, card_phy->phy); 659 card_phy->phy_is_assigned = 1; 660 card_phy->card_port = card_port; 661 } 662 663 if (sas_dev) { 664 rphy = sas_end_device_alloc(port); 665 sas_dev->rphy = rphy; 666 667 if (topo_node->hdl <= adapter->dev_topo.card.phys_num) { 668 if (!vphy) 669 card_port->sas_address = sas_dev->sas_addr; 670 else 671 vphy->sas_address = sas_dev->sas_addr; 672 } 673 } else { 674 rphy = sas_expander_alloc( 675 port, 676 sas_port->remote_identify.device_type); 677 if (topo_node->hdl <= adapter->dev_topo.card.phys_num) 678 card_port->sas_address = 679 sas_port->remote_identify.sas_address; 680 } 681 682 if (!rphy) { 683 dev_err(&adapter->pdev->dev, 684 "%s: Failed to allocate RPHY\n", __func__); 685 goto cleanup_card_phy; 686 } 687 688 rphy->identify = sas_port->remote_identify; 689 690 if (sas_rphy_add(rphy)) { 691 dev_err(&adapter->pdev->dev, 692 "%s: Failed to add RPHY\n", __func__); 693 if (sas_dev) 694 sas_dev->rphy = NULL; 695 696 sas_rphy_free(rphy); 697 goto cleanup_card_phy; 698 } 699 sas_port->port = port; 700 701 if (sas_dev) { 702 sas_dev->pend_sas_rphy_add = 0; 703 leapraid_sdev_put(sas_dev); 704 } 705 706 return rphy; 707 708 cleanup_card_phy: 709 if (topo_node->hdl <= adapter->dev_topo.card.phys_num) { 710 if (!vphy) 711 card_port->sas_address = 0; 712 else 713 vphy->sas_address = 0; 714 } 715 716 list_for_each_entry(card_phy, &sas_port->phy_list, port_siblings) { 717 card_phy->phy_is_assigned = 0; 718 card_phy->card_port = NULL; 719 } 720 721 out_delete_port: 722 sas_port_delete(port); 723 724 cleanup_sas_dev: 725 if (sas_dev) { 726 sas_dev->pend_sas_rphy_add = 0; 727 leapraid_sdev_put(sas_dev); 728 } 729 return NULL; 730 } 731 732 struct leapraid_sas_port *leapraid_transport_port_add( 733 struct leapraid_adapter *adapter, 734 u16 hdl, u64 sas_address, 735 struct leapraid_card_port *card_port) 736 { 737 struct leapraid_card_phy *card_phy, *card_phy_next; 738 struct leapraid_topo_node *topo_node = NULL; 739 struct leapraid_sas_port *sas_port; 740 struct leapraid_vphy *vphy = NULL; 741 struct sas_rphy *rphy; 742 unsigned long flags; 743 744 if (!card_port) { 745 dev_warn(&adapter->pdev->dev, 746 "%s: Invalid card_port\n", __func__); 747 return NULL; 748 } 749 750 sas_port = leapraid_prepare_sas_port(adapter, hdl, sas_address, 751 card_port, &topo_node); 752 if (!sas_port) 753 return NULL; 754 755 leapraid_detach_phy_from_old_port( 756 adapter, 757 topo_node, 758 sas_port->remote_identify.sas_address, 759 card_port); 760 761 if (leapraid_bind_phys_and_vphy(adapter, sas_port, topo_node, 762 card_port, &vphy)) { 763 dev_err(&adapter->pdev->dev, 764 "%s: Failed to bind phy to vphy\n", __func__); 765 goto out_fail; 766 } 767 768 rphy = leapraid_create_and_register_rphy(adapter, sas_port, topo_node, 769 card_port, vphy); 770 if (!rphy) { 771 dev_err(&adapter->pdev->dev, 772 "%s: Failed to create rphy\n", __func__); 773 goto out_fail; 774 } 775 776 dev_info(&rphy->dev, 777 "%s: Added dev: hdl=0x%04x, SAS addr=0x%016llx\n", 778 __func__, hdl, 779 (unsigned long long)sas_port->remote_identify.sas_address); 780 781 sas_port->rphy = rphy; 782 783 spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); 784 list_add_tail(&sas_port->port_list, &topo_node->sas_port_list); 785 spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); 786 787 if (sas_port->remote_identify.device_type == 788 SAS_EDGE_EXPANDER_DEVICE || 789 sas_port->remote_identify.device_type == 790 SAS_FANOUT_EXPANDER_DEVICE) 791 leapraid_transport_exp_report_manu( 792 adapter, 793 sas_port->remote_identify.sas_address, 794 rphy_to_expander_device(rphy), 795 card_port->port_id); 796 797 return sas_port; 798 799 out_fail: 800 list_for_each_entry_safe(card_phy, card_phy_next, 801 &sas_port->phy_list, port_siblings) { 802 if (topo_node->hdl <= adapter->dev_topo.card.phys_num && 803 !card_phy->vphy) 804 card_port->phy_mask &= ~BIT(card_phy->phy_id); 805 806 list_del_init(&card_phy->port_siblings); 807 } 808 809 kfree(sas_port); 810 return NULL; 811 } 812 813 static struct leapraid_sas_port *leapraid_find_and_remove_sas_port( 814 struct leapraid_topo_node *topo_node, 815 u64 sas_address, 816 struct leapraid_card_port *remove_card_port, 817 bool *found) 818 { 819 struct leapraid_sas_port *sas_port, *sas_port_next; 820 821 list_for_each_entry_safe(sas_port, sas_port_next, 822 &topo_node->sas_port_list, port_list) { 823 if (sas_port->remote_identify.sas_address != sas_address) 824 continue; 825 826 if (sas_port->card_port != remove_card_port) 827 continue; 828 829 *found = true; 830 list_del(&sas_port->port_list); 831 return sas_port; 832 } 833 return NULL; 834 } 835 836 static void leapraid_cleanup_card_port_and_vphys( 837 struct leapraid_adapter *adapter, 838 u64 sas_address, 839 struct leapraid_card_port *remove_card_port) 840 { 841 struct leapraid_card_port *card_port, *card_port_next; 842 struct leapraid_vphy *vphy, *vphy_next; 843 844 if (remove_card_port->vphys_mask) { 845 list_for_each_entry_safe(vphy, vphy_next, 846 &remove_card_port->vphys_list, list) { 847 if (vphy->sas_address != sas_address) 848 continue; 849 850 dev_dbg(&adapter->pdev->dev, 851 "%s: Remove vphy=%p from port=%p port_id=%d\n", 852 __func__, vphy, remove_card_port, 853 remove_card_port->port_id); 854 855 remove_card_port->vphys_mask &= ~vphy->phy_mask; 856 list_del(&vphy->list); 857 kfree(vphy); 858 } 859 860 if (!remove_card_port->vphys_mask && 861 !remove_card_port->sas_address) { 862 dev_dbg(&adapter->pdev->dev, 863 "%s: Remove empty hba_port: %p, port_id=%d\n", 864 __func__, 865 remove_card_port, 866 remove_card_port->port_id); 867 list_del(&remove_card_port->list); 868 kfree(remove_card_port); 869 remove_card_port = NULL; 870 } 871 } 872 873 list_for_each_entry_safe(card_port, card_port_next, 874 &adapter->dev_topo.card_port_list, list) { 875 if (card_port != remove_card_port) 876 continue; 877 878 if (card_port->sas_address != sas_address) 879 continue; 880 881 if (!remove_card_port->vphys_mask) { 882 dev_dbg(&adapter->pdev->dev, 883 "%s: Remove hba_port: %p, port_id=%d\n", 884 __func__, card_port, card_port->port_id); 885 list_del(&card_port->list); 886 kfree(card_port); 887 } else { 888 dev_dbg(&adapter->pdev->dev, 889 "Clear sas_address of port=%p, port_id=%d\n", 890 card_port, card_port->port_id); 891 remove_card_port->sas_address = 0; 892 } 893 break; 894 } 895 } 896 897 static void leapraid_clear_topo_node_phys(struct leapraid_topo_node *topo_node, 898 u64 sas_address) 899 { 900 int i; 901 902 for (i = 0; i < topo_node->phys_num; i++) 903 if (topo_node->card_phy[i].remote_identify.sas_address == 904 sas_address) { 905 memset(&topo_node->card_phy[i].remote_identify, 0, 906 sizeof(struct sas_identify)); 907 topo_node->card_phy[i].vphy = 0; 908 } 909 } 910 911 void leapraid_transport_port_remove( 912 struct leapraid_adapter *adapter, 913 u64 sas_address, 914 u64 sas_address_parent, 915 struct leapraid_card_port *remove_card_port) 916 { 917 struct leapraid_card_phy *card_phy, *card_phy_next; 918 struct leapraid_sas_port *sas_port; 919 struct leapraid_topo_node *topo_node; 920 unsigned long flags; 921 bool found = false; 922 923 if (!remove_card_port) 924 return; 925 926 spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); 927 928 topo_node = leapraid_transport_topo_node_by_sas_addr(adapter, 929 sas_address_parent, 930 remove_card_port); 931 if (!topo_node) { 932 spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, 933 flags); 934 return; 935 } 936 937 sas_port = leapraid_find_and_remove_sas_port(topo_node, sas_address, 938 remove_card_port, &found); 939 940 if (!found) { 941 spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, 942 flags); 943 return; 944 } 945 946 if (topo_node->hdl <= adapter->dev_topo.card.phys_num && 947 adapter->adapter_attr.enable_mp) 948 leapraid_cleanup_card_port_and_vphys(adapter, sas_address, 949 remove_card_port); 950 951 leapraid_clear_topo_node_phys(topo_node, sas_address); 952 spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); 953 954 list_for_each_entry_safe(card_phy, card_phy_next, 955 &sas_port->phy_list, port_siblings) { 956 card_phy->phy_is_assigned = 0; 957 if (!adapter->access_ctrl.host_removing) 958 sas_port_delete_phy(sas_port->port, card_phy->phy); 959 960 list_del(&card_phy->port_siblings); 961 } 962 963 if (!adapter->access_ctrl.host_removing) 964 sas_port_delete(sas_port->port); 965 966 dev_dbg(&adapter->pdev->dev, 967 "%s: Removed sas_port for SAS addr=0x%016llx\n", 968 __func__, (unsigned long long)sas_address); 969 970 kfree(sas_port); 971 } 972 973 static void leapraid_init_sas_or_exp_phy(struct leapraid_adapter *adapter, 974 struct leapraid_card_phy *card_phy, 975 struct sas_phy *phy, 976 struct leapraid_sas_phy_p0 *phy_pg0, 977 struct leapraid_exp_p1 *exp_pg1) 978 { 979 if (exp_pg1 && phy_pg0) 980 return; 981 982 if (!exp_pg1 && !phy_pg0) 983 return; 984 985 phy->identify = card_phy->identify; 986 phy->identify.phy_identifier = card_phy->phy_id; 987 phy->negotiated_linkrate = phy_pg0 ? 988 leapraid_transport_convert_phy_link_rate( 989 phy_pg0->neg_link_rate & 990 LEAPRAID_SAS_NEG_LINK_RATE_MASK_PHYSICAL) : 991 leapraid_transport_convert_phy_link_rate( 992 exp_pg1->neg_link_rate & 993 LEAPRAID_SAS_NEG_LINK_RATE_MASK_PHYSICAL); 994 phy->minimum_linkrate_hw = phy_pg0 ? 995 leapraid_transport_convert_phy_link_rate( 996 phy_pg0->hw_link_rate & 997 LEAPRAID_SAS_HWRATE_MIN_RATE_MASK) : 998 leapraid_transport_convert_phy_link_rate( 999 exp_pg1->hw_link_rate & 1000 LEAPRAID_SAS_HWRATE_MIN_RATE_MASK); 1001 phy->maximum_linkrate_hw = phy_pg0 ? 1002 leapraid_transport_convert_phy_link_rate( 1003 phy_pg0->hw_link_rate >> 1004 LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) : 1005 leapraid_transport_convert_phy_link_rate( 1006 exp_pg1->hw_link_rate >> 1007 LEAPRAID_SAS_NEG_LINK_RATE_SHIFT); 1008 phy->minimum_linkrate = phy_pg0 ? 1009 leapraid_transport_convert_phy_link_rate( 1010 phy_pg0->p_link_rate & 1011 LEAPRAID_SAS_PRATE_MIN_RATE_MASK) : 1012 leapraid_transport_convert_phy_link_rate( 1013 exp_pg1->p_link_rate & 1014 LEAPRAID_SAS_PRATE_MIN_RATE_MASK); 1015 phy->maximum_linkrate = phy_pg0 ? 1016 leapraid_transport_convert_phy_link_rate( 1017 phy_pg0->p_link_rate >> 1018 LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) : 1019 leapraid_transport_convert_phy_link_rate( 1020 exp_pg1->p_link_rate >> 1021 LEAPRAID_SAS_NEG_LINK_RATE_SHIFT); 1022 phy->hostdata = card_phy->card_port; 1023 } 1024 1025 void leapraid_transport_add_card_phy(struct leapraid_adapter *adapter, 1026 struct leapraid_card_phy *card_phy, 1027 struct leapraid_sas_phy_p0 *phy_pg0, 1028 struct device *parent_dev) 1029 { 1030 struct sas_phy *phy; 1031 int ret; 1032 1033 INIT_LIST_HEAD(&card_phy->port_siblings); 1034 phy = sas_phy_alloc(parent_dev, card_phy->phy_id); 1035 if (!phy) { 1036 dev_err(&adapter->pdev->dev, 1037 "%s: sas_phy_alloc failed!\n", __func__); 1038 return; 1039 } 1040 1041 if (leapraid_transport_set_identify(adapter, card_phy->hdl, 1042 &card_phy->identify)) { 1043 dev_err(&adapter->pdev->dev, 1044 "%s: Set PHY handle identify failed!\n", __func__); 1045 sas_phy_free(phy); 1046 return; 1047 } 1048 1049 card_phy->attached_hdl = le16_to_cpu(phy_pg0->attached_dev_hdl); 1050 if (card_phy->attached_hdl) { 1051 ret = leapraid_transport_set_identify( 1052 adapter, 1053 card_phy->attached_hdl, 1054 &card_phy->remote_identify); 1055 if (ret) { 1056 dev_err(&adapter->pdev->dev, 1057 "%s: Set PHY attached hdl identify failed!\n", 1058 __func__); 1059 sas_phy_free(phy); 1060 return; 1061 } 1062 } 1063 1064 leapraid_init_sas_or_exp_phy(adapter, card_phy, phy, phy_pg0, NULL); 1065 1066 if (sas_phy_add(phy)) { 1067 dev_err(&adapter->pdev->dev, 1068 "%s: SAS PHY add failed!\n", __func__); 1069 sas_phy_free(phy); 1070 return; 1071 } 1072 1073 card_phy->phy = phy; 1074 } 1075 1076 int leapraid_transport_add_exp_phy(struct leapraid_adapter *adapter, 1077 struct leapraid_card_phy *card_phy, 1078 struct leapraid_exp_p1 *exp_pg1, 1079 struct device *parent_dev) 1080 { 1081 struct sas_phy *phy; 1082 int ret; 1083 1084 INIT_LIST_HEAD(&card_phy->port_siblings); 1085 phy = sas_phy_alloc(parent_dev, card_phy->phy_id); 1086 if (!phy) { 1087 dev_err(&adapter->pdev->dev, 1088 "%s: sas_phy_alloc failed!\n", __func__); 1089 return -EFAULT; 1090 } 1091 1092 if (leapraid_transport_set_identify(adapter, card_phy->hdl, 1093 &card_phy->identify)) { 1094 dev_err(&adapter->pdev->dev, 1095 "%s: Set PHY hdl identify failed!\n", __func__); 1096 sas_phy_free(phy); 1097 return -EFAULT; 1098 } 1099 1100 card_phy->attached_hdl = le16_to_cpu(exp_pg1->attached_dev_hdl); 1101 if (card_phy->attached_hdl) { 1102 ret = leapraid_transport_set_identify( 1103 adapter, 1104 card_phy->attached_hdl, 1105 &card_phy->remote_identify); 1106 if (ret) 1107 dev_warn(&adapter->pdev->dev, 1108 "%s: Set PHY attached hdl identify failed!\n", 1109 __func__); 1110 } 1111 1112 leapraid_init_sas_or_exp_phy(adapter, card_phy, phy, NULL, exp_pg1); 1113 1114 if (sas_phy_add(phy)) { 1115 dev_err(&adapter->pdev->dev, 1116 "%s: SAS PHY add failed!\n", __func__); 1117 sas_phy_free(phy); 1118 return -EFAULT; 1119 } 1120 1121 card_phy->phy = phy; 1122 return 0; 1123 } 1124 1125 void leapraid_transport_update_links( 1126 struct leapraid_adapter *adapter, 1127 u64 sas_address, u16 hdl, u8 phy_index, 1128 u8 link_rate, struct leapraid_card_port *target_card_port) 1129 { 1130 struct leapraid_topo_node *topo_node; 1131 struct leapraid_card_phy *card_phy; 1132 struct leapraid_card_port *card_port; 1133 unsigned long flags; 1134 1135 if (adapter->access_ctrl.shost_recovering || 1136 adapter->access_ctrl.pcie_recovering) 1137 return; 1138 1139 spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); 1140 topo_node = leapraid_transport_topo_node_by_sas_addr(adapter, 1141 sas_address, 1142 target_card_port); 1143 if (!topo_node) { 1144 spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, 1145 flags); 1146 return; 1147 } 1148 1149 card_phy = &topo_node->card_phy[phy_index]; 1150 card_phy->attached_hdl = hdl; 1151 spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); 1152 1153 if (hdl && link_rate >= LEAPRAID_SAS_NEG_LINK_RATE_1_5) { 1154 leapraid_transport_set_identify(adapter, hdl, 1155 &card_phy->remote_identify); 1156 if (topo_node->hdl <= adapter->dev_topo.card.phys_num && 1157 adapter->adapter_attr.enable_mp) { 1158 list_for_each_entry(card_port, 1159 &adapter->dev_topo.card_port_list, 1160 list) { 1161 if (card_port->sas_address == sas_address && 1162 card_port == target_card_port) 1163 card_port->phy_mask |= 1164 BIT(card_phy->phy_id); 1165 } 1166 } 1167 leapraid_transport_attach_phy_to_port( 1168 adapter, 1169 topo_node, 1170 card_phy, 1171 card_phy->remote_identify.sas_address, 1172 target_card_port); 1173 } else { 1174 memset(&card_phy->remote_identify, 0, 1175 sizeof(struct sas_identify)); 1176 } 1177 1178 if (card_phy->phy) 1179 card_phy->phy->negotiated_linkrate = 1180 leapraid_transport_convert_phy_link_rate(link_rate); 1181 } 1182 1183 static int leapraid_dma_map_buffer(struct device *dev, struct bsg_buffer *buf, 1184 dma_addr_t *dma_addr, 1185 size_t *dma_len, void **p) 1186 { 1187 if (buf->sg_cnt > 1) { 1188 *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr, 1189 GFP_KERNEL); 1190 if (!*p) 1191 return -ENOMEM; 1192 1193 *dma_len = buf->payload_len; 1194 } else { 1195 if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL)) { 1196 dev_err(dev, 1197 "%s: Failed to map sg buffer for dma\n", 1198 __func__); 1199 return -ENOMEM; 1200 } 1201 1202 *dma_addr = sg_dma_address(buf->sg_list); 1203 *dma_len = sg_dma_len(buf->sg_list); 1204 *p = NULL; 1205 } 1206 return 0; 1207 } 1208 1209 static void leapraid_dma_unmap_buffer(struct device *dev, 1210 struct bsg_buffer *buf, 1211 dma_addr_t dma_addr, 1212 void *p) 1213 { 1214 if (p) 1215 dma_free_coherent(dev, buf->payload_len, p, dma_addr); 1216 else 1217 dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL); 1218 } 1219 1220 static void leapraid_build_smp_task(struct leapraid_adapter *adapter, 1221 struct sas_rphy *rphy, 1222 dma_addr_t h2c_dma_addr, size_t h2c_size, 1223 dma_addr_t c2h_dma_addr, size_t c2h_size) 1224 { 1225 struct leapraid_smp_passthrough_req *smp_passthrough_req; 1226 u16 inter_taskid; 1227 void *psge; 1228 1229 inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid; 1230 smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid); 1231 memset(smp_passthrough_req, 0, sizeof(*smp_passthrough_req)); 1232 1233 smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH; 1234 smp_passthrough_req->physical_port = 1235 leapraid_transport_get_port_id_by_rphy(adapter, rphy); 1236 smp_passthrough_req->sas_address = (rphy) ? 1237 cpu_to_le64(rphy->identify.sas_address) : 1238 cpu_to_le64(adapter->dev_topo.card.sas_address); 1239 smp_passthrough_req->req_data_len = 1240 cpu_to_le16(h2c_size - LEAPRAID_SMP_FRAME_HEADER_SIZE); 1241 psge = &smp_passthrough_req->sgl; 1242 leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, 1243 h2c_size - LEAPRAID_SMP_FRAME_HEADER_SIZE, 1244 c2h_dma_addr, 1245 c2h_size - LEAPRAID_SMP_FRAME_HEADER_SIZE); 1246 } 1247 1248 static int leapraid_send_smp_req(struct leapraid_adapter *adapter) 1249 { 1250 const struct leapraid_smp_passthrough_req *smp_passthrough_req; 1251 u16 inter_taskid; 1252 1253 dev_dbg(&adapter->pdev->dev, 1254 "%s: Sending smp request\n", __func__); 1255 inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid; 1256 smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid); 1257 init_completion(&adapter->driver_cmds.transport_cmd.done); 1258 leapraid_fire_task(adapter, inter_taskid); 1259 wait_for_completion_timeout(&adapter->driver_cmds.transport_cmd.done, 1260 LEAPRAID_TRANSPORT_CMD_TIMEOUT * HZ); 1261 if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_DONE)) { 1262 dev_err(&adapter->pdev->dev, "%s: timeout, st=0x%x\n", 1263 __func__, adapter->driver_cmds.transport_cmd.status); 1264 leapraid_log_req_context(adapter, inter_taskid, 1265 smp_passthrough_req); 1266 if (!(adapter->driver_cmds.transport_cmd.status & 1267 LEAPRAID_CMD_RESET)) { 1268 dev_dbg(&adapter->pdev->dev, 1269 "%s:%d: call hard_reset\n", 1270 __func__, __LINE__); 1271 leapraid_hard_reset_handler(adapter, FULL_RESET); 1272 return -ETIMEDOUT; 1273 } 1274 } 1275 1276 dev_dbg(&adapter->pdev->dev, "%s: SMP request complete\n", __func__); 1277 if (!(adapter->driver_cmds.transport_cmd.status & 1278 LEAPRAID_CMD_REPLY_VALID)) { 1279 dev_err(&adapter->pdev->dev, 1280 "%s: SMP request no reply\n", __func__); 1281 return -ENXIO; 1282 } 1283 1284 return 0; 1285 } 1286 1287 static void leapraid_handle_smp_rep(struct leapraid_adapter *adapter, 1288 struct bsg_job *job, void *addr_in, 1289 unsigned int *reslen) 1290 { 1291 struct leapraid_smp_passthrough_rep *smp_passthrough_rep; 1292 1293 smp_passthrough_rep = 1294 (void *)&adapter->driver_cmds.transport_cmd.reply; 1295 1296 dev_dbg(&adapter->pdev->dev, "%s: Response data len=%d\n", 1297 __func__, le16_to_cpu(smp_passthrough_rep->resp_data_len)); 1298 1299 memcpy(job->reply, smp_passthrough_rep, sizeof(*smp_passthrough_rep)); 1300 job->reply_len = sizeof(*smp_passthrough_rep); 1301 *reslen = le16_to_cpu(smp_passthrough_rep->resp_data_len); 1302 1303 if (addr_in) 1304 sg_copy_from_buffer(job->reply_payload.sg_list, 1305 job->reply_payload.sg_cnt, addr_in, 1306 job->reply_payload.payload_len); 1307 } 1308 1309 static void leapraid_transport_smp_handler(struct bsg_job *job, 1310 struct Scsi_Host *shost, 1311 struct sas_rphy *rphy) 1312 { 1313 struct leapraid_adapter *adapter = shost_priv(shost); 1314 dma_addr_t c2h_dma_addr; 1315 dma_addr_t h2c_dma_addr; 1316 void *addr_in = NULL; 1317 void *addr_out = NULL; 1318 size_t c2h_size; 1319 size_t h2c_size; 1320 int rc; 1321 unsigned int reslen = 0; 1322 1323 if (adapter->access_ctrl.shost_recovering || 1324 adapter->access_ctrl.pcie_recovering) { 1325 dev_err(&adapter->pdev->dev, 1326 "%s: Failed, shost_recovering=%d pcie_recovering=%d\n", 1327 __func__, 1328 adapter->access_ctrl.shost_recovering, 1329 adapter->access_ctrl.pcie_recovering); 1330 rc = -EFAULT; 1331 goto exit_bsg_job; 1332 } 1333 1334 rc = mutex_lock_interruptible(&adapter->driver_cmds 1335 .transport_cmd.mutex); 1336 if (rc) 1337 goto exit_bsg_job; 1338 1339 adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_PENDING; 1340 rc = leapraid_dma_map_buffer(&adapter->pdev->dev, 1341 &job->request_payload, 1342 &h2c_dma_addr, &h2c_size, &addr_out); 1343 if (rc) 1344 goto release_lock; 1345 1346 if (h2c_size < LEAPRAID_SMP_FRAME_HEADER_SIZE) { 1347 dev_err(&adapter->pdev->dev, 1348 "%s: Invalid SMP request payload size=%zu\n", 1349 __func__, h2c_size); 1350 rc = -EINVAL; 1351 goto free_req_buf; 1352 } 1353 1354 if (addr_out) 1355 sg_copy_to_buffer(job->request_payload.sg_list, 1356 job->request_payload.sg_cnt, addr_out, 1357 job->request_payload.payload_len); 1358 1359 rc = leapraid_dma_map_buffer(&adapter->pdev->dev, &job->reply_payload, 1360 &c2h_dma_addr, &c2h_size, &addr_in); 1361 if (rc) 1362 goto free_req_buf; 1363 1364 if (c2h_size < LEAPRAID_SMP_FRAME_HEADER_SIZE) { 1365 dev_err(&adapter->pdev->dev, 1366 "%s: Invalid SMP reply payload size=%zu\n", 1367 __func__, c2h_size); 1368 rc = -EINVAL; 1369 goto free_rep_buf; 1370 } 1371 1372 rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, 1373 __func__); 1374 if (rc) 1375 goto free_rep_buf; 1376 1377 leapraid_build_smp_task(adapter, rphy, h2c_dma_addr, 1378 h2c_size, c2h_dma_addr, c2h_size); 1379 1380 rc = leapraid_send_smp_req(adapter); 1381 if (rc) 1382 goto free_rep_buf; 1383 1384 leapraid_handle_smp_rep(adapter, job, addr_in, &reslen); 1385 1386 free_rep_buf: 1387 leapraid_dma_unmap_buffer(&adapter->pdev->dev, &job->reply_payload, 1388 c2h_dma_addr, addr_in); 1389 free_req_buf: 1390 leapraid_dma_unmap_buffer(&adapter->pdev->dev, &job->request_payload, 1391 h2c_dma_addr, addr_out); 1392 release_lock: 1393 adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_NOT_USED; 1394 mutex_unlock(&adapter->driver_cmds.transport_cmd.mutex); 1395 exit_bsg_job: 1396 bsg_job_done(job, rc, reslen); 1397 } 1398 1399 struct sas_function_template leapraid_transport_functions = { 1400 .smp_handler = leapraid_transport_smp_handler, 1401 }; 1402 1403 struct scsi_transport_template *leapraid_transport_template; 1404