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 | ||
56 | #ifndef _SCIC_SDS_PORT_H_ | |
57 | #define _SCIC_SDS_PORT_H_ | |
58 | ||
11c88986 | 59 | #include <linux/kernel.h> |
6f231dda DW |
60 | #include "sci_controller_constants.h" |
61 | #include "intel_sas.h" | |
6f231dda DW |
62 | #include "scu_registers.h" |
63 | ||
64 | #define SCIC_SDS_DUMMY_PORT 0xFF | |
65 | ||
41e2b905 MT |
66 | struct scic_sds_controller; |
67 | struct scic_sds_phy; | |
68 | struct scic_sds_remote_device; | |
69 | struct scic_sds_request; | |
70 | ||
a8d4b9fe TC |
71 | /** |
72 | * This constant defines the value utilized by SCI Components to indicate | |
73 | * an invalid handle. | |
74 | */ | |
75 | #define SCI_INVALID_HANDLE 0x0 | |
76 | ||
6f231dda DW |
77 | /** |
78 | * enum SCIC_SDS_PORT_READY_SUBSTATES - | |
79 | * | |
80 | * This enumeration depicts all of the states for the core port ready substate | |
81 | * machine. | |
82 | */ | |
de728b7d | 83 | enum scic_sds_port_ready_substates { |
6f231dda | 84 | /** |
de728b7d DJ |
85 | * The substate where the port is started and ready but has no |
86 | * active phys. | |
6f231dda DW |
87 | */ |
88 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING, | |
89 | ||
90 | /** | |
de728b7d DJ |
91 | * The substate where the port is started and ready and there is |
92 | * at least one phy operational. | |
6f231dda DW |
93 | */ |
94 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, | |
95 | ||
96 | /** | |
de728b7d DJ |
97 | * The substate where the port is started and there was an |
98 | * add/remove phy event. This state is only used in Automatic | |
99 | * Port Configuration Mode (APC) | |
6f231dda DW |
100 | */ |
101 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, | |
102 | ||
103 | SCIC_SDS_PORT_READY_MAX_SUBSTATES | |
104 | }; | |
105 | ||
41e2b905 MT |
106 | /** |
107 | * enum scic_sds_port_states - This enumeration depicts all the states for the | |
108 | * common port state machine. | |
109 | * | |
110 | * | |
111 | */ | |
112 | enum scic_sds_port_states { | |
113 | /** | |
114 | * This state indicates that the port has successfully been stopped. | |
115 | * In this state no new IO operations are permitted. | |
116 | * This state is entered from the STOPPING state. | |
117 | */ | |
118 | SCI_BASE_PORT_STATE_STOPPED, | |
119 | ||
120 | /** | |
121 | * This state indicates that the port is in the process of stopping. | |
122 | * In this state no new IO operations are permitted, but existing IO | |
123 | * operations are allowed to complete. | |
124 | * This state is entered from the READY state. | |
125 | */ | |
126 | SCI_BASE_PORT_STATE_STOPPING, | |
127 | ||
128 | /** | |
129 | * This state indicates the port is now ready. Thus, the user is | |
130 | * able to perform IO operations on this port. | |
131 | * This state is entered from the STARTING state. | |
132 | */ | |
133 | SCI_BASE_PORT_STATE_READY, | |
134 | ||
135 | /** | |
136 | * This state indicates the port is in the process of performing a hard | |
137 | * reset. Thus, the user is unable to perform IO operations on this | |
138 | * port. | |
139 | * This state is entered from the READY state. | |
140 | */ | |
141 | SCI_BASE_PORT_STATE_RESETTING, | |
142 | ||
143 | /** | |
144 | * This state indicates the port has failed a reset request. This state | |
145 | * is entered when a port reset request times out. | |
146 | * This state is entered from the RESETTING state. | |
147 | */ | |
148 | SCI_BASE_PORT_STATE_FAILED, | |
149 | ||
150 | SCI_BASE_PORT_MAX_STATES | |
151 | ||
152 | }; | |
6f231dda DW |
153 | |
154 | /** | |
155 | * struct scic_sds_port - | |
156 | * | |
157 | * The core port object provides the the abstraction for an SCU port. | |
158 | */ | |
159 | struct scic_sds_port { | |
160 | /** | |
41e2b905 MT |
161 | * The field specifies that the parent object for the base controller |
162 | * is the base object itself. | |
6f231dda | 163 | */ |
41e2b905 MT |
164 | struct sci_base_object parent; |
165 | ||
166 | /** | |
167 | * This field contains the information for the base port state machine. | |
168 | */ | |
169 | struct sci_base_state_machine state_machine; | |
6f231dda DW |
170 | |
171 | /** | |
de728b7d DJ |
172 | * This field is the port index that is reported to the SCI USER. |
173 | * This allows the actual hardware physical port to change without | |
174 | * the SCI USER getting a different answer for the get port index. | |
6f231dda DW |
175 | */ |
176 | u8 logical_port_index; | |
177 | ||
178 | /** | |
179 | * This field is the port index used to program the SCU hardware. | |
180 | */ | |
181 | u8 physical_port_index; | |
182 | ||
183 | /** | |
de728b7d DJ |
184 | * This field contains the active phy mask for the port. |
185 | * This mask is used in conjunction with the phy state to determine | |
186 | * which phy to select for some port operations. | |
6f231dda DW |
187 | */ |
188 | u8 active_phy_mask; | |
189 | ||
a8d4b9fe TC |
190 | u16 reserved_rni; |
191 | u16 reserved_tci; | |
192 | ||
6f231dda DW |
193 | /** |
194 | * This field contains the count of the io requests started on this port | |
195 | * object. It is used to control controller shutdown. | |
196 | */ | |
197 | u32 started_request_count; | |
198 | ||
199 | /** | |
de728b7d DJ |
200 | * This field contains the number of devices assigned to this port. |
201 | * It is used to control port start requests. | |
6f231dda DW |
202 | */ |
203 | u32 assigned_device_count; | |
204 | ||
205 | /** | |
206 | * This field contains the reason for the port not going ready. It is | |
207 | * assigned in the state handlers and used in the state transition. | |
208 | */ | |
209 | u32 not_ready_reason; | |
210 | ||
211 | /** | |
212 | * This field is the table of phys assigned to the port. | |
213 | */ | |
214 | struct scic_sds_phy *phy_table[SCI_MAX_PHYS]; | |
215 | ||
216 | /** | |
de728b7d DJ |
217 | * This field is a pointer back to the controller that owns this |
218 | * port object. | |
6f231dda DW |
219 | */ |
220 | struct scic_sds_controller *owning_controller; | |
221 | ||
222 | /** | |
223 | * This field contains the port start/stop timer handle. | |
224 | */ | |
225 | void *timer_handle; | |
226 | ||
227 | /** | |
228 | * This field points to the current set of state handlers for this port | |
de728b7d DJ |
229 | * object. These state handlers are assigned at each enter state of |
230 | * the state machine. | |
6f231dda DW |
231 | */ |
232 | struct scic_sds_port_state_handler *state_handlers; | |
233 | ||
234 | /** | |
235 | * This field is the ready substate machine for the port. | |
236 | */ | |
237 | struct sci_base_state_machine ready_substate_machine; | |
238 | ||
239 | /* / Memory mapped hardware register space */ | |
6f231dda DW |
240 | |
241 | /** | |
de728b7d DJ |
242 | * This field is the pointer to the port task scheduler registers |
243 | * for the SCU hardware. | |
6f231dda | 244 | */ |
de728b7d DJ |
245 | struct scu_port_task_scheduler_registers __iomem |
246 | *port_task_scheduler_registers; | |
6f231dda DW |
247 | |
248 | /** | |
de728b7d DJ |
249 | * This field is identical for all port objects and points to the port |
250 | * task scheduler group PE configuration registers. | |
251 | * It is used to assign PEs to a port. | |
6f231dda | 252 | */ |
de728b7d | 253 | u32 *port_pe_configuration_register; |
6f231dda DW |
254 | |
255 | /** | |
256 | * This field is the VIIT register space for ths port object. | |
257 | */ | |
24621466 | 258 | struct scu_viit_entry __iomem *viit_registers; |
6f231dda DW |
259 | |
260 | }; | |
261 | ||
41e2b905 MT |
262 | typedef enum sci_status (*scic_sds_port_handler_t)(struct scic_sds_port *); |
263 | ||
264 | typedef enum sci_status (*scic_sds_port_phy_handler_t)(struct scic_sds_port *, | |
d857d9a0 | 265 | struct scic_sds_phy *); |
41e2b905 MT |
266 | |
267 | typedef enum sci_status (*scic_sds_port_reset_handler_t)(struct scic_sds_port *, | |
268 | u32 timeout); | |
6f231dda | 269 | |
de728b7d | 270 | typedef enum sci_status (*scic_sds_port_event_handler_t)(struct scic_sds_port *, u32); |
6f231dda | 271 | |
de728b7d | 272 | typedef enum sci_status (*scic_sds_port_frame_handler_t)(struct scic_sds_port *, u32); |
6f231dda | 273 | |
de728b7d | 274 | typedef void (*scic_sds_port_link_handler_t)(struct scic_sds_port *, struct scic_sds_phy *); |
6f231dda | 275 | |
41e2b905 MT |
276 | typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_port *, |
277 | struct scic_sds_remote_device *, | |
278 | struct scic_sds_request *); | |
6f231dda DW |
279 | |
280 | struct scic_sds_port_state_handler { | |
41e2b905 MT |
281 | /** |
282 | * The start_handler specifies the method invoked when a user | |
283 | * attempts to start a port. | |
284 | */ | |
285 | scic_sds_port_handler_t start_handler; | |
286 | ||
287 | /** | |
288 | * The stop_handler specifies the method invoked when a user | |
289 | * attempts to stop a port. | |
290 | */ | |
291 | scic_sds_port_handler_t stop_handler; | |
292 | ||
293 | /** | |
294 | * The destruct_handler specifies the method invoked when attempting to | |
295 | * destruct a port. | |
296 | */ | |
297 | scic_sds_port_handler_t destruct_handler; | |
298 | ||
299 | /** | |
300 | * The reset_handler specifies the method invoked when a user | |
301 | * attempts to hard reset a port. | |
302 | */ | |
303 | scic_sds_port_reset_handler_t reset_handler; | |
304 | ||
305 | /** | |
306 | * The add_phy_handler specifies the method invoked when a user | |
307 | * attempts to add another phy into the port. | |
308 | */ | |
309 | scic_sds_port_phy_handler_t add_phy_handler; | |
310 | ||
311 | /** | |
312 | * The remove_phy_handler specifies the method invoked when a user | |
313 | * attempts to remove a phy from the port. | |
314 | */ | |
315 | scic_sds_port_phy_handler_t remove_phy_handler; | |
6f231dda | 316 | |
de728b7d DJ |
317 | scic_sds_port_frame_handler_t frame_handler; |
318 | scic_sds_port_event_handler_t event_handler; | |
6f231dda | 319 | |
de728b7d DJ |
320 | scic_sds_port_link_handler_t link_up_handler; |
321 | scic_sds_port_link_handler_t link_down_handler; | |
6f231dda | 322 | |
de728b7d DJ |
323 | scic_sds_port_io_request_handler_t start_io_handler; |
324 | scic_sds_port_io_request_handler_t complete_io_handler; | |
6f231dda DW |
325 | |
326 | }; | |
327 | ||
6f231dda DW |
328 | /** |
329 | * scic_sds_port_get_controller() - | |
330 | * | |
331 | * Helper macro to get the owning controller of this port | |
332 | */ | |
333 | #define scic_sds_port_get_controller(this_port) \ | |
334 | ((this_port)->owning_controller) | |
335 | ||
6f231dda DW |
336 | /** |
337 | * scic_sds_port_set_base_state_handlers() - | |
338 | * | |
339 | * This macro will change the state handlers to those of the specified state id | |
340 | */ | |
341 | #define scic_sds_port_set_base_state_handlers(this_port, state_id) \ | |
342 | scic_sds_port_set_state_handlers(\ | |
343 | (this_port), &scic_sds_port_state_handler_table[(state_id)]) | |
344 | ||
6f231dda DW |
345 | /** |
346 | * scic_sds_port_set_state_handlers() - | |
347 | * | |
348 | * Helper macro to set the port object state handlers | |
349 | */ | |
350 | #define scic_sds_port_set_state_handlers(this_port, handlers) \ | |
351 | ((this_port)->state_handlers = (handlers)) | |
352 | ||
353 | /** | |
354 | * scic_sds_port_get_index() - | |
355 | * | |
356 | * This macro returns the physical port index for this port object | |
357 | */ | |
358 | #define scic_sds_port_get_index(this_port) \ | |
359 | ((this_port)->physical_port_index) | |
360 | ||
6f231dda | 361 | |
11c88986 DW |
362 | static inline void scic_sds_port_increment_request_count(struct scic_sds_port *sci_port) |
363 | { | |
364 | sci_port->started_request_count++; | |
365 | } | |
366 | ||
367 | static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *sci_port) | |
368 | { | |
369 | if (WARN_ONCE(sci_port->started_request_count == 0, | |
370 | "%s: tried to decrement started_request_count past 0!?", | |
371 | __func__)) | |
372 | /* pass */; | |
373 | else | |
374 | sci_port->started_request_count--; | |
375 | } | |
6f231dda | 376 | |
6f231dda DW |
377 | #define scic_sds_port_active_phy(port, phy) \ |
378 | (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) | |
379 | ||
6f231dda DW |
380 | void scic_sds_port_construct( |
381 | struct scic_sds_port *this_port, | |
382 | u8 port_index, | |
383 | struct scic_sds_controller *owning_controller); | |
384 | ||
385 | enum sci_status scic_sds_port_initialize( | |
386 | struct scic_sds_port *this_port, | |
24621466 HD |
387 | void __iomem *port_task_scheduler_registers, |
388 | void __iomem *port_configuration_regsiter, | |
389 | void __iomem *viit_registers); | |
6f231dda | 390 | |
6f231dda DW |
391 | enum sci_status scic_sds_port_add_phy( |
392 | struct scic_sds_port *this_port, | |
393 | struct scic_sds_phy *the_phy); | |
394 | ||
395 | enum sci_status scic_sds_port_remove_phy( | |
396 | struct scic_sds_port *this_port, | |
397 | struct scic_sds_phy *the_phy); | |
398 | ||
24621466 | 399 | void scic_sds_port_setup_transports( |
6f231dda DW |
400 | struct scic_sds_port *this_port, |
401 | u32 device_id); | |
402 | ||
6f231dda DW |
403 | |
404 | void scic_sds_port_deactivate_phy( | |
405 | struct scic_sds_port *this_port, | |
406 | struct scic_sds_phy *phy, | |
407 | bool do_notify_user); | |
408 | ||
6f231dda DW |
409 | bool scic_sds_port_link_detected( |
410 | struct scic_sds_port *this_port, | |
411 | struct scic_sds_phy *phy); | |
412 | ||
413 | void scic_sds_port_link_up( | |
414 | struct scic_sds_port *this_port, | |
415 | struct scic_sds_phy *phy); | |
416 | ||
417 | void scic_sds_port_link_down( | |
418 | struct scic_sds_port *this_port, | |
419 | struct scic_sds_phy *phy); | |
420 | ||
6f231dda DW |
421 | enum sci_status scic_sds_port_start_io( |
422 | struct scic_sds_port *this_port, | |
423 | struct scic_sds_remote_device *the_device, | |
424 | struct scic_sds_request *the_io_request); | |
425 | ||
426 | enum sci_status scic_sds_port_complete_io( | |
427 | struct scic_sds_port *this_port, | |
428 | struct scic_sds_remote_device *the_device, | |
429 | struct scic_sds_request *the_io_request); | |
430 | ||
6f231dda DW |
431 | enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed( |
432 | struct scic_sds_port *this_port); | |
433 | ||
434 | void scic_sds_port_broadcast_change_received( | |
435 | struct scic_sds_port *this_port, | |
436 | struct scic_sds_phy *this_phy); | |
437 | ||
438 | bool scic_sds_port_is_valid_phy_assignment( | |
439 | struct scic_sds_port *this_port, | |
440 | u32 phy_index); | |
441 | ||
6f231dda DW |
442 | void scic_sds_port_get_sas_address( |
443 | struct scic_sds_port *this_port, | |
444 | struct sci_sas_address *sas_address); | |
445 | ||
446 | void scic_sds_port_get_attached_sas_address( | |
447 | struct scic_sds_port *this_port, | |
448 | struct sci_sas_address *sas_address); | |
449 | ||
450 | void scic_sds_port_get_attached_protocols( | |
451 | struct scic_sds_port *this_port, | |
452 | struct sci_sas_identify_address_frame_protocols *protocols); | |
453 | ||
6f231dda | 454 | #endif /* _SCIC_SDS_PORT_H_ */ |