1 | /* |
2 | * This file is provided under a dual BSD/GPLv2 license. When using or |
3 | * redistributing this file, you may do so under either license. |
4 | * |
5 | * GPL LICENSE SUMMARY |
6 | * |
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. |
8 | * |
9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of version 2 of the GNU General Public License as |
11 | * published by the Free Software Foundation. |
12 | * |
13 | * This program is distributed in the hope that it will be useful, but |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. |
23 | * |
24 | * BSD LICENSE |
25 | * |
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. |
27 | * All rights reserved. |
28 | * |
29 | * Redistribution and use in source and binary forms, with or without |
30 | * modification, are permitted provided that the following conditions |
31 | * are met: |
32 | * |
33 | * * Redistributions of source code must retain the above copyright |
34 | * notice, this list of conditions and the following disclaimer. |
35 | * * Redistributions in binary form must reproduce the above copyright |
36 | * notice, this list of conditions and the following disclaimer in |
37 | * the documentation and/or other materials provided with the |
38 | * distribution. |
39 | * * Neither the name of Intel Corporation nor the names of its |
40 | * contributors may be used to endorse or promote products derived |
41 | * from this software without specific prior written permission. |
42 | * |
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
54 | */ |
55 | |
56 | #ifndef _ISCI_PORT_H_ |
57 | #define _ISCI_PORT_H_ |
58 | |
59 | #include <scsi/libsas.h> |
60 | #include "isci.h" |
61 | #include "sas.h" |
62 | #include "phy.h" |
63 | |
64 | #define SCIC_SDS_DUMMY_PORT 0xFF |
65 | |
66 | #define PF_NOTIFY (1 << 0) |
67 | #define PF_RESUME (1 << 1) |
68 | |
69 | struct isci_phy; |
70 | struct isci_host; |
71 | |
72 | enum isci_status { |
73 | isci_freed = 0x00, |
74 | isci_starting = 0x01, |
75 | isci_ready = 0x02, |
76 | isci_ready_for_io = 0x03, |
77 | isci_stopping = 0x04, |
78 | isci_stopped = 0x05, |
79 | }; |
80 | |
81 | /** |
82 | * struct isci_port - isci direct attached sas port object |
83 | * @ready_exit: several states constitute 'ready'. When exiting ready we |
84 | * need to take extra port-teardown actions that are |
85 | * skipped when exiting to another 'ready' state. |
86 | * @logical_port_index: software port index |
87 | * @physical_port_index: hardware port index |
88 | * @active_phy_mask: identifies phy members |
89 | * @enabled_phy_mask: phy mask for the port |
90 | * that are already part of the port |
91 | * @reserved_tag: |
92 | * @reserved_rni: reserver for port task scheduler workaround |
93 | * @started_request_count: reference count for outstanding commands |
94 | * @not_ready_reason: set during state transitions and notified |
95 | * @timer: timeout start/stop operations |
96 | */ |
97 | struct isci_port { |
98 | struct isci_host *isci_host; |
99 | struct list_head remote_dev_list; |
100 | #define IPORT_RESET_PENDING 0 |
101 | unsigned long state; |
102 | enum sci_status hard_reset_status; |
103 | struct sci_base_state_machine sm; |
104 | bool ready_exit; |
105 | u8 logical_port_index; |
106 | u8 physical_port_index; |
107 | u8 active_phy_mask; |
108 | u8 enabled_phy_mask; |
109 | u8 last_active_phy; |
110 | u16 reserved_rni; |
111 | u16 reserved_tag; |
112 | u32 started_request_count; |
113 | u32 assigned_device_count; |
114 | u32 hang_detect_users; |
115 | u32 not_ready_reason; |
116 | struct isci_phy *phy_table[SCI_MAX_PHYS]; |
117 | struct isci_host *owning_controller; |
118 | struct sci_timer timer; |
119 | struct scu_port_task_scheduler_registers __iomem *port_task_scheduler_registers; |
120 | /* XXX rework: only one register, no need to replicate per-port */ |
121 | u32 __iomem *port_pe_configuration_register; |
122 | struct scu_viit_entry __iomem *viit_registers; |
123 | }; |
124 | |
125 | enum sci_port_not_ready_reason_code { |
126 | SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, |
127 | SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, |
128 | SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION, |
129 | SCIC_PORT_NOT_READY_RECONFIGURING, |
130 | |
131 | SCIC_PORT_NOT_READY_REASON_CODE_MAX |
132 | }; |
133 | |
134 | struct sci_port_end_point_properties { |
135 | struct sci_sas_address sas_address; |
136 | struct sci_phy_proto protocols; |
137 | }; |
138 | |
139 | struct sci_port_properties { |
140 | u32 index; |
141 | struct sci_port_end_point_properties local; |
142 | struct sci_port_end_point_properties remote; |
143 | u32 phy_mask; |
144 | }; |
145 | |
146 | /** |
147 | * enum sci_port_states - port state machine states |
148 | * @SCI_PORT_STOPPED: port has successfully been stopped. In this state |
149 | * no new IO operations are permitted. This state is |
150 | * entered from the STOPPING state. |
151 | * @SCI_PORT_STOPPING: port is in the process of stopping. In this |
152 | * state no new IO operations are permitted, but |
153 | * existing IO operations are allowed to complete. |
154 | * This state is entered from the READY state. |
155 | * @SCI_PORT_READY: port is now ready. Thus, the user is able to |
156 | * perform IO operations on this port. This state is |
157 | * entered from the STARTING state. |
158 | * @SCI_PORT_SUB_WAITING: port is started and ready but has no active |
159 | * phys. |
160 | * @SCI_PORT_SUB_OPERATIONAL: port is started and ready and there is at |
161 | * least one phy operational. |
162 | * @SCI_PORT_SUB_CONFIGURING: port is started and there was an |
163 | * add/remove phy event. This state is only |
164 | * used in Automatic Port Configuration Mode |
165 | * (APC) |
166 | * @SCI_PORT_RESETTING: port is in the process of performing a hard |
167 | * reset. Thus, the user is unable to perform IO |
168 | * operations on this port. This state is entered |
169 | * from the READY state. |
170 | * @SCI_PORT_FAILED: port has failed a reset request. This state is |
171 | * entered when a port reset request times out. This |
172 | * state is entered from the RESETTING state. |
173 | */ |
174 | #define PORT_STATES {\ |
175 | C(PORT_STOPPED),\ |
176 | C(PORT_STOPPING),\ |
177 | C(PORT_READY),\ |
178 | C(PORT_SUB_WAITING),\ |
179 | C(PORT_SUB_OPERATIONAL),\ |
180 | C(PORT_SUB_CONFIGURING),\ |
181 | C(PORT_RESETTING),\ |
182 | C(PORT_FAILED),\ |
183 | } |
184 | #undef C |
185 | #define C(a) SCI_##a |
186 | enum sci_port_states PORT_STATES; |
187 | #undef C |
188 | |
189 | static inline void sci_port_decrement_request_count(struct isci_port *iport) |
190 | { |
191 | if (WARN_ONCE(iport->started_request_count == 0, |
192 | "%s: tried to decrement started_request_count past 0!?" , |
193 | __func__)) |
194 | /* pass */; |
195 | else |
196 | iport->started_request_count--; |
197 | } |
198 | |
199 | #define sci_port_active_phy(port, phy) \ |
200 | (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) |
201 | |
202 | void sci_port_construct( |
203 | struct isci_port *iport, |
204 | u8 port_index, |
205 | struct isci_host *ihost); |
206 | |
207 | enum sci_status sci_port_start(struct isci_port *iport); |
208 | enum sci_status sci_port_stop(struct isci_port *iport); |
209 | |
210 | enum sci_status sci_port_add_phy( |
211 | struct isci_port *iport, |
212 | struct isci_phy *iphy); |
213 | |
214 | enum sci_status sci_port_remove_phy( |
215 | struct isci_port *iport, |
216 | struct isci_phy *iphy); |
217 | |
218 | void sci_port_setup_transports( |
219 | struct isci_port *iport, |
220 | u32 device_id); |
221 | |
222 | void isci_port_bcn_enable(struct isci_host *, struct isci_port *); |
223 | |
224 | void sci_port_deactivate_phy( |
225 | struct isci_port *iport, |
226 | struct isci_phy *iphy, |
227 | bool do_notify_user); |
228 | |
229 | bool sci_port_link_detected( |
230 | struct isci_port *iport, |
231 | struct isci_phy *iphy); |
232 | |
233 | enum sci_status sci_port_get_properties( |
234 | struct isci_port *iport, |
235 | struct sci_port_properties *prop); |
236 | |
237 | enum sci_status sci_port_link_up(struct isci_port *iport, |
238 | struct isci_phy *iphy); |
239 | enum sci_status sci_port_link_down(struct isci_port *iport, |
240 | struct isci_phy *iphy); |
241 | |
242 | struct isci_request; |
243 | struct isci_remote_device; |
244 | enum sci_status sci_port_start_io( |
245 | struct isci_port *iport, |
246 | struct isci_remote_device *idev, |
247 | struct isci_request *ireq); |
248 | |
249 | enum sci_status sci_port_complete_io( |
250 | struct isci_port *iport, |
251 | struct isci_remote_device *idev, |
252 | struct isci_request *ireq); |
253 | |
254 | enum sas_linkrate sci_port_get_max_allowed_speed( |
255 | struct isci_port *iport); |
256 | |
257 | void sci_port_broadcast_change_received( |
258 | struct isci_port *iport, |
259 | struct isci_phy *iphy); |
260 | |
261 | bool sci_port_is_valid_phy_assignment( |
262 | struct isci_port *iport, |
263 | u32 phy_index); |
264 | |
265 | void sci_port_get_sas_address( |
266 | struct isci_port *iport, |
267 | struct sci_sas_address *sas_address); |
268 | |
269 | void sci_port_get_attached_sas_address( |
270 | struct isci_port *iport, |
271 | struct sci_sas_address *sas_address); |
272 | |
273 | void sci_port_set_hang_detection_timeout( |
274 | struct isci_port *isci_port, |
275 | u32 timeout); |
276 | |
277 | void isci_port_formed(struct asd_sas_phy *); |
278 | void isci_port_deformed(struct asd_sas_phy *); |
279 | |
280 | int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, |
281 | struct isci_phy *iphy); |
282 | int isci_ata_check_ready(struct domain_device *dev); |
283 | #endif /* !defined(_ISCI_PORT_H_) */ |
284 | |