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