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/scatterlist.h> 26#include <linux/blkdev.h> 27#include <linux/slab.h> 28 29#include "sas_internal.h" 30 31#include <scsi/sas_ata.h> 32#include <scsi/scsi_transport.h> 33#include <scsi/scsi_transport_sas.h> 34#include "../scsi_sas_internal.h" 35 36static int sas_discover_expander(struct domain_device *dev); 37static int sas_configure_routing(struct domain_device *dev, u8 *sas_addr); 38static int sas_configure_phy(struct domain_device *dev, int phy_id, 39 u8 *sas_addr, int include); 40static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr); 41 42/* ---------- SMP task management ---------- */ 43 44static void smp_task_timedout(unsigned long _task) 45{ 46 struct sas_task *task = (void *) _task; 47 unsigned long flags; 48 49 spin_lock_irqsave(&task->task_state_lock, flags); 50 if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) 51 task->task_state_flags |= SAS_TASK_STATE_ABORTED; 52 spin_unlock_irqrestore(&task->task_state_lock, flags); 53 54 complete(&task->slow_task->completion); 55} 56 57static void smp_task_done(struct sas_task *task) 58{ 59 if (!del_timer(&task->slow_task->timer)) 60 return; 61 complete(&task->slow_task->completion); 62} 63 64/* Give it some long enough timeout. In seconds. */ 65#define SMP_TIMEOUT 10 66 67static int smp_execute_task(struct domain_device *dev, void *req, int req_size, 68 void *resp, int resp_size) 69{ 70 int res, retry; 71 struct sas_task *task = NULL; 72 struct sas_internal *i = 73 to_sas_internal(dev->port->ha->core.shost->transportt); 74 75 mutex_lock(&dev->ex_dev.cmd_mutex); 76 for (retry = 0; retry < 3; retry++) { 77 if (test_bit(SAS_DEV_GONE, &dev->state)) { 78 res = -ECOMM; 79 break; 80 } 81 82 task = sas_alloc_slow_task(GFP_KERNEL); 83 if (!task) { 84 res = -ENOMEM; 85 break; 86 } 87 task->dev = dev; 88 task->task_proto = dev->tproto; 89 sg_init_one(&task->smp_task.smp_req, req, req_size); 90 sg_init_one(&task->smp_task.smp_resp, resp, resp_size); 91 92 task->task_done = smp_task_done; 93 94 task->slow_task->timer.data = (unsigned long) task; 95 task->slow_task->timer.function = smp_task_timedout; 96 task->slow_task->timer.expires = jiffies + SMP_TIMEOUT*HZ; 97 add_timer(&task->slow_task->timer); 98 99 res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); 100 101 if (res) { 102 del_timer(&task->slow_task->timer); 103 SAS_DPRINTK("executing SMP task failed:%d\n", res); 104 break; 105 } 106 107 wait_for_completion(&task->slow_task->completion); 108 res = -ECOMM; 109 if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { 110 SAS_DPRINTK("smp task timed out or aborted\n"); 111 i->dft->lldd_abort_task(task); 112 if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { 113 SAS_DPRINTK("SMP task aborted and not done\n"); 114 break; 115 } 116 } 117 if (task->task_status.resp == SAS_TASK_COMPLETE && 118 task->task_status.stat == SAM_STAT_GOOD) { 119 res = 0; 120 break; 121 } 122 if (task->task_status.resp == SAS_TASK_COMPLETE && 123 task->task_status.stat == SAS_DATA_UNDERRUN) { 124 /* no error, but return the number of bytes of 125 * underrun */ 126 res = task->task_status.residual; 127 break; 128 } 129 if (task->task_status.resp == SAS_TASK_COMPLETE && 130 task->task_status.stat == SAS_DATA_OVERRUN) { 131 res = -EMSGSIZE; 132 break; 133 } 134 if (task->task_status.resp == SAS_TASK_UNDELIVERED && 135 task->task_status.stat == SAS_DEVICE_UNKNOWN) 136 break; 137 else { 138 SAS_DPRINTK("%s: task to dev %016llx response: 0x%x " 139 "status 0x%x\n", __func__, 140 SAS_ADDR(dev->sas_addr), 141 task->task_status.resp, 142 task->task_status.stat); 143 sas_free_task(task); 144 task = NULL; 145 } 146 } 147 mutex_unlock(&dev->ex_dev.cmd_mutex); 148 149 BUG_ON(retry == 3 && task != NULL); 150 sas_free_task(task); 151 return res; 152} 153 154/* ---------- Allocations ---------- */ 155 156static inline void *alloc_smp_req(int size) 157{ 158 u8 *p = kzalloc(size, GFP_KERNEL); 159 if (p) 160 p[0] = SMP_REQUEST; 161 return p; 162} 163 164static inline void *alloc_smp_resp(int size) 165{ 166 return kzalloc(size, GFP_KERNEL); 167} 168 169static char sas_route_char(struct domain_device *dev, struct ex_phy *phy) 170{ 171 switch (phy->routing_attr) { 172 case TABLE_ROUTING: 173 if (dev->ex_dev.t2t_supp) 174 return 'U'; 175 else 176 return 'T'; 177 case DIRECT_ROUTING: 178 return 'D'; 179 case SUBTRACTIVE_ROUTING: 180 return 'S'; 181 default: 182 return '?'; 183 } 184} 185 186static enum sas_device_type to_dev_type(struct discover_resp *dr) 187{ 188 /* This is detecting a failure to transmit initial dev to host 189 * FIS as described in section J.5 of sas-2 r16 190 */ 191 if (dr->attached_dev_type == SAS_PHY_UNUSED && dr->attached_sata_dev && 192 dr->linkrate >= SAS_LINK_RATE_1_5_GBPS) 193 return SAS_SATA_PENDING; 194 else 195 return dr->attached_dev_type; 196} 197 198static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) 199{ 200 enum sas_device_type dev_type; 201 enum sas_linkrate linkrate; 202 u8 sas_addr[SAS_ADDR_SIZE]; 203 struct smp_resp *resp = rsp; 204 struct discover_resp *dr = &resp->disc; 205 struct sas_ha_struct *ha = dev->port->ha; 206 struct expander_device *ex = &dev->ex_dev; 207 struct ex_phy *phy = &ex->ex_phy[phy_id]; 208 struct sas_rphy *rphy = dev->rphy; 209 bool new_phy = !phy->phy; 210 char *type; 211 212 if (new_phy) { 213 if (WARN_ON_ONCE(test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))) 214 return; 215 phy->phy = sas_phy_alloc(&rphy->dev, phy_id); 216 217 /* FIXME: error_handling */ 218 BUG_ON(!phy->phy); 219 } 220 221 switch (resp->result) { 222 case SMP_RESP_PHY_VACANT: 223 phy->phy_state = PHY_VACANT; 224 break; 225 default: 226 phy->phy_state = PHY_NOT_PRESENT; 227 break; 228 case SMP_RESP_FUNC_ACC: 229 phy->phy_state = PHY_EMPTY; /* do not know yet */ 230 break; 231 } 232 233 /* check if anything important changed to squelch debug */ 234 dev_type = phy->attached_dev_type; 235 linkrate = phy->linkrate; 236 memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); 237 238 /* Handle vacant phy - rest of dr data is not valid so skip it */ 239 if (phy->phy_state == PHY_VACANT) { 240 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); 241 phy->attached_dev_type = SAS_PHY_UNUSED; 242 if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) { 243 phy->phy_id = phy_id; 244 goto skip; 245 } else 246 goto out; 247 } 248 249 phy->attached_dev_type = to_dev_type(dr); 250 if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) 251 goto out; 252 phy->phy_id = phy_id; 253 phy->linkrate = dr->linkrate; 254 phy->attached_sata_host = dr->attached_sata_host; 255 phy->attached_sata_dev = dr->attached_sata_dev; 256 phy->attached_sata_ps = dr->attached_sata_ps; 257 phy->attached_iproto = dr->iproto << 1; 258 phy->attached_tproto = dr->tproto << 1; 259 /* help some expanders that fail to zero sas_address in the 'no 260 * device' case 261 */ 262 if (phy->attached_dev_type == SAS_PHY_UNUSED || 263 phy->linkrate < SAS_LINK_RATE_1_5_GBPS) 264 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); 265 else 266 memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE); 267 phy->attached_phy_id = dr->attached_phy_id; 268 phy->phy_change_count = dr->change_count; 269 phy->routing_attr = dr->routing_attr; 270 phy->virtual = dr->virtual; 271 phy->last_da_index = -1; 272 273 phy->phy->identify.sas_address = SAS_ADDR(phy->attached_sas_addr); 274 phy->phy->identify.device_type = dr->attached_dev_type; 275 phy->phy->identify.initiator_port_protocols = phy->attached_iproto; 276 phy->phy->identify.target_port_protocols = phy->attached_tproto; 277 if (!phy->attached_tproto && dr->attached_sata_dev) 278 phy->phy->identify.target_port_protocols = SAS_PROTOCOL_SATA; 279 phy->phy->identify.phy_identifier = phy_id; 280 phy->phy->minimum_linkrate_hw = dr->hmin_linkrate; 281 phy->phy->maximum_linkrate_hw = dr->hmax_linkrate; 282 phy->phy->minimum_linkrate = dr->pmin_linkrate; 283 phy->phy->maximum_linkrate = dr->pmax_linkrate; 284 phy->phy->negotiated_linkrate = phy->linkrate; 285 286 skip: 287 if (new_phy) 288 if (sas_phy_add(phy->phy)) { 289 sas_phy_free(phy->phy); 290 return; 291 } 292 293 out: 294 switch (phy->attached_dev_type) { 295 case SAS_SATA_PENDING: 296 type = "stp pending"; 297 break; 298 case SAS_PHY_UNUSED: 299 type = "no device"; 300 break; 301 case SAS_END_DEVICE: 302 if (phy->attached_iproto) { 303 if (phy->attached_tproto) 304 type = "host+target"; 305 else 306 type = "host"; 307 } else { 308 if (dr->attached_sata_dev) 309 type = "stp"; 310 else 311 type = "ssp"; 312 } 313 break; 314 case SAS_EDGE_EXPANDER_DEVICE: 315 case SAS_FANOUT_EXPANDER_DEVICE: 316 type = "smp"; 317 break; 318 default: 319 type = "unknown"; 320 } 321 322 /* this routine is polled by libata error recovery so filter 323 * unimportant messages 324 */ 325 if (new_phy || phy->attached_dev_type != dev_type || 326 phy->linkrate != linkrate || 327 SAS_ADDR(phy->attached_sas_addr) != SAS_ADDR(sas_addr)) 328 /* pass */; 329 else 330 return; 331 332 /* if the attached device type changed and ata_eh is active, 333 * make sure we run revalidation when eh completes (see: 334 * sas_enable_revalidation) 335 */ 336 if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) 337 set_bit(DISCE_REVALIDATE_DOMAIN, &dev->port->disc.pending); 338 339 SAS_DPRINTK("%sex %016llx phy%02d:%c:%X attached: %016llx (%s)\n", 340 test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state) ? "ata: " : "", 341 SAS_ADDR(dev->sas_addr), phy->phy_id, 342 sas_route_char(dev, phy), phy->linkrate, 343 SAS_ADDR(phy->attached_sas_addr), type); 344} 345 346/* check if we have an existing attached ata device on this expander phy */ 347struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id) 348{ 349 struct ex_phy *ex_phy = &ex_dev->ex_dev.ex_phy[phy_id]; 350 struct domain_device *dev; 351 struct sas_rphy *rphy; 352 353 if (!ex_phy->port) 354 return NULL; 355 356 rphy = ex_phy->port->rphy; 357 if (!rphy) 358 return NULL; 359 360 dev = sas_find_dev_by_rphy(rphy); 361 362 if (dev && dev_is_sata(dev)) 363 return dev; 364 365 return NULL; 366} 367 368#define DISCOVER_REQ_SIZE 16 369#define DISCOVER_RESP_SIZE 56 370 371static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req, 372 u8 *disc_resp, int single) 373{ 374 struct discover_resp *dr; 375 int res; 376 377 disc_req[9] = single; 378 379 res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE, 380 disc_resp, DISCOVER_RESP_SIZE); 381 if (res) 382 return res; 383 dr = &((struct smp_resp *)disc_resp)->disc; 384 if (memcmp(dev->sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE) == 0) { 385 sas_printk("Found loopback topology, just ignore it!\n"); 386 return 0; 387 } 388 sas_set_ex_phy(dev, single, disc_resp); 389 return 0; 390} 391 392int sas_ex_phy_discover(struct domain_device *dev, int single) 393{ 394 struct expander_device *ex = &dev->ex_dev; 395 int res = 0; 396 u8 *disc_req; 397 u8 *disc_resp; 398 399 disc_req = alloc_smp_req(DISCOVER_REQ_SIZE); 400 if (!disc_req) 401 return -ENOMEM; 402 403 disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE); 404 if (!disc_resp) { 405 kfree(disc_req); 406 return -ENOMEM; 407 } 408 409 disc_req[1] = SMP_DISCOVER; 410 411 if (0 <= single && single < ex->num_phys) { 412 res = sas_ex_phy_discover_helper(dev, disc_req, disc_resp, single); 413 } else { 414 int i; 415 416 for (i = 0; i < ex->num_phys; i++) { 417 res = sas_ex_phy_discover_helper(dev, disc_req, 418 disc_resp, i); 419 if (res) 420 goto out_err; 421 } 422 } 423out_err: 424 kfree(disc_resp); 425 kfree(disc_req); 426 return res; 427} 428 429static int sas_expander_discover(struct domain_device *dev) 430{ 431 struct expander_device *ex = &dev->ex_dev; 432 int res = -ENOMEM; 433 434 ex->ex_phy = kzalloc(sizeof(*ex->ex_phy)*ex->num_phys, GFP_KERNEL); 435 if (!ex->ex_phy) 436 return -ENOMEM; 437 438 res = sas_ex_phy_discover(dev, -1); 439 if (res) 440 goto out_err; 441 442 return 0; 443 out_err: 444 kfree(ex->ex_phy); 445 ex->ex_phy = NULL; 446 return res; 447} 448 449#define MAX_EXPANDER_PHYS 128 450 451static void ex_assign_report_general(struct domain_device *dev, 452 struct smp_resp *resp) 453{ 454 struct report_general_resp *rg = &resp->rg; 455 456 dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count); 457 dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes); 458 dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS); 459 dev->ex_dev.t2t_supp = rg->t2t_supp; 460 dev->ex_dev.conf_route_table = rg->conf_route_table; 461 dev->ex_dev.configuring = rg->configuring; 462 memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8); 463} 464 465#define RG_REQ_SIZE 8 466#define RG_RESP_SIZE 32 467 468static int sas_ex_general(struct domain_device *dev) 469{ 470 u8 *rg_req; 471 struct smp_resp *rg_resp; 472 int res; 473 int i; 474 475 rg_req = alloc_smp_req(RG_REQ_SIZE); 476 if (!rg_req) 477 return -ENOMEM; 478 479 rg_resp = alloc_smp_resp(RG_RESP_SIZE); 480 if (!rg_resp) { 481 kfree(rg_req); 482 return -ENOMEM; 483 } 484 485 rg_req[1] = SMP_REPORT_GENERAL; 486 487 for (i = 0; i < 5; i++) { 488 res = smp_execute_task(dev, rg_req, RG_REQ_SIZE, rg_resp, 489 RG_RESP_SIZE); 490 491 if (res) { 492 SAS_DPRINTK("RG to ex %016llx failed:0x%x\n", 493 SAS_ADDR(dev->sas_addr), res); 494 goto out; 495 } else if (rg_resp->result != SMP_RESP_FUNC_ACC) { 496 SAS_DPRINTK("RG:ex %016llx returned SMP result:0x%x\n", 497 SAS_ADDR(dev->sas_addr), rg_resp->result); 498 res = rg_resp->result; 499 goto out; 500 } 501 502 ex_assign_report_general(dev, rg_resp); 503 504 if (dev->ex_dev.configuring) { 505 SAS_DPRINTK("RG: ex %llx self-configuring...\n", 506 SAS_ADDR(dev->sas_addr)); 507 schedule_timeout_interruptible(5*HZ); 508 } else 509 break; 510 } 511out: 512 kfree(rg_req); 513 kfree(rg_resp); 514 return res; 515} 516 517static void ex_assign_manuf_info(struct domain_device *dev, void 518 *_mi_resp) 519{ 520 u8 *mi_resp = _mi_resp; 521 struct sas_rphy *rphy = dev->rphy; 522 struct sas_expander_device *edev = rphy_to_expander_device(rphy); 523 524 memcpy(edev->vendor_id, mi_resp + 12, SAS_EXPANDER_VENDOR_ID_LEN); 525 memcpy(edev->product_id, mi_resp + 20, SAS_EXPANDER_PRODUCT_ID_LEN); 526 memcpy(edev->product_rev, mi_resp + 36, 527 SAS_EXPANDER_PRODUCT_REV_LEN); 528 529 if (mi_resp[8] & 1) { 530 memcpy(edev->component_vendor_id, mi_resp + 40, 531 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN); 532 edev->component_id = mi_resp[48] << 8 | mi_resp[49]; 533 edev->component_revision_id = mi_resp[50]; 534 } 535} 536 537#define MI_REQ_SIZE 8 538#define MI_RESP_SIZE 64 539 540static int sas_ex_manuf_info(struct domain_device *dev) 541{ 542 u8 *mi_req; 543 u8 *mi_resp; 544 int res; 545 546 mi_req = alloc_smp_req(MI_REQ_SIZE); 547 if (!mi_req) 548 return -ENOMEM; 549 550 mi_resp = alloc_smp_resp(MI_RESP_SIZE); 551 if (!mi_resp) { 552 kfree(mi_req); 553 return -ENOMEM; 554 } 555 556 mi_req[1] = SMP_REPORT_MANUF_INFO; 557 558 res = smp_execute_task(dev, mi_req, MI_REQ_SIZE, mi_resp,MI_RESP_SIZE); 559 if (res) { 560 SAS_DPRINTK("MI: ex %016llx failed:0x%x\n", 561 SAS_ADDR(dev->sas_addr), res); 562 goto out; 563 } else if (mi_resp[2] != SMP_RESP_FUNC_ACC) { 564 SAS_DPRINTK("MI ex %016llx returned SMP result:0x%x\n", 565 SAS_ADDR(dev->sas_addr), mi_resp[2]); 566 goto out; 567 } 568 569 ex_assign_manuf_info(dev, mi_resp); 570out: 571 kfree(mi_req); 572 kfree(mi_resp); 573 return res; 574} 575 576#define PC_REQ_SIZE 44 577#define PC_RESP_SIZE 8 578 579int sas_smp_phy_control(struct domain_device *dev, int phy_id, 580 enum phy_func phy_func, 581 struct sas_phy_linkrates *rates) 582{ 583 u8 *pc_req; 584 u8 *pc_resp; 585 int res; 586 587 pc_req = alloc_smp_req(PC_REQ_SIZE); 588 if (!pc_req) 589 return -ENOMEM; 590 591 pc_resp = alloc_smp_resp(PC_RESP_SIZE); 592 if (!pc_resp) { 593 kfree(pc_req); 594 return -ENOMEM; 595 } 596 597 pc_req[1] = SMP_PHY_CONTROL; 598 pc_req[9] = phy_id; 599 pc_req[10]= phy_func; 600 if (rates) { 601 pc_req[32] = rates->minimum_linkrate << 4; 602 pc_req[33] = rates->maximum_linkrate << 4; 603 } 604 605 res = smp_execute_task(dev, pc_req, PC_REQ_SIZE, pc_resp,PC_RESP_SIZE); 606 607 kfree(pc_resp); 608 kfree(pc_req); 609 return res; 610} 611 612static void sas_ex_disable_phy(struct domain_device *dev, int phy_id) 613{ 614 struct expander_device *ex = &dev->ex_dev; 615 struct ex_phy *phy = &ex->ex_phy[phy_id]; 616 617 sas_smp_phy_control(dev, phy_id, PHY_FUNC_DISABLE, NULL); 618 phy->linkrate = SAS_PHY_DISABLED; 619} 620 621static void sas_ex_disable_port(struct domain_device *dev, u8 *sas_addr) 622{ 623 struct expander_device *ex = &dev->ex_dev; 624 int i; 625 626 for (i = 0; i < ex->num_phys; i++) { 627 struct ex_phy *phy = &ex->ex_phy[i]; 628 629 if (phy->phy_state == PHY_VACANT || 630 phy->phy_state == PHY_NOT_PRESENT) 631 continue; 632 633 if (SAS_ADDR(phy->attached_sas_addr) == SAS_ADDR(sas_addr)) 634 sas_ex_disable_phy(dev, i); 635 } 636} 637 638static int sas_dev_present_in_domain(struct asd_sas_port *port, 639 u8 *sas_addr) 640{ 641 struct domain_device *dev; 642 643 if (SAS_ADDR(port->sas_addr) == SAS_ADDR(sas_addr)) 644 return 1; 645 list_for_each_entry(dev, &port->dev_list, dev_list_node) { 646 if (SAS_ADDR(dev->sas_addr) == SAS_ADDR(sas_addr)) 647 return 1; 648 } 649 return 0; 650} 651 652#define RPEL_REQ_SIZE 16 653#define RPEL_RESP_SIZE 32 654int sas_smp_get_phy_events(struct sas_phy *phy) 655{ 656 int res; 657 u8 *req; 658 u8 *resp; 659 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); 660 struct domain_device *dev = sas_find_dev_by_rphy(rphy); 661 662 req = alloc_smp_req(RPEL_REQ_SIZE); 663 if (!req) 664 return -ENOMEM; 665 666 resp = alloc_smp_resp(RPEL_RESP_SIZE); 667 if (!resp) { 668 kfree(req); 669 return -ENOMEM; 670 } 671 672 req[1] = SMP_REPORT_PHY_ERR_LOG; 673 req[9] = phy->number; 674 675 res = smp_execute_task(dev, req, RPEL_REQ_SIZE, 676 resp, RPEL_RESP_SIZE); 677 678 if (!res) 679 goto out; 680 681 phy->invalid_dword_count = scsi_to_u32(&resp[12]); 682 phy->running_disparity_error_count = scsi_to_u32(&resp[16]); 683 phy->loss_of_dword_sync_count = scsi_to_u32(&resp[20]); 684 phy->phy_reset_problem_count = scsi_to_u32(&resp[24]); 685 686 out: 687 kfree(resp); 688 return res; 689 690} 691 692#ifdef CONFIG_SCSI_SAS_ATA 693 694#define RPS_REQ_SIZE 16 695#define RPS_RESP_SIZE 60 696 697int sas_get_report_phy_sata(struct domain_device *dev, int phy_id, 698 struct smp_resp *rps_resp) 699{ 700 int res; 701 u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE); 702 u8 *resp = (u8 *)rps_resp; 703 704 if (!rps_req) 705 return -ENOMEM; 706 707 rps_req[1] = SMP_REPORT_PHY_SATA; 708 rps_req[9] = phy_id; 709 710 res = smp_execute_task(dev, rps_req, RPS_REQ_SIZE, 711 rps_resp, RPS_RESP_SIZE); 712 713 /* 0x34 is the FIS type for the D2H fis. There's a potential 714 * standards cockup here. sas-2 explicitly specifies the FIS 715 * should be encoded so that FIS type is in resp[24]. 716 * However, some expanders endian reverse this. Undo the 717 * reversal here */ 718 if (!res && resp[27] == 0x34 && resp[24] != 0x34) { 719 int i; 720 721 for (i = 0; i < 5; i++) { 722 int j = 24 + (i*4); 723 u8 a, b; 724 a = resp[j + 0]; 725 b = resp[j + 1]; 726 resp[j + 0] = resp[j + 3]; 727 resp[j + 1] = resp[j + 2]; 728 resp[j + 2] = b; 729 resp[j + 3] = a; 730 } 731 } 732 733 kfree(rps_req); 734 return res; 735} 736#endif 737 738static void sas_ex_get_linkrate(struct domain_device *parent, 739 struct domain_device *child, 740 struct ex_phy *parent_phy) 741{ 742 struct expander_device *parent_ex = &parent->ex_dev; 743 struct sas_port *port; 744 int i; 745 746 child->pathways = 0; 747 748 port = parent_phy->port; 749 750 for (i = 0; i < parent_ex->num_phys; i++) { 751 struct ex_phy *phy = &parent_ex->ex_phy[i]; 752 753 if (phy->phy_state == PHY_VACANT || 754 phy->phy_state == PHY_NOT_PRESENT) 755 continue; 756 757 if (SAS_ADDR(phy->attached_sas_addr) == 758 SAS_ADDR(child->sas_addr)) { 759 760 child->min_linkrate = min(parent->min_linkrate, 761 phy->linkrate); 762 child->max_linkrate = max(parent->max_linkrate, 763 phy->linkrate); 764 child->pathways++; 765 sas_port_add_phy(port, phy->phy); 766 } 767 } 768 child->linkrate = min(parent_phy->linkrate, child->max_linkrate); 769 child->pathways = min(child->pathways, parent->pathways); 770} 771 772static struct domain_device *sas_ex_discover_end_dev( 773 struct domain_device *parent, int phy_id) 774{ 775 struct expander_device *parent_ex = &parent->ex_dev; 776 struct ex_phy *phy = &parent_ex->ex_phy[phy_id]; 777 struct domain_device *child = NULL; 778 struct sas_rphy *rphy; 779 int res; 780 781 if (phy->attached_sata_host || phy->attached_sata_ps) 782 return NULL; 783 784 child = sas_alloc_device(); 785 if (!child) 786 return NULL; 787 788 kref_get(&parent->kref); 789 child->parent = parent; 790 child->port = parent->port; 791 child->iproto = phy->attached_iproto; 792 memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); 793 sas_hash_addr(child->hashed_sas_addr, child->sas_addr); 794 if (!phy->port) { 795 phy->port = sas_port_alloc(&parent->rphy->dev, phy_id); 796 if (unlikely(!phy->port)) 797 goto out_err; 798 if (unlikely(sas_port_add(phy->port) != 0)) { 799 sas_port_free(phy->port); 800 goto out_err; 801 } 802 } 803 sas_ex_get_linkrate(parent, child, phy); 804 sas_device_set_phy(child, phy->port); 805 806#ifdef CONFIG_SCSI_SAS_ATA 807 if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) { 808 res = sas_get_ata_info(child, phy); 809 if (res) 810 goto out_free; 811 812 sas_init_dev(child); 813 res = sas_ata_init(child); 814 if (res) 815 goto out_free; 816 rphy = sas_end_device_alloc(phy->port); 817 if (!rphy) 818 goto out_free; 819 820 child->rphy = rphy; 821 get_device(&rphy->dev); 822 823 list_add_tail(&child->disco_list_node, &parent->port->disco_list); 824 825 res = sas_discover_sata(child); 826 if (res) { 827 SAS_DPRINTK("sas_discover_sata() for device %16llx at " 828 "%016llx:0x%x returned 0x%x\n", 829 SAS_ADDR(child->sas_addr), 830 SAS_ADDR(parent->sas_addr), phy_id, res); 831 goto out_list_del; 832 } 833 } else 834#endif 835 if (phy->attached_tproto & SAS_PROTOCOL_SSP) { 836 child->dev_type = SAS_END_DEVICE; 837 rphy = sas_end_device_alloc(phy->port); 838 /* FIXME: error handling */ 839 if (unlikely(!rphy)) 840 goto out_free; 841 child->tproto = phy->attached_tproto; 842 sas_init_dev(child); 843 844 child->rphy = rphy; 845 get_device(&rphy->dev); 846 sas_fill_in_rphy(child, rphy); 847 848 list_add_tail(&child->disco_list_node, &parent->port->disco_list); 849 850 res = sas_discover_end_dev(child); 851 if (res) { 852 SAS_DPRINTK("sas_discover_end_dev() for device %16llx " 853 "at %016llx:0x%x returned 0x%x\n", 854 SAS_ADDR(child->sas_addr), 855 SAS_ADDR(parent->sas_addr), phy_id, res); 856 goto out_list_del; 857 } 858 } else { 859 SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", 860 phy->attached_tproto, SAS_ADDR(parent->sas_addr), 861 phy_id); 862 goto out_free; 863 } 864 865 list_add_tail(&child->siblings, &parent_ex->children); 866 return child; 867 868 out_list_del: 869 sas_rphy_free(child->rphy); 870 list_del(&child->disco_list_node); 871 spin_lock_irq(&parent->port->dev_list_lock); 872 list_del(&child->dev_list_node); 873 spin_unlock_irq(&parent->port->dev_list_lock); 874 out_free: 875 sas_port_delete(phy->port); 876 out_err: 877 phy->port = NULL; 878 sas_put_device(child); 879 return NULL; 880} 881 882/* See if this phy is part of a wide port */ 883static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id) 884{ 885 struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id]; 886 int i; 887 888 for (i = 0; i < parent->ex_dev.num_phys; i++) { 889 struct ex_phy *ephy = &parent->ex_dev.ex_phy[i]; 890 891 if (ephy == phy) 892 continue; 893 894 if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr, 895 SAS_ADDR_SIZE) && ephy->port) { 896 sas_port_add_phy(ephy->port, phy->phy); 897 phy->port = ephy->port; 898 phy->phy_state = PHY_DEVICE_DISCOVERED; 899 return true; 900 } 901 } 902 903 return false; 904} 905 906static struct domain_device *sas_ex_discover_expander( 907 struct domain_device *parent, int phy_id) 908{ 909 struct sas_expander_device *parent_ex = rphy_to_expander_device(parent->rphy); 910 struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id]; 911 struct domain_device *child = NULL; 912 struct sas_rphy *rphy; 913 struct sas_expander_device *edev; 914 struct asd_sas_port *port; 915 int res; 916 917 if (phy->routing_attr == DIRECT_ROUTING) { 918 SAS_DPRINTK("ex %016llx:0x%x:D <--> ex %016llx:0x%x is not " 919 "allowed\n", 920 SAS_ADDR(parent->sas_addr), phy_id, 921 SAS_ADDR(phy->attached_sas_addr), 922 phy->attached_phy_id); 923 return NULL; 924 } 925 child = sas_alloc_device(); 926 if (!child) 927 return NULL; 928 929 phy->port = sas_port_alloc(&parent->rphy->dev, phy_id); 930 /* FIXME: better error handling */ 931 BUG_ON(sas_port_add(phy->port) != 0); 932 933 934 switch (phy->attached_dev_type) { 935 case SAS_EDGE_EXPANDER_DEVICE: 936 rphy = sas_expander_alloc(phy->port, 937 SAS_EDGE_EXPANDER_DEVICE); 938 break; 939 case SAS_FANOUT_EXPANDER_DEVICE: 940 rphy = sas_expander_alloc(phy->port, 941 SAS_FANOUT_EXPANDER_DEVICE); 942 break; 943 default: 944 rphy = NULL; /* shut gcc up */ 945 BUG(); 946 } 947 port = parent->port; 948 child->rphy = rphy; 949 get_device(&rphy->dev); 950 edev = rphy_to_expander_device(rphy); 951 child->dev_type = phy->attached_dev_type; 952 kref_get(&parent->kref); 953 child->parent = parent; 954 child->port = port; 955 child->iproto = phy->attached_iproto; 956 child->tproto = phy->attached_tproto; 957 memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); 958 sas_hash_addr(child->hashed_sas_addr, child->sas_addr); 959 sas_ex_get_linkrate(parent, child, phy); 960 edev->level = parent_ex->level + 1; 961 parent->port->disc.max_level = max(parent->port->disc.max_level, 962 edev->level); 963 sas_init_dev(child); 964 sas_fill_in_rphy(child, rphy); 965 sas_rphy_add(rphy); 966 967 spin_lock_irq(&parent->port->dev_list_lock); 968 list_add_tail(&child->dev_list_node, &parent->port->dev_list); 969 spin_unlock_irq(&parent->port->dev_list_lock); 970 971 res = sas_discover_expander(child); 972 if (res) { 973 sas_rphy_delete(rphy); 974 spin_lock_irq(&parent->port->dev_list_lock); 975 list_del(&child->dev_list_node); 976 spin_unlock_irq(&parent->port->dev_list_lock); 977 sas_put_device(child); 978 return NULL; 979 } 980 list_add_tail(&child->siblings, &parent->ex_dev.children); 981 return child; 982} 983 984static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) 985{ 986 struct expander_device *ex = &dev->ex_dev; 987 struct ex_phy *ex_phy = &ex->ex_phy[phy_id]; 988 struct domain_device *child = NULL; 989 int res = 0; 990 991 /* Phy state */ 992 if (ex_phy->linkrate == SAS_SATA_SPINUP_HOLD) { 993 if (!sas_smp_phy_control(dev, phy_id, PHY_FUNC_LINK_RESET, NULL)) 994 res = sas_ex_phy_discover(dev, phy_id); 995 if (res) 996 return res; 997 } 998 999 /* Parent and domain coherency */ 1000 if (!dev->parent && (SAS_ADDR(ex_phy->attached_sas_addr) == 1001 SAS_ADDR(dev->port->sas_addr))) { 1002 sas_add_parent_port(dev, phy_id); 1003 return 0; 1004 } 1005 if (dev->parent && (SAS_ADDR(ex_phy->attached_sas_addr) == 1006 SAS_ADDR(dev->parent->sas_addr))) { 1007 sas_add_parent_port(dev, phy_id); 1008 if (ex_phy->routing_attr == TABLE_ROUTING) 1009 sas_configure_phy(dev, phy_id, dev->port->sas_addr, 1); 1010 return 0; 1011 } 1012 1013 if (sas_dev_present_in_domain(dev->port, ex_phy->attached_sas_addr)) 1014 sas_ex_disable_port(dev, ex_phy->attached_sas_addr); 1015 1016 if (ex_phy->attached_dev_type == SAS_PHY_UNUSED) { 1017 if (ex_phy->routing_attr == DIRECT_ROUTING) { 1018 memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE); 1019 sas_configure_routing(dev, ex_phy->attached_sas_addr); 1020 } 1021 return 0; 1022 } else if (ex_phy->linkrate == SAS_LINK_RATE_UNKNOWN) 1023 return 0; 1024 1025 if (ex_phy->attached_dev_type != SAS_END_DEVICE && 1026 ex_phy->attached_dev_type != SAS_FANOUT_EXPANDER_DEVICE && 1027 ex_phy->attached_dev_type != SAS_EDGE_EXPANDER_DEVICE && 1028 ex_phy->attached_dev_type != SAS_SATA_PENDING) { 1029 SAS_DPRINTK("unknown device type(0x%x) attached to ex %016llx " 1030 "phy 0x%x\n", ex_phy->attached_dev_type, 1031 SAS_ADDR(dev->sas_addr), 1032 phy_id); 1033 return 0; 1034 } 1035 1036 res = sas_configure_routing(dev, ex_phy->attached_sas_addr); 1037 if (res) { 1038 SAS_DPRINTK("configure routing for dev %016llx " 1039 "reported 0x%x. Forgotten\n", 1040 SAS_ADDR(ex_phy->attached_sas_addr), res); 1041 sas_disable_routing(dev, ex_phy->attached_sas_addr); 1042 return res; 1043 } 1044 1045 if (sas_ex_join_wide_port(dev, phy_id)) { 1046 SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", 1047 phy_id, SAS_ADDR(ex_phy->attached_sas_addr)); 1048 return res; 1049 } 1050 1051 switch (ex_phy->attached_dev_type) { 1052 case SAS_END_DEVICE: 1053 case SAS_SATA_PENDING: 1054 child = sas_ex_discover_end_dev(dev, phy_id); 1055 break; 1056 case SAS_FANOUT_EXPANDER_DEVICE: 1057 if (SAS_ADDR(dev->port->disc.fanout_sas_addr)) { 1058 SAS_DPRINTK("second fanout expander %016llx phy 0x%x " 1059 "attached to ex %016llx phy 0x%x\n", 1060 SAS_ADDR(ex_phy->attached_sas_addr), 1061 ex_phy->attached_phy_id, 1062 SAS_ADDR(dev->sas_addr), 1063 phy_id); 1064 sas_ex_disable_phy(dev, phy_id); 1065 break; 1066 } else 1067 memcpy(dev->port->disc.fanout_sas_addr, 1068 ex_phy->attached_sas_addr, SAS_ADDR_SIZE); 1069 /* fallthrough */ 1070 case SAS_EDGE_EXPANDER_DEVICE: 1071 child = sas_ex_discover_expander(dev, phy_id); 1072 break; 1073 default: 1074 break; 1075 } 1076 1077 if (child) { 1078 int i; 1079 1080 for (i = 0; i < ex->num_phys; i++) { 1081 if (ex->ex_phy[i].phy_state == PHY_VACANT || 1082 ex->ex_phy[i].phy_state == PHY_NOT_PRESENT) 1083 continue; 1084 /* 1085 * Due to races, the phy might not get added to the 1086 * wide port, so we add the phy to the wide port here. 1087 */ 1088 if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == 1089 SAS_ADDR(child->sas_addr)) { 1090 ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; 1091 if (sas_ex_join_wide_port(dev, i)) 1092 SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", 1093 i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr)); 1094 1095 } 1096 } 1097 } 1098 1099 return res; 1100} 1101 1102static int sas_find_sub_addr(struct domain_device *dev, u8 *sub_addr) 1103{ 1104 struct expander_device *ex = &dev->ex_dev; 1105 int i; 1106 1107 for (i = 0; i < ex->num_phys; i++) { 1108 struct ex_phy *phy = &ex->ex_phy[i]; 1109 1110 if (phy->phy_state == PHY_VACANT || 1111 phy->phy_state == PHY_NOT_PRESENT) 1112 continue; 1113 1114 if ((phy->attached_dev_type == SAS_EDGE_EXPANDER_DEVICE || 1115 phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE) && 1116 phy->routing_attr == SUBTRACTIVE_ROUTING) { 1117 1118 memcpy(sub_addr, phy->attached_sas_addr,SAS_ADDR_SIZE); 1119 1120 return 1; 1121 } 1122 } 1123 return 0; 1124} 1125 1126static int sas_check_level_subtractive_boundary(struct domain_device *dev) 1127{ 1128 struct expander_device *ex = &dev->ex_dev; 1129 struct domain_device *child; 1130 u8 sub_addr[8] = {0, }; 1131 1132 list_for_each_entry(child, &ex->children, siblings) { 1133 if (child->dev_type != SAS_EDGE_EXPANDER_DEVICE && 1134 child->dev_type != SAS_FANOUT_EXPANDER_DEVICE) 1135 continue; 1136 if (sub_addr[0] == 0) { 1137 sas_find_sub_addr(child, sub_addr); 1138 continue; 1139 } else { 1140 u8 s2[8]; 1141 1142 if (sas_find_sub_addr(child, s2) && 1143 (SAS_ADDR(sub_addr) != SAS_ADDR(s2))) { 1144 1145 SAS_DPRINTK("ex %016llx->%016llx-?->%016llx " 1146 "diverges from subtractive " 1147 "boundary %016llx\n", 1148 SAS_ADDR(dev->sas_addr), 1149 SAS_ADDR(child->sas_addr), 1150 SAS_ADDR(s2), 1151 SAS_ADDR(sub_addr)); 1152 1153 sas_ex_disable_port(child, s2); 1154 } 1155 } 1156 } 1157 return 0; 1158} 1159/** 1160 * sas_ex_discover_devices -- discover devices attached to this expander 1161 * dev: pointer to the expander domain device 1162 * single: if you want to do a single phy, else set to -1; 1163 * 1164 * Configure this expander for use with its devices and register the 1165 * devices of this expander. 1166 */ 1167static int sas_ex_discover_devices(struct domain_device *dev, int single) 1168{ 1169 struct expander_device *ex = &dev->ex_dev; 1170 int i = 0, end = ex->num_phys; 1171 int res = 0; 1172 1173 if (0 <= single && single < end) { 1174 i = single; 1175 end = i+1; 1176 } 1177 1178 for ( ; i < end; i++) { 1179 struct ex_phy *ex_phy = &ex->ex_phy[i]; 1180 1181 if (ex_phy->phy_state == PHY_VACANT || 1182 ex_phy->phy_state == PHY_NOT_PRESENT || 1183 ex_phy->phy_state == PHY_DEVICE_DISCOVERED) 1184 continue; 1185 1186 switch (ex_phy->linkrate) { 1187 case SAS_PHY_DISABLED: 1188 case SAS_PHY_RESET_PROBLEM: 1189 case SAS_SATA_PORT_SELECTOR: 1190 continue; 1191 default: 1192 res = sas_ex_discover_dev(dev, i); 1193 if (res) 1194 break; 1195 continue; 1196 } 1197 } 1198 1199 if (!res) 1200 sas_check_level_subtractive_boundary(dev); 1201 1202 return res; 1203} 1204 1205static int sas_check_ex_subtractive_boundary(struct domain_device *dev) 1206{ 1207 struct expander_device *ex = &dev->ex_dev; 1208 int i; 1209 u8 *sub_sas_addr = NULL; 1210 1211 if (dev->dev_type != SAS_EDGE_EXPANDER_DEVICE) 1212 return 0; 1213 1214 for (i = 0; i < ex->num_phys; i++) { 1215 struct ex_phy *phy = &ex->ex_phy[i]; 1216 1217 if (phy->phy_state == PHY_VACANT || 1218 phy->phy_state == PHY_NOT_PRESENT) 1219 continue; 1220 1221 if ((phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE || 1222 phy->attached_dev_type == SAS_EDGE_EXPANDER_DEVICE) && 1223 phy->routing_attr == SUBTRACTIVE_ROUTING) { 1224 1225 if (!sub_sas_addr) 1226 sub_sas_addr = &phy->attached_sas_addr[0]; 1227 else if (SAS_ADDR(sub_sas_addr) != 1228 SAS_ADDR(phy->attached_sas_addr)) { 1229 1230 SAS_DPRINTK("ex %016llx phy 0x%x " 1231 "diverges(%016llx) on subtractive " 1232 "boundary(%016llx). Disabled\n", 1233 SAS_ADDR(dev->sas_addr), i, 1234 SAS_ADDR(phy->attached_sas_addr), 1235 SAS_ADDR(sub_sas_addr)); 1236 sas_ex_disable_phy(dev, i); 1237 } 1238 } 1239 } 1240 return 0; 1241} 1242 1243static void sas_print_parent_topology_bug(struct domain_device *child, 1244 struct ex_phy *parent_phy, 1245 struct ex_phy *child_phy) 1246{ 1247 static const char *ex_type[] = { 1248 [SAS_EDGE_EXPANDER_DEVICE] = "edge", 1249 [SAS_FANOUT_EXPANDER_DEVICE] = "fanout", 1250 }; 1251 struct domain_device *parent = child->parent; 1252 1253 sas_printk("%s ex %016llx phy 0x%x <--> %s ex %016llx " 1254 "phy 0x%x has %c:%c routing link!\n", 1255 1256 ex_type[parent->dev_type], 1257 SAS_ADDR(parent->sas_addr), 1258 parent_phy->phy_id, 1259 1260 ex_type[child->dev_type], 1261 SAS_ADDR(child->sas_addr), 1262 child_phy->phy_id, 1263 1264 sas_route_char(parent, parent_phy), 1265 sas_route_char(child, child_phy)); 1266} 1267 1268static int sas_check_eeds(struct domain_device *child, 1269 struct ex_phy *parent_phy, 1270 struct ex_phy *child_phy) 1271{ 1272 int res = 0; 1273 struct domain_device *parent = child->parent; 1274 1275 if (SAS_ADDR(parent->port->disc.fanout_sas_addr) != 0) { 1276 res = -ENODEV; 1277 SAS_DPRINTK("edge ex %016llx phy S:0x%x <--> edge ex %016llx " 1278 "phy S:0x%x, while there is a fanout ex %016llx\n", 1279 SAS_ADDR(parent->sas_addr), 1280 parent_phy->phy_id, 1281 SAS_ADDR(child->sas_addr), 1282 child_phy->phy_id, 1283 SAS_ADDR(parent->port->disc.fanout_sas_addr)); 1284 } else if (SAS_ADDR(parent->port->disc.eeds_a) == 0) { 1285 memcpy(parent->port->disc.eeds_a, parent->sas_addr, 1286 SAS_ADDR_SIZE); 1287 memcpy(parent->port->disc.eeds_b, child->sas_addr, 1288 SAS_ADDR_SIZE); 1289 } else if (((SAS_ADDR(parent->port->disc.eeds_a) == 1290 SAS_ADDR(parent->sas_addr)) || 1291 (SAS_ADDR(parent->port->disc.eeds_a) == 1292 SAS_ADDR(child->sas_addr))) 1293 && 1294 ((SAS_ADDR(parent->port->disc.eeds_b) == 1295 SAS_ADDR(parent->sas_addr)) || 1296 (SAS_ADDR(parent->port->disc.eeds_b) == 1297 SAS_ADDR(child->sas_addr)))) 1298 ; 1299 else { 1300 res = -ENODEV; 1301 SAS_DPRINTK("edge ex %016llx phy 0x%x <--> edge ex %016llx " 1302 "phy 0x%x link forms a third EEDS!\n", 1303 SAS_ADDR(parent->sas_addr), 1304 parent_phy->phy_id, 1305 SAS_ADDR(child->sas_addr), 1306 child_phy->phy_id); 1307 } 1308 1309 return res; 1310} 1311 1312/* Here we spill over 80 columns. It is intentional. 1313 */ 1314static int sas_check_parent_topology(struct domain_device *child) 1315{ 1316 struct expander_device *child_ex = &child->ex_dev; 1317 struct expander_device *parent_ex; 1318 int i; 1319 int res = 0; 1320 1321 if (!child->parent) 1322 return 0; 1323 1324 if (child->parent->dev_type != SAS_EDGE_EXPANDER_DEVICE && 1325 child->parent->dev_type != SAS_FANOUT_EXPANDER_DEVICE) 1326 return 0; 1327 1328 parent_ex = &child->parent->ex_dev; 1329 1330 for (i = 0; i < parent_ex->num_phys; i++) { 1331 struct ex_phy *parent_phy = &parent_ex->ex_phy[i]; 1332 struct ex_phy *child_phy; 1333 1334 if (parent_phy->phy_state == PHY_VACANT || 1335 parent_phy->phy_state == PHY_NOT_PRESENT) 1336 continue; 1337 1338 if (SAS_ADDR(parent_phy->attached_sas_addr) != SAS_ADDR(child->sas_addr)) 1339 continue; 1340 1341 child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id]; 1342 1343 switch (child->parent->dev_type) { 1344 case SAS_EDGE_EXPANDER_DEVICE: 1345 if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { 1346 if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING || 1347 child_phy->routing_attr != TABLE_ROUTING) { 1348 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1349 res = -ENODEV; 1350 } 1351 } else if (parent_phy->routing_attr == SUBTRACTIVE_ROUTING) { 1352 if (child_phy->routing_attr == SUBTRACTIVE_ROUTING) { 1353 res = sas_check_eeds(child, parent_phy, child_phy); 1354 } else if (child_phy->routing_attr != TABLE_ROUTING) { 1355 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1356 res = -ENODEV; 1357 } 1358 } else if (parent_phy->routing_attr == TABLE_ROUTING) { 1359 if (child_phy->routing_attr == SUBTRACTIVE_ROUTING || 1360 (child_phy->routing_attr == TABLE_ROUTING && 1361 child_ex->t2t_supp && parent_ex->t2t_supp)) { 1362 /* All good */; 1363 } else { 1364 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1365 res = -ENODEV; 1366 } 1367 } 1368 break; 1369 case SAS_FANOUT_EXPANDER_DEVICE: 1370 if (parent_phy->routing_attr != TABLE_ROUTING || 1371 child_phy->routing_attr != SUBTRACTIVE_ROUTING) { 1372 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1373 res = -ENODEV; 1374 } 1375 break; 1376 default: 1377 break; 1378 } 1379 } 1380 1381 return res; 1382} 1383 1384#define RRI_REQ_SIZE 16 1385#define RRI_RESP_SIZE 44 1386 1387static int sas_configure_present(struct domain_device *dev, int phy_id, 1388 u8 *sas_addr, int *index, int *present) 1389{ 1390 int i, res = 0; 1391 struct expander_device *ex = &dev->ex_dev; 1392 struct ex_phy *phy = &ex->ex_phy[phy_id]; 1393 u8 *rri_req; 1394 u8 *rri_resp; 1395 1396 *present = 0; 1397 *index = 0; 1398 1399 rri_req = alloc_smp_req(RRI_REQ_SIZE); 1400 if (!rri_req) 1401 return -ENOMEM; 1402 1403 rri_resp = alloc_smp_resp(RRI_RESP_SIZE); 1404 if (!rri_resp) { 1405 kfree(rri_req); 1406 return -ENOMEM; 1407 } 1408 1409 rri_req[1] = SMP_REPORT_ROUTE_INFO; 1410 rri_req[9] = phy_id; 1411 1412 for (i = 0; i < ex->max_route_indexes ; i++) { 1413 *(__be16 *)(rri_req+6) = cpu_to_be16(i); 1414 res = smp_execute_task(dev, rri_req, RRI_REQ_SIZE, rri_resp, 1415 RRI_RESP_SIZE); 1416 if (res) 1417 goto out; 1418 res = rri_resp[2]; 1419 if (res == SMP_RESP_NO_INDEX) { 1420 SAS_DPRINTK("overflow of indexes: dev %016llx " 1421 "phy 0x%x index 0x%x\n", 1422 SAS_ADDR(dev->sas_addr), phy_id, i); 1423 goto out; 1424 } else if (res != SMP_RESP_FUNC_ACC) { 1425 SAS_DPRINTK("%s: dev %016llx phy 0x%x index 0x%x " 1426 "result 0x%x\n", __func__, 1427 SAS_ADDR(dev->sas_addr), phy_id, i, res); 1428 goto out; 1429 } 1430 if (SAS_ADDR(sas_addr) != 0) { 1431 if (SAS_ADDR(rri_resp+16) == SAS_ADDR(sas_addr)) { 1432 *index = i; 1433 if ((rri_resp[12] & 0x80) == 0x80) 1434 *present = 0; 1435 else 1436 *present = 1; 1437 goto out; 1438 } else if (SAS_ADDR(rri_resp+16) == 0) { 1439 *index = i; 1440 *present = 0; 1441 goto out; 1442 } 1443 } else if (SAS_ADDR(rri_resp+16) == 0 && 1444 phy->last_da_index < i) { 1445 phy->last_da_index = i; 1446 *index = i; 1447 *present = 0; 1448 goto out; 1449 } 1450 } 1451 res = -1; 1452out: 1453 kfree(rri_req); 1454 kfree(rri_resp); 1455 return res; 1456} 1457 1458#define CRI_REQ_SIZE 44 1459#define CRI_RESP_SIZE 8 1460 1461static int sas_configure_set(struct domain_device *dev, int phy_id, 1462 u8 *sas_addr, int index, int include) 1463{ 1464 int res; 1465 u8 *cri_req; 1466 u8 *cri_resp; 1467 1468 cri_req = alloc_smp_req(CRI_REQ_SIZE); 1469 if (!cri_req) 1470 return -ENOMEM; 1471 1472 cri_resp = alloc_smp_resp(CRI_RESP_SIZE); 1473 if (!cri_resp) { 1474 kfree(cri_req); 1475 return -ENOMEM; 1476 } 1477 1478 cri_req[1] = SMP_CONF_ROUTE_INFO; 1479 *(__be16 *)(cri_req+6) = cpu_to_be16(index); 1480 cri_req[9] = phy_id; 1481 if (SAS_ADDR(sas_addr) == 0 || !include) 1482 cri_req[12] |= 0x80; 1483 memcpy(cri_req+16, sas_addr, SAS_ADDR_SIZE); 1484 1485 res = smp_execute_task(dev, cri_req, CRI_REQ_SIZE, cri_resp, 1486 CRI_RESP_SIZE); 1487 if (res) 1488 goto out; 1489 res = cri_resp[2]; 1490 if (res == SMP_RESP_NO_INDEX) { 1491 SAS_DPRINTK("overflow of indexes: dev %016llx phy 0x%x " 1492 "index 0x%x\n", 1493 SAS_ADDR(dev->sas_addr), phy_id, index); 1494 } 1495out: 1496 kfree(cri_req); 1497 kfree(cri_resp); 1498 return res; 1499} 1500 1501static int sas_configure_phy(struct domain_device *dev, int phy_id, 1502 u8 *sas_addr, int include) 1503{ 1504 int index; 1505 int present; 1506 int res; 1507 1508 res = sas_configure_present(dev, phy_id, sas_addr, &index, &present); 1509 if (res) 1510 return res; 1511 if (include ^ present) 1512 return sas_configure_set(dev, phy_id, sas_addr, index,include); 1513 1514 return res; 1515} 1516 1517/** 1518 * sas_configure_parent -- configure routing table of parent 1519 * parent: parent expander 1520 * child: child expander 1521 * sas_addr: SAS port identifier of device directly attached to child 1522 */ 1523static int sas_configure_parent(struct domain_device *parent, 1524 struct domain_device *child, 1525 u8 *sas_addr, int include) 1526{ 1527 struct expander_device *ex_parent = &parent->ex_dev; 1528 int res = 0; 1529 int i; 1530 1531 if (parent->parent) { 1532 res = sas_configure_parent(parent->parent, parent, sas_addr, 1533 include); 1534 if (res) 1535 return res; 1536 } 1537 1538 if (ex_parent->conf_route_table == 0) { 1539 SAS_DPRINTK("ex %016llx has self-configuring routing table\n", 1540 SAS_ADDR(parent->sas_addr)); 1541 return 0; 1542 } 1543 1544 for (i = 0; i < ex_parent->num_phys; i++) { 1545 struct ex_phy *phy = &ex_parent->ex_phy[i]; 1546 1547 if ((phy->routing_attr == TABLE_ROUTING) && 1548 (SAS_ADDR(phy->attached_sas_addr) == 1549 SAS_ADDR(child->sas_addr))) { 1550 res = sas_configure_phy(parent, i, sas_addr, include); 1551 if (res) 1552 return res; 1553 } 1554 } 1555 1556 return res; 1557} 1558 1559/** 1560 * sas_configure_routing -- configure routing 1561 * dev: expander device 1562 * sas_addr: port identifier of device directly attached to the expander device 1563 */ 1564static int sas_configure_routing(struct domain_device *dev, u8 *sas_addr) 1565{ 1566 if (dev->parent) 1567 return sas_configure_parent(dev->parent, dev, sas_addr, 1); 1568 return 0; 1569} 1570 1571static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr) 1572{ 1573 if (dev->parent) 1574 return sas_configure_parent(dev->parent, dev, sas_addr, 0); 1575 return 0; 1576} 1577 1578/** 1579 * sas_discover_expander -- expander discovery 1580 * @ex: pointer to expander domain device 1581 * 1582 * See comment in sas_discover_sata(). 1583 */ 1584static int sas_discover_expander(struct domain_device *dev) 1585{ 1586 int res; 1587 1588 res = sas_notify_lldd_dev_found(dev); 1589 if (res) 1590 return res; 1591 1592 res = sas_ex_general(dev); 1593 if (res) 1594 goto out_err; 1595 res = sas_ex_manuf_info(dev); 1596 if (res) 1597 goto out_err; 1598 1599 res = sas_expander_discover(dev); 1600 if (res) { 1601 SAS_DPRINTK("expander %016llx discovery failed(0x%x)\n", 1602 SAS_ADDR(dev->sas_addr), res); 1603 goto out_err; 1604 } 1605 1606 sas_check_ex_subtractive_boundary(dev); 1607 res = sas_check_parent_topology(dev); 1608 if (res) 1609 goto out_err; 1610 return 0; 1611out_err: 1612 sas_notify_lldd_dev_gone(dev); 1613 return res; 1614} 1615 1616static int sas_ex_level_discovery(struct asd_sas_port *port, const int level) 1617{ 1618 int res = 0; 1619 struct domain_device *dev; 1620 1621 list_for_each_entry(dev, &port->dev_list, dev_list_node) { 1622 if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || 1623 dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { 1624 struct sas_expander_device *ex = 1625 rphy_to_expander_device(dev->rphy); 1626 1627 if (level == ex->level) 1628 res = sas_ex_discover_devices(dev, -1); 1629 else if (level > 0) 1630 res = sas_ex_discover_devices(port->port_dev, -1); 1631 1632 } 1633 } 1634 1635 return res; 1636} 1637 1638static int sas_ex_bfs_disc(struct asd_sas_port *port) 1639{ 1640 int res; 1641 int level; 1642 1643 do { 1644 level = port->disc.max_level; 1645 res = sas_ex_level_discovery(port, level); 1646 mb(); 1647 } while (level < port->disc.max_level); 1648 1649 return res; 1650} 1651 1652int sas_discover_root_expander(struct domain_device *dev) 1653{ 1654 int res; 1655 struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy); 1656 1657 res = sas_rphy_add(dev->rphy); 1658 if (res) 1659 goto out_err; 1660 1661 ex->level = dev->port->disc.max_level; /* 0 */ 1662 res = sas_discover_expander(dev); 1663 if (res) 1664 goto out_err2; 1665 1666 sas_ex_bfs_disc(dev->port); 1667 1668 return res; 1669 1670out_err2: 1671 sas_rphy_remove(dev->rphy); 1672out_err: 1673 return res; 1674} 1675 1676/* ---------- Domain revalidation ---------- */ 1677 1678static int sas_get_phy_discover(struct domain_device *dev, 1679 int phy_id, struct smp_resp *disc_resp) 1680{ 1681 int res; 1682 u8 *disc_req; 1683 1684 disc_req = alloc_smp_req(DISCOVER_REQ_SIZE); 1685 if (!disc_req) 1686 return -ENOMEM; 1687 1688 disc_req[1] = SMP_DISCOVER; 1689 disc_req[9] = phy_id; 1690 1691 res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE, 1692 disc_resp, DISCOVER_RESP_SIZE); 1693 if (res) 1694 goto out; 1695 else if (disc_resp->result != SMP_RESP_FUNC_ACC) { 1696 res = disc_resp->result; 1697 goto out; 1698 } 1699out: 1700 kfree(disc_req); 1701 return res; 1702} 1703 1704static int sas_get_phy_change_count(struct domain_device *dev, 1705 int phy_id, int *pcc) 1706{ 1707 int res; 1708 struct smp_resp *disc_resp; 1709 1710 disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE); 1711 if (!disc_resp) 1712 return -ENOMEM; 1713 1714 res = sas_get_phy_discover(dev, phy_id, disc_resp); 1715 if (!res) 1716 *pcc = disc_resp->disc.change_count; 1717 1718 kfree(disc_resp); 1719 return res; 1720} 1721 1722static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id, 1723 u8 *sas_addr, enum sas_device_type *type) 1724{ 1725 int res; 1726 struct smp_resp *disc_resp; 1727 struct discover_resp *dr; 1728 1729 disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE); 1730 if (!disc_resp) 1731 return -ENOMEM; 1732 dr = &disc_resp->disc; 1733 1734 res = sas_get_phy_discover(dev, phy_id, disc_resp); 1735 if (res == 0) { 1736 memcpy(sas_addr, disc_resp->disc.attached_sas_addr, 8); 1737 *type = to_dev_type(dr); 1738 if (*type == 0) 1739 memset(sas_addr, 0, 8); 1740 } 1741 kfree(disc_resp); 1742 return res; 1743} 1744 1745static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id, 1746 int from_phy, bool update) 1747{ 1748 struct expander_device *ex = &dev->ex_dev; 1749 int res = 0; 1750 int i; 1751 1752 for (i = from_phy; i < ex->num_phys; i++) { 1753 int phy_change_count = 0; 1754 1755 res = sas_get_phy_change_count(dev, i, &phy_change_count); 1756 switch (res) { 1757 case SMP_RESP_PHY_VACANT: 1758 case SMP_RESP_NO_PHY: 1759 continue; 1760 case SMP_RESP_FUNC_ACC: 1761 break; 1762 default: 1763 return res; 1764 } 1765 1766 if (phy_change_count != ex->ex_phy[i].phy_change_count) { 1767 if (update) 1768 ex->ex_phy[i].phy_change_count = 1769 phy_change_count; 1770 *phy_id = i; 1771 return 0; 1772 } 1773 } 1774 return 0; 1775} 1776 1777static int sas_get_ex_change_count(struct domain_device *dev, int *ecc) 1778{ 1779 int res; 1780 u8 *rg_req; 1781 struct smp_resp *rg_resp; 1782 1783 rg_req = alloc_smp_req(RG_REQ_SIZE); 1784 if (!rg_req) 1785 return -ENOMEM; 1786 1787 rg_resp = alloc_smp_resp(RG_RESP_SIZE); 1788 if (!rg_resp) { 1789 kfree(rg_req); 1790 return -ENOMEM; 1791 } 1792 1793 rg_req[1] = SMP_REPORT_GENERAL; 1794 1795 res = smp_execute_task(dev, rg_req, RG_REQ_SIZE, rg_resp, 1796 RG_RESP_SIZE); 1797 if (res) 1798 goto out; 1799 if (rg_resp->result != SMP_RESP_FUNC_ACC) { 1800 res = rg_resp->result; 1801 goto out; 1802 } 1803 1804 *ecc = be16_to_cpu(rg_resp->rg.change_count); 1805out: 1806 kfree(rg_resp); 1807 kfree(rg_req); 1808 return res; 1809} 1810/** 1811 * sas_find_bcast_dev - find the device issue BROADCAST(CHANGE). 1812 * @dev:domain device to be detect. 1813 * @src_dev: the device which originated BROADCAST(CHANGE). 1814 * 1815 * Add self-configuration expander support. Suppose two expander cascading, 1816 * when the first level expander is self-configuring, hotplug the disks in 1817 * second level expander, BROADCAST(CHANGE) will not only be originated 1818 * in the second level expander, but also be originated in the first level 1819 * expander (see SAS protocol SAS 2r-14, 7.11 for detail), it is to say, 1820 * expander changed count in two level expanders will all increment at least 1821 * once, but the phy which chang count has changed is the source device which 1822 * we concerned. 1823 */ 1824 1825static int sas_find_bcast_dev(struct domain_device *dev, 1826 struct domain_device **src_dev) 1827{ 1828 struct expander_device *ex = &dev->ex_dev; 1829 int ex_change_count = -1; 1830 int phy_id = -1; 1831 int res; 1832 struct domain_device *ch; 1833 1834 res = sas_get_ex_change_count(dev, &ex_change_count); 1835 if (res) 1836 goto out; 1837 if (ex_change_count != -1 && ex_change_count != ex->ex_change_count) { 1838 /* Just detect if this expander phys phy change count changed, 1839 * in order to determine if this expander originate BROADCAST, 1840 * and do not update phy change count field in our structure. 1841 */ 1842 res = sas_find_bcast_phy(dev, &phy_id, 0, false); 1843 if (phy_id != -1) { 1844 *src_dev = dev; 1845 ex->ex_change_count = ex_change_count; 1846 SAS_DPRINTK("Expander phy change count has changed\n"); 1847 return res; 1848 } else 1849 SAS_DPRINTK("Expander phys DID NOT change\n"); 1850 } 1851 list_for_each_entry(ch, &ex->children, siblings) { 1852 if (ch->dev_type == SAS_EDGE_EXPANDER_DEVICE || ch->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { 1853 res = sas_find_bcast_dev(ch, src_dev); 1854 if (*src_dev) 1855 return res; 1856 } 1857 } 1858out: 1859 return res; 1860} 1861 1862static void sas_unregister_ex_tree(struct asd_sas_port *port, struct domain_device *dev) 1863{ 1864 struct expander_device *ex = &dev->ex_dev; 1865 struct domain_device *child, *n; 1866 1867 list_for_each_entry_safe(child, n, &ex->children, siblings) { 1868 set_bit(SAS_DEV_GONE, &child->state); 1869 if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || 1870 child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) 1871 sas_unregister_ex_tree(port, child); 1872 else 1873 sas_unregister_dev(port, child); 1874 } 1875 sas_unregister_dev(port, dev); 1876} 1877 1878static void sas_unregister_devs_sas_addr(struct domain_device *parent, 1879 int phy_id, bool last) 1880{ 1881 struct expander_device *ex_dev = &parent->ex_dev; 1882 struct ex_phy *phy = &ex_dev->ex_phy[phy_id]; 1883 struct domain_device *child, *n, *found = NULL; 1884 if (last) { 1885 list_for_each_entry_safe(child, n, 1886 &ex_dev->children, siblings) { 1887 if (SAS_ADDR(child->sas_addr) == 1888 SAS_ADDR(phy->attached_sas_addr)) { 1889 set_bit(SAS_DEV_GONE, &child->state); 1890 if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || 1891 child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) 1892 sas_unregister_ex_tree(parent->port, child); 1893 else 1894 sas_unregister_dev(parent->port, child); 1895 found = child; 1896 break; 1897 } 1898 } 1899 sas_disable_routing(parent, phy->attached_sas_addr); 1900 } 1901 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); 1902 if (phy->port) { 1903 sas_port_delete_phy(phy->port, phy->phy); 1904 sas_device_set_phy(found, phy->port); 1905 if (phy->port->num_phys == 0) 1906 sas_port_delete(phy->port); 1907 phy->port = NULL; 1908 } 1909} 1910 1911static int sas_discover_bfs_by_root_level(struct domain_device *root, 1912 const int level) 1913{ 1914 struct expander_device *ex_root = &root->ex_dev; 1915 struct domain_device *child; 1916 int res = 0; 1917 1918 list_for_each_entry(child, &ex_root->children, siblings) { 1919 if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || 1920 child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { 1921 struct sas_expander_device *ex = 1922 rphy_to_expander_device(child->rphy); 1923 1924 if (level > ex->level) 1925 res = sas_discover_bfs_by_root_level(child, 1926 level); 1927 else if (level == ex->level) 1928 res = sas_ex_discover_devices(child, -1); 1929 } 1930 } 1931 return res; 1932} 1933 1934static int sas_discover_bfs_by_root(struct domain_device *dev) 1935{ 1936 int res; 1937 struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy); 1938 int level = ex->level+1; 1939 1940 res = sas_ex_discover_devices(dev, -1); 1941 if (res) 1942 goto out; 1943 do { 1944 res = sas_discover_bfs_by_root_level(dev, level); 1945 mb(); 1946 level += 1; 1947 } while (level <= dev->port->disc.max_level); 1948out: 1949 return res; 1950} 1951 1952static int sas_discover_new(struct domain_device *dev, int phy_id) 1953{ 1954 struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; 1955 struct domain_device *child; 1956 int res; 1957 1958 SAS_DPRINTK("ex %016llx phy%d new device attached\n", 1959 SAS_ADDR(dev->sas_addr), phy_id); 1960 res = sas_ex_phy_discover(dev, phy_id); 1961 if (res) 1962 return res; 1963 1964 if (sas_ex_join_wide_port(dev, phy_id)) 1965 return 0; 1966 1967 res = sas_ex_discover_devices(dev, phy_id); 1968 if (res) 1969 return res; 1970 list_for_each_entry(child, &dev->ex_dev.children, siblings) { 1971 if (SAS_ADDR(child->sas_addr) == 1972 SAS_ADDR(ex_phy->attached_sas_addr)) { 1973 if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || 1974 child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) 1975 res = sas_discover_bfs_by_root(child); 1976 break; 1977 } 1978 } 1979 return res; 1980} 1981 1982static bool dev_type_flutter(enum sas_device_type new, enum sas_device_type old) 1983{ 1984 if (old == new) 1985 return true; 1986 1987 /* treat device directed resets as flutter, if we went 1988 * SAS_END_DEVICE to SAS_SATA_PENDING the link needs recovery 1989 */ 1990 if ((old == SAS_SATA_PENDING && new == SAS_END_DEVICE) || 1991 (old == SAS_END_DEVICE && new == SAS_SATA_PENDING)) 1992 return true; 1993 1994 return false; 1995} 1996 1997static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last) 1998{ 1999 struct expander_device *ex = &dev->ex_dev; 2000 struct ex_phy *phy = &ex->ex_phy[phy_id]; 2001 enum sas_device_type type = SAS_PHY_UNUSED; 2002 u8 sas_addr[8]; 2003 int res; 2004 2005 memset(sas_addr, 0, 8); 2006 res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type); 2007 switch (res) { 2008 case SMP_RESP_NO_PHY: 2009 phy->phy_state = PHY_NOT_PRESENT; 2010 sas_unregister_devs_sas_addr(dev, phy_id, last); 2011 return res; 2012 case SMP_RESP_PHY_VACANT: 2013 phy->phy_state = PHY_VACANT; 2014 sas_unregister_devs_sas_addr(dev, phy_id, last); 2015 return res; 2016 case SMP_RESP_FUNC_ACC: 2017 break; 2018 case -ECOMM: 2019 break; 2020 default: 2021 return res; 2022 } 2023 2024 if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) { 2025 phy->phy_state = PHY_EMPTY; 2026 sas_unregister_devs_sas_addr(dev, phy_id, last); 2027 return res; 2028 } else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) && 2029 dev_type_flutter(type, phy->attached_dev_type)) { 2030 struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id); 2031 char *action = ""; 2032 2033 sas_ex_phy_discover(dev, phy_id); 2034 2035 if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING) 2036 action = ", needs recovery"; 2037 SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter%s\n", 2038 SAS_ADDR(dev->sas_addr), phy_id, action); 2039 return res; 2040 } 2041 2042 /* delete the old link */ 2043 if (SAS_ADDR(phy->attached_sas_addr) && 2044 SAS_ADDR(sas_addr) != SAS_ADDR(phy->attached_sas_addr)) { 2045 SAS_DPRINTK("ex %016llx phy 0x%x replace %016llx\n", 2046 SAS_ADDR(dev->sas_addr), phy_id, 2047 SAS_ADDR(phy->attached_sas_addr)); 2048 sas_unregister_devs_sas_addr(dev, phy_id, last); 2049 } 2050 2051 return sas_discover_new(dev, phy_id); 2052} 2053 2054/** 2055 * sas_rediscover - revalidate the domain. 2056 * @dev:domain device to be detect. 2057 * @phy_id: the phy id will be detected. 2058 * 2059 * NOTE: this process _must_ quit (return) as soon as any connection 2060 * errors are encountered. Connection recovery is done elsewhere. 2061 * Discover process only interrogates devices in order to discover the 2062 * domain.For plugging out, we un-register the device only when it is 2063 * the last phy in the port, for other phys in this port, we just delete it 2064 * from the port.For inserting, we do discovery when it is the 2065 * first phy,for other phys in this port, we add it to the port to 2066 * forming the wide-port. 2067 */ 2068static int sas_rediscover(struct domain_device *dev, const int phy_id) 2069{ 2070 struct expander_device *ex = &dev->ex_dev; 2071 struct ex_phy *changed_phy = &ex->ex_phy[phy_id]; 2072 int res = 0; 2073 int i; 2074 bool last = true; /* is this the last phy of the port */ 2075 2076 SAS_DPRINTK("ex %016llx phy%d originated BROADCAST(CHANGE)\n", 2077 SAS_ADDR(dev->sas_addr), phy_id); 2078 2079 if (SAS_ADDR(changed_phy->attached_sas_addr) != 0) { 2080 for (i = 0; i < ex->num_phys; i++) { 2081 struct ex_phy *phy = &ex->ex_phy[i]; 2082 2083 if (i == phy_id) 2084 continue; 2085 if (SAS_ADDR(phy->attached_sas_addr) == 2086 SAS_ADDR(changed_phy->attached_sas_addr)) { 2087 SAS_DPRINTK("phy%d part of wide port with " 2088 "phy%d\n", phy_id, i); 2089 last = false; 2090 break; 2091 } 2092 } 2093 res = sas_rediscover_dev(dev, phy_id, last); 2094 } else 2095 res = sas_discover_new(dev, phy_id); 2096 return res; 2097} 2098 2099/** 2100 * sas_revalidate_domain -- revalidate the domain 2101 * @port: port to the domain of interest 2102 * 2103 * NOTE: this process _must_ quit (return) as soon as any connection 2104 * errors are encountered. Connection recovery is done elsewhere. 2105 * Discover process only interrogates devices in order to discover the 2106 * domain. 2107 */ 2108int sas_ex_revalidate_domain(struct domain_device *port_dev) 2109{ 2110 int res; 2111 struct domain_device *dev = NULL; 2112 2113 res = sas_find_bcast_dev(port_dev, &dev); 2114 while (res == 0 && dev) { 2115 struct expander_device *ex = &dev->ex_dev; 2116 int i = 0, phy_id; 2117 2118 do { 2119 phy_id = -1; 2120 res = sas_find_bcast_phy(dev, &phy_id, i, true); 2121 if (phy_id == -1) 2122 break; 2123 res = sas_rediscover(dev, phy_id); 2124 i = phy_id + 1; 2125 } while (i < ex->num_phys); 2126 2127 dev = NULL; 2128 res = sas_find_bcast_dev(port_dev, &dev); 2129 } 2130 return res; 2131} 2132 2133int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, 2134 struct request *req) 2135{ 2136 struct domain_device *dev; 2137 int ret, type; 2138 struct request *rsp = req->next_rq; 2139 2140 if (!rsp) { 2141 printk("%s: space for a smp response is missing\n", 2142 __func__); 2143 return -EINVAL; 2144 } 2145 2146 /* no rphy means no smp target support (ie aic94xx host) */ 2147 if (!rphy) 2148 return sas_smp_host_handler(shost, req, rsp); 2149 2150 type = rphy->identify.device_type; 2151 2152 if (type != SAS_EDGE_EXPANDER_DEVICE && 2153 type != SAS_FANOUT_EXPANDER_DEVICE) { 2154 printk("%s: can we send a smp request to a device?\n", 2155 __func__); 2156 return -EINVAL; 2157 } 2158 2159 dev = sas_find_dev_by_rphy(rphy); 2160 if (!dev) { 2161 printk("%s: fail to find a domain_device?\n", __func__); 2162 return -EINVAL; 2163 } 2164 2165 /* do we need to support multiple segments? */ 2166 if (bio_multiple_segments(req->bio) || 2167 bio_multiple_segments(rsp->bio)) { 2168 printk("%s: multiple segments req %u, rsp %u\n", 2169 __func__, blk_rq_bytes(req), blk_rq_bytes(rsp)); 2170 return -EINVAL; 2171 } 2172 2173 ret = smp_execute_task(dev, bio_data(req->bio), blk_rq_bytes(req), 2174 bio_data(rsp->bio), blk_rq_bytes(rsp)); 2175 if (ret > 0) { 2176 /* positive number is the untransferred residual */ 2177 rsp->resid_len = ret; 2178 req->resid_len = 0; 2179 ret = 0; 2180 } else if (ret == 0) { 2181 rsp->resid_len = 0; 2182 req->resid_len = 0; 2183 } 2184 2185 return ret; 2186} 2187