scsi_transport_sas.c revision 6d99a3f372181160a56d7b1ee3259dbe03663f0d
1c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 2a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * Copyright (C) 2005-2006 Dell Inc. 3c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Released under GPL v2. 4c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 5c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Serial Attached SCSI (SAS) transport class. 6c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 7c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * The SAS transport class contains common code to deal with SAS HBAs, 8c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * an aproximated representation of SAS topologies in the driver model, 9c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * and various sysfs attributes to expose these topologies and managment 10c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * interfaces to userspace. 11c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 12c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * In addition to the basic SCSI core objects this transport class 13c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * introduces two additional intermediate objects: The SAS PHY 14c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * as represented by struct sas_phy defines an "outgoing" PHY on 15c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * a SAS HBA or Expander, and the SAS remote PHY represented by 16c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * struct sas_rphy defines an "incoming" PHY on a SAS Expander or 17c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * end device. Note that this is purely a software concept, the 18c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * underlying hardware for a PHY and a remote PHY is the exactly 19c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * the same. 20c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 21c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * There is no concept of a SAS port in this code, users can see 22c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * what PHYs form a wide port based on the port_identifier attribute, 23c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * which is the same for all PHYs in a port. 24c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 25c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 26c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <linux/init.h> 27c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <linux/module.h> 28c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <linux/err.h> 298c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/slab.h> 308c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/string.h> 31c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 32e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig#include <scsi/scsi.h> 33c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_device.h> 34c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_host.h> 35c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_transport.h> 36c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_transport_sas.h> 37c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 38d6159c17c2c76963a8067d1e1ac3c4c36c05e674James Bottomley#include "scsi_sas_internal.h" 39c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_host_attrs { 40c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct list_head rphy_list; 41e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig struct mutex lock; 42c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 next_target_id; 4379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley u32 next_expander_id; 44c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 45c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) 46c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 47c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 48c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 49c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Hack to allow attributes of the same name in different objects. 50c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 51c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \ 52c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct class_device_attribute class_device_attr_##_prefix##_##_name = \ 53c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig __ATTR(_name,_mode,_show,_store) 54c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 55c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 56c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 57c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Pretty printing helpers 58c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 59c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 60c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_match(title, table) \ 61c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 62c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf) \ 63c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 64c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *prefix = ""; \ 65c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig ssize_t len = 0; \ 66c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int i; \ 67c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 68c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ 69c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (table[i].value & table_key) { \ 70c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "%s%s", \ 71c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig prefix, table[i].name); \ 72c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig prefix = ", "; \ 73c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 74c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 75c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "\n"); \ 76c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return len; \ 77c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 78c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 79c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_search(title, table) \ 80c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 81c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf) \ 82c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 83c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig ssize_t len = 0; \ 84c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int i; \ 85c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 86c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ 87c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (table[i].value == table_key) { \ 88c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "%s", \ 89c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig table[i].name); \ 90c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig break; \ 91c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 92c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 93c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "\n"); \ 94c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return len; \ 95c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 96c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 97c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 98c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 99c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 100c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_device_type_names[] = { 101c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PHY_UNUSED, "unused" }, 102c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_END_DEVICE, "end device" }, 103c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_EDGE_EXPANDER_DEVICE, "edge expander" }, 104c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" }, 105c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 106c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(device_type, sas_device_type_names) 107c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 108c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 109c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 110c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 111c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 112c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_protocol_names[] = { 113c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SATA, "sata" }, 114c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SMP, "smp" }, 115c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_STP, "stp" }, 116c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SSP, "ssp" }, 117c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 118c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_match(protocol, sas_protocol_names) 119c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 120c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 121c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 122c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 123c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_linkspeed_names[] = { 124c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_UNKNOWN, "Unknown" }, 125c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PHY_DISABLED, "Phy disabled" }, 126c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_FAILED, "Link Rate failed" }, 127c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_SATA_SPINUP_HOLD, "Spin-up hold" }, 128c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, 129c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, 1307e6dff62dad539cbd608bb3b8b833193d13f00acJames Bottomley { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, 131c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 132c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(linkspeed, sas_linkspeed_names) 133c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 134c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 135c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 136c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS host attributes 137c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 138c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 13937be6eeb4990c05fc7dd683ceaf1501d46ebe9a4James Bottomleystatic int sas_host_setup(struct transport_container *tc, struct device *dev, 14037be6eeb4990c05fc7dd683ceaf1501d46ebe9a4James Bottomley struct class_device *cdev) 141c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 142c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(dev); 143c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 144c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 145c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig INIT_LIST_HEAD(&sas_host->rphy_list); 146e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_init(&sas_host->lock); 147c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_host->next_target_id = 0; 14879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sas_host->next_expander_id = 0; 149c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 150c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 151c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 152c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_host_class, 153c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig "sas_host", sas_host_setup, NULL, NULL); 154c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 155c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_host_match(struct attribute_container *cont, 156c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev) 157c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 158c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 159c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 160c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 161c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_host_device(dev)) 162c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 163c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev); 164c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 165c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 166c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 167c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 168c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 169c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 170c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 171c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 172c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t.host_attrs.ac == cont; 173c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 174c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 175c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int do_sas_phy_delete(struct device *dev, void *data) 176c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 177c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (scsi_is_sas_phy(dev)) 178c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_delete(dev_to_phy(dev)); 179c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 180c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 181c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 182c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 183c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_remove_host -- tear down a Scsi_Host's SAS data structures 184c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @shost: Scsi Host that is torn down 185c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 186c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes all SAS PHYs and remote PHYs for a given Scsi_Host. 187c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Must be called just before scsi_remove_host for SAS HBAs. 188c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 189c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_remove_host(struct Scsi_Host *shost) 190c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 191c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_for_each_child(&shost->shost_gendev, NULL, do_sas_phy_delete); 192c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 193c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_remove_host); 194c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 195c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 196c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 197c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS Port attributes 198c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 199c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 200c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_simple(field, name, format_string, cast) \ 201c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 202c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##name(struct class_device *cdev, char *buf) \ 203c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 204c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 205c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 206c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast phy->field); \ 207c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 208c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 209c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_simple_attr(field, name, format_string, type) \ 210c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_simple(field, name, format_string, (type)) \ 211c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 212c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 213c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_protocol(field, name) \ 214c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 215c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##name(struct class_device *cdev, char *buf) \ 216c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 217c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 218c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 219c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy->field) \ 220c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 221c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(phy->field, buf); \ 222c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 223c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 224c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_protocol_attr(field, name) \ 225c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_protocol(field, name) \ 226c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 227c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 228c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_linkspeed(field) \ 229c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 230c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##field(struct class_device *cdev, char *buf) \ 231c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 232c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 233c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 234c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_linkspeed_names(phy->field, buf); \ 235c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 236c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 237c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_linkspeed_attr(field) \ 238c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_linkspeed(field) \ 239c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 240c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 241c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig#define sas_phy_show_linkerror(field) \ 242c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigstatic ssize_t \ 243c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigshow_sas_phy_##field(struct class_device *cdev, char *buf) \ 244c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig{ \ 245c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 246c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \ 247c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); \ 248c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig int error; \ 249c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig \ 250ac01bbbd3b7ebfca64357aed12cf476b16abe3ceChristoph Hellwig if (!phy->local_attached) \ 251ac01bbbd3b7ebfca64357aed12cf476b16abe3ceChristoph Hellwig return -EINVAL; \ 252ac01bbbd3b7ebfca64357aed12cf476b16abe3ceChristoph Hellwig \ 253dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0; \ 254c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig if (error) \ 255c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig return error; \ 256c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig return snprintf(buf, 20, "%u\n", phy->field); \ 257c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig} 258c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 259c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig#define sas_phy_linkerror_attr(field) \ 260c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig sas_phy_show_linkerror(field) \ 261c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigstatic CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 262c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 263c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 264c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 265c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_device_type(struct class_device *cdev, char *buf) 266c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 267c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); 268c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 269c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy->identify.device_type) 270c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 271c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names(phy->identify.device_type, buf); 272c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 273c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); 274c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 27507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic ssize_t do_sas_phy_reset(struct class_device *cdev, 27607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig size_t count, int hard_reset) 27707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 27807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); 27907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 28007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 28107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig int error; 28207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 28307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig if (!phy->local_attached) 28407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return -EINVAL; 28507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 28607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig error = i->f->phy_reset(phy, hard_reset); 28707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig if (error) 28807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return error; 28907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return count; 29007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig}; 29107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 29207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic ssize_t store_sas_link_reset(struct class_device *cdev, 29307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig const char *buf, size_t count) 29407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 29507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return do_sas_phy_reset(cdev, count, 0); 29607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig} 29707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); 29807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 29907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic ssize_t store_sas_hard_reset(struct class_device *cdev, 30007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig const char *buf, size_t count) 30107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 30207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return do_sas_phy_reset(cdev, count, 1); 30307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig} 30407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); 30507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 306c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.initiator_port_protocols, 307c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 308c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.target_port_protocols, 309c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig target_port_protocols); 310c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 311c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 312c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 313c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8); 314c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(negotiated_linkrate); 315c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(minimum_linkrate_hw); 316c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(minimum_linkrate); 317c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(maximum_linkrate_hw); 318c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(maximum_linkrate); 319c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(invalid_dword_count); 320c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(running_disparity_error_count); 321c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(loss_of_dword_sync_count); 322c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(phy_reset_problem_count); 323c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 324c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 325c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_phy_class, 326c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig "sas_phy", NULL, NULL, NULL); 327c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 328c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_phy_match(struct attribute_container *cont, struct device *dev) 329c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 330c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 331c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 332c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 333c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_phy(dev)) 334c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 335c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent); 336c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 337c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 338c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 339c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 340c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 341c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 342c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 343c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 344c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->phy_attr_cont.ac == cont; 345c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 346c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 347c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void sas_phy_release(struct device *dev) 348c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 349c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = dev_to_phy(dev); 350c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 351c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 352c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(phy); 353c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 354c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 355c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 356c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_alloc -- allocates and initialize a SAS PHY structure 357c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @parent: Parent device 358d99ca4180fe44ae7f409fc73f1a09f270b8d458aMoore, Eric * @number: Phy index 359c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 360c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Allocates an SAS PHY structure. It will be added in the device tree 361c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * below the device specified by @parent, which has to be either a Scsi_Host 362c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * or sas_rphy. 363c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 364c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 365c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS PHY allocated or %NULL if the allocation failed. 366c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 367c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_phy *sas_phy_alloc(struct device *parent, int number) 368c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 369c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent); 370c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy; 371c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 37224669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen phy = kzalloc(sizeof(*phy), GFP_KERNEL); 373c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy) 374c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 375c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 376c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->number = number; 377c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 378c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_initialize(&phy->dev); 379c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.parent = get_device(parent); 380c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.release = sas_phy_release; 38179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (scsi_is_sas_expander_device(parent)) { 38279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 38379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sprintf(phy->dev.bus_id, "phy-%d-%d:%d", shost->host_no, 38479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id, number); 38579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } else 38679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); 387c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 388c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_setup_device(&phy->dev); 389c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 390c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return phy; 391c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 392c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_alloc); 393c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 394c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 395c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_add -- add a SAS PHY to the device hierachy 396c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: The PHY to be added 397c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 398c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS PHY to the rest of the system. 399c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 400c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_phy_add(struct sas_phy *phy) 401c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 402c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 403c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 404c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&phy->dev); 405c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!error) { 406c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&phy->dev); 407c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&phy->dev); 408c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 409c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 410c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 411c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 412c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_add); 413c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 414c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 415c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_free -- free a SAS PHY 416c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to free 417c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 418c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS PHY. 419c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 420c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 421c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a PHY that has not 422c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sucessfully been added using sas_phy_add(). 423c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 424c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_phy_free(struct sas_phy *phy) 425c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 426c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(&phy->dev); 42792aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(&phy->dev); 428c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 429c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_free); 430c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 431c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 432c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_delete -- remove SAS PHY 433c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to remove 434c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 435c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes the specified SAS PHY. If the SAS PHY has an 436c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * associated remote PHY it is removed before. 437c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 438c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 439c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_delete(struct sas_phy *phy) 440c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 441c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &phy->dev; 442c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 443c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (phy->rphy) 444c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_delete(phy->rphy); 445c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 446c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_remove_device(dev); 447c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_del(dev); 448c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(dev); 44992aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 450c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 451c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_delete); 452c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 453c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 454c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * scsi_is_sas_phy -- check if a struct device represents a SAS PHY 455c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 456c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 457c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 458c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS PHY, %0 else 459c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 460c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_phy(const struct device *dev) 461c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 462c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return dev->release == sas_phy_release; 463c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 464c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_phy); 465c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 466c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 467c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS remote PHY attributes. 468c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 469c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 470c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_simple(field, name, format_string, cast) \ 471c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 472c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_##name(struct class_device *cdev, char *buf) \ 473c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 474c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 475c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 476c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast rphy->field); \ 477c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 478c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 479c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_simple_attr(field, name, format_string, type) \ 480c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_simple(field, name, format_string, (type)) \ 481c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 482c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 483c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 484c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_protocol(field, name) \ 485c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 486c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_##name(struct class_device *cdev, char *buf) \ 487c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 488c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 489c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 490c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->field) \ 491c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 492c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(rphy->field, buf); \ 493c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 494c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 495c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_protocol_attr(field, name) \ 496c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_protocol(field, name) \ 497c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 498c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 499c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 500c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 501c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_device_type(struct class_device *cdev, char *buf) 502c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 503c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 504c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 505c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->identify.device_type) 506c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 507c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names( 508c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->identify.device_type, buf); 509c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 510c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 511c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, 512c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_device_type, NULL); 513c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 514a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 515a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigshow_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf) 516a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 517a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 518a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 519a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 520a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 521a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig u64 identifier; 522a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int error; 523a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 524a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig /* 525a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * Only devices behind an expander are supported, because the 526a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * enclosure identifier is a SMP feature. 527a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig */ 528a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (phy->local_attached) 529a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 530a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 531a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig error = i->f->get_enclosure_identifier(rphy, &identifier); 532a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (error) 533a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return error; 534a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); 535a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 536a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 537a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, 538a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_enclosure_identifier, NULL); 539a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 540a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 541a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigshow_sas_rphy_bay_identifier(struct class_device *cdev, char *buf) 542a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 543a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 544a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 545a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 546a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 547a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int val; 548a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 549a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (phy->local_attached) 550a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 551a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 552a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig val = i->f->get_bay_identifier(rphy); 553a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (val < 0) 554a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return val; 555a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "%d\n", val); 556a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 557a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 558a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, 559a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_bay_identifier, NULL); 560a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 561c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.initiator_port_protocols, 562c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 563c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); 564c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 565c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 566c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 567c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 56842ab03609cca4ef5079e248296f015650c626899James Bottomley/* only need 8 bytes of data plus header (4 or 8) */ 56942ab03609cca4ef5079e248296f015650c626899James Bottomley#define BUF_SIZE 64 57042ab03609cca4ef5079e248296f015650c626899James Bottomley 57142ab03609cca4ef5079e248296f015650c626899James Bottomleyint sas_read_port_mode_page(struct scsi_device *sdev) 57242ab03609cca4ef5079e248296f015650c626899James Bottomley{ 57342ab03609cca4ef5079e248296f015650c626899James Bottomley char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; 57442ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target); 57542ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev; 57642ab03609cca4ef5079e248296f015650c626899James Bottomley struct scsi_mode_data mode_data; 57742ab03609cca4ef5079e248296f015650c626899James Bottomley int res, error; 57842ab03609cca4ef5079e248296f015650c626899James Bottomley 57942ab03609cca4ef5079e248296f015650c626899James Bottomley BUG_ON(rphy->identify.device_type != SAS_END_DEVICE); 58042ab03609cca4ef5079e248296f015650c626899James Bottomley 58142ab03609cca4ef5079e248296f015650c626899James Bottomley rdev = rphy_to_end_device(rphy); 58242ab03609cca4ef5079e248296f015650c626899James Bottomley 58342ab03609cca4ef5079e248296f015650c626899James Bottomley if (!buffer) 58442ab03609cca4ef5079e248296f015650c626899James Bottomley return -ENOMEM; 58542ab03609cca4ef5079e248296f015650c626899James Bottomley 58642ab03609cca4ef5079e248296f015650c626899James Bottomley res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, 58742ab03609cca4ef5079e248296f015650c626899James Bottomley &mode_data, NULL); 58842ab03609cca4ef5079e248296f015650c626899James Bottomley 58942ab03609cca4ef5079e248296f015650c626899James Bottomley error = -EINVAL; 59042ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_status_is_good(res)) 59142ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 59242ab03609cca4ef5079e248296f015650c626899James Bottomley 59342ab03609cca4ef5079e248296f015650c626899James Bottomley msdata = buffer + mode_data.header_length + 59442ab03609cca4ef5079e248296f015650c626899James Bottomley mode_data.block_descriptor_length; 59542ab03609cca4ef5079e248296f015650c626899James Bottomley 59642ab03609cca4ef5079e248296f015650c626899James Bottomley if (msdata - buffer > BUF_SIZE - 8) 59742ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 59842ab03609cca4ef5079e248296f015650c626899James Bottomley 59942ab03609cca4ef5079e248296f015650c626899James Bottomley error = 0; 60042ab03609cca4ef5079e248296f015650c626899James Bottomley 60142ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0; 60242ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5]; 60342ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7]; 60442ab03609cca4ef5079e248296f015650c626899James Bottomley 60542ab03609cca4ef5079e248296f015650c626899James Bottomley out: 60642ab03609cca4ef5079e248296f015650c626899James Bottomley kfree(buffer); 60742ab03609cca4ef5079e248296f015650c626899James Bottomley return error; 60842ab03609cca4ef5079e248296f015650c626899James Bottomley} 60942ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_read_port_mode_page); 61042ab03609cca4ef5079e248296f015650c626899James Bottomley 61179cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_end_dev_class, 61279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_end_device", NULL, NULL, NULL); 61379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 61442ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_show_simple(field, name, format_string, cast) \ 61542ab03609cca4ef5079e248296f015650c626899James Bottomleystatic ssize_t \ 61642ab03609cca4ef5079e248296f015650c626899James Bottomleyshow_sas_end_dev_##name(struct class_device *cdev, char *buf) \ 61742ab03609cca4ef5079e248296f015650c626899James Bottomley{ \ 61842ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 61942ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev = rphy_to_end_device(rphy); \ 62042ab03609cca4ef5079e248296f015650c626899James Bottomley \ 62142ab03609cca4ef5079e248296f015650c626899James Bottomley return snprintf(buf, 20, format_string, cast rdev->field); \ 62242ab03609cca4ef5079e248296f015650c626899James Bottomley} 62342ab03609cca4ef5079e248296f015650c626899James Bottomley 62442ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_simple_attr(field, name, format_string, type) \ 62542ab03609cca4ef5079e248296f015650c626899James Bottomley sas_end_dev_show_simple(field, name, format_string, (type)) \ 62642ab03609cca4ef5079e248296f015650c626899James Bottomleystatic SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ 62742ab03609cca4ef5079e248296f015650c626899James Bottomley show_sas_end_dev_##name, NULL) 62842ab03609cca4ef5079e248296f015650c626899James Bottomley 62942ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); 63042ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, 63142ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 63242ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, 63342ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 63442ab03609cca4ef5079e248296f015650c626899James Bottomley 63579cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_expander_class, 63679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_expander", NULL, NULL, NULL); 63779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 63879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_show_simple(field, name, format_string, cast) \ 63979cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic ssize_t \ 64079cb1819e231f811211133a09a5382cb89d7ec67James Bottomleyshow_sas_expander_##name(struct class_device *cdev, char *buf) \ 64179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ \ 64279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 64379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ 64479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley \ 64579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return snprintf(buf, 20, format_string, cast edev->field); \ 64679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 64779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 64879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_simple_attr(field, name, format_string, type) \ 64979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sas_expander_show_simple(field, name, format_string, (type)) \ 65079cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, \ 65179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley show_sas_expander_##name, NULL) 65279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 65379cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); 65479cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_id, product_id, "%s\n", char *); 65579cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_rev, product_rev, "%s\n", char *); 65679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_vendor_id, component_vendor_id, 65779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "%s\n", char *); 65879cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int); 65979cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", 66079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley unsigned int); 66179cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(level, level, "%d\n", int); 66242ab03609cca4ef5079e248296f015650c626899James Bottomley 663c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_rphy_class, 6642f8600dff2b140096a7df781884e918a16aa90e0James Bottomley "sas_device", NULL, NULL, NULL); 665c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 666c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_rphy_match(struct attribute_container *cont, struct device *dev) 667c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 668c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 669c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 670c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 671c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_rphy(dev)) 672c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 673c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent->parent); 674c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 675c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 676c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 677c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 678c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 679c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 680c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 681c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 682c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->rphy_attr_cont.ac == cont; 683c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 684c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 68542ab03609cca4ef5079e248296f015650c626899James Bottomleystatic int sas_end_dev_match(struct attribute_container *cont, 68642ab03609cca4ef5079e248296f015650c626899James Bottomley struct device *dev) 68742ab03609cca4ef5079e248296f015650c626899James Bottomley{ 68842ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost; 68942ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_internal *i; 69042ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy; 69142ab03609cca4ef5079e248296f015650c626899James Bottomley 69242ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_is_sas_rphy(dev)) 69342ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 69442ab03609cca4ef5079e248296f015650c626899James Bottomley shost = dev_to_shost(dev->parent->parent); 69542ab03609cca4ef5079e248296f015650c626899James Bottomley rphy = dev_to_rphy(dev); 69642ab03609cca4ef5079e248296f015650c626899James Bottomley 69742ab03609cca4ef5079e248296f015650c626899James Bottomley if (!shost->transportt) 69842ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 69942ab03609cca4ef5079e248296f015650c626899James Bottomley if (shost->transportt->host_attrs.ac.class != 70042ab03609cca4ef5079e248296f015650c626899James Bottomley &sas_host_class.class) 70142ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 70242ab03609cca4ef5079e248296f015650c626899James Bottomley 70342ab03609cca4ef5079e248296f015650c626899James Bottomley i = to_sas_internal(shost->transportt); 70442ab03609cca4ef5079e248296f015650c626899James Bottomley return &i->end_dev_attr_cont.ac == cont && 7052f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_END_DEVICE; 70642ab03609cca4ef5079e248296f015650c626899James Bottomley} 70742ab03609cca4ef5079e248296f015650c626899James Bottomley 70879cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic int sas_expander_match(struct attribute_container *cont, 70979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct device *dev) 71079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 71179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost; 71279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_internal *i; 71379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy; 71479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 71579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!scsi_is_sas_rphy(dev)) 71679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 71779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley shost = dev_to_shost(dev->parent->parent); 71879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy = dev_to_rphy(dev); 71979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 72079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!shost->transportt) 72179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 72279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (shost->transportt->host_attrs.ac.class != 72379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley &sas_host_class.class) 72479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 72579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 72679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i = to_sas_internal(shost->transportt); 72779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &i->expander_attr_cont.ac == cont && 72879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || 7292f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE); 73079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 73179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 7322f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_expander_release(struct device *dev) 733c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 734c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = dev_to_rphy(dev); 7352f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); 736c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 737c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 7382f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 739c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 740c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 7412f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_end_device_release(struct device *dev) 742c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 7432f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_rphy *rphy = dev_to_rphy(dev); 7442f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_end_device *edev = rphy_to_end_device(rphy); 745c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 7462f8600dff2b140096a7df781884e918a16aa90e0James Bottomley put_device(dev->parent); 7472f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 748c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 749c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 750c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 75142ab03609cca4ef5079e248296f015650c626899James Bottomley * sas_end_device_alloc - allocate an rphy for an end device 75242ab03609cca4ef5079e248296f015650c626899James Bottomley * 75342ab03609cca4ef5079e248296f015650c626899James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 75442ab03609cca4ef5079e248296f015650c626899James Bottomley * 75542ab03609cca4ef5079e248296f015650c626899James Bottomley * Returns: 75642ab03609cca4ef5079e248296f015650c626899James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 75742ab03609cca4ef5079e248296f015650c626899James Bottomley */ 75842ab03609cca4ef5079e248296f015650c626899James Bottomleystruct sas_rphy *sas_end_device_alloc(struct sas_phy *parent) 75942ab03609cca4ef5079e248296f015650c626899James Bottomley{ 76042ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 76142ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev; 76242ab03609cca4ef5079e248296f015650c626899James Bottomley 76342ab03609cca4ef5079e248296f015650c626899James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 76442ab03609cca4ef5079e248296f015650c626899James Bottomley if (!rdev) { 76542ab03609cca4ef5079e248296f015650c626899James Bottomley return NULL; 76642ab03609cca4ef5079e248296f015650c626899James Bottomley } 76742ab03609cca4ef5079e248296f015650c626899James Bottomley 76842ab03609cca4ef5079e248296f015650c626899James Bottomley device_initialize(&rdev->rphy.dev); 76942ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 7702f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_end_device_release; 7712f8600dff2b140096a7df781884e918a16aa90e0James Bottomley sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d-%d", 77242ab03609cca4ef5079e248296f015650c626899James Bottomley shost->host_no, parent->port_identifier, parent->number); 77342ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.identify.device_type = SAS_END_DEVICE; 77442ab03609cca4ef5079e248296f015650c626899James Bottomley transport_setup_device(&rdev->rphy.dev); 77542ab03609cca4ef5079e248296f015650c626899James Bottomley 77642ab03609cca4ef5079e248296f015650c626899James Bottomley return &rdev->rphy; 77742ab03609cca4ef5079e248296f015650c626899James Bottomley} 77842ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_end_device_alloc); 77942ab03609cca4ef5079e248296f015650c626899James Bottomley 78079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley/** 78179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * sas_expander_alloc - allocate an rphy for an end device 78279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 78379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 78479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 78579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Returns: 78679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 78779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley */ 78879cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystruct sas_rphy *sas_expander_alloc(struct sas_phy *parent, 78979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley enum sas_device_type type) 79079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 79179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 79279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *rdev; 79379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 79479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 79579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE && 79679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley type != SAS_FANOUT_EXPANDER_DEVICE); 79779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 79879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 79979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!rdev) { 80079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return NULL; 80179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } 80279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 80379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley device_initialize(&rdev->rphy.dev); 80479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 8052f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_expander_release; 80679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_lock(&sas_host->lock); 80779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.scsi_target_id = sas_host->next_expander_id++; 80879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_unlock(&sas_host->lock); 80979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", 81079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley shost->host_no, rdev->rphy.scsi_target_id); 81179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.identify.device_type = type; 81279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_setup_device(&rdev->rphy.dev); 81379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 81479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &rdev->rphy; 81579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 81679cb1819e231f811211133a09a5382cb89d7ec67James BottomleyEXPORT_SYMBOL(sas_expander_alloc); 81742ab03609cca4ef5079e248296f015650c626899James Bottomley 81842ab03609cca4ef5079e248296f015650c626899James Bottomley/** 819c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_add -- add a SAS remote PHY to the device hierachy 820c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy: The remote PHY to be added 821c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 822c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS remote PHY to the rest of the system. 823c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 824c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_rphy_add(struct sas_rphy *rphy) 825c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 826c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *parent = dev_to_phy(rphy->dev.parent); 827c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 828c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 829c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_identify *identify = &rphy->identify; 830c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 831c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 832c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (parent->rphy) 833c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return -ENXIO; 834c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig parent->rphy = rphy; 835c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 836c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&rphy->dev); 837c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 838c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 839c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&rphy->dev); 840c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&rphy->dev); 841c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 842e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 843c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_add_tail(&rphy->list, &sas_host->rphy_list); 844c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (identify->device_type == SAS_END_DEVICE && 845c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (identify->target_port_protocols & 846c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) 847c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id = sas_host->next_target_id++; 8487676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley else if (identify->device_type == SAS_END_DEVICE) 8497676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley rphy->scsi_target_id = -1; 850e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 851c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 85279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (identify->device_type == SAS_END_DEVICE && 85379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id != -1) { 854e6bc863cf25f30ed8e2a4d41b76d5688f8efaee9Moore, Eric scsi_scan_target(&rphy->dev, parent->port_identifier, 855c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id, ~0, 0); 856c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 857c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 858c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 859c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 860c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_add); 861c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 862c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 863c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_free -- free a SAS remote PHY 864c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy SAS remote PHY to free 865c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 866c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS remote PHY. 867c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 868c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 869c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a remote 870c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * PHY that has not sucessfully been added using 871c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_add(). 872c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 873c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_rphy_free(struct sas_rphy *rphy) 874c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 87592aab6464be735139f9ea38fd039c3b84c722630Mike Anderson struct device *dev = &rphy->dev; 876c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 877c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 878c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 879e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 880c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_del(&rphy->list); 881e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 882c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 88392aab6464be735139f9ea38fd039c3b84c722630Mike Anderson transport_destroy_device(dev); 8842f8600dff2b140096a7df781884e918a16aa90e0James Bottomley 88592aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 886c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 887c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_free); 888c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 889c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 890c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_delete -- remove SAS remote PHY 891c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy: SAS remote PHY to remove 892c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 893c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes the specified SAS remote PHY. 894c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 895c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 896c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_delete(struct sas_rphy *rphy) 897c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 898c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &rphy->dev; 899c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *parent = dev_to_phy(dev->parent); 900c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 901c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 902c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 903d4054239929479907f20b9d68c905589125ad343Christoph Hellwig switch (rphy->identify.device_type) { 904d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_END_DEVICE: 905d4054239929479907f20b9d68c905589125ad343Christoph Hellwig scsi_remove_target(dev); 906d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 907d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_EDGE_EXPANDER_DEVICE: 908d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_FANOUT_EXPANDER_DEVICE: 909d4054239929479907f20b9d68c905589125ad343Christoph Hellwig device_for_each_child(dev, NULL, do_sas_phy_delete); 910d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 911d4054239929479907f20b9d68c905589125ad343Christoph Hellwig default: 912d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 913d4054239929479907f20b9d68c905589125ad343Christoph Hellwig } 914c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 915fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig transport_remove_device(dev); 916fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig device_del(dev); 917fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig transport_destroy_device(dev); 918c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 919e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 920c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_del(&rphy->list); 921e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 922c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 92333b114e935a2202206e224dd2c695cee5a5986bfChristoph Hellwig parent->rphy = NULL; 92433b114e935a2202206e224dd2c695cee5a5986bfChristoph Hellwig 92592aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 926c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 927c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_delete); 928c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 929c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 930c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY 931c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 932c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 933c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 934c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS remote PHY, %0 else 935c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 936c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_rphy(const struct device *dev) 937c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 9382f8600dff2b140096a7df781884e918a16aa90e0James Bottomley return dev->release == sas_end_device_release || 9392f8600dff2b140096a7df781884e918a16aa90e0James Bottomley dev->release == sas_expander_release; 940c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 941c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_rphy); 942c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 943c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 944c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 945c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SCSI scan helper 946c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 947c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 948e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwigstatic int sas_user_scan(struct Scsi_Host *shost, uint channel, 949e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig uint id, uint lun) 950c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 951c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 952c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy; 953c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 954e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 955c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_for_each_entry(rphy, &sas_host->rphy_list, list) { 956c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *parent = dev_to_phy(rphy->dev.parent); 957e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig 9586d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley if (rphy->identify.device_type != SAS_END_DEVICE || 9596d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley rphy->scsi_target_id == -1) 960e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig continue; 961e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig 962e6bc863cf25f30ed8e2a4d41b76d5688f8efaee9Moore, Eric if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) && 963e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { 964e6bc863cf25f30ed8e2a4d41b76d5688f8efaee9Moore, Eric scsi_scan_target(&rphy->dev, parent->port_identifier, 965e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig rphy->scsi_target_id, lun, 1); 966e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig } 967c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 968e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 969c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 970e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig return 0; 971c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 972c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 973c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 974c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 975c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Setup / Teardown code 976c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 977c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 97842ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_TEMPLATE(attrb, field, perm, test) \ 97942ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count] = class_device_attr_##field; \ 98042ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count].attr.mode = perm; \ 98142ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count].store = NULL; \ 98242ab03609cca4ef5079e248296f015650c626899James Bottomley i->attrb[count] = &i->private_##attrb[count]; \ 98342ab03609cca4ef5079e248296f015650c626899James Bottomley if (test) \ 98442ab03609cca4ef5079e248296f015650c626899James Bottomley count++ 98542ab03609cca4ef5079e248296f015650c626899James Bottomley 98642ab03609cca4ef5079e248296f015650c626899James Bottomley 98742ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_RPORT_ATTRIBUTE(field) \ 98842ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) 989c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 990dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ 99142ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func) 992dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 993c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define SETUP_PORT_ATTRIBUTE(field) \ 99442ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) 995c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 996dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley#define SETUP_OPTIONAL_PORT_ATTRIBUTE(field, func) \ 99742ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) 998dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 99907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig#define SETUP_PORT_ATTRIBUTE_WRONLY(field) \ 100042ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1) 100107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 1002dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley#define SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(field, func) \ 100342ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func) 1004dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 100542ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_END_DEV_ATTRIBUTE(field) \ 100642ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) 1007c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 100879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define SETUP_EXPANDER_ATTRIBUTE(field) \ 100979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) 101079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1011c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1012c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_attach_transport -- instantiate SAS transport template 1013c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @ft: SAS transport class function template 1014c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1015c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct scsi_transport_template * 1016c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_attach_transport(struct sas_function_template *ft) 1017c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1018c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 1019c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int count; 1020c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 102124669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL); 1022c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!i) 1023c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 1024c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1025e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig i->t.user_scan = sas_user_scan; 1026c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1027c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 1028c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.class = &sas_host_class.class; 1029c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.match = sas_host_match; 1030c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->t.host_attrs); 1031c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_size = sizeof(struct sas_host_attrs); 1032c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1033c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.class = &sas_phy_class.class; 1034c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.attrs = &i->phy_attrs[0]; 1035c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.match = sas_phy_match; 1036c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->phy_attr_cont); 1037c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1038c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.class = &sas_rphy_class.class; 1039c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0]; 1040c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.match = sas_rphy_match; 1041c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->rphy_attr_cont); 1042c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 104342ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class; 104442ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0]; 104542ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.match = sas_end_dev_match; 104642ab03609cca4ef5079e248296f015650c626899James Bottomley transport_container_register(&i->end_dev_attr_cont); 104742ab03609cca4ef5079e248296f015650c626899James Bottomley 104879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.class = &sas_expander_class.class; 104979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.attrs = &i->expander_attrs[0]; 105079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.match = sas_expander_match; 105179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_register(&i->expander_attr_cont); 105279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1053c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->f = ft; 1054c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1055c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 1056c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->host_attrs[count] = NULL; 1057c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1058c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 1059c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(initiator_port_protocols); 1060c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(target_port_protocols); 1061c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(device_type); 1062c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(sas_address); 1063c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(phy_identifier); 1064c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(port_identifier); 1065c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(negotiated_linkrate); 1066c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(minimum_linkrate_hw); 1067c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(minimum_linkrate); 1068c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw); 1069c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(maximum_linkrate); 1070c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 1071c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig SETUP_PORT_ATTRIBUTE(invalid_dword_count); 1072c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig SETUP_PORT_ATTRIBUTE(running_disparity_error_count); 1073c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig SETUP_PORT_ATTRIBUTE(loss_of_dword_sync_count); 1074c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig SETUP_PORT_ATTRIBUTE(phy_reset_problem_count); 1075dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(link_reset, phy_reset); 1076dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(hard_reset, phy_reset); 1077c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attrs[count] = NULL; 1078c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1079c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 1080c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols); 1081c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols); 1082c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_device_type); 1083c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_sas_address); 1084c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); 1085dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier, 1086dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_enclosure_identifier); 1087dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier, 1088dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_bay_identifier); 1089c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attrs[count] = NULL; 1090c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 109142ab03609cca4ef5079e248296f015650c626899James Bottomley count = 0; 109242ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); 109342ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); 109442ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); 109542ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attrs[count] = NULL; 109642ab03609cca4ef5079e248296f015650c626899James Bottomley 109779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley count = 0; 109879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(vendor_id); 109979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_id); 110079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_rev); 110179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_vendor_id); 110279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_id); 110379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_revision_id); 110479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(level); 110579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attrs[count] = NULL; 110679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1107c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t; 1108c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1109c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_attach_transport); 1110c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1111c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1112c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_release_transport -- release SAS transport template instance 1113c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @t: transport template instance 1114c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1115c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_release_transport(struct scsi_transport_template *t) 1116c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1117c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i = to_sas_internal(t); 1118c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1119c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->t.host_attrs); 1120c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->phy_attr_cont); 1121c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->rphy_attr_cont); 1122db82f8410ed7546792358964aa5f8dafff1c70a2James Bottomley transport_container_unregister(&i->end_dev_attr_cont); 112379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_unregister(&i->expander_attr_cont); 1124c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1125c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(i); 1126c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1127c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_release_transport); 1128c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1129c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic __init int sas_transport_init(void) 1130c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1131c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1132c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1133c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_host_class); 1134c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1135c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out; 1136c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_phy_class); 1137c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1138c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_transport; 1139c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_rphy_class); 1140c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1141c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_phy; 114242ab03609cca4ef5079e248296f015650c626899James Bottomley error = transport_class_register(&sas_end_dev_class); 114342ab03609cca4ef5079e248296f015650c626899James Bottomley if (error) 114442ab03609cca4ef5079e248296f015650c626899James Bottomley goto out_unregister_rphy; 114579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley error = transport_class_register(&sas_expander_class); 114679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (error) 114779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley goto out_unregister_end_dev; 1148c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1149c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1150c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 115179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley out_unregister_end_dev: 115279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_end_dev_class); 115342ab03609cca4ef5079e248296f015650c626899James Bottomley out_unregister_rphy: 115442ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_rphy_class); 1155c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_phy: 1156c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 1157c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_transport: 1158c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1159c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out: 1160c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1161c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1162c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1163c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1164c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void __exit sas_transport_exit(void) 1165c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1166c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1167c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 1168c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_rphy_class); 116942ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_end_dev_class); 117079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_expander_class); 1171c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1172c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1173c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_AUTHOR("Christoph Hellwig"); 1174c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_DESCRIPTION("SAS Transphy Attributes"); 1175c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_LICENSE("GPL"); 1176c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1177c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_init(sas_transport_init); 1178c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_exit(sas_transport_exit); 1179