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
);
}
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]
#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"
* * SCIC SDS PHY Internal Methods
* ***************************************************************************** */
+/**
+ * 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:
*/
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;
*/
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(
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);
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);
+}
/**
*
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);
}
/**
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;
};
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);
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(
#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
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++) {
*/
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 */
}
/**
- *
- * @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.
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);
}
/**
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
- );
}
/**
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
/**
* This field is the VIIT register space for ths port object.
*/
- struct scu_viit_entry *viit_registers;
+ struct scu_viit_entry __iomem *viit_registers;
};
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);
/* --------------------------------------------------------------------------- */
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);
*
*/
-/**
- * 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() -
*
(value) \
)
-/*
- * ****************************************************************************
- * * 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
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
{
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);
}
} 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
);
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
);
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
- );
- }
}
/*
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;
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