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