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