scsi_transport_sas.c revision c7ebbbce366c02e5657ac6b6059933fe0353b175
1c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 2c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Copyright (C) 2005 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> 29c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 30c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_device.h> 31c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_host.h> 32c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_transport.h> 33c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_transport_sas.h> 34c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 35c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 36c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define SAS_HOST_ATTRS 0 37c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define SAS_PORT_ATTRS 11 38c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define SAS_RPORT_ATTRS 5 39c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 40c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_internal { 41c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct scsi_transport_template t; 42c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_function_template *f; 43c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 44c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS]; 45c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS]; 46c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS]; 47c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 48c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct transport_container phy_attr_cont; 49c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct transport_container rphy_attr_cont; 50c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 51c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig /* 52c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * The array of null terminated pointers to attributes 53c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * needed by scsi_sysfs.c 54c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 55c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1]; 56c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1]; 57c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1]; 58c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 59c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t) 60c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 61c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_host_attrs { 62c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct list_head rphy_list; 63c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig spinlock_t lock; 64c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 next_target_id; 65c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 66c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) 67c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 68c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 69c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 70c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Hack to allow attributes of the same name in different objects. 71c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 72c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \ 73c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct class_device_attribute class_device_attr_##_prefix##_##_name = \ 74c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig __ATTR(_name,_mode,_show,_store) 75c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 76c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 77c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 78c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Pretty printing helpers 79c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 80c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 81c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_match(title, table) \ 82c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 83c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf) \ 84c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 85c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *prefix = ""; \ 86c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig ssize_t len = 0; \ 87c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int i; \ 88c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 89c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ 90c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (table[i].value & table_key) { \ 91c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "%s%s", \ 92c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig prefix, table[i].name); \ 93c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig prefix = ", "; \ 94c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 95c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 96c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "\n"); \ 97c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return len; \ 98c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 99c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 100c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_search(title, table) \ 101c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 102c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf) \ 103c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 104c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig ssize_t len = 0; \ 105c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int i; \ 106c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 107c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ 108c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (table[i].value == table_key) { \ 109c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "%s", \ 110c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig table[i].name); \ 111c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig break; \ 112c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 113c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 114c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "\n"); \ 115c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return len; \ 116c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 117c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 118c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 119c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 120c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 121c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_device_type_names[] = { 122c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PHY_UNUSED, "unused" }, 123c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_END_DEVICE, "end device" }, 124c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_EDGE_EXPANDER_DEVICE, "edge expander" }, 125c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" }, 126c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 127c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(device_type, sas_device_type_names) 128c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 129c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 130c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 131c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 132c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 133c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_protocol_names[] = { 134c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SATA, "sata" }, 135c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SMP, "smp" }, 136c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_STP, "stp" }, 137c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SSP, "ssp" }, 138c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 139c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_match(protocol, sas_protocol_names) 140c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 141c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 142c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 143c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 144c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_linkspeed_names[] = { 145c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_UNKNOWN, "Unknown" }, 146c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PHY_DISABLED, "Phy disabled" }, 147c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_FAILED, "Link Rate failed" }, 148c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_SATA_SPINUP_HOLD, "Spin-up hold" }, 149c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, 150c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, 151c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 152c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(linkspeed, sas_linkspeed_names) 153c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 154c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 155c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 156c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS host attributes 157c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 158c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 159c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_host_setup(struct device *dev) 160c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 161c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(dev); 162c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 163c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 164c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig INIT_LIST_HEAD(&sas_host->rphy_list); 165c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig spin_lock_init(&sas_host->lock); 166c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_host->next_target_id = 0; 167c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 168c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 169c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 170c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_host_class, 171c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig "sas_host", sas_host_setup, NULL, NULL); 172c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 173c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_host_match(struct attribute_container *cont, 174c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev) 175c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 176c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 177c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 178c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 179c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_host_device(dev)) 180c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 181c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev); 182c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 183c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 184c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 185c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 186c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 187c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 188c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 189c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 190c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t.host_attrs.ac == cont; 191c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 192c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 193c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int do_sas_phy_delete(struct device *dev, void *data) 194c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 195c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (scsi_is_sas_phy(dev)) 196c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_delete(dev_to_phy(dev)); 197c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 198c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 199c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 200c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 201c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_remove_host -- tear down a Scsi_Host's SAS data structures 202c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @shost: Scsi Host that is torn down 203c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 204c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes all SAS PHYs and remote PHYs for a given Scsi_Host. 205c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Must be called just before scsi_remove_host for SAS HBAs. 206c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 207c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_remove_host(struct Scsi_Host *shost) 208c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 209c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_for_each_child(&shost->shost_gendev, NULL, do_sas_phy_delete); 210c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 211c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_remove_host); 212c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 213c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 214c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 215c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS Port attributes 216c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 217c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 218c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_simple(field, name, format_string, cast) \ 219c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 220c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##name(struct class_device *cdev, char *buf) \ 221c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 222c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 223c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 224c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast phy->field); \ 225c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 226c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 227c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_simple_attr(field, name, format_string, type) \ 228c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_simple(field, name, format_string, (type)) \ 229c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 230c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 231c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_protocol(field, name) \ 232c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 233c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##name(struct class_device *cdev, char *buf) \ 234c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 235c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 236c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 237c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy->field) \ 238c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 239c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(phy->field, buf); \ 240c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 241c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 242c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_protocol_attr(field, name) \ 243c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_protocol(field, name) \ 244c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 245c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 246c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_linkspeed(field) \ 247c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 248c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##field(struct class_device *cdev, char *buf) \ 249c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 250c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 251c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 252c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_linkspeed_names(phy->field, buf); \ 253c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 254c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 255c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_linkspeed_attr(field) \ 256c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_linkspeed(field) \ 257c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 258c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 259c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 260c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_device_type(struct class_device *cdev, char *buf) 261c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 262c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); 263c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 264c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy->identify.device_type) 265c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 266c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names(phy->identify.device_type, buf); 267c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 268c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 269c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); 270c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 271c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.initiator_port_protocols, 272c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 273c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.target_port_protocols, 274c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig target_port_protocols); 275c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 276c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 277c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 278c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8); 279c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(negotiated_linkrate); 280c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(minimum_linkrate_hw); 281c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(minimum_linkrate); 282c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(maximum_linkrate_hw); 283c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(maximum_linkrate); 284c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 285c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 286c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_phy_class, 287c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig "sas_phy", NULL, NULL, NULL); 288c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 289c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_phy_match(struct attribute_container *cont, struct device *dev) 290c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 291c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 292c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 293c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 294c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_phy(dev)) 295c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 296c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent); 297c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 298c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 299c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 300c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 301c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 302c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 303c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 304c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 305c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->phy_attr_cont.ac == cont; 306c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 307c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 308c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void sas_phy_release(struct device *dev) 309c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 310c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = dev_to_phy(dev); 311c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 312c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 313c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(phy); 314c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 315c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 316c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 317c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_alloc -- allocates and initialize a SAS PHY structure 318c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @parent: Parent device 319c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @number: Port number 320c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 321c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Allocates an SAS PHY structure. It will be added in the device tree 322c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * below the device specified by @parent, which has to be either a Scsi_Host 323c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * or sas_rphy. 324c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 325c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 326c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS PHY allocated or %NULL if the allocation failed. 327c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 328c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_phy *sas_phy_alloc(struct device *parent, int number) 329c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 330c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent); 331c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy; 332c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 333c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy = kmalloc(sizeof(*phy), GFP_KERNEL); 334c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy) 335c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 336c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig memset(phy, 0, sizeof(*phy)); 337c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 338c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig get_device(parent); 339c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 340c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->number = number; 341c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 342c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_initialize(&phy->dev); 343c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.parent = get_device(parent); 344c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.release = sas_phy_release; 345c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); 346c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 347c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_setup_device(&phy->dev); 348c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 349c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return phy; 350c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 351c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_alloc); 352c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 353c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 354c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_add -- add a SAS PHY to the device hierachy 355c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: The PHY to be added 356c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 357c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS PHY to the rest of the system. 358c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 359c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_phy_add(struct sas_phy *phy) 360c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 361c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 362c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 363c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&phy->dev); 364c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!error) { 365c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&phy->dev); 366c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&phy->dev); 367c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 368c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 369c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 370c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 371c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_add); 372c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 373c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 374c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_free -- free a SAS PHY 375c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to free 376c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 377c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS PHY. 378c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 379c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 380c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a PHY that has not 381c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sucessfully been added using sas_phy_add(). 382c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 383c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_phy_free(struct sas_phy *phy) 384c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 385c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(&phy->dev); 386c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(phy->dev.parent); 387c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(phy->dev.parent); 388c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(phy->dev.parent); 389c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(phy); 390c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 391c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_free); 392c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 393c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 394c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_delete -- remove SAS PHY 395c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to remove 396c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 397c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes the specified SAS PHY. If the SAS PHY has an 398c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * associated remote PHY it is removed before. 399c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 400c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 401c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_delete(struct sas_phy *phy) 402c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 403c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &phy->dev; 404c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 405c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (phy->rphy) 406c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_delete(phy->rphy); 407c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 408c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_remove_device(dev); 409c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_del(dev); 410c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(dev); 411c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 412c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 413c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_delete); 414c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 415c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 416c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * scsi_is_sas_phy -- check if a struct device represents a SAS PHY 417c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 418c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 419c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 420c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS PHY, %0 else 421c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 422c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_phy(const struct device *dev) 423c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 424c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return dev->release == sas_phy_release; 425c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 426c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_phy); 427c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 428c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 429c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS remote PHY attributes. 430c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 431c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 432c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_simple(field, name, format_string, cast) \ 433c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 434c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_##name(struct class_device *cdev, char *buf) \ 435c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 436c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 437c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 438c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast rphy->field); \ 439c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 440c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 441c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_simple_attr(field, name, format_string, type) \ 442c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_simple(field, name, format_string, (type)) \ 443c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 444c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 445c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 446c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_protocol(field, name) \ 447c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 448c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_##name(struct class_device *cdev, char *buf) \ 449c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 450c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 451c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 452c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->field) \ 453c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 454c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(rphy->field, buf); \ 455c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 456c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 457c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_protocol_attr(field, name) \ 458c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_protocol(field, name) \ 459c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 460c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 461c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 462c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 463c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_device_type(struct class_device *cdev, char *buf) 464c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 465c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 466c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 467c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->identify.device_type) 468c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 469c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names( 470c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->identify.device_type, buf); 471c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 472c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 473c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, 474c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_device_type, NULL); 475c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 476c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.initiator_port_protocols, 477c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 478c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); 479c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 480c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 481c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 482c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 483c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_rphy_class, 484c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig "sas_rphy", NULL, NULL, NULL); 485c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 486c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_rphy_match(struct attribute_container *cont, struct device *dev) 487c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 488c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 489c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 490c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 491c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_rphy(dev)) 492c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 493c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent->parent); 494c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 495c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 496c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 497c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 498c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 499c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 500c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 501c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 502c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->rphy_attr_cont.ac == cont; 503c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 504c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 505c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void sas_rphy_release(struct device *dev) 506c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 507c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = dev_to_rphy(dev); 508c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 509c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 510c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(rphy); 511c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 512c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 513c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 514c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_alloc -- allocates and initialize a SAS remote PHY structure 515c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @parent: SAS PHY this remote PHY is conneted to 516c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 517c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Allocates an SAS remote PHY structure, connected to @parent. 518c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 519c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 520c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS PHY allocated or %NULL if the allocation failed. 521c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 522c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_rphy *sas_rphy_alloc(struct sas_phy *parent) 523c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 524c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(&parent->dev); 525c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy; 526c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 527c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy = kmalloc(sizeof(*rphy), GFP_KERNEL); 528c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy) { 529c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(&parent->dev); 530c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 531c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 532c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig memset(rphy, 0, sizeof(*rphy)); 533c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 534c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_initialize(&rphy->dev); 535c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->dev.parent = get_device(&parent->dev); 536c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->dev.release = sas_rphy_release; 537c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sprintf(rphy->dev.bus_id, "rphy-%d:%d", 538c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost->host_no, parent->number); 539c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_setup_device(&rphy->dev); 540c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 541c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return rphy; 542c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 543c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_alloc); 544c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 545c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 546c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_add -- add a SAS remote PHY to the device hierachy 547c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy: The remote PHY to be added 548c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 549c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS remote PHY to the rest of the system. 550c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 551c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_rphy_add(struct sas_rphy *rphy) 552c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 553c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *parent = dev_to_phy(rphy->dev.parent); 554c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 555c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 556c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_identify *identify = &rphy->identify; 557c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 558c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 559c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (parent->rphy) 560c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return -ENXIO; 561c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig parent->rphy = rphy; 562c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 563c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&rphy->dev); 564c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 565c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 566c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&rphy->dev); 567c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&rphy->dev); 568c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 569c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig spin_lock(&sas_host->lock); 570c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_add_tail(&rphy->list, &sas_host->rphy_list); 571c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (identify->device_type == SAS_END_DEVICE && 572c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (identify->target_port_protocols & 573c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) 574c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id = sas_host->next_target_id++; 575c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig else 576c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id = -1; 577c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig spin_unlock(&sas_host->lock); 578c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 579c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (rphy->scsi_target_id != -1) { 580c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig scsi_scan_target(&rphy->dev, parent->number, 581c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id, ~0, 0); 582c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 583c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 584c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 585c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 586c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_add); 587c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 588c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 589c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_free -- free a SAS remote PHY 590c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy SAS remote PHY to free 591c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 592c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS remote PHY. 593c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 594c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 595c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a remote 596c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * PHY that has not sucessfully been added using 597c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_add(). 598c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 599c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_rphy_free(struct sas_rphy *rphy) 600c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 601c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 602c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 603c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 604c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig spin_lock(&sas_host->lock); 605c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_del(&rphy->list); 606c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig spin_unlock(&sas_host->lock); 607c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 608c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(&rphy->dev); 609c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(rphy->dev.parent); 610c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(rphy->dev.parent); 611c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(rphy->dev.parent); 612c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(rphy); 613c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 614c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_free); 615c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 616c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 617c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_delete -- remove SAS remote PHY 618c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy: SAS remote PHY to remove 619c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 620c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes the specified SAS remote PHY. 621c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 622c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 623c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_delete(struct sas_rphy *rphy) 624c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 625c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &rphy->dev; 626c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *parent = dev_to_phy(dev->parent); 627c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 628c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 629c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 630c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(&rphy->dev); 631c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 632c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig scsi_remove_target(&rphy->dev); 633c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 634c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig spin_lock(&sas_host->lock); 635c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_del(&rphy->list); 636c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig spin_unlock(&sas_host->lock); 637c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 638c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_remove_device(dev); 639c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_del(dev); 640c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(dev); 641c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(&parent->dev); 642c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 643c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_delete); 644c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 645c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 646c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY 647c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 648c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 649c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 650c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS remote PHY, %0 else 651c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 652c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_rphy(const struct device *dev) 653c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 654c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return dev->release == sas_rphy_release; 655c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 656c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_rphy); 657c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 658c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 659c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 660c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SCSI scan helper 661c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 662c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 663c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct device *sas_target_parent(struct Scsi_Host *shost, 664c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int channel, uint id) 665c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 666c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 667c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy; 668c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = NULL; 669c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 670c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig spin_lock(&sas_host->lock); 671c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_for_each_entry(rphy, &sas_host->rphy_list, list) { 672c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *parent = dev_to_phy(rphy->dev.parent); 673c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (parent->number == channel && 674c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id == id) 675c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig dev = &rphy->dev; 676c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 677c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig spin_unlock(&sas_host->lock); 678c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 679c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return dev; 680c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 681c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 682c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 683c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 684c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Setup / Teardown code 685c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 686c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 687c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define SETUP_RPORT_ATTRIBUTE(field) \ 688c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->private_rphy_attrs[count] = class_device_attr_##field; \ 689c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->private_rphy_attrs[count].attr.mode = S_IRUGO; \ 690c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->private_rphy_attrs[count].store = NULL; \ 691c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \ 692c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count++ 693c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 694c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define SETUP_PORT_ATTRIBUTE(field) \ 695c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->private_phy_attrs[count] = class_device_attr_##field; \ 696c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->private_phy_attrs[count].attr.mode = S_IRUGO; \ 697c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->private_phy_attrs[count].store = NULL; \ 698c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attrs[count] = &i->private_phy_attrs[count]; \ 699c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count++ 700c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 701c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 702c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 703c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_attach_transport -- instantiate SAS transport template 704c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @ft: SAS transport class function template 705c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 706c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct scsi_transport_template * 707c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_attach_transport(struct sas_function_template *ft) 708c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 709c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 710c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int count; 711c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 712c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = kmalloc(sizeof(struct sas_internal), GFP_KERNEL); 713c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!i) 714c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 715c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig memset(i, 0, sizeof(struct sas_internal)); 716c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 717c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.target_parent = sas_target_parent; 718c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 719c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 720c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.class = &sas_host_class.class; 721c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.match = sas_host_match; 722c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->t.host_attrs); 723c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_size = sizeof(struct sas_host_attrs); 724c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 725c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.class = &sas_phy_class.class; 726c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.attrs = &i->phy_attrs[0]; 727c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.match = sas_phy_match; 728c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->phy_attr_cont); 729c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 730c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.class = &sas_rphy_class.class; 731c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0]; 732c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.match = sas_rphy_match; 733c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->rphy_attr_cont); 734c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 735c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->f = ft; 736c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 737c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 738c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->host_attrs[count] = NULL; 739c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 740c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 741c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(initiator_port_protocols); 742c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(target_port_protocols); 743c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(device_type); 744c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(sas_address); 745c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(phy_identifier); 746c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(port_identifier); 747c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(negotiated_linkrate); 748c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(minimum_linkrate_hw); 749c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(minimum_linkrate); 750c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw); 751c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_PORT_ATTRIBUTE(maximum_linkrate); 752c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attrs[count] = NULL; 753c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 754c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 755c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols); 756c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols); 757c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_device_type); 758c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_sas_address); 759c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); 760c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attrs[count] = NULL; 761c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 762c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t; 763c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 764c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_attach_transport); 765c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 766c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 767c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_release_transport -- release SAS transport template instance 768c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @t: transport template instance 769c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 770c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_release_transport(struct scsi_transport_template *t) 771c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 772c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i = to_sas_internal(t); 773c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 774c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->t.host_attrs); 775c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->phy_attr_cont); 776c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->rphy_attr_cont); 777c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 778c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(i); 779c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 780c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_release_transport); 781c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 782c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic __init int sas_transport_init(void) 783c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 784c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 785c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 786c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_host_class); 787c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 788c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out; 789c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_phy_class); 790c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 791c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_transport; 792c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_rphy_class); 793c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 794c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_phy; 795c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 796c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 797c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 798c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_phy: 799c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 800c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_transport: 801c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 802c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out: 803c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 804c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 805c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 806c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 807c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void __exit sas_transport_exit(void) 808c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 809c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 810c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 811c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_rphy_class); 812c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 813c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 814c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_AUTHOR("Christoph Hellwig"); 815c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_DESCRIPTION("SAS Transphy Attributes"); 816c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_LICENSE("GPL"); 817c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 818c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_init(sas_transport_init); 819c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_exit(sas_transport_exit); 820