diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-05-10 02:28:46 -0700 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 04:04:47 -0700 |
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 59505cbf2bb..ea41dcead3a 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -58,7 +58,10 @@ #include <scsi/libsas.h> #include "isci.h" -#include "scic_sds_port.h" +#include "sas.h" +#include "phy.h" + +#define SCIC_SDS_DUMMY_PORT 0xFF struct isci_phy; struct isci_host; @@ -73,6 +76,111 @@ enum isci_status { }; /** + * struct scic_sds_port + * + * The core port object provides the the abstraction for an SCU port. + */ +struct scic_sds_port { + + /** + * This field contains the information for the base port state machine. + */ + struct sci_base_state_machine state_machine; + + /** + * This field is the port index that is reported to the SCI USER. + * This allows the actual hardware physical port to change without + * the SCI USER getting a different answer for the get port index. + */ + u8 logical_port_index; + + /** + * This field is the port index used to program the SCU hardware. + */ + u8 physical_port_index; + + /** + * This field contains the active phy mask for the port. + * This mask is used in conjunction with the phy state to determine + * which phy to select for some port operations. + */ + u8 active_phy_mask; + + u16 reserved_rni; + u16 reserved_tci; + + /** + * This field contains the count of the io requests started on this port + * object. It is used to control controller shutdown. + */ + u32 started_request_count; + + /** + * This field contains the number of devices assigned to this port. + * It is used to control port start requests. + */ + u32 assigned_device_count; + + /** + * This field contains the reason for the port not going ready. It is + * assigned in the state handlers and used in the state transition. + */ + u32 not_ready_reason; + + /** + * This field is the table of phys assigned to the port. + */ + struct scic_sds_phy *phy_table[SCI_MAX_PHYS]; + + /** + * This field is a pointer back to the controller that owns this + * port object. + */ + struct scic_sds_controller *owning_controller; + + /** + * This field contains the port start/stop timer handle. + */ + void *timer_handle; + + /** + * This field points to the current set of state handlers for this port + * object. These state handlers are assigned at each enter state of + * the state machine. + */ + struct scic_sds_port_state_handler *state_handlers; + + /** + * This field is the ready substate machine for the port. + */ + struct sci_base_state_machine ready_substate_machine; + + /* / Memory mapped hardware register space */ + + /** + * This field is the pointer to the port task scheduler registers + * for the SCU hardware. + */ + struct scu_port_task_scheduler_registers __iomem + *port_task_scheduler_registers; + + /** + * This field is identical for all port objects and points to the port + * task scheduler group PE configuration registers. + * It is used to assign PEs to a port. + */ + u32 __iomem *port_pe_configuration_register; + + /** + * This field is the VIIT register space for ths port object. + */ + struct scu_viit_entry __iomem *viit_registers; + +}; + + + +/** * struct isci_port - This class represents the port object used to internally * represent libsas port objects. It also keeps a list of remote device * objects. @@ -99,54 +207,301 @@ static inline struct isci_port *sci_port_to_iport(struct scic_sds_port *sci_port return iport; } -enum isci_status isci_port_get_state( - struct isci_port *isci_port); +enum scic_port_not_ready_reason_code { + SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, + SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, + SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION, + SCIC_PORT_NOT_READY_RECONFIGURING, + + SCIC_PORT_NOT_READY_REASON_CODE_MAX +}; + +struct scic_port_end_point_properties { + struct sci_sas_address sas_address; + struct scic_phy_proto protocols; +}; + +struct scic_port_properties { + u32 index; + struct scic_port_end_point_properties local; + struct scic_port_end_point_properties remote; + u32 phy_mask; +}; + +/** + * enum SCIC_SDS_PORT_READY_SUBSTATES - + * + * This enumeration depicts all of the states for the core port ready substate + * machine. + */ +enum scic_sds_port_ready_substates { + /** + * The substate where the port is started and ready but has no + * active phys. + */ + SCIC_SDS_PORT_READY_SUBSTATE_WAITING, + + /** + * The substate where the port is started and ready and there is + * at least one phy operational. + */ + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, + + /** + * The substate where the port is started and there was an + * add/remove phy event. This state is only used in Automatic + * Port Configuration Mode (APC) + */ + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, + + SCIC_SDS_PORT_READY_MAX_SUBSTATES +}; + +/** + * enum scic_sds_port_states - This enumeration depicts all the states for the + * common port state machine. + * + * + */ +enum scic_sds_port_states { + /** + * This state indicates that the port has successfully been stopped. + * In this state no new IO operations are permitted. + * This state is entered from the STOPPING state. + */ + SCI_BASE_PORT_STATE_STOPPED, + + /** + * This state indicates that the port is in the process of stopping. + * In this state no new IO operations are permitted, but existing IO + * operations are allowed to complete. + * This state is entered from the READY state. + */ + SCI_BASE_PORT_STATE_STOPPING, + + /** + * This state indicates the port is now ready. Thus, the user is + * able to perform IO operations on this port. + * This state is entered from the STARTING state. + */ + SCI_BASE_PORT_STATE_READY, + + /** + * This state indicates the port is in the process of performing a hard + * reset. Thus, the user is unable to perform IO operations on this + * port. + * This state is entered from the READY state. + */ + SCI_BASE_PORT_STATE_RESETTING, + + /** + * This state indicates the port has failed a reset request. This state + * is entered when a port reset request times out. + * This state is entered from the RESETTING state. + */ + SCI_BASE_PORT_STATE_FAILED, + + SCI_BASE_PORT_MAX_STATES + +}; + +struct scic_sds_remote_device; +struct scic_sds_request; + +typedef enum sci_status (*scic_sds_port_handler_t)(struct scic_sds_port *); -void isci_port_formed( - struct asd_sas_phy *); +typedef enum sci_status (*scic_sds_port_phy_handler_t)(struct scic_sds_port *, + struct scic_sds_phy *); -void isci_port_deformed( - struct asd_sas_phy *); +typedef enum sci_status (*scic_sds_port_reset_handler_t)(struct scic_sds_port *, + u32 timeout); -void isci_port_bc_change_received( - struct isci_host *isci_host, - struct scic_sds_port *port, - struct scic_sds_phy *phy); +typedef enum sci_status (*scic_sds_port_event_handler_t)(struct scic_sds_port *, u32); -void isci_port_link_up( - struct isci_host *isci_host, - struct scic_sds_port *port, - struct scic_sds_phy *phy); +typedef enum sci_status (*scic_sds_port_frame_handler_t)(struct scic_sds_port *, u32); -void isci_port_link_down( - struct isci_host *isci_host, - struct isci_phy *isci_phy, - struct isci_port *port); +typedef void (*scic_sds_port_link_handler_t)(struct scic_sds_port *, struct scic_sds_phy *); -void isci_port_ready( - struct isci_host *isci_host, +typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_port *, + struct scic_sds_remote_device *, + struct scic_sds_request *); + +struct scic_sds_port_state_handler { + /** + * The start_handler specifies the method invoked when a user + * attempts to start a port. + */ + scic_sds_port_handler_t start_handler; + + /** + * The stop_handler specifies the method invoked when a user + * attempts to stop a port. + */ + scic_sds_port_handler_t stop_handler; + + /** + * The destruct_handler specifies the method invoked when attempting to + * destruct a port. + */ + scic_sds_port_handler_t destruct_handler; + + /** + * The reset_handler specifies the method invoked when a user + * attempts to hard reset a port. + */ + scic_sds_port_reset_handler_t reset_handler; + + /** + * The add_phy_handler specifies the method invoked when a user + * attempts to add another phy into the port. + */ + scic_sds_port_phy_handler_t add_phy_handler; + + /** + * The remove_phy_handler specifies the method invoked when a user + * attempts to remove a phy from the port. + */ + scic_sds_port_phy_handler_t remove_phy_handler; + + scic_sds_port_frame_handler_t frame_handler; + scic_sds_port_event_handler_t event_handler; + + scic_sds_port_link_handler_t link_up_handler; + scic_sds_port_link_handler_t link_down_handler; + + scic_sds_port_io_request_handler_t start_io_handler; + scic_sds_port_io_request_handler_t complete_io_handler; + +}; + +/** + * scic_sds_port_get_controller() - + * + * Helper macro to get the owning controller of this port + */ +#define scic_sds_port_get_controller(this_port) \ + ((this_port)->owning_controller) + +/** + * scic_sds_port_set_base_state_handlers() - + * + * This macro will change the state handlers to those of the specified state id + */ +#define scic_sds_port_set_base_state_handlers(this_port, state_id) \ + scic_sds_port_set_state_handlers(\ + (this_port), &scic_sds_port_state_handler_table[(state_id)]) + +/** + * scic_sds_port_set_state_handlers() - + * + * Helper macro to set the port object state handlers + */ +#define scic_sds_port_set_state_handlers(this_port, handlers) \ + ((this_port)->state_handlers = (handlers)) + +/** + * scic_sds_port_get_index() - + * + * This macro returns the physical port index for this port object + */ +#define scic_sds_port_get_index(this_port) \ + ((this_port)->physical_port_index) + + +static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *sci_port) +{ + if (WARN_ONCE(sci_port->started_request_count == 0, + "%s: tried to decrement started_request_count past 0!?", + __func__)) + /* pass */; + else + sci_port->started_request_count--; +} + +#define scic_sds_port_active_phy(port, phy) \ + (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) + +void scic_sds_port_construct( + struct scic_sds_port *sci_port, + u8 port_index, + struct scic_sds_controller *scic); + +enum sci_status scic_sds_port_initialize( + struct scic_sds_port *sci_port, + void __iomem *port_task_scheduler_registers, + void __iomem *port_configuration_regsiter, + void __iomem *viit_registers); + +enum sci_status scic_sds_port_add_phy( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +enum sci_status scic_sds_port_remove_phy( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +void scic_sds_port_setup_transports( + struct scic_sds_port *sci_port, + u32 device_id); + + +void scic_sds_port_deactivate_phy( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy, + bool do_notify_user); + +bool scic_sds_port_link_detected( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +void scic_sds_port_link_up( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +void scic_sds_port_link_down( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +enum sci_status scic_sds_port_start_io( + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req); + +enum sci_status scic_sds_port_complete_io( + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req); + +enum sas_linkrate scic_sds_port_get_max_allowed_speed( + struct scic_sds_port *sci_port); + +void scic_sds_port_broadcast_change_received( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +bool scic_sds_port_is_valid_phy_assignment( + struct scic_sds_port *sci_port, + u32 phy_index); + +void scic_sds_port_get_sas_address( + struct scic_sds_port *sci_port, + struct sci_sas_address *sas_address); + +void scic_sds_port_get_attached_sas_address( + struct scic_sds_port *sci_port, + struct sci_sas_address *sas_address); + +enum isci_status isci_port_get_state( struct isci_port *isci_port); -void isci_port_not_ready( - struct isci_host *isci_host, - struct isci_port *port); +void isci_port_formed(struct asd_sas_phy *); +void isci_port_deformed(struct asd_sas_phy *); void isci_port_init( struct isci_port *port, struct isci_host *host, int index); -void isci_port_hard_reset_complete( - struct isci_port *isci_port, - enum sci_status completion_status); - int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, struct isci_phy *iphy); - -void isci_port_stop_complete( - struct scic_sds_controller *scic, - struct scic_sds_port *sci_port, - enum sci_status completion_status); - #endif /* !defined(_ISCI_PORT_H_) */ - |