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" 39 struct 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) \ 61 static ssize_t \ 62 get_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 < sizeof(table)/sizeof(table[0]); 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) \ 80 static ssize_t \ 81 get_sas_##title##_names(u32 table_key, char *buf) \ 82 { \ 83 ssize_t len = 0; \ 84 int i; \ 85 \ 86 for (i = 0; i < sizeof(table)/sizeof(table[0]); 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 97 static 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 }; 106 sas_bitfield_name_search(device_type, sas_device_type_names) 107 108 109 static 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 }; 118 sas_bitfield_name_match(protocol, sas_protocol_names) 119 120 static 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 }; 132 sas_bitfield_name_search(linkspeed, sas_linkspeed_names) 133 134 135 /* 136 * SAS host attributes 137 */ 138 139 static 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 152 static DECLARE_TRANSPORT_CLASS(sas_host_class, 153 "sas_host", sas_host_setup, NULL, NULL); 154 155 static 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 175 static int do_sas_phy_delete(struct device *dev, void *data) 176 { 177 if (scsi_is_sas_phy(dev)) 178 sas_phy_delete(dev_to_phy(dev)); 179 return 0; 180 } 181 182 /** 183 * sas_remove_host -- tear down a Scsi_Host's SAS data structures 184 * @shost: Scsi Host that is torn down 185 * 186 * Removes all SAS PHYs and remote PHYs for a given Scsi_Host. 187 * Must be called just before scsi_remove_host for SAS HBAs. 188 */ 189 void sas_remove_host(struct Scsi_Host *shost) 190 { 191 device_for_each_child(&shost->shost_gendev, NULL, do_sas_phy_delete); 192 } 193 EXPORT_SYMBOL(sas_remove_host); 194 195 196 /* 197 * SAS Port attributes 198 */ 199 200 #define sas_phy_show_simple(field, name, format_string, cast) \ 201 static ssize_t \ 202 show_sas_phy_##name(struct class_device *cdev, char *buf) \ 203 { \ 204 struct sas_phy *phy = transport_class_to_phy(cdev); \ 205 \ 206 return snprintf(buf, 20, format_string, cast phy->field); \ 207 } 208 209 #define sas_phy_simple_attr(field, name, format_string, type) \ 210 sas_phy_show_simple(field, name, format_string, (type)) \ 211 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 212 213 #define sas_phy_show_protocol(field, name) \ 214 static ssize_t \ 215 show_sas_phy_##name(struct class_device *cdev, char *buf) \ 216 { \ 217 struct sas_phy *phy = transport_class_to_phy(cdev); \ 218 \ 219 if (!phy->field) \ 220 return snprintf(buf, 20, "none\n"); \ 221 return get_sas_protocol_names(phy->field, buf); \ 222 } 223 224 #define sas_phy_protocol_attr(field, name) \ 225 sas_phy_show_protocol(field, name) \ 226 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 227 228 #define sas_phy_show_linkspeed(field) \ 229 static ssize_t \ 230 show_sas_phy_##field(struct class_device *cdev, char *buf) \ 231 { \ 232 struct sas_phy *phy = transport_class_to_phy(cdev); \ 233 \ 234 return get_sas_linkspeed_names(phy->field, buf); \ 235 } 236 237 #define sas_phy_linkspeed_attr(field) \ 238 sas_phy_show_linkspeed(field) \ 239 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 240 241 #define sas_phy_show_linkerror(field) \ 242 static ssize_t \ 243 show_sas_phy_##field(struct class_device *cdev, char *buf) \ 244 { \ 245 struct sas_phy *phy = transport_class_to_phy(cdev); \ 246 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \ 247 struct sas_internal *i = to_sas_internal(shost->transportt); \ 248 int error; \ 249 \ 250 if (!phy->local_attached) \ 251 return -EINVAL; \ 252 \ 253 error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0; \ 254 if (error) \ 255 return error; \ 256 return snprintf(buf, 20, "%u\n", phy->field); \ 257 } 258 259 #define sas_phy_linkerror_attr(field) \ 260 sas_phy_show_linkerror(field) \ 261 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 262 263 264 static ssize_t 265 show_sas_device_type(struct class_device *cdev, char *buf) 266 { 267 struct sas_phy *phy = transport_class_to_phy(cdev); 268 269 if (!phy->identify.device_type) 270 return snprintf(buf, 20, "none\n"); 271 return get_sas_device_type_names(phy->identify.device_type, buf); 272 } 273 static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); 274 275 static ssize_t do_sas_phy_reset(struct class_device *cdev, 276 size_t count, int hard_reset) 277 { 278 struct sas_phy *phy = transport_class_to_phy(cdev); 279 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 280 struct sas_internal *i = to_sas_internal(shost->transportt); 281 int error; 282 283 if (!phy->local_attached) 284 return -EINVAL; 285 286 error = i->f->phy_reset(phy, hard_reset); 287 if (error) 288 return error; 289 return count; 290 }; 291 292 static ssize_t store_sas_link_reset(struct class_device *cdev, 293 const char *buf, size_t count) 294 { 295 return do_sas_phy_reset(cdev, count, 0); 296 } 297 static CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); 298 299 static ssize_t store_sas_hard_reset(struct class_device *cdev, 300 const char *buf, size_t count) 301 { 302 return do_sas_phy_reset(cdev, count, 1); 303 } 304 static CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); 305 306 sas_phy_protocol_attr(identify.initiator_port_protocols, 307 initiator_port_protocols); 308 sas_phy_protocol_attr(identify.target_port_protocols, 309 target_port_protocols); 310 sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 311 unsigned long long); 312 sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 313 sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8); 314 sas_phy_linkspeed_attr(negotiated_linkrate); 315 sas_phy_linkspeed_attr(minimum_linkrate_hw); 316 sas_phy_linkspeed_attr(minimum_linkrate); 317 sas_phy_linkspeed_attr(maximum_linkrate_hw); 318 sas_phy_linkspeed_attr(maximum_linkrate); 319 sas_phy_linkerror_attr(invalid_dword_count); 320 sas_phy_linkerror_attr(running_disparity_error_count); 321 sas_phy_linkerror_attr(loss_of_dword_sync_count); 322 sas_phy_linkerror_attr(phy_reset_problem_count); 323 324 325 static DECLARE_TRANSPORT_CLASS(sas_phy_class, 326 "sas_phy", NULL, NULL, NULL); 327 328 static int sas_phy_match(struct attribute_container *cont, struct device *dev) 329 { 330 struct Scsi_Host *shost; 331 struct sas_internal *i; 332 333 if (!scsi_is_sas_phy(dev)) 334 return 0; 335 shost = dev_to_shost(dev->parent); 336 337 if (!shost->transportt) 338 return 0; 339 if (shost->transportt->host_attrs.ac.class != 340 &sas_host_class.class) 341 return 0; 342 343 i = to_sas_internal(shost->transportt); 344 return &i->phy_attr_cont.ac == cont; 345 } 346 347 static void sas_phy_release(struct device *dev) 348 { 349 struct sas_phy *phy = dev_to_phy(dev); 350 351 put_device(dev->parent); 352 kfree(phy); 353 } 354 355 /** 356 * sas_phy_alloc -- allocates and initialize a SAS PHY structure 357 * @parent: Parent device 358 * @number: Phy index 359 * 360 * Allocates an SAS PHY structure. It will be added in the device tree 361 * below the device specified by @parent, which has to be either a Scsi_Host 362 * or sas_rphy. 363 * 364 * Returns: 365 * SAS PHY allocated or %NULL if the allocation failed. 366 */ 367 struct sas_phy *sas_phy_alloc(struct device *parent, int number) 368 { 369 struct Scsi_Host *shost = dev_to_shost(parent); 370 struct sas_phy *phy; 371 372 phy = kzalloc(sizeof(*phy), GFP_KERNEL); 373 if (!phy) 374 return NULL; 375 376 phy->number = number; 377 378 device_initialize(&phy->dev); 379 phy->dev.parent = get_device(parent); 380 phy->dev.release = sas_phy_release; 381 if (scsi_is_sas_expander_device(parent)) { 382 struct sas_rphy *rphy = dev_to_rphy(parent); 383 sprintf(phy->dev.bus_id, "phy-%d-%d:%d", shost->host_no, 384 rphy->scsi_target_id, number); 385 } else 386 sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); 387 388 transport_setup_device(&phy->dev); 389 390 return phy; 391 } 392 EXPORT_SYMBOL(sas_phy_alloc); 393 394 /** 395 * sas_phy_add -- add a SAS PHY to the device hierachy 396 * @phy: The PHY to be added 397 * 398 * Publishes a SAS PHY to the rest of the system. 399 */ 400 int sas_phy_add(struct sas_phy *phy) 401 { 402 int error; 403 404 error = device_add(&phy->dev); 405 if (!error) { 406 transport_add_device(&phy->dev); 407 transport_configure_device(&phy->dev); 408 } 409 410 return error; 411 } 412 EXPORT_SYMBOL(sas_phy_add); 413 414 /** 415 * sas_phy_free -- free a SAS PHY 416 * @phy: SAS PHY to free 417 * 418 * Frees the specified SAS PHY. 419 * 420 * Note: 421 * This function must only be called on a PHY that has not 422 * sucessfully been added using sas_phy_add(). 423 */ 424 void sas_phy_free(struct sas_phy *phy) 425 { 426 transport_destroy_device(&phy->dev); 427 put_device(&phy->dev); 428 } 429 EXPORT_SYMBOL(sas_phy_free); 430 431 /** 432 * sas_phy_delete -- remove SAS PHY 433 * @phy: SAS PHY to remove 434 * 435 * Removes the specified SAS PHY. If the SAS PHY has an 436 * associated remote PHY it is removed before. 437 */ 438 void 439 sas_phy_delete(struct sas_phy *phy) 440 { 441 struct device *dev = &phy->dev; 442 443 if (phy->rphy) 444 sas_rphy_delete(phy->rphy); 445 446 transport_remove_device(dev); 447 device_del(dev); 448 transport_destroy_device(dev); 449 put_device(dev); 450 } 451 EXPORT_SYMBOL(sas_phy_delete); 452 453 /** 454 * scsi_is_sas_phy -- check if a struct device represents a SAS PHY 455 * @dev: device to check 456 * 457 * Returns: 458 * %1 if the device represents a SAS PHY, %0 else 459 */ 460 int scsi_is_sas_phy(const struct device *dev) 461 { 462 return dev->release == sas_phy_release; 463 } 464 EXPORT_SYMBOL(scsi_is_sas_phy); 465 466 /* 467 * SAS remote PHY attributes. 468 */ 469 470 #define sas_rphy_show_simple(field, name, format_string, cast) \ 471 static ssize_t \ 472 show_sas_rphy_##name(struct class_device *cdev, char *buf) \ 473 { \ 474 struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 475 \ 476 return snprintf(buf, 20, format_string, cast rphy->field); \ 477 } 478 479 #define sas_rphy_simple_attr(field, name, format_string, type) \ 480 sas_rphy_show_simple(field, name, format_string, (type)) \ 481 static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 482 show_sas_rphy_##name, NULL) 483 484 #define sas_rphy_show_protocol(field, name) \ 485 static ssize_t \ 486 show_sas_rphy_##name(struct class_device *cdev, char *buf) \ 487 { \ 488 struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 489 \ 490 if (!rphy->field) \ 491 return snprintf(buf, 20, "none\n"); \ 492 return get_sas_protocol_names(rphy->field, buf); \ 493 } 494 495 #define sas_rphy_protocol_attr(field, name) \ 496 sas_rphy_show_protocol(field, name) \ 497 static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 498 show_sas_rphy_##name, NULL) 499 500 static ssize_t 501 show_sas_rphy_device_type(struct class_device *cdev, char *buf) 502 { 503 struct sas_rphy *rphy = transport_class_to_rphy(cdev); 504 505 if (!rphy->identify.device_type) 506 return snprintf(buf, 20, "none\n"); 507 return get_sas_device_type_names( 508 rphy->identify.device_type, buf); 509 } 510 511 static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, 512 show_sas_rphy_device_type, NULL); 513 514 static ssize_t 515 show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf) 516 { 517 struct sas_rphy *rphy = transport_class_to_rphy(cdev); 518 struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 519 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 520 struct sas_internal *i = to_sas_internal(shost->transportt); 521 u64 identifier; 522 int error; 523 524 /* 525 * Only devices behind an expander are supported, because the 526 * enclosure identifier is a SMP feature. 527 */ 528 if (phy->local_attached) 529 return -EINVAL; 530 531 error = i->f->get_enclosure_identifier(rphy, &identifier); 532 if (error) 533 return error; 534 return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); 535 } 536 537 static SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, 538 show_sas_rphy_enclosure_identifier, NULL); 539 540 static ssize_t 541 show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf) 542 { 543 struct sas_rphy *rphy = transport_class_to_rphy(cdev); 544 struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 545 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 546 struct sas_internal *i = to_sas_internal(shost->transportt); 547 int val; 548 549 if (phy->local_attached) 550 return -EINVAL; 551 552 val = i->f->get_bay_identifier(rphy); 553 if (val < 0) 554 return val; 555 return sprintf(buf, "%d\n", val); 556 } 557 558 static SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, 559 show_sas_rphy_bay_identifier, NULL); 560 561 sas_rphy_protocol_attr(identify.initiator_port_protocols, 562 initiator_port_protocols); 563 sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); 564 sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 565 unsigned long long); 566 sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 567 568 /* only need 8 bytes of data plus header (4 or 8) */ 569 #define BUF_SIZE 64 570 571 int sas_read_port_mode_page(struct scsi_device *sdev) 572 { 573 char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; 574 struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target); 575 struct sas_end_device *rdev; 576 struct scsi_mode_data mode_data; 577 int res, error; 578 579 BUG_ON(rphy->identify.device_type != SAS_END_DEVICE); 580 581 rdev = rphy_to_end_device(rphy); 582 583 if (!buffer) 584 return -ENOMEM; 585 586 res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, 587 &mode_data, NULL); 588 589 error = -EINVAL; 590 if (!scsi_status_is_good(res)) 591 goto out; 592 593 msdata = buffer + mode_data.header_length + 594 mode_data.block_descriptor_length; 595 596 if (msdata - buffer > BUF_SIZE - 8) 597 goto out; 598 599 error = 0; 600 601 rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0; 602 rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5]; 603 rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7]; 604 605 out: 606 kfree(buffer); 607 return error; 608 } 609 EXPORT_SYMBOL(sas_read_port_mode_page); 610 611 static DECLARE_TRANSPORT_CLASS(sas_end_dev_class, 612 "sas_end_device", NULL, NULL, NULL); 613 614 #define sas_end_dev_show_simple(field, name, format_string, cast) \ 615 static ssize_t \ 616 show_sas_end_dev_##name(struct class_device *cdev, char *buf) \ 617 { \ 618 struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 619 struct sas_end_device *rdev = rphy_to_end_device(rphy); \ 620 \ 621 return snprintf(buf, 20, format_string, cast rdev->field); \ 622 } 623 624 #define sas_end_dev_simple_attr(field, name, format_string, type) \ 625 sas_end_dev_show_simple(field, name, format_string, (type)) \ 626 static SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ 627 show_sas_end_dev_##name, NULL) 628 629 sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); 630 sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, 631 "%d\n", int); 632 sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, 633 "%d\n", int); 634 635 static DECLARE_TRANSPORT_CLASS(sas_expander_class, 636 "sas_expander", NULL, NULL, NULL); 637 638 #define sas_expander_show_simple(field, name, format_string, cast) \ 639 static ssize_t \ 640 show_sas_expander_##name(struct class_device *cdev, char *buf) \ 641 { \ 642 struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 643 struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ 644 \ 645 return snprintf(buf, 20, format_string, cast edev->field); \ 646 } 647 648 #define sas_expander_simple_attr(field, name, format_string, type) \ 649 sas_expander_show_simple(field, name, format_string, (type)) \ 650 static SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, \ 651 show_sas_expander_##name, NULL) 652 653 sas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); 654 sas_expander_simple_attr(product_id, product_id, "%s\n", char *); 655 sas_expander_simple_attr(product_rev, product_rev, "%s\n", char *); 656 sas_expander_simple_attr(component_vendor_id, component_vendor_id, 657 "%s\n", char *); 658 sas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int); 659 sas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", 660 unsigned int); 661 sas_expander_simple_attr(level, level, "%d\n", int); 662 663 static DECLARE_TRANSPORT_CLASS(sas_rphy_class, 664 "sas_device", NULL, NULL, NULL); 665 666 static int sas_rphy_match(struct attribute_container *cont, struct device *dev) 667 { 668 struct Scsi_Host *shost; 669 struct sas_internal *i; 670 671 if (!scsi_is_sas_rphy(dev)) 672 return 0; 673 shost = dev_to_shost(dev->parent->parent); 674 675 if (!shost->transportt) 676 return 0; 677 if (shost->transportt->host_attrs.ac.class != 678 &sas_host_class.class) 679 return 0; 680 681 i = to_sas_internal(shost->transportt); 682 return &i->rphy_attr_cont.ac == cont; 683 } 684 685 static int sas_end_dev_match(struct attribute_container *cont, 686 struct device *dev) 687 { 688 struct Scsi_Host *shost; 689 struct sas_internal *i; 690 struct sas_rphy *rphy; 691 692 if (!scsi_is_sas_rphy(dev)) 693 return 0; 694 shost = dev_to_shost(dev->parent->parent); 695 rphy = dev_to_rphy(dev); 696 697 if (!shost->transportt) 698 return 0; 699 if (shost->transportt->host_attrs.ac.class != 700 &sas_host_class.class) 701 return 0; 702 703 i = to_sas_internal(shost->transportt); 704 return &i->end_dev_attr_cont.ac == cont && 705 rphy->identify.device_type == SAS_END_DEVICE; 706 } 707 708 static int sas_expander_match(struct attribute_container *cont, 709 struct device *dev) 710 { 711 struct Scsi_Host *shost; 712 struct sas_internal *i; 713 struct sas_rphy *rphy; 714 715 if (!scsi_is_sas_rphy(dev)) 716 return 0; 717 shost = dev_to_shost(dev->parent->parent); 718 rphy = dev_to_rphy(dev); 719 720 if (!shost->transportt) 721 return 0; 722 if (shost->transportt->host_attrs.ac.class != 723 &sas_host_class.class) 724 return 0; 725 726 i = to_sas_internal(shost->transportt); 727 return &i->expander_attr_cont.ac == cont && 728 (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || 729 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE); 730 } 731 732 static void sas_expander_release(struct device *dev) 733 { 734 struct sas_rphy *rphy = dev_to_rphy(dev); 735 struct sas_expander_device *edev = rphy_to_expander_device(rphy); 736 737 put_device(dev->parent); 738 kfree(edev); 739 } 740 741 static void sas_end_device_release(struct device *dev) 742 { 743 struct sas_rphy *rphy = dev_to_rphy(dev); 744 struct sas_end_device *edev = rphy_to_end_device(rphy); 745 746 put_device(dev->parent); 747 kfree(edev); 748 } 749 750 /** 751 * sas_end_device_alloc - allocate an rphy for an end device 752 * 753 * Allocates an SAS remote PHY structure, connected to @parent. 754 * 755 * Returns: 756 * SAS PHY allocated or %NULL if the allocation failed. 757 */ 758 struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent) 759 { 760 struct Scsi_Host *shost = dev_to_shost(&parent->dev); 761 struct sas_end_device *rdev; 762 763 rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 764 if (!rdev) { 765 return NULL; 766 } 767 768 device_initialize(&rdev->rphy.dev); 769 rdev->rphy.dev.parent = get_device(&parent->dev); 770 rdev->rphy.dev.release = sas_end_device_release; 771 sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d-%d", 772 shost->host_no, parent->port_identifier, parent->number); 773 rdev->rphy.identify.device_type = SAS_END_DEVICE; 774 transport_setup_device(&rdev->rphy.dev); 775 776 return &rdev->rphy; 777 } 778 EXPORT_SYMBOL(sas_end_device_alloc); 779 780 /** 781 * sas_expander_alloc - allocate an rphy for an end device 782 * 783 * Allocates an SAS remote PHY structure, connected to @parent. 784 * 785 * Returns: 786 * SAS PHY allocated or %NULL if the allocation failed. 787 */ 788 struct sas_rphy *sas_expander_alloc(struct sas_phy *parent, 789 enum sas_device_type type) 790 { 791 struct Scsi_Host *shost = dev_to_shost(&parent->dev); 792 struct sas_expander_device *rdev; 793 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 794 795 BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE && 796 type != SAS_FANOUT_EXPANDER_DEVICE); 797 798 rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 799 if (!rdev) { 800 return NULL; 801 } 802 803 device_initialize(&rdev->rphy.dev); 804 rdev->rphy.dev.parent = get_device(&parent->dev); 805 rdev->rphy.dev.release = sas_expander_release; 806 mutex_lock(&sas_host->lock); 807 rdev->rphy.scsi_target_id = sas_host->next_expander_id++; 808 mutex_unlock(&sas_host->lock); 809 sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", 810 shost->host_no, rdev->rphy.scsi_target_id); 811 rdev->rphy.identify.device_type = type; 812 transport_setup_device(&rdev->rphy.dev); 813 814 return &rdev->rphy; 815 } 816 EXPORT_SYMBOL(sas_expander_alloc); 817 818 /** 819 * sas_rphy_add -- add a SAS remote PHY to the device hierachy 820 * @rphy: The remote PHY to be added 821 * 822 * Publishes a SAS remote PHY to the rest of the system. 823 */ 824 int sas_rphy_add(struct sas_rphy *rphy) 825 { 826 struct sas_phy *parent = dev_to_phy(rphy->dev.parent); 827 struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 828 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 829 struct sas_identify *identify = &rphy->identify; 830 int error; 831 832 if (parent->rphy) 833 return -ENXIO; 834 parent->rphy = rphy; 835 836 error = device_add(&rphy->dev); 837 if (error) 838 return error; 839 transport_add_device(&rphy->dev); 840 transport_configure_device(&rphy->dev); 841 842 mutex_lock(&sas_host->lock); 843 list_add_tail(&rphy->list, &sas_host->rphy_list); 844 if (identify->device_type == SAS_END_DEVICE && 845 (identify->target_port_protocols & 846 (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) 847 rphy->scsi_target_id = sas_host->next_target_id++; 848 else if (identify->device_type == SAS_END_DEVICE) 849 rphy->scsi_target_id = -1; 850 mutex_unlock(&sas_host->lock); 851 852 if (identify->device_type == SAS_END_DEVICE && 853 rphy->scsi_target_id != -1) { 854 scsi_scan_target(&rphy->dev, parent->port_identifier, 855 rphy->scsi_target_id, ~0, 0); 856 } 857 858 return 0; 859 } 860 EXPORT_SYMBOL(sas_rphy_add); 861 862 /** 863 * sas_rphy_free -- free a SAS remote PHY 864 * @rphy SAS remote PHY to free 865 * 866 * Frees the specified SAS remote PHY. 867 * 868 * Note: 869 * This function must only be called on a remote 870 * PHY that has not sucessfully been added using 871 * sas_rphy_add(). 872 */ 873 void sas_rphy_free(struct sas_rphy *rphy) 874 { 875 struct device *dev = &rphy->dev; 876 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 877 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 878 879 mutex_lock(&sas_host->lock); 880 list_del(&rphy->list); 881 mutex_unlock(&sas_host->lock); 882 883 transport_destroy_device(dev); 884 885 put_device(dev); 886 } 887 EXPORT_SYMBOL(sas_rphy_free); 888 889 /** 890 * sas_rphy_delete -- remove SAS remote PHY 891 * @rphy: SAS remote PHY to remove 892 * 893 * Removes the specified SAS remote PHY. 894 */ 895 void 896 sas_rphy_delete(struct sas_rphy *rphy) 897 { 898 struct device *dev = &rphy->dev; 899 struct sas_phy *parent = dev_to_phy(dev->parent); 900 struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 901 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 902 903 switch (rphy->identify.device_type) { 904 case SAS_END_DEVICE: 905 scsi_remove_target(dev); 906 break; 907 case SAS_EDGE_EXPANDER_DEVICE: 908 case SAS_FANOUT_EXPANDER_DEVICE: 909 device_for_each_child(dev, NULL, do_sas_phy_delete); 910 break; 911 default: 912 break; 913 } 914 915 transport_remove_device(dev); 916 device_del(dev); 917 transport_destroy_device(dev); 918 919 mutex_lock(&sas_host->lock); 920 list_del(&rphy->list); 921 mutex_unlock(&sas_host->lock); 922 923 parent->rphy = NULL; 924 925 put_device(dev); 926 } 927 EXPORT_SYMBOL(sas_rphy_delete); 928 929 /** 930 * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY 931 * @dev: device to check 932 * 933 * Returns: 934 * %1 if the device represents a SAS remote PHY, %0 else 935 */ 936 int scsi_is_sas_rphy(const struct device *dev) 937 { 938 return dev->release == sas_end_device_release || 939 dev->release == sas_expander_release; 940 } 941 EXPORT_SYMBOL(scsi_is_sas_rphy); 942 943 944 /* 945 * SCSI scan helper 946 */ 947 948 static int sas_user_scan(struct Scsi_Host *shost, uint channel, 949 uint id, uint lun) 950 { 951 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 952 struct sas_rphy *rphy; 953 954 mutex_lock(&sas_host->lock); 955 list_for_each_entry(rphy, &sas_host->rphy_list, list) { 956 struct sas_phy *parent = dev_to_phy(rphy->dev.parent); 957 958 if (rphy->scsi_target_id == -1) 959 continue; 960 961 if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) && 962 (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { 963 scsi_scan_target(&rphy->dev, parent->port_identifier, 964 rphy->scsi_target_id, lun, 1); 965 } 966 } 967 mutex_unlock(&sas_host->lock); 968 969 return 0; 970 } 971 972 973 /* 974 * Setup / Teardown code 975 */ 976 977 #define SETUP_TEMPLATE(attrb, field, perm, test) \ 978 i->private_##attrb[count] = class_device_attr_##field; \ 979 i->private_##attrb[count].attr.mode = perm; \ 980 i->private_##attrb[count].store = NULL; \ 981 i->attrb[count] = &i->private_##attrb[count]; \ 982 if (test) \ 983 count++ 984 985 986 #define SETUP_RPORT_ATTRIBUTE(field) \ 987 SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) 988 989 #define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ 990 SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func) 991 992 #define SETUP_PORT_ATTRIBUTE(field) \ 993 SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) 994 995 #define SETUP_OPTIONAL_PORT_ATTRIBUTE(field, func) \ 996 SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) 997 998 #define SETUP_PORT_ATTRIBUTE_WRONLY(field) \ 999 SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1) 1000 1001 #define SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(field, func) \ 1002 SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func) 1003 1004 #define SETUP_END_DEV_ATTRIBUTE(field) \ 1005 SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) 1006 1007 #define SETUP_EXPANDER_ATTRIBUTE(field) \ 1008 SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) 1009 1010 /** 1011 * sas_attach_transport -- instantiate SAS transport template 1012 * @ft: SAS transport class function template 1013 */ 1014 struct scsi_transport_template * 1015 sas_attach_transport(struct sas_function_template *ft) 1016 { 1017 struct sas_internal *i; 1018 int count; 1019 1020 i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL); 1021 if (!i) 1022 return NULL; 1023 1024 i->t.user_scan = sas_user_scan; 1025 1026 i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 1027 i->t.host_attrs.ac.class = &sas_host_class.class; 1028 i->t.host_attrs.ac.match = sas_host_match; 1029 transport_container_register(&i->t.host_attrs); 1030 i->t.host_size = sizeof(struct sas_host_attrs); 1031 1032 i->phy_attr_cont.ac.class = &sas_phy_class.class; 1033 i->phy_attr_cont.ac.attrs = &i->phy_attrs[0]; 1034 i->phy_attr_cont.ac.match = sas_phy_match; 1035 transport_container_register(&i->phy_attr_cont); 1036 1037 i->rphy_attr_cont.ac.class = &sas_rphy_class.class; 1038 i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0]; 1039 i->rphy_attr_cont.ac.match = sas_rphy_match; 1040 transport_container_register(&i->rphy_attr_cont); 1041 1042 i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class; 1043 i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0]; 1044 i->end_dev_attr_cont.ac.match = sas_end_dev_match; 1045 transport_container_register(&i->end_dev_attr_cont); 1046 1047 i->expander_attr_cont.ac.class = &sas_expander_class.class; 1048 i->expander_attr_cont.ac.attrs = &i->expander_attrs[0]; 1049 i->expander_attr_cont.ac.match = sas_expander_match; 1050 transport_container_register(&i->expander_attr_cont); 1051 1052 i->f = ft; 1053 1054 count = 0; 1055 i->host_attrs[count] = NULL; 1056 1057 count = 0; 1058 SETUP_PORT_ATTRIBUTE(initiator_port_protocols); 1059 SETUP_PORT_ATTRIBUTE(target_port_protocols); 1060 SETUP_PORT_ATTRIBUTE(device_type); 1061 SETUP_PORT_ATTRIBUTE(sas_address); 1062 SETUP_PORT_ATTRIBUTE(phy_identifier); 1063 SETUP_PORT_ATTRIBUTE(port_identifier); 1064 SETUP_PORT_ATTRIBUTE(negotiated_linkrate); 1065 SETUP_PORT_ATTRIBUTE(minimum_linkrate_hw); 1066 SETUP_PORT_ATTRIBUTE(minimum_linkrate); 1067 SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw); 1068 SETUP_PORT_ATTRIBUTE(maximum_linkrate); 1069 1070 SETUP_PORT_ATTRIBUTE(invalid_dword_count); 1071 SETUP_PORT_ATTRIBUTE(running_disparity_error_count); 1072 SETUP_PORT_ATTRIBUTE(loss_of_dword_sync_count); 1073 SETUP_PORT_ATTRIBUTE(phy_reset_problem_count); 1074 SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(link_reset, phy_reset); 1075 SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(hard_reset, phy_reset); 1076 i->phy_attrs[count] = NULL; 1077 1078 count = 0; 1079 SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols); 1080 SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols); 1081 SETUP_RPORT_ATTRIBUTE(rphy_device_type); 1082 SETUP_RPORT_ATTRIBUTE(rphy_sas_address); 1083 SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); 1084 SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier, 1085 get_enclosure_identifier); 1086 SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier, 1087 get_bay_identifier); 1088 i->rphy_attrs[count] = NULL; 1089 1090 count = 0; 1091 SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); 1092 SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); 1093 SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); 1094 i->end_dev_attrs[count] = NULL; 1095 1096 count = 0; 1097 SETUP_EXPANDER_ATTRIBUTE(vendor_id); 1098 SETUP_EXPANDER_ATTRIBUTE(product_id); 1099 SETUP_EXPANDER_ATTRIBUTE(product_rev); 1100 SETUP_EXPANDER_ATTRIBUTE(component_vendor_id); 1101 SETUP_EXPANDER_ATTRIBUTE(component_id); 1102 SETUP_EXPANDER_ATTRIBUTE(component_revision_id); 1103 SETUP_EXPANDER_ATTRIBUTE(level); 1104 i->expander_attrs[count] = NULL; 1105 1106 return &i->t; 1107 } 1108 EXPORT_SYMBOL(sas_attach_transport); 1109 1110 /** 1111 * sas_release_transport -- release SAS transport template instance 1112 * @t: transport template instance 1113 */ 1114 void sas_release_transport(struct scsi_transport_template *t) 1115 { 1116 struct sas_internal *i = to_sas_internal(t); 1117 1118 transport_container_unregister(&i->t.host_attrs); 1119 transport_container_unregister(&i->phy_attr_cont); 1120 transport_container_unregister(&i->rphy_attr_cont); 1121 transport_container_unregister(&i->end_dev_attr_cont); 1122 transport_container_unregister(&i->expander_attr_cont); 1123 1124 kfree(i); 1125 } 1126 EXPORT_SYMBOL(sas_release_transport); 1127 1128 static __init int sas_transport_init(void) 1129 { 1130 int error; 1131 1132 error = transport_class_register(&sas_host_class); 1133 if (error) 1134 goto out; 1135 error = transport_class_register(&sas_phy_class); 1136 if (error) 1137 goto out_unregister_transport; 1138 error = transport_class_register(&sas_rphy_class); 1139 if (error) 1140 goto out_unregister_phy; 1141 error = transport_class_register(&sas_end_dev_class); 1142 if (error) 1143 goto out_unregister_rphy; 1144 error = transport_class_register(&sas_expander_class); 1145 if (error) 1146 goto out_unregister_end_dev; 1147 1148 return 0; 1149 1150 out_unregister_end_dev: 1151 transport_class_unregister(&sas_end_dev_class); 1152 out_unregister_rphy: 1153 transport_class_unregister(&sas_rphy_class); 1154 out_unregister_phy: 1155 transport_class_unregister(&sas_phy_class); 1156 out_unregister_transport: 1157 transport_class_unregister(&sas_host_class); 1158 out: 1159 return error; 1160 1161 } 1162 1163 static void __exit sas_transport_exit(void) 1164 { 1165 transport_class_unregister(&sas_host_class); 1166 transport_class_unregister(&sas_phy_class); 1167 transport_class_unregister(&sas_rphy_class); 1168 transport_class_unregister(&sas_end_dev_class); 1169 transport_class_unregister(&sas_expander_class); 1170 } 1171 1172 MODULE_AUTHOR("Christoph Hellwig"); 1173 MODULE_DESCRIPTION("SAS Transphy Attributes"); 1174 MODULE_LICENSE("GPL"); 1175 1176 module_init(sas_transport_init); 1177 module_exit(sas_transport_exit); 1178