diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-05-10 05:28:46 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 07:04:47 -0400 |
commit | e2f8db509fdd354bb7a68c86515e9d2d8909ccc9 (patch) | |
tree | e27f2d33290b0c6f7ca20e408ce7f8ff9309dc43 /drivers/scsi/isci/port.h | |
parent | d35bc1bd18ab9e986cfb67c5a281a70cfd717f05 (diff) |
isci: uplevel port infrastructure
* Move port configuration agent implementation
* Merge core/scic_sds_port.[ch] into port.[ch]
Reported-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/port.h')
-rw-r--r-- | drivers/scsi/isci/port.h | 425 |
1 files changed, 390 insertions, 35 deletions
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 59505cbf2bb3..ea41dcead3ae 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h | |||
@@ -58,7 +58,10 @@ | |||
58 | 58 | ||
59 | #include <scsi/libsas.h> | 59 | #include <scsi/libsas.h> |
60 | #include "isci.h" | 60 | #include "isci.h" |
61 | #include "scic_sds_port.h" | 61 | #include "sas.h" |
62 | #include "phy.h" | ||
63 | |||
64 | #define SCIC_SDS_DUMMY_PORT 0xFF | ||
62 | 65 | ||
63 | struct isci_phy; | 66 | struct isci_phy; |
64 | struct isci_host; | 67 | struct isci_host; |
@@ -73,6 +76,111 @@ enum isci_status { | |||
73 | }; | 76 | }; |
74 | 77 | ||
75 | /** | 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 { | ||
84 | |||
85 | /** | ||
86 | * This field contains the information for the base port state machine. | ||
87 | */ | ||
88 | struct sci_base_state_machine state_machine; | ||
89 | |||
90 | /** | ||
91 | * This field is the port index that is reported to the SCI USER. | ||
92 | * This allows the actual hardware physical port to change without | ||
93 | * the SCI USER getting a different answer for the get port index. | ||
94 | */ | ||
95 | u8 logical_port_index; | ||
96 | |||
97 | /** | ||
98 | * This field is the port index used to program the SCU hardware. | ||
99 | */ | ||
100 | u8 physical_port_index; | ||
101 | |||
102 | /** | ||
103 | * This field contains the active phy mask for the port. | ||
104 | * This mask is used in conjunction with the phy state to determine | ||
105 | * which phy to select for some port operations. | ||
106 | */ | ||
107 | u8 active_phy_mask; | ||
108 | |||
109 | u16 reserved_rni; | ||
110 | u16 reserved_tci; | ||
111 | |||
112 | /** | ||
113 | * This field contains the count of the io requests started on this port | ||
114 | * object. It is used to control controller shutdown. | ||
115 | */ | ||
116 | u32 started_request_count; | ||
117 | |||
118 | /** | ||
119 | * This field contains the number of devices assigned to this port. | ||
120 | * It is used to control port start requests. | ||
121 | */ | ||
122 | u32 assigned_device_count; | ||
123 | |||
124 | /** | ||
125 | * This field contains the reason for the port not going ready. It is | ||
126 | * assigned in the state handlers and used in the state transition. | ||
127 | */ | ||
128 | u32 not_ready_reason; | ||
129 | |||
130 | /** | ||
131 | * This field is the table of phys assigned to the port. | ||
132 | */ | ||
133 | struct scic_sds_phy *phy_table[SCI_MAX_PHYS]; | ||
134 | |||
135 | /** | ||
136 | * This field is a pointer back to the controller that owns this | ||
137 | * port object. | ||
138 | */ | ||
139 | struct scic_sds_controller *owning_controller; | ||
140 | |||
141 | /** | ||
142 | * This field contains the port start/stop timer handle. | ||
143 | */ | ||
144 | void *timer_handle; | ||
145 | |||
146 | /** | ||
147 | * This field points to the current set of state handlers for this port | ||
148 | * object. These state handlers are assigned at each enter state of | ||
149 | * the state machine. | ||
150 | */ | ||
151 | struct scic_sds_port_state_handler *state_handlers; | ||
152 | |||
153 | /** | ||
154 | * This field is the ready substate machine for the port. | ||
155 | */ | ||
156 | struct sci_base_state_machine ready_substate_machine; | ||
157 | |||
158 | /* / Memory mapped hardware register space */ | ||
159 | |||
160 | /** | ||
161 | * This field is the pointer to the port task scheduler registers | ||
162 | * for the SCU hardware. | ||
163 | */ | ||
164 | struct scu_port_task_scheduler_registers __iomem | ||
165 | *port_task_scheduler_registers; | ||
166 | |||
167 | /** | ||
168 | * This field is identical for all port objects and points to the port | ||
169 | * task scheduler group PE configuration registers. | ||
170 | * It is used to assign PEs to a port. | ||
171 | */ | ||
172 | u32 __iomem *port_pe_configuration_register; | ||
173 | |||
174 | /** | ||
175 | * This field is the VIIT register space for ths port object. | ||
176 | */ | ||
177 | struct scu_viit_entry __iomem *viit_registers; | ||
178 | |||
179 | }; | ||
180 | |||
181 | |||
182 | |||
183 | /** | ||
76 | * struct isci_port - This class represents the port object used to internally | 184 | * struct isci_port - This class represents the port object used to internally |
77 | * represent libsas port objects. It also keeps a list of remote device | 185 | * represent libsas port objects. It also keeps a list of remote device |
78 | * objects. | 186 | * objects. |
@@ -99,54 +207,301 @@ static inline struct isci_port *sci_port_to_iport(struct scic_sds_port *sci_port | |||
99 | return iport; | 207 | return iport; |
100 | } | 208 | } |
101 | 209 | ||
102 | enum isci_status isci_port_get_state( | 210 | enum scic_port_not_ready_reason_code { |
103 | struct isci_port *isci_port); | 211 | SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, |
212 | SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, | ||
213 | SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION, | ||
214 | SCIC_PORT_NOT_READY_RECONFIGURING, | ||
215 | |||
216 | SCIC_PORT_NOT_READY_REASON_CODE_MAX | ||
217 | }; | ||
218 | |||
219 | struct scic_port_end_point_properties { | ||
220 | struct sci_sas_address sas_address; | ||
221 | struct scic_phy_proto protocols; | ||
222 | }; | ||
223 | |||
224 | struct scic_port_properties { | ||
225 | u32 index; | ||
226 | struct scic_port_end_point_properties local; | ||
227 | struct scic_port_end_point_properties remote; | ||
228 | u32 phy_mask; | ||
229 | }; | ||
230 | |||
231 | /** | ||
232 | * enum SCIC_SDS_PORT_READY_SUBSTATES - | ||
233 | * | ||
234 | * This enumeration depicts all of the states for the core port ready substate | ||
235 | * machine. | ||
236 | */ | ||
237 | enum scic_sds_port_ready_substates { | ||
238 | /** | ||
239 | * The substate where the port is started and ready but has no | ||
240 | * active phys. | ||
241 | */ | ||
242 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING, | ||
243 | |||
244 | /** | ||
245 | * The substate where the port is started and ready and there is | ||
246 | * at least one phy operational. | ||
247 | */ | ||
248 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, | ||
249 | |||
250 | /** | ||
251 | * The substate where the port is started and there was an | ||
252 | * add/remove phy event. This state is only used in Automatic | ||
253 | * Port Configuration Mode (APC) | ||
254 | */ | ||
255 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, | ||
256 | |||
257 | SCIC_SDS_PORT_READY_MAX_SUBSTATES | ||
258 | }; | ||
259 | |||
260 | /** | ||
261 | * enum scic_sds_port_states - This enumeration depicts all the states for the | ||
262 | * common port state machine. | ||
263 | * | ||
264 | * | ||
265 | */ | ||
266 | enum scic_sds_port_states { | ||
267 | /** | ||
268 | * This state indicates that the port has successfully been stopped. | ||
269 | * In this state no new IO operations are permitted. | ||
270 | * This state is entered from the STOPPING state. | ||
271 | */ | ||
272 | SCI_BASE_PORT_STATE_STOPPED, | ||
273 | |||
274 | /** | ||
275 | * This state indicates that the port is in the process of stopping. | ||
276 | * In this state no new IO operations are permitted, but existing IO | ||
277 | * operations are allowed to complete. | ||
278 | * This state is entered from the READY state. | ||
279 | */ | ||
280 | SCI_BASE_PORT_STATE_STOPPING, | ||
281 | |||
282 | /** | ||
283 | * This state indicates the port is now ready. Thus, the user is | ||
284 | * able to perform IO operations on this port. | ||
285 | * This state is entered from the STARTING state. | ||
286 | */ | ||
287 | SCI_BASE_PORT_STATE_READY, | ||
288 | |||
289 | /** | ||
290 | * This state indicates the port is in the process of performing a hard | ||
291 | * reset. Thus, the user is unable to perform IO operations on this | ||
292 | * port. | ||
293 | * This state is entered from the READY state. | ||
294 | */ | ||
295 | SCI_BASE_PORT_STATE_RESETTING, | ||
296 | |||
297 | /** | ||
298 | * This state indicates the port has failed a reset request. This state | ||
299 | * is entered when a port reset request times out. | ||
300 | * This state is entered from the RESETTING state. | ||
301 | */ | ||
302 | SCI_BASE_PORT_STATE_FAILED, | ||
303 | |||
304 | SCI_BASE_PORT_MAX_STATES | ||
305 | |||
306 | }; | ||
307 | |||
308 | struct scic_sds_remote_device; | ||
309 | struct scic_sds_request; | ||
310 | |||
311 | typedef enum sci_status (*scic_sds_port_handler_t)(struct scic_sds_port *); | ||
104 | 312 | ||
105 | void isci_port_formed( | 313 | typedef enum sci_status (*scic_sds_port_phy_handler_t)(struct scic_sds_port *, |
106 | struct asd_sas_phy *); | 314 | struct scic_sds_phy *); |
107 | 315 | ||
108 | void isci_port_deformed( | 316 | typedef enum sci_status (*scic_sds_port_reset_handler_t)(struct scic_sds_port *, |
109 | struct asd_sas_phy *); | 317 | u32 timeout); |
110 | 318 | ||
111 | void isci_port_bc_change_received( | 319 | typedef enum sci_status (*scic_sds_port_event_handler_t)(struct scic_sds_port *, u32); |
112 | struct isci_host *isci_host, | ||
113 | struct scic_sds_port *port, | ||
114 | struct scic_sds_phy *phy); | ||
115 | 320 | ||
116 | void isci_port_link_up( | 321 | typedef enum sci_status (*scic_sds_port_frame_handler_t)(struct scic_sds_port *, u32); |
117 | struct isci_host *isci_host, | ||
118 | struct scic_sds_port *port, | ||
119 | struct scic_sds_phy *phy); | ||
120 | 322 | ||
121 | void isci_port_link_down( | 323 | typedef void (*scic_sds_port_link_handler_t)(struct scic_sds_port *, struct scic_sds_phy *); |
122 | struct isci_host *isci_host, | ||
123 | struct isci_phy *isci_phy, | ||
124 | struct isci_port *port); | ||
125 | 324 | ||
126 | void isci_port_ready( | 325 | typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_port *, |
127 | struct isci_host *isci_host, | 326 | struct scic_sds_remote_device *, |
327 | struct scic_sds_request *); | ||
328 | |||
329 | struct scic_sds_port_state_handler { | ||
330 | /** | ||
331 | * The start_handler specifies the method invoked when a user | ||
332 | * attempts to start a port. | ||
333 | */ | ||
334 | scic_sds_port_handler_t start_handler; | ||
335 | |||
336 | /** | ||
337 | * The stop_handler specifies the method invoked when a user | ||
338 | * attempts to stop a port. | ||
339 | */ | ||
340 | scic_sds_port_handler_t stop_handler; | ||
341 | |||
342 | /** | ||
343 | * The destruct_handler specifies the method invoked when attempting to | ||
344 | * destruct a port. | ||
345 | */ | ||
346 | scic_sds_port_handler_t destruct_handler; | ||
347 | |||
348 | /** | ||
349 | * The reset_handler specifies the method invoked when a user | ||
350 | * attempts to hard reset a port. | ||
351 | */ | ||
352 | scic_sds_port_reset_handler_t reset_handler; | ||
353 | |||
354 | /** | ||
355 | * The add_phy_handler specifies the method invoked when a user | ||
356 | * attempts to add another phy into the port. | ||
357 | */ | ||
358 | scic_sds_port_phy_handler_t add_phy_handler; | ||
359 | |||
360 | /** | ||
361 | * The remove_phy_handler specifies the method invoked when a user | ||
362 | * attempts to remove a phy from the port. | ||
363 | */ | ||
364 | scic_sds_port_phy_handler_t remove_phy_handler; | ||
365 | |||
366 | scic_sds_port_frame_handler_t frame_handler; | ||
367 | scic_sds_port_event_handler_t event_handler; | ||
368 | |||
369 | scic_sds_port_link_handler_t link_up_handler; | ||
370 | scic_sds_port_link_handler_t link_down_handler; | ||
371 | |||
372 | scic_sds_port_io_request_handler_t start_io_handler; | ||
373 | scic_sds_port_io_request_handler_t complete_io_handler; | ||
374 | |||
375 | }; | ||
376 | |||
377 | /** | ||
378 | * scic_sds_port_get_controller() - | ||
379 | * | ||
380 | * Helper macro to get the owning controller of this port | ||
381 | */ | ||
382 | #define scic_sds_port_get_controller(this_port) \ | ||
383 | ((this_port)->owning_controller) | ||
384 | |||
385 | /** | ||
386 | * scic_sds_port_set_base_state_handlers() - | ||
387 | * | ||
388 | * This macro will change the state handlers to those of the specified state id | ||
389 | */ | ||
390 | #define scic_sds_port_set_base_state_handlers(this_port, state_id) \ | ||
391 | scic_sds_port_set_state_handlers(\ | ||
392 | (this_port), &scic_sds_port_state_handler_table[(state_id)]) | ||
393 | |||
394 | /** | ||
395 | * scic_sds_port_set_state_handlers() - | ||
396 | * | ||
397 | * Helper macro to set the port object state handlers | ||
398 | */ | ||
399 | #define scic_sds_port_set_state_handlers(this_port, handlers) \ | ||
400 | ((this_port)->state_handlers = (handlers)) | ||
401 | |||
402 | /** | ||
403 | * scic_sds_port_get_index() - | ||
404 | * | ||
405 | * This macro returns the physical port index for this port object | ||
406 | */ | ||
407 | #define scic_sds_port_get_index(this_port) \ | ||
408 | ((this_port)->physical_port_index) | ||
409 | |||
410 | |||
411 | static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *sci_port) | ||
412 | { | ||
413 | if (WARN_ONCE(sci_port->started_request_count == 0, | ||
414 | "%s: tried to decrement started_request_count past 0!?", | ||
415 | __func__)) | ||
416 | /* pass */; | ||
417 | else | ||
418 | sci_port->started_request_count--; | ||
419 | } | ||
420 | |||
421 | #define scic_sds_port_active_phy(port, phy) \ | ||
422 | (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) | ||
423 | |||
424 | void scic_sds_port_construct( | ||
425 | struct scic_sds_port *sci_port, | ||
426 | u8 port_index, | ||
427 | struct scic_sds_controller *scic); | ||
428 | |||
429 | enum sci_status scic_sds_port_initialize( | ||
430 | struct scic_sds_port *sci_port, | ||
431 | void __iomem *port_task_scheduler_registers, | ||
432 | void __iomem *port_configuration_regsiter, | ||
433 | void __iomem *viit_registers); | ||
434 | |||
435 | enum sci_status scic_sds_port_add_phy( | ||
436 | struct scic_sds_port *sci_port, | ||
437 | struct scic_sds_phy *sci_phy); | ||
438 | |||
439 | enum sci_status scic_sds_port_remove_phy( | ||
440 | struct scic_sds_port *sci_port, | ||
441 | struct scic_sds_phy *sci_phy); | ||
442 | |||
443 | void scic_sds_port_setup_transports( | ||
444 | struct scic_sds_port *sci_port, | ||
445 | u32 device_id); | ||
446 | |||
447 | |||
448 | void scic_sds_port_deactivate_phy( | ||
449 | struct scic_sds_port *sci_port, | ||
450 | struct scic_sds_phy *sci_phy, | ||
451 | bool do_notify_user); | ||
452 | |||
453 | bool scic_sds_port_link_detected( | ||
454 | struct scic_sds_port *sci_port, | ||
455 | struct scic_sds_phy *sci_phy); | ||
456 | |||
457 | void scic_sds_port_link_up( | ||
458 | struct scic_sds_port *sci_port, | ||
459 | struct scic_sds_phy *sci_phy); | ||
460 | |||
461 | void scic_sds_port_link_down( | ||
462 | struct scic_sds_port *sci_port, | ||
463 | struct scic_sds_phy *sci_phy); | ||
464 | |||
465 | enum sci_status scic_sds_port_start_io( | ||
466 | struct scic_sds_port *sci_port, | ||
467 | struct scic_sds_remote_device *sci_dev, | ||
468 | struct scic_sds_request *sci_req); | ||
469 | |||
470 | enum sci_status scic_sds_port_complete_io( | ||
471 | struct scic_sds_port *sci_port, | ||
472 | struct scic_sds_remote_device *sci_dev, | ||
473 | struct scic_sds_request *sci_req); | ||
474 | |||
475 | enum sas_linkrate scic_sds_port_get_max_allowed_speed( | ||
476 | struct scic_sds_port *sci_port); | ||
477 | |||
478 | void scic_sds_port_broadcast_change_received( | ||
479 | struct scic_sds_port *sci_port, | ||
480 | struct scic_sds_phy *sci_phy); | ||
481 | |||
482 | bool scic_sds_port_is_valid_phy_assignment( | ||
483 | struct scic_sds_port *sci_port, | ||
484 | u32 phy_index); | ||
485 | |||
486 | void scic_sds_port_get_sas_address( | ||
487 | struct scic_sds_port *sci_port, | ||
488 | struct sci_sas_address *sas_address); | ||
489 | |||
490 | void scic_sds_port_get_attached_sas_address( | ||
491 | struct scic_sds_port *sci_port, | ||
492 | struct sci_sas_address *sas_address); | ||
493 | |||
494 | enum isci_status isci_port_get_state( | ||
128 | struct isci_port *isci_port); | 495 | struct isci_port *isci_port); |
129 | 496 | ||
130 | void isci_port_not_ready( | 497 | void isci_port_formed(struct asd_sas_phy *); |
131 | struct isci_host *isci_host, | 498 | void isci_port_deformed(struct asd_sas_phy *); |
132 | struct isci_port *port); | ||
133 | 499 | ||
134 | void isci_port_init( | 500 | void isci_port_init( |
135 | struct isci_port *port, | 501 | struct isci_port *port, |
136 | struct isci_host *host, | 502 | struct isci_host *host, |
137 | int index); | 503 | int index); |
138 | 504 | ||
139 | void isci_port_hard_reset_complete( | ||
140 | struct isci_port *isci_port, | ||
141 | enum sci_status completion_status); | ||
142 | |||
143 | int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, | 505 | int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, |
144 | struct isci_phy *iphy); | 506 | struct isci_phy *iphy); |
145 | |||
146 | void isci_port_stop_complete( | ||
147 | struct scic_sds_controller *scic, | ||
148 | struct scic_sds_port *sci_port, | ||
149 | enum sci_status completion_status); | ||
150 | |||
151 | #endif /* !defined(_ISCI_PORT_H_) */ | 507 | #endif /* !defined(_ISCI_PORT_H_) */ |
152 | |||