linux/drivers/scsi/scsi_transport_sas.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2005-2006 Dell Inc.
   3 *      Released under GPL v2.
   4 *
   5 * Serial Attached SCSI (SAS) transport class.
   6 *
   7 * The SAS transport class contains common code to deal with SAS HBAs,
   8 * an aproximated representation of SAS topologies in the driver model,
   9 * and various sysfs attributes to expose these topologies and management
  10 * interfaces to userspace.
  11 *
  12 * In addition to the basic SCSI core objects this transport class
  13 * introduces two additional intermediate objects:  The SAS PHY
  14 * as represented by struct sas_phy defines an "outgoing" PHY on
  15 * a SAS HBA or Expander, and the SAS remote PHY represented by
  16 * struct sas_rphy defines an "incoming" PHY on a SAS Expander or
  17 * end device.  Note that this is purely a software concept, the
  18 * underlying hardware for a PHY and a remote PHY is the exactly
  19 * the same.
  20 *
  21 * There is no concept of a SAS port in this code, users can see
  22 * what PHYs form a wide port based on the port_identifier attribute,
  23 * which is the same for all PHYs in a port.
  24 */
  25
  26#include <linux/init.h>
  27#include <linux/module.h>
  28#include <linux/jiffies.h>
  29#include <linux/err.h>
  30#include <linux/slab.h>
  31#include <linux/string.h>
  32#include <linux/blkdev.h>
  33#include <linux/bsg.h>
  34
  35#include <scsi/scsi.h>
  36#include <scsi/scsi_device.h>
  37#include <scsi/scsi_host.h>
  38#include <scsi/scsi_transport.h>
  39#include <scsi/scsi_transport_sas.h>
  40
  41#include "scsi_sas_internal.h"
  42struct sas_host_attrs {
  43        struct list_head rphy_list;
  44        struct mutex lock;
  45        struct request_queue *q;
  46        u32 next_target_id;
  47        u32 next_expander_id;
  48        int next_port_id;
  49};
  50#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
  51
  52
  53/*
  54 * Hack to allow attributes of the same name in different objects.
  55 */
  56#define SAS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
  57        struct device_attribute dev_attr_##_prefix##_##_name = \
  58        __ATTR(_name,_mode,_show,_store)
  59
  60
  61/*
  62 * Pretty printing helpers
  63 */
  64
  65#define sas_bitfield_name_match(title, table)                   \
  66static ssize_t                                                  \
  67get_sas_##title##_names(u32 table_key, char *buf)               \
  68{                                                               \
  69        char *prefix = "";                                      \
  70        ssize_t len = 0;                                        \
  71        int i;                                                  \
  72                                                                \
  73        for (i = 0; i < ARRAY_SIZE(table); i++) {               \
  74                if (table[i].value & table_key) {               \
  75                        len += sprintf(buf + len, "%s%s",       \
  76                                prefix, table[i].name);         \
  77                        prefix = ", ";                          \
  78                }                                               \
  79        }                                                       \
  80        len += sprintf(buf + len, "\n");                        \
  81        return len;                                             \
  82}
  83
  84#define sas_bitfield_name_set(title, table)                     \
  85static ssize_t                                                  \
  86set_sas_##title##_names(u32 *table_key, const char *buf)        \
  87{                                                               \
  88        ssize_t len = 0;                                        \
  89        int i;                                                  \
  90                                                                \
  91        for (i = 0; i < ARRAY_SIZE(table); i++) {               \
  92                len = strlen(table[i].name);                    \
  93                if (strncmp(buf, table[i].name, len) == 0 &&    \
  94                    (buf[len] == '\n' || buf[len] == '\0')) {   \
  95                        *table_key = table[i].value;            \
  96                        return 0;                               \
  97                }                                               \
  98        }                                                       \
  99        return -EINVAL;                                         \
 100}
 101
 102#define sas_bitfield_name_search(title, table)                  \
 103static ssize_t                                                  \
 104get_sas_##title##_names(u32 table_key, char *buf)               \
 105{                                                               \
 106        ssize_t len = 0;                                        \
 107        int i;                                                  \
 108                                                                \
 109        for (i = 0; i < ARRAY_SIZE(table); i++) {               \
 110                if (table[i].value == table_key) {              \
 111                        len += sprintf(buf + len, "%s",         \
 112                                table[i].name);                 \
 113                        break;                                  \
 114                }                                               \
 115        }                                                       \
 116        len += sprintf(buf + len, "\n");                        \
 117        return len;                                             \
 118}
 119
 120static struct {
 121        u32             value;
 122        char            *name;
 123} sas_device_type_names[] = {
 124        { SAS_PHY_UNUSED,               "unused" },
 125        { SAS_END_DEVICE,               "end device" },
 126        { SAS_EDGE_EXPANDER_DEVICE,     "edge expander" },
 127        { SAS_FANOUT_EXPANDER_DEVICE,   "fanout expander" },
 128};
 129sas_bitfield_name_search(device_type, sas_device_type_names)
 130
 131
 132static struct {
 133        u32             value;
 134        char            *name;
 135} sas_protocol_names[] = {
 136        { SAS_PROTOCOL_SATA,            "sata" },
 137        { SAS_PROTOCOL_SMP,             "smp" },
 138        { SAS_PROTOCOL_STP,             "stp" },
 139        { SAS_PROTOCOL_SSP,             "ssp" },
 140};
 141sas_bitfield_name_match(protocol, sas_protocol_names)
 142
 143static struct {
 144        u32             value;
 145        char            *name;
 146} sas_linkspeed_names[] = {
 147        { SAS_LINK_RATE_UNKNOWN,        "Unknown" },
 148        { SAS_PHY_DISABLED,             "Phy disabled" },
 149        { SAS_LINK_RATE_FAILED,         "Link Rate failed" },
 150        { SAS_SATA_SPINUP_HOLD,         "Spin-up hold" },
 151        { SAS_LINK_RATE_1_5_GBPS,       "1.5 Gbit" },
 152        { SAS_LINK_RATE_3_0_GBPS,       "3.0 Gbit" },
 153        { SAS_LINK_RATE_6_0_GBPS,       "6.0 Gbit" },
 154        { SAS_LINK_RATE_12_0_GBPS,      "12.0 Gbit" },
 155};
 156sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
 157sas_bitfield_name_set(linkspeed, sas_linkspeed_names)
 158
 159static struct sas_end_device *sas_sdev_to_rdev(struct scsi_device *sdev)
 160{
 161        struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target);
 162        struct sas_end_device *rdev;
 163
 164        BUG_ON(rphy->identify.device_type != SAS_END_DEVICE);
 165
 166        rdev = rphy_to_end_device(rphy);
 167        return rdev;
 168}
 169
 170static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
 171                            struct sas_rphy *rphy)
 172{
 173        struct request *req;
 174        int ret;
 175        int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
 176
 177        while ((req = blk_fetch_request(q)) != NULL) {
 178                spin_unlock_irq(q->queue_lock);
 179
 180                handler = to_sas_internal(shost->transportt)->f->smp_handler;
 181                ret = handler(shost, rphy, req);
 182                req->errors = ret;
 183
 184                blk_end_request_all(req, ret);
 185
 186                spin_lock_irq(q->queue_lock);
 187        }
 188}
 189
 190static void sas_host_smp_request(struct request_queue *q)
 191{
 192        sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL);
 193}
 194
 195static void sas_non_host_smp_request(struct request_queue *q)
 196{
 197        struct sas_rphy *rphy = q->queuedata;
 198        sas_smp_request(q, rphy_to_shost(rphy), rphy);
 199}
 200
 201static void sas_host_release(struct device *dev)
 202{
 203        struct Scsi_Host *shost = dev_to_shost(dev);
 204        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 205        struct request_queue *q = sas_host->q;
 206
 207        if (q)
 208                blk_cleanup_queue(q);
 209}
 210
 211static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
 212{
 213        struct request_queue *q;
 214        int error;
 215        struct device *dev;
 216        char namebuf[20];
 217        const char *name;
 218        void (*release)(struct device *);
 219
 220        if (!to_sas_internal(shost->transportt)->f->smp_handler) {
 221                printk("%s can't handle SMP requests\n", shost->hostt->name);
 222                return 0;
 223        }
 224
 225        if (rphy) {
 226                q = blk_init_queue(sas_non_host_smp_request, NULL);
 227                dev = &rphy->dev;
 228                name = dev_name(dev);
 229                release = NULL;
 230        } else {
 231                q = blk_init_queue(sas_host_smp_request, NULL);
 232                dev = &shost->shost_gendev;
 233                snprintf(namebuf, sizeof(namebuf),
 234                         "sas_host%d", shost->host_no);
 235                name = namebuf;
 236                release = sas_host_release;
 237        }
 238        if (!q)
 239                return -ENOMEM;
 240
 241        error = bsg_register_queue(q, dev, name, release);
 242        if (error) {
 243                blk_cleanup_queue(q);
 244                return -ENOMEM;
 245        }
 246
 247        if (rphy)
 248                rphy->q = q;
 249        else
 250                to_sas_host_attrs(shost)->q = q;
 251
 252        if (rphy)
 253                q->queuedata = rphy;
 254        else
 255                q->queuedata = shost;
 256
 257        queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
 258        return 0;
 259}
 260
 261static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
 262{
 263        struct request_queue *q;
 264
 265        if (rphy)
 266                q = rphy->q;
 267        else
 268                q = to_sas_host_attrs(shost)->q;
 269
 270        if (!q)
 271                return;
 272
 273        bsg_unregister_queue(q);
 274}
 275
 276/*
 277 * SAS host attributes
 278 */
 279
 280static int sas_host_setup(struct transport_container *tc, struct device *dev,
 281                          struct device *cdev)
 282{
 283        struct Scsi_Host *shost = dev_to_shost(dev);
 284        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 285
 286        INIT_LIST_HEAD(&sas_host->rphy_list);
 287        mutex_init(&sas_host->lock);
 288        sas_host->next_target_id = 0;
 289        sas_host->next_expander_id = 0;
 290        sas_host->next_port_id = 0;
 291
 292        if (sas_bsg_initialize(shost, NULL))
 293                dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n",
 294                           shost->host_no);
 295
 296        return 0;
 297}
 298
 299static int sas_host_remove(struct transport_container *tc, struct device *dev,
 300                           struct device *cdev)
 301{
 302        struct Scsi_Host *shost = dev_to_shost(dev);
 303
 304        sas_bsg_remove(shost, NULL);
 305
 306        return 0;
 307}
 308
 309static DECLARE_TRANSPORT_CLASS(sas_host_class,
 310                "sas_host", sas_host_setup, sas_host_remove, NULL);
 311
 312static int sas_host_match(struct attribute_container *cont,
 313                            struct device *dev)
 314{
 315        struct Scsi_Host *shost;
 316        struct sas_internal *i;
 317
 318        if (!scsi_is_host_device(dev))
 319                return 0;
 320        shost = dev_to_shost(dev);
 321
 322        if (!shost->transportt)
 323                return 0;
 324        if (shost->transportt->host_attrs.ac.class !=
 325                        &sas_host_class.class)
 326                return 0;
 327
 328        i = to_sas_internal(shost->transportt);
 329        return &i->t.host_attrs.ac == cont;
 330}
 331
 332static int do_sas_phy_delete(struct device *dev, void *data)
 333{
 334        int pass = (int)(unsigned long)data;
 335
 336        if (pass == 0 && scsi_is_sas_port(dev))
 337                sas_port_delete(dev_to_sas_port(dev));
 338        else if (pass == 1 && scsi_is_sas_phy(dev))
 339                sas_phy_delete(dev_to_phy(dev));
 340        return 0;
 341}
 342
 343/**
 344 * sas_remove_children  -  tear down a devices SAS data structures
 345 * @dev:        device belonging to the sas object
 346 *
 347 * Removes all SAS PHYs and remote PHYs for a given object
 348 */
 349void sas_remove_children(struct device *dev)
 350{
 351        device_for_each_child(dev, (void *)0, do_sas_phy_delete);
 352        device_for_each_child(dev, (void *)1, do_sas_phy_delete);
 353}
 354EXPORT_SYMBOL(sas_remove_children);
 355
 356/**
 357 * sas_remove_host  -  tear down a Scsi_Host's SAS data structures
 358 * @shost:      Scsi Host that is torn down
 359 *
 360 * Removes all SAS PHYs and remote PHYs for a given Scsi_Host.
 361 * Must be called just before scsi_remove_host for SAS HBAs.
 362 */
 363void sas_remove_host(struct Scsi_Host *shost)
 364{
 365        sas_remove_children(&shost->shost_gendev);
 366}
 367EXPORT_SYMBOL(sas_remove_host);
 368
 369/**
 370 * sas_tlr_supported - checking TLR bit in vpd 0x90
 371 * @sdev: scsi device struct
 372 *
 373 * Check Transport Layer Retries are supported or not.
 374 * If vpd page 0x90 is present, TRL is supported.
 375 *
 376 */
 377unsigned int
 378sas_tlr_supported(struct scsi_device *sdev)
 379{
 380        const int vpd_len = 32;
 381        struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
 382        char *buffer = kzalloc(vpd_len, GFP_KERNEL);
 383        int ret = 0;
 384
 385        if (scsi_get_vpd_page(sdev, 0x90, buffer, vpd_len))
 386                goto out;
 387
 388        /*
 389         * Magic numbers: the VPD Protocol page (0x90)
 390         * has a 4 byte header and then one entry per device port
 391         * the TLR bit is at offset 8 on each port entry
 392         * if we take the first port, that's at total offset 12
 393         */
 394        ret = buffer[12] & 0x01;
 395
 396 out:
 397        kfree(buffer);
 398        rdev->tlr_supported = ret;
 399        return ret;
 400
 401}
 402EXPORT_SYMBOL_GPL(sas_tlr_supported);
 403
 404/**
 405 * sas_disable_tlr - setting TLR flags
 406 * @sdev: scsi device struct
 407 *
 408 * Seting tlr_enabled flag to 0.
 409 *
 410 */
 411void
 412sas_disable_tlr(struct scsi_device *sdev)
 413{
 414        struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
 415
 416        rdev->tlr_enabled = 0;
 417}
 418EXPORT_SYMBOL_GPL(sas_disable_tlr);
 419
 420/**
 421 * sas_enable_tlr - setting TLR flags
 422 * @sdev: scsi device struct
 423 *
 424 * Seting tlr_enabled flag 1.
 425 *
 426 */
 427void sas_enable_tlr(struct scsi_device *sdev)
 428{
 429        unsigned int tlr_supported = 0;
 430        tlr_supported  = sas_tlr_supported(sdev);
 431
 432        if (tlr_supported) {
 433                struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
 434
 435                rdev->tlr_enabled = 1;
 436        }
 437
 438        return;
 439}
 440EXPORT_SYMBOL_GPL(sas_enable_tlr);
 441
 442unsigned int sas_is_tlr_enabled(struct scsi_device *sdev)
 443{
 444        struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
 445        return rdev->tlr_enabled;
 446}
 447EXPORT_SYMBOL_GPL(sas_is_tlr_enabled);
 448
 449/*
 450 * SAS Phy attributes
 451 */
 452
 453#define sas_phy_show_simple(field, name, format_string, cast)           \
 454static ssize_t                                                          \
 455show_sas_phy_##name(struct device *dev,                                 \
 456                    struct device_attribute *attr, char *buf)           \
 457{                                                                       \
 458        struct sas_phy *phy = transport_class_to_phy(dev);              \
 459                                                                        \
 460        return snprintf(buf, 20, format_string, cast phy->field);       \
 461}
 462
 463#define sas_phy_simple_attr(field, name, format_string, type)           \
 464        sas_phy_show_simple(field, name, format_string, (type)) \
 465static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
 466
 467#define sas_phy_show_protocol(field, name)                              \
 468static ssize_t                                                          \
 469show_sas_phy_##name(struct device *dev,                                 \
 470                    struct device_attribute *attr, char *buf)           \
 471{                                                                       \
 472        struct sas_phy *phy = transport_class_to_phy(dev);              \
 473                                                                        \
 474        if (!phy->field)                                                \
 475                return snprintf(buf, 20, "none\n");                     \
 476        return get_sas_protocol_names(phy->field, buf);         \
 477}
 478
 479#define sas_phy_protocol_attr(field, name)                              \
 480        sas_phy_show_protocol(field, name)                              \
 481static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
 482
 483#define sas_phy_show_linkspeed(field)                                   \
 484static ssize_t                                                          \
 485show_sas_phy_##field(struct device *dev,                                \
 486                     struct device_attribute *attr, char *buf)          \
 487{                                                                       \
 488        struct sas_phy *phy = transport_class_to_phy(dev);              \
 489                                                                        \
 490        return get_sas_linkspeed_names(phy->field, buf);                \
 491}
 492
 493/* Fudge to tell if we're minimum or maximum */
 494#define sas_phy_store_linkspeed(field)                                  \
 495static ssize_t                                                          \
 496store_sas_phy_##field(struct device *dev,                               \
 497                      struct device_attribute *attr,                    \
 498                      const char *buf,  size_t count)                   \
 499{                                                                       \
 500        struct sas_phy *phy = transport_class_to_phy(dev);              \
 501        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);        \
 502        struct sas_internal *i = to_sas_internal(shost->transportt);    \
 503        u32 value;                                                      \
 504        struct sas_phy_linkrates rates = {0};                           \
 505        int error;                                                      \
 506                                                                        \
 507        error = set_sas_linkspeed_names(&value, buf);                   \
 508        if (error)                                                      \
 509                return error;                                           \
 510        rates.field = value;                                            \
 511        error = i->f->set_phy_speed(phy, &rates);                       \
 512                                                                        \
 513        return error ? error : count;                                   \
 514}
 515
 516#define sas_phy_linkspeed_rw_attr(field)                                \
 517        sas_phy_show_linkspeed(field)                                   \
 518        sas_phy_store_linkspeed(field)                                  \
 519static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field,                \
 520        store_sas_phy_##field)
 521
 522#define sas_phy_linkspeed_attr(field)                                   \
 523        sas_phy_show_linkspeed(field)                                   \
 524static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
 525
 526
 527#define sas_phy_show_linkerror(field)                                   \
 528static ssize_t                                                          \
 529show_sas_phy_##field(struct device *dev,                                \
 530                     struct device_attribute *attr, char *buf)          \
 531{                                                                       \
 532        struct sas_phy *phy = transport_class_to_phy(dev);              \
 533        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);        \
 534        struct sas_internal *i = to_sas_internal(shost->transportt);    \
 535        int error;                                                      \
 536                                                                        \
 537        error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0;   \
 538        if (error)                                                      \
 539                return error;                                           \
 540        return snprintf(buf, 20, "%u\n", phy->field);                   \
 541}
 542
 543#define sas_phy_linkerror_attr(field)                                   \
 544        sas_phy_show_linkerror(field)                                   \
 545static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
 546
 547
 548static ssize_t
 549show_sas_device_type(struct device *dev,
 550                     struct device_attribute *attr, char *buf)
 551{
 552        struct sas_phy *phy = transport_class_to_phy(dev);
 553
 554        if (!phy->identify.device_type)
 555                return snprintf(buf, 20, "none\n");
 556        return get_sas_device_type_names(phy->identify.device_type, buf);
 557}
 558static DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
 559
 560static ssize_t do_sas_phy_enable(struct device *dev,
 561                size_t count, int enable)
 562{
 563        struct sas_phy *phy = transport_class_to_phy(dev);
 564        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 565        struct sas_internal *i = to_sas_internal(shost->transportt);
 566        int error;
 567
 568        error = i->f->phy_enable(phy, enable);
 569        if (error)
 570                return error;
 571        phy->enabled = enable;
 572        return count;
 573};
 574
 575static ssize_t
 576store_sas_phy_enable(struct device *dev, struct device_attribute *attr,
 577                     const char *buf, size_t count)
 578{
 579        if (count < 1)
 580                return -EINVAL;
 581
 582        switch (buf[0]) {
 583        case '0':
 584                do_sas_phy_enable(dev, count, 0);
 585                break;
 586        case '1':
 587                do_sas_phy_enable(dev, count, 1);
 588                break;
 589        default:
 590                return -EINVAL;
 591        }
 592
 593        return count;
 594}
 595
 596static ssize_t
 597show_sas_phy_enable(struct device *dev, struct device_attribute *attr,
 598                    char *buf)
 599{
 600        struct sas_phy *phy = transport_class_to_phy(dev);
 601
 602        return snprintf(buf, 20, "%d", phy->enabled);
 603}
 604
 605static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
 606                         store_sas_phy_enable);
 607
 608static ssize_t
 609do_sas_phy_reset(struct device *dev, size_t count, int hard_reset)
 610{
 611        struct sas_phy *phy = transport_class_to_phy(dev);
 612        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 613        struct sas_internal *i = to_sas_internal(shost->transportt);
 614        int error;
 615
 616        error = i->f->phy_reset(phy, hard_reset);
 617        if (error)
 618                return error;
 619        phy->enabled = 1;
 620        return count;
 621};
 622
 623static ssize_t
 624store_sas_link_reset(struct device *dev, struct device_attribute *attr,
 625                     const char *buf, size_t count)
 626{
 627        return do_sas_phy_reset(dev, count, 0);
 628}
 629static DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset);
 630
 631static ssize_t
 632store_sas_hard_reset(struct device *dev, struct device_attribute *attr,
 633                     const char *buf, size_t count)
 634{
 635        return do_sas_phy_reset(dev, count, 1);
 636}
 637static DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset);
 638
 639sas_phy_protocol_attr(identify.initiator_port_protocols,
 640                initiator_port_protocols);
 641sas_phy_protocol_attr(identify.target_port_protocols,
 642                target_port_protocols);
 643sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
 644                unsigned long long);
 645sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
 646//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int);
 647sas_phy_linkspeed_attr(negotiated_linkrate);
 648sas_phy_linkspeed_attr(minimum_linkrate_hw);
 649sas_phy_linkspeed_rw_attr(minimum_linkrate);
 650sas_phy_linkspeed_attr(maximum_linkrate_hw);
 651sas_phy_linkspeed_rw_attr(maximum_linkrate);
 652sas_phy_linkerror_attr(invalid_dword_count);
 653sas_phy_linkerror_attr(running_disparity_error_count);
 654sas_phy_linkerror_attr(loss_of_dword_sync_count);
 655sas_phy_linkerror_attr(phy_reset_problem_count);
 656
 657static int sas_phy_setup(struct transport_container *tc, struct device *dev,
 658                         struct device *cdev)
 659{
 660        struct sas_phy *phy = dev_to_phy(dev);
 661        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 662        struct sas_internal *i = to_sas_internal(shost->transportt);
 663
 664        if (i->f->phy_setup)
 665                i->f->phy_setup(phy);
 666
 667        return 0;
 668}
 669
 670static DECLARE_TRANSPORT_CLASS(sas_phy_class,
 671                "sas_phy", sas_phy_setup, NULL, NULL);
 672
 673static int sas_phy_match(struct attribute_container *cont, struct device *dev)
 674{
 675        struct Scsi_Host *shost;
 676        struct sas_internal *i;
 677
 678        if (!scsi_is_sas_phy(dev))
 679                return 0;
 680        shost = dev_to_shost(dev->parent);
 681
 682        if (!shost->transportt)
 683                return 0;
 684        if (shost->transportt->host_attrs.ac.class !=
 685                        &sas_host_class.class)
 686                return 0;
 687
 688        i = to_sas_internal(shost->transportt);
 689        return &i->phy_attr_cont.ac == cont;
 690}
 691
 692static void sas_phy_release(struct device *dev)
 693{
 694        struct sas_phy *phy = dev_to_phy(dev);
 695        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 696        struct sas_internal *i = to_sas_internal(shost->transportt);
 697
 698        if (i->f->phy_release)
 699                i->f->phy_release(phy);
 700        put_device(dev->parent);
 701        kfree(phy);
 702}
 703
 704/**
 705 * sas_phy_alloc  -  allocates and initialize a SAS PHY structure
 706 * @parent:     Parent device
 707 * @number:     Phy index
 708 *
 709 * Allocates an SAS PHY structure.  It will be added in the device tree
 710 * below the device specified by @parent, which has to be either a Scsi_Host
 711 * or sas_rphy.
 712 *
 713 * Returns:
 714 *      SAS PHY allocated or %NULL if the allocation failed.
 715 */
 716struct sas_phy *sas_phy_alloc(struct device *parent, int number)
 717{
 718        struct Scsi_Host *shost = dev_to_shost(parent);
 719        struct sas_phy *phy;
 720
 721        phy = kzalloc(sizeof(*phy), GFP_KERNEL);
 722        if (!phy)
 723                return NULL;
 724
 725        phy->number = number;
 726        phy->enabled = 1;
 727
 728        device_initialize(&phy->dev);
 729        phy->dev.parent = get_device(parent);
 730        phy->dev.release = sas_phy_release;
 731        INIT_LIST_HEAD(&phy->port_siblings);
 732        if (scsi_is_sas_expander_device(parent)) {
 733                struct sas_rphy *rphy = dev_to_rphy(parent);
 734                dev_set_name(&phy->dev, "phy-%d:%d:%d", shost->host_no,
 735                        rphy->scsi_target_id, number);
 736        } else
 737                dev_set_name(&phy->dev, "phy-%d:%d", shost->host_no, number);
 738
 739        transport_setup_device(&phy->dev);
 740
 741        return phy;
 742}
 743EXPORT_SYMBOL(sas_phy_alloc);
 744
 745/**
 746 * sas_phy_add  -  add a SAS PHY to the device hierarchy
 747 * @phy:        The PHY to be added
 748 *
 749 * Publishes a SAS PHY to the rest of the system.
 750 */
 751int sas_phy_add(struct sas_phy *phy)
 752{
 753        int error;
 754
 755        error = device_add(&phy->dev);
 756        if (!error) {
 757                transport_add_device(&phy->dev);
 758                transport_configure_device(&phy->dev);
 759        }
 760
 761        return error;
 762}
 763EXPORT_SYMBOL(sas_phy_add);
 764
 765/**
 766 * sas_phy_free  -  free a SAS PHY
 767 * @phy:        SAS PHY to free
 768 *
 769 * Frees the specified SAS PHY.
 770 *
 771 * Note:
 772 *   This function must only be called on a PHY that has not
 773 *   successfully been added using sas_phy_add().
 774 */
 775void sas_phy_free(struct sas_phy *phy)
 776{
 777        transport_destroy_device(&phy->dev);
 778        put_device(&phy->dev);
 779}
 780EXPORT_SYMBOL(sas_phy_free);
 781
 782/**
 783 * sas_phy_delete  -  remove SAS PHY
 784 * @phy:        SAS PHY to remove
 785 *
 786 * Removes the specified SAS PHY.  If the SAS PHY has an
 787 * associated remote PHY it is removed before.
 788 */
 789void
 790sas_phy_delete(struct sas_phy *phy)
 791{
 792        struct device *dev = &phy->dev;
 793
 794        /* this happens if the phy is still part of a port when deleted */
 795        BUG_ON(!list_empty(&phy->port_siblings));
 796
 797        transport_remove_device(dev);
 798        device_del(dev);
 799        transport_destroy_device(dev);
 800        put_device(dev);
 801}
 802EXPORT_SYMBOL(sas_phy_delete);
 803
 804/**
 805 * scsi_is_sas_phy  -  check if a struct device represents a SAS PHY
 806 * @dev:        device to check
 807 *
 808 * Returns:
 809 *      %1 if the device represents a SAS PHY, %0 else
 810 */
 811int scsi_is_sas_phy(const struct device *dev)
 812{
 813        return dev->release == sas_phy_release;
 814}
 815EXPORT_SYMBOL(scsi_is_sas_phy);
 816
 817/*
 818 * SAS Port attributes
 819 */
 820#define sas_port_show_simple(field, name, format_string, cast)          \
 821static ssize_t                                                          \
 822show_sas_port_##name(struct device *dev,                                \
 823                     struct device_attribute *attr, char *buf)          \
 824{                                                                       \
 825        struct sas_port *port = transport_class_to_sas_port(dev);       \
 826                                                                        \
 827        return snprintf(buf, 20, format_string, cast port->field);      \
 828}
 829
 830#define sas_port_simple_attr(field, name, format_string, type)          \
 831        sas_port_show_simple(field, name, format_string, (type))        \
 832static DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
 833
 834sas_port_simple_attr(num_phys, num_phys, "%d\n", int);
 835
 836static DECLARE_TRANSPORT_CLASS(sas_port_class,
 837                               "sas_port", NULL, NULL, NULL);
 838
 839static int sas_port_match(struct attribute_container *cont, struct device *dev)
 840{
 841        struct Scsi_Host *shost;
 842        struct sas_internal *i;
 843
 844        if (!scsi_is_sas_port(dev))
 845                return 0;
 846        shost = dev_to_shost(dev->parent);
 847
 848        if (!shost->transportt)
 849                return 0;
 850        if (shost->transportt->host_attrs.ac.class !=
 851                        &sas_host_class.class)
 852                return 0;
 853
 854        i = to_sas_internal(shost->transportt);
 855        return &i->port_attr_cont.ac == cont;
 856}
 857
 858
 859static void sas_port_release(struct device *dev)
 860{
 861        struct sas_port *port = dev_to_sas_port(dev);
 862
 863        BUG_ON(!list_empty(&port->phy_list));
 864
 865        put_device(dev->parent);
 866        kfree(port);
 867}
 868
 869static void sas_port_create_link(struct sas_port *port,
 870                                 struct sas_phy *phy)
 871{
 872        int res;
 873
 874        res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj,
 875                                dev_name(&phy->dev));
 876        if (res)
 877                goto err;
 878        res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port");
 879        if (res)
 880                goto err;
 881        return;
 882err:
 883        printk(KERN_ERR "%s: Cannot create port links, err=%d\n",
 884               __func__, res);
 885}
 886
 887static void sas_port_delete_link(struct sas_port *port,
 888                                 struct sas_phy *phy)
 889{
 890        sysfs_remove_link(&port->dev.kobj, dev_name(&phy->dev));
 891        sysfs_remove_link(&phy->dev.kobj, "port");
 892}
 893
 894/** sas_port_alloc - allocate and initialize a SAS port structure
 895 *
 896 * @parent:     parent device
 897 * @port_id:    port number
 898 *
 899 * Allocates a SAS port structure.  It will be added to the device tree
 900 * below the device specified by @parent which must be either a Scsi_Host
 901 * or a sas_expander_device.
 902 *
 903 * Returns %NULL on error
 904 */
 905struct sas_port *sas_port_alloc(struct device *parent, int port_id)
 906{
 907        struct Scsi_Host *shost = dev_to_shost(parent);
 908        struct sas_port *port;
 909
 910        port = kzalloc(sizeof(*port), GFP_KERNEL);
 911        if (!port)
 912                return NULL;
 913
 914        port->port_identifier = port_id;
 915
 916        device_initialize(&port->dev);
 917
 918        port->dev.parent = get_device(parent);
 919        port->dev.release = sas_port_release;
 920
 921        mutex_init(&port->phy_list_mutex);
 922        INIT_LIST_HEAD(&port->phy_list);
 923
 924        if (scsi_is_sas_expander_device(parent)) {
 925                struct sas_rphy *rphy = dev_to_rphy(parent);
 926                dev_set_name(&port->dev, "port-%d:%d:%d", shost->host_no,
 927                             rphy->scsi_target_id, port->port_identifier);
 928        } else
 929                dev_set_name(&port->dev, "port-%d:%d", shost->host_no,
 930                             port->port_identifier);
 931
 932        transport_setup_device(&port->dev);
 933
 934        return port;
 935}
 936EXPORT_SYMBOL(sas_port_alloc);
 937
 938/** sas_port_alloc_num - allocate and initialize a SAS port structure
 939 *
 940 * @parent:     parent device
 941 *
 942 * Allocates a SAS port structure and a number to go with it.  This
 943 * interface is really for adapters where the port number has no
 944 * meansing, so the sas class should manage them.  It will be added to
 945 * the device tree below the device specified by @parent which must be
 946 * either a Scsi_Host or a sas_expander_device.
 947 *
 948 * Returns %NULL on error
 949 */
 950struct sas_port *sas_port_alloc_num(struct device *parent)
 951{
 952        int index;
 953        struct Scsi_Host *shost = dev_to_shost(parent);
 954        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 955
 956        /* FIXME: use idr for this eventually */
 957        mutex_lock(&sas_host->lock);
 958        if (scsi_is_sas_expander_device(parent)) {
 959                struct sas_rphy *rphy = dev_to_rphy(parent);
 960                struct sas_expander_device *exp = rphy_to_expander_device(rphy);
 961
 962                index = exp->next_port_id++;
 963        } else
 964                index = sas_host->next_port_id++;
 965        mutex_unlock(&sas_host->lock);
 966        return sas_port_alloc(parent, index);
 967}
 968EXPORT_SYMBOL(sas_port_alloc_num);
 969
 970/**
 971 * sas_port_add - add a SAS port to the device hierarchy
 972 * @port:       port to be added
 973 *
 974 * publishes a port to the rest of the system
 975 */
 976int sas_port_add(struct sas_port *port)
 977{
 978        int error;
 979
 980        /* No phys should be added until this is made visible */
 981        BUG_ON(!list_empty(&port->phy_list));
 982
 983        error = device_add(&port->dev);
 984
 985        if (error)
 986                return error;
 987
 988        transport_add_device(&port->dev);
 989        transport_configure_device(&port->dev);
 990
 991        return 0;
 992}
 993EXPORT_SYMBOL(sas_port_add);
 994
 995/**
 996 * sas_port_free  -  free a SAS PORT
 997 * @port:       SAS PORT to free
 998 *
 999 * Frees the specified SAS PORT.
1000 *
1001 * Note:
1002 *   This function must only be called on a PORT that has not
1003 *   successfully been added using sas_port_add().
1004 */
1005void sas_port_free(struct sas_port *port)
1006{
1007        transport_destroy_device(&port->dev);
1008        put_device(&port->dev);
1009}
1010EXPORT_SYMBOL(sas_port_free);
1011
1012/**
1013 * sas_port_delete  -  remove SAS PORT
1014 * @port:       SAS PORT to remove
1015 *
1016 * Removes the specified SAS PORT.  If the SAS PORT has an
1017 * associated phys, unlink them from the port as well.
1018 */
1019void sas_port_delete(struct sas_port *port)
1020{
1021        struct device *dev = &port->dev;
1022        struct sas_phy *phy, *tmp_phy;
1023
1024        if (port->rphy) {
1025                sas_rphy_delete(port->rphy);
1026                port->rphy = NULL;
1027        }
1028
1029        mutex_lock(&port->phy_list_mutex);
1030        list_for_each_entry_safe(phy, tmp_phy, &port->phy_list,
1031                                 port_siblings) {
1032                sas_port_delete_link(port, phy);
1033                list_del_init(&phy->port_siblings);
1034        }
1035        mutex_unlock(&port->phy_list_mutex);
1036
1037        if (port->is_backlink) {
1038                struct device *parent = port->dev.parent;
1039
1040                sysfs_remove_link(&port->dev.kobj, dev_name(parent));
1041                port->is_backlink = 0;
1042        }
1043
1044        transport_remove_device(dev);
1045        device_del(dev);
1046        transport_destroy_device(dev);
1047        put_device(dev);
1048}
1049EXPORT_SYMBOL(sas_port_delete);
1050
1051/**
1052 * scsi_is_sas_port -  check if a struct device represents a SAS port
1053 * @dev:        device to check
1054 *
1055 * Returns:
1056 *      %1 if the device represents a SAS Port, %0 else
1057 */
1058int scsi_is_sas_port(const struct device *dev)
1059{
1060        return dev->release == sas_port_release;
1061}
1062EXPORT_SYMBOL(scsi_is_sas_port);
1063
1064/**
1065 * sas_port_get_phy - try to take a reference on a port member
1066 * @port: port to check
1067 */
1068struct sas_phy *sas_port_get_phy(struct sas_port *port)
1069{
1070        struct sas_phy *phy;
1071
1072        mutex_lock(&port->phy_list_mutex);
1073        if (list_empty(&port->phy_list))
1074                phy = NULL;
1075        else {
1076                struct list_head *ent = port->phy_list.next;
1077
1078                phy = list_entry(ent, typeof(*phy), port_siblings);
1079                get_device(&phy->dev);
1080        }
1081        mutex_unlock(&port->phy_list_mutex);
1082
1083        return phy;
1084}
1085EXPORT_SYMBOL(sas_port_get_phy);
1086
1087/**
1088 * sas_port_add_phy - add another phy to a port to form a wide port
1089 * @port:       port to add the phy to
1090 * @phy:        phy to add
1091 *
1092 * When a port is initially created, it is empty (has no phys).  All
1093 * ports must have at least one phy to operated, and all wide ports
1094 * must have at least two.  The current code makes no difference
1095 * between ports and wide ports, but the only object that can be
1096 * connected to a remote device is a port, so ports must be formed on
1097 * all devices with phys if they're connected to anything.
1098 */
1099void sas_port_add_phy(struct sas_port *port, struct sas_phy *phy)
1100{
1101        mutex_lock(&port->phy_list_mutex);
1102        if (unlikely(!list_empty(&phy->port_siblings))) {
1103                /* make sure we're already on this port */
1104                struct sas_phy *tmp;
1105
1106                list_for_each_entry(tmp, &port->phy_list, port_siblings)
1107                        if (tmp == phy)
1108                                break;
1109                /* If this trips, you added a phy that was already
1110                 * part of a different port */
1111                if (unlikely(tmp != phy)) {
1112                        dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n",
1113                                   dev_name(&phy->dev));
1114                        BUG();
1115                }
1116        } else {
1117                sas_port_create_link(port, phy);
1118                list_add_tail(&phy->port_siblings, &port->phy_list);
1119                port->num_phys++;
1120        }
1121        mutex_unlock(&port->phy_list_mutex);
1122}
1123EXPORT_SYMBOL(sas_port_add_phy);
1124
1125/**
1126 * sas_port_delete_phy - remove a phy from a port or wide port
1127 * @port:       port to remove the phy from
1128 * @phy:        phy to remove
1129 *
1130 * This operation is used for tearing down ports again.  It must be
1131 * done to every port or wide port before calling sas_port_delete.
1132 */
1133void sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy)
1134{
1135        mutex_lock(&port->phy_list_mutex);
1136        sas_port_delete_link(port, phy);
1137        list_del_init(&phy->port_siblings);
1138        port->num_phys--;
1139        mutex_unlock(&port->phy_list_mutex);
1140}
1141EXPORT_SYMBOL(sas_port_delete_phy);
1142
1143void sas_port_mark_backlink(struct sas_port *port)
1144{
1145        int res;
1146        struct device *parent = port->dev.parent->parent->parent;
1147
1148        if (port->is_backlink)
1149                return;
1150        port->is_backlink = 1;
1151        res = sysfs_create_link(&port->dev.kobj, &parent->kobj,
1152                                dev_name(parent));
1153        if (res)
1154                goto err;
1155        return;
1156err:
1157        printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n",
1158               __func__, res);
1159
1160}
1161EXPORT_SYMBOL(sas_port_mark_backlink);
1162
1163/*
1164 * SAS remote PHY attributes.
1165 */
1166
1167#define sas_rphy_show_simple(field, name, format_string, cast)          \
1168static ssize_t                                                          \
1169show_sas_rphy_##name(struct device *dev,                                \
1170                     struct device_attribute *attr, char *buf)          \
1171{                                                                       \
1172        struct sas_rphy *rphy = transport_class_to_rphy(dev);           \
1173                                                                        \
1174        return snprintf(buf, 20, format_string, cast rphy->field);      \
1175}
1176
1177#define sas_rphy_simple_attr(field, name, format_string, type)          \
1178        sas_rphy_show_simple(field, name, format_string, (type))        \
1179static SAS_DEVICE_ATTR(rphy, name, S_IRUGO,                     \
1180                show_sas_rphy_##name, NULL)
1181
1182#define sas_rphy_show_protocol(field, name)                             \
1183static ssize_t                                                          \
1184show_sas_rphy_##name(struct device *dev,                                \
1185                     struct device_attribute *attr, char *buf)          \
1186{                                                                       \
1187        struct sas_rphy *rphy = transport_class_to_rphy(dev);           \
1188                                                                        \
1189        if (!rphy->field)                                       \
1190                return snprintf(buf, 20, "none\n");                     \
1191        return get_sas_protocol_names(rphy->field, buf);        \
1192}
1193
1194#define sas_rphy_protocol_attr(field, name)                             \
1195        sas_rphy_show_protocol(field, name)                             \
1196static SAS_DEVICE_ATTR(rphy, name, S_IRUGO,                     \
1197                show_sas_rphy_##name, NULL)
1198
1199static ssize_t
1200show_sas_rphy_device_type(struct device *dev,
1201                          struct device_attribute *attr, char *buf)
1202{
1203        struct sas_rphy *rphy = transport_class_to_rphy(dev);
1204
1205        if (!rphy->identify.device_type)
1206                return snprintf(buf, 20, "none\n");
1207        return get_sas_device_type_names(
1208                        rphy->identify.device_type, buf);
1209}
1210
1211static SAS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
1212                show_sas_rphy_device_type, NULL);
1213
1214static ssize_t
1215show_sas_rphy_enclosure_identifier(struct device *dev,
1216                                   struct device_attribute *attr, char *buf)
1217{
1218        struct sas_rphy *rphy = transport_class_to_rphy(dev);
1219        struct sas_phy *phy = dev_to_phy(rphy->dev.parent);
1220        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1221        struct sas_internal *i = to_sas_internal(shost->transportt);
1222        u64 identifier;
1223        int error;
1224
1225        /*
1226         * Only devices behind an expander are supported, because the
1227         * enclosure identifier is a SMP feature.
1228         */
1229        if (scsi_is_sas_phy_local(phy))
1230                return -EINVAL;
1231
1232        error = i->f->get_enclosure_identifier(rphy, &identifier);
1233        if (error)
1234                return error;
1235        return sprintf(buf, "0x%llx\n", (unsigned long long)identifier);
1236}
1237
1238static SAS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO,
1239                show_sas_rphy_enclosure_identifier, NULL);
1240
1241static ssize_t
1242show_sas_rphy_bay_identifier(struct device *dev,
1243                             struct device_attribute *attr, char *buf)
1244{
1245        struct sas_rphy *rphy = transport_class_to_rphy(dev);
1246        struct sas_phy *phy = dev_to_phy(rphy->dev.parent);
1247        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1248        struct sas_internal *i = to_sas_internal(shost->transportt);
1249        int val;
1250
1251        if (scsi_is_sas_phy_local(phy))
1252                return -EINVAL;
1253
1254        val = i->f->get_bay_identifier(rphy);
1255        if (val < 0)
1256                return val;
1257        return sprintf(buf, "%d\n", val);
1258}
1259
1260static SAS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO,
1261                show_sas_rphy_bay_identifier, NULL);
1262
1263sas_rphy_protocol_attr(identify.initiator_port_protocols,
1264                initiator_port_protocols);
1265sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols);
1266sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
1267                unsigned long long);
1268sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
1269
1270/* only need 8 bytes of data plus header (4 or 8) */
1271#define BUF_SIZE 64
1272
1273int sas_read_port_mode_page(struct scsi_device *sdev)
1274{
1275        char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata;
1276        struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
1277        struct scsi_mode_data mode_data;
1278        int res, error;
1279
1280        if (!buffer)
1281                return -ENOMEM;
1282
1283        res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3,
1284                              &mode_data, NULL);
1285
1286        error = -EINVAL;
1287        if (!scsi_status_is_good(res))
1288                goto out;
1289
1290        msdata = buffer +  mode_data.header_length +
1291                mode_data.block_descriptor_length;
1292
1293        if (msdata - buffer > BUF_SIZE - 8)
1294                goto out;
1295
1296        error = 0;
1297
1298        rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0;
1299        rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5];
1300        rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7];
1301
1302 out:
1303        kfree(buffer);
1304        return error;
1305}
1306EXPORT_SYMBOL(sas_read_port_mode_page);
1307
1308static DECLARE_TRANSPORT_CLASS(sas_end_dev_class,
1309                               "sas_end_device", NULL, NULL, NULL);
1310
1311#define sas_end_dev_show_simple(field, name, format_string, cast)       \
1312static ssize_t                                                          \
1313show_sas_end_dev_##name(struct device *dev,                             \
1314                        struct device_attribute *attr, char *buf)       \
1315{                                                                       \
1316        struct sas_rphy *rphy = transport_class_to_rphy(dev);           \
1317        struct sas_end_device *rdev = rphy_to_end_device(rphy);         \
1318                                                                        \
1319        return snprintf(buf, 20, format_string, cast rdev->field);      \
1320}
1321
1322#define sas_end_dev_simple_attr(field, name, format_string, type)       \
1323        sas_end_dev_show_simple(field, name, format_string, (type))     \
1324static SAS_DEVICE_ATTR(end_dev, name, S_IRUGO,                  \
1325                show_sas_end_dev_##name, NULL)
1326
1327sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int);
1328sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout,
1329                        "%d\n", int);
1330sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout,
1331                        "%d\n", int);
1332sas_end_dev_simple_attr(tlr_supported, tlr_supported,
1333                        "%d\n", int);
1334sas_end_dev_simple_attr(tlr_enabled, tlr_enabled,
1335                        "%d\n", int);
1336
1337static DECLARE_TRANSPORT_CLASS(sas_expander_class,
1338                               "sas_expander", NULL, NULL, NULL);
1339
1340#define sas_expander_show_simple(field, name, format_string, cast)      \
1341static ssize_t                                                          \
1342show_sas_expander_##name(struct device *dev,                            \
1343                         struct device_attribute *attr, char *buf)      \
1344{                                                                       \
1345        struct sas_rphy *rphy = transport_class_to_rphy(dev);           \
1346        struct sas_expander_device *edev = rphy_to_expander_device(rphy); \
1347                                                                        \
1348        return snprintf(buf, 20, format_string, cast edev->field);      \
1349}
1350
1351#define sas_expander_simple_attr(field, name, format_string, type)      \
1352        sas_expander_show_simple(field, name, format_string, (type))    \
1353static SAS_DEVICE_ATTR(expander, name, S_IRUGO,                         \
1354                show_sas_expander_##name, NULL)
1355
1356sas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *);
1357sas_expander_simple_attr(product_id, product_id, "%s\n", char *);
1358sas_expander_simple_attr(product_rev, product_rev, "%s\n", char *);
1359sas_expander_simple_attr(component_vendor_id, component_vendor_id,
1360                         "%s\n", char *);
1361sas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int);
1362sas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n",
1363                         unsigned int);
1364sas_expander_simple_attr(level, level, "%d\n", int);
1365
1366static DECLARE_TRANSPORT_CLASS(sas_rphy_class,
1367                "sas_device", NULL, NULL, NULL);
1368
1369static int sas_rphy_match(struct attribute_container *cont, struct device *dev)
1370{
1371        struct Scsi_Host *shost;
1372        struct sas_internal *i;
1373
1374        if (!scsi_is_sas_rphy(dev))
1375                return 0;
1376        shost = dev_to_shost(dev->parent->parent);
1377
1378        if (!shost->transportt)
1379                return 0;
1380        if (shost->transportt->host_attrs.ac.class !=
1381                        &sas_host_class.class)
1382                return 0;
1383
1384        i = to_sas_internal(shost->transportt);
1385        return &i->rphy_attr_cont.ac == cont;
1386}
1387
1388static int sas_end_dev_match(struct attribute_container *cont,
1389                             struct device *dev)
1390{
1391        struct Scsi_Host *shost;
1392        struct sas_internal *i;
1393        struct sas_rphy *rphy;
1394
1395        if (!scsi_is_sas_rphy(dev))
1396                return 0;
1397        shost = dev_to_shost(dev->parent->parent);
1398        rphy = dev_to_rphy(dev);
1399
1400        if (!shost->transportt)
1401                return 0;
1402        if (shost->transportt->host_attrs.ac.class !=
1403                        &sas_host_class.class)
1404                return 0;
1405
1406        i = to_sas_internal(shost->transportt);
1407        return &i->end_dev_attr_cont.ac == cont &&
1408                rphy->identify.device_type == SAS_END_DEVICE;
1409}
1410
1411static int sas_expander_match(struct attribute_container *cont,
1412                              struct device *dev)
1413{
1414        struct Scsi_Host *shost;
1415        struct sas_internal *i;
1416        struct sas_rphy *rphy;
1417
1418        if (!scsi_is_sas_rphy(dev))
1419                return 0;
1420        shost = dev_to_shost(dev->parent->parent);
1421        rphy = dev_to_rphy(dev);
1422
1423        if (!shost->transportt)
1424                return 0;
1425        if (shost->transportt->host_attrs.ac.class !=
1426                        &sas_host_class.class)
1427                return 0;
1428
1429        i = to_sas_internal(shost->transportt);
1430        return &i->expander_attr_cont.ac == cont &&
1431                (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
1432                 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE);
1433}
1434
1435static void sas_expander_release(struct device *dev)
1436{
1437        struct sas_rphy *rphy = dev_to_rphy(dev);
1438        struct sas_expander_device *edev = rphy_to_expander_device(rphy);
1439
1440        if (rphy->q)
1441                blk_cleanup_queue(rphy->q);
1442
1443        put_device(dev->parent);
1444        kfree(edev);
1445}
1446
1447static void sas_end_device_release(struct device *dev)
1448{
1449        struct sas_rphy *rphy = dev_to_rphy(dev);
1450        struct sas_end_device *edev = rphy_to_end_device(rphy);
1451
1452        if (rphy->q)
1453                blk_cleanup_queue(rphy->q);
1454
1455        put_device(dev->parent);
1456        kfree(edev);
1457}
1458
1459/**
1460 * sas_rphy_initialize - common rphy intialization
1461 * @rphy:       rphy to initialise
1462 *
1463 * Used by both sas_end_device_alloc() and sas_expander_alloc() to
1464 * initialise the common rphy component of each.
1465 */
1466static void sas_rphy_initialize(struct sas_rphy *rphy)
1467{
1468        INIT_LIST_HEAD(&rphy->list);
1469}
1470
1471/**
1472 * sas_end_device_alloc - allocate an rphy for an end device
1473 * @parent: which port
1474 *
1475 * Allocates an SAS remote PHY structure, connected to @parent.
1476 *
1477 * Returns:
1478 *      SAS PHY allocated or %NULL if the allocation failed.
1479 */
1480struct sas_rphy *sas_end_device_alloc(struct sas_port *parent)
1481{
1482        struct Scsi_Host *shost = dev_to_shost(&parent->dev);
1483        struct sas_end_device *rdev;
1484
1485        rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
1486        if (!rdev) {
1487                return NULL;
1488        }
1489
1490        device_initialize(&rdev->rphy.dev);
1491        rdev->rphy.dev.parent = get_device(&parent->dev);
1492        rdev->rphy.dev.release = sas_end_device_release;
1493        if (scsi_is_sas_expander_device(parent->dev.parent)) {
1494                struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent);
1495                dev_set_name(&rdev->rphy.dev, "end_device-%d:%d:%d",
1496                             shost->host_no, rphy->scsi_target_id,
1497                             parent->port_identifier);
1498        } else
1499                dev_set_name(&rdev->rphy.dev, "end_device-%d:%d",
1500                             shost->host_no, parent->port_identifier);
1501        rdev->rphy.identify.device_type = SAS_END_DEVICE;
1502        sas_rphy_initialize(&rdev->rphy);
1503        transport_setup_device(&rdev->rphy.dev);
1504
1505        return &rdev->rphy;
1506}
1507EXPORT_SYMBOL(sas_end_device_alloc);
1508
1509/**
1510 * sas_expander_alloc - allocate an rphy for an end device
1511 * @parent: which port
1512 * @type: SAS_EDGE_EXPANDER_DEVICE or SAS_FANOUT_EXPANDER_DEVICE
1513 *
1514 * Allocates an SAS remote PHY structure, connected to @parent.
1515 *
1516 * Returns:
1517 *      SAS PHY allocated or %NULL if the allocation failed.
1518 */
1519struct sas_rphy *sas_expander_alloc(struct sas_port *parent,
1520                                    enum sas_device_type type)
1521{
1522        struct Scsi_Host *shost = dev_to_shost(&parent->dev);
1523        struct sas_expander_device *rdev;
1524        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1525
1526        BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE &&
1527               type != SAS_FANOUT_EXPANDER_DEVICE);
1528
1529        rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
1530        if (!rdev) {
1531                return NULL;
1532        }
1533
1534        device_initialize(&rdev->rphy.dev);
1535        rdev->rphy.dev.parent = get_device(&parent->dev);
1536        rdev->rphy.dev.release = sas_expander_release;
1537        mutex_lock(&sas_host->lock);
1538        rdev->rphy.scsi_target_id = sas_host->next_expander_id++;
1539        mutex_unlock(&sas_host->lock);
1540        dev_set_name(&rdev->rphy.dev, "expander-%d:%d",
1541                     shost->host_no, rdev->rphy.scsi_target_id);
1542        rdev->rphy.identify.device_type = type;
1543        sas_rphy_initialize(&rdev->rphy);
1544        transport_setup_device(&rdev->rphy.dev);
1545
1546        return &rdev->rphy;
1547}
1548EXPORT_SYMBOL(sas_expander_alloc);
1549
1550/**
1551 * sas_rphy_add  -  add a SAS remote PHY to the device hierarchy
1552 * @rphy:       The remote PHY to be added
1553 *
1554 * Publishes a SAS remote PHY to the rest of the system.
1555 */
1556int sas_rphy_add(struct sas_rphy *rphy)
1557{
1558        struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
1559        struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
1560        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1561        struct sas_identify *identify = &rphy->identify;
1562        int error;
1563
1564        if (parent->rphy)
1565                return -ENXIO;
1566        parent->rphy = rphy;
1567
1568        error = device_add(&rphy->dev);
1569        if (error)
1570                return error;
1571        transport_add_device(&rphy->dev);
1572        transport_configure_device(&rphy->dev);
1573        if (sas_bsg_initialize(shost, rphy))
1574                printk("fail to a bsg device %s\n", dev_name(&rphy->dev));
1575
1576
1577        mutex_lock(&sas_host->lock);
1578        list_add_tail(&rphy->list, &sas_host->rphy_list);
1579        if (identify->device_type == SAS_END_DEVICE &&
1580            (identify->target_port_protocols &
1581             (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))
1582                rphy->scsi_target_id = sas_host->next_target_id++;
1583        else if (identify->device_type == SAS_END_DEVICE)
1584                rphy->scsi_target_id = -1;
1585        mutex_unlock(&sas_host->lock);
1586
1587        if (identify->device_type == SAS_END_DEVICE &&
1588            rphy->scsi_target_id != -1) {
1589                int lun;
1590
1591                if (identify->target_port_protocols & SAS_PROTOCOL_SSP)
1592                        lun = SCAN_WILD_CARD;
1593                else
1594                        lun = 0;
1595
1596                scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun, 0);
1597        }
1598
1599        return 0;
1600}
1601EXPORT_SYMBOL(sas_rphy_add);
1602
1603/**
1604 * sas_rphy_free  -  free a SAS remote PHY
1605 * @rphy: SAS remote PHY to free
1606 *
1607 * Frees the specified SAS remote PHY.
1608 *
1609 * Note:
1610 *   This function must only be called on a remote
1611 *   PHY that has not successfully been added using
1612 *   sas_rphy_add() (or has been sas_rphy_remove()'d)
1613 */
1614void sas_rphy_free(struct sas_rphy *rphy)
1615{
1616        struct device *dev = &rphy->dev;
1617        struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1618        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1619
1620        mutex_lock(&sas_host->lock);
1621        list_del(&rphy->list);
1622        mutex_unlock(&sas_host->lock);
1623
1624        sas_bsg_remove(shost, rphy);
1625
1626        transport_destroy_device(dev);
1627
1628        put_device(dev);
1629}
1630EXPORT_SYMBOL(sas_rphy_free);
1631
1632/**
1633 * sas_rphy_delete  -  remove and free SAS remote PHY
1634 * @rphy:       SAS remote PHY to remove and free
1635 *
1636 * Removes the specified SAS remote PHY and frees it.
1637 */
1638void
1639sas_rphy_delete(struct sas_rphy *rphy)
1640{
1641        sas_rphy_remove(rphy);
1642        sas_rphy_free(rphy);
1643}
1644EXPORT_SYMBOL(sas_rphy_delete);
1645
1646/**
1647 * sas_rphy_unlink  -  unlink SAS remote PHY
1648 * @rphy:       SAS remote phy to unlink from its parent port
1649 *
1650 * Removes port reference to an rphy
1651 */
1652void sas_rphy_unlink(struct sas_rphy *rphy)
1653{
1654        struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
1655
1656        parent->rphy = NULL;
1657}
1658EXPORT_SYMBOL(sas_rphy_unlink);
1659
1660/**
1661 * sas_rphy_remove  -  remove SAS remote PHY
1662 * @rphy:       SAS remote phy to remove
1663 *
1664 * Removes the specified SAS remote PHY.
1665 */
1666void
1667sas_rphy_remove(struct sas_rphy *rphy)
1668{
1669        struct device *dev = &rphy->dev;
1670
1671        switch (rphy->identify.device_type) {
1672        case SAS_END_DEVICE:
1673                scsi_remove_target(dev);
1674                break;
1675        case SAS_EDGE_EXPANDER_DEVICE:
1676        case SAS_FANOUT_EXPANDER_DEVICE:
1677                sas_remove_children(dev);
1678                break;
1679        default:
1680                break;
1681        }
1682
1683        sas_rphy_unlink(rphy);
1684        transport_remove_device(dev);
1685        device_del(dev);
1686}
1687EXPORT_SYMBOL(sas_rphy_remove);
1688
1689/**
1690 * scsi_is_sas_rphy  -  check if a struct device represents a SAS remote PHY
1691 * @dev:        device to check
1692 *
1693 * Returns:
1694 *      %1 if the device represents a SAS remote PHY, %0 else
1695 */
1696int scsi_is_sas_rphy(const struct device *dev)
1697{
1698        return dev->release == sas_end_device_release ||
1699                dev->release == sas_expander_release;
1700}
1701EXPORT_SYMBOL(scsi_is_sas_rphy);
1702
1703
1704/*
1705 * SCSI scan helper
1706 */
1707
1708static int sas_user_scan(struct Scsi_Host *shost, uint channel,
1709                uint id, uint lun)
1710{
1711        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1712        struct sas_rphy *rphy;
1713
1714        mutex_lock(&sas_host->lock);
1715        list_for_each_entry(rphy, &sas_host->rphy_list, list) {
1716                if (rphy->identify.device_type != SAS_END_DEVICE ||
1717                    rphy->scsi_target_id == -1)
1718                        continue;
1719
1720                if ((channel == SCAN_WILD_CARD || channel == 0) &&
1721                    (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
1722                        scsi_scan_target(&rphy->dev, 0,
1723                                         rphy->scsi_target_id, lun, 1);
1724                }
1725        }
1726        mutex_unlock(&sas_host->lock);
1727
1728        return 0;
1729}
1730
1731
1732/*
1733 * Setup / Teardown code
1734 */
1735
1736#define SETUP_TEMPLATE(attrb, field, perm, test)                        \
1737        i->private_##attrb[count] = dev_attr_##field;           \
1738        i->private_##attrb[count].attr.mode = perm;                     \
1739        i->attrb[count] = &i->private_##attrb[count];                   \
1740        if (test)                                                       \
1741                count++
1742
1743#define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm)   \
1744        i->private_##attrb[count] = dev_attr_##field;           \
1745        i->private_##attrb[count].attr.mode = perm;                     \
1746        if (ro_test) {                                                  \
1747                i->private_##attrb[count].attr.mode = ro_perm;          \
1748                i->private_##attrb[count].store = NULL;                 \
1749        }                                                               \
1750        i->attrb[count] = &i->private_##attrb[count];                   \
1751        if (test)                                                       \
1752                count++
1753
1754#define SETUP_RPORT_ATTRIBUTE(field)                                    \
1755        SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1)
1756
1757#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func)                     \
1758        SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func)
1759
1760#define SETUP_PHY_ATTRIBUTE(field)                                      \
1761        SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1)
1762
1763#define SETUP_PHY_ATTRIBUTE_RW(field)                                   \
1764        SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1,       \
1765                        !i->f->set_phy_speed, S_IRUGO)
1766
1767#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func)                    \
1768        SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1,       \
1769                          !i->f->func, S_IRUGO)
1770
1771#define SETUP_PORT_ATTRIBUTE(field)                                     \
1772        SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
1773
1774#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func)                       \
1775        SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func)
1776
1777#define SETUP_PHY_ATTRIBUTE_WRONLY(field)                               \
1778        SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1)
1779
1780#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func)                \
1781        SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func)
1782
1783#define SETUP_END_DEV_ATTRIBUTE(field)                                  \
1784        SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1)
1785
1786#define SETUP_EXPANDER_ATTRIBUTE(field)                                 \
1787        SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1)
1788
1789/**
1790 * sas_attach_transport  -  instantiate SAS transport template
1791 * @ft:         SAS transport class function template
1792 */
1793struct scsi_transport_template *
1794sas_attach_transport(struct sas_function_template *ft)
1795{
1796        struct sas_internal *i;
1797        int count;
1798
1799        i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL);
1800        if (!i)
1801                return NULL;
1802
1803        i->t.user_scan = sas_user_scan;
1804
1805        i->t.host_attrs.ac.attrs = &i->host_attrs[0];
1806        i->t.host_attrs.ac.class = &sas_host_class.class;
1807        i->t.host_attrs.ac.match = sas_host_match;
1808        transport_container_register(&i->t.host_attrs);
1809        i->t.host_size = sizeof(struct sas_host_attrs);
1810
1811        i->phy_attr_cont.ac.class = &sas_phy_class.class;
1812        i->phy_attr_cont.ac.attrs = &i->phy_attrs[0];
1813        i->phy_attr_cont.ac.match = sas_phy_match;
1814        transport_container_register(&i->phy_attr_cont);
1815
1816        i->port_attr_cont.ac.class = &sas_port_class.class;
1817        i->port_attr_cont.ac.attrs = &i->port_attrs[0];
1818        i->port_attr_cont.ac.match = sas_port_match;
1819        transport_container_register(&i->port_attr_cont);
1820
1821        i->rphy_attr_cont.ac.class = &sas_rphy_class.class;
1822        i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0];
1823        i->rphy_attr_cont.ac.match = sas_rphy_match;
1824        transport_container_register(&i->rphy_attr_cont);
1825
1826        i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class;
1827        i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0];
1828        i->end_dev_attr_cont.ac.match = sas_end_dev_match;
1829        transport_container_register(&i->end_dev_attr_cont);
1830
1831        i->expander_attr_cont.ac.class = &sas_expander_class.class;
1832        i->expander_attr_cont.ac.attrs = &i->expander_attrs[0];
1833        i->expander_attr_cont.ac.match = sas_expander_match;
1834        transport_container_register(&i->expander_attr_cont);
1835
1836        i->f = ft;
1837
1838        count = 0;
1839        SETUP_PHY_ATTRIBUTE(initiator_port_protocols);
1840        SETUP_PHY_ATTRIBUTE(target_port_protocols);
1841        SETUP_PHY_ATTRIBUTE(device_type);
1842        SETUP_PHY_ATTRIBUTE(sas_address);
1843        SETUP_PHY_ATTRIBUTE(phy_identifier);
1844        //SETUP_PHY_ATTRIBUTE(port_identifier);
1845        SETUP_PHY_ATTRIBUTE(negotiated_linkrate);
1846        SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw);
1847        SETUP_PHY_ATTRIBUTE_RW(minimum_linkrate);
1848        SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw);
1849        SETUP_PHY_ATTRIBUTE_RW(maximum_linkrate);
1850
1851        SETUP_PHY_ATTRIBUTE(invalid_dword_count);
1852        SETUP_PHY_ATTRIBUTE(running_disparity_error_count);
1853        SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count);
1854        SETUP_PHY_ATTRIBUTE(phy_reset_problem_count);
1855        SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset);
1856        SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset);
1857        SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable);
1858        i->phy_attrs[count] = NULL;
1859
1860        count = 0;
1861        SETUP_PORT_ATTRIBUTE(num_phys);
1862        i->port_attrs[count] = NULL;
1863
1864        count = 0;
1865        SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols);
1866        SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols);
1867        SETUP_RPORT_ATTRIBUTE(rphy_device_type);
1868        SETUP_RPORT_ATTRIBUTE(rphy_sas_address);
1869        SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier);
1870        SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier,
1871                                       get_enclosure_identifier);
1872        SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier,
1873                                       get_bay_identifier);
1874        i->rphy_attrs[count] = NULL;
1875
1876        count = 0;
1877        SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning);
1878        SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout);
1879        SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout);
1880        SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_supported);
1881        SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_enabled);
1882        i->end_dev_attrs[count] = NULL;
1883
1884        count = 0;
1885        SETUP_EXPANDER_ATTRIBUTE(vendor_id);
1886        SETUP_EXPANDER_ATTRIBUTE(product_id);
1887        SETUP_EXPANDER_ATTRIBUTE(product_rev);
1888        SETUP_EXPANDER_ATTRIBUTE(component_vendor_id);
1889        SETUP_EXPANDER_ATTRIBUTE(component_id);
1890        SETUP_EXPANDER_ATTRIBUTE(component_revision_id);
1891        SETUP_EXPANDER_ATTRIBUTE(level);
1892        i->expander_attrs[count] = NULL;
1893
1894        return &i->t;
1895}
1896EXPORT_SYMBOL(sas_attach_transport);
1897
1898/**
1899 * sas_release_transport  -  release SAS transport template instance
1900 * @t:          transport template instance
1901 */
1902void sas_release_transport(struct scsi_transport_template *t)
1903{
1904        struct sas_internal *i = to_sas_internal(t);
1905
1906        transport_container_unregister(&i->t.host_attrs);
1907        transport_container_unregister(&i->phy_attr_cont);
1908        transport_container_unregister(&i->port_attr_cont);
1909        transport_container_unregister(&i->rphy_attr_cont);
1910        transport_container_unregister(&i->end_dev_attr_cont);
1911        transport_container_unregister(&i->expander_attr_cont);
1912
1913        kfree(i);
1914}
1915EXPORT_SYMBOL(sas_release_transport);
1916
1917static __init int sas_transport_init(void)
1918{
1919        int error;
1920
1921        error = transport_class_register(&sas_host_class);
1922        if (error)
1923                goto out;
1924        error = transport_class_register(&sas_phy_class);
1925        if (error)
1926                goto out_unregister_transport;
1927        error = transport_class_register(&sas_port_class);
1928        if (error)
1929                goto out_unregister_phy;
1930        error = transport_class_register(&sas_rphy_class);
1931        if (error)
1932                goto out_unregister_port;
1933        error = transport_class_register(&sas_end_dev_class);
1934        if (error)
1935                goto out_unregister_rphy;
1936        error = transport_class_register(&sas_expander_class);
1937        if (error)
1938                goto out_unregister_end_dev;
1939
1940        return 0;
1941
1942 out_unregister_end_dev:
1943        transport_class_unregister(&sas_end_dev_class);
1944 out_unregister_rphy:
1945        transport_class_unregister(&sas_rphy_class);
1946 out_unregister_port:
1947        transport_class_unregister(&sas_port_class);
1948 out_unregister_phy:
1949        transport_class_unregister(&sas_phy_class);
1950 out_unregister_transport:
1951        transport_class_unregister(&sas_host_class);
1952 out:
1953        return error;
1954
1955}
1956
1957static void __exit sas_transport_exit(void)
1958{
1959        transport_class_unregister(&sas_host_class);
1960        transport_class_unregister(&sas_phy_class);
1961        transport_class_unregister(&sas_port_class);
1962        transport_class_unregister(&sas_rphy_class);
1963        transport_class_unregister(&sas_end_dev_class);
1964        transport_class_unregister(&sas_expander_class);
1965}
1966
1967MODULE_AUTHOR("Christoph Hellwig");
1968MODULE_DESCRIPTION("SAS Transport Attributes");
1969MODULE_LICENSE("GPL");
1970
1971module_init(sas_transport_init);
1972module_exit(sas_transport_exit);
1973
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.