scsi_transport_sas.c revision 65c92b09acf0218b64f1c7ba4fdabeb8b732c876
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/err.h> 29#include <linux/slab.h> 30#include <linux/string.h> 31 32#include <scsi/scsi.h> 33#include <scsi/scsi_device.h> 34#include <scsi/scsi_host.h> 35#include <scsi/scsi_transport.h> 36#include <scsi/scsi_transport_sas.h> 37 38#include "scsi_sas_internal.h" 39struct sas_host_attrs { 40 struct list_head rphy_list; 41 struct mutex lock; 42 u32 next_target_id; 43 u32 next_expander_id; 44}; 45#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) 46 47 48/* 49 * Hack to allow attributes of the same name in different objects. 50 */ 51#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \ 52 struct class_device_attribute class_device_attr_##_prefix##_##_name = \ 53 __ATTR(_name,_mode,_show,_store) 54 55 56/* 57 * Pretty printing helpers 58 */ 59 60#define sas_bitfield_name_match(title, table) \ 61static ssize_t \ 62get_sas_##title##_names(u32 table_key, char *buf) \ 63{ \ 64 char *prefix = ""; \ 65 ssize_t len = 0; \ 66 int i; \ 67 \ 68 for (i = 0; i < ARRAY_SIZE(table); i++) { \ 69 if (table[i].value & table_key) { \ 70 len += sprintf(buf + len, "%s%s", \ 71 prefix, table[i].name); \ 72 prefix = ", "; \ 73 } \ 74 } \ 75 len += sprintf(buf + len, "\n"); \ 76 return len; \ 77} 78 79#define sas_bitfield_name_search(title, table) \ 80static ssize_t \ 81get_sas_##title##_names(u32 table_key, char *buf) \ 82{ \ 83 ssize_t len = 0; \ 84 int i; \ 85 \ 86 for (i = 0; i < ARRAY_SIZE(table); i++) { \ 87 if (table[i].value == table_key) { \ 88 len += sprintf(buf + len, "%s", \ 89 table[i].name); \ 90 break; \ 91 } \ 92 } \ 93 len += sprintf(buf + len, "\n"); \ 94 return len; \ 95} 96 97static struct { 98 u32 value; 99 char *name; 100} sas_device_type_names[] = { 101 { SAS_PHY_UNUSED, "unused" }, 102 { SAS_END_DEVICE, "end device" }, 103 { SAS_EDGE_EXPANDER_DEVICE, "edge expander" }, 104 { SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" }, 105}; 106sas_bitfield_name_search(device_type, sas_device_type_names) 107 108 109static struct { 110 u32 value; 111 char *name; 112} sas_protocol_names[] = { 113 { SAS_PROTOCOL_SATA, "sata" }, 114 { SAS_PROTOCOL_SMP, "smp" }, 115 { SAS_PROTOCOL_STP, "stp" }, 116 { SAS_PROTOCOL_SSP, "ssp" }, 117}; 118sas_bitfield_name_match(protocol, sas_protocol_names) 119 120static struct { 121 u32 value; 122 char *name; 123} sas_linkspeed_names[] = { 124 { SAS_LINK_RATE_UNKNOWN, "Unknown" }, 125 { SAS_PHY_DISABLED, "Phy disabled" }, 126 { SAS_LINK_RATE_FAILED, "Link Rate failed" }, 127 { SAS_SATA_SPINUP_HOLD, "Spin-up hold" }, 128 { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, 129 { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, 130 { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, 131}; 132sas_bitfield_name_search(linkspeed, sas_linkspeed_names) 133 134 135/* 136 * SAS host attributes 137 */ 138 139static int sas_host_setup(struct transport_container *tc, struct device *dev, 140 struct class_device *cdev) 141{ 142 struct Scsi_Host *shost = dev_to_shost(dev); 143 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 144 145 INIT_LIST_HEAD(&sas_host->rphy_list); 146 mutex_init(&sas_host->lock); 147 sas_host->next_target_id = 0; 148 sas_host->next_expander_id = 0; 149 return 0; 150} 151 152static DECLARE_TRANSPORT_CLASS(sas_host_class, 153 "sas_host", sas_host_setup, NULL, NULL); 154 155static int sas_host_match(struct attribute_container *cont, 156 struct device *dev) 157{ 158 struct Scsi_Host *shost; 159 struct sas_internal *i; 160 161 if (!scsi_is_host_device(dev)) 162 return 0; 163 shost = dev_to_shost(dev); 164 165 if (!shost->transportt) 166 return 0; 167 if (shost->transportt->host_attrs.ac.class != 168 &sas_host_class.class) 169 return 0; 170 171 i = to_sas_internal(shost->transportt); 172 return &i->t.host_attrs.ac == cont; 173} 174 175static int do_sas_phy_delete(struct device *dev, void *data) 176{ 177 int pass = (int)(unsigned long)data; 178 179 if (pass == 0 && scsi_is_sas_port(dev)) 180 sas_port_delete(dev_to_sas_port(dev)); 181 else if (pass == 1 && scsi_is_sas_phy(dev)) 182 sas_phy_delete(dev_to_phy(dev)); 183 return 0; 184} 185 186/** 187 * sas_remove_children -- tear down a devices SAS data structures 188 * @dev: device belonging to the sas object 189 * 190 * Removes all SAS PHYs and remote PHYs for a given object 191 */ 192void sas_remove_children(struct device *dev) 193{ 194 device_for_each_child(dev, (void *)0, do_sas_phy_delete); 195 device_for_each_child(dev, (void *)1, do_sas_phy_delete); 196} 197EXPORT_SYMBOL(sas_remove_children); 198 199/** 200 * sas_remove_host -- tear down a Scsi_Host's SAS data structures 201 * @shost: Scsi Host that is torn down 202 * 203 * Removes all SAS PHYs and remote PHYs for a given Scsi_Host. 204 * Must be called just before scsi_remove_host for SAS HBAs. 205 */ 206void sas_remove_host(struct Scsi_Host *shost) 207{ 208 sas_remove_children(&shost->shost_gendev); 209} 210EXPORT_SYMBOL(sas_remove_host); 211 212 213/* 214 * SAS Phy attributes 215 */ 216 217#define sas_phy_show_simple(field, name, format_string, cast) \ 218static ssize_t \ 219show_sas_phy_##name(struct class_device *cdev, char *buf) \ 220{ \ 221 struct sas_phy *phy = transport_class_to_phy(cdev); \ 222 \ 223 return snprintf(buf, 20, format_string, cast phy->field); \ 224} 225 226#define sas_phy_simple_attr(field, name, format_string, type) \ 227 sas_phy_show_simple(field, name, format_string, (type)) \ 228static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 229 230#define sas_phy_show_protocol(field, name) \ 231static ssize_t \ 232show_sas_phy_##name(struct class_device *cdev, char *buf) \ 233{ \ 234 struct sas_phy *phy = transport_class_to_phy(cdev); \ 235 \ 236 if (!phy->field) \ 237 return snprintf(buf, 20, "none\n"); \ 238 return get_sas_protocol_names(phy->field, buf); \ 239} 240 241#define sas_phy_protocol_attr(field, name) \ 242 sas_phy_show_protocol(field, name) \ 243static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 244 245#define sas_phy_show_linkspeed(field) \ 246static ssize_t \ 247show_sas_phy_##field(struct class_device *cdev, char *buf) \ 248{ \ 249 struct sas_phy *phy = transport_class_to_phy(cdev); \ 250 \ 251 return get_sas_linkspeed_names(phy->field, buf); \ 252} 253 254#define sas_phy_linkspeed_attr(field) \ 255 sas_phy_show_linkspeed(field) \ 256static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 257 258#define sas_phy_show_linkerror(field) \ 259static ssize_t \ 260show_sas_phy_##field(struct class_device *cdev, char *buf) \ 261{ \ 262 struct sas_phy *phy = transport_class_to_phy(cdev); \ 263 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \ 264 struct sas_internal *i = to_sas_internal(shost->transportt); \ 265 int error; \ 266 \ 267 if (!phy->local_attached) \ 268 return -EINVAL; \ 269 \ 270 error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0; \ 271 if (error) \ 272 return error; \ 273 return snprintf(buf, 20, "%u\n", phy->field); \ 274} 275 276#define sas_phy_linkerror_attr(field) \ 277 sas_phy_show_linkerror(field) \ 278static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 279 280 281static ssize_t 282show_sas_device_type(struct class_device *cdev, char *buf) 283{ 284 struct sas_phy *phy = transport_class_to_phy(cdev); 285 286 if (!phy->identify.device_type) 287 return snprintf(buf, 20, "none\n"); 288 return get_sas_device_type_names(phy->identify.device_type, buf); 289} 290static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); 291 292static ssize_t do_sas_phy_reset(struct class_device *cdev, 293 size_t count, int hard_reset) 294{ 295 struct sas_phy *phy = transport_class_to_phy(cdev); 296 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 297 struct sas_internal *i = to_sas_internal(shost->transportt); 298 int error; 299 300 if (!phy->local_attached) 301 return -EINVAL; 302 303 error = i->f->phy_reset(phy, hard_reset); 304 if (error) 305 return error; 306 return count; 307}; 308 309static ssize_t store_sas_link_reset(struct class_device *cdev, 310 const char *buf, size_t count) 311{ 312 return do_sas_phy_reset(cdev, count, 0); 313} 314static CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); 315 316static ssize_t store_sas_hard_reset(struct class_device *cdev, 317 const char *buf, size_t count) 318{ 319 return do_sas_phy_reset(cdev, count, 1); 320} 321static CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); 322 323sas_phy_protocol_attr(identify.initiator_port_protocols, 324 initiator_port_protocols); 325sas_phy_protocol_attr(identify.target_port_protocols, 326 target_port_protocols); 327sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 328 unsigned long long); 329sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 330//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8); 331sas_phy_linkspeed_attr(negotiated_linkrate); 332sas_phy_linkspeed_attr(minimum_linkrate_hw); 333sas_phy_linkspeed_attr(minimum_linkrate); 334sas_phy_linkspeed_attr(maximum_linkrate_hw); 335sas_phy_linkspeed_attr(maximum_linkrate); 336sas_phy_linkerror_attr(invalid_dword_count); 337sas_phy_linkerror_attr(running_disparity_error_count); 338sas_phy_linkerror_attr(loss_of_dword_sync_count); 339sas_phy_linkerror_attr(phy_reset_problem_count); 340 341 342static DECLARE_TRANSPORT_CLASS(sas_phy_class, 343 "sas_phy", NULL, NULL, NULL); 344 345static int sas_phy_match(struct attribute_container *cont, struct device *dev) 346{ 347 struct Scsi_Host *shost; 348 struct sas_internal *i; 349 350 if (!scsi_is_sas_phy(dev)) 351 return 0; 352 shost = dev_to_shost(dev->parent); 353 354 if (!shost->transportt) 355 return 0; 356 if (shost->transportt->host_attrs.ac.class != 357 &sas_host_class.class) 358 return 0; 359 360 i = to_sas_internal(shost->transportt); 361 return &i->phy_attr_cont.ac == cont; 362} 363 364static void sas_phy_release(struct device *dev) 365{ 366 struct sas_phy *phy = dev_to_phy(dev); 367 368 put_device(dev->parent); 369 kfree(phy); 370} 371 372/** 373 * sas_phy_alloc -- allocates and initialize a SAS PHY structure 374 * @parent: Parent device 375 * @number: Phy index 376 * 377 * Allocates an SAS PHY structure. It will be added in the device tree 378 * below the device specified by @parent, which has to be either a Scsi_Host 379 * or sas_rphy. 380 * 381 * Returns: 382 * SAS PHY allocated or %NULL if the allocation failed. 383 */ 384struct sas_phy *sas_phy_alloc(struct device *parent, int number) 385{ 386 struct Scsi_Host *shost = dev_to_shost(parent); 387 struct sas_phy *phy; 388 389 phy = kzalloc(sizeof(*phy), GFP_KERNEL); 390 if (!phy) 391 return NULL; 392 393 phy->number = number; 394 395 device_initialize(&phy->dev); 396 phy->dev.parent = get_device(parent); 397 phy->dev.release = sas_phy_release; 398 INIT_LIST_HEAD(&phy->port_siblings); 399 if (scsi_is_sas_expander_device(parent)) { 400 struct sas_rphy *rphy = dev_to_rphy(parent); 401 sprintf(phy->dev.bus_id, "phy-%d:%d:%d", shost->host_no, 402 rphy->scsi_target_id, number); 403 } else 404 sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); 405 406 transport_setup_device(&phy->dev); 407 408 return phy; 409} 410EXPORT_SYMBOL(sas_phy_alloc); 411 412/** 413 * sas_phy_add -- add a SAS PHY to the device hierachy 414 * @phy: The PHY to be added 415 * 416 * Publishes a SAS PHY to the rest of the system. 417 */ 418int sas_phy_add(struct sas_phy *phy) 419{ 420 int error; 421 422 error = device_add(&phy->dev); 423 if (!error) { 424 transport_add_device(&phy->dev); 425 transport_configure_device(&phy->dev); 426 } 427 428 return error; 429} 430EXPORT_SYMBOL(sas_phy_add); 431 432/** 433 * sas_phy_free -- free a SAS PHY 434 * @phy: SAS PHY to free 435 * 436 * Frees the specified SAS PHY. 437 * 438 * Note: 439 * This function must only be called on a PHY that has not 440 * sucessfully been added using sas_phy_add(). 441 */ 442void sas_phy_free(struct sas_phy *phy) 443{ 444 transport_destroy_device(&phy->dev); 445 put_device(&phy->dev); 446} 447EXPORT_SYMBOL(sas_phy_free); 448 449/** 450 * sas_phy_delete -- remove SAS PHY 451 * @phy: SAS PHY to remove 452 * 453 * Removes the specified SAS PHY. If the SAS PHY has an 454 * associated remote PHY it is removed before. 455 */ 456void 457sas_phy_delete(struct sas_phy *phy) 458{ 459 struct device *dev = &phy->dev; 460 461 /* this happens if the phy is still part of a port when deleted */ 462 BUG_ON(!list_empty(&phy->port_siblings)); 463 464 transport_remove_device(dev); 465 device_del(dev); 466 transport_destroy_device(dev); 467 put_device(dev); 468} 469EXPORT_SYMBOL(sas_phy_delete); 470 471/** 472 * scsi_is_sas_phy -- check if a struct device represents a SAS PHY 473 * @dev: device to check 474 * 475 * Returns: 476 * %1 if the device represents a SAS PHY, %0 else 477 */ 478int scsi_is_sas_phy(const struct device *dev) 479{ 480 return dev->release == sas_phy_release; 481} 482EXPORT_SYMBOL(scsi_is_sas_phy); 483 484/* 485 * SAS Port attributes 486 */ 487#define sas_port_show_simple(field, name, format_string, cast) \ 488static ssize_t \ 489show_sas_port_##name(struct class_device *cdev, char *buf) \ 490{ \ 491 struct sas_port *port = transport_class_to_sas_port(cdev); \ 492 \ 493 return snprintf(buf, 20, format_string, cast port->field); \ 494} 495 496#define sas_port_simple_attr(field, name, format_string, type) \ 497 sas_port_show_simple(field, name, format_string, (type)) \ 498static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL) 499 500sas_port_simple_attr(num_phys, num_phys, "%d\n", int); 501 502static DECLARE_TRANSPORT_CLASS(sas_port_class, 503 "sas_port", NULL, NULL, NULL); 504 505static int sas_port_match(struct attribute_container *cont, struct device *dev) 506{ 507 struct Scsi_Host *shost; 508 struct sas_internal *i; 509 510 if (!scsi_is_sas_port(dev)) 511 return 0; 512 shost = dev_to_shost(dev->parent); 513 514 if (!shost->transportt) 515 return 0; 516 if (shost->transportt->host_attrs.ac.class != 517 &sas_host_class.class) 518 return 0; 519 520 i = to_sas_internal(shost->transportt); 521 return &i->port_attr_cont.ac == cont; 522} 523 524 525static void sas_port_release(struct device *dev) 526{ 527 struct sas_port *port = dev_to_sas_port(dev); 528 529 BUG_ON(!list_empty(&port->phy_list)); 530 531 put_device(dev->parent); 532 kfree(port); 533} 534 535static void sas_port_create_link(struct sas_port *port, 536 struct sas_phy *phy) 537{ 538 sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, phy->dev.bus_id); 539 sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port"); 540} 541 542static void sas_port_delete_link(struct sas_port *port, 543 struct sas_phy *phy) 544{ 545 sysfs_remove_link(&port->dev.kobj, phy->dev.bus_id); 546 sysfs_remove_link(&phy->dev.kobj, "port"); 547} 548 549/** sas_port_alloc - allocate and initialize a SAS port structure 550 * 551 * @parent: parent device 552 * @port_id: port number 553 * 554 * Allocates a SAS port structure. It will be added to the device tree 555 * below the device specified by @parent which must be either a Scsi_Host 556 * or a sas_expander_device. 557 * 558 * Returns %NULL on error 559 */ 560struct sas_port *sas_port_alloc(struct device *parent, int port_id) 561{ 562 struct Scsi_Host *shost = dev_to_shost(parent); 563 struct sas_port *port; 564 565 port = kzalloc(sizeof(*port), GFP_KERNEL); 566 if (!port) 567 return NULL; 568 569 port->port_identifier = port_id; 570 571 device_initialize(&port->dev); 572 573 port->dev.parent = get_device(parent); 574 port->dev.release = sas_port_release; 575 576 mutex_init(&port->phy_list_mutex); 577 INIT_LIST_HEAD(&port->phy_list); 578 579 if (scsi_is_sas_expander_device(parent)) { 580 struct sas_rphy *rphy = dev_to_rphy(parent); 581 sprintf(port->dev.bus_id, "port-%d:%d:%d", shost->host_no, 582 rphy->scsi_target_id, port->port_identifier); 583 } else 584 sprintf(port->dev.bus_id, "port-%d:%d", shost->host_no, 585 port->port_identifier); 586 587 transport_setup_device(&port->dev); 588 589 return port; 590} 591EXPORT_SYMBOL(sas_port_alloc); 592 593/** 594 * sas_port_add - add a SAS port to the device hierarchy 595 * 596 * @port: port to be added 597 * 598 * publishes a port to the rest of the system 599 */ 600int sas_port_add(struct sas_port *port) 601{ 602 int error; 603 604 /* No phys should be added until this is made visible */ 605 BUG_ON(!list_empty(&port->phy_list)); 606 607 error = device_add(&port->dev); 608 609 if (error) 610 return error; 611 612 transport_add_device(&port->dev); 613 transport_configure_device(&port->dev); 614 615 return 0; 616} 617EXPORT_SYMBOL(sas_port_add); 618 619/** 620 * sas_port_free -- free a SAS PORT 621 * @port: SAS PORT to free 622 * 623 * Frees the specified SAS PORT. 624 * 625 * Note: 626 * This function must only be called on a PORT that has not 627 * sucessfully been added using sas_port_add(). 628 */ 629void sas_port_free(struct sas_port *port) 630{ 631 transport_destroy_device(&port->dev); 632 put_device(&port->dev); 633} 634EXPORT_SYMBOL(sas_port_free); 635 636/** 637 * sas_port_delete -- remove SAS PORT 638 * @port: SAS PORT to remove 639 * 640 * Removes the specified SAS PORT. If the SAS PORT has an 641 * associated phys, unlink them from the port as well. 642 */ 643void sas_port_delete(struct sas_port *port) 644{ 645 struct device *dev = &port->dev; 646 struct sas_phy *phy, *tmp_phy; 647 648 if (port->rphy) { 649 sas_rphy_delete(port->rphy); 650 port->rphy = NULL; 651 } 652 653 mutex_lock(&port->phy_list_mutex); 654 list_for_each_entry_safe(phy, tmp_phy, &port->phy_list, 655 port_siblings) { 656 sas_port_delete_link(port, phy); 657 list_del_init(&phy->port_siblings); 658 } 659 mutex_unlock(&port->phy_list_mutex); 660 661 transport_remove_device(dev); 662 device_del(dev); 663 transport_destroy_device(dev); 664 put_device(dev); 665} 666EXPORT_SYMBOL(sas_port_delete); 667 668/** 669 * scsi_is_sas_port -- check if a struct device represents a SAS port 670 * @dev: device to check 671 * 672 * Returns: 673 * %1 if the device represents a SAS Port, %0 else 674 */ 675int scsi_is_sas_port(const struct device *dev) 676{ 677 return dev->release == sas_port_release; 678} 679EXPORT_SYMBOL(scsi_is_sas_port); 680 681/** 682 * sas_port_add_phy - add another phy to a port to form a wide port 683 * @port: port to add the phy to 684 * @phy: phy to add 685 * 686 * When a port is initially created, it is empty (has no phys). All 687 * ports must have at least one phy to operated, and all wide ports 688 * must have at least two. The current code makes no difference 689 * between ports and wide ports, but the only object that can be 690 * connected to a remote device is a port, so ports must be formed on 691 * all devices with phys if they're connected to anything. 692 */ 693void sas_port_add_phy(struct sas_port *port, struct sas_phy *phy) 694{ 695 mutex_lock(&port->phy_list_mutex); 696 if (unlikely(!list_empty(&phy->port_siblings))) { 697 /* make sure we're already on this port */ 698 struct sas_phy *tmp; 699 700 list_for_each_entry(tmp, &port->phy_list, port_siblings) 701 if (tmp == phy) 702 break; 703 /* If this trips, you added a phy that was already 704 * part of a different port */ 705 if (unlikely(tmp != phy)) { 706 dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n", phy->dev.bus_id); 707 BUG(); 708 } 709 } else { 710 sas_port_create_link(port, phy); 711 list_add_tail(&phy->port_siblings, &port->phy_list); 712 port->num_phys++; 713 } 714 mutex_unlock(&port->phy_list_mutex); 715} 716EXPORT_SYMBOL(sas_port_add_phy); 717 718/** 719 * sas_port_delete_phy - remove a phy from a port or wide port 720 * @port: port to remove the phy from 721 * @phy: phy to remove 722 * 723 * This operation is used for tearing down ports again. It must be 724 * done to every port or wide port before calling sas_port_delete. 725 */ 726void sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy) 727{ 728 mutex_lock(&port->phy_list_mutex); 729 sas_port_delete_link(port, phy); 730 list_del_init(&phy->port_siblings); 731 port->num_phys--; 732 mutex_unlock(&port->phy_list_mutex); 733} 734EXPORT_SYMBOL(sas_port_delete_phy); 735 736/* 737 * SAS remote PHY attributes. 738 */ 739 740#define sas_rphy_show_simple(field, name, format_string, cast) \ 741static ssize_t \ 742show_sas_rphy_##name(struct class_device *cdev, char *buf) \ 743{ \ 744 struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 745 \ 746 return snprintf(buf, 20, format_string, cast rphy->field); \ 747} 748 749#define sas_rphy_simple_attr(field, name, format_string, type) \ 750 sas_rphy_show_simple(field, name, format_string, (type)) \ 751static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 752 show_sas_rphy_##name, NULL) 753 754#define sas_rphy_show_protocol(field, name) \ 755static ssize_t \ 756show_sas_rphy_##name(struct class_device *cdev, char *buf) \ 757{ \ 758 struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 759 \ 760 if (!rphy->field) \ 761 return snprintf(buf, 20, "none\n"); \ 762 return get_sas_protocol_names(rphy->field, buf); \ 763} 764 765#define sas_rphy_protocol_attr(field, name) \ 766 sas_rphy_show_protocol(field, name) \ 767static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 768 show_sas_rphy_##name, NULL) 769 770static ssize_t 771show_sas_rphy_device_type(struct class_device *cdev, char *buf) 772{ 773 struct sas_rphy *rphy = transport_class_to_rphy(cdev); 774 775 if (!rphy->identify.device_type) 776 return snprintf(buf, 20, "none\n"); 777 return get_sas_device_type_names( 778 rphy->identify.device_type, buf); 779} 780 781static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, 782 show_sas_rphy_device_type, NULL); 783 784static ssize_t 785show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf) 786{ 787 struct sas_rphy *rphy = transport_class_to_rphy(cdev); 788 struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 789 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 790 struct sas_internal *i = to_sas_internal(shost->transportt); 791 u64 identifier; 792 int error; 793 794 /* 795 * Only devices behind an expander are supported, because the 796 * enclosure identifier is a SMP feature. 797 */ 798 if (phy->local_attached) 799 return -EINVAL; 800 801 error = i->f->get_enclosure_identifier(rphy, &identifier); 802 if (error) 803 return error; 804 return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); 805} 806 807static SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, 808 show_sas_rphy_enclosure_identifier, NULL); 809 810static ssize_t 811show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf) 812{ 813 struct sas_rphy *rphy = transport_class_to_rphy(cdev); 814 struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 815 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 816 struct sas_internal *i = to_sas_internal(shost->transportt); 817 int val; 818 819 if (phy->local_attached) 820 return -EINVAL; 821 822 val = i->f->get_bay_identifier(rphy); 823 if (val < 0) 824 return val; 825 return sprintf(buf, "%d\n", val); 826} 827 828static SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, 829 show_sas_rphy_bay_identifier, NULL); 830 831sas_rphy_protocol_attr(identify.initiator_port_protocols, 832 initiator_port_protocols); 833sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); 834sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 835 unsigned long long); 836sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 837 838/* only need 8 bytes of data plus header (4 or 8) */ 839#define BUF_SIZE 64 840 841int sas_read_port_mode_page(struct scsi_device *sdev) 842{ 843 char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; 844 struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target); 845 struct sas_end_device *rdev; 846 struct scsi_mode_data mode_data; 847 int res, error; 848 849 BUG_ON(rphy->identify.device_type != SAS_END_DEVICE); 850 851 rdev = rphy_to_end_device(rphy); 852 853 if (!buffer) 854 return -ENOMEM; 855 856 res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, 857 &mode_data, NULL); 858 859 error = -EINVAL; 860 if (!scsi_status_is_good(res)) 861 goto out; 862 863 msdata = buffer + mode_data.header_length + 864 mode_data.block_descriptor_length; 865 866 if (msdata - buffer > BUF_SIZE - 8) 867 goto out; 868 869 error = 0; 870 871 rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0; 872 rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5]; 873 rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7]; 874 875 out: 876 kfree(buffer); 877 return error; 878} 879EXPORT_SYMBOL(sas_read_port_mode_page); 880 881static DECLARE_TRANSPORT_CLASS(sas_end_dev_class, 882 "sas_end_device", NULL, NULL, NULL); 883 884#define sas_end_dev_show_simple(field, name, format_string, cast) \ 885static ssize_t \ 886show_sas_end_dev_##name(struct class_device *cdev, char *buf) \ 887{ \ 888 struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 889 struct sas_end_device *rdev = rphy_to_end_device(rphy); \ 890 \ 891 return snprintf(buf, 20, format_string, cast rdev->field); \ 892} 893 894#define sas_end_dev_simple_attr(field, name, format_string, type) \ 895 sas_end_dev_show_simple(field, name, format_string, (type)) \ 896static SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ 897 show_sas_end_dev_##name, NULL) 898 899sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); 900sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, 901 "%d\n", int); 902sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, 903 "%d\n", int); 904 905static DECLARE_TRANSPORT_CLASS(sas_expander_class, 906 "sas_expander", NULL, NULL, NULL); 907 908#define sas_expander_show_simple(field, name, format_string, cast) \ 909static ssize_t \ 910show_sas_expander_##name(struct class_device *cdev, char *buf) \ 911{ \ 912 struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 913 struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ 914 \ 915 return snprintf(buf, 20, format_string, cast edev->field); \ 916} 917 918#define sas_expander_simple_attr(field, name, format_string, type) \ 919 sas_expander_show_simple(field, name, format_string, (type)) \ 920static SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, \ 921 show_sas_expander_##name, NULL) 922 923sas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); 924sas_expander_simple_attr(product_id, product_id, "%s\n", char *); 925sas_expander_simple_attr(product_rev, product_rev, "%s\n", char *); 926sas_expander_simple_attr(component_vendor_id, component_vendor_id, 927 "%s\n", char *); 928sas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int); 929sas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", 930 unsigned int); 931sas_expander_simple_attr(level, level, "%d\n", int); 932 933static DECLARE_TRANSPORT_CLASS(sas_rphy_class, 934 "sas_device", NULL, NULL, NULL); 935 936static int sas_rphy_match(struct attribute_container *cont, struct device *dev) 937{ 938 struct Scsi_Host *shost; 939 struct sas_internal *i; 940 941 if (!scsi_is_sas_rphy(dev)) 942 return 0; 943 shost = dev_to_shost(dev->parent->parent); 944 945 if (!shost->transportt) 946 return 0; 947 if (shost->transportt->host_attrs.ac.class != 948 &sas_host_class.class) 949 return 0; 950 951 i = to_sas_internal(shost->transportt); 952 return &i->rphy_attr_cont.ac == cont; 953} 954 955static int sas_end_dev_match(struct attribute_container *cont, 956 struct device *dev) 957{ 958 struct Scsi_Host *shost; 959 struct sas_internal *i; 960 struct sas_rphy *rphy; 961 962 if (!scsi_is_sas_rphy(dev)) 963 return 0; 964 shost = dev_to_shost(dev->parent->parent); 965 rphy = dev_to_rphy(dev); 966 967 if (!shost->transportt) 968 return 0; 969 if (shost->transportt->host_attrs.ac.class != 970 &sas_host_class.class) 971 return 0; 972 973 i = to_sas_internal(shost->transportt); 974 return &i->end_dev_attr_cont.ac == cont && 975 rphy->identify.device_type == SAS_END_DEVICE; 976} 977 978static int sas_expander_match(struct attribute_container *cont, 979 struct device *dev) 980{ 981 struct Scsi_Host *shost; 982 struct sas_internal *i; 983 struct sas_rphy *rphy; 984 985 if (!scsi_is_sas_rphy(dev)) 986 return 0; 987 shost = dev_to_shost(dev->parent->parent); 988 rphy = dev_to_rphy(dev); 989 990 if (!shost->transportt) 991 return 0; 992 if (shost->transportt->host_attrs.ac.class != 993 &sas_host_class.class) 994 return 0; 995 996 i = to_sas_internal(shost->transportt); 997 return &i->expander_attr_cont.ac == cont && 998 (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || 999 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE); 1000} 1001 1002static void sas_expander_release(struct device *dev) 1003{ 1004 struct sas_rphy *rphy = dev_to_rphy(dev); 1005 struct sas_expander_device *edev = rphy_to_expander_device(rphy); 1006 1007 put_device(dev->parent); 1008 kfree(edev); 1009} 1010 1011static void sas_end_device_release(struct device *dev) 1012{ 1013 struct sas_rphy *rphy = dev_to_rphy(dev); 1014 struct sas_end_device *edev = rphy_to_end_device(rphy); 1015 1016 put_device(dev->parent); 1017 kfree(edev); 1018} 1019 1020/** 1021 * sas_rphy_initialize - common rphy intialization 1022 * @rphy: rphy to initialise 1023 * 1024 * Used by both sas_end_device_alloc() and sas_expander_alloc() to 1025 * initialise the common rphy component of each. 1026 */ 1027static void sas_rphy_initialize(struct sas_rphy *rphy) 1028{ 1029 INIT_LIST_HEAD(&rphy->list); 1030} 1031 1032/** 1033 * sas_end_device_alloc - allocate an rphy for an end device 1034 * 1035 * Allocates an SAS remote PHY structure, connected to @parent. 1036 * 1037 * Returns: 1038 * SAS PHY allocated or %NULL if the allocation failed. 1039 */ 1040struct sas_rphy *sas_end_device_alloc(struct sas_port *parent) 1041{ 1042 struct Scsi_Host *shost = dev_to_shost(&parent->dev); 1043 struct sas_end_device *rdev; 1044 1045 rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 1046 if (!rdev) { 1047 return NULL; 1048 } 1049 1050 device_initialize(&rdev->rphy.dev); 1051 rdev->rphy.dev.parent = get_device(&parent->dev); 1052 rdev->rphy.dev.release = sas_end_device_release; 1053 if (scsi_is_sas_expander_device(parent->dev.parent)) { 1054 struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent); 1055 sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d:%d", 1056 shost->host_no, rphy->scsi_target_id, parent->port_identifier); 1057 } else 1058 sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d", 1059 shost->host_no, parent->port_identifier); 1060 rdev->rphy.identify.device_type = SAS_END_DEVICE; 1061 sas_rphy_initialize(&rdev->rphy); 1062 transport_setup_device(&rdev->rphy.dev); 1063 1064 return &rdev->rphy; 1065} 1066EXPORT_SYMBOL(sas_end_device_alloc); 1067 1068/** 1069 * sas_expander_alloc - allocate an rphy for an end device 1070 * 1071 * Allocates an SAS remote PHY structure, connected to @parent. 1072 * 1073 * Returns: 1074 * SAS PHY allocated or %NULL if the allocation failed. 1075 */ 1076struct sas_rphy *sas_expander_alloc(struct sas_port *parent, 1077 enum sas_device_type type) 1078{ 1079 struct Scsi_Host *shost = dev_to_shost(&parent->dev); 1080 struct sas_expander_device *rdev; 1081 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1082 1083 BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE && 1084 type != SAS_FANOUT_EXPANDER_DEVICE); 1085 1086 rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 1087 if (!rdev) { 1088 return NULL; 1089 } 1090 1091 device_initialize(&rdev->rphy.dev); 1092 rdev->rphy.dev.parent = get_device(&parent->dev); 1093 rdev->rphy.dev.release = sas_expander_release; 1094 mutex_lock(&sas_host->lock); 1095 rdev->rphy.scsi_target_id = sas_host->next_expander_id++; 1096 mutex_unlock(&sas_host->lock); 1097 sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", 1098 shost->host_no, rdev->rphy.scsi_target_id); 1099 rdev->rphy.identify.device_type = type; 1100 sas_rphy_initialize(&rdev->rphy); 1101 transport_setup_device(&rdev->rphy.dev); 1102 1103 return &rdev->rphy; 1104} 1105EXPORT_SYMBOL(sas_expander_alloc); 1106 1107/** 1108 * sas_rphy_add -- add a SAS remote PHY to the device hierachy 1109 * @rphy: The remote PHY to be added 1110 * 1111 * Publishes a SAS remote PHY to the rest of the system. 1112 */ 1113int sas_rphy_add(struct sas_rphy *rphy) 1114{ 1115 struct sas_port *parent = dev_to_sas_port(rphy->dev.parent); 1116 struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 1117 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1118 struct sas_identify *identify = &rphy->identify; 1119 int error; 1120 1121 if (parent->rphy) 1122 return -ENXIO; 1123 parent->rphy = rphy; 1124 1125 error = device_add(&rphy->dev); 1126 if (error) 1127 return error; 1128 transport_add_device(&rphy->dev); 1129 transport_configure_device(&rphy->dev); 1130 1131 mutex_lock(&sas_host->lock); 1132 list_add_tail(&rphy->list, &sas_host->rphy_list); 1133 if (identify->device_type == SAS_END_DEVICE && 1134 (identify->target_port_protocols & 1135 (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) 1136 rphy->scsi_target_id = sas_host->next_target_id++; 1137 else if (identify->device_type == SAS_END_DEVICE) 1138 rphy->scsi_target_id = -1; 1139 mutex_unlock(&sas_host->lock); 1140 1141 if (identify->device_type == SAS_END_DEVICE && 1142 rphy->scsi_target_id != -1) { 1143 scsi_scan_target(&rphy->dev, parent->port_identifier, 1144 rphy->scsi_target_id, ~0, 0); 1145 } 1146 1147 return 0; 1148} 1149EXPORT_SYMBOL(sas_rphy_add); 1150 1151/** 1152 * sas_rphy_free -- free a SAS remote PHY 1153 * @rphy SAS remote PHY to free 1154 * 1155 * Frees the specified SAS remote PHY. 1156 * 1157 * Note: 1158 * This function must only be called on a remote 1159 * PHY that has not sucessfully been added using 1160 * sas_rphy_add(). 1161 */ 1162void sas_rphy_free(struct sas_rphy *rphy) 1163{ 1164 struct device *dev = &rphy->dev; 1165 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 1166 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1167 1168 mutex_lock(&sas_host->lock); 1169 list_del(&rphy->list); 1170 mutex_unlock(&sas_host->lock); 1171 1172 transport_destroy_device(dev); 1173 1174 put_device(dev); 1175} 1176EXPORT_SYMBOL(sas_rphy_free); 1177 1178/** 1179 * sas_rphy_delete -- remove SAS remote PHY 1180 * @rphy: SAS remote PHY to remove 1181 * 1182 * Removes the specified SAS remote PHY. 1183 */ 1184void 1185sas_rphy_delete(struct sas_rphy *rphy) 1186{ 1187 struct device *dev = &rphy->dev; 1188 struct sas_port *parent = dev_to_sas_port(dev->parent); 1189 struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 1190 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1191 1192 switch (rphy->identify.device_type) { 1193 case SAS_END_DEVICE: 1194 scsi_remove_target(dev); 1195 break; 1196 case SAS_EDGE_EXPANDER_DEVICE: 1197 case SAS_FANOUT_EXPANDER_DEVICE: 1198 sas_remove_children(dev); 1199 break; 1200 default: 1201 break; 1202 } 1203 1204 transport_remove_device(dev); 1205 device_del(dev); 1206 transport_destroy_device(dev); 1207 1208 mutex_lock(&sas_host->lock); 1209 list_del(&rphy->list); 1210 mutex_unlock(&sas_host->lock); 1211 1212 parent->rphy = NULL; 1213 1214 put_device(dev); 1215} 1216EXPORT_SYMBOL(sas_rphy_delete); 1217 1218/** 1219 * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY 1220 * @dev: device to check 1221 * 1222 * Returns: 1223 * %1 if the device represents a SAS remote PHY, %0 else 1224 */ 1225int scsi_is_sas_rphy(const struct device *dev) 1226{ 1227 return dev->release == sas_end_device_release || 1228 dev->release == sas_expander_release; 1229} 1230EXPORT_SYMBOL(scsi_is_sas_rphy); 1231 1232 1233/* 1234 * SCSI scan helper 1235 */ 1236 1237static int sas_user_scan(struct Scsi_Host *shost, uint channel, 1238 uint id, uint lun) 1239{ 1240 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1241 struct sas_rphy *rphy; 1242 1243 mutex_lock(&sas_host->lock); 1244 list_for_each_entry(rphy, &sas_host->rphy_list, list) { 1245 struct sas_port *parent = dev_to_sas_port(rphy->dev.parent); 1246 1247 if (rphy->identify.device_type != SAS_END_DEVICE || 1248 rphy->scsi_target_id == -1) 1249 continue; 1250 1251 if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) && 1252 (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { 1253 scsi_scan_target(&rphy->dev, parent->port_identifier, 1254 rphy->scsi_target_id, lun, 1); 1255 } 1256 } 1257 mutex_unlock(&sas_host->lock); 1258 1259 return 0; 1260} 1261 1262 1263/* 1264 * Setup / Teardown code 1265 */ 1266 1267#define SETUP_TEMPLATE(attrb, field, perm, test) \ 1268 i->private_##attrb[count] = class_device_attr_##field; \ 1269 i->private_##attrb[count].attr.mode = perm; \ 1270 i->attrb[count] = &i->private_##attrb[count]; \ 1271 if (test) \ 1272 count++ 1273 1274 1275#define SETUP_RPORT_ATTRIBUTE(field) \ 1276 SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) 1277 1278#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ 1279 SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func) 1280 1281#define SETUP_PHY_ATTRIBUTE(field) \ 1282 SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) 1283 1284#define SETUP_PORT_ATTRIBUTE(field) \ 1285 SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) 1286 1287#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func) \ 1288 SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) 1289 1290#define SETUP_PHY_ATTRIBUTE_WRONLY(field) \ 1291 SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1) 1292 1293#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func) \ 1294 SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func) 1295 1296#define SETUP_END_DEV_ATTRIBUTE(field) \ 1297 SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) 1298 1299#define SETUP_EXPANDER_ATTRIBUTE(field) \ 1300 SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) 1301 1302/** 1303 * sas_attach_transport -- instantiate SAS transport template 1304 * @ft: SAS transport class function template 1305 */ 1306struct scsi_transport_template * 1307sas_attach_transport(struct sas_function_template *ft) 1308{ 1309 struct sas_internal *i; 1310 int count; 1311 1312 i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL); 1313 if (!i) 1314 return NULL; 1315 1316 i->t.user_scan = sas_user_scan; 1317 1318 i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 1319 i->t.host_attrs.ac.class = &sas_host_class.class; 1320 i->t.host_attrs.ac.match = sas_host_match; 1321 transport_container_register(&i->t.host_attrs); 1322 i->t.host_size = sizeof(struct sas_host_attrs); 1323 1324 i->phy_attr_cont.ac.class = &sas_phy_class.class; 1325 i->phy_attr_cont.ac.attrs = &i->phy_attrs[0]; 1326 i->phy_attr_cont.ac.match = sas_phy_match; 1327 transport_container_register(&i->phy_attr_cont); 1328 1329 i->port_attr_cont.ac.class = &sas_port_class.class; 1330 i->port_attr_cont.ac.attrs = &i->port_attrs[0]; 1331 i->port_attr_cont.ac.match = sas_port_match; 1332 transport_container_register(&i->port_attr_cont); 1333 1334 i->rphy_attr_cont.ac.class = &sas_rphy_class.class; 1335 i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0]; 1336 i->rphy_attr_cont.ac.match = sas_rphy_match; 1337 transport_container_register(&i->rphy_attr_cont); 1338 1339 i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class; 1340 i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0]; 1341 i->end_dev_attr_cont.ac.match = sas_end_dev_match; 1342 transport_container_register(&i->end_dev_attr_cont); 1343 1344 i->expander_attr_cont.ac.class = &sas_expander_class.class; 1345 i->expander_attr_cont.ac.attrs = &i->expander_attrs[0]; 1346 i->expander_attr_cont.ac.match = sas_expander_match; 1347 transport_container_register(&i->expander_attr_cont); 1348 1349 i->f = ft; 1350 1351 count = 0; 1352 SETUP_PORT_ATTRIBUTE(num_phys); 1353 i->host_attrs[count] = NULL; 1354 1355 count = 0; 1356 SETUP_PHY_ATTRIBUTE(initiator_port_protocols); 1357 SETUP_PHY_ATTRIBUTE(target_port_protocols); 1358 SETUP_PHY_ATTRIBUTE(device_type); 1359 SETUP_PHY_ATTRIBUTE(sas_address); 1360 SETUP_PHY_ATTRIBUTE(phy_identifier); 1361 //SETUP_PHY_ATTRIBUTE(port_identifier); 1362 SETUP_PHY_ATTRIBUTE(negotiated_linkrate); 1363 SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw); 1364 SETUP_PHY_ATTRIBUTE(minimum_linkrate); 1365 SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw); 1366 SETUP_PHY_ATTRIBUTE(maximum_linkrate); 1367 1368 SETUP_PHY_ATTRIBUTE(invalid_dword_count); 1369 SETUP_PHY_ATTRIBUTE(running_disparity_error_count); 1370 SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count); 1371 SETUP_PHY_ATTRIBUTE(phy_reset_problem_count); 1372 SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset); 1373 SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset); 1374 i->phy_attrs[count] = NULL; 1375 1376 count = 0; 1377 SETUP_PORT_ATTRIBUTE(num_phys); 1378 i->port_attrs[count] = NULL; 1379 1380 count = 0; 1381 SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols); 1382 SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols); 1383 SETUP_RPORT_ATTRIBUTE(rphy_device_type); 1384 SETUP_RPORT_ATTRIBUTE(rphy_sas_address); 1385 SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); 1386 SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier, 1387 get_enclosure_identifier); 1388 SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier, 1389 get_bay_identifier); 1390 i->rphy_attrs[count] = NULL; 1391 1392 count = 0; 1393 SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); 1394 SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); 1395 SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); 1396 i->end_dev_attrs[count] = NULL; 1397 1398 count = 0; 1399 SETUP_EXPANDER_ATTRIBUTE(vendor_id); 1400 SETUP_EXPANDER_ATTRIBUTE(product_id); 1401 SETUP_EXPANDER_ATTRIBUTE(product_rev); 1402 SETUP_EXPANDER_ATTRIBUTE(component_vendor_id); 1403 SETUP_EXPANDER_ATTRIBUTE(component_id); 1404 SETUP_EXPANDER_ATTRIBUTE(component_revision_id); 1405 SETUP_EXPANDER_ATTRIBUTE(level); 1406 i->expander_attrs[count] = NULL; 1407 1408 return &i->t; 1409} 1410EXPORT_SYMBOL(sas_attach_transport); 1411 1412/** 1413 * sas_release_transport -- release SAS transport template instance 1414 * @t: transport template instance 1415 */ 1416void sas_release_transport(struct scsi_transport_template *t) 1417{ 1418 struct sas_internal *i = to_sas_internal(t); 1419 1420 transport_container_unregister(&i->t.host_attrs); 1421 transport_container_unregister(&i->phy_attr_cont); 1422 transport_container_unregister(&i->port_attr_cont); 1423 transport_container_unregister(&i->rphy_attr_cont); 1424 transport_container_unregister(&i->end_dev_attr_cont); 1425 transport_container_unregister(&i->expander_attr_cont); 1426 1427 kfree(i); 1428} 1429EXPORT_SYMBOL(sas_release_transport); 1430 1431static __init int sas_transport_init(void) 1432{ 1433 int error; 1434 1435 error = transport_class_register(&sas_host_class); 1436 if (error) 1437 goto out; 1438 error = transport_class_register(&sas_phy_class); 1439 if (error) 1440 goto out_unregister_transport; 1441 error = transport_class_register(&sas_port_class); 1442 if (error) 1443 goto out_unregister_phy; 1444 error = transport_class_register(&sas_rphy_class); 1445 if (error) 1446 goto out_unregister_port; 1447 error = transport_class_register(&sas_end_dev_class); 1448 if (error) 1449 goto out_unregister_rphy; 1450 error = transport_class_register(&sas_expander_class); 1451 if (error) 1452 goto out_unregister_end_dev; 1453 1454 return 0; 1455 1456 out_unregister_end_dev: 1457 transport_class_unregister(&sas_end_dev_class); 1458 out_unregister_rphy: 1459 transport_class_unregister(&sas_rphy_class); 1460 out_unregister_port: 1461 transport_class_unregister(&sas_port_class); 1462 out_unregister_phy: 1463 transport_class_unregister(&sas_phy_class); 1464 out_unregister_transport: 1465 transport_class_unregister(&sas_host_class); 1466 out: 1467 return error; 1468 1469} 1470 1471static void __exit sas_transport_exit(void) 1472{ 1473 transport_class_unregister(&sas_host_class); 1474 transport_class_unregister(&sas_phy_class); 1475 transport_class_unregister(&sas_port_class); 1476 transport_class_unregister(&sas_rphy_class); 1477 transport_class_unregister(&sas_end_dev_class); 1478 transport_class_unregister(&sas_expander_class); 1479} 1480 1481MODULE_AUTHOR("Christoph Hellwig"); 1482MODULE_DESCRIPTION("SAS Transphy Attributes"); 1483MODULE_LICENSE("GPL"); 1484 1485module_init(sas_transport_init); 1486module_exit(sas_transport_exit); 1487