Commit | Line | Data |
---|---|---|
6f231dda DW |
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 | ||
e531381e | 56 | #ifndef _ISCI_PORT_H_ |
6f231dda | 57 | #define _ISCI_PORT_H_ |
ce2b3261 DW |
58 | |
59 | #include <scsi/libsas.h> | |
60 | #include "isci.h" | |
e2f8db50 DW |
61 | #include "sas.h" |
62 | #include "phy.h" | |
63 | ||
64 | #define SCIC_SDS_DUMMY_PORT 0xFF | |
6f231dda DW |
65 | |
66 | struct isci_phy; | |
67 | struct isci_host; | |
6f231dda DW |
68 | |
69 | enum isci_status { | |
70 | isci_freed = 0x00, | |
71 | isci_starting = 0x01, | |
72 | isci_ready = 0x02, | |
73 | isci_ready_for_io = 0x03, | |
74 | isci_stopping = 0x04, | |
75 | isci_stopped = 0x05, | |
6f231dda DW |
76 | }; |
77 | ||
e2f8db50 DW |
78 | /** |
79 | * struct scic_sds_port | |
80 | * | |
81 | * The core port object provides the the abstraction for an SCU port. | |
82 | */ | |
83 | struct scic_sds_port { | |
e2f8db50 DW |
84 | /** |
85 | * This field contains the information for the base port state machine. | |
86 | */ | |
87 | struct sci_base_state_machine state_machine; | |
88 | ||
e91f41ef PS |
89 | bool ready_exit; |
90 | ||
e2f8db50 DW |
91 | /** |
92 | * This field is the port index that is reported to the SCI USER. | |
93 | * This allows the actual hardware physical port to change without | |
94 | * the SCI USER getting a different answer for the get port index. | |
95 | */ | |
96 | u8 logical_port_index; | |
97 | ||
98 | /** | |
99 | * This field is the port index used to program the SCU hardware. | |
100 | */ | |
101 | u8 physical_port_index; | |
102 | ||
103 | /** | |
104 | * This field contains the active phy mask for the port. | |
105 | * This mask is used in conjunction with the phy state to determine | |
106 | * which phy to select for some port operations. | |
107 | */ | |
108 | u8 active_phy_mask; | |
109 | ||
110 | u16 reserved_rni; | |
111 | u16 reserved_tci; | |
112 | ||
113 | /** | |
114 | * This field contains the count of the io requests started on this port | |
115 | * object. It is used to control controller shutdown. | |
116 | */ | |
117 | u32 started_request_count; | |
118 | ||
119 | /** | |
120 | * This field contains the number of devices assigned to this port. | |
121 | * It is used to control port start requests. | |
122 | */ | |
123 | u32 assigned_device_count; | |
124 | ||
125 | /** | |
126 | * This field contains the reason for the port not going ready. It is | |
127 | * assigned in the state handlers and used in the state transition. | |
128 | */ | |
129 | u32 not_ready_reason; | |
130 | ||
131 | /** | |
132 | * This field is the table of phys assigned to the port. | |
133 | */ | |
134 | struct scic_sds_phy *phy_table[SCI_MAX_PHYS]; | |
135 | ||
136 | /** | |
137 | * This field is a pointer back to the controller that owns this | |
138 | * port object. | |
139 | */ | |
140 | struct scic_sds_controller *owning_controller; | |
141 | ||
142 | /** | |
143 | * This field contains the port start/stop timer handle. | |
144 | */ | |
145 | void *timer_handle; | |
146 | ||
e2f8db50 DW |
147 | /** |
148 | * This field is the pointer to the port task scheduler registers | |
149 | * for the SCU hardware. | |
150 | */ | |
151 | struct scu_port_task_scheduler_registers __iomem | |
152 | *port_task_scheduler_registers; | |
153 | ||
154 | /** | |
155 | * This field is identical for all port objects and points to the port | |
156 | * task scheduler group PE configuration registers. | |
157 | * It is used to assign PEs to a port. | |
158 | */ | |
159 | u32 __iomem *port_pe_configuration_register; | |
160 | ||
161 | /** | |
162 | * This field is the VIIT register space for ths port object. | |
163 | */ | |
164 | struct scu_viit_entry __iomem *viit_registers; | |
e2f8db50 DW |
165 | }; |
166 | ||
167 | ||
168 | ||
6f231dda DW |
169 | /** |
170 | * struct isci_port - This class represents the port object used to internally | |
171 | * represent libsas port objects. It also keeps a list of remote device | |
172 | * objects. | |
173 | * | |
174 | * | |
175 | */ | |
176 | struct isci_port { | |
6f231dda DW |
177 | enum isci_status status; |
178 | struct isci_host *isci_host; | |
179 | struct asd_sas_port sas_port; | |
180 | struct list_head remote_dev_list; | |
6f231dda DW |
181 | spinlock_t state_lock; |
182 | struct list_head domain_dev_list; | |
183 | struct completion start_complete; | |
184 | struct completion hard_reset_complete; | |
185 | enum sci_status hard_reset_status; | |
e531381e | 186 | struct scic_sds_port sci; |
6f231dda DW |
187 | }; |
188 | ||
e531381e DW |
189 | static inline struct isci_port *sci_port_to_iport(struct scic_sds_port *sci_port) |
190 | { | |
191 | struct isci_port *iport = container_of(sci_port, typeof(*iport), sci); | |
192 | ||
193 | return iport; | |
194 | } | |
6f231dda | 195 | |
e2f8db50 DW |
196 | enum scic_port_not_ready_reason_code { |
197 | SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, | |
198 | SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, | |
199 | SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION, | |
200 | SCIC_PORT_NOT_READY_RECONFIGURING, | |
201 | ||
202 | SCIC_PORT_NOT_READY_REASON_CODE_MAX | |
203 | }; | |
204 | ||
205 | struct scic_port_end_point_properties { | |
206 | struct sci_sas_address sas_address; | |
207 | struct scic_phy_proto protocols; | |
208 | }; | |
209 | ||
210 | struct scic_port_properties { | |
211 | u32 index; | |
212 | struct scic_port_end_point_properties local; | |
213 | struct scic_port_end_point_properties remote; | |
214 | u32 phy_mask; | |
215 | }; | |
216 | ||
e2f8db50 DW |
217 | /** |
218 | * enum scic_sds_port_states - This enumeration depicts all the states for the | |
219 | * common port state machine. | |
220 | * | |
221 | * | |
222 | */ | |
223 | enum scic_sds_port_states { | |
224 | /** | |
225 | * This state indicates that the port has successfully been stopped. | |
226 | * In this state no new IO operations are permitted. | |
227 | * This state is entered from the STOPPING state. | |
228 | */ | |
229 | SCI_BASE_PORT_STATE_STOPPED, | |
230 | ||
231 | /** | |
232 | * This state indicates that the port is in the process of stopping. | |
233 | * In this state no new IO operations are permitted, but existing IO | |
234 | * operations are allowed to complete. | |
235 | * This state is entered from the READY state. | |
236 | */ | |
237 | SCI_BASE_PORT_STATE_STOPPING, | |
238 | ||
239 | /** | |
240 | * This state indicates the port is now ready. Thus, the user is | |
241 | * able to perform IO operations on this port. | |
242 | * This state is entered from the STARTING state. | |
243 | */ | |
244 | SCI_BASE_PORT_STATE_READY, | |
245 | ||
e91f41ef PS |
246 | /** |
247 | * The substate where the port is started and ready but has no | |
248 | * active phys. | |
249 | */ | |
250 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING, | |
251 | ||
252 | /** | |
253 | * The substate where the port is started and ready and there is | |
254 | * at least one phy operational. | |
255 | */ | |
256 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, | |
257 | ||
258 | /** | |
259 | * The substate where the port is started and there was an | |
260 | * add/remove phy event. This state is only used in Automatic | |
261 | * Port Configuration Mode (APC) | |
262 | */ | |
263 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, | |
264 | ||
e2f8db50 DW |
265 | /** |
266 | * This state indicates the port is in the process of performing a hard | |
267 | * reset. Thus, the user is unable to perform IO operations on this | |
268 | * port. | |
269 | * This state is entered from the READY state. | |
270 | */ | |
271 | SCI_BASE_PORT_STATE_RESETTING, | |
272 | ||
273 | /** | |
274 | * This state indicates the port has failed a reset request. This state | |
275 | * is entered when a port reset request times out. | |
276 | * This state is entered from the RESETTING state. | |
277 | */ | |
278 | SCI_BASE_PORT_STATE_FAILED, | |
279 | ||
6f231dda | 280 | |
e2f8db50 DW |
281 | }; |
282 | ||
283 | /** | |
284 | * scic_sds_port_get_controller() - | |
285 | * | |
286 | * Helper macro to get the owning controller of this port | |
287 | */ | |
288 | #define scic_sds_port_get_controller(this_port) \ | |
289 | ((this_port)->owning_controller) | |
290 | ||
e2f8db50 DW |
291 | /** |
292 | * scic_sds_port_get_index() - | |
293 | * | |
294 | * This macro returns the physical port index for this port object | |
295 | */ | |
296 | #define scic_sds_port_get_index(this_port) \ | |
297 | ((this_port)->physical_port_index) | |
298 | ||
299 | ||
300 | static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *sci_port) | |
301 | { | |
302 | if (WARN_ONCE(sci_port->started_request_count == 0, | |
303 | "%s: tried to decrement started_request_count past 0!?", | |
304 | __func__)) | |
305 | /* pass */; | |
306 | else | |
307 | sci_port->started_request_count--; | |
308 | } | |
309 | ||
310 | #define scic_sds_port_active_phy(port, phy) \ | |
311 | (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) | |
312 | ||
313 | void scic_sds_port_construct( | |
314 | struct scic_sds_port *sci_port, | |
315 | u8 port_index, | |
316 | struct scic_sds_controller *scic); | |
317 | ||
318 | enum sci_status scic_sds_port_initialize( | |
319 | struct scic_sds_port *sci_port, | |
320 | void __iomem *port_task_scheduler_registers, | |
321 | void __iomem *port_configuration_regsiter, | |
322 | void __iomem *viit_registers); | |
323 | ||
d76f71d9 | 324 | enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port); |
8bc80d30 | 325 | enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port); |
d76f71d9 | 326 | |
e2f8db50 DW |
327 | enum sci_status scic_sds_port_add_phy( |
328 | struct scic_sds_port *sci_port, | |
329 | struct scic_sds_phy *sci_phy); | |
330 | ||
331 | enum sci_status scic_sds_port_remove_phy( | |
332 | struct scic_sds_port *sci_port, | |
333 | struct scic_sds_phy *sci_phy); | |
334 | ||
335 | void scic_sds_port_setup_transports( | |
336 | struct scic_sds_port *sci_port, | |
337 | u32 device_id); | |
338 | ||
339 | ||
340 | void scic_sds_port_deactivate_phy( | |
341 | struct scic_sds_port *sci_port, | |
342 | struct scic_sds_phy *sci_phy, | |
343 | bool do_notify_user); | |
344 | ||
345 | bool scic_sds_port_link_detected( | |
346 | struct scic_sds_port *sci_port, | |
347 | struct scic_sds_phy *sci_phy); | |
348 | ||
051266ca PS |
349 | enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, |
350 | struct scic_sds_phy *sci_phy); | |
351 | enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, | |
352 | struct scic_sds_phy *sci_phy); | |
e2f8db50 | 353 | |
6813820c DW |
354 | struct scic_sds_request; |
355 | struct scic_sds_remote_device; | |
e2f8db50 DW |
356 | enum sci_status scic_sds_port_start_io( |
357 | struct scic_sds_port *sci_port, | |
358 | struct scic_sds_remote_device *sci_dev, | |
359 | struct scic_sds_request *sci_req); | |
360 | ||
361 | enum sci_status scic_sds_port_complete_io( | |
362 | struct scic_sds_port *sci_port, | |
363 | struct scic_sds_remote_device *sci_dev, | |
364 | struct scic_sds_request *sci_req); | |
365 | ||
366 | enum sas_linkrate scic_sds_port_get_max_allowed_speed( | |
367 | struct scic_sds_port *sci_port); | |
368 | ||
369 | void scic_sds_port_broadcast_change_received( | |
370 | struct scic_sds_port *sci_port, | |
371 | struct scic_sds_phy *sci_phy); | |
372 | ||
373 | bool scic_sds_port_is_valid_phy_assignment( | |
374 | struct scic_sds_port *sci_port, | |
375 | u32 phy_index); | |
376 | ||
377 | void scic_sds_port_get_sas_address( | |
378 | struct scic_sds_port *sci_port, | |
379 | struct sci_sas_address *sas_address); | |
380 | ||
381 | void scic_sds_port_get_attached_sas_address( | |
382 | struct scic_sds_port *sci_port, | |
383 | struct sci_sas_address *sas_address); | |
384 | ||
385 | enum isci_status isci_port_get_state( | |
6f231dda DW |
386 | struct isci_port *isci_port); |
387 | ||
e2f8db50 DW |
388 | void isci_port_formed(struct asd_sas_phy *); |
389 | void isci_port_deformed(struct asd_sas_phy *); | |
6f231dda DW |
390 | |
391 | void isci_port_init( | |
392 | struct isci_port *port, | |
393 | struct isci_host *host, | |
394 | int index); | |
395 | ||
4393aa4e DW |
396 | int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, |
397 | struct isci_phy *iphy); | |
6f231dda | 398 | #endif /* !defined(_ISCI_PORT_H_) */ |