scsi_transport_sas.c revision e8bf39417b578a11e2ee2cd16e794a5b2d40757b
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; 44c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley int next_port_id; 45c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 46c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) 47c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 48c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 49c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 50c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Hack to allow attributes of the same name in different objects. 51c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 52c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \ 53c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct class_device_attribute class_device_attr_##_prefix##_##_name = \ 54c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig __ATTR(_name,_mode,_show,_store) 55c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 56c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 57c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 58c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Pretty printing helpers 59c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 60c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 61c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_match(title, table) \ 62c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 63c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf) \ 64c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 65c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *prefix = ""; \ 66c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig ssize_t len = 0; \ 67c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int i; \ 68c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 696391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser for (i = 0; i < ARRAY_SIZE(table); i++) { \ 70c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (table[i].value & table_key) { \ 71c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "%s%s", \ 72c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig prefix, table[i].name); \ 73c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig prefix = ", "; \ 74c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 75c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 76c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "\n"); \ 77c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return len; \ 78c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 79c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 80c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_search(title, table) \ 81c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 82c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf) \ 83c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 84c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig ssize_t len = 0; \ 85c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int i; \ 86c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 876391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser for (i = 0; i < ARRAY_SIZE(table); i++) { \ 88c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (table[i].value == table_key) { \ 89c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "%s", \ 90c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig table[i].name); \ 91c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig break; \ 92c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 93c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 94c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "\n"); \ 95c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return len; \ 96c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 97c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 98c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 99c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 100c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 101c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_device_type_names[] = { 102c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PHY_UNUSED, "unused" }, 103c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_END_DEVICE, "end device" }, 104c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_EDGE_EXPANDER_DEVICE, "edge expander" }, 105c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" }, 106c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 107c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(device_type, sas_device_type_names) 108c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 109c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 110c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 111c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 112c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 113c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_protocol_names[] = { 114c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SATA, "sata" }, 115c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SMP, "smp" }, 116c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_STP, "stp" }, 117c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SSP, "ssp" }, 118c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 119c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_match(protocol, sas_protocol_names) 120c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 121c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 122c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 123c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 124c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_linkspeed_names[] = { 125c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_UNKNOWN, "Unknown" }, 126c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PHY_DISABLED, "Phy disabled" }, 127c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_FAILED, "Link Rate failed" }, 128c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_SATA_SPINUP_HOLD, "Spin-up hold" }, 129c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, 130c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, 1317e6dff62dad539cbd608bb3b8b833193d13f00acJames Bottomley { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, 132c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 133c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(linkspeed, sas_linkspeed_names) 134c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 135c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 136c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 137c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS host attributes 138c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 139c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 14037be6eeb4990c05fc7dd683ceaf1501d46ebe9a4James Bottomleystatic int sas_host_setup(struct transport_container *tc, struct device *dev, 14137be6eeb4990c05fc7dd683ceaf1501d46ebe9a4James Bottomley struct class_device *cdev) 142c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 143c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(dev); 144c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 145c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 146c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig INIT_LIST_HEAD(&sas_host->rphy_list); 147e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_init(&sas_host->lock); 148c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_host->next_target_id = 0; 14979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sas_host->next_expander_id = 0; 150c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley sas_host->next_port_id = 0; 151c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 152c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 153c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 154c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_host_class, 155c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig "sas_host", sas_host_setup, NULL, NULL); 156c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 157c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_host_match(struct attribute_container *cont, 158c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev) 159c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 160c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 161c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 162c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 163c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_host_device(dev)) 164c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 165c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev); 166c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 167c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 168c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 169c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 170c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 171c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 172c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 173c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 174c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t.host_attrs.ac == cont; 175c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 176c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 177c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int do_sas_phy_delete(struct device *dev, void *data) 178c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 17965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley int pass = (int)(unsigned long)data; 18065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 18165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (pass == 0 && scsi_is_sas_port(dev)) 18265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete(dev_to_sas_port(dev)); 18365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley else if (pass == 1 && scsi_is_sas_phy(dev)) 184c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_delete(dev_to_phy(dev)); 185c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 186c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 187c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 188c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 18965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_remove_children -- tear down a devices SAS data structures 19065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @dev: device belonging to the sas object 19165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 19265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Removes all SAS PHYs and remote PHYs for a given object 19365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 19465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_remove_children(struct device *dev) 19565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 19665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_for_each_child(dev, (void *)0, do_sas_phy_delete); 19765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_for_each_child(dev, (void *)1, do_sas_phy_delete); 19865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 19965c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_remove_children); 20065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 20165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 202c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_remove_host -- tear down a Scsi_Host's SAS data structures 203c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @shost: Scsi Host that is torn down 204c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 205c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes all SAS PHYs and remote PHYs for a given Scsi_Host. 206c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Must be called just before scsi_remove_host for SAS HBAs. 207c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 208c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_remove_host(struct Scsi_Host *shost) 209c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 21065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_remove_children(&shost->shost_gendev); 211c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 212c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_remove_host); 213c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 214c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 215c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 21665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * SAS Phy attributes 217c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 218c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 219c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_simple(field, name, format_string, cast) \ 220c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 221c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##name(struct class_device *cdev, char *buf) \ 222c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 223c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 224c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 225c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast phy->field); \ 226c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 227c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 228c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_simple_attr(field, name, format_string, type) \ 229c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_simple(field, name, format_string, (type)) \ 230c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 231c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 232c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_protocol(field, name) \ 233c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 234c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##name(struct class_device *cdev, char *buf) \ 235c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 236c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 237c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 238c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy->field) \ 239c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 240c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(phy->field, buf); \ 241c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 242c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 243c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_protocol_attr(field, name) \ 244c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_protocol(field, name) \ 245c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 246c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 247c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_linkspeed(field) \ 248c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 249c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##field(struct class_device *cdev, char *buf) \ 250c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 251c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 252c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 253c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_linkspeed_names(phy->field, buf); \ 254c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 255c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 256c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_linkspeed_attr(field) \ 257c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_linkspeed(field) \ 258c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 259c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 260c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig#define sas_phy_show_linkerror(field) \ 261c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigstatic ssize_t \ 262c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigshow_sas_phy_##field(struct class_device *cdev, char *buf) \ 263c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig{ \ 264c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 265c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \ 266c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); \ 267c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig int error; \ 268c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig \ 269ac01bbbd3b7ebfca64357aed12cf476b16abe3ceChristoph Hellwig if (!phy->local_attached) \ 270ac01bbbd3b7ebfca64357aed12cf476b16abe3ceChristoph Hellwig return -EINVAL; \ 271ac01bbbd3b7ebfca64357aed12cf476b16abe3ceChristoph Hellwig \ 272dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0; \ 273c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig if (error) \ 274c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig return error; \ 275c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig return snprintf(buf, 20, "%u\n", phy->field); \ 276c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig} 277c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 278c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig#define sas_phy_linkerror_attr(field) \ 279c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig sas_phy_show_linkerror(field) \ 280c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigstatic CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 281c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 282c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 283c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 284c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_device_type(struct class_device *cdev, char *buf) 285c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 286c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); 287c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 288c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy->identify.device_type) 289c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 290c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names(phy->identify.device_type, buf); 291c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 292c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); 293c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 29407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic ssize_t do_sas_phy_reset(struct class_device *cdev, 29507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig size_t count, int hard_reset) 29607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 29707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); 29807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 29907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 30007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig int error; 30107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 30207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig if (!phy->local_attached) 30307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return -EINVAL; 30407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 30507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig error = i->f->phy_reset(phy, hard_reset); 30607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig if (error) 30707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return error; 30807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return count; 30907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig}; 31007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 31107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic ssize_t store_sas_link_reset(struct class_device *cdev, 31207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig const char *buf, size_t count) 31307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 31407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return do_sas_phy_reset(cdev, count, 0); 31507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig} 31607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); 31707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 31807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic ssize_t store_sas_hard_reset(struct class_device *cdev, 31907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig const char *buf, size_t count) 32007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 32107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return do_sas_phy_reset(cdev, count, 1); 32207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig} 32307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); 32407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 325c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.initiator_port_protocols, 326c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 327c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.target_port_protocols, 328c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig target_port_protocols); 329c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 330c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 331c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 332c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int); 333c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(negotiated_linkrate); 334c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(minimum_linkrate_hw); 335c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(minimum_linkrate); 336c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(maximum_linkrate_hw); 337c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(maximum_linkrate); 338c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(invalid_dword_count); 339c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(running_disparity_error_count); 340c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(loss_of_dword_sync_count); 341c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(phy_reset_problem_count); 342c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 343c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 344c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_phy_class, 345c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig "sas_phy", NULL, NULL, NULL); 346c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 347c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_phy_match(struct attribute_container *cont, struct device *dev) 348c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 349c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 350c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 351c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 352c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_phy(dev)) 353c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 354c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent); 355c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 356c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 357c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 358c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 359c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 360c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 361c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 362c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 363c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->phy_attr_cont.ac == cont; 364c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 365c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 366c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void sas_phy_release(struct device *dev) 367c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 368c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = dev_to_phy(dev); 369c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 370c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 371c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(phy); 372c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 373c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 374c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 375c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_alloc -- allocates and initialize a SAS PHY structure 376c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @parent: Parent device 377d99ca4180fe44ae7f409fc73f1a09f270b8d458aMoore, Eric * @number: Phy index 378c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 379c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Allocates an SAS PHY structure. It will be added in the device tree 380c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * below the device specified by @parent, which has to be either a Scsi_Host 381c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * or sas_rphy. 382c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 383c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 384c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS PHY allocated or %NULL if the allocation failed. 385c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 386c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_phy *sas_phy_alloc(struct device *parent, int number) 387c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 388c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent); 389c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy; 390c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 39124669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen phy = kzalloc(sizeof(*phy), GFP_KERNEL); 392c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy) 393c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 394c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 395c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->number = number; 396c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 397c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_initialize(&phy->dev); 398c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.parent = get_device(parent); 399c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.release = sas_phy_release; 40065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley INIT_LIST_HEAD(&phy->port_siblings); 40179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (scsi_is_sas_expander_device(parent)) { 40279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 40365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(phy->dev.bus_id, "phy-%d:%d:%d", shost->host_no, 40479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id, number); 40579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } else 40679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); 407c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 408c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_setup_device(&phy->dev); 409c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 410c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return phy; 411c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 412c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_alloc); 413c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 414c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 415c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_add -- add a SAS PHY to the device hierachy 416c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: The PHY to be added 417c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 418c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS PHY to the rest of the system. 419c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 420c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_phy_add(struct sas_phy *phy) 421c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 422c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 423c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 424c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&phy->dev); 425c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!error) { 426c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&phy->dev); 427c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&phy->dev); 428c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 429c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 430c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 431c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 432c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_add); 433c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 434c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 435c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_free -- free a SAS PHY 436c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to free 437c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 438c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS PHY. 439c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 440c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 441c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a PHY that has not 442c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sucessfully been added using sas_phy_add(). 443c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 444c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_phy_free(struct sas_phy *phy) 445c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 446c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(&phy->dev); 44792aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(&phy->dev); 448c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 449c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_free); 450c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 451c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 452c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_delete -- remove SAS PHY 453c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to remove 454c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 455c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes the specified SAS PHY. If the SAS PHY has an 456c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * associated remote PHY it is removed before. 457c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 458c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 459c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_delete(struct sas_phy *phy) 460c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 461c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &phy->dev; 462c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 46365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* this happens if the phy is still part of a port when deleted */ 46465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&phy->port_siblings)); 465c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 466c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_remove_device(dev); 467c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_del(dev); 468c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(dev); 46992aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 470c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 471c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_delete); 472c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 473c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 474c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * scsi_is_sas_phy -- check if a struct device represents a SAS PHY 475c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 476c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 477c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 478c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS PHY, %0 else 479c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 480c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_phy(const struct device *dev) 481c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 482c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return dev->release == sas_phy_release; 483c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 484c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_phy); 485c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 486c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 48765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * SAS Port attributes 48865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 48965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define sas_port_show_simple(field, name, format_string, cast) \ 49065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic ssize_t \ 49165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyshow_sas_port_##name(struct class_device *cdev, char *buf) \ 49265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ \ 49365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port = transport_class_to_sas_port(cdev); \ 49465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley \ 49565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return snprintf(buf, 20, format_string, cast port->field); \ 49665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 49765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 49865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define sas_port_simple_attr(field, name, format_string, type) \ 49965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_show_simple(field, name, format_string, (type)) \ 50065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL) 50165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 50265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleysas_port_simple_attr(num_phys, num_phys, "%d\n", int); 50365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 50465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_port_class, 50565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley "sas_port", NULL, NULL, NULL); 50665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 50765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic int sas_port_match(struct attribute_container *cont, struct device *dev) 50865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 50965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct Scsi_Host *shost; 51065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_internal *i; 51165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 51265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!scsi_is_sas_port(dev)) 51365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 51465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley shost = dev_to_shost(dev->parent); 51565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 51665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!shost->transportt) 51765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 51865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (shost->transportt->host_attrs.ac.class != 51965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley &sas_host_class.class) 52065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 52165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 52265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i = to_sas_internal(shost->transportt); 52365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return &i->port_attr_cont.ac == cont; 52465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 52565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 52665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 52765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_release(struct device *dev) 52865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 52965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port = dev_to_sas_port(dev); 53065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 53165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&port->phy_list)); 53265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 53365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(dev->parent); 53465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley kfree(port); 53565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 53665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 53765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_create_link(struct sas_port *port, 53865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy) 53965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 54065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, phy->dev.bus_id); 54165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port"); 54265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 54365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 54465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_delete_link(struct sas_port *port, 54565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy) 54665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 54765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_remove_link(&port->dev.kobj, phy->dev.bus_id); 54865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_remove_link(&phy->dev.kobj, "port"); 54965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 55065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 55165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** sas_port_alloc - allocate and initialize a SAS port structure 55265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 55365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @parent: parent device 55465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port_id: port number 55565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 55665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Allocates a SAS port structure. It will be added to the device tree 55765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * below the device specified by @parent which must be either a Scsi_Host 55865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * or a sas_expander_device. 55965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 56065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns %NULL on error 56165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 56265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_port *sas_port_alloc(struct device *parent, int port_id) 56365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 56465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 56565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port; 56665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 56765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port = kzalloc(sizeof(*port), GFP_KERNEL); 56865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!port) 56965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return NULL; 57065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 57165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->port_identifier = port_id; 57265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 57365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_initialize(&port->dev); 57465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 57565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->dev.parent = get_device(parent); 57665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->dev.release = sas_port_release; 57765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 57865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_init(&port->phy_list_mutex); 57965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley INIT_LIST_HEAD(&port->phy_list); 58065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 58165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (scsi_is_sas_expander_device(parent)) { 58265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 58365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(port->dev.bus_id, "port-%d:%d:%d", shost->host_no, 58465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley rphy->scsi_target_id, port->port_identifier); 58565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else 58665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(port->dev.bus_id, "port-%d:%d", shost->host_no, 58765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->port_identifier); 58865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 58965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_setup_device(&port->dev); 59065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 59165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return port; 59265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 59365c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_alloc); 59465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 595c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley/** sas_port_alloc_num - allocate and initialize a SAS port structure 596c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 597c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * @parent: parent device 598c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 599c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Allocates a SAS port structure and a number to go with it. This 600c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * interface is really for adapters where the port number has no 601c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * meansing, so the sas class should manage them. It will be added to 602c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * the device tree below the device specified by @parent which must be 603c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * either a Scsi_Host or a sas_expander_device. 604c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 605c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Returns %NULL on error 606c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley */ 607c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomleystruct sas_port *sas_port_alloc_num(struct device *parent) 608c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley{ 609c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley int index; 610c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 611c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 612c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 613c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley /* FIXME: use idr for this eventually */ 614c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley mutex_lock(&sas_host->lock); 615c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley if (scsi_is_sas_expander_device(parent)) { 616c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 617c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_expander_device *exp = rphy_to_expander_device(rphy); 618c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 619c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley index = exp->next_port_id++; 620c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley } else 621c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley index = sas_host->next_port_id++; 622c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley mutex_unlock(&sas_host->lock); 623c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley return sas_port_alloc(parent, index); 624c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley} 625c9fefeb26457b87f4a767faefcf77321bb90db52James BottomleyEXPORT_SYMBOL(sas_port_alloc_num); 626c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 62765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 62865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add - add a SAS port to the device hierarchy 62965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 63065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to be added 63165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 63265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * publishes a port to the rest of the system 63365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 63465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint sas_port_add(struct sas_port *port) 63565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 63665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley int error; 63765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 63865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* No phys should be added until this is made visible */ 63965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&port->phy_list)); 64065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 64165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = device_add(&port->dev); 64265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 64365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (error) 64465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return error; 64565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 64665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_add_device(&port->dev); 64765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_configure_device(&port->dev); 64865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 64965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 65065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 65165c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add); 65265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 65365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 65465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_free -- free a SAS PORT 65565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: SAS PORT to free 65665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 65765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Frees the specified SAS PORT. 65865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 65965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Note: 66065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This function must only be called on a PORT that has not 66165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sucessfully been added using sas_port_add(). 66265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 66365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_free(struct sas_port *port) 66465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 66565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_destroy_device(&port->dev); 66665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(&port->dev); 66765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 66865c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_free); 66965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 67065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 67165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_delete -- remove SAS PORT 67265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: SAS PORT to remove 67365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 67465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Removes the specified SAS PORT. If the SAS PORT has an 67565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * associated phys, unlink them from the port as well. 67665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 67765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete(struct sas_port *port) 67865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 67965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct device *dev = &port->dev; 68065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy, *tmp_phy; 68165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 68265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (port->rphy) { 68365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_rphy_delete(port->rphy); 68465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->rphy = NULL; 68565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 68665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 68765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 68865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_for_each_entry_safe(phy, tmp_phy, &port->phy_list, 68965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port_siblings) { 69065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete_link(port, phy); 69165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_del_init(&phy->port_siblings); 69265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 69365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 69465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 695a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley if (port->is_backlink) { 696a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley struct device *parent = port->dev.parent; 697a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 698a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley sysfs_remove_link(&port->dev.kobj, parent->bus_id); 699a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley port->is_backlink = 0; 700a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley } 701a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 70265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_remove_device(dev); 70365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_del(dev); 70465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_destroy_device(dev); 70565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(dev); 70665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 70765c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete); 70865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 70965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 71065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * scsi_is_sas_port -- check if a struct device represents a SAS port 71165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @dev: device to check 71265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 71365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns: 71465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * %1 if the device represents a SAS Port, %0 else 71565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 71665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint scsi_is_sas_port(const struct device *dev) 71765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 71865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return dev->release == sas_port_release; 71965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 72065c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(scsi_is_sas_port); 72165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 72265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 72365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add_phy - add another phy to a port to form a wide port 72465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to add the phy to 72565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy: phy to add 72665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 72765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * When a port is initially created, it is empty (has no phys). All 72865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * ports must have at least one phy to operated, and all wide ports 72965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * must have at least two. The current code makes no difference 73065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * between ports and wide ports, but the only object that can be 73165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * connected to a remote device is a port, so ports must be formed on 73265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * all devices with phys if they're connected to anything. 73365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 73465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_add_phy(struct sas_port *port, struct sas_phy *phy) 73565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 73665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 73765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (unlikely(!list_empty(&phy->port_siblings))) { 73865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* make sure we're already on this port */ 73965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *tmp; 74065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 74165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_for_each_entry(tmp, &port->phy_list, port_siblings) 74265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (tmp == phy) 74365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley break; 74465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* If this trips, you added a phy that was already 74565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * part of a different port */ 74665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (unlikely(tmp != phy)) { 74765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n", phy->dev.bus_id); 74865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG(); 74965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 75065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else { 75165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_create_link(port, phy); 75265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_add_tail(&phy->port_siblings, &port->phy_list); 75365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->num_phys++; 75465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 75565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 75665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 75765c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add_phy); 75865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 75965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 76065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_delete_phy - remove a phy from a port or wide port 76165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to remove the phy from 76265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy: phy to remove 76365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 76465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This operation is used for tearing down ports again. It must be 76565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * done to every port or wide port before calling sas_port_delete. 76665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 76765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy) 76865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 76965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 77065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete_link(port, phy); 77165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_del_init(&phy->port_siblings); 77265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->num_phys--; 77365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 77465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 77565c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete_phy); 77665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 777a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomleyvoid sas_port_mark_backlink(struct sas_port *port) 778a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley{ 779a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley struct device *parent = port->dev.parent->parent->parent; 780a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 781a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley if (port->is_backlink) 782a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley return; 783a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley port->is_backlink = 1; 784a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley sysfs_create_link(&port->dev.kobj, &parent->kobj, 785a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley parent->bus_id); 786a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 787a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley} 788a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames BottomleyEXPORT_SYMBOL(sas_port_mark_backlink); 789a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 79065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/* 791c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS remote PHY attributes. 792c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 793c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 794c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_simple(field, name, format_string, cast) \ 795c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 796c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_##name(struct class_device *cdev, char *buf) \ 797c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 798c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 799c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 800c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast rphy->field); \ 801c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 802c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 803c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_simple_attr(field, name, format_string, type) \ 804c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_simple(field, name, format_string, (type)) \ 805c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 806c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 807c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 808c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_protocol(field, name) \ 809c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 810c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_##name(struct class_device *cdev, char *buf) \ 811c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 812c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 813c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 814c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->field) \ 815c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 816c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(rphy->field, buf); \ 817c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 818c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 819c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_protocol_attr(field, name) \ 820c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_protocol(field, name) \ 821c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 822c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 823c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 824c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 825c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_device_type(struct class_device *cdev, char *buf) 826c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 827c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 828c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 829c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->identify.device_type) 830c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 831c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names( 832c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->identify.device_type, buf); 833c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 834c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 835c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, 836c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_device_type, NULL); 837c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 838a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 839a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigshow_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf) 840a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 841a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 842a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 843a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 844a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 845a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig u64 identifier; 846a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int error; 847a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 848a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig /* 849a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * Only devices behind an expander are supported, because the 850a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * enclosure identifier is a SMP feature. 851a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig */ 852a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (phy->local_attached) 853a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 854a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 855a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig error = i->f->get_enclosure_identifier(rphy, &identifier); 856a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (error) 857a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return error; 858a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); 859a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 860a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 861a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, 862a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_enclosure_identifier, NULL); 863a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 864a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 865a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigshow_sas_rphy_bay_identifier(struct class_device *cdev, char *buf) 866a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 867a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 868a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 869a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 870a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 871a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int val; 872a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 873a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (phy->local_attached) 874a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 875a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 876a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig val = i->f->get_bay_identifier(rphy); 877a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (val < 0) 878a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return val; 879a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "%d\n", val); 880a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 881a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 882a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, 883a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_bay_identifier, NULL); 884a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 885c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.initiator_port_protocols, 886c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 887c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); 888c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 889c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 890c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 891c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 89242ab03609cca4ef5079e248296f015650c626899James Bottomley/* only need 8 bytes of data plus header (4 or 8) */ 89342ab03609cca4ef5079e248296f015650c626899James Bottomley#define BUF_SIZE 64 89442ab03609cca4ef5079e248296f015650c626899James Bottomley 89542ab03609cca4ef5079e248296f015650c626899James Bottomleyint sas_read_port_mode_page(struct scsi_device *sdev) 89642ab03609cca4ef5079e248296f015650c626899James Bottomley{ 89742ab03609cca4ef5079e248296f015650c626899James Bottomley char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; 89842ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target); 89942ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev; 90042ab03609cca4ef5079e248296f015650c626899James Bottomley struct scsi_mode_data mode_data; 90142ab03609cca4ef5079e248296f015650c626899James Bottomley int res, error; 90242ab03609cca4ef5079e248296f015650c626899James Bottomley 90342ab03609cca4ef5079e248296f015650c626899James Bottomley BUG_ON(rphy->identify.device_type != SAS_END_DEVICE); 90442ab03609cca4ef5079e248296f015650c626899James Bottomley 90542ab03609cca4ef5079e248296f015650c626899James Bottomley rdev = rphy_to_end_device(rphy); 90642ab03609cca4ef5079e248296f015650c626899James Bottomley 90742ab03609cca4ef5079e248296f015650c626899James Bottomley if (!buffer) 90842ab03609cca4ef5079e248296f015650c626899James Bottomley return -ENOMEM; 90942ab03609cca4ef5079e248296f015650c626899James Bottomley 91042ab03609cca4ef5079e248296f015650c626899James Bottomley res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, 91142ab03609cca4ef5079e248296f015650c626899James Bottomley &mode_data, NULL); 91242ab03609cca4ef5079e248296f015650c626899James Bottomley 91342ab03609cca4ef5079e248296f015650c626899James Bottomley error = -EINVAL; 91442ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_status_is_good(res)) 91542ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 91642ab03609cca4ef5079e248296f015650c626899James Bottomley 91742ab03609cca4ef5079e248296f015650c626899James Bottomley msdata = buffer + mode_data.header_length + 91842ab03609cca4ef5079e248296f015650c626899James Bottomley mode_data.block_descriptor_length; 91942ab03609cca4ef5079e248296f015650c626899James Bottomley 92042ab03609cca4ef5079e248296f015650c626899James Bottomley if (msdata - buffer > BUF_SIZE - 8) 92142ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 92242ab03609cca4ef5079e248296f015650c626899James Bottomley 92342ab03609cca4ef5079e248296f015650c626899James Bottomley error = 0; 92442ab03609cca4ef5079e248296f015650c626899James Bottomley 92542ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0; 92642ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5]; 92742ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7]; 92842ab03609cca4ef5079e248296f015650c626899James Bottomley 92942ab03609cca4ef5079e248296f015650c626899James Bottomley out: 93042ab03609cca4ef5079e248296f015650c626899James Bottomley kfree(buffer); 93142ab03609cca4ef5079e248296f015650c626899James Bottomley return error; 93242ab03609cca4ef5079e248296f015650c626899James Bottomley} 93342ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_read_port_mode_page); 93442ab03609cca4ef5079e248296f015650c626899James Bottomley 93579cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_end_dev_class, 93679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_end_device", NULL, NULL, NULL); 93779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 93842ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_show_simple(field, name, format_string, cast) \ 93942ab03609cca4ef5079e248296f015650c626899James Bottomleystatic ssize_t \ 94042ab03609cca4ef5079e248296f015650c626899James Bottomleyshow_sas_end_dev_##name(struct class_device *cdev, char *buf) \ 94142ab03609cca4ef5079e248296f015650c626899James Bottomley{ \ 94242ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 94342ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev = rphy_to_end_device(rphy); \ 94442ab03609cca4ef5079e248296f015650c626899James Bottomley \ 94542ab03609cca4ef5079e248296f015650c626899James Bottomley return snprintf(buf, 20, format_string, cast rdev->field); \ 94642ab03609cca4ef5079e248296f015650c626899James Bottomley} 94742ab03609cca4ef5079e248296f015650c626899James Bottomley 94842ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_simple_attr(field, name, format_string, type) \ 94942ab03609cca4ef5079e248296f015650c626899James Bottomley sas_end_dev_show_simple(field, name, format_string, (type)) \ 95042ab03609cca4ef5079e248296f015650c626899James Bottomleystatic SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ 95142ab03609cca4ef5079e248296f015650c626899James Bottomley show_sas_end_dev_##name, NULL) 95242ab03609cca4ef5079e248296f015650c626899James Bottomley 95342ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); 95442ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, 95542ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 95642ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, 95742ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 95842ab03609cca4ef5079e248296f015650c626899James Bottomley 95979cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_expander_class, 96079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_expander", NULL, NULL, NULL); 96179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 96279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_show_simple(field, name, format_string, cast) \ 96379cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic ssize_t \ 96479cb1819e231f811211133a09a5382cb89d7ec67James Bottomleyshow_sas_expander_##name(struct class_device *cdev, char *buf) \ 96579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ \ 96679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 96779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ 96879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley \ 96979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return snprintf(buf, 20, format_string, cast edev->field); \ 97079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 97179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 97279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_simple_attr(field, name, format_string, type) \ 97379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sas_expander_show_simple(field, name, format_string, (type)) \ 97479cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, \ 97579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley show_sas_expander_##name, NULL) 97679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 97779cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); 97879cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_id, product_id, "%s\n", char *); 97979cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_rev, product_rev, "%s\n", char *); 98079cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_vendor_id, component_vendor_id, 98179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "%s\n", char *); 98279cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int); 98379cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", 98479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley unsigned int); 98579cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(level, level, "%d\n", int); 98642ab03609cca4ef5079e248296f015650c626899James Bottomley 987c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_rphy_class, 9882f8600dff2b140096a7df781884e918a16aa90e0James Bottomley "sas_device", NULL, NULL, NULL); 989c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 990c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_rphy_match(struct attribute_container *cont, struct device *dev) 991c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 992c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 993c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 994c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 995c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_rphy(dev)) 996c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 997c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent->parent); 998c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 999c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 1000c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1001c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 1002c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 1003c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1004c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1005c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 1006c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->rphy_attr_cont.ac == cont; 1007c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1008c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 100942ab03609cca4ef5079e248296f015650c626899James Bottomleystatic int sas_end_dev_match(struct attribute_container *cont, 101042ab03609cca4ef5079e248296f015650c626899James Bottomley struct device *dev) 101142ab03609cca4ef5079e248296f015650c626899James Bottomley{ 101242ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost; 101342ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_internal *i; 101442ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy; 101542ab03609cca4ef5079e248296f015650c626899James Bottomley 101642ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_is_sas_rphy(dev)) 101742ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 101842ab03609cca4ef5079e248296f015650c626899James Bottomley shost = dev_to_shost(dev->parent->parent); 101942ab03609cca4ef5079e248296f015650c626899James Bottomley rphy = dev_to_rphy(dev); 102042ab03609cca4ef5079e248296f015650c626899James Bottomley 102142ab03609cca4ef5079e248296f015650c626899James Bottomley if (!shost->transportt) 102242ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 102342ab03609cca4ef5079e248296f015650c626899James Bottomley if (shost->transportt->host_attrs.ac.class != 102442ab03609cca4ef5079e248296f015650c626899James Bottomley &sas_host_class.class) 102542ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 102642ab03609cca4ef5079e248296f015650c626899James Bottomley 102742ab03609cca4ef5079e248296f015650c626899James Bottomley i = to_sas_internal(shost->transportt); 102842ab03609cca4ef5079e248296f015650c626899James Bottomley return &i->end_dev_attr_cont.ac == cont && 10292f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_END_DEVICE; 103042ab03609cca4ef5079e248296f015650c626899James Bottomley} 103142ab03609cca4ef5079e248296f015650c626899James Bottomley 103279cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic int sas_expander_match(struct attribute_container *cont, 103379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct device *dev) 103479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 103579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost; 103679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_internal *i; 103779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy; 103879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 103979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!scsi_is_sas_rphy(dev)) 104079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 104179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley shost = dev_to_shost(dev->parent->parent); 104279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy = dev_to_rphy(dev); 104379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 104479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!shost->transportt) 104579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 104679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (shost->transportt->host_attrs.ac.class != 104779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley &sas_host_class.class) 104879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 104979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 105079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i = to_sas_internal(shost->transportt); 105179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &i->expander_attr_cont.ac == cont && 105279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || 10532f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE); 105479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 105579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 10562f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_expander_release(struct device *dev) 1057c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1058c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = dev_to_rphy(dev); 10592f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); 1060c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1061c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 10622f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 1063c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1064c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 10652f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_end_device_release(struct device *dev) 1066c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 10672f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_rphy *rphy = dev_to_rphy(dev); 10682f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_end_device *edev = rphy_to_end_device(rphy); 1069c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 10702f8600dff2b140096a7df781884e918a16aa90e0James Bottomley put_device(dev->parent); 10712f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 1072c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1073c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1074c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1075c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * sas_rphy_initialize - common rphy intialization 1076c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * @rphy: rphy to initialise 1077c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * 1078c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * Used by both sas_end_device_alloc() and sas_expander_alloc() to 1079c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * initialise the common rphy component of each. 1080c5943d36aebb79589ac3983eec418bbeca897573James Bottomley */ 1081c5943d36aebb79589ac3983eec418bbeca897573James Bottomleystatic void sas_rphy_initialize(struct sas_rphy *rphy) 1082c5943d36aebb79589ac3983eec418bbeca897573James Bottomley{ 1083c5943d36aebb79589ac3983eec418bbeca897573James Bottomley INIT_LIST_HEAD(&rphy->list); 1084c5943d36aebb79589ac3983eec418bbeca897573James Bottomley} 1085c5943d36aebb79589ac3983eec418bbeca897573James Bottomley 1086c5943d36aebb79589ac3983eec418bbeca897573James Bottomley/** 108742ab03609cca4ef5079e248296f015650c626899James Bottomley * sas_end_device_alloc - allocate an rphy for an end device 108842ab03609cca4ef5079e248296f015650c626899James Bottomley * 108942ab03609cca4ef5079e248296f015650c626899James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 109042ab03609cca4ef5079e248296f015650c626899James Bottomley * 109142ab03609cca4ef5079e248296f015650c626899James Bottomley * Returns: 109242ab03609cca4ef5079e248296f015650c626899James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 109342ab03609cca4ef5079e248296f015650c626899James Bottomley */ 109465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_end_device_alloc(struct sas_port *parent) 109542ab03609cca4ef5079e248296f015650c626899James Bottomley{ 109642ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 109742ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev; 109842ab03609cca4ef5079e248296f015650c626899James Bottomley 109942ab03609cca4ef5079e248296f015650c626899James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 110042ab03609cca4ef5079e248296f015650c626899James Bottomley if (!rdev) { 110142ab03609cca4ef5079e248296f015650c626899James Bottomley return NULL; 110242ab03609cca4ef5079e248296f015650c626899James Bottomley } 110342ab03609cca4ef5079e248296f015650c626899James Bottomley 110442ab03609cca4ef5079e248296f015650c626899James Bottomley device_initialize(&rdev->rphy.dev); 110542ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 11062f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_end_device_release; 110765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (scsi_is_sas_expander_device(parent->dev.parent)) { 110865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent); 110965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d:%d", 111065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley shost->host_no, rphy->scsi_target_id, parent->port_identifier); 111165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else 111265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d", 111365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley shost->host_no, parent->port_identifier); 111442ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.identify.device_type = SAS_END_DEVICE; 1115c5943d36aebb79589ac3983eec418bbeca897573James Bottomley sas_rphy_initialize(&rdev->rphy); 111642ab03609cca4ef5079e248296f015650c626899James Bottomley transport_setup_device(&rdev->rphy.dev); 111742ab03609cca4ef5079e248296f015650c626899James Bottomley 111842ab03609cca4ef5079e248296f015650c626899James Bottomley return &rdev->rphy; 111942ab03609cca4ef5079e248296f015650c626899James Bottomley} 112042ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_end_device_alloc); 112142ab03609cca4ef5079e248296f015650c626899James Bottomley 112279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley/** 112379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * sas_expander_alloc - allocate an rphy for an end device 112479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 112579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 112679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 112779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Returns: 112879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 112979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley */ 113065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_expander_alloc(struct sas_port *parent, 113179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley enum sas_device_type type) 113279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 113379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 113479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *rdev; 113579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 113679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 113779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE && 113879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley type != SAS_FANOUT_EXPANDER_DEVICE); 113979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 114079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 114179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!rdev) { 114279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return NULL; 114379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } 114479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 114579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley device_initialize(&rdev->rphy.dev); 114679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 11472f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_expander_release; 114879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_lock(&sas_host->lock); 114979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.scsi_target_id = sas_host->next_expander_id++; 115079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_unlock(&sas_host->lock); 115179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", 115279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley shost->host_no, rdev->rphy.scsi_target_id); 115379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.identify.device_type = type; 1154c5943d36aebb79589ac3983eec418bbeca897573James Bottomley sas_rphy_initialize(&rdev->rphy); 115579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_setup_device(&rdev->rphy.dev); 115679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 115779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &rdev->rphy; 115879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 115979cb1819e231f811211133a09a5382cb89d7ec67James BottomleyEXPORT_SYMBOL(sas_expander_alloc); 116042ab03609cca4ef5079e248296f015650c626899James Bottomley 116142ab03609cca4ef5079e248296f015650c626899James Bottomley/** 1162c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_add -- add a SAS remote PHY to the device hierachy 1163c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy: The remote PHY to be added 1164c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1165c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS remote PHY to the rest of the system. 1166c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1167c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_rphy_add(struct sas_rphy *rphy) 1168c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 116965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *parent = dev_to_sas_port(rphy->dev.parent); 1170c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 1171c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1172c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_identify *identify = &rphy->identify; 1173c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1174c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1175c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (parent->rphy) 1176c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return -ENXIO; 1177c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig parent->rphy = rphy; 1178c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1179c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&rphy->dev); 1180c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1181c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1182c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&rphy->dev); 1183c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&rphy->dev); 1184c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1185e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1186c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_add_tail(&rphy->list, &sas_host->rphy_list); 1187c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (identify->device_type == SAS_END_DEVICE && 1188c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (identify->target_port_protocols & 1189c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) 1190c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id = sas_host->next_target_id++; 11917676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley else if (identify->device_type == SAS_END_DEVICE) 11927676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley rphy->scsi_target_id = -1; 1193e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1194c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 119579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (identify->device_type == SAS_END_DEVICE && 119679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id != -1) { 1197e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley scsi_scan_target(&rphy->dev, 0, 1198c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id, ~0, 0); 1199c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 1200c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1201c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1202c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1203c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_add); 1204c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1205c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1206c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_free -- free a SAS remote PHY 1207c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy SAS remote PHY to free 1208c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1209c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS remote PHY. 1210c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1211c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 1212c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a remote 1213c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * PHY that has not sucessfully been added using 1214c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_add(). 1215c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1216c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_rphy_free(struct sas_rphy *rphy) 1217c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 121892aab6464be735139f9ea38fd039c3b84c722630Mike Anderson struct device *dev = &rphy->dev; 1219c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 1220c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1221c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1222e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1223c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_del(&rphy->list); 1224e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1225c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 122692aab6464be735139f9ea38fd039c3b84c722630Mike Anderson transport_destroy_device(dev); 12272f8600dff2b140096a7df781884e918a16aa90e0James Bottomley 122892aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 1229c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1230c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_free); 1231c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1232c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1233c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_delete -- remove SAS remote PHY 1234c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy: SAS remote PHY to remove 1235c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1236c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes the specified SAS remote PHY. 1237c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1238c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 1239c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_delete(struct sas_rphy *rphy) 1240c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1241c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &rphy->dev; 124265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *parent = dev_to_sas_port(dev->parent); 1243c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 1244c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1245c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1246d4054239929479907f20b9d68c905589125ad343Christoph Hellwig switch (rphy->identify.device_type) { 1247d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_END_DEVICE: 1248d4054239929479907f20b9d68c905589125ad343Christoph Hellwig scsi_remove_target(dev); 1249d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1250d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_EDGE_EXPANDER_DEVICE: 1251d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_FANOUT_EXPANDER_DEVICE: 125265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_remove_children(dev); 1253d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1254d4054239929479907f20b9d68c905589125ad343Christoph Hellwig default: 1255d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1256d4054239929479907f20b9d68c905589125ad343Christoph Hellwig } 1257c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1258fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig transport_remove_device(dev); 1259fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig device_del(dev); 1260fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig transport_destroy_device(dev); 1261c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1262e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1263c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_del(&rphy->list); 1264e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1265c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 126633b114e935a2202206e224dd2c695cee5a5986bfChristoph Hellwig parent->rphy = NULL; 126733b114e935a2202206e224dd2c695cee5a5986bfChristoph Hellwig 126892aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 1269c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1270c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_delete); 1271c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1272c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1273c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY 1274c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 1275c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1276c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 1277c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS remote PHY, %0 else 1278c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1279c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_rphy(const struct device *dev) 1280c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 12812f8600dff2b140096a7df781884e918a16aa90e0James Bottomley return dev->release == sas_end_device_release || 12822f8600dff2b140096a7df781884e918a16aa90e0James Bottomley dev->release == sas_expander_release; 1283c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1284c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_rphy); 1285c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1286c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1287c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 1288c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SCSI scan helper 1289c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1290c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1291e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwigstatic int sas_user_scan(struct Scsi_Host *shost, uint channel, 1292e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig uint id, uint lun) 1293c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1294c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1295c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy; 1296c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1297e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1298c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_for_each_entry(rphy, &sas_host->rphy_list, list) { 12996d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley if (rphy->identify.device_type != SAS_END_DEVICE || 13006d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley rphy->scsi_target_id == -1) 1301e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig continue; 1302e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig 1303e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley if ((channel == SCAN_WILD_CARD || channel == 0) && 1304e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { 1305e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley scsi_scan_target(&rphy->dev, 0, 1306e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig rphy->scsi_target_id, lun, 1); 1307e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig } 1308c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 1309e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1310c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1311e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig return 0; 1312c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1313c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1314c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1315c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 1316c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Setup / Teardown code 1317c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1318c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 131942ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_TEMPLATE(attrb, field, perm, test) \ 132042ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count] = class_device_attr_##field; \ 132142ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count].attr.mode = perm; \ 132242ab03609cca4ef5079e248296f015650c626899James Bottomley i->attrb[count] = &i->private_##attrb[count]; \ 132342ab03609cca4ef5079e248296f015650c626899James Bottomley if (test) \ 132442ab03609cca4ef5079e248296f015650c626899James Bottomley count++ 132542ab03609cca4ef5079e248296f015650c626899James Bottomley 132642ab03609cca4ef5079e248296f015650c626899James Bottomley 132742ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_RPORT_ATTRIBUTE(field) \ 132842ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) 1329c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1330dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ 133142ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func) 1332dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 133365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE(field) \ 133442ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) 1335c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 133665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PORT_ATTRIBUTE(field) \ 133765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) 133865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 133965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func) \ 134042ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) 1341dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 134265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE_WRONLY(field) \ 134342ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1) 134407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 134565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func) \ 134642ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func) 1347dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 134842ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_END_DEV_ATTRIBUTE(field) \ 134942ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) 1350c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 135179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define SETUP_EXPANDER_ATTRIBUTE(field) \ 135279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) 135379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1354c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1355c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_attach_transport -- instantiate SAS transport template 1356c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @ft: SAS transport class function template 1357c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1358c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct scsi_transport_template * 1359c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_attach_transport(struct sas_function_template *ft) 1360c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1361c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 1362c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int count; 1363c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 136424669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL); 1365c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!i) 1366c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 1367c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1368e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig i->t.user_scan = sas_user_scan; 1369c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1370c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 1371c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.class = &sas_host_class.class; 1372c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.match = sas_host_match; 1373c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->t.host_attrs); 1374c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_size = sizeof(struct sas_host_attrs); 1375c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1376c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.class = &sas_phy_class.class; 1377c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.attrs = &i->phy_attrs[0]; 1378c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.match = sas_phy_match; 1379c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->phy_attr_cont); 1380c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 138165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.class = &sas_port_class.class; 138265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.attrs = &i->port_attrs[0]; 138365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.match = sas_port_match; 138465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_container_register(&i->port_attr_cont); 138565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 1386c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.class = &sas_rphy_class.class; 1387c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0]; 1388c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.match = sas_rphy_match; 1389c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->rphy_attr_cont); 1390c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 139142ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class; 139242ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0]; 139342ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.match = sas_end_dev_match; 139442ab03609cca4ef5079e248296f015650c626899James Bottomley transport_container_register(&i->end_dev_attr_cont); 139542ab03609cca4ef5079e248296f015650c626899James Bottomley 139679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.class = &sas_expander_class.class; 139779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.attrs = &i->expander_attrs[0]; 139879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.match = sas_expander_match; 139979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_register(&i->expander_attr_cont); 140079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1401c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->f = ft; 1402c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1403c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 140465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PORT_ATTRIBUTE(num_phys); 1405c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->host_attrs[count] = NULL; 1406c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1407c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 140865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(initiator_port_protocols); 140965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(target_port_protocols); 141065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(device_type); 141165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(sas_address); 141265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(phy_identifier); 141365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley //SETUP_PHY_ATTRIBUTE(port_identifier); 141465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(negotiated_linkrate); 141565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw); 141665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(minimum_linkrate); 141765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw); 141865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(maximum_linkrate); 141965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 142065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(invalid_dword_count); 142165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(running_disparity_error_count); 142265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count); 142365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(phy_reset_problem_count); 142465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset); 142565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset); 1426c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attrs[count] = NULL; 1427c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1428c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 142965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PORT_ATTRIBUTE(num_phys); 143065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attrs[count] = NULL; 143165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 143265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley count = 0; 1433c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols); 1434c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols); 1435c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_device_type); 1436c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_sas_address); 1437c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); 1438dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier, 1439dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_enclosure_identifier); 1440dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier, 1441dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_bay_identifier); 1442c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attrs[count] = NULL; 1443c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 144442ab03609cca4ef5079e248296f015650c626899James Bottomley count = 0; 144542ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); 144642ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); 144742ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); 144842ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attrs[count] = NULL; 144942ab03609cca4ef5079e248296f015650c626899James Bottomley 145079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley count = 0; 145179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(vendor_id); 145279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_id); 145379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_rev); 145479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_vendor_id); 145579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_id); 145679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_revision_id); 145779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(level); 145879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attrs[count] = NULL; 145979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1460c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t; 1461c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1462c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_attach_transport); 1463c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1464c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1465c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_release_transport -- release SAS transport template instance 1466c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @t: transport template instance 1467c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1468c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_release_transport(struct scsi_transport_template *t) 1469c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1470c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i = to_sas_internal(t); 1471c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1472c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->t.host_attrs); 1473c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->phy_attr_cont); 147465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_container_unregister(&i->port_attr_cont); 1475c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->rphy_attr_cont); 1476db82f8410ed7546792358964aa5f8dafff1c70a2James Bottomley transport_container_unregister(&i->end_dev_attr_cont); 147779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_unregister(&i->expander_attr_cont); 1478c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1479c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(i); 1480c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1481c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_release_transport); 1482c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1483c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic __init int sas_transport_init(void) 1484c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1485c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1486c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1487c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_host_class); 1488c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1489c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out; 1490c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_phy_class); 1491c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1492c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_transport; 149365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = transport_class_register(&sas_port_class); 1494c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1495c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_phy; 149665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = transport_class_register(&sas_rphy_class); 149765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (error) 149865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley goto out_unregister_port; 149942ab03609cca4ef5079e248296f015650c626899James Bottomley error = transport_class_register(&sas_end_dev_class); 150042ab03609cca4ef5079e248296f015650c626899James Bottomley if (error) 150142ab03609cca4ef5079e248296f015650c626899James Bottomley goto out_unregister_rphy; 150279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley error = transport_class_register(&sas_expander_class); 150379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (error) 150479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley goto out_unregister_end_dev; 1505c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1506c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1507c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 150879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley out_unregister_end_dev: 150979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_end_dev_class); 151042ab03609cca4ef5079e248296f015650c626899James Bottomley out_unregister_rphy: 151142ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_rphy_class); 151265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley out_unregister_port: 151365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_class_unregister(&sas_port_class); 1514c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_phy: 1515c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 1516c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_transport: 1517c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1518c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out: 1519c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1520c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1521c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1522c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1523c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void __exit sas_transport_exit(void) 1524c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1525c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1526c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 152765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_class_unregister(&sas_port_class); 1528c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_rphy_class); 152942ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_end_dev_class); 153079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_expander_class); 1531c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1532c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1533c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_AUTHOR("Christoph Hellwig"); 1534c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_DESCRIPTION("SAS Transphy Attributes"); 1535c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_LICENSE("GPL"); 1536c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1537c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_init(sas_transport_init); 1538c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_exit(sas_transport_exit); 1539