static struct isci_port *sci_port_configuration_agent_find_port( struct isci_host *ihost, struct isci_phy *iphy) { u8 i; struct sci_sas_address port_sas_address; struct sci_sas_address port_attached_device_address; struct sci_sas_address phy_sas_address; struct sci_sas_address phy_attached_device_address; sci_phy_get_sas_address(iphy, &phy_sas_address); sci_phy_get_attached_sas_address(iphy, &phy_attached_device_address); for (i = 0; i < ihost->logical_port_entries; i++) { struct isci_port *iport = &ihost->ports[i]; sci_port_get_sas_address(iport, &port_sas_address); sci_port_get_attached_sas_address(iport, &port_attached_device_address); if (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0 && sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) return iport; } return NULL; }
/** * * @controller: The controller object used for the port search. * @phy: The phy object to match. * * This routine will find a matching port for the phy. This means that the * port and phy both have the same broadcast sas address and same received sas * address. The port address or the NULL if there is no matching * port. port address if the port can be found to match the phy. * NULL if there is no matching port for the phy. */ static struct isci_port *sci_port_configuration_agent_find_port( struct isci_host *ihost, struct isci_phy *iphy) { u8 i; struct sci_sas_address port_sas_address; struct sci_sas_address port_attached_device_address; struct sci_sas_address phy_sas_address; struct sci_sas_address phy_attached_device_address; /* * Since this phy can be a member of a wide port check to see if one or * more phys match the sent and received SAS address as this phy in which * case it should participate in the same port. */ sci_phy_get_sas_address(iphy, &phy_sas_address); sci_phy_get_attached_sas_address(iphy, &phy_attached_device_address); for (i = 0; i < ihost->logical_port_entries; i++) { struct isci_port *iport = &ihost->ports[i]; sci_port_get_sas_address(iport, &port_sas_address); sci_port_get_attached_sas_address(iport, &port_attached_device_address); if (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0 && sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) return iport; } return NULL; }
static enum sci_status sci_port_configuration_agent_validate_ports( struct isci_host *ihost, struct sci_port_configuration_agent *port_agent) { struct sci_sas_address first_address; struct sci_sas_address second_address; if (port_agent->phy_valid_port_range[0].max_index != 0 || port_agent->phy_valid_port_range[1].max_index != 1 || port_agent->phy_valid_port_range[2].max_index != 2 || port_agent->phy_valid_port_range[3].max_index != 3) return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; if (port_agent->phy_valid_port_range[0].min_index == 0 && port_agent->phy_valid_port_range[1].min_index == 0 && port_agent->phy_valid_port_range[2].min_index == 0 && port_agent->phy_valid_port_range[3].min_index == 0) return SCI_SUCCESS; if (port_agent->phy_valid_port_range[2].min_index == 1) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } sci_phy_get_sas_address(&ihost->phys[0], &first_address); sci_phy_get_sas_address(&ihost->phys[3], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } if (port_agent->phy_valid_port_range[0].min_index == 0 && port_agent->phy_valid_port_range[1].min_index == 1) { sci_phy_get_sas_address(&ihost->phys[0], &first_address); sci_phy_get_sas_address(&ihost->phys[2], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } } if (port_agent->phy_valid_port_range[2].min_index == 2 && port_agent->phy_valid_port_range[3].min_index == 3) { sci_phy_get_sas_address(&ihost->phys[1], &first_address); sci_phy_get_sas_address(&ihost->phys[3], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } } return SCI_SUCCESS; }
/** * This routine will find a matching port for the phy. This means that the * port and phy both have the same broadcast sas address and same received * sas address. * * @param[in] controller The controller object used for the port search. * @param[in] phy The phy object to match. * * @return The port address or the SCI_INVALID_HANDLE if there is no matching * port. * * @retvalue port address if the port can be found to match the phy. * @retvalue SCI_INVALID_HANDLE if there is no matching port for the phy. */ static SCIC_SDS_PORT_T * scic_sds_port_configuration_agent_find_port( SCIC_SDS_CONTROLLER_T * controller, SCIC_SDS_PHY_T * phy ) { U8 port_index; SCI_PORT_HANDLE_T port_handle; SCI_SAS_ADDRESS_T port_sas_address; SCI_SAS_ADDRESS_T port_attached_device_address; SCI_SAS_ADDRESS_T phy_sas_address; SCI_SAS_ADDRESS_T phy_attached_device_address; SCIC_LOG_TRACE(( sci_base_object_get_logger(controller), SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_PHY, "scic_sds_port_confgiruation_agent_find_port(0x%08x, 0x%08x) enter\n", controller, phy )); // Since this phy can be a member of a wide port check to see if one or // more phys match the sent and received SAS address as this phy in which // case it should participate in the same port. scic_sds_phy_get_sas_address(phy, &phy_sas_address); scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address); for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { if (scic_controller_get_port_handle(controller, port_index, &port_handle) == SCI_SUCCESS) { SCIC_SDS_PORT_T * port = (SCIC_SDS_PORT_T *)port_handle; scic_sds_port_get_sas_address(port, &port_sas_address); scic_sds_port_get_attached_sas_address(port, &port_attached_device_address); if ( (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0) && (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) ) { return port; } } } return SCI_INVALID_HANDLE; }
/** * This routine will verify that the phys are assigned a valid SAS address for * automatic port configuration mode. */ static SCI_STATUS scic_sds_apc_agent_validate_phy_configuration( SCIC_SDS_CONTROLLER_T * controller, SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent ) { U8 phy_index; U8 port_index; SCI_SAS_ADDRESS_T sas_address; SCI_SAS_ADDRESS_T phy_assigned_address; SCIC_LOG_TRACE(( sci_base_object_get_logger(controller), SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT, "scic_sds_apc_agent_validate_phy_configuration(0x%08x, 0x%08x) enter\n", controller, port_agent )); phy_index = 0; while (phy_index < SCI_MAX_PHYS) { port_index = phy_index; // Get the assigned SAS Address for the first PHY on the controller. scic_sds_phy_get_sas_address( &controller->phy_table[phy_index], &sas_address ); while (++phy_index < SCI_MAX_PHYS) { scic_sds_phy_get_sas_address( &controller->phy_table[phy_index], &phy_assigned_address ); // Verify each of the SAS address are all the same for every PHY if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) { port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; } else { port_agent->phy_valid_port_range[phy_index].min_index = phy_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; break; } } } return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); }
static enum sci_status sci_apc_agent_validate_phy_configuration(struct isci_host *ihost, struct sci_port_configuration_agent *port_agent) { u8 phy_index; u8 port_index; struct sci_sas_address sas_address; struct sci_sas_address phy_assigned_address; phy_index = 0; while (phy_index < SCI_MAX_PHYS) { port_index = phy_index; sci_phy_get_sas_address(&ihost->phys[phy_index], &sas_address); while (++phy_index < SCI_MAX_PHYS) { sci_phy_get_sas_address(&ihost->phys[phy_index], &phy_assigned_address); if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) { port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; } else { port_agent->phy_valid_port_range[phy_index].min_index = phy_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; break; } } } return sci_port_configuration_agent_validate_ports(ihost, port_agent); }
/* verify phys are assigned a valid SAS address for automatic port * configuration mode. */ static enum sci_status sci_apc_agent_validate_phy_configuration(struct isci_host *ihost, struct sci_port_configuration_agent *port_agent) { u8 phy_index; u8 port_index; struct sci_sas_address sas_address; struct sci_sas_address phy_assigned_address; phy_index = 0; while (phy_index < SCI_MAX_PHYS) { port_index = phy_index; /* Get the assigned SAS Address for the first PHY on the controller. */ sci_phy_get_sas_address(&ihost->phys[phy_index], &sas_address); while (++phy_index < SCI_MAX_PHYS) { sci_phy_get_sas_address(&ihost->phys[phy_index], &phy_assigned_address); /* Verify each of the SAS address are all the same for every PHY */ if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) { port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; } else { port_agent->phy_valid_port_range[phy_index].min_index = phy_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; break; } } } return sci_port_configuration_agent_validate_ports(ihost, port_agent); }
/** * This routine will verify that all of the phys in the same port are using * the same SAS address. * * @param[in] controller This is the controller that contains the PHYs to * be verified. */ static SCI_STATUS scic_sds_mpc_agent_validate_phy_configuration( SCIC_SDS_CONTROLLER_T * controller, SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent ) { U32 phy_mask; U32 assigned_phy_mask; SCI_SAS_ADDRESS_T sas_address; SCI_SAS_ADDRESS_T phy_assigned_address; U8 port_index; U8 phy_index; assigned_phy_mask = 0; sas_address.high = 0; sas_address.low = 0; SCIC_LOG_TRACE(( sci_base_object_get_logger(controller), SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT, "scic_sds_mpc_agent_validate_phy_configuration(0x%08x, 0x%08x) enter\n", controller, port_agent )); for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask; if (phy_mask != 0) { // Make sure that one or more of the phys were not already assinged to // a different port. if ((phy_mask & ~assigned_phy_mask) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } // Find the starting phy index for this round through the loop for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { if ((1 << phy_index) & phy_mask) { scic_sds_phy_get_sas_address( &controller->phy_table[phy_index], &sas_address ); // The phy_index can be used as the starting point for the // port range since the hardware starts all logical ports // the same as the PE index. port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; if (phy_index != port_index) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } break; } } // See how many additional phys are being added to this logical port. // Note: We have not moved the current phy_index so we will actually // compare the startting phy with itself. // This is expected and required to add the phy to the port. while (phy_index < SCI_MAX_PHYS) { if ((1 << phy_index) & phy_mask) { scic_sds_phy_get_sas_address( &controller->phy_table[phy_index], &phy_assigned_address ); if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { // The phy mask specified that this phy is part of the same port // as the starting phy and it is not so fail this configuration return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; scic_sds_port_add_phy( &controller->port_table[port_index], &controller->phy_table[phy_index] ); assigned_phy_mask |= (1 << phy_index); } phy_index++; } } } return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); }
/** * This routine will validate the port configuration is correct for the SCU * hardware. The SCU hardware allows for port configurations as follows. * LP0 -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3) * LP1 -> (PE1) * LP2 -> (PE2), (PE2, PE3) * LP3 -> (PE3) * * @param[in] controller This is the controller object that contains the * port agent * @param[in] port_agent This is the port configruation agent for * the controller. * * @return SCI_STATUS * @retval SCI_SUCCESS the port configuration is valid for this * port configuration agent. * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION the port configuration * is not valid for this port configuration agent. */ static SCI_STATUS scic_sds_port_configuration_agent_validate_ports( SCIC_SDS_CONTROLLER_T * controller, SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent ) { #if !defined(ARLINGTON_BUILD) SCI_SAS_ADDRESS_T first_address; SCI_SAS_ADDRESS_T second_address; SCIC_LOG_TRACE(( sci_base_object_get_logger(controller), SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT, "scic_sds_port_configuration_agent_validate_ports(0x%08x, 0x%08x) enter\n", controller, port_agent )); // Sanity check the max ranges for all the phys the max index // is always equal to the port range index if ( (port_agent->phy_valid_port_range[0].max_index != 0) || (port_agent->phy_valid_port_range[1].max_index != 1) || (port_agent->phy_valid_port_range[2].max_index != 2) || (port_agent->phy_valid_port_range[3].max_index != 3) ) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } // This is a request to configure a single x4 port or at least attempt // to make all the phys into a single port if ( (port_agent->phy_valid_port_range[0].min_index == 0) && (port_agent->phy_valid_port_range[1].min_index == 0) && (port_agent->phy_valid_port_range[2].min_index == 0) && (port_agent->phy_valid_port_range[3].min_index == 0) ) { return SCI_SUCCESS; } // This is a degenerate case where phy 1 and phy 2 are assigned // to the same port this is explicitly disallowed by the hardware // unless they are part of the same x4 port and this condition was // already checked above. if (port_agent->phy_valid_port_range[2].min_index == 1) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } // PE0 and PE3 can never have the same SAS Address unless they // are part of the same x4 wide port and we have already checked // for this condition. scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address); scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } // PE0 and PE1 are configured into a 2x1 ports make sure that the // SAS Address for PE0 and PE2 are different since they can not be // part of the same port. if ( (port_agent->phy_valid_port_range[0].min_index == 0) && (port_agent->phy_valid_port_range[1].min_index == 1) ) { scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address); scic_sds_phy_get_sas_address(&controller->phy_table[2], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } } // PE2 and PE3 are configured into a 2x1 ports make sure that the // SAS Address for PE1 and PE3 are different since they can not be // part of the same port. if ( (port_agent->phy_valid_port_range[2].min_index == 2) && (port_agent->phy_valid_port_range[3].min_index == 3) ) { scic_sds_phy_get_sas_address(&controller->phy_table[1], &first_address); scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } } #endif // !defined(ARLINGTON_BUILD) return SCI_SUCCESS; }
static enum sci_status sci_mpc_agent_validate_phy_configuration(struct isci_host *ihost, struct sci_port_configuration_agent *port_agent) { u32 phy_mask; u32 assigned_phy_mask; struct sci_sas_address sas_address; struct sci_sas_address phy_assigned_address; u8 port_index; u8 phy_index; assigned_phy_mask = 0; sas_address.high = 0; sas_address.low = 0; for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { phy_mask = ihost->oem_parameters.ports[port_index].phy_mask; if (!phy_mask) continue; if ((phy_mask & ~assigned_phy_mask) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { if ((phy_mask & (1 << phy_index)) == 0) continue; sci_phy_get_sas_address(&ihost->phys[phy_index], &sas_address); port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; if (phy_index != port_index) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } break; } while (phy_index < SCI_MAX_PHYS) { if ((phy_mask & (1 << phy_index)) == 0) continue; sci_phy_get_sas_address(&ihost->phys[phy_index], &phy_assigned_address); if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; sci_port_add_phy(&ihost->ports[port_index], &ihost->phys[phy_index]); assigned_phy_mask |= (1 << phy_index); } phy_index++; } return sci_port_configuration_agent_validate_ports(ihost, port_agent); }
/* verify all of the phys in the same port are using the same SAS address */ static enum sci_status sci_mpc_agent_validate_phy_configuration(struct isci_host *ihost, struct sci_port_configuration_agent *port_agent) { u32 phy_mask; u32 assigned_phy_mask; struct sci_sas_address sas_address; struct sci_sas_address phy_assigned_address; u8 port_index; u8 phy_index; assigned_phy_mask = 0; sas_address.high = 0; sas_address.low = 0; for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { phy_mask = ihost->oem_parameters.ports[port_index].phy_mask; if (!phy_mask) continue; /* * Make sure that one or more of the phys were not already assinged to * a different port. */ if ((phy_mask & ~assigned_phy_mask) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } /* Find the starting phy index for this round through the loop */ for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { if ((phy_mask & (1 << phy_index)) == 0) continue; sci_phy_get_sas_address(&ihost->phys[phy_index], &sas_address); /* * The phy_index can be used as the starting point for the * port range since the hardware starts all logical ports * the same as the PE index. */ port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; if (phy_index != port_index) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } break; } /* * See how many additional phys are being added to this logical port. * Note: We have not moved the current phy_index so we will actually * compare the startting phy with itself. * This is expected and required to add the phy to the port. */ while (phy_index < SCI_MAX_PHYS) { if ((phy_mask & (1 << phy_index)) == 0) continue; sci_phy_get_sas_address(&ihost->phys[phy_index], &phy_assigned_address); if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { /* * The phy mask specified that this phy is part of the same port * as the starting phy and it is not so fail this configuration */ return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; sci_port_add_phy(&ihost->ports[port_index], &ihost->phys[phy_index]); assigned_phy_mask |= (1 << phy_index); } phy_index++; } return sci_port_configuration_agent_validate_ports(ihost, port_agent); }
/** * * @controller: This is the controller object that contains the port agent * @port_agent: This is the port configruation agent for the controller. * * This routine will validate the port configuration is correct for the SCU * hardware. The SCU hardware allows for port configurations as follows. LP0 * -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3) LP1 -> (PE1) LP2 -> (PE2), (PE2, * PE3) LP3 -> (PE3) enum sci_status SCI_SUCCESS the port configuration is valid for * this port configuration agent. SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION * the port configuration is not valid for this port configuration agent. */ static enum sci_status sci_port_configuration_agent_validate_ports( struct isci_host *ihost, struct sci_port_configuration_agent *port_agent) { struct sci_sas_address first_address; struct sci_sas_address second_address; /* * Sanity check the max ranges for all the phys the max index * is always equal to the port range index */ if (port_agent->phy_valid_port_range[0].max_index != 0 || port_agent->phy_valid_port_range[1].max_index != 1 || port_agent->phy_valid_port_range[2].max_index != 2 || port_agent->phy_valid_port_range[3].max_index != 3) return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; /* * This is a request to configure a single x4 port or at least attempt * to make all the phys into a single port */ if (port_agent->phy_valid_port_range[0].min_index == 0 && port_agent->phy_valid_port_range[1].min_index == 0 && port_agent->phy_valid_port_range[2].min_index == 0 && port_agent->phy_valid_port_range[3].min_index == 0) return SCI_SUCCESS; /* * This is a degenerate case where phy 1 and phy 2 are assigned * to the same port this is explicitly disallowed by the hardware * unless they are part of the same x4 port and this condition was * already checked above. */ if (port_agent->phy_valid_port_range[2].min_index == 1) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } /* * PE0 and PE3 can never have the same SAS Address unless they * are part of the same x4 wide port and we have already checked * for this condition. */ sci_phy_get_sas_address(&ihost->phys[0], &first_address); sci_phy_get_sas_address(&ihost->phys[3], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } /* * PE0 and PE1 are configured into a 2x1 ports make sure that the * SAS Address for PE0 and PE2 are different since they can not be * part of the same port. */ if (port_agent->phy_valid_port_range[0].min_index == 0 && port_agent->phy_valid_port_range[1].min_index == 1) { sci_phy_get_sas_address(&ihost->phys[0], &first_address); sci_phy_get_sas_address(&ihost->phys[2], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } } /* * PE2 and PE3 are configured into a 2x1 ports make sure that the * SAS Address for PE1 and PE3 are different since they can not be * part of the same port. */ if (port_agent->phy_valid_port_range[2].min_index == 2 && port_agent->phy_valid_port_range[3].min_index == 3) { sci_phy_get_sas_address(&ihost->phys[1], &first_address); sci_phy_get_sas_address(&ihost->phys[3], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } } return SCI_SUCCESS; }