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>
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
index 59505cb..ea41dce 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 @@
 };
 
 /**
+ * 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 @@
 	return iport;
 }
 
+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 *);
+
+typedef enum sci_status (*scic_sds_port_phy_handler_t)(struct scic_sds_port *,
+						       struct scic_sds_phy *);
+
+typedef enum sci_status (*scic_sds_port_reset_handler_t)(struct scic_sds_port *,
+							 u32 timeout);
+
+typedef enum sci_status (*scic_sds_port_event_handler_t)(struct scic_sds_port *, u32);
+
+typedef enum sci_status (*scic_sds_port_frame_handler_t)(struct scic_sds_port *, u32);
+
+typedef void (*scic_sds_port_link_handler_t)(struct scic_sds_port *, struct scic_sds_phy *);
+
+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_formed(
-	struct asd_sas_phy *);
-
-void isci_port_deformed(
-	struct asd_sas_phy *);
-
-void isci_port_bc_change_received(
-	struct isci_host *isci_host,
-	struct scic_sds_port *port,
-	struct scic_sds_phy *phy);
-
-void isci_port_link_up(
-	struct isci_host *isci_host,
-	struct scic_sds_port *port,
-	struct scic_sds_phy *phy);
-
-void isci_port_link_down(
-	struct isci_host *isci_host,
-	struct isci_phy *isci_phy,
-	struct isci_port *port);
-
-void isci_port_ready(
-	struct isci_host *isci_host,
-	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_) */
-