xref: /linux/include/scsi/scsi_transport_sas.h (revision de2fe5e07d58424bc286fff3fd3c1b0bf933cd58)
1 #ifndef SCSI_TRANSPORT_SAS_H
2 #define SCSI_TRANSPORT_SAS_H
3 
4 #include <linux/transport_class.h>
5 #include <linux/types.h>
6 
7 struct scsi_transport_template;
8 struct sas_rphy;
9 
10 
11 enum sas_device_type {
12 	SAS_PHY_UNUSED,
13 	SAS_END_DEVICE,
14 	SAS_EDGE_EXPANDER_DEVICE,
15 	SAS_FANOUT_EXPANDER_DEVICE,
16 };
17 
18 enum sas_protocol {
19 	SAS_PROTOCOL_SATA		= 0x01,
20 	SAS_PROTOCOL_SMP		= 0x02,
21 	SAS_PROTOCOL_STP		= 0x04,
22 	SAS_PROTOCOL_SSP		= 0x08,
23 };
24 
25 enum sas_linkrate {
26 	SAS_LINK_RATE_UNKNOWN,
27 	SAS_PHY_DISABLED,
28 	SAS_LINK_RATE_FAILED,
29 	SAS_SATA_SPINUP_HOLD,
30 	SAS_SATA_PORT_SELECTOR,
31 	SAS_LINK_RATE_1_5_GBPS,
32 	SAS_LINK_RATE_3_0_GBPS,
33 	SAS_LINK_RATE_6_0_GBPS,
34 	SAS_LINK_VIRTUAL,
35 };
36 
37 struct sas_identify {
38 	enum sas_device_type	device_type;
39 	enum sas_protocol	initiator_port_protocols;
40 	enum sas_protocol	target_port_protocols;
41 	u64			sas_address;
42 	u8			phy_identifier;
43 };
44 
45 struct sas_phy {
46 	struct device		dev;
47 	int			number;
48 
49 	/* phy identification */
50 	struct sas_identify	identify;
51 
52 	/* phy attributes */
53 	enum sas_linkrate	negotiated_linkrate;
54 	enum sas_linkrate	minimum_linkrate_hw;
55 	enum sas_linkrate	minimum_linkrate;
56 	enum sas_linkrate	maximum_linkrate_hw;
57 	enum sas_linkrate	maximum_linkrate;
58 	u8			port_identifier;
59 
60 	/* internal state */
61 	unsigned int		local_attached : 1;
62 
63 	/* link error statistics */
64 	u32			invalid_dword_count;
65 	u32			running_disparity_error_count;
66 	u32			loss_of_dword_sync_count;
67 	u32			phy_reset_problem_count;
68 
69 	/* the other end of the link */
70 	struct sas_rphy		*rphy;
71 };
72 
73 #define dev_to_phy(d) \
74 	container_of((d), struct sas_phy, dev)
75 #define transport_class_to_phy(cdev) \
76 	dev_to_phy((cdev)->dev)
77 #define phy_to_shost(phy) \
78 	dev_to_shost((phy)->dev.parent)
79 
80 struct sas_rphy {
81 	struct device		dev;
82 	struct sas_identify	identify;
83 	struct list_head	list;
84 	u32			scsi_target_id;
85 };
86 
87 #define dev_to_rphy(d) \
88 	container_of((d), struct sas_rphy, dev)
89 #define transport_class_to_rphy(cdev) \
90 	dev_to_rphy((cdev)->dev)
91 #define rphy_to_shost(rphy) \
92 	dev_to_shost((rphy)->dev.parent)
93 #define target_to_rphy(targ) \
94 	dev_to_rphy((targ)->dev.parent)
95 
96 struct sas_end_device {
97 	struct sas_rphy		rphy;
98 	/* flags */
99 	unsigned		ready_led_meaning:1;
100 	/* parameters */
101 	u16			I_T_nexus_loss_timeout;
102 	u16			initiator_response_timeout;
103 };
104 #define rphy_to_end_device(r) \
105 	container_of((r), struct sas_end_device, rphy)
106 
107 struct sas_expander_device {
108 	int    level;
109 
110 	#define SAS_EXPANDER_VENDOR_ID_LEN	8
111 	char   vendor_id[SAS_EXPANDER_VENDOR_ID_LEN+1];
112 	#define SAS_EXPANDER_PRODUCT_ID_LEN	16
113 	char   product_id[SAS_EXPANDER_PRODUCT_ID_LEN+1];
114 	#define SAS_EXPANDER_PRODUCT_REV_LEN	4
115 	char   product_rev[SAS_EXPANDER_PRODUCT_REV_LEN+1];
116 	#define SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN	8
117 	char   component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN+1];
118 	u16    component_id;
119 	u8     component_revision_id;
120 
121 	struct sas_rphy		rphy;
122 
123 };
124 #define rphy_to_expander_device(r) \
125 	container_of((r), struct sas_expander_device, rphy)
126 
127 /* The functions by which the transport class and the driver communicate */
128 struct sas_function_template {
129 	int (*get_linkerrors)(struct sas_phy *);
130 	int (*get_enclosure_identifier)(struct sas_rphy *, u64 *);
131 	int (*get_bay_identifier)(struct sas_rphy *);
132 	int (*phy_reset)(struct sas_phy *, int);
133 };
134 
135 
136 extern void sas_remove_host(struct Scsi_Host *);
137 
138 extern struct sas_phy *sas_phy_alloc(struct device *, int);
139 extern void sas_phy_free(struct sas_phy *);
140 extern int sas_phy_add(struct sas_phy *);
141 extern void sas_phy_delete(struct sas_phy *);
142 extern int scsi_is_sas_phy(const struct device *);
143 
144 extern struct sas_rphy *sas_end_device_alloc(struct sas_phy *);
145 extern struct sas_rphy *sas_expander_alloc(struct sas_phy *, enum sas_device_type);
146 void sas_rphy_free(struct sas_rphy *);
147 extern int sas_rphy_add(struct sas_rphy *);
148 extern void sas_rphy_delete(struct sas_rphy *);
149 extern int scsi_is_sas_rphy(const struct device *);
150 
151 extern struct scsi_transport_template *
152 sas_attach_transport(struct sas_function_template *);
153 extern void sas_release_transport(struct scsi_transport_template *);
154 int sas_read_port_mode_page(struct scsi_device *);
155 
156 static inline int
157 scsi_is_sas_expander_device(struct device *dev)
158 {
159 	struct sas_rphy *rphy;
160 	if (!scsi_is_sas_rphy(dev))
161 		return 0;
162 	rphy = dev_to_rphy(dev);
163 	return rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE ||
164 		rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE;
165 }
166 
167 #endif /* SCSI_TRANSPORT_SAS_H */
168