scsi_transport_sas.c revision 75ad23bc0fcb4f992a5d06982bf0857ab1738e9e
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,
9b1c118121ae37285ddc0a7a908999196bb35fb0bJoe Perches * and various sysfs attributes to expose these topologies and management
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>
327aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori#include <linux/blkdev.h>
337aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori#include <linux/bsg.h>
34c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
35e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig#include <scsi/scsi.h>
36c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_device.h>
37c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_host.h>
38c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_transport.h>
39c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_transport_sas.h>
40c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
41d6159c17c2c76963a8067d1e1ac3c4c36c05e674James Bottomley#include "scsi_sas_internal.h"
42c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_host_attrs {
43c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct list_head rphy_list;
44e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig	struct mutex lock;
45b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	struct request_queue *q;
46c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	u32 next_target_id;
4779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	u32 next_expander_id;
48c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	int next_port_id;
49c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig};
50c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define to_sas_host_attrs(host)	((struct sas_host_attrs *)(host)->shost_data)
51c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
52c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
53c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/*
54c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Hack to allow attributes of the same name in different objects.
55c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
56ee959b00c335d7780136c5abda37809191fe52c3Tony Jones#define SAS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
57ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct device_attribute dev_attr_##_prefix##_##_name = \
58c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	__ATTR(_name,_mode,_show,_store)
59c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
60c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
61c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/*
62c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Pretty printing helpers
63c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
64c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
65c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_match(title, table)			\
66c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t							\
67c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf)		\
68c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{								\
69c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	char *prefix = "";					\
70c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	ssize_t len = 0;					\
71c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	int i;							\
72c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig								\
736391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser	for (i = 0; i < ARRAY_SIZE(table); i++) {		\
74c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		if (table[i].value & table_key) {		\
75c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig			len += sprintf(buf + len, "%s%s",	\
76c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig				prefix, table[i].name);		\
77c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig			prefix = ", ";				\
78c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		}						\
79c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	}							\
80c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	len += sprintf(buf + len, "\n");			\
81c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return len;						\
82c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
83c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
84d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define sas_bitfield_name_set(title, table)			\
85d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleystatic ssize_t							\
86d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleyset_sas_##title##_names(u32 *table_key, const char *buf)	\
87d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley{								\
88d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	ssize_t len = 0;					\
89d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	int i;							\
90d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley								\
91d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	for (i = 0; i < ARRAY_SIZE(table); i++) {		\
92d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley		len = strlen(table[i].name);			\
93d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley		if (strncmp(buf, table[i].name, len) == 0 &&	\
94d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley		    (buf[len] == '\n' || buf[len] == '\0')) {	\
95d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley			*table_key = table[i].value;		\
96d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley			return 0;				\
97d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley		}						\
98d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	}							\
99d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	return -EINVAL;						\
100d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley}
101d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley
102c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_search(title, table)			\
103c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t							\
104c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf)		\
105c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{								\
106c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	ssize_t len = 0;					\
107c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	int i;							\
108c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig								\
1096391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser	for (i = 0; i < ARRAY_SIZE(table); i++) {		\
110c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		if (table[i].value == table_key) {		\
111c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig			len += sprintf(buf + len, "%s",		\
112c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig				table[i].name);			\
113c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig			break;					\
114c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		}						\
115c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	}							\
116c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	len += sprintf(buf + len, "\n");			\
117c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return len;						\
118c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
119c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
120c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct {
121c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	u32		value;
122c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	char		*name;
123c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_device_type_names[] = {
124c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_PHY_UNUSED,		"unused" },
125c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_END_DEVICE,		"end device" },
126c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_EDGE_EXPANDER_DEVICE,	"edge expander" },
127c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_FANOUT_EXPANDER_DEVICE,	"fanout expander" },
128c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig};
129c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(device_type, sas_device_type_names)
130c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
131c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
132c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct {
133c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	u32		value;
134c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	char		*name;
135c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_protocol_names[] = {
136c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_PROTOCOL_SATA,		"sata" },
137c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_PROTOCOL_SMP,		"smp" },
138c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_PROTOCOL_STP,		"stp" },
139c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_PROTOCOL_SSP,		"ssp" },
140c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig};
141c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_match(protocol, sas_protocol_names)
142c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
143c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct {
144c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	u32		value;
145c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	char		*name;
146c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_linkspeed_names[] = {
147c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_LINK_RATE_UNKNOWN,	"Unknown" },
148c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_PHY_DISABLED,		"Phy disabled" },
149c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_LINK_RATE_FAILED,		"Link Rate failed" },
150c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_SATA_SPINUP_HOLD,		"Spin-up hold" },
151c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_LINK_RATE_1_5_GBPS,	"1.5 Gbit" },
152c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	{ SAS_LINK_RATE_3_0_GBPS,	"3.0 Gbit" },
1537e6dff62dad539cbd608bb3b8b833193d13f00acJames Bottomley	{ SAS_LINK_RATE_6_0_GBPS,	"6.0 Gbit" },
154c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig};
155c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(linkspeed, sas_linkspeed_names)
156d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_bitfield_name_set(linkspeed, sas_linkspeed_names)
157c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1587aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonoristatic void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
1597aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori			    struct sas_rphy *rphy)
1607aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori{
1617aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	struct request *req;
1627aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	int ret;
1637aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
1647aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
1657aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	while (!blk_queue_plugged(q)) {
1667aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		req = elv_next_request(q);
1677aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		if (!req)
1687aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori			break;
1697aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
1707aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		blkdev_dequeue_request(req);
1717aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
1727aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		spin_unlock_irq(q->queue_lock);
1737aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
1747aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		handler = to_sas_internal(shost->transportt)->f->smp_handler;
1757aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		ret = handler(shost, rphy, req);
1762d507a01dac338831266b44ccbb01c69e84606edJames Bottomley		req->errors = ret;
1777aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
1787aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		spin_lock_irq(q->queue_lock);
1797aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
1807aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		req->end_io(req, ret);
1817aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	}
1827aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori}
1837aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
1847aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonoristatic void sas_host_smp_request(struct request_queue *q)
1857aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori{
1867aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL);
1877aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori}
1887aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
1897aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonoristatic void sas_non_host_smp_request(struct request_queue *q)
1907aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori{
1917aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	struct sas_rphy *rphy = q->queuedata;
1927aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	sas_smp_request(q, rphy_to_shost(rphy), rphy);
1937aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori}
1947aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
19593c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonoristatic void sas_host_release(struct device *dev)
19693c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori{
19793c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori	struct Scsi_Host *shost = dev_to_shost(dev);
19893c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
19993c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori	struct request_queue *q = sas_host->q;
20093c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori
20193c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori	if (q)
20293c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori		blk_cleanup_queue(q);
20393c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori}
20493c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori
20539dca558a5b52b63e49bc234a7e887be092aa690James Bottomleystatic int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
2067aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori{
2077aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	struct request_queue *q;
2087aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	int error;
20939dca558a5b52b63e49bc234a7e887be092aa690James Bottomley	struct device *dev;
21039dca558a5b52b63e49bc234a7e887be092aa690James Bottomley	char namebuf[BUS_ID_SIZE];
21139dca558a5b52b63e49bc234a7e887be092aa690James Bottomley	const char *name;
21293c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori	void (*release)(struct device *);
2137aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
2147aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	if (!to_sas_internal(shost->transportt)->f->smp_handler) {
2157aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		printk("%s can't handle SMP requests\n", shost->hostt->name);
2167aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		return 0;
2177aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	}
2187aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
21939dca558a5b52b63e49bc234a7e887be092aa690James Bottomley	if (rphy) {
2207aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		q = blk_init_queue(sas_non_host_smp_request, NULL);
22139dca558a5b52b63e49bc234a7e887be092aa690James Bottomley		dev = &rphy->dev;
22239dca558a5b52b63e49bc234a7e887be092aa690James Bottomley		name = dev->bus_id;
22393c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori		release = NULL;
22439dca558a5b52b63e49bc234a7e887be092aa690James Bottomley	} else {
2257aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		q = blk_init_queue(sas_host_smp_request, NULL);
22639dca558a5b52b63e49bc234a7e887be092aa690James Bottomley		dev = &shost->shost_gendev;
22739dca558a5b52b63e49bc234a7e887be092aa690James Bottomley		snprintf(namebuf, sizeof(namebuf),
22839dca558a5b52b63e49bc234a7e887be092aa690James Bottomley			 "sas_host%d", shost->host_no);
22939dca558a5b52b63e49bc234a7e887be092aa690James Bottomley		name = namebuf;
23093c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori		release = sas_host_release;
23139dca558a5b52b63e49bc234a7e887be092aa690James Bottomley	}
2327aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	if (!q)
2337aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		return -ENOMEM;
2347aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
23593c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori	error = bsg_register_queue(q, dev, name, release);
2367aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	if (error) {
2377aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		blk_cleanup_queue(q);
2387aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		return -ENOMEM;
2397aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	}
2407aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
2417aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	if (rphy)
242b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley		rphy->q = q;
243b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	else
244b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley		to_sas_host_attrs(shost)->q = q;
245b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley
246b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	if (rphy)
2477aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		q->queuedata = rphy;
2487aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	else
2497aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		q->queuedata = shost;
2507aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
25175ad23bc0fcb4f992a5d06982bf0857ab1738e9eNick Piggin	queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
2527aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori	return 0;
2537aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori}
2547aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
255b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomleystatic void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
256b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley{
257b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	struct request_queue *q;
258b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley
259b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	if (rphy)
260b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley		q = rphy->q;
261b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	else
262b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley		q = to_sas_host_attrs(shost)->q;
263b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley
264b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	if (!q)
265b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley		return;
266b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley
267b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	bsg_unregister_queue(q);
268b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley}
269b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley
270c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/*
271c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS host attributes
272c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
273c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
27437be6eeb4990c05fc7dd683ceaf1501d46ebe9a4James Bottomleystatic int sas_host_setup(struct transport_container *tc, struct device *dev,
275ee959b00c335d7780136c5abda37809191fe52c3Tony Jones			  struct device *cdev)
276c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
277c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct Scsi_Host *shost = dev_to_shost(dev);
278c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
279c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
280c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	INIT_LIST_HEAD(&sas_host->rphy_list);
281e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig	mutex_init(&sas_host->lock);
282c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	sas_host->next_target_id = 0;
28379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	sas_host->next_expander_id = 0;
284c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	sas_host->next_port_id = 0;
2857aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
28639dca558a5b52b63e49bc234a7e887be092aa690James Bottomley	if (sas_bsg_initialize(shost, NULL))
2877aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori		dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n",
2887aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori			   shost->host_no);
2897aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori
290c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return 0;
291c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
292c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
293b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomleystatic int sas_host_remove(struct transport_container *tc, struct device *dev,
294ee959b00c335d7780136c5abda37809191fe52c3Tony Jones			   struct device *cdev)
295b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley{
296b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	struct Scsi_Host *shost = dev_to_shost(dev);
297b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley
298b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	sas_bsg_remove(shost, NULL);
299b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley
300b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	return 0;
301b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley}
302b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley
303c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_host_class,
304b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley		"sas_host", sas_host_setup, sas_host_remove, NULL);
305c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
306c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_host_match(struct attribute_container *cont,
307c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig			    struct device *dev)
308c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
309c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct Scsi_Host *shost;
310c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_internal *i;
311c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
312c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!scsi_is_host_device(dev))
313c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return 0;
314c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	shost = dev_to_shost(dev);
315c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
316c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!shost->transportt)
317c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return 0;
318c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (shost->transportt->host_attrs.ac.class !=
319c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig			&sas_host_class.class)
320c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return 0;
321c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
322c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i = to_sas_internal(shost->transportt);
323c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return &i->t.host_attrs.ac == cont;
324c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
325c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
326c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int do_sas_phy_delete(struct device *dev, void *data)
327c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
32865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	int pass = (int)(unsigned long)data;
32965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
33065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (pass == 0 && scsi_is_sas_port(dev))
33165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		sas_port_delete(dev_to_sas_port(dev));
33265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	else if (pass == 1 && scsi_is_sas_phy(dev))
333c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		sas_phy_delete(dev_to_phy(dev));
334c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return 0;
335c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
336c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
337c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
338eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_remove_children  -  tear down a devices SAS data structures
33965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @dev:	device belonging to the sas object
34065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
34165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Removes all SAS PHYs and remote PHYs for a given object
34265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */
34365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_remove_children(struct device *dev)
34465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
34565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	device_for_each_child(dev, (void *)0, do_sas_phy_delete);
34665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	device_for_each_child(dev, (void *)1, do_sas_phy_delete);
34765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
34865c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_remove_children);
34965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
35065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/**
351eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_remove_host  -  tear down a Scsi_Host's SAS data structures
352c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @shost:	Scsi Host that is torn down
353c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
354c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes all SAS PHYs and remote PHYs for a given Scsi_Host.
355c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Must be called just before scsi_remove_host for SAS HBAs.
356c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
357c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_remove_host(struct Scsi_Host *shost)
358c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
35965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	sas_remove_children(&shost->shost_gendev);
360c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
361c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_remove_host);
362c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
363c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
364c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/*
36565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * SAS Phy attributes
366c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
367c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
368c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_simple(field, name, format_string, cast)		\
369c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t								\
370ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_phy_##name(struct device *dev, 				\
371ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		    struct device_attribute *attr, char *buf)		\
372c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{									\
373ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_phy *phy = transport_class_to_phy(dev);		\
374c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig									\
375c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return snprintf(buf, 20, format_string, cast phy->field);	\
376c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
377c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
378c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_simple_attr(field, name, format_string, type)		\
379c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	sas_phy_show_simple(field, name, format_string, (type))	\
380ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
381c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
382c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_protocol(field, name)				\
383c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t								\
384ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_phy_##name(struct device *dev, 				\
385ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		    struct device_attribute *attr, char *buf)		\
386c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{									\
387ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_phy *phy = transport_class_to_phy(dev);		\
388c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig									\
389c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!phy->field)						\
390c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return snprintf(buf, 20, "none\n");			\
391c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return get_sas_protocol_names(phy->field, buf);		\
392c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
393c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
394c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_protocol_attr(field, name)				\
395c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	sas_phy_show_protocol(field, name)				\
396ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
397c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
398c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_linkspeed(field)					\
399c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t								\
400ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_phy_##field(struct device *dev, 				\
401ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		     struct device_attribute *attr, char *buf)		\
402c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{									\
403ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_phy *phy = transport_class_to_phy(dev);		\
404c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig									\
405c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return get_sas_linkspeed_names(phy->field, buf);		\
406c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
407c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
408d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley/* Fudge to tell if we're minimum or maximum */
409d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define sas_phy_store_linkspeed(field)					\
410d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleystatic ssize_t								\
411ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstore_sas_phy_##field(struct device *dev, 				\
412ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		      struct device_attribute *attr, 			\
413ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		      const char *buf,	size_t count)			\
414d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley{									\
415ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_phy *phy = transport_class_to_phy(dev);		\
416d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);	\
417d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	struct sas_internal *i = to_sas_internal(shost->transportt);	\
418d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	u32 value;							\
419d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	struct sas_phy_linkrates rates = {0};				\
420d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	int error;							\
421d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley									\
422d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	error = set_sas_linkspeed_names(&value, buf);			\
423d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	if (error)							\
424d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley		return error;						\
425d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	rates.field = value;						\
426d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	error = i->f->set_phy_speed(phy, &rates);			\
427d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley									\
428d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	return error ? error : count;					\
429d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley}
430d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley
431d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define sas_phy_linkspeed_rw_attr(field)				\
432d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	sas_phy_show_linkspeed(field)					\
433d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	sas_phy_store_linkspeed(field)					\
434ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field,		\
435d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	store_sas_phy_##field)
436d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley
437c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_linkspeed_attr(field)					\
438c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	sas_phy_show_linkspeed(field)					\
439ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
440c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
441d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley
442c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig#define sas_phy_show_linkerror(field)					\
443c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigstatic ssize_t								\
444ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_phy_##field(struct device *dev, 				\
445ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		     struct device_attribute *attr, char *buf)		\
446c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig{									\
447ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_phy *phy = transport_class_to_phy(dev);		\
448c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);	\
449c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig	struct sas_internal *i = to_sas_internal(shost->transportt);	\
450c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig	int error;							\
451c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig									\
452dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley	error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0;	\
453c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig	if (error)							\
454c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig		return error;						\
455c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig	return snprintf(buf, 20, "%u\n", phy->field);			\
456c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig}
457c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig
458c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig#define sas_phy_linkerror_attr(field)					\
459c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig	sas_phy_show_linkerror(field)					\
460ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
461c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig
462c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig
463c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t
464ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_device_type(struct device *dev,
465ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		     struct device_attribute *attr, char *buf)
466c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
467ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_phy *phy = transport_class_to_phy(dev);
468c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
469c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!phy->identify.device_type)
470c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return snprintf(buf, 20, "none\n");
471c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return get_sas_device_type_names(phy->identify.device_type, buf);
472c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
473ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
474c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
475ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t do_sas_phy_enable(struct device *dev,
476acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong		size_t count, int enable)
477acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong{
478ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_phy *phy = transport_class_to_phy(dev);
479acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
480acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	struct sas_internal *i = to_sas_internal(shost->transportt);
481acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	int error;
482acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong
483acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	error = i->f->phy_enable(phy, enable);
484acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	if (error)
485acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong		return error;
486acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	phy->enabled = enable;
487acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	return count;
488acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong};
489acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong
490ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t
491ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstore_sas_phy_enable(struct device *dev, struct device_attribute *attr,
492ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		     const char *buf, size_t count)
493acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong{
494acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	if (count < 1)
495acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong		return -EINVAL;
496acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong
497acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	switch (buf[0]) {
498acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	case '0':
499ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		do_sas_phy_enable(dev, count, 0);
500acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong		break;
501acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	case '1':
502ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		do_sas_phy_enable(dev, count, 1);
503acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong		break;
504acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	default:
505acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong		return -EINVAL;
506acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	}
507acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong
508acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	return count;
509acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong}
510acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong
511ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t
512ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_phy_enable(struct device *dev, struct device_attribute *attr,
513ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		    char *buf)
514acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong{
515ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_phy *phy = transport_class_to_phy(dev);
516acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong
517acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	return snprintf(buf, 20, "%d", phy->enabled);
518acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong}
519acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong
520ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
521acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong			 store_sas_phy_enable);
522acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong
523ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t
524ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesdo_sas_phy_reset(struct device *dev, size_t count, int hard_reset)
52507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{
526ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_phy *phy = transport_class_to_phy(dev);
52707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
52807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig	struct sas_internal *i = to_sas_internal(shost->transportt);
52907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig	int error;
53007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig
53107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig	error = i->f->phy_reset(phy, hard_reset);
53207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig	if (error)
53307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig		return error;
53407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig	return count;
53507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig};
53607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig
537ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t
538ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstore_sas_link_reset(struct device *dev, struct device_attribute *attr,
539ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		     const char *buf, size_t count)
54007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{
541ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	return do_sas_phy_reset(dev, count, 0);
54207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig}
543ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset);
54407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig
545ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t
546ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstore_sas_hard_reset(struct device *dev, struct device_attribute *attr,
547ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		     const char *buf, size_t count)
54807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{
549ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	return do_sas_phy_reset(dev, count, 1);
55007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig}
551ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset);
55207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig
553c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.initiator_port_protocols,
554c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		initiator_port_protocols);
555c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.target_port_protocols,
556c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		target_port_protocols);
557c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
558c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		unsigned long long);
559c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
560c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int);
561c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(negotiated_linkrate);
562c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(minimum_linkrate_hw);
563d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_phy_linkspeed_rw_attr(minimum_linkrate);
564c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(maximum_linkrate_hw);
565d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_phy_linkspeed_rw_attr(maximum_linkrate);
566c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(invalid_dword_count);
567c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(running_disparity_error_count);
568c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(loss_of_dword_sync_count);
569c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(phy_reset_problem_count);
570c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
571c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
572c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_phy_class,
573c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		"sas_phy", NULL, NULL, NULL);
574c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
575c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_phy_match(struct attribute_container *cont, struct device *dev)
576c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
577c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct Scsi_Host *shost;
578c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_internal *i;
579c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
580c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!scsi_is_sas_phy(dev))
581c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return 0;
582c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	shost = dev_to_shost(dev->parent);
583c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
584c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!shost->transportt)
585c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return 0;
586c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (shost->transportt->host_attrs.ac.class !=
587c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig			&sas_host_class.class)
588c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return 0;
589c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
590c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i = to_sas_internal(shost->transportt);
591c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return &i->phy_attr_cont.ac == cont;
592c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
593c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
594c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void sas_phy_release(struct device *dev)
595c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
596c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_phy *phy = dev_to_phy(dev);
597c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
598c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	put_device(dev->parent);
599c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	kfree(phy);
600c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
601c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
602c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
603eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_alloc  -  allocates and initialize a SAS PHY structure
604c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @parent:	Parent device
605d99ca4180fe44ae7f409fc73f1a09f270b8d458aMoore, Eric * @number:	Phy index
606c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
607c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Allocates an SAS PHY structure.  It will be added in the device tree
608c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * below the device specified by @parent, which has to be either a Scsi_Host
609c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * or sas_rphy.
610c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
611c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns:
612c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *	SAS PHY allocated or %NULL if the allocation failed.
613c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
614c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_phy *sas_phy_alloc(struct device *parent, int number)
615c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
616c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct Scsi_Host *shost = dev_to_shost(parent);
617c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_phy *phy;
618c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
61924669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
620c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!phy)
621c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return NULL;
622c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
623c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	phy->number = number;
624acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	phy->enabled = 1;
625c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
626c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	device_initialize(&phy->dev);
627c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	phy->dev.parent = get_device(parent);
628c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	phy->dev.release = sas_phy_release;
62965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	INIT_LIST_HEAD(&phy->port_siblings);
63079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	if (scsi_is_sas_expander_device(parent)) {
63179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley		struct sas_rphy *rphy = dev_to_rphy(parent);
63265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		sprintf(phy->dev.bus_id, "phy-%d:%d:%d", shost->host_no,
63379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley			rphy->scsi_target_id, number);
63479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	} else
63579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley		sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number);
636c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
637c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_setup_device(&phy->dev);
638c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
639c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return phy;
640c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
641c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_alloc);
642c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
643c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
644eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_add  -  add a SAS PHY to the device hierarchy
645c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy:	The PHY to be added
646c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
647c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS PHY to the rest of the system.
648c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
649c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_phy_add(struct sas_phy *phy)
650c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
651c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	int error;
652c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
653c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	error = device_add(&phy->dev);
654c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!error) {
655c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		transport_add_device(&phy->dev);
656c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		transport_configure_device(&phy->dev);
657c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	}
658c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
659c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return error;
660c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
661c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_add);
662c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
663c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
664eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_free  -  free a SAS PHY
665c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy:	SAS PHY to free
666c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
667c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS PHY.
668c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
669c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note:
670c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *   This function must only be called on a PHY that has not
671c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *   sucessfully been added using sas_phy_add().
672c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
673c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_phy_free(struct sas_phy *phy)
674c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
675c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_destroy_device(&phy->dev);
67692aab6464be735139f9ea38fd039c3b84c722630Mike Anderson	put_device(&phy->dev);
677c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
678c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_free);
679c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
680c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
681eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_delete  -  remove SAS PHY
682c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy:	SAS PHY to remove
683c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
684c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes the specified SAS PHY.  If the SAS PHY has an
685c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * associated remote PHY it is removed before.
686c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
687c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid
688c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_delete(struct sas_phy *phy)
689c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
690c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct device *dev = &phy->dev;
691c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
69265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	/* this happens if the phy is still part of a port when deleted */
69365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	BUG_ON(!list_empty(&phy->port_siblings));
694c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
695c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_remove_device(dev);
696c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	device_del(dev);
697c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_destroy_device(dev);
69892aab6464be735139f9ea38fd039c3b84c722630Mike Anderson	put_device(dev);
699c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
700c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_delete);
701c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
702c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
703eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * scsi_is_sas_phy  -  check if a struct device represents a SAS PHY
704c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev:	device to check
705c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
706c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns:
707c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *	%1 if the device represents a SAS PHY, %0 else
708c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
709c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_phy(const struct device *dev)
710c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
711c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return dev->release == sas_phy_release;
712c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
713c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_phy);
714c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
715c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/*
71665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * SAS Port attributes
71765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */
71865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define sas_port_show_simple(field, name, format_string, cast)		\
71965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic ssize_t								\
720ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_port_##name(struct device *dev, 				\
721ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		     struct device_attribute *attr, char *buf)		\
72265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{									\
723ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_port *port = transport_class_to_sas_port(dev);	\
72465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley									\
72565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	return snprintf(buf, 20, format_string, cast port->field);	\
72665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
72765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
72865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define sas_port_simple_attr(field, name, format_string, type)		\
72965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	sas_port_show_simple(field, name, format_string, (type))	\
730ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
73165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
73265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleysas_port_simple_attr(num_phys, num_phys, "%d\n", int);
73365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
73465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_port_class,
73565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley			       "sas_port", NULL, NULL, NULL);
73665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
73765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic int sas_port_match(struct attribute_container *cont, struct device *dev)
73865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
73965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	struct Scsi_Host *shost;
74065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	struct sas_internal *i;
74165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
74265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (!scsi_is_sas_port(dev))
74365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		return 0;
74465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	shost = dev_to_shost(dev->parent);
74565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
74665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (!shost->transportt)
74765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		return 0;
74865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (shost->transportt->host_attrs.ac.class !=
74965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley			&sas_host_class.class)
75065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		return 0;
75165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
75265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	i = to_sas_internal(shost->transportt);
75365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	return &i->port_attr_cont.ac == cont;
75465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
75565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
75665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
75765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_release(struct device *dev)
75865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
75965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	struct sas_port *port = dev_to_sas_port(dev);
76065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
76165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	BUG_ON(!list_empty(&port->phy_list));
76265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
76365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	put_device(dev->parent);
76465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	kfree(port);
76565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
76665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
76765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_create_link(struct sas_port *port,
76865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley				 struct sas_phy *phy)
76965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
77021434966462d57145c861b43f6206d945ac57630Darrick J. Wong	int res;
77121434966462d57145c861b43f6206d945ac57630Darrick J. Wong
77221434966462d57145c861b43f6206d945ac57630Darrick J. Wong	res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj,
77321434966462d57145c861b43f6206d945ac57630Darrick J. Wong				phy->dev.bus_id);
77421434966462d57145c861b43f6206d945ac57630Darrick J. Wong	if (res)
77521434966462d57145c861b43f6206d945ac57630Darrick J. Wong		goto err;
77621434966462d57145c861b43f6206d945ac57630Darrick J. Wong	res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port");
77721434966462d57145c861b43f6206d945ac57630Darrick J. Wong	if (res)
77821434966462d57145c861b43f6206d945ac57630Darrick J. Wong		goto err;
77921434966462d57145c861b43f6206d945ac57630Darrick J. Wong	return;
78021434966462d57145c861b43f6206d945ac57630Darrick J. Wongerr:
78121434966462d57145c861b43f6206d945ac57630Darrick J. Wong	printk(KERN_ERR "%s: Cannot create port links, err=%d\n",
78221434966462d57145c861b43f6206d945ac57630Darrick J. Wong	       __FUNCTION__, res);
78365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
78465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
78565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_delete_link(struct sas_port *port,
78665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley				 struct sas_phy *phy)
78765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
78865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	sysfs_remove_link(&port->dev.kobj, phy->dev.bus_id);
78965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	sysfs_remove_link(&phy->dev.kobj, "port");
79065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
79165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
79265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** sas_port_alloc - allocate and initialize a SAS port structure
79365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
79465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @parent:	parent device
79565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port_id:	port number
79665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
79765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Allocates a SAS port structure.  It will be added to the device tree
79865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * below the device specified by @parent which must be either a Scsi_Host
79965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * or a sas_expander_device.
80065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
80165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns %NULL on error
80265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */
80365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_port *sas_port_alloc(struct device *parent, int port_id)
80465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
80565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	struct Scsi_Host *shost = dev_to_shost(parent);
80665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	struct sas_port *port;
80765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
80865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	port = kzalloc(sizeof(*port), GFP_KERNEL);
80965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (!port)
81065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		return NULL;
81165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
81265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	port->port_identifier = port_id;
81365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
81465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	device_initialize(&port->dev);
81565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
81665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	port->dev.parent = get_device(parent);
81765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	port->dev.release = sas_port_release;
81865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
81965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	mutex_init(&port->phy_list_mutex);
82065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	INIT_LIST_HEAD(&port->phy_list);
82165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
82265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (scsi_is_sas_expander_device(parent)) {
82365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		struct sas_rphy *rphy = dev_to_rphy(parent);
82465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		sprintf(port->dev.bus_id, "port-%d:%d:%d", shost->host_no,
82565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley			rphy->scsi_target_id, port->port_identifier);
82665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	} else
82765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		sprintf(port->dev.bus_id, "port-%d:%d", shost->host_no,
82865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley			port->port_identifier);
82965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
83065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	transport_setup_device(&port->dev);
83165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
83265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	return port;
83365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
83465c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_alloc);
83565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
836c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley/** sas_port_alloc_num - allocate and initialize a SAS port structure
837c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley *
838c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * @parent:	parent device
839c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley *
840c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Allocates a SAS port structure and a number to go with it.  This
841c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * interface is really for adapters where the port number has no
842c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * meansing, so the sas class should manage them.  It will be added to
843c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * the device tree below the device specified by @parent which must be
844c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * either a Scsi_Host or a sas_expander_device.
845c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley *
846c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Returns %NULL on error
847c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley */
848c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomleystruct sas_port *sas_port_alloc_num(struct device *parent)
849c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley{
850c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	int index;
851c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	struct Scsi_Host *shost = dev_to_shost(parent);
852c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
853c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley
854c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	/* FIXME: use idr for this eventually */
855c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	mutex_lock(&sas_host->lock);
856c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	if (scsi_is_sas_expander_device(parent)) {
857c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley		struct sas_rphy *rphy = dev_to_rphy(parent);
858c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley		struct sas_expander_device *exp = rphy_to_expander_device(rphy);
859c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley
860c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley		index = exp->next_port_id++;
861c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	} else
862c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley		index = sas_host->next_port_id++;
863c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	mutex_unlock(&sas_host->lock);
864c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley	return sas_port_alloc(parent, index);
865c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley}
866c9fefeb26457b87f4a767faefcf77321bb90db52James BottomleyEXPORT_SYMBOL(sas_port_alloc_num);
867c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley
86865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/**
86965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add - add a SAS port to the device hierarchy
87065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port:	port to be added
87165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
87265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * publishes a port to the rest of the system
87365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */
87465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint sas_port_add(struct sas_port *port)
87565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
87665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	int error;
87765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
87865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	/* No phys should be added until this is made visible */
87965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	BUG_ON(!list_empty(&port->phy_list));
88065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
88165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	error = device_add(&port->dev);
88265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
88365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (error)
88465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		return error;
88565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
88665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	transport_add_device(&port->dev);
88765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	transport_configure_device(&port->dev);
88865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
88965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	return 0;
89065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
89165c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add);
89265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
89365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/**
894eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_port_free  -  free a SAS PORT
89565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port:	SAS PORT to free
89665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
89765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Frees the specified SAS PORT.
89865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
89965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Note:
90065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *   This function must only be called on a PORT that has not
90165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *   sucessfully been added using sas_port_add().
90265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */
90365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_free(struct sas_port *port)
90465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
90565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	transport_destroy_device(&port->dev);
90665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	put_device(&port->dev);
90765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
90865c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_free);
90965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
91065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/**
911eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_port_delete  -  remove SAS PORT
91265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port:	SAS PORT to remove
91365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
91465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Removes the specified SAS PORT.  If the SAS PORT has an
91565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * associated phys, unlink them from the port as well.
91665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */
91765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete(struct sas_port *port)
91865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
91965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	struct device *dev = &port->dev;
92065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	struct sas_phy *phy, *tmp_phy;
92165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
92265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (port->rphy) {
92365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		sas_rphy_delete(port->rphy);
92465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		port->rphy = NULL;
92565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	}
92665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
92765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	mutex_lock(&port->phy_list_mutex);
92865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	list_for_each_entry_safe(phy, tmp_phy, &port->phy_list,
92965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley				 port_siblings) {
93065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		sas_port_delete_link(port, phy);
93165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		list_del_init(&phy->port_siblings);
93265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	}
93365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	mutex_unlock(&port->phy_list_mutex);
93465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
935a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley	if (port->is_backlink) {
936a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley		struct device *parent = port->dev.parent;
937a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley
938a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley		sysfs_remove_link(&port->dev.kobj, parent->bus_id);
939a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley		port->is_backlink = 0;
940a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley	}
941a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley
94265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	transport_remove_device(dev);
94365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	device_del(dev);
94465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	transport_destroy_device(dev);
94565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	put_device(dev);
94665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
94765c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete);
94865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
94965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/**
950eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * scsi_is_sas_port -  check if a struct device represents a SAS port
95165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @dev:	device to check
95265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
95365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns:
95465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *	%1 if the device represents a SAS Port, %0 else
95565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */
95665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint scsi_is_sas_port(const struct device *dev)
95765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
95865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	return dev->release == sas_port_release;
95965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
96065c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(scsi_is_sas_port);
96165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
96265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/**
96365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add_phy - add another phy to a port to form a wide port
96465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port:	port to add the phy to
96565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy:	phy to add
96665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
96765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * When a port is initially created, it is empty (has no phys).  All
96865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * ports must have at least one phy to operated, and all wide ports
96965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * must have at least two.  The current code makes no difference
97065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * between ports and wide ports, but the only object that can be
97165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * connected to a remote device is a port, so ports must be formed on
97265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * all devices with phys if they're connected to anything.
97365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */
97465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_add_phy(struct sas_port *port, struct sas_phy *phy)
97565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
97665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	mutex_lock(&port->phy_list_mutex);
97765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (unlikely(!list_empty(&phy->port_siblings))) {
97865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		/* make sure we're already on this port */
97965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		struct sas_phy *tmp;
98065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
98165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		list_for_each_entry(tmp, &port->phy_list, port_siblings)
98265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley			if (tmp == phy)
98365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley				break;
98465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		/* If this trips, you added a phy that was already
98565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		 * part of a different port */
98665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		if (unlikely(tmp != phy)) {
98765c92b09acf0218b64f1c7ba4fdabeb8b732c876James 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);
98865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley			BUG();
98965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		}
99065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	} else {
99165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		sas_port_create_link(port, phy);
99265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		list_add_tail(&phy->port_siblings, &port->phy_list);
99365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		port->num_phys++;
99465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	}
99565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	mutex_unlock(&port->phy_list_mutex);
99665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
99765c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add_phy);
99865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
99965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/**
100065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_delete_phy - remove a phy from a port or wide port
100165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port:	port to remove the phy from
100265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy:	phy to remove
100365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley *
100465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This operation is used for tearing down ports again.  It must be
100565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * done to every port or wide port before calling sas_port_delete.
100665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */
100765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy)
100865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{
100965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	mutex_lock(&port->phy_list_mutex);
101065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	sas_port_delete_link(port, phy);
101165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	list_del_init(&phy->port_siblings);
101265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	port->num_phys--;
101365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	mutex_unlock(&port->phy_list_mutex);
101465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley}
101565c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete_phy);
101665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
1017a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomleyvoid sas_port_mark_backlink(struct sas_port *port)
1018a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley{
101921434966462d57145c861b43f6206d945ac57630Darrick J. Wong	int res;
1020a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley	struct device *parent = port->dev.parent->parent->parent;
1021a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley
1022a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley	if (port->is_backlink)
1023a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley		return;
1024a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley	port->is_backlink = 1;
102521434966462d57145c861b43f6206d945ac57630Darrick J. Wong	res = sysfs_create_link(&port->dev.kobj, &parent->kobj,
102621434966462d57145c861b43f6206d945ac57630Darrick J. Wong				parent->bus_id);
102721434966462d57145c861b43f6206d945ac57630Darrick J. Wong	if (res)
102821434966462d57145c861b43f6206d945ac57630Darrick J. Wong		goto err;
102921434966462d57145c861b43f6206d945ac57630Darrick J. Wong	return;
103021434966462d57145c861b43f6206d945ac57630Darrick J. Wongerr:
103121434966462d57145c861b43f6206d945ac57630Darrick J. Wong	printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n",
103221434966462d57145c861b43f6206d945ac57630Darrick J. Wong	       __FUNCTION__, res);
1033a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley
1034a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley}
1035a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames BottomleyEXPORT_SYMBOL(sas_port_mark_backlink);
1036a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley
103765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/*
1038c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS remote PHY attributes.
1039c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
1040c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1041c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_simple(field, name, format_string, cast)		\
1042c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t								\
1043ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_##name(struct device *dev, 				\
1044ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		     struct device_attribute *attr, char *buf)		\
1045c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{									\
1046ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\
1047c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig									\
1048c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return snprintf(buf, 20, format_string, cast rphy->field);	\
1049c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1050c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1051c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_simple_attr(field, name, format_string, type)		\
1052c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	sas_rphy_show_simple(field, name, format_string, (type))	\
1053ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, name, S_IRUGO, 			\
1054c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		show_sas_rphy_##name, NULL)
1055c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1056c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_protocol(field, name)				\
1057c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t								\
1058ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_##name(struct device *dev, 				\
1059ee959b00c335d7780136c5abda37809191fe52c3Tony Jones		     struct device_attribute *attr, char *buf)		\
1060c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{									\
1061ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\
1062c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig									\
1063c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!rphy->field)					\
1064c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return snprintf(buf, 20, "none\n");			\
1065c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return get_sas_protocol_names(rphy->field, buf);	\
1066c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1067c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1068c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_protocol_attr(field, name)				\
1069c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	sas_rphy_show_protocol(field, name)				\
1070ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, name, S_IRUGO,			\
1071c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		show_sas_rphy_##name, NULL)
1072c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1073c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t
1074ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_device_type(struct device *dev,
1075ee959b00c335d7780136c5abda37809191fe52c3Tony Jones			  struct device_attribute *attr, char *buf)
1076c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
1077ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_rphy *rphy = transport_class_to_rphy(dev);
1078c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1079c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!rphy->identify.device_type)
1080c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return snprintf(buf, 20, "none\n");
1081c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return get_sas_device_type_names(
1082c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig			rphy->identify.device_type, buf);
1083c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1084c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1085ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
1086c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		show_sas_rphy_device_type, NULL);
1087c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1088a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t
1089ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_enclosure_identifier(struct device *dev,
1090ee959b00c335d7780136c5abda37809191fe52c3Tony Jones				   struct device_attribute *attr, char *buf)
1091a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{
1092ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_rphy *rphy = transport_class_to_rphy(dev);
1093a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	struct sas_phy *phy = dev_to_phy(rphy->dev.parent);
1094a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1095a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	struct sas_internal *i = to_sas_internal(shost->transportt);
1096a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	u64 identifier;
1097a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	int error;
1098a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig
1099a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	/*
1100a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	 * Only devices behind an expander are supported, because the
1101a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	 * enclosure identifier is a SMP feature.
1102a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	 */
1103f4ad7b5807385ad1fed0347d966e51a797cd1013James Bottomley	if (scsi_is_sas_phy_local(phy))
1104a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig		return -EINVAL;
1105a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig
1106a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	error = i->f->get_enclosure_identifier(rphy, &identifier);
1107a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	if (error)
1108a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig		return error;
1109a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	return sprintf(buf, "0x%llx\n", (unsigned long long)identifier);
1110a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig}
1111a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig
1112ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO,
1113a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig		show_sas_rphy_enclosure_identifier, NULL);
1114a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig
1115a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t
1116ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_bay_identifier(struct device *dev,
1117ee959b00c335d7780136c5abda37809191fe52c3Tony Jones			     struct device_attribute *attr, char *buf)
1118a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{
1119ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_rphy *rphy = transport_class_to_rphy(dev);
1120a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	struct sas_phy *phy = dev_to_phy(rphy->dev.parent);
1121a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1122a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	struct sas_internal *i = to_sas_internal(shost->transportt);
1123a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	int val;
1124a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig
1125f4ad7b5807385ad1fed0347d966e51a797cd1013James Bottomley	if (scsi_is_sas_phy_local(phy))
1126a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig		return -EINVAL;
1127a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig
1128a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	val = i->f->get_bay_identifier(rphy);
1129a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	if (val < 0)
1130a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig		return val;
1131a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig	return sprintf(buf, "%d\n", val);
1132a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig}
1133a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig
1134ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO,
1135a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig		show_sas_rphy_bay_identifier, NULL);
1136a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig
1137c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.initiator_port_protocols,
1138c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		initiator_port_protocols);
1139c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols);
1140c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
1141c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		unsigned long long);
1142c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
1143c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
114442ab03609cca4ef5079e248296f015650c626899James Bottomley/* only need 8 bytes of data plus header (4 or 8) */
114542ab03609cca4ef5079e248296f015650c626899James Bottomley#define BUF_SIZE 64
114642ab03609cca4ef5079e248296f015650c626899James Bottomley
114742ab03609cca4ef5079e248296f015650c626899James Bottomleyint sas_read_port_mode_page(struct scsi_device *sdev)
114842ab03609cca4ef5079e248296f015650c626899James Bottomley{
114942ab03609cca4ef5079e248296f015650c626899James Bottomley	char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata;
115042ab03609cca4ef5079e248296f015650c626899James Bottomley	struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target);
115142ab03609cca4ef5079e248296f015650c626899James Bottomley	struct sas_end_device *rdev;
115242ab03609cca4ef5079e248296f015650c626899James Bottomley	struct scsi_mode_data mode_data;
115342ab03609cca4ef5079e248296f015650c626899James Bottomley	int res, error;
115442ab03609cca4ef5079e248296f015650c626899James Bottomley
115542ab03609cca4ef5079e248296f015650c626899James Bottomley	BUG_ON(rphy->identify.device_type != SAS_END_DEVICE);
115642ab03609cca4ef5079e248296f015650c626899James Bottomley
115742ab03609cca4ef5079e248296f015650c626899James Bottomley	rdev = rphy_to_end_device(rphy);
115842ab03609cca4ef5079e248296f015650c626899James Bottomley
115942ab03609cca4ef5079e248296f015650c626899James Bottomley	if (!buffer)
116042ab03609cca4ef5079e248296f015650c626899James Bottomley		return -ENOMEM;
116142ab03609cca4ef5079e248296f015650c626899James Bottomley
116242ab03609cca4ef5079e248296f015650c626899James Bottomley	res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3,
116342ab03609cca4ef5079e248296f015650c626899James Bottomley			      &mode_data, NULL);
116442ab03609cca4ef5079e248296f015650c626899James Bottomley
116542ab03609cca4ef5079e248296f015650c626899James Bottomley	error = -EINVAL;
116642ab03609cca4ef5079e248296f015650c626899James Bottomley	if (!scsi_status_is_good(res))
116742ab03609cca4ef5079e248296f015650c626899James Bottomley		goto out;
116842ab03609cca4ef5079e248296f015650c626899James Bottomley
116942ab03609cca4ef5079e248296f015650c626899James Bottomley	msdata = buffer +  mode_data.header_length +
117042ab03609cca4ef5079e248296f015650c626899James Bottomley		mode_data.block_descriptor_length;
117142ab03609cca4ef5079e248296f015650c626899James Bottomley
117242ab03609cca4ef5079e248296f015650c626899James Bottomley	if (msdata - buffer > BUF_SIZE - 8)
117342ab03609cca4ef5079e248296f015650c626899James Bottomley		goto out;
117442ab03609cca4ef5079e248296f015650c626899James Bottomley
117542ab03609cca4ef5079e248296f015650c626899James Bottomley	error = 0;
117642ab03609cca4ef5079e248296f015650c626899James Bottomley
117742ab03609cca4ef5079e248296f015650c626899James Bottomley	rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0;
117842ab03609cca4ef5079e248296f015650c626899James Bottomley	rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5];
117942ab03609cca4ef5079e248296f015650c626899James Bottomley	rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7];
118042ab03609cca4ef5079e248296f015650c626899James Bottomley
118142ab03609cca4ef5079e248296f015650c626899James Bottomley out:
118242ab03609cca4ef5079e248296f015650c626899James Bottomley	kfree(buffer);
118342ab03609cca4ef5079e248296f015650c626899James Bottomley	return error;
118442ab03609cca4ef5079e248296f015650c626899James Bottomley}
118542ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_read_port_mode_page);
118642ab03609cca4ef5079e248296f015650c626899James Bottomley
118779cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_end_dev_class,
118879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley			       "sas_end_device", NULL, NULL, NULL);
118979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
119042ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_show_simple(field, name, format_string, cast)	\
119142ab03609cca4ef5079e248296f015650c626899James Bottomleystatic ssize_t								\
1192ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_end_dev_##name(struct device *dev, 				\
1193ee959b00c335d7780136c5abda37809191fe52c3Tony Jones			struct device_attribute *attr, char *buf)	\
119442ab03609cca4ef5079e248296f015650c626899James Bottomley{									\
1195ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\
119642ab03609cca4ef5079e248296f015650c626899James Bottomley	struct sas_end_device *rdev = rphy_to_end_device(rphy);		\
119742ab03609cca4ef5079e248296f015650c626899James Bottomley									\
119842ab03609cca4ef5079e248296f015650c626899James Bottomley	return snprintf(buf, 20, format_string, cast rdev->field);	\
119942ab03609cca4ef5079e248296f015650c626899James Bottomley}
120042ab03609cca4ef5079e248296f015650c626899James Bottomley
120142ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_simple_attr(field, name, format_string, type)	\
120242ab03609cca4ef5079e248296f015650c626899James Bottomley	sas_end_dev_show_simple(field, name, format_string, (type))	\
1203ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(end_dev, name, S_IRUGO, 			\
120442ab03609cca4ef5079e248296f015650c626899James Bottomley		show_sas_end_dev_##name, NULL)
120542ab03609cca4ef5079e248296f015650c626899James Bottomley
120642ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int);
120742ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout,
120842ab03609cca4ef5079e248296f015650c626899James Bottomley			"%d\n", int);
120942ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout,
121042ab03609cca4ef5079e248296f015650c626899James Bottomley			"%d\n", int);
121142ab03609cca4ef5079e248296f015650c626899James Bottomley
121279cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_expander_class,
121379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley			       "sas_expander", NULL, NULL, NULL);
121479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
121579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_show_simple(field, name, format_string, cast)	\
121679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic ssize_t								\
1217ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_expander_##name(struct device *dev, 				\
1218ee959b00c335d7780136c5abda37809191fe52c3Tony Jones			 struct device_attribute *attr, char *buf)	\
121979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{									\
1220ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\
122179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	struct sas_expander_device *edev = rphy_to_expander_device(rphy); \
122279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley									\
122379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	return snprintf(buf, 20, format_string, cast edev->field);	\
122479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley}
122579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
122679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_simple_attr(field, name, format_string, type)	\
122779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	sas_expander_show_simple(field, name, format_string, (type))	\
1228ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(expander, name, S_IRUGO, 			\
122979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley		show_sas_expander_##name, NULL)
123079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
123179cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *);
123279cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_id, product_id, "%s\n", char *);
123379cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_rev, product_rev, "%s\n", char *);
123479cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_vendor_id, component_vendor_id,
123579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley			 "%s\n", char *);
123679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int);
123779cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n",
123879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley			 unsigned int);
123979cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(level, level, "%d\n", int);
124042ab03609cca4ef5079e248296f015650c626899James Bottomley
1241c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_rphy_class,
12422f8600dff2b140096a7df781884e918a16aa90e0James Bottomley		"sas_device", NULL, NULL, NULL);
1243c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1244c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_rphy_match(struct attribute_container *cont, struct device *dev)
1245c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
1246c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct Scsi_Host *shost;
1247c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_internal *i;
1248c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1249c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!scsi_is_sas_rphy(dev))
1250c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return 0;
1251c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	shost = dev_to_shost(dev->parent->parent);
1252c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1253c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!shost->transportt)
1254c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return 0;
1255c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (shost->transportt->host_attrs.ac.class !=
1256c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig			&sas_host_class.class)
1257c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return 0;
1258c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1259c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i = to_sas_internal(shost->transportt);
1260c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return &i->rphy_attr_cont.ac == cont;
1261c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1262c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
126342ab03609cca4ef5079e248296f015650c626899James Bottomleystatic int sas_end_dev_match(struct attribute_container *cont,
126442ab03609cca4ef5079e248296f015650c626899James Bottomley			     struct device *dev)
126542ab03609cca4ef5079e248296f015650c626899James Bottomley{
126642ab03609cca4ef5079e248296f015650c626899James Bottomley	struct Scsi_Host *shost;
126742ab03609cca4ef5079e248296f015650c626899James Bottomley	struct sas_internal *i;
126842ab03609cca4ef5079e248296f015650c626899James Bottomley	struct sas_rphy *rphy;
126942ab03609cca4ef5079e248296f015650c626899James Bottomley
127042ab03609cca4ef5079e248296f015650c626899James Bottomley	if (!scsi_is_sas_rphy(dev))
127142ab03609cca4ef5079e248296f015650c626899James Bottomley		return 0;
127242ab03609cca4ef5079e248296f015650c626899James Bottomley	shost = dev_to_shost(dev->parent->parent);
127342ab03609cca4ef5079e248296f015650c626899James Bottomley	rphy = dev_to_rphy(dev);
127442ab03609cca4ef5079e248296f015650c626899James Bottomley
127542ab03609cca4ef5079e248296f015650c626899James Bottomley	if (!shost->transportt)
127642ab03609cca4ef5079e248296f015650c626899James Bottomley		return 0;
127742ab03609cca4ef5079e248296f015650c626899James Bottomley	if (shost->transportt->host_attrs.ac.class !=
127842ab03609cca4ef5079e248296f015650c626899James Bottomley			&sas_host_class.class)
127942ab03609cca4ef5079e248296f015650c626899James Bottomley		return 0;
128042ab03609cca4ef5079e248296f015650c626899James Bottomley
128142ab03609cca4ef5079e248296f015650c626899James Bottomley	i = to_sas_internal(shost->transportt);
128242ab03609cca4ef5079e248296f015650c626899James Bottomley	return &i->end_dev_attr_cont.ac == cont &&
12832f8600dff2b140096a7df781884e918a16aa90e0James Bottomley		rphy->identify.device_type == SAS_END_DEVICE;
128442ab03609cca4ef5079e248296f015650c626899James Bottomley}
128542ab03609cca4ef5079e248296f015650c626899James Bottomley
128679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic int sas_expander_match(struct attribute_container *cont,
128779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley			      struct device *dev)
128879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{
128979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	struct Scsi_Host *shost;
129079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	struct sas_internal *i;
129179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	struct sas_rphy *rphy;
129279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
129379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	if (!scsi_is_sas_rphy(dev))
129479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley		return 0;
129579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	shost = dev_to_shost(dev->parent->parent);
129679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	rphy = dev_to_rphy(dev);
129779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
129879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	if (!shost->transportt)
129979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley		return 0;
130079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	if (shost->transportt->host_attrs.ac.class !=
130179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley			&sas_host_class.class)
130279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley		return 0;
130379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
130479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	i = to_sas_internal(shost->transportt);
130579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	return &i->expander_attr_cont.ac == cont &&
130679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley		(rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
13072f8600dff2b140096a7df781884e918a16aa90e0James Bottomley		 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE);
130879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley}
130979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
13102f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_expander_release(struct device *dev)
1311c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
1312c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_rphy *rphy = dev_to_rphy(dev);
13132f8600dff2b140096a7df781884e918a16aa90e0James Bottomley	struct sas_expander_device *edev = rphy_to_expander_device(rphy);
1314c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
131593c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori	if (rphy->q)
131693c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori		blk_cleanup_queue(rphy->q);
131793c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori
1318c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	put_device(dev->parent);
13192f8600dff2b140096a7df781884e918a16aa90e0James Bottomley	kfree(edev);
1320c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1321c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
13222f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_end_device_release(struct device *dev)
1323c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
13242f8600dff2b140096a7df781884e918a16aa90e0James Bottomley	struct sas_rphy *rphy = dev_to_rphy(dev);
13252f8600dff2b140096a7df781884e918a16aa90e0James Bottomley	struct sas_end_device *edev = rphy_to_end_device(rphy);
1326c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
132793c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori	if (rphy->q)
132893c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori		blk_cleanup_queue(rphy->q);
132993c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori
13302f8600dff2b140096a7df781884e918a16aa90e0James Bottomley	put_device(dev->parent);
13312f8600dff2b140096a7df781884e918a16aa90e0James Bottomley	kfree(edev);
1332c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1333c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1334c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
1335c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * sas_rphy_initialize - common rphy intialization
1336c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * @rphy:	rphy to initialise
1337c5943d36aebb79589ac3983eec418bbeca897573James Bottomley *
1338c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * Used by both sas_end_device_alloc() and sas_expander_alloc() to
1339c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * initialise the common rphy component of each.
1340c5943d36aebb79589ac3983eec418bbeca897573James Bottomley */
1341c5943d36aebb79589ac3983eec418bbeca897573James Bottomleystatic void sas_rphy_initialize(struct sas_rphy *rphy)
1342c5943d36aebb79589ac3983eec418bbeca897573James Bottomley{
1343c5943d36aebb79589ac3983eec418bbeca897573James Bottomley	INIT_LIST_HEAD(&rphy->list);
1344c5943d36aebb79589ac3983eec418bbeca897573James Bottomley}
1345c5943d36aebb79589ac3983eec418bbeca897573James Bottomley
1346c5943d36aebb79589ac3983eec418bbeca897573James Bottomley/**
134742ab03609cca4ef5079e248296f015650c626899James Bottomley * sas_end_device_alloc - allocate an rphy for an end device
1348eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @parent: which port
134942ab03609cca4ef5079e248296f015650c626899James Bottomley *
135042ab03609cca4ef5079e248296f015650c626899James Bottomley * Allocates an SAS remote PHY structure, connected to @parent.
135142ab03609cca4ef5079e248296f015650c626899James Bottomley *
135242ab03609cca4ef5079e248296f015650c626899James Bottomley * Returns:
135342ab03609cca4ef5079e248296f015650c626899James Bottomley *	SAS PHY allocated or %NULL if the allocation failed.
135442ab03609cca4ef5079e248296f015650c626899James Bottomley */
135565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_end_device_alloc(struct sas_port *parent)
135642ab03609cca4ef5079e248296f015650c626899James Bottomley{
135742ab03609cca4ef5079e248296f015650c626899James Bottomley	struct Scsi_Host *shost = dev_to_shost(&parent->dev);
135842ab03609cca4ef5079e248296f015650c626899James Bottomley	struct sas_end_device *rdev;
135942ab03609cca4ef5079e248296f015650c626899James Bottomley
136042ab03609cca4ef5079e248296f015650c626899James Bottomley	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
136142ab03609cca4ef5079e248296f015650c626899James Bottomley	if (!rdev) {
136242ab03609cca4ef5079e248296f015650c626899James Bottomley		return NULL;
136342ab03609cca4ef5079e248296f015650c626899James Bottomley	}
136442ab03609cca4ef5079e248296f015650c626899James Bottomley
136542ab03609cca4ef5079e248296f015650c626899James Bottomley	device_initialize(&rdev->rphy.dev);
136642ab03609cca4ef5079e248296f015650c626899James Bottomley	rdev->rphy.dev.parent = get_device(&parent->dev);
13672f8600dff2b140096a7df781884e918a16aa90e0James Bottomley	rdev->rphy.dev.release = sas_end_device_release;
136865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (scsi_is_sas_expander_device(parent->dev.parent)) {
136965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent);
137065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d:%d",
137165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley			shost->host_no, rphy->scsi_target_id, parent->port_identifier);
137265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	} else
137365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d",
137465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley			shost->host_no, parent->port_identifier);
137542ab03609cca4ef5079e248296f015650c626899James Bottomley	rdev->rphy.identify.device_type = SAS_END_DEVICE;
1376c5943d36aebb79589ac3983eec418bbeca897573James Bottomley	sas_rphy_initialize(&rdev->rphy);
137742ab03609cca4ef5079e248296f015650c626899James Bottomley	transport_setup_device(&rdev->rphy.dev);
137842ab03609cca4ef5079e248296f015650c626899James Bottomley
137942ab03609cca4ef5079e248296f015650c626899James Bottomley	return &rdev->rphy;
138042ab03609cca4ef5079e248296f015650c626899James Bottomley}
138142ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_end_device_alloc);
138242ab03609cca4ef5079e248296f015650c626899James Bottomley
138379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley/**
138479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * sas_expander_alloc - allocate an rphy for an end device
1385eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @parent: which port
1386eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @type: SAS_EDGE_EXPANDER_DEVICE or SAS_FANOUT_EXPANDER_DEVICE
138779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley *
138879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Allocates an SAS remote PHY structure, connected to @parent.
138979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley *
139079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Returns:
139179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley *	SAS PHY allocated or %NULL if the allocation failed.
139279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley */
139365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_expander_alloc(struct sas_port *parent,
139479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley				    enum sas_device_type type)
139579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{
139679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	struct Scsi_Host *shost = dev_to_shost(&parent->dev);
139779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	struct sas_expander_device *rdev;
139879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
139979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
140079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE &&
140179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	       type != SAS_FANOUT_EXPANDER_DEVICE);
140279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
140379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
140479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	if (!rdev) {
140579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley		return NULL;
140679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	}
140779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
140879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	device_initialize(&rdev->rphy.dev);
140979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	rdev->rphy.dev.parent = get_device(&parent->dev);
14102f8600dff2b140096a7df781884e918a16aa90e0James Bottomley	rdev->rphy.dev.release = sas_expander_release;
141179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	mutex_lock(&sas_host->lock);
141279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	rdev->rphy.scsi_target_id = sas_host->next_expander_id++;
141379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	mutex_unlock(&sas_host->lock);
141479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d",
141579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley		shost->host_no, rdev->rphy.scsi_target_id);
141679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	rdev->rphy.identify.device_type = type;
1417c5943d36aebb79589ac3983eec418bbeca897573James Bottomley	sas_rphy_initialize(&rdev->rphy);
141879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	transport_setup_device(&rdev->rphy.dev);
141979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
142079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	return &rdev->rphy;
142179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley}
142279cb1819e231f811211133a09a5382cb89d7ec67James BottomleyEXPORT_SYMBOL(sas_expander_alloc);
142342ab03609cca4ef5079e248296f015650c626899James Bottomley
142442ab03609cca4ef5079e248296f015650c626899James Bottomley/**
1425eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_add  -  add a SAS remote PHY to the device hierarchy
1426c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy:	The remote PHY to be added
1427c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
1428c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS remote PHY to the rest of the system.
1429c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
1430c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_rphy_add(struct sas_rphy *rphy)
1431c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
143265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
1433c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
1434c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1435c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_identify *identify = &rphy->identify;
1436c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	int error;
1437c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1438c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (parent->rphy)
1439c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return -ENXIO;
1440c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	parent->rphy = rphy;
1441c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1442c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	error = device_add(&rphy->dev);
1443c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (error)
1444c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return error;
1445c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_add_device(&rphy->dev);
1446c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_configure_device(&rphy->dev);
144739dca558a5b52b63e49bc234a7e887be092aa690James Bottomley	if (sas_bsg_initialize(shost, rphy))
144839dca558a5b52b63e49bc234a7e887be092aa690James Bottomley		printk("fail to a bsg device %s\n", rphy->dev.bus_id);
144939dca558a5b52b63e49bc234a7e887be092aa690James Bottomley
1450c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1451e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig	mutex_lock(&sas_host->lock);
1452c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	list_add_tail(&rphy->list, &sas_host->rphy_list);
1453c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (identify->device_type == SAS_END_DEVICE &&
1454c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	    (identify->target_port_protocols &
1455c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	     (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))
1456c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		rphy->scsi_target_id = sas_host->next_target_id++;
14577676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley	else if (identify->device_type == SAS_END_DEVICE)
14587676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley		rphy->scsi_target_id = -1;
1459e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig	mutex_unlock(&sas_host->lock);
1460c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
146179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	if (identify->device_type == SAS_END_DEVICE &&
146279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	    rphy->scsi_target_id != -1) {
1463e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley		scsi_scan_target(&rphy->dev, 0,
1464c8490f3a77805d04321d9e44486a679801a035b8Darrick J. Wong				rphy->scsi_target_id, SCAN_WILD_CARD, 0);
1465c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	}
1466c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1467c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return 0;
1468c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1469c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_add);
1470c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1471c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
1472eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_free  -  free a SAS remote PHY
1473eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @rphy: SAS remote PHY to free
1474c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
1475c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS remote PHY.
1476c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
1477c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note:
1478c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *   This function must only be called on a remote
1479c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *   PHY that has not sucessfully been added using
14806f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong *   sas_rphy_add() (or has been sas_rphy_remove()'d)
1481c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
1482c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_rphy_free(struct sas_rphy *rphy)
1483c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
148492aab6464be735139f9ea38fd039c3b84c722630Mike Anderson	struct device *dev = &rphy->dev;
1485c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1486c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1487c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1488e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig	mutex_lock(&sas_host->lock);
1489c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	list_del(&rphy->list);
1490e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig	mutex_unlock(&sas_host->lock);
1491c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1492b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley	sas_bsg_remove(shost, rphy);
1493b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley
149492aab6464be735139f9ea38fd039c3b84c722630Mike Anderson	transport_destroy_device(dev);
14952f8600dff2b140096a7df781884e918a16aa90e0James Bottomley
149692aab6464be735139f9ea38fd039c3b84c722630Mike Anderson	put_device(dev);
1497c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1498c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_free);
1499c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1500c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
1501eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_delete  -  remove and free SAS remote PHY
15026f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * @rphy:	SAS remote PHY to remove and free
1503c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
15046f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * Removes the specified SAS remote PHY and frees it.
1505c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
1506c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid
1507c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_delete(struct sas_rphy *rphy)
1508c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
15096f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong	sas_rphy_remove(rphy);
15106f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong	sas_rphy_free(rphy);
15116f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong}
15126f63caae2172e97e528b58319480217b0b36542eDarrick J. WongEXPORT_SYMBOL(sas_rphy_delete);
15136f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong
15146f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong/**
1515eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_remove  -  remove SAS remote PHY
15166f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * @rphy:	SAS remote phy to remove
15176f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong *
15186f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * Removes the specified SAS remote PHY.
15196f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong */
15206f63caae2172e97e528b58319480217b0b36542eDarrick J. Wongvoid
15216f63caae2172e97e528b58319480217b0b36542eDarrick J. Wongsas_rphy_remove(struct sas_rphy *rphy)
15226f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong{
1523c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct device *dev = &rphy->dev;
152465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	struct sas_port *parent = dev_to_sas_port(dev->parent);
1525c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1526d4054239929479907f20b9d68c905589125ad343Christoph Hellwig	switch (rphy->identify.device_type) {
1527d4054239929479907f20b9d68c905589125ad343Christoph Hellwig	case SAS_END_DEVICE:
1528d4054239929479907f20b9d68c905589125ad343Christoph Hellwig		scsi_remove_target(dev);
1529d4054239929479907f20b9d68c905589125ad343Christoph Hellwig		break;
1530d4054239929479907f20b9d68c905589125ad343Christoph Hellwig	case SAS_EDGE_EXPANDER_DEVICE:
1531d4054239929479907f20b9d68c905589125ad343Christoph Hellwig	case SAS_FANOUT_EXPANDER_DEVICE:
153265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		sas_remove_children(dev);
1533d4054239929479907f20b9d68c905589125ad343Christoph Hellwig		break;
1534d4054239929479907f20b9d68c905589125ad343Christoph Hellwig	default:
1535d4054239929479907f20b9d68c905589125ad343Christoph Hellwig		break;
1536d4054239929479907f20b9d68c905589125ad343Christoph Hellwig	}
1537c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1538fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig	transport_remove_device(dev);
1539fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig	device_del(dev);
1540c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
154133b114e935a2202206e224dd2c695cee5a5986bfChristoph Hellwig	parent->rphy = NULL;
1542c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
15436f63caae2172e97e528b58319480217b0b36542eDarrick J. WongEXPORT_SYMBOL(sas_rphy_remove);
1544c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1545c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
1546eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * scsi_is_sas_rphy  -  check if a struct device represents a SAS remote PHY
1547c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev:	device to check
1548c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *
1549c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns:
1550c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig *	%1 if the device represents a SAS remote PHY, %0 else
1551c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
1552c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_rphy(const struct device *dev)
1553c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
15542f8600dff2b140096a7df781884e918a16aa90e0James Bottomley	return dev->release == sas_end_device_release ||
15552f8600dff2b140096a7df781884e918a16aa90e0James Bottomley		dev->release == sas_expander_release;
1556c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1557c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_rphy);
1558c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1559c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1560c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/*
1561c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SCSI scan helper
1562c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
1563c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1564e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwigstatic int sas_user_scan(struct Scsi_Host *shost, uint channel,
1565e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig		uint id, uint lun)
1566c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
1567c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1568c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_rphy *rphy;
1569c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1570e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig	mutex_lock(&sas_host->lock);
1571c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	list_for_each_entry(rphy, &sas_host->rphy_list, list) {
15726d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley		if (rphy->identify.device_type != SAS_END_DEVICE ||
15736d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley		    rphy->scsi_target_id == -1)
1574e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig			continue;
1575e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig
1576e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley		if ((channel == SCAN_WILD_CARD || channel == 0) &&
1577e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig		    (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
1578e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley			scsi_scan_target(&rphy->dev, 0,
1579e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig					 rphy->scsi_target_id, lun, 1);
1580e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig		}
1581c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	}
1582e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig	mutex_unlock(&sas_host->lock);
1583c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1584e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig	return 0;
1585c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1586c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1587c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1588c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/*
1589c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Setup / Teardown code
1590c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
1591c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1592d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_TEMPLATE(attrb, field, perm, test)			\
1593ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	i->private_##attrb[count] = dev_attr_##field;		\
159442ab03609cca4ef5079e248296f015650c626899James Bottomley	i->private_##attrb[count].attr.mode = perm;			\
159542ab03609cca4ef5079e248296f015650c626899James Bottomley	i->attrb[count] = &i->private_##attrb[count];			\
159642ab03609cca4ef5079e248296f015650c626899James Bottomley	if (test)							\
159742ab03609cca4ef5079e248296f015650c626899James Bottomley		count++
159842ab03609cca4ef5079e248296f015650c626899James Bottomley
1599d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm)	\
1600ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	i->private_##attrb[count] = dev_attr_##field;		\
1601d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	i->private_##attrb[count].attr.mode = perm;			\
1602d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	if (ro_test) {							\
1603d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley		i->private_##attrb[count].attr.mode = ro_perm;		\
1604d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley		i->private_##attrb[count].store = NULL;			\
1605d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	}								\
1606d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	i->attrb[count] = &i->private_##attrb[count];			\
1607d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	if (test)							\
1608d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley		count++
160942ab03609cca4ef5079e248296f015650c626899James Bottomley
161042ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_RPORT_ATTRIBUTE(field) 					\
161142ab03609cca4ef5079e248296f015650c626899James Bottomley	SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1)
1612c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1613dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func)			\
161442ab03609cca4ef5079e248296f015650c626899James Bottomley	SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func)
1615dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley
161665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE(field)					\
161742ab03609cca4ef5079e248296f015650c626899James Bottomley	SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1)
1618c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1619d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_PHY_ATTRIBUTE_RW(field)					\
1620d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1,	\
1621d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley			!i->f->set_phy_speed, S_IRUGO)
1622d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley
1623acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func)			\
1624acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1,	\
1625acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong			  !i->f->func, S_IRUGO)
1626acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong
162765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PORT_ATTRIBUTE(field)					\
162865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
162965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
163065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func)			\
163142ab03609cca4ef5079e248296f015650c626899James Bottomley	SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func)
1632dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley
163365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE_WRONLY(field)				\
1634fe3b5bfe73ace420709f0cfb198b0ffc704bd38bDarrick J. Wong	SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1)
163507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig
163665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func)		\
1637fe3b5bfe73ace420709f0cfb198b0ffc704bd38bDarrick J. Wong	SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func)
1638dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley
163942ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_END_DEV_ATTRIBUTE(field)					\
164042ab03609cca4ef5079e248296f015650c626899James Bottomley	SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1)
1641c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
164279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define SETUP_EXPANDER_ATTRIBUTE(field)					\
164379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1)
164479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
1645c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
1646eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_attach_transport  -  instantiate SAS transport template
1647c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @ft:		SAS transport class function template
1648c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
1649c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct scsi_transport_template *
1650c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_attach_transport(struct sas_function_template *ft)
1651c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
1652c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_internal *i;
1653c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	int count;
1654c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
165524669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen	i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL);
1656c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (!i)
1657c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		return NULL;
1658c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1659e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig	i->t.user_scan = sas_user_scan;
1660c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1661c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->t.host_attrs.ac.attrs = &i->host_attrs[0];
1662c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->t.host_attrs.ac.class = &sas_host_class.class;
1663c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->t.host_attrs.ac.match = sas_host_match;
1664c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_container_register(&i->t.host_attrs);
1665c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->t.host_size = sizeof(struct sas_host_attrs);
1666c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1667c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->phy_attr_cont.ac.class = &sas_phy_class.class;
1668c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->phy_attr_cont.ac.attrs = &i->phy_attrs[0];
1669c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->phy_attr_cont.ac.match = sas_phy_match;
1670c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_container_register(&i->phy_attr_cont);
1671c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
167265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	i->port_attr_cont.ac.class = &sas_port_class.class;
167365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	i->port_attr_cont.ac.attrs = &i->port_attrs[0];
167465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	i->port_attr_cont.ac.match = sas_port_match;
167565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	transport_container_register(&i->port_attr_cont);
167665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
1677c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->rphy_attr_cont.ac.class = &sas_rphy_class.class;
1678c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0];
1679c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->rphy_attr_cont.ac.match = sas_rphy_match;
1680c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_container_register(&i->rphy_attr_cont);
1681c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
168242ab03609cca4ef5079e248296f015650c626899James Bottomley	i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class;
168342ab03609cca4ef5079e248296f015650c626899James Bottomley	i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0];
168442ab03609cca4ef5079e248296f015650c626899James Bottomley	i->end_dev_attr_cont.ac.match = sas_end_dev_match;
168542ab03609cca4ef5079e248296f015650c626899James Bottomley	transport_container_register(&i->end_dev_attr_cont);
168642ab03609cca4ef5079e248296f015650c626899James Bottomley
168779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	i->expander_attr_cont.ac.class = &sas_expander_class.class;
168879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	i->expander_attr_cont.ac.attrs = &i->expander_attrs[0];
168979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	i->expander_attr_cont.ac.match = sas_expander_match;
169079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	transport_container_register(&i->expander_attr_cont);
169179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
1692c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->f = ft;
1693c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1694c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	count = 0;
169565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PORT_ATTRIBUTE(num_phys);
1696c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->host_attrs[count] = NULL;
1697c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1698c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	count = 0;
169965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(initiator_port_protocols);
170065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(target_port_protocols);
170165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(device_type);
170265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(sas_address);
170365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(phy_identifier);
170465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	//SETUP_PHY_ATTRIBUTE(port_identifier);
170565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(negotiated_linkrate);
170665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw);
1707d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	SETUP_PHY_ATTRIBUTE_RW(minimum_linkrate);
170865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw);
1709d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley	SETUP_PHY_ATTRIBUTE_RW(maximum_linkrate);
171065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
171165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(invalid_dword_count);
171265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(running_disparity_error_count);
171365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count);
171465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PHY_ATTRIBUTE(phy_reset_problem_count);
171565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset);
171665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset);
1717acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong	SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable);
1718c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->phy_attrs[count] = NULL;
1719c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1720c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	count = 0;
172165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	SETUP_PORT_ATTRIBUTE(num_phys);
172265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	i->port_attrs[count] = NULL;
172365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley
172465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	count = 0;
1725c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols);
1726c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols);
1727c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	SETUP_RPORT_ATTRIBUTE(rphy_device_type);
1728c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	SETUP_RPORT_ATTRIBUTE(rphy_sas_address);
1729c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier);
1730dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley	SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier,
1731dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley				       get_enclosure_identifier);
1732dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley	SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier,
1733dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley				       get_bay_identifier);
1734c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	i->rphy_attrs[count] = NULL;
1735c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
173642ab03609cca4ef5079e248296f015650c626899James Bottomley	count = 0;
173742ab03609cca4ef5079e248296f015650c626899James Bottomley	SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning);
173842ab03609cca4ef5079e248296f015650c626899James Bottomley	SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout);
173942ab03609cca4ef5079e248296f015650c626899James Bottomley	SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout);
174042ab03609cca4ef5079e248296f015650c626899James Bottomley	i->end_dev_attrs[count] = NULL;
174142ab03609cca4ef5079e248296f015650c626899James Bottomley
174279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	count = 0;
174379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	SETUP_EXPANDER_ATTRIBUTE(vendor_id);
174479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	SETUP_EXPANDER_ATTRIBUTE(product_id);
174579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	SETUP_EXPANDER_ATTRIBUTE(product_rev);
174679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	SETUP_EXPANDER_ATTRIBUTE(component_vendor_id);
174779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	SETUP_EXPANDER_ATTRIBUTE(component_id);
174879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	SETUP_EXPANDER_ATTRIBUTE(component_revision_id);
174979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	SETUP_EXPANDER_ATTRIBUTE(level);
175079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	i->expander_attrs[count] = NULL;
175179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley
1752c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return &i->t;
1753c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1754c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_attach_transport);
1755c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1756c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/**
1757eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_release_transport  -  release SAS transport template instance
1758c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @t:		transport template instance
1759c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */
1760c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_release_transport(struct scsi_transport_template *t)
1761c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
1762c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	struct sas_internal *i = to_sas_internal(t);
1763c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1764c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_container_unregister(&i->t.host_attrs);
1765c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_container_unregister(&i->phy_attr_cont);
176665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	transport_container_unregister(&i->port_attr_cont);
1767c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_container_unregister(&i->rphy_attr_cont);
1768db82f8410ed7546792358964aa5f8dafff1c70a2James Bottomley	transport_container_unregister(&i->end_dev_attr_cont);
176979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	transport_container_unregister(&i->expander_attr_cont);
1770c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1771c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	kfree(i);
1772c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1773c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_release_transport);
1774c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1775c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic __init int sas_transport_init(void)
1776c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
1777c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	int error;
1778c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1779c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	error = transport_class_register(&sas_host_class);
1780c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (error)
1781c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		goto out;
1782c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	error = transport_class_register(&sas_phy_class);
1783c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (error)
1784c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		goto out_unregister_transport;
178565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	error = transport_class_register(&sas_port_class);
1786c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	if (error)
1787c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig		goto out_unregister_phy;
178865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	error = transport_class_register(&sas_rphy_class);
178965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	if (error)
179065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley		goto out_unregister_port;
179142ab03609cca4ef5079e248296f015650c626899James Bottomley	error = transport_class_register(&sas_end_dev_class);
179242ab03609cca4ef5079e248296f015650c626899James Bottomley	if (error)
179342ab03609cca4ef5079e248296f015650c626899James Bottomley		goto out_unregister_rphy;
179479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	error = transport_class_register(&sas_expander_class);
179579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	if (error)
179679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley		goto out_unregister_end_dev;
1797c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1798c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return 0;
1799c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
180079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley out_unregister_end_dev:
180179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	transport_class_unregister(&sas_end_dev_class);
180242ab03609cca4ef5079e248296f015650c626899James Bottomley out_unregister_rphy:
180342ab03609cca4ef5079e248296f015650c626899James Bottomley	transport_class_unregister(&sas_rphy_class);
180465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley out_unregister_port:
180565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	transport_class_unregister(&sas_port_class);
1806c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_phy:
1807c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_class_unregister(&sas_phy_class);
1808c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_transport:
1809c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_class_unregister(&sas_host_class);
1810c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out:
1811c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	return error;
1812c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1813c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1814c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1815c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void __exit sas_transport_exit(void)
1816c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{
1817c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_class_unregister(&sas_host_class);
1818c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_class_unregister(&sas_phy_class);
181965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley	transport_class_unregister(&sas_port_class);
1820c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig	transport_class_unregister(&sas_rphy_class);
182142ab03609cca4ef5079e248296f015650c626899James Bottomley	transport_class_unregister(&sas_end_dev_class);
182279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley	transport_class_unregister(&sas_expander_class);
1823c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}
1824c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1825c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_AUTHOR("Christoph Hellwig");
182686b9c4c16a1589d05959af2d96d52a4352c6306eAlexis BruemmerMODULE_DESCRIPTION("SAS Transport Attributes");
1827c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_LICENSE("GPL");
1828c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig
1829c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_init(sas_transport_init);
1830c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_exit(sas_transport_exit);
1831