scsi_transport_sas.c revision 21434966462d57145c861b43f6206d945ac57630
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{ 62821434966462d57145c861b43f6206d945ac57630Darrick J. Wong int res; 62921434966462d57145c861b43f6206d945ac57630Darrick J. Wong 63021434966462d57145c861b43f6206d945ac57630Darrick J. Wong res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, 63121434966462d57145c861b43f6206d945ac57630Darrick J. Wong phy->dev.bus_id); 63221434966462d57145c861b43f6206d945ac57630Darrick J. Wong if (res) 63321434966462d57145c861b43f6206d945ac57630Darrick J. Wong goto err; 63421434966462d57145c861b43f6206d945ac57630Darrick J. Wong res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port"); 63521434966462d57145c861b43f6206d945ac57630Darrick J. Wong if (res) 63621434966462d57145c861b43f6206d945ac57630Darrick J. Wong goto err; 63721434966462d57145c861b43f6206d945ac57630Darrick J. Wong return; 63821434966462d57145c861b43f6206d945ac57630Darrick J. Wongerr: 63921434966462d57145c861b43f6206d945ac57630Darrick J. Wong printk(KERN_ERR "%s: Cannot create port links, err=%d\n", 64021434966462d57145c861b43f6206d945ac57630Darrick J. Wong __FUNCTION__, res); 64165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 64265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 64365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_delete_link(struct sas_port *port, 64465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy) 64565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 64665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_remove_link(&port->dev.kobj, phy->dev.bus_id); 64765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_remove_link(&phy->dev.kobj, "port"); 64865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 64965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 65065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** sas_port_alloc - allocate and initialize a SAS port structure 65165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 65265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @parent: parent device 65365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port_id: port number 65465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 65565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Allocates a SAS port structure. It will be added to the device tree 65665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * below the device specified by @parent which must be either a Scsi_Host 65765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * or a sas_expander_device. 65865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 65965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns %NULL on error 66065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 66165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_port *sas_port_alloc(struct device *parent, int port_id) 66265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 66365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 66465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port; 66565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 66665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port = kzalloc(sizeof(*port), GFP_KERNEL); 66765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!port) 66865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return NULL; 66965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 67065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->port_identifier = port_id; 67165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 67265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_initialize(&port->dev); 67365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 67465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->dev.parent = get_device(parent); 67565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->dev.release = sas_port_release; 67665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 67765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_init(&port->phy_list_mutex); 67865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley INIT_LIST_HEAD(&port->phy_list); 67965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 68065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (scsi_is_sas_expander_device(parent)) { 68165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 68265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(port->dev.bus_id, "port-%d:%d:%d", shost->host_no, 68365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley rphy->scsi_target_id, port->port_identifier); 68465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else 68565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(port->dev.bus_id, "port-%d:%d", shost->host_no, 68665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->port_identifier); 68765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 68865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_setup_device(&port->dev); 68965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 69065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return port; 69165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 69265c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_alloc); 69365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 694c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley/** sas_port_alloc_num - allocate and initialize a SAS port structure 695c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 696c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * @parent: parent device 697c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 698c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Allocates a SAS port structure and a number to go with it. This 699c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * interface is really for adapters where the port number has no 700c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * meansing, so the sas class should manage them. It will be added to 701c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * the device tree below the device specified by @parent which must be 702c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * either a Scsi_Host or a sas_expander_device. 703c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 704c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Returns %NULL on error 705c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley */ 706c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomleystruct sas_port *sas_port_alloc_num(struct device *parent) 707c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley{ 708c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley int index; 709c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 710c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 711c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 712c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley /* FIXME: use idr for this eventually */ 713c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley mutex_lock(&sas_host->lock); 714c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley if (scsi_is_sas_expander_device(parent)) { 715c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 716c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_expander_device *exp = rphy_to_expander_device(rphy); 717c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 718c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley index = exp->next_port_id++; 719c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley } else 720c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley index = sas_host->next_port_id++; 721c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley mutex_unlock(&sas_host->lock); 722c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley return sas_port_alloc(parent, index); 723c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley} 724c9fefeb26457b87f4a767faefcf77321bb90db52James BottomleyEXPORT_SYMBOL(sas_port_alloc_num); 725c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 72665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 72765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add - add a SAS port to the device hierarchy 72865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 72965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to be added 73065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 73165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * publishes a port to the rest of the system 73265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 73365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint sas_port_add(struct sas_port *port) 73465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 73565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley int error; 73665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 73765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* No phys should be added until this is made visible */ 73865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&port->phy_list)); 73965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 74065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = device_add(&port->dev); 74165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 74265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (error) 74365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return error; 74465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 74565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_add_device(&port->dev); 74665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_configure_device(&port->dev); 74765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 74865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 74965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 75065c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add); 75165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 75265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 75365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_free -- free a SAS PORT 75465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: SAS PORT to free 75565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 75665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Frees the specified SAS PORT. 75765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 75865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Note: 75965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This function must only be called on a PORT that has not 76065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sucessfully been added using sas_port_add(). 76165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 76265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_free(struct sas_port *port) 76365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 76465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_destroy_device(&port->dev); 76565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(&port->dev); 76665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 76765c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_free); 76865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 76965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 77065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_delete -- remove SAS PORT 77165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: SAS PORT to remove 77265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 77365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Removes the specified SAS PORT. If the SAS PORT has an 77465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * associated phys, unlink them from the port as well. 77565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 77665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete(struct sas_port *port) 77765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 77865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct device *dev = &port->dev; 77965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy, *tmp_phy; 78065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 78165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (port->rphy) { 78265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_rphy_delete(port->rphy); 78365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->rphy = NULL; 78465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 78565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 78665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 78765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_for_each_entry_safe(phy, tmp_phy, &port->phy_list, 78865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port_siblings) { 78965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete_link(port, phy); 79065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_del_init(&phy->port_siblings); 79165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 79265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 79365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 794a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley if (port->is_backlink) { 795a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley struct device *parent = port->dev.parent; 796a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 797a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley sysfs_remove_link(&port->dev.kobj, parent->bus_id); 798a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley port->is_backlink = 0; 799a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley } 800a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 80165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_remove_device(dev); 80265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_del(dev); 80365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_destroy_device(dev); 80465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(dev); 80565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 80665c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete); 80765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 80865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 80965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * scsi_is_sas_port -- check if a struct device represents a SAS port 81065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @dev: device to check 81165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 81265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns: 81365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * %1 if the device represents a SAS Port, %0 else 81465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 81565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint scsi_is_sas_port(const struct device *dev) 81665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 81765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return dev->release == sas_port_release; 81865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 81965c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(scsi_is_sas_port); 82065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 82165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 82265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add_phy - add another phy to a port to form a wide port 82365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to add the phy to 82465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy: phy to add 82565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 82665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * When a port is initially created, it is empty (has no phys). All 82765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * ports must have at least one phy to operated, and all wide ports 82865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * must have at least two. The current code makes no difference 82965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * between ports and wide ports, but the only object that can be 83065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * connected to a remote device is a port, so ports must be formed on 83165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * all devices with phys if they're connected to anything. 83265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 83365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_add_phy(struct sas_port *port, struct sas_phy *phy) 83465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 83565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 83665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (unlikely(!list_empty(&phy->port_siblings))) { 83765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* make sure we're already on this port */ 83865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *tmp; 83965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 84065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_for_each_entry(tmp, &port->phy_list, port_siblings) 84165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (tmp == phy) 84265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley break; 84365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* If this trips, you added a phy that was already 84465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * part of a different port */ 84565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (unlikely(tmp != phy)) { 84665c92b09acf0218b64f1c7ba4fdabeb8b732c876James 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); 84765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG(); 84865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 84965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else { 85065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_create_link(port, phy); 85165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_add_tail(&phy->port_siblings, &port->phy_list); 85265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->num_phys++; 85365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 85465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 85565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 85665c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add_phy); 85765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 85865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 85965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_delete_phy - remove a phy from a port or wide port 86065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to remove the phy from 86165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy: phy to remove 86265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 86365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This operation is used for tearing down ports again. It must be 86465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * done to every port or wide port before calling sas_port_delete. 86565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 86665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy) 86765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 86865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 86965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete_link(port, phy); 87065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_del_init(&phy->port_siblings); 87165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->num_phys--; 87265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 87365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 87465c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete_phy); 87565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 876a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomleyvoid sas_port_mark_backlink(struct sas_port *port) 877a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley{ 87821434966462d57145c861b43f6206d945ac57630Darrick J. Wong int res; 879a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley struct device *parent = port->dev.parent->parent->parent; 880a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 881a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley if (port->is_backlink) 882a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley return; 883a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley port->is_backlink = 1; 88421434966462d57145c861b43f6206d945ac57630Darrick J. Wong res = sysfs_create_link(&port->dev.kobj, &parent->kobj, 88521434966462d57145c861b43f6206d945ac57630Darrick J. Wong parent->bus_id); 88621434966462d57145c861b43f6206d945ac57630Darrick J. Wong if (res) 88721434966462d57145c861b43f6206d945ac57630Darrick J. Wong goto err; 88821434966462d57145c861b43f6206d945ac57630Darrick J. Wong return; 88921434966462d57145c861b43f6206d945ac57630Darrick J. Wongerr: 89021434966462d57145c861b43f6206d945ac57630Darrick J. Wong printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n", 89121434966462d57145c861b43f6206d945ac57630Darrick J. Wong __FUNCTION__, res); 892a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 893a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley} 894a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames BottomleyEXPORT_SYMBOL(sas_port_mark_backlink); 895a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 89665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/* 897c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS remote PHY attributes. 898c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 899c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 900c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_simple(field, name, format_string, cast) \ 901c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 902c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_##name(struct class_device *cdev, char *buf) \ 903c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 904c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 905c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 906c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast rphy->field); \ 907c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 908c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 909c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_simple_attr(field, name, format_string, type) \ 910c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_simple(field, name, format_string, (type)) \ 911c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 912c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 913c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 914c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_protocol(field, name) \ 915c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 916c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_##name(struct class_device *cdev, char *buf) \ 917c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 918c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 919c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 920c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->field) \ 921c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 922c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(rphy->field, buf); \ 923c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 924c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 925c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_protocol_attr(field, name) \ 926c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_protocol(field, name) \ 927c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 928c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 929c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 930c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 931c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigshow_sas_rphy_device_type(struct class_device *cdev, char *buf) 932c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 933c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 934c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 935c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->identify.device_type) 936c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 937c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names( 938c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->identify.device_type, buf); 939c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 940c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 941c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, 942c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_device_type, NULL); 943c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 944a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 945a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigshow_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf) 946a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 947a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 948a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 949a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 950a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 951a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig u64 identifier; 952a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int error; 953a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 954a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig /* 955a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * Only devices behind an expander are supported, because the 956a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * enclosure identifier is a SMP feature. 957a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig */ 958f4ad7b5807385ad1fed0347d966e51a797cd1013James Bottomley if (scsi_is_sas_phy_local(phy)) 959a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 960a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 961a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig error = i->f->get_enclosure_identifier(rphy, &identifier); 962a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (error) 963a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return error; 964a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); 965a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 966a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 967a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, 968a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_enclosure_identifier, NULL); 969a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 970a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 971a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigshow_sas_rphy_bay_identifier(struct class_device *cdev, char *buf) 972a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 973a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_rphy *rphy = transport_class_to_rphy(cdev); 974a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 975a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 976a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 977a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int val; 978a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 979f4ad7b5807385ad1fed0347d966e51a797cd1013James Bottomley if (scsi_is_sas_phy_local(phy)) 980a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 981a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 982a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig val = i->f->get_bay_identifier(rphy); 983a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (val < 0) 984a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return val; 985a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "%d\n", val); 986a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 987a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 988a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, 989a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_bay_identifier, NULL); 990a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 991c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.initiator_port_protocols, 992c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 993c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); 994c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 995c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 996c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 997c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 99842ab03609cca4ef5079e248296f015650c626899James Bottomley/* only need 8 bytes of data plus header (4 or 8) */ 99942ab03609cca4ef5079e248296f015650c626899James Bottomley#define BUF_SIZE 64 100042ab03609cca4ef5079e248296f015650c626899James Bottomley 100142ab03609cca4ef5079e248296f015650c626899James Bottomleyint sas_read_port_mode_page(struct scsi_device *sdev) 100242ab03609cca4ef5079e248296f015650c626899James Bottomley{ 100342ab03609cca4ef5079e248296f015650c626899James Bottomley char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; 100442ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target); 100542ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev; 100642ab03609cca4ef5079e248296f015650c626899James Bottomley struct scsi_mode_data mode_data; 100742ab03609cca4ef5079e248296f015650c626899James Bottomley int res, error; 100842ab03609cca4ef5079e248296f015650c626899James Bottomley 100942ab03609cca4ef5079e248296f015650c626899James Bottomley BUG_ON(rphy->identify.device_type != SAS_END_DEVICE); 101042ab03609cca4ef5079e248296f015650c626899James Bottomley 101142ab03609cca4ef5079e248296f015650c626899James Bottomley rdev = rphy_to_end_device(rphy); 101242ab03609cca4ef5079e248296f015650c626899James Bottomley 101342ab03609cca4ef5079e248296f015650c626899James Bottomley if (!buffer) 101442ab03609cca4ef5079e248296f015650c626899James Bottomley return -ENOMEM; 101542ab03609cca4ef5079e248296f015650c626899James Bottomley 101642ab03609cca4ef5079e248296f015650c626899James Bottomley res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, 101742ab03609cca4ef5079e248296f015650c626899James Bottomley &mode_data, NULL); 101842ab03609cca4ef5079e248296f015650c626899James Bottomley 101942ab03609cca4ef5079e248296f015650c626899James Bottomley error = -EINVAL; 102042ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_status_is_good(res)) 102142ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 102242ab03609cca4ef5079e248296f015650c626899James Bottomley 102342ab03609cca4ef5079e248296f015650c626899James Bottomley msdata = buffer + mode_data.header_length + 102442ab03609cca4ef5079e248296f015650c626899James Bottomley mode_data.block_descriptor_length; 102542ab03609cca4ef5079e248296f015650c626899James Bottomley 102642ab03609cca4ef5079e248296f015650c626899James Bottomley if (msdata - buffer > BUF_SIZE - 8) 102742ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 102842ab03609cca4ef5079e248296f015650c626899James Bottomley 102942ab03609cca4ef5079e248296f015650c626899James Bottomley error = 0; 103042ab03609cca4ef5079e248296f015650c626899James Bottomley 103142ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0; 103242ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5]; 103342ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7]; 103442ab03609cca4ef5079e248296f015650c626899James Bottomley 103542ab03609cca4ef5079e248296f015650c626899James Bottomley out: 103642ab03609cca4ef5079e248296f015650c626899James Bottomley kfree(buffer); 103742ab03609cca4ef5079e248296f015650c626899James Bottomley return error; 103842ab03609cca4ef5079e248296f015650c626899James Bottomley} 103942ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_read_port_mode_page); 104042ab03609cca4ef5079e248296f015650c626899James Bottomley 104179cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_end_dev_class, 104279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_end_device", NULL, NULL, NULL); 104379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 104442ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_show_simple(field, name, format_string, cast) \ 104542ab03609cca4ef5079e248296f015650c626899James Bottomleystatic ssize_t \ 104642ab03609cca4ef5079e248296f015650c626899James Bottomleyshow_sas_end_dev_##name(struct class_device *cdev, char *buf) \ 104742ab03609cca4ef5079e248296f015650c626899James Bottomley{ \ 104842ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 104942ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev = rphy_to_end_device(rphy); \ 105042ab03609cca4ef5079e248296f015650c626899James Bottomley \ 105142ab03609cca4ef5079e248296f015650c626899James Bottomley return snprintf(buf, 20, format_string, cast rdev->field); \ 105242ab03609cca4ef5079e248296f015650c626899James Bottomley} 105342ab03609cca4ef5079e248296f015650c626899James Bottomley 105442ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_simple_attr(field, name, format_string, type) \ 105542ab03609cca4ef5079e248296f015650c626899James Bottomley sas_end_dev_show_simple(field, name, format_string, (type)) \ 105642ab03609cca4ef5079e248296f015650c626899James Bottomleystatic SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ 105742ab03609cca4ef5079e248296f015650c626899James Bottomley show_sas_end_dev_##name, NULL) 105842ab03609cca4ef5079e248296f015650c626899James Bottomley 105942ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); 106042ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, 106142ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 106242ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, 106342ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 106442ab03609cca4ef5079e248296f015650c626899James Bottomley 106579cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_expander_class, 106679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_expander", NULL, NULL, NULL); 106779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 106879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_show_simple(field, name, format_string, cast) \ 106979cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic ssize_t \ 107079cb1819e231f811211133a09a5382cb89d7ec67James Bottomleyshow_sas_expander_##name(struct class_device *cdev, char *buf) \ 107179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ \ 107279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ 107379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ 107479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley \ 107579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return snprintf(buf, 20, format_string, cast edev->field); \ 107679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 107779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 107879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_simple_attr(field, name, format_string, type) \ 107979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sas_expander_show_simple(field, name, format_string, (type)) \ 108079cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, \ 108179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley show_sas_expander_##name, NULL) 108279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 108379cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); 108479cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_id, product_id, "%s\n", char *); 108579cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_rev, product_rev, "%s\n", char *); 108679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_vendor_id, component_vendor_id, 108779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "%s\n", char *); 108879cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int); 108979cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", 109079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley unsigned int); 109179cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(level, level, "%d\n", int); 109242ab03609cca4ef5079e248296f015650c626899James Bottomley 1093c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_rphy_class, 10942f8600dff2b140096a7df781884e918a16aa90e0James Bottomley "sas_device", NULL, NULL, NULL); 1095c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1096c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_rphy_match(struct attribute_container *cont, struct device *dev) 1097c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1098c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 1099c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 1100c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1101c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_rphy(dev)) 1102c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1103c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent->parent); 1104c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1105c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 1106c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1107c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 1108c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 1109c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1110c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1111c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 1112c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->rphy_attr_cont.ac == cont; 1113c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1114c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 111542ab03609cca4ef5079e248296f015650c626899James Bottomleystatic int sas_end_dev_match(struct attribute_container *cont, 111642ab03609cca4ef5079e248296f015650c626899James Bottomley struct device *dev) 111742ab03609cca4ef5079e248296f015650c626899James Bottomley{ 111842ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost; 111942ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_internal *i; 112042ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy; 112142ab03609cca4ef5079e248296f015650c626899James Bottomley 112242ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_is_sas_rphy(dev)) 112342ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 112442ab03609cca4ef5079e248296f015650c626899James Bottomley shost = dev_to_shost(dev->parent->parent); 112542ab03609cca4ef5079e248296f015650c626899James Bottomley rphy = dev_to_rphy(dev); 112642ab03609cca4ef5079e248296f015650c626899James Bottomley 112742ab03609cca4ef5079e248296f015650c626899James Bottomley if (!shost->transportt) 112842ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 112942ab03609cca4ef5079e248296f015650c626899James Bottomley if (shost->transportt->host_attrs.ac.class != 113042ab03609cca4ef5079e248296f015650c626899James Bottomley &sas_host_class.class) 113142ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 113242ab03609cca4ef5079e248296f015650c626899James Bottomley 113342ab03609cca4ef5079e248296f015650c626899James Bottomley i = to_sas_internal(shost->transportt); 113442ab03609cca4ef5079e248296f015650c626899James Bottomley return &i->end_dev_attr_cont.ac == cont && 11352f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_END_DEVICE; 113642ab03609cca4ef5079e248296f015650c626899James Bottomley} 113742ab03609cca4ef5079e248296f015650c626899James Bottomley 113879cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic int sas_expander_match(struct attribute_container *cont, 113979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct device *dev) 114079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 114179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost; 114279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_internal *i; 114379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy; 114479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 114579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!scsi_is_sas_rphy(dev)) 114679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 114779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley shost = dev_to_shost(dev->parent->parent); 114879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy = dev_to_rphy(dev); 114979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 115079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!shost->transportt) 115179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 115279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (shost->transportt->host_attrs.ac.class != 115379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley &sas_host_class.class) 115479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 115579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 115679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i = to_sas_internal(shost->transportt); 115779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &i->expander_attr_cont.ac == cont && 115879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || 11592f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE); 116079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 116179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 11622f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_expander_release(struct device *dev) 1163c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1164c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = dev_to_rphy(dev); 11652f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); 1166c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1167c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 11682f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 1169c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1170c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 11712f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_end_device_release(struct device *dev) 1172c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 11732f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_rphy *rphy = dev_to_rphy(dev); 11742f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_end_device *edev = rphy_to_end_device(rphy); 1175c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 11762f8600dff2b140096a7df781884e918a16aa90e0James Bottomley put_device(dev->parent); 11772f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 1178c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1179c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1180c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1181c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * sas_rphy_initialize - common rphy intialization 1182c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * @rphy: rphy to initialise 1183c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * 1184c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * Used by both sas_end_device_alloc() and sas_expander_alloc() to 1185c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * initialise the common rphy component of each. 1186c5943d36aebb79589ac3983eec418bbeca897573James Bottomley */ 1187c5943d36aebb79589ac3983eec418bbeca897573James Bottomleystatic void sas_rphy_initialize(struct sas_rphy *rphy) 1188c5943d36aebb79589ac3983eec418bbeca897573James Bottomley{ 1189c5943d36aebb79589ac3983eec418bbeca897573James Bottomley INIT_LIST_HEAD(&rphy->list); 1190c5943d36aebb79589ac3983eec418bbeca897573James Bottomley} 1191c5943d36aebb79589ac3983eec418bbeca897573James Bottomley 1192c5943d36aebb79589ac3983eec418bbeca897573James Bottomley/** 119342ab03609cca4ef5079e248296f015650c626899James Bottomley * sas_end_device_alloc - allocate an rphy for an end device 119442ab03609cca4ef5079e248296f015650c626899James Bottomley * 119542ab03609cca4ef5079e248296f015650c626899James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 119642ab03609cca4ef5079e248296f015650c626899James Bottomley * 119742ab03609cca4ef5079e248296f015650c626899James Bottomley * Returns: 119842ab03609cca4ef5079e248296f015650c626899James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 119942ab03609cca4ef5079e248296f015650c626899James Bottomley */ 120065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_end_device_alloc(struct sas_port *parent) 120142ab03609cca4ef5079e248296f015650c626899James Bottomley{ 120242ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 120342ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev; 120442ab03609cca4ef5079e248296f015650c626899James Bottomley 120542ab03609cca4ef5079e248296f015650c626899James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 120642ab03609cca4ef5079e248296f015650c626899James Bottomley if (!rdev) { 120742ab03609cca4ef5079e248296f015650c626899James Bottomley return NULL; 120842ab03609cca4ef5079e248296f015650c626899James Bottomley } 120942ab03609cca4ef5079e248296f015650c626899James Bottomley 121042ab03609cca4ef5079e248296f015650c626899James Bottomley device_initialize(&rdev->rphy.dev); 121142ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 12122f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_end_device_release; 121365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (scsi_is_sas_expander_device(parent->dev.parent)) { 121465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent); 121565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d:%d", 121665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley shost->host_no, rphy->scsi_target_id, parent->port_identifier); 121765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else 121865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d", 121965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley shost->host_no, parent->port_identifier); 122042ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.identify.device_type = SAS_END_DEVICE; 1221c5943d36aebb79589ac3983eec418bbeca897573James Bottomley sas_rphy_initialize(&rdev->rphy); 122242ab03609cca4ef5079e248296f015650c626899James Bottomley transport_setup_device(&rdev->rphy.dev); 122342ab03609cca4ef5079e248296f015650c626899James Bottomley 122442ab03609cca4ef5079e248296f015650c626899James Bottomley return &rdev->rphy; 122542ab03609cca4ef5079e248296f015650c626899James Bottomley} 122642ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_end_device_alloc); 122742ab03609cca4ef5079e248296f015650c626899James Bottomley 122879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley/** 122979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * sas_expander_alloc - allocate an rphy for an end device 123079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 123179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 123279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 123379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Returns: 123479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 123579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley */ 123665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_expander_alloc(struct sas_port *parent, 123779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley enum sas_device_type type) 123879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 123979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 124079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *rdev; 124179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 124279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 124379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE && 124479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley type != SAS_FANOUT_EXPANDER_DEVICE); 124579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 124679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 124779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!rdev) { 124879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return NULL; 124979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } 125079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 125179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley device_initialize(&rdev->rphy.dev); 125279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 12532f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_expander_release; 125479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_lock(&sas_host->lock); 125579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.scsi_target_id = sas_host->next_expander_id++; 125679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_unlock(&sas_host->lock); 125779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", 125879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley shost->host_no, rdev->rphy.scsi_target_id); 125979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.identify.device_type = type; 1260c5943d36aebb79589ac3983eec418bbeca897573James Bottomley sas_rphy_initialize(&rdev->rphy); 126179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_setup_device(&rdev->rphy.dev); 126279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 126379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &rdev->rphy; 126479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 126579cb1819e231f811211133a09a5382cb89d7ec67James BottomleyEXPORT_SYMBOL(sas_expander_alloc); 126642ab03609cca4ef5079e248296f015650c626899James Bottomley 126742ab03609cca4ef5079e248296f015650c626899James Bottomley/** 1268c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_add -- add a SAS remote PHY to the device hierachy 1269c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy: The remote PHY to be added 1270c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1271c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS remote PHY to the rest of the system. 1272c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1273c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_rphy_add(struct sas_rphy *rphy) 1274c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 127565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *parent = dev_to_sas_port(rphy->dev.parent); 1276c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 1277c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1278c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_identify *identify = &rphy->identify; 1279c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1280c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1281c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (parent->rphy) 1282c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return -ENXIO; 1283c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig parent->rphy = rphy; 1284c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1285c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&rphy->dev); 1286c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1287c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1288c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&rphy->dev); 1289c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&rphy->dev); 1290c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1291e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1292c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_add_tail(&rphy->list, &sas_host->rphy_list); 1293c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (identify->device_type == SAS_END_DEVICE && 1294c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (identify->target_port_protocols & 1295c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) 1296c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id = sas_host->next_target_id++; 12977676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley else if (identify->device_type == SAS_END_DEVICE) 12987676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley rphy->scsi_target_id = -1; 1299e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1300c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 130179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (identify->device_type == SAS_END_DEVICE && 130279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id != -1) { 1303e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley scsi_scan_target(&rphy->dev, 0, 1304c8490f3a77805d04321d9e44486a679801a035b8Darrick J. Wong rphy->scsi_target_id, SCAN_WILD_CARD, 0); 1305c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 1306c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1307c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1308c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1309c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_add); 1310c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1311c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1312c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_rphy_free -- free a SAS remote PHY 1313c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy SAS remote PHY to free 1314c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1315c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS remote PHY. 1316c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1317c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 1318c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a remote 1319c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * PHY that has not sucessfully been added using 13206f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * sas_rphy_add() (or has been sas_rphy_remove()'d) 1321c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1322c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_rphy_free(struct sas_rphy *rphy) 1323c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 132492aab6464be735139f9ea38fd039c3b84c722630Mike Anderson struct device *dev = &rphy->dev; 1325c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 1326c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1327c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1328e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1329c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_del(&rphy->list); 1330e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1331c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 133292aab6464be735139f9ea38fd039c3b84c722630Mike Anderson transport_destroy_device(dev); 13332f8600dff2b140096a7df781884e918a16aa90e0James Bottomley 133492aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 1335c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1336c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_free); 1337c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1338c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 13396f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * sas_rphy_delete -- remove and free SAS remote PHY 13406f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * @rphy: SAS remote PHY to remove and free 1341c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 13426f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * Removes the specified SAS remote PHY and frees it. 1343c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1344c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 1345c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_delete(struct sas_rphy *rphy) 1346c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 13476f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong sas_rphy_remove(rphy); 13486f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong sas_rphy_free(rphy); 13496f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong} 13506f63caae2172e97e528b58319480217b0b36542eDarrick J. WongEXPORT_SYMBOL(sas_rphy_delete); 13516f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong 13526f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong/** 13536f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * sas_rphy_remove -- remove SAS remote PHY 13546f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * @rphy: SAS remote phy to remove 13556f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * 13566f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * Removes the specified SAS remote PHY. 13576f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong */ 13586f63caae2172e97e528b58319480217b0b36542eDarrick J. Wongvoid 13596f63caae2172e97e528b58319480217b0b36542eDarrick J. Wongsas_rphy_remove(struct sas_rphy *rphy) 13606f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong{ 1361c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &rphy->dev; 136265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *parent = dev_to_sas_port(dev->parent); 1363c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1364d4054239929479907f20b9d68c905589125ad343Christoph Hellwig switch (rphy->identify.device_type) { 1365d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_END_DEVICE: 1366d4054239929479907f20b9d68c905589125ad343Christoph Hellwig scsi_remove_target(dev); 1367d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1368d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_EDGE_EXPANDER_DEVICE: 1369d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_FANOUT_EXPANDER_DEVICE: 137065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_remove_children(dev); 1371d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1372d4054239929479907f20b9d68c905589125ad343Christoph Hellwig default: 1373d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1374d4054239929479907f20b9d68c905589125ad343Christoph Hellwig } 1375c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1376fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig transport_remove_device(dev); 1377fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig device_del(dev); 1378c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 137933b114e935a2202206e224dd2c695cee5a5986bfChristoph Hellwig parent->rphy = NULL; 1380c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 13816f63caae2172e97e528b58319480217b0b36542eDarrick J. WongEXPORT_SYMBOL(sas_rphy_remove); 1382c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1383c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1384c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY 1385c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 1386c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1387c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 1388c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS remote PHY, %0 else 1389c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1390c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_rphy(const struct device *dev) 1391c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 13922f8600dff2b140096a7df781884e918a16aa90e0James Bottomley return dev->release == sas_end_device_release || 13932f8600dff2b140096a7df781884e918a16aa90e0James Bottomley dev->release == sas_expander_release; 1394c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1395c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_rphy); 1396c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1397c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1398c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 1399c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SCSI scan helper 1400c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1401c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1402e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwigstatic int sas_user_scan(struct Scsi_Host *shost, uint channel, 1403e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig uint id, uint lun) 1404c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1405c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1406c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy; 1407c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1408e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1409c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_for_each_entry(rphy, &sas_host->rphy_list, list) { 14106d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley if (rphy->identify.device_type != SAS_END_DEVICE || 14116d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley rphy->scsi_target_id == -1) 1412e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig continue; 1413e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig 1414e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley if ((channel == SCAN_WILD_CARD || channel == 0) && 1415e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { 1416e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley scsi_scan_target(&rphy->dev, 0, 1417e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig rphy->scsi_target_id, lun, 1); 1418e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig } 1419c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 1420e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1421c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1422e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig return 0; 1423c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1424c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1425c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1426c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 1427c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Setup / Teardown code 1428c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1429c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1430d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_TEMPLATE(attrb, field, perm, test) \ 143142ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count] = class_device_attr_##field; \ 143242ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count].attr.mode = perm; \ 143342ab03609cca4ef5079e248296f015650c626899James Bottomley i->attrb[count] = &i->private_##attrb[count]; \ 143442ab03609cca4ef5079e248296f015650c626899James Bottomley if (test) \ 143542ab03609cca4ef5079e248296f015650c626899James Bottomley count++ 143642ab03609cca4ef5079e248296f015650c626899James Bottomley 1437d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm) \ 1438d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count] = class_device_attr_##field; \ 1439d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].attr.mode = perm; \ 1440d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (ro_test) { \ 1441d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].attr.mode = ro_perm; \ 1442d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].store = NULL; \ 1443d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley } \ 1444d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->attrb[count] = &i->private_##attrb[count]; \ 1445d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (test) \ 1446d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley count++ 144742ab03609cca4ef5079e248296f015650c626899James Bottomley 144842ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_RPORT_ATTRIBUTE(field) \ 144942ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) 1450c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1451dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ 145242ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func) 1453dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 145465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE(field) \ 145542ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) 1456c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1457d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_PHY_ATTRIBUTE_RW(field) \ 1458d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ 1459d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley !i->f->set_phy_speed, S_IRUGO) 1460d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 1461acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func) \ 1462acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ 1463acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong !i->f->func, S_IRUGO) 1464acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 146565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PORT_ATTRIBUTE(field) \ 146665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) 146765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 146865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func) \ 146942ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) 1470dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 147165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE_WRONLY(field) \ 1472fe3b5bfe73ace420709f0cfb198b0ffc704bd38bDarrick J. Wong SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1) 147307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 147465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func) \ 1475fe3b5bfe73ace420709f0cfb198b0ffc704bd38bDarrick J. Wong SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func) 1476dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 147742ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_END_DEV_ATTRIBUTE(field) \ 147842ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) 1479c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 148079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define SETUP_EXPANDER_ATTRIBUTE(field) \ 148179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) 148279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1483c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1484c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_attach_transport -- instantiate SAS transport template 1485c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @ft: SAS transport class function template 1486c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1487c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct scsi_transport_template * 1488c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_attach_transport(struct sas_function_template *ft) 1489c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1490c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 1491c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int count; 1492c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 149324669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL); 1494c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!i) 1495c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 1496c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1497e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig i->t.user_scan = sas_user_scan; 1498c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1499c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 1500c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.class = &sas_host_class.class; 1501c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.match = sas_host_match; 1502c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->t.host_attrs); 1503c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_size = sizeof(struct sas_host_attrs); 1504c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1505c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.class = &sas_phy_class.class; 1506c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.attrs = &i->phy_attrs[0]; 1507c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.match = sas_phy_match; 1508c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->phy_attr_cont); 1509c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 151065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.class = &sas_port_class.class; 151165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.attrs = &i->port_attrs[0]; 151265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.match = sas_port_match; 151365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_container_register(&i->port_attr_cont); 151465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 1515c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.class = &sas_rphy_class.class; 1516c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0]; 1517c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.match = sas_rphy_match; 1518c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->rphy_attr_cont); 1519c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 152042ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class; 152142ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0]; 152242ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.match = sas_end_dev_match; 152342ab03609cca4ef5079e248296f015650c626899James Bottomley transport_container_register(&i->end_dev_attr_cont); 152442ab03609cca4ef5079e248296f015650c626899James Bottomley 152579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.class = &sas_expander_class.class; 152679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.attrs = &i->expander_attrs[0]; 152779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.match = sas_expander_match; 152879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_register(&i->expander_attr_cont); 152979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1530c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->f = ft; 1531c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1532c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 153365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PORT_ATTRIBUTE(num_phys); 1534c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->host_attrs[count] = NULL; 1535c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1536c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 153765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(initiator_port_protocols); 153865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(target_port_protocols); 153965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(device_type); 154065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(sas_address); 154165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(phy_identifier); 154265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley //SETUP_PHY_ATTRIBUTE(port_identifier); 154365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(negotiated_linkrate); 154465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw); 1545d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_PHY_ATTRIBUTE_RW(minimum_linkrate); 154665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw); 1547d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_PHY_ATTRIBUTE_RW(maximum_linkrate); 154865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 154965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(invalid_dword_count); 155065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(running_disparity_error_count); 155165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count); 155265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(phy_reset_problem_count); 155365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset); 155465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset); 1555acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable); 1556c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attrs[count] = NULL; 1557c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1558c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 155965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PORT_ATTRIBUTE(num_phys); 156065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attrs[count] = NULL; 156165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 156265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley count = 0; 1563c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols); 1564c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols); 1565c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_device_type); 1566c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_sas_address); 1567c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); 1568dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier, 1569dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_enclosure_identifier); 1570dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier, 1571dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_bay_identifier); 1572c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attrs[count] = NULL; 1573c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 157442ab03609cca4ef5079e248296f015650c626899James Bottomley count = 0; 157542ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); 157642ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); 157742ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); 157842ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attrs[count] = NULL; 157942ab03609cca4ef5079e248296f015650c626899James Bottomley 158079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley count = 0; 158179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(vendor_id); 158279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_id); 158379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_rev); 158479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_vendor_id); 158579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_id); 158679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_revision_id); 158779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(level); 158879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attrs[count] = NULL; 158979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1590c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t; 1591c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1592c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_attach_transport); 1593c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1594c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1595c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * sas_release_transport -- release SAS transport template instance 1596c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @t: transport template instance 1597c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1598c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_release_transport(struct scsi_transport_template *t) 1599c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1600c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i = to_sas_internal(t); 1601c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1602c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->t.host_attrs); 1603c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->phy_attr_cont); 160465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_container_unregister(&i->port_attr_cont); 1605c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->rphy_attr_cont); 1606db82f8410ed7546792358964aa5f8dafff1c70a2James Bottomley transport_container_unregister(&i->end_dev_attr_cont); 160779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_unregister(&i->expander_attr_cont); 1608c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1609c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(i); 1610c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1611c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_release_transport); 1612c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1613c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic __init int sas_transport_init(void) 1614c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1615c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1616c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1617c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_host_class); 1618c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1619c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out; 1620c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_phy_class); 1621c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1622c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_transport; 162365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = transport_class_register(&sas_port_class); 1624c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1625c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_phy; 162665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = transport_class_register(&sas_rphy_class); 162765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (error) 162865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley goto out_unregister_port; 162942ab03609cca4ef5079e248296f015650c626899James Bottomley error = transport_class_register(&sas_end_dev_class); 163042ab03609cca4ef5079e248296f015650c626899James Bottomley if (error) 163142ab03609cca4ef5079e248296f015650c626899James Bottomley goto out_unregister_rphy; 163279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley error = transport_class_register(&sas_expander_class); 163379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (error) 163479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley goto out_unregister_end_dev; 1635c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1636c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1637c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 163879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley out_unregister_end_dev: 163979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_end_dev_class); 164042ab03609cca4ef5079e248296f015650c626899James Bottomley out_unregister_rphy: 164142ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_rphy_class); 164265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley out_unregister_port: 164365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_class_unregister(&sas_port_class); 1644c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_phy: 1645c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 1646c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_transport: 1647c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1648c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out: 1649c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1650c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1651c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1652c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1653c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void __exit sas_transport_exit(void) 1654c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1655c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1656c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 165765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_class_unregister(&sas_port_class); 1658c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_rphy_class); 165942ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_end_dev_class); 166079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_expander_class); 1661c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1662c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1663c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_AUTHOR("Christoph Hellwig"); 166486b9c4c16a1589d05959af2d96d52a4352c6306eAlexis BruemmerMODULE_DESCRIPTION("SAS Transport Attributes"); 1665c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_LICENSE("GPL"); 1666c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1667c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_init(sas_transport_init); 1668c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_exit(sas_transport_exit); 1669