*/
static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic)
{
+ struct isci_host *ihost = scic_to_ihost(scic);
struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1;
struct scic_sds_phy *sci_phy;
enum sci_status status;
u8 index;
for (index = 0; index < SCI_MAX_PHYS; index++) {
- sci_phy = &scic->phy_table[index];
+ sci_phy = &ihost->phys[index].sci;
state = sci_phy->state_machine.current_state_id;
if (!scic_sds_phy_get_port(sci_phy))
scic_sds_controller_phy_timer_stop(scic);
}
} else {
- sci_phy = &scic->phy_table[scic->next_phy_to_start];
+ sci_phy = &ihost->phys[scic->next_phy_to_start].sci;
if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
if (scic_sds_phy_get_port(sci_phy) == NULL) {
"to stop phy %d because of status "
"%d.\n",
__func__,
- scic->phy_table[scic->next_phy_to_start].phy_index,
+ ihost->phys[scic->next_phy_to_start].sci.phy_index,
status);
}
u32 index;
enum sci_status status;
enum sci_status phy_status;
+ struct isci_host *ihost = scic_to_ihost(scic);
status = SCI_SUCCESS;
for (index = 0; index < SCI_MAX_PHYS; index++) {
- phy_status = scic_sds_phy_stop(&scic->phy_table[index]);
+ phy_status = scic_sds_phy_stop(&ihost->phys[index].sci);
- if (
- (phy_status != SCI_SUCCESS)
- && (phy_status != SCI_FAILURE_INVALID_STATE)
- ) {
+ if (phy_status != SCI_SUCCESS &&
+ phy_status != SCI_FAILURE_INVALID_STATE) {
status = SCI_FAILURE;
dev_warn(scic_to_dev(scic),
"%s: Controller stop operation failed to stop "
"phy %d because of status %d.\n",
__func__,
- scic->phy_table[index].phy_index, phy_status);
+ ihost->phys[index].sci.phy_index, phy_status);
}
}
}
}
-/**
- *
- * @scic:
- * @completion_entry:
- *
- * This method processes an unsolicited frame message. This is called from
- * within the controller completion handler. none
- */
-static void scic_sds_controller_unsolicited_frame(
- struct scic_sds_controller *scic,
- u32 completion_entry)
+static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *scic,
+ u32 completion_entry)
{
u32 index;
u32 frame_index;
+ struct isci_host *ihost = scic_to_ihost(scic);
struct scu_unsolicited_frame_header *frame_header;
struct scic_sds_phy *phy;
struct scic_sds_remote_device *device;
frame_index = SCU_GET_FRAME_INDEX(completion_entry);
- frame_header
- = scic->uf_control.buffers.array[frame_index].header;
- scic->uf_control.buffers.array[frame_index].state
- = UNSOLICITED_FRAME_IN_USE;
+ frame_header = scic->uf_control.buffers.array[frame_index].header;
+ scic->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE;
if (SCU_GET_FRAME_ERROR(completion_entry)) {
/*
if (frame_header->is_address_frame) {
index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
- phy = &scic->phy_table[index];
- if (phy != NULL) {
- result = scic_sds_phy_frame_handler(phy, frame_index);
- }
+ phy = &ihost->phys[index].sci;
+ result = scic_sds_phy_frame_handler(phy, frame_index);
} else {
index = SCU_GET_COMPLETION_INDEX(completion_entry);
* device that has not yet been created. In either case forwared
* the frame to the PE and let it take care of the frame data. */
index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
- phy = &scic->phy_table[index];
+ phy = &ihost->phys[index].sci;
result = scic_sds_phy_frame_handler(phy, frame_index);
} else {
if (index < scic->remote_node_entries)
}
}
-/**
- * This method processes an event completion entry. This is called from within
- * the controller completion handler.
- * @scic:
- * @completion_entry:
- *
- */
-static void scic_sds_controller_event_completion(
- struct scic_sds_controller *scic,
- u32 completion_entry)
+static void scic_sds_controller_event_completion(struct scic_sds_controller *scic,
+ u32 completion_entry)
{
- u32 index;
+ struct isci_host *ihost = scic_to_ihost(scic);
struct scic_sds_request *io_request;
struct scic_sds_remote_device *device;
struct scic_sds_phy *phy;
+ u32 index;
index = SCU_GET_COMPLETION_INDEX(completion_entry);
* we get the event notification. This is a type 4 event. */
case SCU_EVENT_TYPE_OSSP_EVENT:
index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);
- phy = &scic->phy_table[index];
+ phy = &ihost->phys[index].sci;
scic_sds_phy_event_handler(phy, completion_entry);
break;
return status;
}
-/**
- * scic_controller_get_phy_handle() - This method simply provides the user with
- * a unique handle for a given SAS/SATA phy index/identifier.
- * @controller: This parameter represents the handle to the controller object
- * from which to retrieve a phy (SAS or SATA) handle.
- * @phy_index: This parameter specifies the phy index in the controller for
- * which to retrieve the phy handle. 0 <= phy_index < maximum number of phys.
- * @phy_handle: This parameter specifies the retrieved phy handle to be
- * provided to the caller.
- *
- * Indicate if the retrieval of the phy handle was successful. SCI_SUCCESS This
- * value is returned if the retrieval was successful. SCI_FAILURE_INVALID_PHY
- * This value is returned if the supplied phy id is not in the supported range.
- */
-enum sci_status scic_controller_get_phy_handle(
- struct scic_sds_controller *scic,
- u8 phy_index,
- struct scic_sds_phy **phy_handle)
-{
- if (phy_index < ARRAY_SIZE(scic->phy_table)) {
- *phy_handle = &scic->phy_table[phy_index];
-
- return SCI_SUCCESS;
- }
-
- dev_err(scic_to_dev(scic),
- "%s: Controller:0x%p PhyId:0x%x invalid phy index\n",
- __func__, scic, phy_index);
-
- return SCI_FAILURE_INVALID_PHY;
-}
-
/**
* scic_controller_allocate_io_tag() - This method will allocate a tag from the
* pool of free IO tags. Direct allocation of IO tags by the SCI Core user
(result == SCI_SUCCESS) && (index < SCI_MAX_PHYS);
index++) {
result = scic_sds_phy_initialize(
- &scic->phy_table[index],
+ &ihost->phys[index].sci,
&scic->scu_registers->peg0.pe[index].tl,
&scic->scu_registers->peg0.pe[index].ll);
}
void __iomem *scu_base,
void __iomem *smu_base)
{
+ struct isci_host *ihost = scic_to_ihost(scic);
u8 i;
sci_base_state_machine_construct(&scic->state_machine,
/* Construct the phys for this controller */
for (i = 0; i < SCI_MAX_PHYS; i++) {
/* Add all the PHYs to the dummy port */
- scic_sds_phy_construct(&scic->phy_table[i],
+ scic_sds_phy_construct(&ihost->phys[i].sci,
&scic->port_table[SCI_MAX_PORTS], i);
}
*/
struct scic_sds_port port_table[SCI_MAX_PORTS + 1];
- /**
- * This field is the array of phy objects that are controlled by this
- * controller object.
- */
- struct scic_sds_phy phy_table[SCI_MAX_PHYS];
-
/**
* This field is the array of device objects that are currently constructed
* for this controller object. This table is used as a fast lookup of device
struct sci_sas_address *sas_address)
{
struct sas_identify_frame *iaf;
- struct isci_phy *iphy = sci_phy->iphy;
+ struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);
iaf = &iphy->frame_rcvd.iaf;
memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE);
enum sci_status result;
u32 *frame_words;
struct sas_identify_frame iaf;
- struct isci_phy *iphy = sci_phy->iphy;
+ struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);
result = scic_sds_unsolicited_frame_control_get_header(
&(scic_sds_phy_get_controller(sci_phy)->uf_control),
enum sci_status result;
struct dev_to_host_fis *frame_header;
u32 *fis_frame_data;
- struct isci_phy *iphy = sci_phy->iphy;
+ struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);
result = scic_sds_unsolicited_frame_control_get_header(
&(scic_sds_phy_get_controller(sci_phy)->uf_control),
SCIC_SDS_MAX_PHY_PROTOCOLS
};
-struct isci_phy;
/**
* struct scic_sds_phy - This structure contains or references all of the data
* necessary to represent the core phy object and SCU harware protocol
*
*/
struct scic_sds_phy {
- /**
- * This field depicts the peer object for the phy.
- */
- struct isci_phy *iphy;
-
/**
* This field contains the information for the base phy state machine.
*/
struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port);
struct isci_port *iport = sci_port->iport;
struct isci_host *ihost = scic_to_ihost(scic);
- struct isci_phy *iphy = sci_phy->iphy;
+ struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);
sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index);
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent)
{
+ struct isci_host *ihost = scic_to_ihost(controller);
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)
- ) {
+ 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)
- ) {
+ 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
* 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);
+ scic_sds_phy_get_sas_address(&ihost->phys[0].sci, &first_address);
+ scic_sds_phy_get_sas_address(&ihost->phys[3].sci, &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 (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(&ihost->phys[0].sci, &first_address);
+ scic_sds_phy_get_sas_address(&ihost->phys[2].sci, &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 (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(&ihost->phys[1].sci, &first_address);
+ scic_sds_phy_get_sas_address(&ihost->phys[3].sci, &second_address);
if (sci_sas_address_compare(first_address, second_address) == 0) {
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent)
{
+ struct isci_host *ihost = scic_to_ihost(controller);
u32 phy_mask;
u32 assigned_phy_mask;
struct sci_sas_address sas_address;
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;
- }
+ 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 ((1 << phy_index) & phy_mask) {
- scic_sds_phy_get_sas_address(
- &controller->phy_table[phy_index], &sas_address
- );
+ /* 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;
+ scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci,
+ &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;
- }
+ /*
+ * 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;
- break;
- }
+ if (phy_index != port_index) {
+ return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
}
- /*
- * 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;
- }
+ break;
+ }
- port_agent->phy_valid_port_range[phy_index].min_index = port_index;
- port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
+ /*
+ * 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;
+ scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci,
+ &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;
+ }
- scic_sds_port_add_phy(
- &controller->port_table[port_index],
- &controller->phy_table[phy_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;
- assigned_phy_mask |= (1 << phy_index);
- }
+ scic_sds_port_add_phy(&controller->port_table[port_index],
+ &ihost->phys[phy_index].sci);
- phy_index++;
- }
+ assigned_phy_mask |= (1 << phy_index);
}
+
+ phy_index++;
}
return scic_sds_port_configuration_agent_validate_ports(controller, port_agent);
* device objects before a new series of link up notifications because a link
* down has allowed a better port configuration.
*/
-static void scic_sds_mpc_agent_timeout_handler(
- void *object)
+static void scic_sds_mpc_agent_timeout_handler(void *object)
{
u8 index;
- struct scic_sds_controller *controller = (struct scic_sds_controller *)object;
- struct scic_sds_port_configuration_agent *port_agent = &controller->port_agent;
+ struct scic_sds_controller *scic = object;
+ struct isci_host *ihost = scic_to_ihost(scic);
+ struct scic_sds_port_configuration_agent *port_agent = &scic->port_agent;
u16 configure_phy_mask;
port_agent->timer_pending = false;
configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
for (index = 0; index < SCI_MAX_PHYS; index++) {
+ struct scic_sds_phy *sci_phy = &ihost->phys[index].sci;
+
if (configure_phy_mask & (1 << index)) {
- port_agent->link_up_handler(
- controller,
- port_agent,
- scic_sds_phy_get_port(&controller->phy_table[index]),
- &controller->phy_table[index]
- );
+ port_agent->link_up_handler(scic, port_agent,
+ scic_sds_phy_get_port(sci_phy),
+ sci_phy);
}
}
}
u8 port_index;
struct sci_sas_address sas_address;
struct sci_sas_address phy_assigned_address;
+ struct isci_host *ihost = scic_to_ihost(controller);
phy_index = 0;
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
- );
+ scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci,
+ &sas_address);
while (++phy_index < SCI_MAX_PHYS) {
- scic_sds_phy_get_sas_address(
- &controller->phy_table[phy_index], &phy_assigned_address
- );
+ scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci,
+ &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) {
}
}
-/**
- *
- *
- * This routine will try to configure the phys into ports when the timer fires.
- */
-static void scic_sds_apc_agent_timeout_handler(
- void *object)
+/* configure the phys into ports when the timer fires */
+static void scic_sds_apc_agent_timeout_handler(void *object)
{
u32 index;
struct scic_sds_port_configuration_agent *port_agent;
- struct scic_sds_controller *controller = (struct scic_sds_controller *)object;
+ struct scic_sds_controller *scic = object;
+ struct isci_host *ihost = scic_to_ihost(scic);
u16 configure_phy_mask;
- port_agent = scic_sds_controller_get_port_configuration_agent(controller);
+ port_agent = scic_sds_controller_get_port_configuration_agent(scic);
port_agent->timer_pending = false;
configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
- if (configure_phy_mask != 0x00) {
- for (index = 0; index < SCI_MAX_PHYS; index++) {
- if (configure_phy_mask & (1 << index)) {
- scic_sds_apc_agent_configure_ports(
- controller, port_agent, &controller->phy_table[index], false
- );
- }
- }
+ if (!configure_phy_mask)
+ return;
+
+ for (index = 0; index < SCI_MAX_PHYS; index++) {
+ if ((configure_phy_mask & (1 << index)) == 0)
+ continue;
+
+ scic_sds_apc_agent_configure_ports(scic, port_agent,
+ &ihost->phys[index].sci, false);
}
}
extern enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy);
extern enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy);
-/**
- * isci_phy_init() - This function is called by the probe function to
- * initialize the phy objects. This func assumes that the isci_port objects
- * associated with the SCU have been initialized.
- * @isci_phy: This parameter specifies the isci_phy object to initialize
- * @isci_host: This parameter specifies the parent SCU host object for this
- * isci_phy
- * @index: This parameter specifies which SCU phy associates with this
- * isci_phy. Generally, SCU phy 0 relates isci_phy 0, etc.
- *
- */
-void isci_phy_init(
- struct isci_phy *phy,
- struct isci_host *isci_host,
- int index)
+void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index)
{
- struct scic_sds_phy *scic_phy;
union scic_oem_parameters oem;
- enum sci_status status = SCI_SUCCESS;
- u64 sas_addr;
-
- /*--------------- SCU_Phy Initialization Stuff -----------------------*/
-
- status = scic_controller_get_phy_handle(&isci_host->sci, index, &scic_phy);
- if (status == SCI_SUCCESS) {
- phy->sci_phy_handle = scic_phy;
- scic_phy->iphy = phy;
- } else
- dev_err(&isci_host->pdev->dev,
- "failed scic_controller_get_phy_handle\n");
-
- scic_oem_parameters_get(&isci_host->sci, &oem);
- sas_addr = oem.sds1.phys[index].sas_address.high;
- sas_addr <<= 32;
- sas_addr |= oem.sds1.phys[index].sas_address.low;
- swab64s(&sas_addr);
-
- memcpy(phy->sas_addr, &sas_addr, sizeof(sas_addr));
-
- phy->isci_port = NULL;
- phy->sas_phy.enabled = 0;
- phy->sas_phy.id = index;
- phy->sas_phy.sas_addr = &phy->sas_addr[0];
- phy->sas_phy.frame_rcvd = (u8 *)&phy->frame_rcvd;
- phy->sas_phy.ha = &isci_host->sas_ha;
- phy->sas_phy.lldd_phy = phy;
- phy->sas_phy.enabled = 1;
- phy->sas_phy.class = SAS;
- phy->sas_phy.iproto = SAS_PROTOCOL_ALL;
- phy->sas_phy.tproto = 0;
- phy->sas_phy.type = PHY_TYPE_PHYSICAL;
- phy->sas_phy.role = PHY_ROLE_INITIATOR;
- phy->sas_phy.oob_mode = OOB_NOT_CONNECTED;
- phy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN;
- memset((u8 *)&phy->frame_rcvd, 0, sizeof(phy->frame_rcvd));
+ u64 sci_sas_addr;
+ __be64 sas_addr;
+
+ scic_oem_parameters_get(&ihost->sci, &oem);
+ sci_sas_addr = oem.sds1.phys[index].sas_address.high;
+ sci_sas_addr <<= 32;
+ sci_sas_addr |= oem.sds1.phys[index].sas_address.low;
+ sas_addr = cpu_to_be64(sci_sas_addr);
+ memcpy(iphy->sas_addr, &sas_addr, sizeof(sas_addr));
+
+ iphy->isci_port = NULL;
+ iphy->sas_phy.enabled = 0;
+ iphy->sas_phy.id = index;
+ iphy->sas_phy.sas_addr = &iphy->sas_addr[0];
+ iphy->sas_phy.frame_rcvd = (u8 *)&iphy->frame_rcvd;
+ iphy->sas_phy.ha = &ihost->sas_ha;
+ iphy->sas_phy.lldd_phy = iphy;
+ iphy->sas_phy.enabled = 1;
+ iphy->sas_phy.class = SAS;
+ iphy->sas_phy.iproto = SAS_PROTOCOL_ALL;
+ iphy->sas_phy.tproto = 0;
+ iphy->sas_phy.type = PHY_TYPE_PHYSICAL;
+ iphy->sas_phy.role = PHY_ROLE_INITIATOR;
+ iphy->sas_phy.oob_mode = OOB_NOT_CONNECTED;
+ iphy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN;
+ memset(&iphy->frame_rcvd, 0, sizeof(iphy->frame_rcvd));
}
switch (func) {
case PHY_FUNC_DISABLE:
spin_lock_irqsave(&ihost->scic_lock, flags);
- scic_sds_phy_stop(iphy->sci_phy_handle);
+ scic_sds_phy_stop(&iphy->sci);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
break;
case PHY_FUNC_LINK_RESET:
spin_lock_irqsave(&ihost->scic_lock, flags);
- scic_sds_phy_stop(iphy->sci_phy_handle);
- scic_sds_phy_start(iphy->sci_phy_handle);
+ scic_sds_phy_stop(&iphy->sci);
+ scic_sds_phy_start(&iphy->sci);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
break;
*/
-#if !defined(_ISCI_PHY_H_)
+#ifndef _ISCI_PHY_H_
#define _ISCI_PHY_H_
-#include "port.h"
-#include "host.h"
#include <scsi/sas.h>
#include <scsi/libsas.h>
-
-
-/**
- * struct isci_phy - This class implements the ISCI specific representation of
- * the phy object.
- *
- *
- */
+#include "scic_sds_phy.h"
+#include "port.h"
+#include "host.h"
struct isci_phy {
- struct scic_sds_phy *sci_phy_handle;
+ struct scic_sds_phy sci;
struct asd_sas_phy sas_phy;
struct isci_port *isci_port;
u8 sas_addr[SAS_ADDR_SIZE];
} frame_rcvd;
};
-#define to_isci_phy(p) \
- container_of(p, struct isci_phy, sas_phy);
+static inline struct isci_phy *to_isci_phy(struct asd_sas_phy *sas_phy)
+{
+ struct isci_phy *iphy = container_of(sas_phy, typeof(*iphy), sas_phy);
+
+ return iphy;
+}
+
+static inline struct isci_phy *sci_phy_to_iphy(struct scic_sds_phy *sci_phy)
+{
+ struct isci_phy *iphy = container_of(sci_phy, typeof(*iphy), sci);
-void isci_phy_init(
- struct isci_phy *phy,
- struct isci_host *isci_host,
- int index);
+ return iphy;
+}
-int isci_phy_control(
- struct asd_sas_phy *phy,
- enum phy_func func,
- void *buf);
+void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index);
+int isci_phy_control(struct asd_sas_phy *phy, enum phy_func func, void *buf);
#endif /* !defined(_ISCI_PHY_H_) */
spin_unlock_irqrestore(&isci_port->state_lock, flags);
}
-void isci_port_bc_change_received(
- struct isci_host *isci_host,
- struct scic_sds_port *port,
- struct scic_sds_phy *phy)
+void isci_port_bc_change_received(struct isci_host *ihost,
+ struct scic_sds_port *sci_port,
+ struct scic_sds_phy *sci_phy)
{
- struct isci_phy *isci_phy = phy->iphy;
+ struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);
- dev_dbg(&isci_host->pdev->dev,
- "%s: isci_phy = %p, sas_phy = %p\n",
- __func__,
- isci_phy,
- &isci_phy->sas_phy);
-
- isci_host->sas_ha.notify_port_event(
- &isci_phy->sas_phy,
- PORTE_BROADCAST_RCVD
- );
+ dev_dbg(&ihost->pdev->dev, "%s: iphy = %p, sas_phy = %p\n",
+ __func__, iphy, &iphy->sas_phy);
- scic_port_enable_broadcast_change_notification(port);
+ ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD);
+ scic_port_enable_broadcast_change_notification(sci_port);
}
-/**
- * isci_port_link_up() - This function is called by the sci core when a link
- * becomes active. the identify address frame is retrieved from the core and
- * a notify port event is sent to libsas.
- * @isci_host: This parameter specifies the isci host object.
- * @port: This parameter specifies the sci port with the active link.
- * @phy: This parameter specifies the sci phy with the active link.
- *
- */
-void isci_port_link_up(
- struct isci_host *isci_host,
- struct scic_sds_port *port,
- struct scic_sds_phy *phy)
+void isci_port_link_up(struct isci_host *isci_host,
+ struct scic_sds_port *port,
+ struct scic_sds_phy *phy)
{
unsigned long flags;
struct scic_port_properties properties;
- struct isci_phy *isci_phy = phy->iphy;
+ struct isci_phy *isci_phy = sci_phy_to_iphy(phy);
struct isci_port *isci_port = port->iport;
unsigned long success = true;
static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy)
{
- struct isci_phy *iphy = sci_phy->iphy;
+ struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);
if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host)
return NULL;