#include "scic_sds_port.h"
#include "scic_sds_phy.h"
#include "remote_node_table.h"
+#include "remote_device.h"
#include "scu_registers.h"
#include "scu_constants.h"
-#include "scu_remote_node_context.h"
#include "scu_task_context.h"
#include "scu_unsolicited_frame.h"
#include "scic_sds_unsolicited_frame_control.h"
#define scic_sds_io_sequence_increment(value) \
((value) = (((value) + 1) & 0x000F))
-#define scic_sds_remote_device_node_count(device) \
- (\
- (\
- (device)->target_protocols.u.bits.attached_stp_target \
- && ((device)->is_direct_attached != true) \
- ) \
- ? SCU_STP_REMOTE_NODE_COUNT : SCU_SSP_REMOTE_NODE_COUNT \
- )
+/* expander attached sata devices require 3 rnc slots */
+static inline int scic_sds_remote_device_node_count(struct scic_sds_remote_device *sci_dev)
+{
+ struct domain_device *dev = sci_dev_to_domain(sci_dev);
+
+ if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) &&
+ !sci_dev->is_direct_attached)
+ return SCU_STP_REMOTE_NODE_COUNT;
+ return SCU_SSP_REMOTE_NODE_COUNT;
+}
/**
* scic_sds_controller_set_invalid_phy() -
* multi-protocol support.
*
*/
-void scic_sds_port_get_attached_protocols(
+static void scic_sds_port_get_attached_protocols(
struct scic_sds_port *sci_port,
struct sci_sas_identify_address_frame_protocols *protocols)
{
struct scic_sds_port *sci_port,
struct sci_sas_address *sas_address);
-void scic_sds_port_get_attached_protocols(
- struct scic_sds_port *sci_port,
- struct sci_sas_identify_address_frame_protocols *protocols);
-
#endif /* _SCIC_SDS_PORT_H_ */
struct scic_sds_request *sci_req,
struct scic_sds_request **new_scic_io_request_handle)
{
+ struct domain_device *dev = sci_dev_to_domain(sci_dev);
enum sci_status status = SCI_SUCCESS;
- struct smp_discover_response_protocols device_protocol;
/* Build the common part of the request */
scic_sds_general_request_construct(scic, sci_dev, io_tag,
if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
return SCI_FAILURE_INVALID_REMOTE_DEVICE;
- scic_remote_device_get_protocols(sci_dev, &device_protocol);
-
- if (device_protocol.u.bits.attached_ssp_target) {
+ if (dev->dev_type == SAS_END_DEV) {
scic_sds_ssp_io_request_assign_buffers(sci_req);
- } else if (device_protocol.u.bits.attached_stp_target) {
+ } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
scic_sds_stp_request_assign_buffers(sci_req);
memset(sci_req->command_buffer, 0, sizeof(struct sata_fis_reg_h2d));
- } else if (device_protocol.u.bits.attached_smp_target) {
+ } else if (dev_is_expander(dev)) {
scic_sds_smp_request_assign_buffers(sci_req);
memset(sci_req->command_buffer, 0, sizeof(struct smp_request));
- } else {
+ } else
status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
- }
if (status == SCI_SUCCESS) {
memset(sci_req->task_context_buffer, 0,
struct scic_sds_request *sci_req,
struct scic_sds_request **new_sci_req)
{
+ struct domain_device *dev = sci_dev_to_domain(sci_dev);
enum sci_status status = SCI_SUCCESS;
- struct smp_discover_response_protocols device_protocol;
/* Build the common part of the request */
scic_sds_general_request_construct(scic, sci_dev, io_tag,
user_io_request_object,
sci_req);
- scic_remote_device_get_protocols(sci_dev, &device_protocol);
-
- if (device_protocol.u.bits.attached_ssp_target) {
+ if (dev->dev_type == SAS_END_DEV) {
scic_sds_ssp_task_request_assign_buffers(sci_req);
sci_req->has_started_substate_machine = true;
scic_sds_io_request_started_task_mgmt_substate_table,
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
);
- } else if (device_protocol.u.bits.attached_stp_target) {
+ } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))
scic_sds_stp_request_assign_buffers(sci_req);
- } else {
+ else
status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
- }
if (status == SCI_SUCCESS) {
sci_req->is_task_management_request = true;
}
-void scic_remote_device_get_protocols(
- struct scic_sds_remote_device *sci_dev,
- struct smp_discover_response_protocols *pr)
-{
- pr->u.all = sci_dev->target_protocols.u.all;
-}
-
#if !defined(DISABLE_ATAPI)
bool scic_remote_device_is_atapi(struct scic_sds_remote_device *sci_dev)
{
{
enum sci_status status;
u16 remote_node_index;
- struct sci_sas_identify_address_frame_protocols protocols;
+ struct domain_device *dev = sci_dev_to_domain(sci_dev);
scic_remote_device_construct(sci_port, sci_dev);
* This information is request to determine how many remote node context
* entries will be needed to store the remote node.
*/
- scic_sds_port_get_attached_protocols(sci_dev->owning_port, &protocols);
- sci_dev->target_protocols.u.all = protocols.u.all;
sci_dev->is_direct_attached = true;
-#if !defined(DISABLE_ATAPI)
- sci_dev->is_atapi = scic_sds_remote_device_is_atapi(sci_dev);
-#endif
+ status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller,
+ sci_dev,
+ &remote_node_index);
- status = scic_sds_controller_allocate_remote_node_context(
- sci_dev->owning_port->owning_controller,
- sci_dev,
- &remote_node_index);
+ if (status != SCI_SUCCESS)
+ return status;
- if (status == SCI_SUCCESS) {
- sci_dev->rnc.remote_node_index = remote_node_index;
+ sci_dev->rnc.remote_node_index = remote_node_index;
- scic_sds_port_get_attached_sas_address(
- sci_dev->owning_port, &sci_dev->device_address);
+ scic_sds_port_get_attached_sas_address(sci_port, &sci_dev->device_address);
- if (sci_dev->target_protocols.u.bits.attached_ssp_target) {
- sci_dev->has_ready_substate_machine = false;
- } else if (sci_dev->target_protocols.u.bits.attached_stp_target) {
- sci_dev->has_ready_substate_machine = true;
+ if (dev->dev_type == SAS_END_DEV)
+ sci_dev->has_ready_substate_machine = false;
+ else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
+ sci_dev->has_ready_substate_machine = true;
- sci_base_state_machine_construct(
+ sci_base_state_machine_construct(
&sci_dev->ready_substate_machine,
&sci_dev->parent,
scic_sds_stp_remote_device_ready_substate_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
- } else if (sci_dev->target_protocols.u.bits.attached_smp_target) {
- sci_dev->has_ready_substate_machine = true;
+ } else if (dev_is_expander(dev)) {
+ sci_dev->has_ready_substate_machine = true;
- /* add the SMP ready substate machine construction here */
- sci_base_state_machine_construct(
+ /* add the SMP ready substate machine construction here */
+ sci_base_state_machine_construct(
&sci_dev->ready_substate_machine,
&sci_dev->parent,
scic_sds_smp_remote_device_ready_substate_table,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
- }
+ } else
+ return SCI_FAILURE_UNSUPPORTED_PROTOCOL;
- sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(
- sci_dev->owning_port);
+ sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(sci_port);
- /* / @todo Should I assign the port width by reading all of the phys on the port? */
- sci_dev->device_port_width = 1;
- }
+ /* / @todo Should I assign the port width by reading all of the phys on the port? */
+ sci_dev->device_port_width = 1;
- return status;
+ return SCI_SUCCESS;
}
static void scic_sds_remote_device_get_info_from_smp_discover_response(
sci_dev->device_address.low =
discover_response->attached_sas_address.low;
-
- sci_dev->target_protocols.u.all = discover_response->protocols.u.all;
}
/**
struct smp_response_discover *discover_response)
{
struct scic_sds_controller *scic = sci_port->owning_controller;
+ struct domain_device *dev = sci_dev_to_domain(sci_dev);
enum sci_status status;
scic_remote_device_construct(sci_port, sci_dev);
status = scic_sds_controller_allocate_remote_node_context(
scic, sci_dev, &sci_dev->rnc.remote_node_index);
+ if (status != SCI_SUCCESS)
+ return status;
- if (status == SCI_SUCCESS) {
- if (sci_dev->target_protocols.u.bits.attached_ssp_target) {
- sci_dev->has_ready_substate_machine = false;
- } else if (sci_dev->target_protocols.u.bits.attached_smp_target) {
- sci_dev->has_ready_substate_machine = true;
+ if (dev->dev_type == SAS_END_DEV)
+ sci_dev->has_ready_substate_machine = false;
+ else if (dev_is_expander(dev)) {
+ sci_dev->has_ready_substate_machine = true;
- /* add the SMP ready substate machine construction here */
- sci_base_state_machine_construct(
+ /* add the SMP ready substate machine construction here */
+ sci_base_state_machine_construct(
&sci_dev->ready_substate_machine,
&sci_dev->parent,
scic_sds_smp_remote_device_ready_substate_table,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
- } else if (sci_dev->target_protocols.u.bits.attached_stp_target) {
- sci_dev->has_ready_substate_machine = true;
+ } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
+ sci_dev->has_ready_substate_machine = true;
- sci_base_state_machine_construct(
+ sci_base_state_machine_construct(
&sci_dev->ready_substate_machine,
&sci_dev->parent,
scic_sds_stp_remote_device_ready_substate_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
- }
+ }
- /*
- * For SAS-2 the physical link rate is actually a logical link
- * rate that incorporates multiplexing. The SCU doesn't
- * incorporate multiplexing and for the purposes of the
- * connection the logical link rate is that same as the
- * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay
- * one another, so this code works for both situations. */
- sci_dev->connection_rate = min_t(u16,
- scic_sds_port_get_max_allowed_speed(sci_port),
+ /*
+ * For SAS-2 the physical link rate is actually a logical link
+ * rate that incorporates multiplexing. The SCU doesn't
+ * incorporate multiplexing and for the purposes of the
+ * connection the logical link rate is that same as the
+ * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay
+ * one another, so this code works for both situations. */
+ sci_dev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(sci_port),
discover_response->u2.sas1_1.negotiated_physical_link_rate);
- /* / @todo Should I assign the port width by reading all of the phys on the port? */
- sci_dev->device_port_width = 1;
- }
+ /* / @todo Should I assign the port width by reading all of the phys on the port? */
+ sci_dev->device_port_width = 1;
return status;
}
enum sci_status status = SCI_SUCCESS;
if (isci_device->domain_dev->parent &&
- (isci_device->domain_dev->parent->dev_type == EDGE_DEV)) {
+ dev_is_expander(isci_device->domain_dev->parent)) {
int i;
/* struct smp_response_discover discover_response; */
enum sas_linkrate connection_rate;
/**
- * This field contains the allowed target protocols for this remote device.
- */
- struct smp_discover_response_protocols target_protocols;
-
- /**
* This field contains the device SAS address.
*/
struct sci_sas_address device_address;
enum sas_linkrate scic_remote_device_get_connection_rate(
struct scic_sds_remote_device *remote_device);
-/**
- * scic_remote_device_get_protocols() - This method will indicate which
- * protocols are supported by this remote device.
- * @remote_device: This parameter specifies the device for which to return the
- * protocol.
- * @protocols: This parameter specifies the output values, from the remote
- * device object, which indicate the protocols supported by the supplied
- * remote_device.
- *
- * The type of protocols supported by this device. The values are returned as
- * part of a bit mask in order to allow for multi-protocol support.
- */
-void scic_remote_device_get_protocols(
- struct scic_sds_remote_device *remote_device,
- struct smp_discover_response_protocols *protocols);
-
-
#if !defined(DISABLE_ATAPI)
/**
* scic_remote_device_is_atapi() -
return sci_dev;
}
+static inline struct domain_device *sci_dev_to_domain(struct scic_sds_remote_device *sci_dev)
+{
+ struct isci_remote_device *idev = container_of(sci_dev, typeof(*idev), sci);
+
+ return idev->domain_dev;
+}
+
+static inline bool dev_is_expander(struct domain_device *dev)
+{
+ return dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV;
+}
+
typedef enum sci_status (*scic_sds_remote_device_request_handler_t)(
struct scic_sds_remote_device *device,
struct scic_sds_request *request);
static void scic_sds_remote_node_context_construct_buffer(
struct scic_sds_remote_node_context *sci_rnc)
{
- union scu_remote_node_context *rnc;
struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc);
+ struct domain_device *dev = sci_dev_to_domain(sci_dev);
+ union scu_remote_node_context *rnc;
struct scic_sds_controller *scic;
scic = scic_sds_remote_device_get_controller(sci_dev);
rnc->ssp.arbitration_wait_time = 0;
-
- if (
- sci_dev->target_protocols.u.bits.attached_sata_device
- || sci_dev->target_protocols.u.bits.attached_stp_target
- ) {
+ if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
rnc->ssp.connection_occupancy_timeout =
scic->user_parameters.sds1.stp_max_occupancy_timeout;
rnc->ssp.connection_inactivity_timeout =
scics_sds_remote_node_context_callback callback,
void *callback_parameter)
{
- enum sci_status status;
- struct smp_discover_response_protocols protocols;
+ struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc);
+ struct domain_device *dev = sci_dev_to_domain(sci_dev);
+ enum sci_status status = SCI_SUCCESS;
- scic_sds_remote_node_context_setup_to_resume(
- sci_rnc, callback, callback_parameter
- );
+ scic_sds_remote_node_context_setup_to_resume(sci_rnc, callback,
+ callback_parameter);
/* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */
-
- scic_remote_device_get_protocols(rnc_to_dev(sci_rnc), &protocols);
-
- if (
- (protocols.u.bits.attached_ssp_target == 1)
- || (protocols.u.bits.attached_smp_target == 1)
- ) {
- sci_base_state_machine_change_state(
- &sci_rnc->state_machine,
- SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
- );
-
- status = SCI_SUCCESS;
- } else if (protocols.u.bits.attached_stp_target == 1) {
- if (rnc_to_dev(sci_rnc)->is_direct_attached) {
+ if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev))
+ sci_base_state_machine_change_state(&sci_rnc->state_machine,
+ SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE);
+ else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
+ if (sci_dev->is_direct_attached) {
/* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */
sci_base_state_machine_change_state(
&sci_rnc->state_machine,
- SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
- );
+ SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE);
} else {
sci_base_state_machine_change_state(
&sci_rnc->state_machine,
- SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
- );
+ SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE);
}
-
- status = SCI_SUCCESS;
- } else {
+ } else
status = SCI_FAILURE;
- }
return status;
}
struct scic_sds_remote_node_context *sci_rnc)
{
struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc);
+ struct domain_device *dev = sci_dev_to_domain(sci_dev);
union scu_remote_node_context *rnc_buffer;
rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
rnc_buffer->ssp.is_valid = true;
if (!sci_dev->is_direct_attached &&
- sci_dev->target_protocols.u.bits.attached_stp_target) {
+ (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))) {
scic_sds_remote_device_post_request(sci_dev,
SCU_CONTEXT_COMMAND_POST_RNC_96);
} else {
struct sci_base_object *object)
{
struct scic_sds_remote_node_context *rnc;
- struct smp_discover_response_protocols protocols;
struct scic_sds_remote_device *sci_dev;
+ struct domain_device *dev;
rnc = (struct scic_sds_remote_node_context *)object;
sci_dev = rnc_to_dev(rnc);
+ dev = sci_dev_to_domain(sci_dev);
SET_STATE_HANDLER(
rnc,
* 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(sci_dev, &protocols);
-
- if (protocols.u.bits.attached_stp_target == 1 &&
- sci_dev->is_direct_attached) {
+ if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) &&
+ sci_dev->is_direct_attached)
scic_sds_port_setup_transports(sci_dev->owning_port,
rnc->remote_node_index);
- }
scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME);
}
struct isci_request *request,
struct isci_remote_device *isci_device)
{
- struct smp_discover_response_protocols dev_protocols;
enum sci_status status = SCI_SUCCESS;
struct sas_task *task = isci_request_access_task(request);
struct scic_sds_remote_device *sci_device = &isci_device->sci;
sci_object_set_association(request->sci_request_handle, request);
- /* Determine protocol and call the appropriate basic constructor */
- scic_remote_device_get_protocols(sci_device, &dev_protocols);
- if (dev_protocols.u.bits.attached_ssp_target)
+ switch (task->task_proto) {
+ case SAS_PROTOCOL_SMP:
+ status = isci_smp_request_build(request);
+ break;
+ case SAS_PROTOCOL_SSP:
status = isci_request_ssp_request_construct(request);
- else if (dev_protocols.u.bits.attached_stp_target)
+ break;
+ case SAS_PROTOCOL_SATA:
+ case SAS_PROTOCOL_STP:
+ case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
status = isci_request_stp_request_construct(request);
- else if (dev_protocols.u.bits.attached_smp_target)
- status = isci_smp_request_build(request);
- else {
+ break;
+ default:
dev_warn(&isci_host->pdev->dev,
"%s: unknown protocol\n", __func__);
return SCI_FAILURE;
enum sci_status status = SCI_FAILURE;
struct isci_request *request = NULL;
struct isci_remote_device *isci_device;
-/* struct sci_sas_identify_address_frame_protocols dev_protocols; */
- struct smp_discover_response_protocols dev_protocols;
-
+ struct domain_device *dev;
dev_dbg(&isci_host->pdev->dev,
"%s: isci_tmf = %p\n", __func__, isci_tmf);
isci_device = isci_tmf->device;
sci_device = &isci_device->sci;
+ dev = isci_device->domain_dev;
/* do common allocation and init of request object. */
status = isci_request_alloc_tmf(
request
);
- scic_remote_device_get_protocols(
- sci_device,
- &dev_protocols
- );
-
- /* let the core do it's protocol
- * specific construction.
- */
- if (dev_protocols.u.bits.attached_ssp_target) {
-
+ /* XXX convert to get this from task->tproto like other drivers */
+ if (dev->dev_type == SAS_END_DEV) {
isci_tmf->proto = SAS_PROTOCOL_SSP;
status = scic_task_request_construct_ssp(
request->sci_request_handle
goto errout;
}
- if (dev_protocols.u.bits.attached_stp_target) {
-
+ if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
isci_tmf->proto = SAS_PROTOCOL_SATA;
status = isci_sata_management_task_request_build(request);