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