scsi_transport_sas.c revision 6f63caae2172e97e528b58319480217b0b36542e
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> 28f6a570333e554b48ad589e7137c77c57809eee81Al Viro#include <linux/jiffies.h> 29c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <linux/err.h> 308c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/slab.h> 318c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/string.h> 32c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 33e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig#include <scsi/scsi.h> 34c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_device.h> 35c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_host.h> 36c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_transport.h> 37c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_transport_sas.h> 38c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 39d6159c17c2c76963a8067d1e1ac3c4c36c05e674James Bottomley#include "scsi_sas_internal.h" 40c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_host_attrs { 41c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct list_head rphy_list; 42e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig struct mutex lock; 43c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 next_target_id; 4479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley u32 next_expander_id; 45c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley int next_port_id; 46c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 47c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) 48c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 49c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 50c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 51c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Hack to allow attributes of the same name in different objects. 52c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 53c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \ 54c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct class_device_attribute class_device_attr_##_prefix##_##_name = \ 55c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig __ATTR(_name,_mode,_show,_store) 56c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 57c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 58c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 59c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Pretty printing helpers 60c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 61c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 62c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_match(title, table) \ 63c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 64c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf) \ 65c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 66c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *prefix = ""; \ 67c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig ssize_t len = 0; \ 68c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int i; \ 69c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 706391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser for (i = 0; i < ARRAY_SIZE(table); i++) { \ 71c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (table[i].value & table_key) { \ 72c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "%s%s", \ 73c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig prefix, table[i].name); \ 74c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig prefix = ", "; \ 75c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 76c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 77c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "\n"); \ 78c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return len; \ 79c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 80c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 81d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define sas_bitfield_name_set(title, table) \ 82d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleystatic ssize_t \ 83d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleyset_sas_##title##_names(u32 *table_key, const char *buf) \ 84d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley{ \ 85d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley ssize_t len = 0; \ 86d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley int i; \ 87d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley \ 88d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley for (i = 0; i < ARRAY_SIZE(table); i++) { \ 89d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley len = strlen(table[i].name); \ 90d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (strncmp(buf, table[i].name, len) == 0 && \ 91d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley (buf[len] == '\n' || buf[len] == '\0')) { \ 92d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley *table_key = table[i].value; \ 93d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley return 0; \ 94d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley } \ 95d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley } \ 96d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley return -EINVAL; \ 97d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley} 98d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 99c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_search(title, table) \ 100c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 101c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf) \ 102c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 103c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig ssize_t len = 0; \ 104c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int i; \ 105c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 1066391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser for (i = 0; i < ARRAY_SIZE(table); i++) { \ 107c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (table[i].value == table_key) { \ 108c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "%s", \ 109c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig table[i].name); \ 110c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig break; \ 111c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 112c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 113c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "\n"); \ 114c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return len; \ 115c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 116c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 117c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 118c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 119c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 120c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_device_type_names[] = { 121c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PHY_UNUSED, "unused" }, 122c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_END_DEVICE, "end device" }, 123c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_EDGE_EXPANDER_DEVICE, "edge expander" }, 124c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" }, 125c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 126c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(device_type, sas_device_type_names) 127c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 128c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 129c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 130c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 131c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 132c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_protocol_names[] = { 133c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SATA, "sata" }, 134c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SMP, "smp" }, 135c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_STP, "stp" }, 136c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SSP, "ssp" }, 137c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 138c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_match(protocol, sas_protocol_names) 139c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 140c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 141c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 142c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 143c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_linkspeed_names[] = { 144c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_UNKNOWN, "Unknown" }, 145c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PHY_DISABLED, "Phy disabled" }, 146c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_FAILED, "Link Rate failed" }, 147c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_SATA_SPINUP_HOLD, "Spin-up hold" }, 148c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, 149c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, 1507e6dff62dad539cbd608bb3b8b833193d13f00acJames Bottomley { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, 151c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 152c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(linkspeed, sas_linkspeed_names) 153d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_bitfield_name_set(linkspeed, sas_linkspeed_names) 154c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 155c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 156c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS host attributes 157c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 158c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 15937be6eeb4990c05fc7dd683ceaf1501d46ebe9a4James Bottomleystatic int sas_host_setup(struct transport_container *tc, struct device *dev, 16037be6eeb4990c05fc7dd683ceaf1501d46ebe9a4James Bottomley struct class_device *cdev) 161c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 162c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(dev); 163c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 164c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 165c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig INIT_LIST_HEAD(&sas_host->rphy_list); 166e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_init(&sas_host->lock); 167c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_host->next_target_id = 0; 16879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sas_host->next_expander_id = 0; 169c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley sas_host->next_port_id = 0; 170c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 171c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 172c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 173c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_host_class, 174c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig "sas_host", sas_host_setup, NULL, NULL); 175c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 176c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_host_match(struct attribute_container *cont, 177c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev) 178c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 179c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 180c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 181c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 182c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_host_device(dev)) 183c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 184c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev); 185c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 186c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 187c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 188c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 189c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 190c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 191c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 192c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 193c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t.host_attrs.ac == cont; 194c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 195c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 196c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int do_sas_phy_delete(struct device *dev, void *data) 197c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 19865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley int pass = (int)(unsigned long)data; 19965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 20065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (pass == 0 && scsi_is_sas_port(dev)) 20165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete(dev_to_sas_port(dev)); 20265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley else if (pass == 1 && scsi_is_sas_phy(dev)) 203c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_delete(dev_to_phy(dev)); 204c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 205c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 206c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 207c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 20865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_remove_children -- tear down a devices SAS data structures 20965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @dev: device belonging to the sas object 21065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 21165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Removes all SAS PHYs and remote PHYs for a given object 21265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 21365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_remove_children(struct device *dev) 21465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 21565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_for_each_child(dev, (void *)0, do_sas_phy_delete); 21665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_for_each_child(dev, (void *)1, do_sas_phy_delete); 21765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 21865c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_remove_children); 21965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 22065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 221c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_remove_host -- tear down a Scsi_Host's SAS data structures 222c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @shost: Scsi Host that is torn down 223c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 224c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes all SAS PHYs and remote PHYs for a given Scsi_Host. 225c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Must be called just before scsi_remove_host for SAS HBAs. 226c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 227c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_remove_host(struct Scsi_Host *shost) 228c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 22965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_remove_children(&shost->shost_gendev); 230c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 231c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_remove_host); 232c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 233c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 234c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 23565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * SAS Phy attributes 236c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 237c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 238c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_simple(field, name, format_string, cast) \ 239c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 240c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##name(struct class_device *cdev, char *buf) \ 241c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 242c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 243c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 244c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast phy->field); \ 245c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 246c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 247c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_simple_attr(field, name, format_string, type) \ 248c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_simple(field, name, format_string, (type)) \ 249c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 250c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 251c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_protocol(field, name) \ 252c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 253c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##name(struct class_device *cdev, char *buf) \ 254c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 255c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 256c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 257c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy->field) \ 258c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 259c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(phy->field, buf); \ 260c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 261c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 262c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_protocol_attr(field, name) \ 263c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_protocol(field, name) \ 264c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 265c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 266c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_linkspeed(field) \ 267c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 268c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_phy_##field(struct class_device *cdev, char *buf) \ 269c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 270c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 271c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 272c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_linkspeed_names(phy->field, buf); \ 273c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 274c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 275d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley/* Fudge to tell if we're minimum or maximum */ 276d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define sas_phy_store_linkspeed(field) \ 277d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleystatic ssize_t \ 278d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleystore_sas_phy_##field(struct class_device *cdev, const char *buf, \ 279d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley size_t count) \ 280d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley{ \ 281d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley struct sas_phy *phy = transport_class_to_phy(cdev); \ 282d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \ 283d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley struct sas_internal *i = to_sas_internal(shost->transportt); \ 284d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley u32 value; \ 285d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley struct sas_phy_linkrates rates = {0}; \ 286d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley int error; \ 287d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley \ 288d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley error = set_sas_linkspeed_names(&value, buf); \ 289d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (error) \ 290d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley return error; \ 291d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley rates.field = value; \ 292d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley error = i->f->set_phy_speed(phy, &rates); \ 293d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley \ 294d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley return error ? error : count; \ 295d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley} 296d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 297d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define sas_phy_linkspeed_rw_attr(field) \ 298d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley sas_phy_show_linkspeed(field) \ 299d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley sas_phy_store_linkspeed(field) \ 300d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleystatic CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, \ 301d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley store_sas_phy_##field) 302d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 303c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_linkspeed_attr(field) \ 304c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_linkspeed(field) \ 305c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 306c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 307d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 308c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig#define sas_phy_show_linkerror(field) \ 309c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigstatic ssize_t \ 310c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigshow_sas_phy_##field(struct class_device *cdev, char *buf) \ 311c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig{ \ 312c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); \ 313c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \ 314c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); \ 315c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig int error; \ 316c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig \ 317dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0; \ 318c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig if (error) \ 319c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig return error; \ 320c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig return snprintf(buf, 20, "%u\n", phy->field); \ 321c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig} 322c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 323c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig#define sas_phy_linkerror_attr(field) \ 324c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig sas_phy_show_linkerror(field) \ 325c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigstatic CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 326c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 327c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 328c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 329c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_device_type(struct class_device *cdev, char *buf) 330c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 331c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); 332c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 333c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy->identify.device_type) 334c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 335c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names(phy->identify.device_type, buf); 336c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 337c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); 338c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 339acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wongstatic ssize_t do_sas_phy_enable(struct class_device *cdev, 340acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong size_t count, int enable) 341acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong{ 342acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong struct sas_phy *phy = transport_class_to_phy(cdev); 343acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 344acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong struct sas_internal *i = to_sas_internal(shost->transportt); 345acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong int error; 346acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 347acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong error = i->f->phy_enable(phy, enable); 348acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong if (error) 349acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return error; 350acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong phy->enabled = enable; 351acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return count; 352acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong}; 353acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 354acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wongstatic ssize_t store_sas_phy_enable(struct class_device *cdev, 355acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong const char *buf, size_t count) 356acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong{ 357acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong if (count < 1) 358acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return -EINVAL; 359acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 360acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong switch (buf[0]) { 361acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong case '0': 362acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong do_sas_phy_enable(cdev, count, 0); 363acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong break; 364acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong case '1': 365acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong do_sas_phy_enable(cdev, count, 1); 366acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong break; 367acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong default: 368acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return -EINVAL; 369acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong } 370acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 371acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return count; 372acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong} 373acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 374acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wongstatic ssize_t show_sas_phy_enable(struct class_device *cdev, char *buf) 375acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong{ 376acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong struct sas_phy *phy = transport_class_to_phy(cdev); 377acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 378acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return snprintf(buf, 20, "%d", phy->enabled); 379acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong} 380acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 381acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wongstatic CLASS_DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable, 382acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong store_sas_phy_enable); 383acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 38407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic ssize_t do_sas_phy_reset(struct class_device *cdev, 38507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig size_t count, int hard_reset) 38607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 38707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct sas_phy *phy = transport_class_to_phy(cdev); 38807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 38907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 39007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig int error; 39107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 39207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig error = i->f->phy_reset(phy, hard_reset); 39307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig if (error) 39407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return error; 39507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return count; 39607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig}; 39707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 39807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic ssize_t store_sas_link_reset(struct class_device *cdev, 39907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig const char *buf, size_t count) 40007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 40107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return do_sas_phy_reset(cdev, count, 0); 40207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig} 40307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); 40407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 40507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic ssize_t store_sas_hard_reset(struct class_device *cdev, 40607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig const char *buf, size_t count) 40707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 40807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return do_sas_phy_reset(cdev, count, 1); 40907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig} 41007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwigstatic CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); 41107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 412c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.initiator_port_protocols, 413c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 414c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.target_port_protocols, 415c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig target_port_protocols); 416c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 417c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 418c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 419c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int); 420c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(negotiated_linkrate); 421c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(minimum_linkrate_hw); 422d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_phy_linkspeed_rw_attr(minimum_linkrate); 423c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(maximum_linkrate_hw); 424d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_phy_linkspeed_rw_attr(maximum_linkrate); 425c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(invalid_dword_count); 426c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(running_disparity_error_count); 427c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(loss_of_dword_sync_count); 428c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(phy_reset_problem_count); 429c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 430c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 431c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_phy_class, 432c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig "sas_phy", NULL, NULL, NULL); 433c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 434c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_phy_match(struct attribute_container *cont, struct device *dev) 435c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 436c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 437c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 438c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 439c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_phy(dev)) 440c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 441c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent); 442c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 443c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 444c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 445c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 446c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 447c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 448c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 449c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 450c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->phy_attr_cont.ac == cont; 451c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 452c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 453c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void sas_phy_release(struct device *dev) 454c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 455c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = dev_to_phy(dev); 456c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 457c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 458c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(phy); 459c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 460c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 461c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 462c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_alloc -- allocates and initialize a SAS PHY structure 463c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @parent: Parent device 464d99ca4180fe44ae7f409fc73f1a09f270b8d458aMoore, Eric * @number: Phy index 465c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 466c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Allocates an SAS PHY structure. It will be added in the device tree 467c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * below the device specified by @parent, which has to be either a Scsi_Host 468c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * or sas_rphy. 469c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 470c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 471c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS PHY allocated or %NULL if the allocation failed. 472c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 473c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_phy *sas_phy_alloc(struct device *parent, int number) 474c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 475c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent); 476c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy; 477c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 47824669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen phy = kzalloc(sizeof(*phy), GFP_KERNEL); 479c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy) 480c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 481c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 482c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->number = number; 483acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong phy->enabled = 1; 484c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 485c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_initialize(&phy->dev); 486c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.parent = get_device(parent); 487c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.release = sas_phy_release; 48865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley INIT_LIST_HEAD(&phy->port_siblings); 48979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (scsi_is_sas_expander_device(parent)) { 49079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 49165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(phy->dev.bus_id, "phy-%d:%d:%d", shost->host_no, 49279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id, number); 49379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } else 49479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); 495c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 496c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_setup_device(&phy->dev); 497c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 498c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return phy; 499c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 500c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_alloc); 501c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 502c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 503c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_add -- add a SAS PHY to the device hierachy 504c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: The PHY to be added 505c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 506c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS PHY to the rest of the system. 507c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 508c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_phy_add(struct sas_phy *phy) 509c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 510c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 511c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 512c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&phy->dev); 513c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!error) { 514c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&phy->dev); 515c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&phy->dev); 516c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 517c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 518c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 519c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 520c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_add); 521c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 522c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 523c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_free -- free a SAS PHY 524c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to free 525c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 526c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS PHY. 527c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 528c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 529c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a PHY that has not 530c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sucessfully been added using sas_phy_add(). 531c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 532c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_phy_free(struct sas_phy *phy) 533c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 534c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(&phy->dev); 53592aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(&phy->dev); 536c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 537c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_free); 538c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 539c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 540c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_phy_delete -- remove SAS PHY 541c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to remove 542c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 543c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes the specified SAS PHY. If the SAS PHY has an 544c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * associated remote PHY it is removed before. 545c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 546c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 547c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_delete(struct sas_phy *phy) 548c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 549c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &phy->dev; 550c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 55165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* this happens if the phy is still part of a port when deleted */ 55265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&phy->port_siblings)); 553c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 554c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_remove_device(dev); 555c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_del(dev); 556c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(dev); 55792aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 558c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 559c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_delete); 560c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 561c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 562c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * scsi_is_sas_phy -- check if a struct device represents a SAS PHY 563c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 564c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 565c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 566c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS PHY, %0 else 567c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 568c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_phy(const struct device *dev) 569c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 570c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return dev->release == sas_phy_release; 571c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 572c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_phy); 573c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 574c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 57565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * SAS Port attributes 57665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 57765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define sas_port_show_simple(field, name, format_string, cast) \ 57865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic ssize_t \ 57965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyshow_sas_port_##name(struct class_device *cdev, char *buf) \ 58065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ \ 58165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port = transport_class_to_sas_port(cdev); \ 58265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley \ 58365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return snprintf(buf, 20, format_string, cast port->field); \ 58465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 58565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 58665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define sas_port_simple_attr(field, name, format_string, type) \ 58765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_show_simple(field, name, format_string, (type)) \ 58865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL) 58965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 59065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleysas_port_simple_attr(num_phys, num_phys, "%d\n", int); 59165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 59265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_port_class, 59365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley "sas_port", NULL, NULL, NULL); 59465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 59565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic int sas_port_match(struct attribute_container *cont, struct device *dev) 59665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 59765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct Scsi_Host *shost; 59865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_internal *i; 59965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 60065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!scsi_is_sas_port(dev)) 60165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 60265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley shost = dev_to_shost(dev->parent); 60365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 60465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!shost->transportt) 60565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 60665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (shost->transportt->host_attrs.ac.class != 60765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley &sas_host_class.class) 60865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 60965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 61065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i = to_sas_internal(shost->transportt); 61165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return &i->port_attr_cont.ac == cont; 61265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 61365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 61465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 61565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_release(struct device *dev) 61665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 61765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port = dev_to_sas_port(dev); 61865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 61965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&port->phy_list)); 62065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 62165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(dev->parent); 62265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley kfree(port); 62365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 62465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 62565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_create_link(struct sas_port *port, 62665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy) 62765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 62865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, phy->dev.bus_id); 62965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port"); 63065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 63165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 63265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_delete_link(struct sas_port *port, 63365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy) 63465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 63565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_remove_link(&port->dev.kobj, phy->dev.bus_id); 63665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_remove_link(&phy->dev.kobj, "port"); 63765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 63865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 63965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** sas_port_alloc - allocate and initialize a SAS port structure 64065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 64165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @parent: parent device 64265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port_id: port number 64365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 64465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Allocates a SAS port structure. It will be added to the device tree 64565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * below the device specified by @parent which must be either a Scsi_Host 64665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * or a sas_expander_device. 64765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 64865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns %NULL on error 64965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 65065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_port *sas_port_alloc(struct device *parent, int port_id) 65165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 65265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 65365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port; 65465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 65565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port = kzalloc(sizeof(*port), GFP_KERNEL); 65665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!port) 65765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return NULL; 65865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 65965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->port_identifier = port_id; 66065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 66165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_initialize(&port->dev); 66265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 66365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->dev.parent = get_device(parent); 66465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->dev.release = sas_port_release; 66565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 66665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_init(&port->phy_list_mutex); 66765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley INIT_LIST_HEAD(&port->phy_list); 66865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 66965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (scsi_is_sas_expander_device(parent)) { 67065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 67165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(port->dev.bus_id, "port-%d:%d:%d", shost->host_no, 67265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley rphy->scsi_target_id, port->port_identifier); 67365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else 67465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(port->dev.bus_id, "port-%d:%d", shost->host_no, 67565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->port_identifier); 67665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 67765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_setup_device(&port->dev); 67865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 67965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return port; 68065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 68165c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_alloc); 68265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 683c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley/** sas_port_alloc_num - allocate and initialize a SAS port structure 684c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 685c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * @parent: parent device 686c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 687c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Allocates a SAS port structure and a number to go with it. This 688c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * interface is really for adapters where the port number has no 689c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * meansing, so the sas class should manage them. It will be added to 690c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * the device tree below the device specified by @parent which must be 691c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * either a Scsi_Host or a sas_expander_device. 692c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 693c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Returns %NULL on error 694c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley */ 695c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomleystruct sas_port *sas_port_alloc_num(struct device *parent) 696c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley{ 697c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley int index; 698c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 699c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 700c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 701c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley /* FIXME: use idr for this eventually */ 702c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley mutex_lock(&sas_host->lock); 703c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley if (scsi_is_sas_expander_device(parent)) { 704c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 705c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_expander_device *exp = rphy_to_expander_device(rphy); 706c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 707c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley index = exp->next_port_id++; 708c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley } else 709c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley index = sas_host->next_port_id++; 710c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley mutex_unlock(&sas_host->lock); 711c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley return sas_port_alloc(parent, index); 712c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley} 713c9fefeb26457b87f4a767faefcf77321bb90db52James BottomleyEXPORT_SYMBOL(sas_port_alloc_num); 714c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 71565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 71665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add - add a SAS port to the device hierarchy 71765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 71865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to be added 71965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 72065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * publishes a port to the rest of the system 72165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 72265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint sas_port_add(struct sas_port *port) 72365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 72465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley int error; 72565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 72665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* No phys should be added until this is made visible */ 72765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&port->phy_list)); 72865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 72965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = device_add(&port->dev); 73065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 73165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (error) 73265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return error; 73365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 73465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_add_device(&port->dev); 73565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_configure_device(&port->dev); 73665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 73765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 73865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 73965c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add); 74065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 74165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 74265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_free -- free a SAS PORT 74365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: SAS PORT to free 74465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 74565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Frees the specified SAS PORT. 74665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 74765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Note: 74865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This function must only be called on a PORT that has not 74965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sucessfully been added using sas_port_add(). 75065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 75165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_free(struct sas_port *port) 75265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 75365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_destroy_device(&port->dev); 75465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(&port->dev); 75565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 75665c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_free); 75765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 75865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 75965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_delete -- remove SAS PORT 76065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: SAS PORT to remove 76165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 76265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Removes the specified SAS PORT. If the SAS PORT has an 76365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * associated phys, unlink them from the port as well. 76465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 76565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete(struct sas_port *port) 76665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 76765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct device *dev = &port->dev; 76865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy, *tmp_phy; 76965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 77065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (port->rphy) { 77165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_rphy_delete(port->rphy); 77265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->rphy = NULL; 77365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 77465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 77565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 77665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_for_each_entry_safe(phy, tmp_phy, &port->phy_list, 77765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port_siblings) { 77865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete_link(port, phy); 77965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_del_init(&phy->port_siblings); 78065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 78165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 78265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 783a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley if (port->is_backlink) { 784a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley struct device *parent = port->dev.parent; 785a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 786a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley sysfs_remove_link(&port->dev.kobj, parent->bus_id); 787a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley port->is_backlink = 0; 788a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley } 789a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 79065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_remove_device(dev); 79165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_del(dev); 79265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_destroy_device(dev); 79365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(dev); 79465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 79565c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete); 79665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 79765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 79865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * scsi_is_sas_port -- check if a struct device represents a SAS port 79965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @dev: device to check 80065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 80165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns: 80265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * %1 if the device represents a SAS Port, %0 else 80365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 80465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint scsi_is_sas_port(const struct device *dev) 80565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 80665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return dev->release == sas_port_release; 80765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 80865c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(scsi_is_sas_port); 80965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 81065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 81165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add_phy - add another phy to a port to form a wide port 81265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to add the phy to 81365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy: phy to add 81465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 81565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * When a port is initially created, it is empty (has no phys). All 81665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * ports must have at least one phy to operated, and all wide ports 81765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * must have at least two. The current code makes no difference 81865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * between ports and wide ports, but the only object that can be 81965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * connected to a remote device is a port, so ports must be formed on 82065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * all devices with phys if they're connected to anything. 82165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 82265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_add_phy(struct sas_port *port, struct sas_phy *phy) 82365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 82465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 82565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (unlikely(!list_empty(&phy->port_siblings))) { 82665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* make sure we're already on this port */ 82765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *tmp; 82865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 82965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_for_each_entry(tmp, &port->phy_list, port_siblings) 83065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (tmp == phy) 83165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley break; 83265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* If this trips, you added a phy that was already 83365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * part of a different port */ 83465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (unlikely(tmp != phy)) { 83565c92b09acf0218b64f1c7ba4fdabeb8b732c876James 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); 83665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG(); 83765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 83865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else { 83965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_create_link(port, phy); 84065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_add_tail(&phy->port_siblings, &port->phy_list); 84165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->num_phys++; 84265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 84365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 84465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 84565c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add_phy); 84665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 84765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 84865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_delete_phy - remove a phy from a port or wide port 84965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to remove the phy from 85065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy: phy to remove 85165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 85265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This operation is used for tearing down ports again. It must be 85365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * done to every port or wide port before calling sas_port_delete. 85465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 85565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy) 85665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 85765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 85865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete_link(port, phy); 85965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_del_init(&phy->port_siblings); 86065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->num_phys--; 86165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 86265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 86365c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete_phy); 86465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 865a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomleyvoid sas_port_mark_backlink(struct sas_port *port) 866a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley{ 867a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley struct device *parent = port->dev.parent->parent->parent; 868a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 869a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley if (port->is_backlink) 870a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley return; 871a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley port->is_backlink = 1; 872a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley sysfs_create_link(&port->dev.kobj, &parent->kobj, 873a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley parent->bus_id); 874a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 875a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley} 876a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames BottomleyEXPORT_SYMBOL(sas_port_mark_backlink); 877a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 87865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/* 879c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS remote PHY attributes. 880c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 881c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 882c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_simple(field, name, format_string, cast) \ 883c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 884c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_##name(struct class_device *cdev, char *buf) \ 885c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 886c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 887c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 888c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast rphy->field); \ 889c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 890c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 891c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_simple_attr(field, name, format_string, type) \ 892c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_simple(field, name, format_string, (type)) \ 893c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 894c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 895c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 896c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_protocol(field, name) \ 897c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 898c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_##name(struct class_device *cdev, char *buf) \ 899c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 900c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 901c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 902c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->field) \ 903c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 904c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(rphy->field, buf); \ 905c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 906c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 907c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_protocol_attr(field, name) \ 908c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_protocol(field, name) \ 909c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 910c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 911c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 912c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 913c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_device_type(struct class_device *cdev, char *buf) 914c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 915c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 916c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 917c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->identify.device_type) 918c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 919c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names( 920c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->identify.device_type, buf); 921c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 922c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 923c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, 924c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_device_type, NULL); 925c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 926a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 927a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigshow_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf) 928a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 929a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 930a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 931a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 932a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 933a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig u64 identifier; 934a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int error; 935a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 936a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig /* 937a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * Only devices behind an expander are supported, because the 938a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * enclosure identifier is a SMP feature. 939a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig */ 940f4ad7b5807385ad1fed0347d966e51a797cd1013James Bottomley if (scsi_is_sas_phy_local(phy)) 941a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 942a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 943a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig error = i->f->get_enclosure_identifier(rphy, &identifier); 944a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (error) 945a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return error; 946a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); 947a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 948a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 949a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, 950a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_enclosure_identifier, NULL); 951a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 952a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 953a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigshow_sas_rphy_bay_identifier(struct class_device *cdev, char *buf) 954a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 955a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 956a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 957a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 958a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 959a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int val; 960a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 961f4ad7b5807385ad1fed0347d966e51a797cd1013James Bottomley if (scsi_is_sas_phy_local(phy)) 962a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 963a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 964a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig val = i->f->get_bay_identifier(rphy); 965a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (val < 0) 966a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return val; 967a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "%d\n", val); 968a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 969a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 970a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, 971a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_bay_identifier, NULL); 972a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 973c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.initiator_port_protocols, 974c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 975c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); 976c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 977c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 978c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 979c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 98042ab03609cca4ef5079e248296f015650c626899James Bottomley/* only need 8 bytes of data plus header (4 or 8) */ 98142ab03609cca4ef5079e248296f015650c626899James Bottomley#define BUF_SIZE 64 98242ab03609cca4ef5079e248296f015650c626899James Bottomley 98342ab03609cca4ef5079e248296f015650c626899James Bottomleyint sas_read_port_mode_page(struct scsi_device *sdev) 98442ab03609cca4ef5079e248296f015650c626899James Bottomley{ 98542ab03609cca4ef5079e248296f015650c626899James Bottomley char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; 98642ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target); 98742ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev; 98842ab03609cca4ef5079e248296f015650c626899James Bottomley struct scsi_mode_data mode_data; 98942ab03609cca4ef5079e248296f015650c626899James Bottomley int res, error; 99042ab03609cca4ef5079e248296f015650c626899James Bottomley 99142ab03609cca4ef5079e248296f015650c626899James Bottomley BUG_ON(rphy->identify.device_type != SAS_END_DEVICE); 99242ab03609cca4ef5079e248296f015650c626899James Bottomley 99342ab03609cca4ef5079e248296f015650c626899James Bottomley rdev = rphy_to_end_device(rphy); 99442ab03609cca4ef5079e248296f015650c626899James Bottomley 99542ab03609cca4ef5079e248296f015650c626899James Bottomley if (!buffer) 99642ab03609cca4ef5079e248296f015650c626899James Bottomley return -ENOMEM; 99742ab03609cca4ef5079e248296f015650c626899James Bottomley 99842ab03609cca4ef5079e248296f015650c626899James Bottomley res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, 99942ab03609cca4ef5079e248296f015650c626899James Bottomley &mode_data, NULL); 100042ab03609cca4ef5079e248296f015650c626899James Bottomley 100142ab03609cca4ef5079e248296f015650c626899James Bottomley error = -EINVAL; 100242ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_status_is_good(res)) 100342ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 100442ab03609cca4ef5079e248296f015650c626899James Bottomley 100542ab03609cca4ef5079e248296f015650c626899James Bottomley msdata = buffer + mode_data.header_length + 100642ab03609cca4ef5079e248296f015650c626899James Bottomley mode_data.block_descriptor_length; 100742ab03609cca4ef5079e248296f015650c626899James Bottomley 100842ab03609cca4ef5079e248296f015650c626899James Bottomley if (msdata - buffer > BUF_SIZE - 8) 100942ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 101042ab03609cca4ef5079e248296f015650c626899James Bottomley 101142ab03609cca4ef5079e248296f015650c626899James Bottomley error = 0; 101242ab03609cca4ef5079e248296f015650c626899James Bottomley 101342ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0; 101442ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5]; 101542ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7]; 101642ab03609cca4ef5079e248296f015650c626899James Bottomley 101742ab03609cca4ef5079e248296f015650c626899James Bottomley out: 101842ab03609cca4ef5079e248296f015650c626899James Bottomley kfree(buffer); 101942ab03609cca4ef5079e248296f015650c626899James Bottomley return error; 102042ab03609cca4ef5079e248296f015650c626899James Bottomley} 102142ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_read_port_mode_page); 102242ab03609cca4ef5079e248296f015650c626899James Bottomley 102379cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_end_dev_class, 102479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_end_device", NULL, NULL, NULL); 102579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 102642ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_show_simple(field, name, format_string, cast) \ 102742ab03609cca4ef5079e248296f015650c626899James Bottomleystatic ssize_t \ 102842ab03609cca4ef5079e248296f015650c626899James Bottomleyshow_sas_end_dev_##name(struct class_device *cdev, char *buf) \ 102942ab03609cca4ef5079e248296f015650c626899James Bottomley{ \ 103042ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 103142ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev = rphy_to_end_device(rphy); \ 103242ab03609cca4ef5079e248296f015650c626899James Bottomley \ 103342ab03609cca4ef5079e248296f015650c626899James Bottomley return snprintf(buf, 20, format_string, cast rdev->field); \ 103442ab03609cca4ef5079e248296f015650c626899James Bottomley} 103542ab03609cca4ef5079e248296f015650c626899James Bottomley 103642ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_simple_attr(field, name, format_string, type) \ 103742ab03609cca4ef5079e248296f015650c626899James Bottomley sas_end_dev_show_simple(field, name, format_string, (type)) \ 103842ab03609cca4ef5079e248296f015650c626899James Bottomleystatic SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ 103942ab03609cca4ef5079e248296f015650c626899James Bottomley show_sas_end_dev_##name, NULL) 104042ab03609cca4ef5079e248296f015650c626899James Bottomley 104142ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); 104242ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, 104342ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 104442ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, 104542ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 104642ab03609cca4ef5079e248296f015650c626899James Bottomley 104779cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_expander_class, 104879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_expander", NULL, NULL, NULL); 104979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 105079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_show_simple(field, name, format_string, cast) \ 105179cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic ssize_t \ 105279cb1819e231f811211133a09a5382cb89d7ec67James Bottomleyshow_sas_expander_##name(struct class_device *cdev, char *buf) \ 105379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ \ 105479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 105579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ 105679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley \ 105779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return snprintf(buf, 20, format_string, cast edev->field); \ 105879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 105979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 106079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_simple_attr(field, name, format_string, type) \ 106179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sas_expander_show_simple(field, name, format_string, (type)) \ 106279cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, \ 106379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley show_sas_expander_##name, NULL) 106479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 106579cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); 106679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_id, product_id, "%s\n", char *); 106779cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_rev, product_rev, "%s\n", char *); 106879cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_vendor_id, component_vendor_id, 106979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "%s\n", char *); 107079cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int); 107179cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", 107279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley unsigned int); 107379cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(level, level, "%d\n", int); 107442ab03609cca4ef5079e248296f015650c626899James Bottomley 1075c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_rphy_class, 10762f8600dff2b140096a7df781884e918a16aa90e0James Bottomley "sas_device", NULL, NULL, NULL); 1077c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1078c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_rphy_match(struct attribute_container *cont, struct device *dev) 1079c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1080c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 1081c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 1082c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1083c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_rphy(dev)) 1084c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1085c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent->parent); 1086c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1087c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 1088c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1089c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 1090c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 1091c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1092c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1093c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 1094c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->rphy_attr_cont.ac == cont; 1095c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1096c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 109742ab03609cca4ef5079e248296f015650c626899James Bottomleystatic int sas_end_dev_match(struct attribute_container *cont, 109842ab03609cca4ef5079e248296f015650c626899James Bottomley struct device *dev) 109942ab03609cca4ef5079e248296f015650c626899James Bottomley{ 110042ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost; 110142ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_internal *i; 110242ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy; 110342ab03609cca4ef5079e248296f015650c626899James Bottomley 110442ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_is_sas_rphy(dev)) 110542ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 110642ab03609cca4ef5079e248296f015650c626899James Bottomley shost = dev_to_shost(dev->parent->parent); 110742ab03609cca4ef5079e248296f015650c626899James Bottomley rphy = dev_to_rphy(dev); 110842ab03609cca4ef5079e248296f015650c626899James Bottomley 110942ab03609cca4ef5079e248296f015650c626899James Bottomley if (!shost->transportt) 111042ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 111142ab03609cca4ef5079e248296f015650c626899James Bottomley if (shost->transportt->host_attrs.ac.class != 111242ab03609cca4ef5079e248296f015650c626899James Bottomley &sas_host_class.class) 111342ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 111442ab03609cca4ef5079e248296f015650c626899James Bottomley 111542ab03609cca4ef5079e248296f015650c626899James Bottomley i = to_sas_internal(shost->transportt); 111642ab03609cca4ef5079e248296f015650c626899James Bottomley return &i->end_dev_attr_cont.ac == cont && 11172f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_END_DEVICE; 111842ab03609cca4ef5079e248296f015650c626899James Bottomley} 111942ab03609cca4ef5079e248296f015650c626899James Bottomley 112079cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic int sas_expander_match(struct attribute_container *cont, 112179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct device *dev) 112279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 112379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost; 112479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_internal *i; 112579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy; 112679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 112779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!scsi_is_sas_rphy(dev)) 112879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 112979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley shost = dev_to_shost(dev->parent->parent); 113079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy = dev_to_rphy(dev); 113179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 113279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!shost->transportt) 113379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 113479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (shost->transportt->host_attrs.ac.class != 113579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley &sas_host_class.class) 113679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 113779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 113879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i = to_sas_internal(shost->transportt); 113979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &i->expander_attr_cont.ac == cont && 114079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || 11412f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE); 114279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 114379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 11442f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_expander_release(struct device *dev) 1145c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1146c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = dev_to_rphy(dev); 11472f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); 1148c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1149c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 11502f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 1151c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1152c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 11532f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_end_device_release(struct device *dev) 1154c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 11552f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_rphy *rphy = dev_to_rphy(dev); 11562f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_end_device *edev = rphy_to_end_device(rphy); 1157c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 11582f8600dff2b140096a7df781884e918a16aa90e0James Bottomley put_device(dev->parent); 11592f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 1160c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1161c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1162c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1163c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * sas_rphy_initialize - common rphy intialization 1164c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * @rphy: rphy to initialise 1165c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * 1166c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * Used by both sas_end_device_alloc() and sas_expander_alloc() to 1167c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * initialise the common rphy component of each. 1168c5943d36aebb79589ac3983eec418bbeca897573James Bottomley */ 1169c5943d36aebb79589ac3983eec418bbeca897573James Bottomleystatic void sas_rphy_initialize(struct sas_rphy *rphy) 1170c5943d36aebb79589ac3983eec418bbeca897573James Bottomley{ 1171c5943d36aebb79589ac3983eec418bbeca897573James Bottomley INIT_LIST_HEAD(&rphy->list); 1172c5943d36aebb79589ac3983eec418bbeca897573James Bottomley} 1173c5943d36aebb79589ac3983eec418bbeca897573James Bottomley 1174c5943d36aebb79589ac3983eec418bbeca897573James Bottomley/** 117542ab03609cca4ef5079e248296f015650c626899James Bottomley * sas_end_device_alloc - allocate an rphy for an end device 117642ab03609cca4ef5079e248296f015650c626899James Bottomley * 117742ab03609cca4ef5079e248296f015650c626899James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 117842ab03609cca4ef5079e248296f015650c626899James Bottomley * 117942ab03609cca4ef5079e248296f015650c626899James Bottomley * Returns: 118042ab03609cca4ef5079e248296f015650c626899James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 118142ab03609cca4ef5079e248296f015650c626899James Bottomley */ 118265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_end_device_alloc(struct sas_port *parent) 118342ab03609cca4ef5079e248296f015650c626899James Bottomley{ 118442ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 118542ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev; 118642ab03609cca4ef5079e248296f015650c626899James Bottomley 118742ab03609cca4ef5079e248296f015650c626899James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 118842ab03609cca4ef5079e248296f015650c626899James Bottomley if (!rdev) { 118942ab03609cca4ef5079e248296f015650c626899James Bottomley return NULL; 119042ab03609cca4ef5079e248296f015650c626899James Bottomley } 119142ab03609cca4ef5079e248296f015650c626899James Bottomley 119242ab03609cca4ef5079e248296f015650c626899James Bottomley device_initialize(&rdev->rphy.dev); 119342ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 11942f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_end_device_release; 119565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (scsi_is_sas_expander_device(parent->dev.parent)) { 119665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent); 119765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d:%d", 119865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley shost->host_no, rphy->scsi_target_id, parent->port_identifier); 119965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else 120065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d", 120165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley shost->host_no, parent->port_identifier); 120242ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.identify.device_type = SAS_END_DEVICE; 1203c5943d36aebb79589ac3983eec418bbeca897573James Bottomley sas_rphy_initialize(&rdev->rphy); 120442ab03609cca4ef5079e248296f015650c626899James Bottomley transport_setup_device(&rdev->rphy.dev); 120542ab03609cca4ef5079e248296f015650c626899James Bottomley 120642ab03609cca4ef5079e248296f015650c626899James Bottomley return &rdev->rphy; 120742ab03609cca4ef5079e248296f015650c626899James Bottomley} 120842ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_end_device_alloc); 120942ab03609cca4ef5079e248296f015650c626899James Bottomley 121079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley/** 121179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * sas_expander_alloc - allocate an rphy for an end device 121279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 121379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 121479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 121579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Returns: 121679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 121779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley */ 121865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_expander_alloc(struct sas_port *parent, 121979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley enum sas_device_type type) 122079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 122179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 122279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *rdev; 122379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 122479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 122579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE && 122679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley type != SAS_FANOUT_EXPANDER_DEVICE); 122779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 122879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 122979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!rdev) { 123079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return NULL; 123179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } 123279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 123379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley device_initialize(&rdev->rphy.dev); 123479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 12352f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_expander_release; 123679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_lock(&sas_host->lock); 123779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.scsi_target_id = sas_host->next_expander_id++; 123879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_unlock(&sas_host->lock); 123979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", 124079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley shost->host_no, rdev->rphy.scsi_target_id); 124179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.identify.device_type = type; 1242c5943d36aebb79589ac3983eec418bbeca897573James Bottomley sas_rphy_initialize(&rdev->rphy); 124379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_setup_device(&rdev->rphy.dev); 124479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 124579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &rdev->rphy; 124679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 124779cb1819e231f811211133a09a5382cb89d7ec67James BottomleyEXPORT_SYMBOL(sas_expander_alloc); 124842ab03609cca4ef5079e248296f015650c626899James Bottomley 124942ab03609cca4ef5079e248296f015650c626899James Bottomley/** 1250c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_add -- add a SAS remote PHY to the device hierachy 1251c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy: The remote PHY to be added 1252c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1253c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS remote PHY to the rest of the system. 1254c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1255c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_rphy_add(struct sas_rphy *rphy) 1256c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 125765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *parent = dev_to_sas_port(rphy->dev.parent); 1258c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 1259c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1260c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_identify *identify = &rphy->identify; 1261c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1262c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1263c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (parent->rphy) 1264c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return -ENXIO; 1265c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig parent->rphy = rphy; 1266c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1267c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&rphy->dev); 1268c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1269c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1270c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&rphy->dev); 1271c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&rphy->dev); 1272c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1273e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1274c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_add_tail(&rphy->list, &sas_host->rphy_list); 1275c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (identify->device_type == SAS_END_DEVICE && 1276c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (identify->target_port_protocols & 1277c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) 1278c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id = sas_host->next_target_id++; 12797676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley else if (identify->device_type == SAS_END_DEVICE) 12807676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley rphy->scsi_target_id = -1; 1281e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1282c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 128379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (identify->device_type == SAS_END_DEVICE && 128479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id != -1) { 1285e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley scsi_scan_target(&rphy->dev, 0, 1286c8490f3a77805d04321d9e44486a679801a035b8Darrick J. Wong rphy->scsi_target_id, SCAN_WILD_CARD, 0); 1287c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 1288c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1289c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1290c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1291c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_add); 1292c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1293c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1294c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_free -- free a SAS remote PHY 1295c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy SAS remote PHY to free 1296c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1297c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS remote PHY. 1298c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1299c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 1300c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a remote 1301c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * PHY that has not sucessfully been added using 13026f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * sas_rphy_add() (or has been sas_rphy_remove()'d) 1303c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1304c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_rphy_free(struct sas_rphy *rphy) 1305c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 130692aab6464be735139f9ea38fd039c3b84c722630Mike Anderson struct device *dev = &rphy->dev; 1307c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 1308c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1309c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1310e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1311c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_del(&rphy->list); 1312e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1313c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 131492aab6464be735139f9ea38fd039c3b84c722630Mike Anderson transport_destroy_device(dev); 13152f8600dff2b140096a7df781884e918a16aa90e0James Bottomley 131692aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 1317c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1318c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_free); 1319c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1320c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 13216f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * sas_rphy_delete -- remove and free SAS remote PHY 13226f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * @rphy: SAS remote PHY to remove and free 1323c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 13246f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * Removes the specified SAS remote PHY and frees it. 1325c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1326c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 1327c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_delete(struct sas_rphy *rphy) 1328c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 13296f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong sas_rphy_remove(rphy); 13306f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong sas_rphy_free(rphy); 13316f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong} 13326f63caae2172e97e528b58319480217b0b36542eDarrick J. WongEXPORT_SYMBOL(sas_rphy_delete); 13336f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong 13346f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong/** 13356f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * sas_rphy_remove -- remove SAS remote PHY 13366f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * @rphy: SAS remote phy to remove 13376f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * 13386f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * Removes the specified SAS remote PHY. 13396f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong */ 13406f63caae2172e97e528b58319480217b0b36542eDarrick J. Wongvoid 13416f63caae2172e97e528b58319480217b0b36542eDarrick J. Wongsas_rphy_remove(struct sas_rphy *rphy) 13426f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong{ 1343c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &rphy->dev; 134465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *parent = dev_to_sas_port(dev->parent); 1345c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1346d4054239929479907f20b9d68c905589125ad343Christoph Hellwig switch (rphy->identify.device_type) { 1347d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_END_DEVICE: 1348d4054239929479907f20b9d68c905589125ad343Christoph Hellwig scsi_remove_target(dev); 1349d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1350d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_EDGE_EXPANDER_DEVICE: 1351d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_FANOUT_EXPANDER_DEVICE: 135265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_remove_children(dev); 1353d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1354d4054239929479907f20b9d68c905589125ad343Christoph Hellwig default: 1355d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1356d4054239929479907f20b9d68c905589125ad343Christoph Hellwig } 1357c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1358fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig transport_remove_device(dev); 1359fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig device_del(dev); 1360c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 136133b114e935a2202206e224dd2c695cee5a5986bfChristoph Hellwig parent->rphy = NULL; 1362c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 13636f63caae2172e97e528b58319480217b0b36542eDarrick J. WongEXPORT_SYMBOL(sas_rphy_remove); 1364c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1365c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1366c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY 1367c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 1368c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1369c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 1370c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS remote PHY, %0 else 1371c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1372c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_rphy(const struct device *dev) 1373c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 13742f8600dff2b140096a7df781884e918a16aa90e0James Bottomley return dev->release == sas_end_device_release || 13752f8600dff2b140096a7df781884e918a16aa90e0James Bottomley dev->release == sas_expander_release; 1376c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1377c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_rphy); 1378c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1379c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1380c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 1381c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SCSI scan helper 1382c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1383c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1384e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwigstatic int sas_user_scan(struct Scsi_Host *shost, uint channel, 1385e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig uint id, uint lun) 1386c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1387c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1388c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy; 1389c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1390e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1391c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_for_each_entry(rphy, &sas_host->rphy_list, list) { 13926d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley if (rphy->identify.device_type != SAS_END_DEVICE || 13936d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley rphy->scsi_target_id == -1) 1394e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig continue; 1395e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig 1396e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley if ((channel == SCAN_WILD_CARD || channel == 0) && 1397e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { 1398e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley scsi_scan_target(&rphy->dev, 0, 1399e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig rphy->scsi_target_id, lun, 1); 1400e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig } 1401c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 1402e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1403c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1404e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig return 0; 1405c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1406c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1407c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1408c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 1409c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Setup / Teardown code 1410c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1411c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1412d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_TEMPLATE(attrb, field, perm, test) \ 141342ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count] = class_device_attr_##field; \ 141442ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count].attr.mode = perm; \ 141542ab03609cca4ef5079e248296f015650c626899James Bottomley i->attrb[count] = &i->private_##attrb[count]; \ 141642ab03609cca4ef5079e248296f015650c626899James Bottomley if (test) \ 141742ab03609cca4ef5079e248296f015650c626899James Bottomley count++ 141842ab03609cca4ef5079e248296f015650c626899James Bottomley 1419d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm) \ 1420d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count] = class_device_attr_##field; \ 1421d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].attr.mode = perm; \ 1422d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (ro_test) { \ 1423d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].attr.mode = ro_perm; \ 1424d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].store = NULL; \ 1425d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley } \ 1426d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->attrb[count] = &i->private_##attrb[count]; \ 1427d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (test) \ 1428d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley count++ 142942ab03609cca4ef5079e248296f015650c626899James Bottomley 143042ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_RPORT_ATTRIBUTE(field) \ 143142ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) 1432c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1433dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ 143442ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func) 1435dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 143665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE(field) \ 143742ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) 1438c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1439d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_PHY_ATTRIBUTE_RW(field) \ 1440d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ 1441d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley !i->f->set_phy_speed, S_IRUGO) 1442d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 1443acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func) \ 1444acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ 1445acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong !i->f->func, S_IRUGO) 1446acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 144765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PORT_ATTRIBUTE(field) \ 144865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) 144965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 145065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func) \ 145142ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) 1452dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 145365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE_WRONLY(field) \ 1454fe3b5bfe73ace420709f0cfb198b0ffc704bd38bDarrick J. Wong SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1) 145507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 145665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func) \ 1457fe3b5bfe73ace420709f0cfb198b0ffc704bd38bDarrick J. Wong SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func) 1458dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 145942ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_END_DEV_ATTRIBUTE(field) \ 146042ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) 1461c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 146279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define SETUP_EXPANDER_ATTRIBUTE(field) \ 146379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) 146479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1465c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1466c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_attach_transport -- instantiate SAS transport template 1467c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @ft: SAS transport class function template 1468c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1469c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct scsi_transport_template * 1470c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_attach_transport(struct sas_function_template *ft) 1471c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1472c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 1473c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int count; 1474c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 147524669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL); 1476c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!i) 1477c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 1478c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1479e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig i->t.user_scan = sas_user_scan; 1480c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1481c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 1482c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.class = &sas_host_class.class; 1483c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.match = sas_host_match; 1484c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->t.host_attrs); 1485c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_size = sizeof(struct sas_host_attrs); 1486c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1487c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.class = &sas_phy_class.class; 1488c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.attrs = &i->phy_attrs[0]; 1489c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.match = sas_phy_match; 1490c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->phy_attr_cont); 1491c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 149265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.class = &sas_port_class.class; 149365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.attrs = &i->port_attrs[0]; 149465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.match = sas_port_match; 149565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_container_register(&i->port_attr_cont); 149665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 1497c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.class = &sas_rphy_class.class; 1498c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0]; 1499c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.match = sas_rphy_match; 1500c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->rphy_attr_cont); 1501c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 150242ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class; 150342ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0]; 150442ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.match = sas_end_dev_match; 150542ab03609cca4ef5079e248296f015650c626899James Bottomley transport_container_register(&i->end_dev_attr_cont); 150642ab03609cca4ef5079e248296f015650c626899James Bottomley 150779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.class = &sas_expander_class.class; 150879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.attrs = &i->expander_attrs[0]; 150979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.match = sas_expander_match; 151079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_register(&i->expander_attr_cont); 151179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1512c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->f = ft; 1513c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1514c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 151565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PORT_ATTRIBUTE(num_phys); 1516c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->host_attrs[count] = NULL; 1517c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1518c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 151965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(initiator_port_protocols); 152065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(target_port_protocols); 152165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(device_type); 152265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(sas_address); 152365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(phy_identifier); 152465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley //SETUP_PHY_ATTRIBUTE(port_identifier); 152565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(negotiated_linkrate); 152665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw); 1527d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_PHY_ATTRIBUTE_RW(minimum_linkrate); 152865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw); 1529d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_PHY_ATTRIBUTE_RW(maximum_linkrate); 153065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 153165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(invalid_dword_count); 153265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(running_disparity_error_count); 153365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count); 153465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(phy_reset_problem_count); 153565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset); 153665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset); 1537acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable); 1538c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attrs[count] = NULL; 1539c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1540c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 154165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PORT_ATTRIBUTE(num_phys); 154265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attrs[count] = NULL; 154365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 154465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley count = 0; 1545c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols); 1546c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols); 1547c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_device_type); 1548c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_sas_address); 1549c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); 1550dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier, 1551dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_enclosure_identifier); 1552dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier, 1553dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_bay_identifier); 1554c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attrs[count] = NULL; 1555c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 155642ab03609cca4ef5079e248296f015650c626899James Bottomley count = 0; 155742ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); 155842ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); 155942ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); 156042ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attrs[count] = NULL; 156142ab03609cca4ef5079e248296f015650c626899James Bottomley 156279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley count = 0; 156379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(vendor_id); 156479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_id); 156579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_rev); 156679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_vendor_id); 156779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_id); 156879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_revision_id); 156979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(level); 157079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attrs[count] = NULL; 157179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1572c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t; 1573c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1574c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_attach_transport); 1575c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1576c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1577c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_release_transport -- release SAS transport template instance 1578c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @t: transport template instance 1579c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1580c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_release_transport(struct scsi_transport_template *t) 1581c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1582c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i = to_sas_internal(t); 1583c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1584c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->t.host_attrs); 1585c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->phy_attr_cont); 158665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_container_unregister(&i->port_attr_cont); 1587c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->rphy_attr_cont); 1588db82f8410ed7546792358964aa5f8dafff1c70a2James Bottomley transport_container_unregister(&i->end_dev_attr_cont); 158979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_unregister(&i->expander_attr_cont); 1590c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1591c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(i); 1592c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1593c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_release_transport); 1594c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1595c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic __init int sas_transport_init(void) 1596c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1597c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1598c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1599c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_host_class); 1600c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1601c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out; 1602c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_phy_class); 1603c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1604c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_transport; 160565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = transport_class_register(&sas_port_class); 1606c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1607c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_phy; 160865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = transport_class_register(&sas_rphy_class); 160965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (error) 161065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley goto out_unregister_port; 161142ab03609cca4ef5079e248296f015650c626899James Bottomley error = transport_class_register(&sas_end_dev_class); 161242ab03609cca4ef5079e248296f015650c626899James Bottomley if (error) 161342ab03609cca4ef5079e248296f015650c626899James Bottomley goto out_unregister_rphy; 161479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley error = transport_class_register(&sas_expander_class); 161579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (error) 161679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley goto out_unregister_end_dev; 1617c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1618c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1619c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 162079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley out_unregister_end_dev: 162179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_end_dev_class); 162242ab03609cca4ef5079e248296f015650c626899James Bottomley out_unregister_rphy: 162342ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_rphy_class); 162465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley out_unregister_port: 162565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_class_unregister(&sas_port_class); 1626c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_phy: 1627c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 1628c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_transport: 1629c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1630c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out: 1631c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1632c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1633c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1634c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1635c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void __exit sas_transport_exit(void) 1636c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1637c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1638c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 163965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_class_unregister(&sas_port_class); 1640c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_rphy_class); 164142ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_end_dev_class); 164279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_expander_class); 1643c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1644c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1645c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_AUTHOR("Christoph Hellwig"); 164686b9c4c16a1589d05959af2d96d52a4352c6306eAlexis BruemmerMODULE_DESCRIPTION("SAS Transport Attributes"); 1647c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_LICENSE("GPL"); 1648c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1649c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_init(sas_transport_init); 1650c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_exit(sas_transport_exit); 1651