isci: Move transport layer registers from port to phy
authorHenryk Dembkowski <Henryk.Dembkowski@intel.com>
Wed, 23 Feb 2011 08:08:52 +0000 (00:08 -0800)
committerDan Williams <dan.j.williams@intel.com>
Sun, 3 Jul 2011 10:55:27 +0000 (03:55 -0700)
At init and RNC resume we need to touch every phy in a port to be sure
we have initialized STP properties in the case where port_index !=
phy_index.  Also add some missing __iomem annotations.

Signed-off-by: Henryk Dembkowski <henryk.dembkowski@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/scsi/isci/core/scic_sds_controller.c
drivers/scsi/isci/core/scic_sds_phy.c
drivers/scsi/isci/core/scic_sds_phy.h
drivers/scsi/isci/core/scic_sds_phy_registers.h
drivers/scsi/isci/core/scic_sds_port.c
drivers/scsi/isci/core/scic_sds_port.h
drivers/scsi/isci/core/scic_sds_port_registers.h
drivers/scsi/isci/core/scic_sds_remote_device.c
drivers/scsi/isci/core/scic_sds_remote_node_context.c

index 1cbb91c..e597c6b 100644 (file)
@@ -2919,6 +2919,7 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(
                     index++) {
                        result = scic_sds_phy_initialize(
                                &this_controller->phy_table[index],
+                               &this_controller->scu_registers->peg0.pe[index].tl,
                                &this_controller->scu_registers->peg0.pe[index].ll
                                );
                }
