From 246214667f275a952b05a42b3c45a6fcb520bd28 Mon Sep 17 00:00:00 2001 From: Henryk Dembkowski Date: Wed, 23 Feb 2011 00:08:52 -0800 Subject: [PATCH] isci: Move transport layer registers from port to phy 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 Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 2 +- drivers/scsi/isci/core/scic_sds_phy.c | 62 ++++++++++++++++-- drivers/scsi/isci/core/scic_sds_phy.h | 15 ++++- drivers/scsi/isci/core/scic_sds_phy_registers.h | 53 +++++++++++++++ drivers/scsi/isci/core/scic_sds_port.c | 58 ++++------------- drivers/scsi/isci/core/scic_sds_port.h | 18 ++--- drivers/scsi/isci/core/scic_sds_port_registers.h | 76 ---------------------- drivers/scsi/isci/core/scic_sds_remote_device.c | 10 --- .../scsi/isci/core/scic_sds_remote_node_context.c | 29 +++++---- 9 files changed, 161 insertions(+), 162 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 1cbb91c..e597c6b 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -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] diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 98e9179..bd0a6ba 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -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); } /** diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index 9ba09bb..dc450c3 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -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( diff --git a/drivers/scsi/isci/core/scic_sds_phy_registers.h b/drivers/scsi/isci/core/scic_sds_phy_registers.h index 7883819..2842176 100644 --- a/drivers/scsi/isci/core/scic_sds_phy_registers.h +++ b/drivers/scsi/isci/core/scic_sds_phy_registers.h @@ -65,6 +65,59 @@ #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 diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index ff06f8c..b8acc23 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -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 - ); } /** diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 56c15fc..3eb80cb 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -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); diff --git a/drivers/scsi/isci/core/scic_sds_port_registers.h b/drivers/scsi/isci/core/scic_sds_port_registers.h index cf8bc07..dbe82d8 100644 --- a/drivers/scsi/isci/core/scic_sds_port_registers.h +++ b/drivers/scsi/isci/core/scic_sds_port_registers.h @@ -64,29 +64,6 @@ */ /** - * 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 @@ -120,59 +97,6 @@ /* * **************************************************************************** - * * 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 * **************************************************************************** */ diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 643247f..cb1cf39 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -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); } diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c index 7fec322..253b2d8 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.c +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.c @@ -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 -- 2.7.4