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