@@ -2932,7 +2933,6 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(
                     index++) {
                        result = scic_sds_port_initialize(
                                &this_controller->port_table[index],
-                               &this_controller->scu_registers->peg0.pe[index].tl,
                                &this_controller->scu_registers->peg0.ptsg.port[index],
                                &this_controller->scu_registers->peg0.ptsg.protocol_engine,
                                &this_controller->scu_registers->peg0.viit[index]
index 98e9179..bd0a6ba 100644 (file)
@@ -62,6 +62,7 @@
 #include "scic_sds_phy.h"
 #include "scic_sds_phy_registers.h"
 #include "scic_sds_port.h"
+#include "scic_sds_remote_node_context.h"
 #include "scic_user_callback.h"
 #include "sci_environment.h"
 #include "sci_util.h"
@@ -84,6 +85,31 @@ enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy)
  * ***************************************************************************** */
 
 /**
+ * This method will initialize the phy transport layer registers
+ * @this_phy:
+ * @transport_layer_registers
+ *
+ * enum sci_status
+ */
+static enum sci_status scic_sds_phy_transport_layer_initialization(
+       struct scic_sds_phy *this_phy,
+       struct scu_transport_layer_registers __iomem *transport_layer_registers)
+{
+       u32 tl_control;
+
+       this_phy->transport_layer_registers = transport_layer_registers;
+
+       SCU_STPTLDARNI_WRITE(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);
+
+       /* Hardware team recommends that we enable the STP prefetch for all transports */
+       tl_control = SCU_TLCR_READ(this_phy);
+       tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH);
+       SCU_TLCR_WRITE(this_phy, tl_control);
+
+       return SCI_SUCCESS;
+}
+
+/**
  * This method will initialize the phy link layer registers
  * @this_phy:
  * @link_layer_registers:
@@ -92,7 +118,7 @@ enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy)
  */
 static enum sci_status scic_sds_phy_link_layer_initialization(
        struct scic_sds_phy *this_phy,
-       struct scu_link_layer_registers *link_layer_registers)
+       struct scu_link_layer_registers __iomem *link_layer_registers)
 {
        u32 phy_configuration;
        struct sas_capabilities phy_capabilities;
@@ -361,7 +387,8 @@ void scic_sds_phy_set_port(
  */
 enum sci_status scic_sds_phy_initialize(
        struct scic_sds_phy *sci_phy,
-       struct scu_link_layer_registers *link_layer_registers)
+       struct scu_transport_layer_registers __iomem *transport_layer_registers,
+       struct scu_link_layer_registers __iomem *link_layer_registers)
 {
        /* Create the SIGNATURE FIS Timeout timer for this phy */
        sci_phy->sata_timeout_timer = scic_cb_timer_create(
@@ -370,6 +397,9 @@ enum sci_status scic_sds_phy_initialize(
                sci_phy
                );
 
+       /* Perfrom the initialization of the TL hardware */
+       scic_sds_phy_transport_layer_initialization(sci_phy, transport_layer_registers);
+
        /* Perofrm the initialization of the PE hardware */
        scic_sds_phy_link_layer_initialization(sci_phy, link_layer_registers);
 
@@ -384,6 +414,31 @@ enum sci_status scic_sds_phy_initialize(
        return SCI_SUCCESS;
 }
 
+/**
+ * This method assigns the direct attached device ID for this phy.
+ *
+ * @this_phy The phy for which the direct attached device id is to
+ *       be assigned.
+ * @device_id The direct attached device ID to assign to the phy.
+ *       This will either be the RNi for the device or an invalid RNi if there
+ *       is no current device assigned to the phy.
+ */
+void scic_sds_phy_setup_transport(
+       struct scic_sds_phy *this_phy,
+       u32 device_id)
+{
+       u32 tl_control;
+
+       SCU_STPTLDARNI_WRITE(this_phy, device_id);
+
+       /*
+        * The read should guarantee that the first write gets posted
+        * before the next write
+        */
+       tl_control = SCU_TLCR_READ(this_phy);
+       tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
+       SCU_TLCR_WRITE(this_phy, tl_control);
+}
 
 /**
  *
@@ -398,10 +453,9 @@ void scic_sds_phy_suspend(
        u32 scu_sas_pcfg_value;
 
        scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy);
-
        scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
-
        SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value);
+       scic_sds_phy_setup_transport(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);
 }
 
 /**
index 9ba09bb..dc450c3 100644 (file)
@@ -248,9 +248,15 @@ struct scic_sds_phy {
        struct sci_base_state_machine starting_substate_machine;
 
        /**
+        * This field is the pointer to the transport layer register for the SCU
+        * hardware.
+        */
+       struct scu_transport_layer_registers __iomem *transport_layer_registers;
+
+       /**
         * This field points to the link layer register set within the SCU.
         */
-       struct scu_link_layer_registers *link_layer_registers;
+       struct scu_link_layer_registers __iomem *link_layer_registers;
 
 };
 
@@ -383,7 +389,8 @@ void scic_sds_phy_set_port(
 
 enum sci_status scic_sds_phy_initialize(
        struct scic_sds_phy *this_phy,
-       struct scu_link_layer_registers *link_layer_registers);
+       struct scu_transport_layer_registers __iomem *transport_layer_registers,
+       struct scu_link_layer_registers __iomem *link_layer_registers);
 
 enum sci_status scic_sds_phy_start(
        struct scic_sds_phy *this_phy);
@@ -402,6 +409,10 @@ void scic_sds_phy_suspend(
 void scic_sds_phy_resume(
        struct scic_sds_phy *this_phy);
 
+void scic_sds_phy_setup_transport(
+       struct scic_sds_phy *this_phy,
+       u32 device_id);
+
 /* --------------------------------------------------------------------------- */
 
 enum sci_status scic_sds_phy_event_handler(
index 7883819..2842176 100644 (file)
 
 #include "scic_sds_controller.h"
 
+/* **************************************************************************
+ * * SCU TRANSPORT LAYER REGISTER OPERATIONS
+ * ************************************************************************** */
+
+/**
+ * Macro to read the transport layer register associated with this phy
+ * object.
+ */
+#define scu_transport_layer_read(phy, reg) \
+       scu_register_read( \
+               scic_sds_phy_get_controller(phy), \
+               (phy)->transport_layer_registers->reg \
+               )
+
+/**
+ * Macro to write the transport layer register associated with this phy
+ * object.
+ */
+#define scu_transport_layer_write(phy, reg, value) \
+       scu_register_write( \
+               scic_sds_phy_get_controller(phy), \
+               (phy)->transport_layer_registers->reg, \
+               (value) \
+               )
+
+/* **************************************************************************
+ * * Transport Layer registers controlled by the phy object
+ * ************************************************************************** */
+
+/* This macro reads the Transport layer control register */
+#define SCU_TLCR_READ(phy) \
+       scu_transport_layer_read(phy, control)
+
+/* This macro writes the Transport layer control register */
+#define SCU_TLCR_WRITE(phy, value) \
+       scu_transport_layer_write(phy, control, value)
+
+/* This macro reads the Transport layer address translation register */
+#define SCU_TLADTR_READ(phy) \
+       scu_transport_layer_read(phy, address_translation)
+
+/* This macro writes the Transport layer address translation register */
+#define SCU_TLADTR_WRITE(phy) \
+       scu_transport_layer_write(phy, address_translation, value)
+
+/* This macro writes the STP Transport Layer Direct Attached RNi register */
+#define SCU_STPTLDARNI_WRITE(phy, index) \
+       scu_transport_layer_write(phy, stp_rni, index)
+
+/* This macro reads the STP Transport Layer Direct Attached RNi register */
+#define SCU_STPTLDARNI_READ(phy) \
+       scu_transport_layer_read(phy, stp_rni)
+
 /*
  * *****************************************************************************
  * * SCU LINK LAYER REGISTER OPERATIONS
index ff06f8c..b8acc23 100644 (file)
@@ -531,7 +531,6 @@ void scic_sds_port_construct(
 
        this_port->timer_handle = NULL;
 
-       this_port->transport_layer_registers = NULL;
        this_port->port_task_scheduler_registers = NULL;
 
        for (index = 0; index < SCI_MAX_PHYS; index++) {
@@ -553,30 +552,14 @@ void scic_sds_port_construct(
  */
 enum sci_status scic_sds_port_initialize(
        struct scic_sds_port *this_port,
-       void *transport_layer_registers,
-       void *port_task_scheduler_registers,
-       void *port_configuration_regsiter,
-       void *viit_registers)
+       void __iomem *port_task_scheduler_registers,
+       void __iomem *port_configuration_regsiter,
+       void __iomem *viit_registers)
 {
-       u32 tl_control;
-
-       this_port->transport_layer_registers      = transport_layer_registers;
        this_port->port_task_scheduler_registers  = port_task_scheduler_registers;
        this_port->port_pe_configuration_register = port_configuration_regsiter;
        this_port->viit_registers                 = viit_registers;
 
-       scic_sds_port_set_direct_attached_device_id(
-               this_port,
-               SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
-               );
-
-       /*
-        * Hardware team recommends that we enable the STP prefetch
-        * for all ports */
-       tl_control = SCU_TLCR_READ(this_port);
-       tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH);
-       SCU_TLCR_WRITE(this_port, tl_control);
-
        /*
         * If this is not the dummy port make the assignment of
         * the timer and start the state machine */
@@ -693,29 +676,25 @@ enum sci_status scic_port_hard_reset(
 }
 
 /**
- *
- * @this_port: The port for which the direct attached device id is to be
- *    assigned.
- *
  * This method assigns the direct attached device ID for this port.
+ *
+ * @param[in] this_port The port for which the direct attached device id is to
+ *       be assigned.
+ * @param[in] device_id The direct attached device ID to assign to the port.
+ *       This will be the RNi for the device
  */
-void scic_sds_port_set_direct_attached_device_id(
+void scic_sds_port_setup_transports(
        struct scic_sds_port *this_port,
        u32 device_id)
 {
-       u32 tl_control;
-
-       SCU_STPTLDARNI_WRITE(this_port, device_id);
+       u8 index;
 
-       /*
-        * The read should guarntee that the first write gets posted
-        * before the next write */
-       tl_control = SCU_TLCR_READ(this_port);
-       tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
-       SCU_TLCR_WRITE(this_port, tl_control);
+       for (index = 0; index < SCI_MAX_PHYS; index++) {
+               if (this_port->active_phy_mask & (1 << index))
+                       scic_sds_phy_setup_transport(this_port->phy_table[index], device_id);
+       }
 }
 
-
 /**
  *
  * @this_port: This is the port on which the phy should be enabled.
@@ -1550,16 +1529,12 @@ static void scic_sds_port_suspend_port_task_scheduler(
        struct scic_sds_port *this_port)
 {
        u32 pts_control_value;
-       u32 tl_control_value;
 
        pts_control_value = scu_port_task_scheduler_read(this_port, control);
-       tl_control_value = scu_transport_layer_read(this_port, control);
 
        pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND);
-       tl_control_value  |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
 
        scu_port_task_scheduler_write(this_port, control, pts_control_value);
-       scu_transport_layer_write(this_port, control, tl_control_value);
 }
 
 /**
@@ -2624,11 +2599,6 @@ static void scic_sds_port_resetting_state_enter(
        scic_sds_port_set_base_state_handlers(
                this_port, SCI_BASE_PORT_STATE_RESETTING
                );
-
-       scic_sds_port_set_direct_attached_device_id(
-               this_port,
-               SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
-               );
 }
 
 /**
index 56c15fc..3eb80cb 100644 (file)
@@ -180,17 +180,12 @@ struct scic_sds_port {
        struct sci_base_state_machine ready_substate_machine;
 
        /* / Memory mapped hardware register space */
-       /**
-        * This field is the pointer to the transport layer register for the SCU
-        * hardware.
-        */
-       struct scu_transport_layer_registers *transport_layer_registers;
 
        /**
         * This field is the pointer to the port task scheduler registers for the SCU
         * hardware.
         */
-       struct scu_port_task_scheduler_registers *port_task_scheduler_registers;
+       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
@@ -202,7 +197,7 @@ struct scic_sds_port {
        /**
         * This field is the VIIT register space for ths port object.
         */
-       struct scu_viit_entry *viit_registers;
+       struct scu_viit_entry __iomem *viit_registers;
 
 };
 
@@ -345,10 +340,9 @@ void scic_sds_port_construct(
 
 enum sci_status scic_sds_port_initialize(
        struct scic_sds_port *this_port,
-       void *transport_layer_registers,
-       void *port_task_scheduler_registers,
-       void *port_configuration_regsiter,
-       void *viit_registers);
+       void __iomem *port_task_scheduler_registers,
+       void __iomem *port_configuration_regsiter,
+       void __iomem *viit_registers);
 
 /* --------------------------------------------------------------------------- */
 
@@ -360,7 +354,7 @@ enum sci_status scic_sds_port_remove_phy(
        struct scic_sds_port *this_port,
        struct scic_sds_phy *the_phy);
 
-void scic_sds_port_set_direct_attached_device_id(
+void scic_sds_port_setup_transports(
        struct scic_sds_port *this_port,
        u32 device_id);
 
index cf8bc07..dbe82d8 100644 (file)
  */
 
 /**
- * scu_transport_layer_read() -
- *
- * Macro to read the transport layer register associated with this port object.
- */
-#define scu_transport_layer_read(port, reg) \
-       scu_register_read(\
-               scic_sds_port_get_controller(port), \
-               (port)->transport_layer_registers->reg \
-               )
-
-/**
- * scu_transport_layer_write() -
- *
- * Macro to write the transport layer register associated with this port object.
- */
-#define scu_transport_layer_write(port, reg, value) \
-       scu_register_write(\
-               scic_sds_port_get_controller(port), \
-               (port)->transport_layer_registers->reg, \
-               (value) \
-               )
-
-/**
  * scu_port_task_scheduler_read() -
  *
  * Macro to read the port task scheduler register associated with this port
 
 /*
  * ****************************************************************************
- * * Transport Layer registers controlled by the port object
- * **************************************************************************** */
-
-/**
- * SCU_TLCR_READ() -
- *
- * This macro reads the Transport layer control register
- */
-#define SCU_TLCR_READ(port) \
-       scu_transport_layer_read(port, control)
-
-/**
- * SCU_TLCR_WRITE() -
- *
- * This macro writes the Transport layer control register
- */
-#define SCU_TLCR_WRITE(port, value) \
-       scu_transport_layer_write(port, control, value)
-
-/**
- * SCU_TLADTR_READ() -
- *
- * This macro reads the Transport layer address translation register
- */
-#define SCU_TLADTR_READ(port) \
-       scu_transport_layer_read(port, address_translation)
-
-/**
- * SCU_TLADTR_WRITE() -
- *
- * This macro writes the Transport layer address translation register
- */
-#define SCU_TLADTR_WRITE(port) \
-       scu_transport_layer_write(port, address_translation, value)
-
-/**
- * SCU_STPTLDARNI_WRITE() -
- *
- * This macro writes the STP Transport Layer Direct Attached RNi register.
- */
-#define SCU_STPTLDARNI_WRITE(port, index) \
-       scu_transport_layer_write(port, stp_rni, index)
-
-/**
- * SCU_STPTLDARNI_READ() -
- *
- * This macro reads the STP Transport Layer Direct Attached RNi register.
- */
-#define SCU_STPTLDARNI_READ(port) \
-       scu_transport_layer_read(port, stp_rni)
-
-/*
- * ****************************************************************************
  * * Port Task Scheduler registers controlled by the port object
  * **************************************************************************** */
 
index 643247f..cb1cf39 100644 (file)
@@ -1210,11 +1210,6 @@ static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler(
                SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
                );
 
-       scic_sds_port_set_direct_attached_device_id(
-               this_device->owning_port,
-               SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
-               );
-
        sci_base_state_machine_change_state(
                scic_sds_remote_device_get_base_state_machine(this_device),
                SCI_BASE_REMOTE_DEVICE_STATE_FINAL
@@ -2018,11 +2013,6 @@ static void scic_sds_remote_device_resetting_state_exit(
 {
        struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
 
-       scic_sds_port_set_direct_attached_device_id(
-               scic_sds_remote_device_get_port(this_device),
-               this_device->rnc->remote_node_index
-               );
-
        scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL);
 }
 
index 7fec322..253b2d8 100644 (file)
@@ -689,11 +689,6 @@ static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_ha
        } else if (protocols.u.bits.attached_stp_target == 1) {
                if (this_rnc->device->is_direct_attached) {
                        /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */
-                       scic_sds_port_set_direct_attached_device_id(
-                               this_rnc->device->owning_port,
-                               this_rnc->remote_node_index
-                               );
-
                        sci_base_state_machine_change_state(
                                &this_rnc->state_machine,
                                SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
@@ -986,7 +981,7 @@ static void scic_sds_remote_node_context_validate_context_buffer(
                        );
 
                if (this_rnc->device->is_direct_attached) {
-                       scic_sds_port_set_direct_attached_device_id(
+                       scic_sds_port_setup_transports(
                                this_rnc->device->owning_port,
                                this_rnc->remote_node_index
                                );
@@ -1016,13 +1011,6 @@ static void scic_sds_remote_node_context_invalidate_context_buffer(
                this_rnc->device,
                SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
                );
-
-       if (this_rnc->device->is_direct_attached) {
-               scic_sds_port_set_direct_attached_device_id(
-                       this_rnc->device->owning_port,
-                       SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
-                       );
-       }
 }
 
 /*
@@ -1112,6 +1100,7 @@ static void scic_sds_remote_node_context_resuming_state_enter(
        struct sci_base_object *object)
 {
        struct scic_sds_remote_node_context *rnc;
+       struct smp_discover_response_protocols protocols;
 
        rnc = (struct scic_sds_remote_node_context *)object;
 
@@ -1121,6 +1110,20 @@ static void scic_sds_remote_node_context_resuming_state_enter(
                SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
                );
 
+       /*
+        * For direct attached SATA devices we need to clear the TLCR
+        * NCQ to TCi tag mapping on the phy and in cases where we
+        * resume because of a target reset we also need to update
+        * the STPTLDARNI register with the RNi of the device
+        */
+       scic_remote_device_get_protocols(rnc->device, &protocols);
+
+       if ((protocols.u.bits.attached_stp_target == 1) &&
+           (rnc->device->is_direct_attached)) {
+               scic_sds_port_setup_transports(
+                       rnc->device->owning_port, rnc->remote_node_index);
+       }
+
        scic_sds_remote_device_post_request(
                rnc->device,
                SCU_CONTEXT_COMMAND_POST_RNC_RESUME