1 /* 2 * Serial Attached SCSI (SAS) Expander discovery and configuration 3 * 4 * Copyright (C) 2005 Adaptec, Inc. All rights reserved. 5 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> 6 * 7 * This file is licensed under GPLv2. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of the 12 * License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 * 23 */ 24 25 #include <linux/pci.h> 26 #include <linux/scatterlist.h> 27 28 #include "sas_internal.h" 29 30 #include <scsi/scsi_transport.h> 31 #include <scsi/scsi_transport_sas.h> 32 #include "../scsi_sas_internal.h" 33 34 static int sas_discover_expander(struct domain_device *dev); 35 static int sas_configure_routing(struct domain_device *dev, u8 *sas_addr); 36 static int sas_configure_phy(struct domain_device *dev, int phy_id, 37 u8 *sas_addr, int include); 38 static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr); 39 40 #if 0 41 /* FIXME: smp needs to migrate into the sas class */ 42 static ssize_t smp_portal_read(struct kobject *, char *, loff_t, size_t); 43 static ssize_t smp_portal_write(struct kobject *, char *, loff_t, size_t); 44 #endif 45 46 /* ---------- SMP task management ---------- */ 47 48 static void smp_task_timedout(unsigned long _task) 49 { 50 struct sas_task *task = (void *) _task; 51 unsigned long flags; 52 53 spin_lock_irqsave(&task->task_state_lock, flags); 54 if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) 55 task->task_state_flags |= SAS_TASK_STATE_ABORTED; 56 spin_unlock_irqrestore(&task->task_state_lock, flags); 57 58 complete(&task->completion); 59 } 60 61 static void smp_task_done(struct sas_task *task) 62 { 63 if (!del_timer(&task->timer)) 64 return; 65 complete(&task->completion); 66 } 67 68 /* Give it some long enough timeout. In seconds. */ 69 #define SMP_TIMEOUT 10 70 71 static int smp_execute_task(struct domain_device *dev, void *req, int req_size, 72 void *resp, int resp_size) 73 { 74 int res, retry; 75 struct sas_task *task = NULL; 76 struct sas_internal *i = 77 to_sas_internal(dev->port->ha->core.shost->transportt); 78 79 for (retry = 0; retry < 3; retry++) { 80 task = sas_alloc_task(GFP_KERNEL); 81 if (!task) 82 return -ENOMEM; 83 84 task->dev = dev; 85 task->task_proto = dev->tproto; 86 sg_init_one(&task->smp_task.smp_req, req, req_size); 87 sg_init_one(&task->smp_task.smp_resp, resp, resp_size); 88 89 task->task_done = smp_task_done; 90 91 task->timer.data = (unsigned long) task; 92 task->timer.function = smp_task_timedout; 93 task->timer.expires = jiffies + SMP_TIMEOUT*HZ; 94 add_timer(&task->timer); 95 96 res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); 97 98 if (res) { 99 del_timer(&task->timer); 100 SAS_DPRINTK("executing SMP task failed:%d\n", res); 101 goto ex_err; 102 } 103 104 wait_for_completion(&task->completion); 105 res = -ETASK; 106 if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { 107 SAS_DPRINTK("smp task timed out or aborted\n"); 108 i->dft->lldd_abort_task(task); 109 if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { 110 SAS_DPRINTK("SMP task aborted and not done\n"); 111 goto ex_err; 112 } 113 } 114 if (task->task_status.resp == SAS_TASK_COMPLETE && 115 task->task_status.stat == SAM_GOOD) { 116 res = 0; 117 break; 118 } else { 119 SAS_DPRINTK("%s: task to dev %016llx response: 0x%x " 120 "status 0x%x\n", __FUNCTION__, 121 SAS_ADDR(dev->sas_addr), 122 task->task_status.resp, 123 task->task_status.stat); 124 sas_free_task(task); 125 task = NULL; 126 } 127 } 128 ex_err: 129 BUG_ON(retry == 3 && task != NULL); 130 if (task != NULL) { 131 sas_free_task(task); 132 } 133 return res; 134 } 135 136 /* ---------- Allocations ---------- */ 137 138 static inline void *alloc_smp_req(int size) 139 { 140 u8 *p = kzalloc(size, GFP_KERNEL); 141 if (p) 142 p[0] = SMP_REQUEST; 143 return p; 144 } 145 146 static inline void *alloc_smp_resp(int size) 147 { 148 return kzalloc(size, GFP_KERNEL); 149 } 150 151 /* ---------- Expander configuration ---------- */ 152 153 static void sas_set_ex_phy(struct domain_device *dev, int phy_id, 154 void *disc_resp) 155 { 156 struct expander_device *ex = &dev->ex_dev; 157 struct ex_phy *phy = &ex->ex_phy[phy_id]; 158 struct smp_resp *resp = disc_resp; 159 struct discover_resp *dr = &resp->disc; 160 struct sas_rphy *rphy = dev->rphy; 161 int rediscover = (phy->phy != NULL); 162 163 if (!rediscover) { 164 phy->phy = sas_phy_alloc(&rphy->dev, phy_id); 165 166 /* FIXME: error_handling */ 167 BUG_ON(!phy->phy); 168 } 169 170 switch (resp->result) { 171 case SMP_RESP_PHY_VACANT: 172 phy->phy_state = PHY_VACANT; 173 return; 174 default: 175 phy->phy_state = PHY_NOT_PRESENT; 176 return; 177 case SMP_RESP_FUNC_ACC: 178 phy->phy_state = PHY_EMPTY; /* do not know yet */ 179 break; 180 } 181 182 phy->phy_id = phy_id; 183 phy->attached_dev_type = dr->attached_dev_type; 184 phy->linkrate = dr->linkrate; 185 phy->attached_sata_host = dr->attached_sata_host; 186 phy->attached_sata_dev = dr->attached_sata_dev; 187 phy->attached_sata_ps = dr->attached_sata_ps; 188 phy->attached_iproto = dr->iproto << 1; 189 phy->attached_tproto = dr->tproto << 1; 190 memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE); 191 phy->attached_phy_id = dr->attached_phy_id; 192 phy->phy_change_count = dr->change_count; 193 phy->routing_attr = dr->routing_attr; 194 phy->virtual = dr->virtual; 195 phy->last_da_index = -1; 196 197 phy->phy->identify.initiator_port_protocols = phy->attached_iproto; 198 phy->phy->identify.target_port_protocols = phy->attached_tproto; 199 phy->phy->identify.phy_identifier = phy_id; 200 phy->phy->minimum_linkrate_hw = dr->hmin_linkrate; 201 phy->phy->maximum_linkrate_hw = dr->hmax_linkrate; 202 phy->phy->minimum_linkrate = dr->pmin_linkrate; 203 phy->phy->maximum_linkrate = dr->pmax_linkrate; 204 phy->phy->negotiated_linkrate = phy->linkrate; 205 206 if (!rediscover) 207 sas_phy_add(phy->phy); 208 209 SAS_DPRINTK("ex %016llx phy%02d:%c attached: %016llx\n", 210 SAS_ADDR(dev->sas_addr), phy->phy_id, 211 phy->routing_attr == TABLE_ROUTING ? 'T' : 212 phy->routing_attr == DIRECT_ROUTING ? 'D' : 213 phy->routing_attr == SUBTRACTIVE_ROUTING ? 'S' : '?', 214 SAS_ADDR(phy->attached_sas_addr)); 215 216 return; 217 } 218 219 #define DISCOVER_REQ_SIZE 16 220 #define DISCOVER_RESP_SIZE 56 221 222 static int sas_ex_phy_discover(struct domain_device *dev, int single) 223 { 224 struct expander_device *ex = &dev->ex_dev; 225 int res = 0; 226 u8 *disc_req; 227 u8 *disc_resp; 228 229 disc_req = alloc_smp_req(DISCOVER_REQ_SIZE); 230 if (!disc_req) 231 return -ENOMEM; 232 233 disc_resp = alloc_smp_req(DISCOVER_RESP_SIZE); 234 if (!disc_resp) { 235 kfree(disc_req); 236 return -ENOMEM; 237 } 238 239 disc_req[1] = SMP_DISCOVER; 240 241 if (0 <= single && single < ex->num_phys) { 242 disc_req[9] = single; 243 res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE, 244 disc_resp, DISCOVER_RESP_SIZE); 245 if (res) 246 goto out_err; 247 sas_set_ex_phy(dev, single, disc_resp); 248 } else { 249 int i; 250 251 for (i = 0; i < ex->num_phys; i++) { 252 disc_req[9] = i; 253 res = smp_execute_task(dev, disc_req, 254 DISCOVER_REQ_SIZE, disc_resp, 255 DISCOVER_RESP_SIZE); 256 if (res) 257 goto out_err; 258 sas_set_ex_phy(dev, i, disc_resp); 259 } 260 } 261 out_err: 262 kfree(disc_resp); 263 kfree(disc_req); 264 return res; 265 } 266 267 static int sas_expander_discover(struct domain_device *dev) 268 { 269 struct expander_device *ex = &dev->ex_dev; 270 int res = -ENOMEM; 271 272 ex->ex_phy = kzalloc(sizeof(*ex->ex_phy)*ex->num_phys, GFP_KERNEL); 273 if (!ex->ex_phy) 274 return -ENOMEM; 275 276 res = sas_ex_phy_discover(dev, -1); 277 if (res) 278 goto out_err; 279 280 return 0; 281 out_err: 282 kfree(ex->ex_phy); 283 ex->ex_phy = NULL; 284 return res; 285 } 286 287 #define MAX_EXPANDER_PHYS 128 288 289 static void ex_assign_report_general(struct domain_device *dev, 290 struct smp_resp *resp) 291 { 292 struct report_general_resp *rg = &resp->rg; 293 294 dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count); 295 dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes); 296 dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS); 297 dev->ex_dev.conf_route_table = rg->conf_route_table; 298 dev->ex_dev.configuring = rg->configuring; 299 memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8); 300 } 301 302 #define RG_REQ_SIZE 8 303 #define RG_RESP_SIZE 32 304 305 static int sas_ex_general(struct domain_device *dev) 306 { 307 u8 *rg_req; 308 struct smp_resp *rg_resp; 309 int res; 310 int i; 311 312 rg_req = alloc_smp_req(RG_REQ_SIZE); 313 if (!rg_req) 314 return -ENOMEM; 315 316 rg_resp = alloc_smp_resp(RG_RESP_SIZE); 317 if (!rg_resp) { 318 kfree(rg_req); 319 return -ENOMEM; 320 } 321 322 rg_req[1] = SMP_REPORT_GENERAL; 323 324 for (i = 0; i < 5; i++) { 325 res = smp_execute_task(dev, rg_req, RG_REQ_SIZE, rg_resp, 326 RG_RESP_SIZE); 327 328 if (res) { 329 SAS_DPRINTK("RG to ex %016llx failed:0x%x\n", 330 SAS_ADDR(dev->sas_addr), res); 331 goto out; 332 } else if (rg_resp->result != SMP_RESP_FUNC_ACC) { 333 SAS_DPRINTK("RG:ex %016llx returned SMP result:0x%x\n", 334 SAS_ADDR(dev->sas_addr), rg_resp->result); 335 res = rg_resp->result; 336 goto out; 337 } 338 339 ex_assign_report_general(dev, rg_resp); 340 341 if (dev->ex_dev.configuring) { 342 SAS_DPRINTK("RG: ex %llx self-configuring...\n", 343 SAS_ADDR(dev->sas_addr)); 344 schedule_timeout_interruptible(5*HZ); 345 } else 346 break; 347 } 348 out: 349 kfree(rg_req); 350 kfree(rg_resp); 351 return res; 352 } 353 354 static void ex_assign_manuf_info(struct domain_device *dev, void 355 *_mi_resp) 356 { 357 u8 *mi_resp = _mi_resp; 358 struct sas_rphy *rphy = dev->rphy; 359 struct sas_expander_device *edev = rphy_to_expander_device(rphy); 360 361 memcpy(edev->vendor_id, mi_resp + 12, SAS_EXPANDER_VENDOR_ID_LEN); 362 memcpy(edev->product_id, mi_resp + 20, SAS_EXPANDER_PRODUCT_ID_LEN); 363 memcpy(edev->product_rev, mi_resp + 36, 364 SAS_EXPANDER_PRODUCT_REV_LEN); 365 366 if (mi_resp[8] & 1) { 367 memcpy(edev->component_vendor_id, mi_resp + 40, 368 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN); 369 edev->component_id = mi_resp[48] << 8 | mi_resp[49]; 370 edev->component_revision_id = mi_resp[50]; 371 } 372 } 373 374 #define MI_REQ_SIZE 8 375 #define MI_RESP_SIZE 64 376 377 static int sas_ex_manuf_info(struct domain_device *dev) 378 { 379 u8 *mi_req; 380 u8 *mi_resp; 381 int res; 382 383 mi_req = alloc_smp_req(MI_REQ_SIZE); 384 if (!mi_req) 385 return -ENOMEM; 386 387 mi_resp = alloc_smp_resp(MI_RESP_SIZE); 388 if (!mi_resp) { 389 kfree(mi_req); 390 return -ENOMEM; 391 } 392 393 mi_req[1] = SMP_REPORT_MANUF_INFO; 394 395 res = smp_execute_task(dev, mi_req, MI_REQ_SIZE, mi_resp,MI_RESP_SIZE); 396 if (res) { 397 SAS_DPRINTK("MI: ex %016llx failed:0x%x\n", 398 SAS_ADDR(dev->sas_addr), res); 399 goto out; 400 } else if (mi_resp[2] != SMP_RESP_FUNC_ACC) { 401 SAS_DPRINTK("MI ex %016llx returned SMP result:0x%x\n", 402 SAS_ADDR(dev->sas_addr), mi_resp[2]); 403 goto out; 404 } 405 406 ex_assign_manuf_info(dev, mi_resp); 407 out: 408 kfree(mi_req); 409 kfree(mi_resp); 410 return res; 411 } 412 413 #define PC_REQ_SIZE 44 414 #define PC_RESP_SIZE 8 415 416 int sas_smp_phy_control(struct domain_device *dev, int phy_id, 417 enum phy_func phy_func, 418 struct sas_phy_linkrates *rates) 419 { 420 u8 *pc_req; 421 u8 *pc_resp; 422 int res; 423 424 pc_req = alloc_smp_req(PC_REQ_SIZE); 425 if (!pc_req) 426 return -ENOMEM; 427 428 pc_resp = alloc_smp_resp(PC_RESP_SIZE); 429 if (!pc_resp) { 430 kfree(pc_req); 431 return -ENOMEM; 432 } 433 434 pc_req[1] = SMP_PHY_CONTROL; 435 pc_req[9] = phy_id; 436 pc_req[10]= phy_func; 437 if (rates) { 438 pc_req[32] = rates->minimum_linkrate << 4; 439 pc_req[33] = rates->maximum_linkrate << 4; 440 } 441 442 res = smp_execute_task(dev, pc_req, PC_REQ_SIZE, pc_resp,PC_RESP_SIZE); 443 444 kfree(pc_resp); 445 kfree(pc_req); 446 return res; 447 } 448 449 static void sas_ex_disable_phy(struct domain_device *dev, int phy_id) 450 { 451 struct expander_device *ex = &dev->ex_dev; 452 struct ex_phy *phy = &ex->ex_phy[phy_id]; 453 454 sas_smp_phy_control(dev, phy_id, PHY_FUNC_DISABLE, NULL); 455 phy->linkrate = SAS_PHY_DISABLED; 456 } 457 458 static void sas_ex_disable_port(struct domain_device *dev, u8 *sas_addr) 459 { 460 struct expander_device *ex = &dev->ex_dev; 461 int i; 462 463 for (i = 0; i < ex->num_phys; i++) { 464 struct ex_phy *phy = &ex->ex_phy[i]; 465 466 if (phy->phy_state == PHY_VACANT || 467 phy->phy_state == PHY_NOT_PRESENT) 468 continue; 469 470 if (SAS_ADDR(phy->attached_sas_addr) == SAS_ADDR(sas_addr)) 471 sas_ex_disable_phy(dev, i); 472 } 473 } 474 475 static int sas_dev_present_in_domain(struct asd_sas_port *port, 476 u8 *sas_addr) 477 { 478 struct domain_device *dev; 479 480 if (SAS_ADDR(port->sas_addr) == SAS_ADDR(sas_addr)) 481 return 1; 482 list_for_each_entry(dev, &port->dev_list, dev_list_node) { 483 if (SAS_ADDR(dev->sas_addr) == SAS_ADDR(sas_addr)) 484 return 1; 485 } 486 return 0; 487 } 488 489 #define RPEL_REQ_SIZE 16 490 #define RPEL_RESP_SIZE 32 491 int sas_smp_get_phy_events(struct sas_phy *phy) 492 { 493 int res; 494 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); 495 struct domain_device *dev = sas_find_dev_by_rphy(rphy); 496 u8 *req = alloc_smp_req(RPEL_REQ_SIZE); 497 u8 *resp = kzalloc(RPEL_RESP_SIZE, GFP_KERNEL); 498 499 if (!resp) 500 return -ENOMEM; 501 502 req[1] = SMP_REPORT_PHY_ERR_LOG; 503 req[9] = phy->number; 504 505 res = smp_execute_task(dev, req, RPEL_REQ_SIZE, 506 resp, RPEL_RESP_SIZE); 507 508 if (!res) 509 goto out; 510 511 phy->invalid_dword_count = scsi_to_u32(&resp[12]); 512 phy->running_disparity_error_count = scsi_to_u32(&resp[16]); 513 phy->loss_of_dword_sync_count = scsi_to_u32(&resp[20]); 514 phy->phy_reset_problem_count = scsi_to_u32(&resp[24]); 515 516 out: 517 kfree(resp); 518 return res; 519 520 } 521 522 #define RPS_REQ_SIZE 16 523 #define RPS_RESP_SIZE 60 524 525 static int sas_get_report_phy_sata(struct domain_device *dev, 526 int phy_id, 527 struct smp_resp *rps_resp) 528 { 529 int res; 530 u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE); 531 532 if (!rps_req) 533 return -ENOMEM; 534 535 rps_req[1] = SMP_REPORT_PHY_SATA; 536 rps_req[9] = phy_id; 537 538 res = smp_execute_task(dev, rps_req, RPS_REQ_SIZE, 539 rps_resp, RPS_RESP_SIZE); 540 541 kfree(rps_req); 542 return 0; 543 } 544 545 static void sas_ex_get_linkrate(struct domain_device *parent, 546 struct domain_device *child, 547 struct ex_phy *parent_phy) 548 { 549 struct expander_device *parent_ex = &parent->ex_dev; 550 struct sas_port *port; 551 int i; 552 553 child->pathways = 0; 554 555 port = parent_phy->port; 556 557 for (i = 0; i < parent_ex->num_phys; i++) { 558 struct ex_phy *phy = &parent_ex->ex_phy[i]; 559 560 if (phy->phy_state == PHY_VACANT || 561 phy->phy_state == PHY_NOT_PRESENT) 562 continue; 563 564 if (SAS_ADDR(phy->attached_sas_addr) == 565 SAS_ADDR(child->sas_addr)) { 566 567 child->min_linkrate = min(parent->min_linkrate, 568 phy->linkrate); 569 child->max_linkrate = max(parent->max_linkrate, 570 phy->linkrate); 571 child->pathways++; 572 sas_port_add_phy(port, phy->phy); 573 } 574 } 575 child->linkrate = min(parent_phy->linkrate, child->max_linkrate); 576 child->pathways = min(child->pathways, parent->pathways); 577 } 578 579 static struct domain_device *sas_ex_discover_end_dev( 580 struct domain_device *parent, int phy_id) 581 { 582 struct expander_device *parent_ex = &parent->ex_dev; 583 struct ex_phy *phy = &parent_ex->ex_phy[phy_id]; 584 struct domain_device *child = NULL; 585 struct sas_rphy *rphy; 586 int res; 587 588 if (phy->attached_sata_host || phy->attached_sata_ps) 589 return NULL; 590 591 child = kzalloc(sizeof(*child), GFP_KERNEL); 592 if (!child) 593 return NULL; 594 595 child->parent = parent; 596 child->port = parent->port; 597 child->iproto = phy->attached_iproto; 598 memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); 599 sas_hash_addr(child->hashed_sas_addr, child->sas_addr); 600 if (!phy->port) { 601 phy->port = sas_port_alloc(&parent->rphy->dev, phy_id); 602 if (unlikely(!phy->port)) 603 goto out_err; 604 if (unlikely(sas_port_add(phy->port) != 0)) { 605 sas_port_free(phy->port); 606 goto out_err; 607 } 608 } 609 sas_ex_get_linkrate(parent, child, phy); 610 611 if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { 612 child->dev_type = SATA_DEV; 613 if (phy->attached_tproto & SAS_PROTO_STP) 614 child->tproto = phy->attached_tproto; 615 if (phy->attached_sata_dev) 616 child->tproto |= SATA_DEV; 617 res = sas_get_report_phy_sata(parent, phy_id, 618 &child->sata_dev.rps_resp); 619 if (res) { 620 SAS_DPRINTK("report phy sata to %016llx:0x%x returned " 621 "0x%x\n", SAS_ADDR(parent->sas_addr), 622 phy_id, res); 623 goto out_free; 624 } 625 memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis, 626 sizeof(struct dev_to_host_fis)); 627 sas_init_dev(child); 628 res = sas_discover_sata(child); 629 if (res) { 630 SAS_DPRINTK("sas_discover_sata() for device %16llx at " 631 "%016llx:0x%x returned 0x%x\n", 632 SAS_ADDR(child->sas_addr), 633 SAS_ADDR(parent->sas_addr), phy_id, res); 634 goto out_free; 635 } 636 } else if (phy->attached_tproto & SAS_PROTO_SSP) { 637 child->dev_type = SAS_END_DEV; 638 rphy = sas_end_device_alloc(phy->port); 639 /* FIXME: error handling */ 640 if (unlikely(!rphy)) 641 goto out_free; 642 child->tproto = phy->attached_tproto; 643 sas_init_dev(child); 644 645 child->rphy = rphy; 646 sas_fill_in_rphy(child, rphy); 647 648 spin_lock(&parent->port->dev_list_lock); 649 list_add_tail(&child->dev_list_node, &parent->port->dev_list); 650 spin_unlock(&parent->port->dev_list_lock); 651 652 res = sas_discover_end_dev(child); 653 if (res) { 654 SAS_DPRINTK("sas_discover_end_dev() for device %16llx " 655 "at %016llx:0x%x returned 0x%x\n", 656 SAS_ADDR(child->sas_addr), 657 SAS_ADDR(parent->sas_addr), phy_id, res); 658 goto out_list_del; 659 } 660 } else { 661 SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", 662 phy->attached_tproto, SAS_ADDR(parent->sas_addr), 663 phy_id); 664 } 665 666 list_add_tail(&child->siblings, &parent_ex->children); 667 return child; 668 669 out_list_del: 670 list_del(&child->dev_list_node); 671 sas_rphy_free(rphy); 672 out_free: 673 sas_port_delete(phy->port); 674 out_err: 675 phy->port = NULL; 676 kfree(child); 677 return NULL; 678 } 679 680 static struct domain_device *sas_ex_discover_expander( 681 struct domain_device *parent, int phy_id) 682 { 683 struct sas_expander_device *parent_ex = rphy_to_expander_device(parent->rphy); 684 struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id]; 685 struct domain_device *child = NULL; 686 struct sas_rphy *rphy; 687 struct sas_expander_device *edev; 688 struct asd_sas_port *port; 689 int res; 690 691 if (phy->routing_attr == DIRECT_ROUTING) { 692 SAS_DPRINTK("ex %016llx:0x%x:D <--> ex %016llx:0x%x is not " 693 "allowed\n", 694 SAS_ADDR(parent->sas_addr), phy_id, 695 SAS_ADDR(phy->attached_sas_addr), 696 phy->attached_phy_id); 697 return NULL; 698 } 699 child = kzalloc(sizeof(*child), GFP_KERNEL); 700 if (!child) 701 return NULL; 702 703 phy->port = sas_port_alloc(&parent->rphy->dev, phy_id); 704 /* FIXME: better error handling */ 705 BUG_ON(sas_port_add(phy->port) != 0); 706 707 708 switch (phy->attached_dev_type) { 709 case EDGE_DEV: 710 rphy = sas_expander_alloc(phy->port, 711 SAS_EDGE_EXPANDER_DEVICE); 712 break; 713 case FANOUT_DEV: 714 rphy = sas_expander_alloc(phy->port, 715 SAS_FANOUT_EXPANDER_DEVICE); 716 break; 717 default: 718 rphy = NULL; /* shut gcc up */ 719 BUG(); 720 } 721 port = parent->port; 722 child->rphy = rphy; 723 edev = rphy_to_expander_device(rphy); 724 child->dev_type = phy->attached_dev_type; 725 child->parent = parent; 726 child->port = port; 727 child->iproto = phy->attached_iproto; 728 child->tproto = phy->attached_tproto; 729 memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); 730 sas_hash_addr(child->hashed_sas_addr, child->sas_addr); 731 sas_ex_get_linkrate(parent, child, phy); 732 edev->level = parent_ex->level + 1; 733 parent->port->disc.max_level = max(parent->port->disc.max_level, 734 edev->level); 735 sas_init_dev(child); 736 sas_fill_in_rphy(child, rphy); 737 sas_rphy_add(rphy); 738 739 spin_lock(&parent->port->dev_list_lock); 740 list_add_tail(&child->dev_list_node, &parent->port->dev_list); 741 spin_unlock(&parent->port->dev_list_lock); 742 743 res = sas_discover_expander(child); 744 if (res) { 745 kfree(child); 746 return NULL; 747 } 748 list_add_tail(&child->siblings, &parent->ex_dev.children); 749 return child; 750 } 751 752 static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) 753 { 754 struct expander_device *ex = &dev->ex_dev; 755 struct ex_phy *ex_phy = &ex->ex_phy[phy_id]; 756 struct domain_device *child = NULL; 757 int res = 0; 758 759 /* Phy state */ 760 if (ex_phy->linkrate == SAS_SATA_SPINUP_HOLD) { 761 if (!sas_smp_phy_control(dev, phy_id, PHY_FUNC_LINK_RESET, NULL)) 762 res = sas_ex_phy_discover(dev, phy_id); 763 if (res) 764 return res; 765 } 766 767 /* Parent and domain coherency */ 768 if (!dev->parent && (SAS_ADDR(ex_phy->attached_sas_addr) == 769 SAS_ADDR(dev->port->sas_addr))) { 770 sas_add_parent_port(dev, phy_id); 771 return 0; 772 } 773 if (dev->parent && (SAS_ADDR(ex_phy->attached_sas_addr) == 774 SAS_ADDR(dev->parent->sas_addr))) { 775 sas_add_parent_port(dev, phy_id); 776 if (ex_phy->routing_attr == TABLE_ROUTING) 777 sas_configure_phy(dev, phy_id, dev->port->sas_addr, 1); 778 return 0; 779 } 780 781 if (sas_dev_present_in_domain(dev->port, ex_phy->attached_sas_addr)) 782 sas_ex_disable_port(dev, ex_phy->attached_sas_addr); 783 784 if (ex_phy->attached_dev_type == NO_DEVICE) { 785 if (ex_phy->routing_attr == DIRECT_ROUTING) { 786 memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE); 787 sas_configure_routing(dev, ex_phy->attached_sas_addr); 788 } 789 return 0; 790 } else if (ex_phy->linkrate == SAS_LINK_RATE_UNKNOWN) 791 return 0; 792 793 if (ex_phy->attached_dev_type != SAS_END_DEV && 794 ex_phy->attached_dev_type != FANOUT_DEV && 795 ex_phy->attached_dev_type != EDGE_DEV) { 796 SAS_DPRINTK("unknown device type(0x%x) attached to ex %016llx " 797 "phy 0x%x\n", ex_phy->attached_dev_type, 798 SAS_ADDR(dev->sas_addr), 799 phy_id); 800 return 0; 801 } 802 803 res = sas_configure_routing(dev, ex_phy->attached_sas_addr); 804 if (res) { 805 SAS_DPRINTK("configure routing for dev %016llx " 806 "reported 0x%x. Forgotten\n", 807 SAS_ADDR(ex_phy->attached_sas_addr), res); 808 sas_disable_routing(dev, ex_phy->attached_sas_addr); 809 return res; 810 } 811 812 switch (ex_phy->attached_dev_type) { 813 case SAS_END_DEV: 814 child = sas_ex_discover_end_dev(dev, phy_id); 815 break; 816 case FANOUT_DEV: 817 if (SAS_ADDR(dev->port->disc.fanout_sas_addr)) { 818 SAS_DPRINTK("second fanout expander %016llx phy 0x%x " 819 "attached to ex %016llx phy 0x%x\n", 820 SAS_ADDR(ex_phy->attached_sas_addr), 821 ex_phy->attached_phy_id, 822 SAS_ADDR(dev->sas_addr), 823 phy_id); 824 sas_ex_disable_phy(dev, phy_id); 825 break; 826 } else 827 memcpy(dev->port->disc.fanout_sas_addr, 828 ex_phy->attached_sas_addr, SAS_ADDR_SIZE); 829 /* fallthrough */ 830 case EDGE_DEV: 831 child = sas_ex_discover_expander(dev, phy_id); 832 break; 833 default: 834 break; 835 } 836 837 if (child) { 838 int i; 839 840 for (i = 0; i < ex->num_phys; i++) { 841 if (ex->ex_phy[i].phy_state == PHY_VACANT || 842 ex->ex_phy[i].phy_state == PHY_NOT_PRESENT) 843 continue; 844 845 if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == 846 SAS_ADDR(child->sas_addr)) 847 ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; 848 } 849 } 850 851 return res; 852 } 853 854 static int sas_find_sub_addr(struct domain_device *dev, u8 *sub_addr) 855 { 856 struct expander_device *ex = &dev->ex_dev; 857 int i; 858 859 for (i = 0; i < ex->num_phys; i++) { 860 struct ex_phy *phy = &ex->ex_phy[i]; 861 862 if (phy->phy_state == PHY_VACANT || 863 phy->phy_state == PHY_NOT_PRESENT) 864 continue; 865 866 if ((phy->attached_dev_type == EDGE_DEV || 867 phy->attached_dev_type == FANOUT_DEV) && 868 phy->routing_attr == SUBTRACTIVE_ROUTING) { 869 870 memcpy(sub_addr, phy->attached_sas_addr,SAS_ADDR_SIZE); 871 872 return 1; 873 } 874 } 875 return 0; 876 } 877 878 static int sas_check_level_subtractive_boundary(struct domain_device *dev) 879 { 880 struct expander_device *ex = &dev->ex_dev; 881 struct domain_device *child; 882 u8 sub_addr[8] = {0, }; 883 884 list_for_each_entry(child, &ex->children, siblings) { 885 if (child->dev_type != EDGE_DEV && 886 child->dev_type != FANOUT_DEV) 887 continue; 888 if (sub_addr[0] == 0) { 889 sas_find_sub_addr(child, sub_addr); 890 continue; 891 } else { 892 u8 s2[8]; 893 894 if (sas_find_sub_addr(child, s2) && 895 (SAS_ADDR(sub_addr) != SAS_ADDR(s2))) { 896 897 SAS_DPRINTK("ex %016llx->%016llx-?->%016llx " 898 "diverges from subtractive " 899 "boundary %016llx\n", 900 SAS_ADDR(dev->sas_addr), 901 SAS_ADDR(child->sas_addr), 902 SAS_ADDR(s2), 903 SAS_ADDR(sub_addr)); 904 905 sas_ex_disable_port(child, s2); 906 } 907 } 908 } 909 return 0; 910 } 911 /** 912 * sas_ex_discover_devices -- discover devices attached to this expander 913 * dev: pointer to the expander domain device 914 * single: if you want to do a single phy, else set to -1; 915 * 916 * Configure this expander for use with its devices and register the 917 * devices of this expander. 918 */ 919 static int sas_ex_discover_devices(struct domain_device *dev, int single) 920 { 921 struct expander_device *ex = &dev->ex_dev; 922 int i = 0, end = ex->num_phys; 923 int res = 0; 924 925 if (0 <= single && single < end) { 926 i = single; 927 end = i+1; 928 } 929 930 for ( ; i < end; i++) { 931 struct ex_phy *ex_phy = &ex->ex_phy[i]; 932 933 if (ex_phy->phy_state == PHY_VACANT || 934 ex_phy->phy_state == PHY_NOT_PRESENT || 935 ex_phy->phy_state == PHY_DEVICE_DISCOVERED) 936 continue; 937 938 switch (ex_phy->linkrate) { 939 case SAS_PHY_DISABLED: 940 case SAS_PHY_RESET_PROBLEM: 941 case SAS_SATA_PORT_SELECTOR: 942 continue; 943 default: 944 res = sas_ex_discover_dev(dev, i); 945 if (res) 946 break; 947 continue; 948 } 949 } 950 951 if (!res) 952 sas_check_level_subtractive_boundary(dev); 953 954 return res; 955 } 956 957 static int sas_check_ex_subtractive_boundary(struct domain_device *dev) 958 { 959 struct expander_device *ex = &dev->ex_dev; 960 int i; 961 u8 *sub_sas_addr = NULL; 962 963 if (dev->dev_type != EDGE_DEV) 964 return 0; 965 966 for (i = 0; i < ex->num_phys; i++) { 967 struct ex_phy *phy = &ex->ex_phy[i]; 968 969 if (phy->phy_state == PHY_VACANT || 970 phy->phy_state == PHY_NOT_PRESENT) 971 continue; 972 973 if ((phy->attached_dev_type == FANOUT_DEV || 974 phy->attached_dev_type == EDGE_DEV) && 975 phy->routing_attr == SUBTRACTIVE_ROUTING) { 976 977 if (!sub_sas_addr) 978 sub_sas_addr = &phy->attached_sas_addr[0]; 979 else if (SAS_ADDR(sub_sas_addr) != 980 SAS_ADDR(phy->attached_sas_addr)) { 981 982 SAS_DPRINTK("ex %016llx phy 0x%x " 983 "diverges(%016llx) on subtractive " 984 "boundary(%016llx). Disabled\n", 985 SAS_ADDR(dev->sas_addr), i, 986 SAS_ADDR(phy->attached_sas_addr), 987 SAS_ADDR(sub_sas_addr)); 988 sas_ex_disable_phy(dev, i); 989 } 990 } 991 } 992 return 0; 993 } 994 995 static void sas_print_parent_topology_bug(struct domain_device *child, 996 struct ex_phy *parent_phy, 997 struct ex_phy *child_phy) 998 { 999 static const char ra_char[] = { 1000 [DIRECT_ROUTING] = 'D', 1001 [SUBTRACTIVE_ROUTING] = 'S', 1002 [TABLE_ROUTING] = 'T', 1003 }; 1004 static const char *ex_type[] = { 1005 [EDGE_DEV] = "edge", 1006 [FANOUT_DEV] = "fanout", 1007 }; 1008 struct domain_device *parent = child->parent; 1009 1010 sas_printk("%s ex %016llx phy 0x%x <--> %s ex %016llx phy 0x%x " 1011 "has %c:%c routing link!\n", 1012 1013 ex_type[parent->dev_type], 1014 SAS_ADDR(parent->sas_addr), 1015 parent_phy->phy_id, 1016 1017 ex_type[child->dev_type], 1018 SAS_ADDR(child->sas_addr), 1019 child_phy->phy_id, 1020 1021 ra_char[parent_phy->routing_attr], 1022 ra_char[child_phy->routing_attr]); 1023 } 1024 1025 static int sas_check_eeds(struct domain_device *child, 1026 struct ex_phy *parent_phy, 1027 struct ex_phy *child_phy) 1028 { 1029 int res = 0; 1030 struct domain_device *parent = child->parent; 1031 1032 if (SAS_ADDR(parent->port->disc.fanout_sas_addr) != 0) { 1033 res = -ENODEV; 1034 SAS_DPRINTK("edge ex %016llx phy S:0x%x <--> edge ex %016llx " 1035 "phy S:0x%x, while there is a fanout ex %016llx\n", 1036 SAS_ADDR(parent->sas_addr), 1037 parent_phy->phy_id, 1038 SAS_ADDR(child->sas_addr), 1039 child_phy->phy_id, 1040 SAS_ADDR(parent->port->disc.fanout_sas_addr)); 1041 } else if (SAS_ADDR(parent->port->disc.eeds_a) == 0) { 1042 memcpy(parent->port->disc.eeds_a, parent->sas_addr, 1043 SAS_ADDR_SIZE); 1044 memcpy(parent->port->disc.eeds_b, child->sas_addr, 1045 SAS_ADDR_SIZE); 1046 } else if (((SAS_ADDR(parent->port->disc.eeds_a) == 1047 SAS_ADDR(parent->sas_addr)) || 1048 (SAS_ADDR(parent->port->disc.eeds_a) == 1049 SAS_ADDR(child->sas_addr))) 1050 && 1051 ((SAS_ADDR(parent->port->disc.eeds_b) == 1052 SAS_ADDR(parent->sas_addr)) || 1053 (SAS_ADDR(parent->port->disc.eeds_b) == 1054 SAS_ADDR(child->sas_addr)))) 1055 ; 1056 else { 1057 res = -ENODEV; 1058 SAS_DPRINTK("edge ex %016llx phy 0x%x <--> edge ex %016llx " 1059 "phy 0x%x link forms a third EEDS!\n", 1060 SAS_ADDR(parent->sas_addr), 1061 parent_phy->phy_id, 1062 SAS_ADDR(child->sas_addr), 1063 child_phy->phy_id); 1064 } 1065 1066 return res; 1067 } 1068 1069 /* Here we spill over 80 columns. It is intentional. 1070 */ 1071 static int sas_check_parent_topology(struct domain_device *child) 1072 { 1073 struct expander_device *child_ex = &child->ex_dev; 1074 struct expander_device *parent_ex; 1075 int i; 1076 int res = 0; 1077 1078 if (!child->parent) 1079 return 0; 1080 1081 if (child->parent->dev_type != EDGE_DEV && 1082 child->parent->dev_type != FANOUT_DEV) 1083 return 0; 1084 1085 parent_ex = &child->parent->ex_dev; 1086 1087 for (i = 0; i < parent_ex->num_phys; i++) { 1088 struct ex_phy *parent_phy = &parent_ex->ex_phy[i]; 1089 struct ex_phy *child_phy; 1090 1091 if (parent_phy->phy_state == PHY_VACANT || 1092 parent_phy->phy_state == PHY_NOT_PRESENT) 1093 continue; 1094 1095 if (SAS_ADDR(parent_phy->attached_sas_addr) != SAS_ADDR(child->sas_addr)) 1096 continue; 1097 1098 child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id]; 1099 1100 switch (child->parent->dev_type) { 1101 case EDGE_DEV: 1102 if (child->dev_type == FANOUT_DEV) { 1103 if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING || 1104 child_phy->routing_attr != TABLE_ROUTING) { 1105 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1106 res = -ENODEV; 1107 } 1108 } else if (parent_phy->routing_attr == SUBTRACTIVE_ROUTING) { 1109 if (child_phy->routing_attr == SUBTRACTIVE_ROUTING) { 1110 res = sas_check_eeds(child, parent_phy, child_phy); 1111 } else if (child_phy->routing_attr != TABLE_ROUTING) { 1112 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1113 res = -ENODEV; 1114 } 1115 } else if (parent_phy->routing_attr == TABLE_ROUTING && 1116 child_phy->routing_attr != SUBTRACTIVE_ROUTING) { 1117 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1118 res = -ENODEV; 1119 } 1120 break; 1121 case FANOUT_DEV: 1122 if (parent_phy->routing_attr != TABLE_ROUTING || 1123 child_phy->routing_attr != SUBTRACTIVE_ROUTING) { 1124 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1125 res = -ENODEV; 1126 } 1127 break; 1128 default: 1129 break; 1130 } 1131 } 1132 1133 return res; 1134 } 1135 1136 #define RRI_REQ_SIZE 16 1137 #define RRI_RESP_SIZE 44 1138 1139 static int sas_configure_present(struct domain_device *dev, int phy_id, 1140 u8 *sas_addr, int *index, int *present) 1141 { 1142 int i, res = 0; 1143 struct expander_device *ex = &dev->ex_dev; 1144 struct ex_phy *phy = &ex->ex_phy[phy_id]; 1145 u8 *rri_req; 1146 u8 *rri_resp; 1147 1148 *present = 0; 1149 *index = 0; 1150 1151 rri_req = alloc_smp_req(RRI_REQ_SIZE); 1152 if (!rri_req) 1153 return -ENOMEM; 1154 1155 rri_resp = alloc_smp_resp(RRI_RESP_SIZE); 1156 if (!rri_resp) { 1157 kfree(rri_req); 1158 return -ENOMEM; 1159 } 1160 1161 rri_req[1] = SMP_REPORT_ROUTE_INFO; 1162 rri_req[9] = phy_id; 1163 1164 for (i = 0; i < ex->max_route_indexes ; i++) { 1165 *(__be16 *)(rri_req+6) = cpu_to_be16(i); 1166 res = smp_execute_task(dev, rri_req, RRI_REQ_SIZE, rri_resp, 1167 RRI_RESP_SIZE); 1168 if (res) 1169 goto out; 1170 res = rri_resp[2]; 1171 if (res == SMP_RESP_NO_INDEX) { 1172 SAS_DPRINTK("overflow of indexes: dev %016llx " 1173 "phy 0x%x index 0x%x\n", 1174 SAS_ADDR(dev->sas_addr), phy_id, i); 1175 goto out; 1176 } else if (res != SMP_RESP_FUNC_ACC) { 1177 SAS_DPRINTK("%s: dev %016llx phy 0x%x index 0x%x " 1178 "result 0x%x\n", __FUNCTION__, 1179 SAS_ADDR(dev->sas_addr), phy_id, i, res); 1180 goto out; 1181 } 1182 if (SAS_ADDR(sas_addr) != 0) { 1183 if (SAS_ADDR(rri_resp+16) == SAS_ADDR(sas_addr)) { 1184 *index = i; 1185 if ((rri_resp[12] & 0x80) == 0x80) 1186 *present = 0; 1187 else 1188 *present = 1; 1189 goto out; 1190 } else if (SAS_ADDR(rri_resp+16) == 0) { 1191 *index = i; 1192 *present = 0; 1193 goto out; 1194 } 1195 } else if (SAS_ADDR(rri_resp+16) == 0 && 1196 phy->last_da_index < i) { 1197 phy->last_da_index = i; 1198 *index = i; 1199 *present = 0; 1200 goto out; 1201 } 1202 } 1203 res = -1; 1204 out: 1205 kfree(rri_req); 1206 kfree(rri_resp); 1207 return res; 1208 } 1209 1210 #define CRI_REQ_SIZE 44 1211 #define CRI_RESP_SIZE 8 1212 1213 static int sas_configure_set(struct domain_device *dev, int phy_id, 1214 u8 *sas_addr, int index, int include) 1215 { 1216 int res; 1217 u8 *cri_req; 1218 u8 *cri_resp; 1219 1220 cri_req = alloc_smp_req(CRI_REQ_SIZE); 1221 if (!cri_req) 1222 return -ENOMEM; 1223 1224 cri_resp = alloc_smp_resp(CRI_RESP_SIZE); 1225 if (!cri_resp) { 1226 kfree(cri_req); 1227 return -ENOMEM; 1228 } 1229 1230 cri_req[1] = SMP_CONF_ROUTE_INFO; 1231 *(__be16 *)(cri_req+6) = cpu_to_be16(index); 1232 cri_req[9] = phy_id; 1233 if (SAS_ADDR(sas_addr) == 0 || !include) 1234 cri_req[12] |= 0x80; 1235 memcpy(cri_req+16, sas_addr, SAS_ADDR_SIZE); 1236 1237 res = smp_execute_task(dev, cri_req, CRI_REQ_SIZE, cri_resp, 1238 CRI_RESP_SIZE); 1239 if (res) 1240 goto out; 1241 res = cri_resp[2]; 1242 if (res == SMP_RESP_NO_INDEX) { 1243 SAS_DPRINTK("overflow of indexes: dev %016llx phy 0x%x " 1244 "index 0x%x\n", 1245 SAS_ADDR(dev->sas_addr), phy_id, index); 1246 } 1247 out: 1248 kfree(cri_req); 1249 kfree(cri_resp); 1250 return res; 1251 } 1252 1253 static int sas_configure_phy(struct domain_device *dev, int phy_id, 1254 u8 *sas_addr, int include) 1255 { 1256 int index; 1257 int present; 1258 int res; 1259 1260 res = sas_configure_present(dev, phy_id, sas_addr, &index, &present); 1261 if (res) 1262 return res; 1263 if (include ^ present) 1264 return sas_configure_set(dev, phy_id, sas_addr, index,include); 1265 1266 return res; 1267 } 1268 1269 /** 1270 * sas_configure_parent -- configure routing table of parent 1271 * parent: parent expander 1272 * child: child expander 1273 * sas_addr: SAS port identifier of device directly attached to child 1274 */ 1275 static int sas_configure_parent(struct domain_device *parent, 1276 struct domain_device *child, 1277 u8 *sas_addr, int include) 1278 { 1279 struct expander_device *ex_parent = &parent->ex_dev; 1280 int res = 0; 1281 int i; 1282 1283 if (parent->parent) { 1284 res = sas_configure_parent(parent->parent, parent, sas_addr, 1285 include); 1286 if (res) 1287 return res; 1288 } 1289 1290 if (ex_parent->conf_route_table == 0) { 1291 SAS_DPRINTK("ex %016llx has self-configuring routing table\n", 1292 SAS_ADDR(parent->sas_addr)); 1293 return 0; 1294 } 1295 1296 for (i = 0; i < ex_parent->num_phys; i++) { 1297 struct ex_phy *phy = &ex_parent->ex_phy[i]; 1298 1299 if ((phy->routing_attr == TABLE_ROUTING) && 1300 (SAS_ADDR(phy->attached_sas_addr) == 1301 SAS_ADDR(child->sas_addr))) { 1302 res = sas_configure_phy(parent, i, sas_addr, include); 1303 if (res) 1304 return res; 1305 } 1306 } 1307 1308 return res; 1309 } 1310 1311 /** 1312 * sas_configure_routing -- configure routing 1313 * dev: expander device 1314 * sas_addr: port identifier of device directly attached to the expander device 1315 */ 1316 static int sas_configure_routing(struct domain_device *dev, u8 *sas_addr) 1317 { 1318 if (dev->parent) 1319 return sas_configure_parent(dev->parent, dev, sas_addr, 1); 1320 return 0; 1321 } 1322 1323 static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr) 1324 { 1325 if (dev->parent) 1326 return sas_configure_parent(dev->parent, dev, sas_addr, 0); 1327 return 0; 1328 } 1329 1330 #if 0 1331 #define SMP_BIN_ATTR_NAME "smp_portal" 1332 1333 static void sas_ex_smp_hook(struct domain_device *dev) 1334 { 1335 struct expander_device *ex_dev = &dev->ex_dev; 1336 struct bin_attribute *bin_attr = &ex_dev->smp_bin_attr; 1337 1338 memset(bin_attr, 0, sizeof(*bin_attr)); 1339 1340 bin_attr->attr.name = SMP_BIN_ATTR_NAME; 1341 bin_attr->attr.owner = THIS_MODULE; 1342 bin_attr->attr.mode = 0600; 1343 1344 bin_attr->size = 0; 1345 bin_attr->private = NULL; 1346 bin_attr->read = smp_portal_read; 1347 bin_attr->write= smp_portal_write; 1348 bin_attr->mmap = NULL; 1349 1350 ex_dev->smp_portal_pid = -1; 1351 init_MUTEX(&ex_dev->smp_sema); 1352 } 1353 #endif 1354 1355 /** 1356 * sas_discover_expander -- expander discovery 1357 * @ex: pointer to expander domain device 1358 * 1359 * See comment in sas_discover_sata(). 1360 */ 1361 static int sas_discover_expander(struct domain_device *dev) 1362 { 1363 int res; 1364 1365 res = sas_notify_lldd_dev_found(dev); 1366 if (res) 1367 return res; 1368 1369 res = sas_ex_general(dev); 1370 if (res) 1371 goto out_err; 1372 res = sas_ex_manuf_info(dev); 1373 if (res) 1374 goto out_err; 1375 1376 res = sas_expander_discover(dev); 1377 if (res) { 1378 SAS_DPRINTK("expander %016llx discovery failed(0x%x)\n", 1379 SAS_ADDR(dev->sas_addr), res); 1380 goto out_err; 1381 } 1382 1383 sas_check_ex_subtractive_boundary(dev); 1384 res = sas_check_parent_topology(dev); 1385 if (res) 1386 goto out_err; 1387 return 0; 1388 out_err: 1389 sas_notify_lldd_dev_gone(dev); 1390 return res; 1391 } 1392 1393 static int sas_ex_level_discovery(struct asd_sas_port *port, const int level) 1394 { 1395 int res = 0; 1396 struct domain_device *dev; 1397 1398 list_for_each_entry(dev, &port->dev_list, dev_list_node) { 1399 if (dev->dev_type == EDGE_DEV || 1400 dev->dev_type == FANOUT_DEV) { 1401 struct sas_expander_device *ex = 1402 rphy_to_expander_device(dev->rphy); 1403 1404 if (level == ex->level) 1405 res = sas_ex_discover_devices(dev, -1); 1406 else if (level > 0) 1407 res = sas_ex_discover_devices(port->port_dev, -1); 1408 1409 } 1410 } 1411 1412 return res; 1413 } 1414 1415 static int sas_ex_bfs_disc(struct asd_sas_port *port) 1416 { 1417 int res; 1418 int level; 1419 1420 do { 1421 level = port->disc.max_level; 1422 res = sas_ex_level_discovery(port, level); 1423 mb(); 1424 } while (level < port->disc.max_level); 1425 1426 return res; 1427 } 1428 1429 int sas_discover_root_expander(struct domain_device *dev) 1430 { 1431 int res; 1432 struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy); 1433 1434 sas_rphy_add(dev->rphy); 1435 1436 ex->level = dev->port->disc.max_level; /* 0 */ 1437 res = sas_discover_expander(dev); 1438 if (!res) 1439 sas_ex_bfs_disc(dev->port); 1440 1441 return res; 1442 } 1443 1444 /* ---------- Domain revalidation ---------- */ 1445 1446 static int sas_get_phy_discover(struct domain_device *dev, 1447 int phy_id, struct smp_resp *disc_resp) 1448 { 1449 int res; 1450 u8 *disc_req; 1451 1452 disc_req = alloc_smp_req(DISCOVER_REQ_SIZE); 1453 if (!disc_req) 1454 return -ENOMEM; 1455 1456 disc_req[1] = SMP_DISCOVER; 1457 disc_req[9] = phy_id; 1458 1459 res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE, 1460 disc_resp, DISCOVER_RESP_SIZE); 1461 if (res) 1462 goto out; 1463 else if (disc_resp->result != SMP_RESP_FUNC_ACC) { 1464 res = disc_resp->result; 1465 goto out; 1466 } 1467 out: 1468 kfree(disc_req); 1469 return res; 1470 } 1471 1472 static int sas_get_phy_change_count(struct domain_device *dev, 1473 int phy_id, int *pcc) 1474 { 1475 int res; 1476 struct smp_resp *disc_resp; 1477 1478 disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE); 1479 if (!disc_resp) 1480 return -ENOMEM; 1481 1482 res = sas_get_phy_discover(dev, phy_id, disc_resp); 1483 if (!res) 1484 *pcc = disc_resp->disc.change_count; 1485 1486 kfree(disc_resp); 1487 return res; 1488 } 1489 1490 static int sas_get_phy_attached_sas_addr(struct domain_device *dev, 1491 int phy_id, u8 *attached_sas_addr) 1492 { 1493 int res; 1494 struct smp_resp *disc_resp; 1495 struct discover_resp *dr; 1496 1497 disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE); 1498 if (!disc_resp) 1499 return -ENOMEM; 1500 dr = &disc_resp->disc; 1501 1502 res = sas_get_phy_discover(dev, phy_id, disc_resp); 1503 if (!res) { 1504 memcpy(attached_sas_addr,disc_resp->disc.attached_sas_addr,8); 1505 if (dr->attached_dev_type == 0) 1506 memset(attached_sas_addr, 0, 8); 1507 } 1508 kfree(disc_resp); 1509 return res; 1510 } 1511 1512 static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id, 1513 int from_phy) 1514 { 1515 struct expander_device *ex = &dev->ex_dev; 1516 int res = 0; 1517 int i; 1518 1519 for (i = from_phy; i < ex->num_phys; i++) { 1520 int phy_change_count = 0; 1521 1522 res = sas_get_phy_change_count(dev, i, &phy_change_count); 1523 if (res) 1524 goto out; 1525 else if (phy_change_count != ex->ex_phy[i].phy_change_count) { 1526 ex->ex_phy[i].phy_change_count = phy_change_count; 1527 *phy_id = i; 1528 return 0; 1529 } 1530 } 1531 out: 1532 return res; 1533 } 1534 1535 static int sas_get_ex_change_count(struct domain_device *dev, int *ecc) 1536 { 1537 int res; 1538 u8 *rg_req; 1539 struct smp_resp *rg_resp; 1540 1541 rg_req = alloc_smp_req(RG_REQ_SIZE); 1542 if (!rg_req) 1543 return -ENOMEM; 1544 1545 rg_resp = alloc_smp_resp(RG_RESP_SIZE); 1546 if (!rg_resp) { 1547 kfree(rg_req); 1548 return -ENOMEM; 1549 } 1550 1551 rg_req[1] = SMP_REPORT_GENERAL; 1552 1553 res = smp_execute_task(dev, rg_req, RG_REQ_SIZE, rg_resp, 1554 RG_RESP_SIZE); 1555 if (res) 1556 goto out; 1557 if (rg_resp->result != SMP_RESP_FUNC_ACC) { 1558 res = rg_resp->result; 1559 goto out; 1560 } 1561 1562 *ecc = be16_to_cpu(rg_resp->rg.change_count); 1563 out: 1564 kfree(rg_resp); 1565 kfree(rg_req); 1566 return res; 1567 } 1568 1569 static int sas_find_bcast_dev(struct domain_device *dev, 1570 struct domain_device **src_dev) 1571 { 1572 struct expander_device *ex = &dev->ex_dev; 1573 int ex_change_count = -1; 1574 int res; 1575 1576 res = sas_get_ex_change_count(dev, &ex_change_count); 1577 if (res) 1578 goto out; 1579 if (ex_change_count != -1 && 1580 ex_change_count != ex->ex_change_count) { 1581 *src_dev = dev; 1582 ex->ex_change_count = ex_change_count; 1583 } else { 1584 struct domain_device *ch; 1585 1586 list_for_each_entry(ch, &ex->children, siblings) { 1587 if (ch->dev_type == EDGE_DEV || 1588 ch->dev_type == FANOUT_DEV) { 1589 res = sas_find_bcast_dev(ch, src_dev); 1590 if (src_dev) 1591 return res; 1592 } 1593 } 1594 } 1595 out: 1596 return res; 1597 } 1598 1599 static void sas_unregister_ex_tree(struct domain_device *dev) 1600 { 1601 struct expander_device *ex = &dev->ex_dev; 1602 struct domain_device *child, *n; 1603 1604 list_for_each_entry_safe(child, n, &ex->children, siblings) { 1605 if (child->dev_type == EDGE_DEV || 1606 child->dev_type == FANOUT_DEV) 1607 sas_unregister_ex_tree(child); 1608 else 1609 sas_unregister_dev(child); 1610 } 1611 sas_unregister_dev(dev); 1612 } 1613 1614 static void sas_unregister_devs_sas_addr(struct domain_device *parent, 1615 int phy_id) 1616 { 1617 struct expander_device *ex_dev = &parent->ex_dev; 1618 struct ex_phy *phy = &ex_dev->ex_phy[phy_id]; 1619 struct domain_device *child, *n; 1620 1621 list_for_each_entry_safe(child, n, &ex_dev->children, siblings) { 1622 if (SAS_ADDR(child->sas_addr) == 1623 SAS_ADDR(phy->attached_sas_addr)) { 1624 if (child->dev_type == EDGE_DEV || 1625 child->dev_type == FANOUT_DEV) 1626 sas_unregister_ex_tree(child); 1627 else 1628 sas_unregister_dev(child); 1629 break; 1630 } 1631 } 1632 sas_disable_routing(parent, phy->attached_sas_addr); 1633 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); 1634 sas_port_delete_phy(phy->port, phy->phy); 1635 if (phy->port->num_phys == 0) 1636 sas_port_delete(phy->port); 1637 phy->port = NULL; 1638 } 1639 1640 static int sas_discover_bfs_by_root_level(struct domain_device *root, 1641 const int level) 1642 { 1643 struct expander_device *ex_root = &root->ex_dev; 1644 struct domain_device *child; 1645 int res = 0; 1646 1647 list_for_each_entry(child, &ex_root->children, siblings) { 1648 if (child->dev_type == EDGE_DEV || 1649 child->dev_type == FANOUT_DEV) { 1650 struct sas_expander_device *ex = 1651 rphy_to_expander_device(child->rphy); 1652 1653 if (level > ex->level) 1654 res = sas_discover_bfs_by_root_level(child, 1655 level); 1656 else if (level == ex->level) 1657 res = sas_ex_discover_devices(child, -1); 1658 } 1659 } 1660 return res; 1661 } 1662 1663 static int sas_discover_bfs_by_root(struct domain_device *dev) 1664 { 1665 int res; 1666 struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy); 1667 int level = ex->level+1; 1668 1669 res = sas_ex_discover_devices(dev, -1); 1670 if (res) 1671 goto out; 1672 do { 1673 res = sas_discover_bfs_by_root_level(dev, level); 1674 mb(); 1675 level += 1; 1676 } while (level <= dev->port->disc.max_level); 1677 out: 1678 return res; 1679 } 1680 1681 static int sas_discover_new(struct domain_device *dev, int phy_id) 1682 { 1683 struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; 1684 struct domain_device *child; 1685 int res; 1686 1687 SAS_DPRINTK("ex %016llx phy%d new device attached\n", 1688 SAS_ADDR(dev->sas_addr), phy_id); 1689 res = sas_ex_phy_discover(dev, phy_id); 1690 if (res) 1691 goto out; 1692 res = sas_ex_discover_devices(dev, phy_id); 1693 if (res) 1694 goto out; 1695 list_for_each_entry(child, &dev->ex_dev.children, siblings) { 1696 if (SAS_ADDR(child->sas_addr) == 1697 SAS_ADDR(ex_phy->attached_sas_addr)) { 1698 if (child->dev_type == EDGE_DEV || 1699 child->dev_type == FANOUT_DEV) 1700 res = sas_discover_bfs_by_root(child); 1701 break; 1702 } 1703 } 1704 out: 1705 return res; 1706 } 1707 1708 static int sas_rediscover_dev(struct domain_device *dev, int phy_id) 1709 { 1710 struct expander_device *ex = &dev->ex_dev; 1711 struct ex_phy *phy = &ex->ex_phy[phy_id]; 1712 u8 attached_sas_addr[8]; 1713 int res; 1714 1715 res = sas_get_phy_attached_sas_addr(dev, phy_id, attached_sas_addr); 1716 switch (res) { 1717 case SMP_RESP_NO_PHY: 1718 phy->phy_state = PHY_NOT_PRESENT; 1719 sas_unregister_devs_sas_addr(dev, phy_id); 1720 goto out; break; 1721 case SMP_RESP_PHY_VACANT: 1722 phy->phy_state = PHY_VACANT; 1723 sas_unregister_devs_sas_addr(dev, phy_id); 1724 goto out; break; 1725 case SMP_RESP_FUNC_ACC: 1726 break; 1727 } 1728 1729 if (SAS_ADDR(attached_sas_addr) == 0) { 1730 phy->phy_state = PHY_EMPTY; 1731 sas_unregister_devs_sas_addr(dev, phy_id); 1732 } else if (SAS_ADDR(attached_sas_addr) == 1733 SAS_ADDR(phy->attached_sas_addr)) { 1734 SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter\n", 1735 SAS_ADDR(dev->sas_addr), phy_id); 1736 sas_ex_phy_discover(dev, phy_id); 1737 } else 1738 res = sas_discover_new(dev, phy_id); 1739 out: 1740 return res; 1741 } 1742 1743 static int sas_rediscover(struct domain_device *dev, const int phy_id) 1744 { 1745 struct expander_device *ex = &dev->ex_dev; 1746 struct ex_phy *changed_phy = &ex->ex_phy[phy_id]; 1747 int res = 0; 1748 int i; 1749 1750 SAS_DPRINTK("ex %016llx phy%d originated BROADCAST(CHANGE)\n", 1751 SAS_ADDR(dev->sas_addr), phy_id); 1752 1753 if (SAS_ADDR(changed_phy->attached_sas_addr) != 0) { 1754 for (i = 0; i < ex->num_phys; i++) { 1755 struct ex_phy *phy = &ex->ex_phy[i]; 1756 1757 if (i == phy_id) 1758 continue; 1759 if (SAS_ADDR(phy->attached_sas_addr) == 1760 SAS_ADDR(changed_phy->attached_sas_addr)) { 1761 SAS_DPRINTK("phy%d part of wide port with " 1762 "phy%d\n", phy_id, i); 1763 goto out; 1764 } 1765 } 1766 res = sas_rediscover_dev(dev, phy_id); 1767 } else 1768 res = sas_discover_new(dev, phy_id); 1769 out: 1770 return res; 1771 } 1772 1773 /** 1774 * sas_revalidate_domain -- revalidate the domain 1775 * @port: port to the domain of interest 1776 * 1777 * NOTE: this process _must_ quit (return) as soon as any connection 1778 * errors are encountered. Connection recovery is done elsewhere. 1779 * Discover process only interrogates devices in order to discover the 1780 * domain. 1781 */ 1782 int sas_ex_revalidate_domain(struct domain_device *port_dev) 1783 { 1784 int res; 1785 struct domain_device *dev = NULL; 1786 1787 res = sas_find_bcast_dev(port_dev, &dev); 1788 if (res) 1789 goto out; 1790 if (dev) { 1791 struct expander_device *ex = &dev->ex_dev; 1792 int i = 0, phy_id; 1793 1794 do { 1795 phy_id = -1; 1796 res = sas_find_bcast_phy(dev, &phy_id, i); 1797 if (phy_id == -1) 1798 break; 1799 res = sas_rediscover(dev, phy_id); 1800 i = phy_id + 1; 1801 } while (i < ex->num_phys); 1802 } 1803 out: 1804 return res; 1805 } 1806 1807 #if 0 1808 /* ---------- SMP portal ---------- */ 1809 1810 static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs, 1811 size_t size) 1812 { 1813 struct domain_device *dev = to_dom_device(kobj); 1814 struct expander_device *ex = &dev->ex_dev; 1815 1816 if (offs != 0) 1817 return -EFBIG; 1818 else if (size == 0) 1819 return 0; 1820 1821 down_interruptible(&ex->smp_sema); 1822 if (ex->smp_req) 1823 kfree(ex->smp_req); 1824 ex->smp_req = kzalloc(size, GFP_USER); 1825 if (!ex->smp_req) { 1826 up(&ex->smp_sema); 1827 return -ENOMEM; 1828 } 1829 memcpy(ex->smp_req, buf, size); 1830 ex->smp_req_size = size; 1831 ex->smp_portal_pid = current->pid; 1832 up(&ex->smp_sema); 1833 1834 return size; 1835 } 1836 1837 static ssize_t smp_portal_read(struct kobject *kobj, char *buf, loff_t offs, 1838 size_t size) 1839 { 1840 struct domain_device *dev = to_dom_device(kobj); 1841 struct expander_device *ex = &dev->ex_dev; 1842 u8 *smp_resp; 1843 int res = -EINVAL; 1844 1845 /* XXX: sysfs gives us an offset of 0x10 or 0x8 while in fact 1846 * it should be 0. 1847 */ 1848 1849 down_interruptible(&ex->smp_sema); 1850 if (!ex->smp_req || ex->smp_portal_pid != current->pid) 1851 goto out; 1852 1853 res = 0; 1854 if (size == 0) 1855 goto out; 1856 1857 res = -ENOMEM; 1858 smp_resp = alloc_smp_resp(size); 1859 if (!smp_resp) 1860 goto out; 1861 res = smp_execute_task(dev, ex->smp_req, ex->smp_req_size, 1862 smp_resp, size); 1863 if (!res) { 1864 memcpy(buf, smp_resp, size); 1865 res = size; 1866 } 1867 1868 kfree(smp_resp); 1869 out: 1870 kfree(ex->smp_req); 1871 ex->smp_req = NULL; 1872 ex->smp_req_size = 0; 1873 ex->smp_portal_pid = -1; 1874 up(&ex->smp_sema); 1875 return res; 1876 } 1877 #endif 1878