isci: Remove event_* calls as they are just wrappers
[linux-2.6-microblaze.git] / drivers / scsi / isci / core / scic_sds_controller.c
index cd8017f..eaaa4cc 100644 (file)
@@ -66,7 +66,6 @@
 #include "scic_sds_port.h"
 #include "scic_sds_remote_device.h"
 #include "scic_sds_request.h"
-#include "scic_user_callback.h"
 #include "sci_environment.h"
 #include "sci_util.h"
 #include "scu_completion_codes.h"
@@ -253,17 +252,23 @@ static void scic_sds_controller_phy_startup_timeout_handler(
  *
  * This method initializes the phy startup operations for controller start.
  */
-void scic_sds_controller_initialize_phy_startup(
-       struct scic_sds_controller *this_controller)
+enum sci_status scic_sds_controller_initialize_phy_startup(
+               struct scic_sds_controller *scic)
 {
-       this_controller->phy_startup_timer = scic_cb_timer_create(
-               this_controller,
-               scic_sds_controller_phy_startup_timeout_handler,
-               this_controller
-               );
+       struct isci_host *ihost = sci_object_get_association(scic);
 
-       this_controller->next_phy_to_start = 0;
-       this_controller->phy_startup_timer_pending = false;
+       scic->phy_startup_timer = isci_timer_create(ihost,
+                                                   scic,
+                                                   scic_sds_controller_phy_startup_timeout_handler);
+
+       if (scic->phy_startup_timer == NULL)
+               return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+       else {
+               scic->next_phy_to_start = 0;
+               scic->phy_startup_timer_pending = false;
+       }
+
+       return SCI_SUCCESS;
 }
 
 /**
@@ -273,21 +278,20 @@ void scic_sds_controller_initialize_phy_startup(
  * object.
  */
 void scic_sds_controller_initialize_power_control(
-       struct scic_sds_controller *this_controller)
+               struct scic_sds_controller *scic)
 {
-       this_controller->power_control.timer = scic_cb_timer_create(
-               this_controller,
-               scic_sds_controller_power_control_timer_handler,
-               this_controller
-               );
+       struct isci_host *ihost = sci_object_get_association(scic);
+       scic->power_control.timer = isci_timer_create(
+                       ihost,
+                       scic,
+                       scic_sds_controller_power_control_timer_handler);
 
-       memset(
-               this_controller->power_control.requesters,
-               0,
-               sizeof(this_controller->power_control.requesters)
-               );
+       memset(scic->power_control.requesters,
+              0,
+              sizeof(scic->power_control.requesters));
 
-       this_controller->power_control.phys_waiting = 0;
+       scic->power_control.phys_waiting = 0;
+       scic->power_control.phys_granted_power = 0;
 }
 
 /* --------------------------------------------------------------------------- */
@@ -306,7 +310,7 @@ void scic_sds_controller_initialize_power_control(
  *    to build the memory table.
  *
  */
-static void scic_sds_controller_build_memory_descriptor_table(
+void scic_sds_controller_build_memory_descriptor_table(
        struct scic_sds_controller *this_controller)
 {
        sci_base_mde_construct(
@@ -584,77 +588,64 @@ void scic_sds_controller_enable_port_task_scheduler(
  */
 #define AFE_REGISTER_WRITE_DELAY 10
 
-static bool is_a0(void)
-{
-       return isci_si_rev == ISCI_SI_REVA0;
-}
-
-static bool is_a2(void)
-{
-       return isci_si_rev == ISCI_SI_REVA2;
-}
-
-static bool is_b0(void)
-{
-       return isci_si_rev > ISCI_SI_REVA2;
-}
-
 /* Initialize the AFE for this phy index. We need to read the AFE setup from
  * the OEM parameters none
  */
 void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)
 {
+       const struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1;
        u32 afe_status;
        u32 phy_id;
 
        /* Clear DFX Status registers */
        scu_afe_register_write(scic, afe_dfx_master_control0, 0x0081000f);
-       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+       udelay(AFE_REGISTER_WRITE_DELAY);
 
        /* Configure bias currents to normal */
        if (is_a0())
                scu_afe_register_write(scic, afe_bias_control, 0x00005500);
        else
                scu_afe_register_write(scic, afe_bias_control, 0x00005A00);
-       
 
-       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+       udelay(AFE_REGISTER_WRITE_DELAY);
 
        /* Enable PLL */
        if (is_b0())
                scu_afe_register_write(scic, afe_pll_control0, 0x80040A08);
        else
                scu_afe_register_write(scic, afe_pll_control0, 0x80040908);
-               
-       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+
+       udelay(AFE_REGISTER_WRITE_DELAY);
 
        /* Wait for the PLL to lock */
        do {
                afe_status = scu_afe_register_read(
                        scic, afe_common_block_status);
-               scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+               udelay(AFE_REGISTER_WRITE_DELAY);
        } while ((afe_status & 0x00001000) == 0);
 
        if (is_b0()) {
                /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */
                scu_afe_register_write(scic, afe_pmsn_master_control0, 0x7bcc96ad);
-               scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+               udelay(AFE_REGISTER_WRITE_DELAY);
        }
 
        for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {
+               const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id];
+
                if (is_b0()) {
                         /* Configure transmitter SSC parameters */
                        scu_afe_txreg_write(scic, phy_id, afe_tx_ssc_control, 0x00030000);
-                       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
                } else {
                        /*
                         * All defaults, except the Receive Word Alignament/Comma Detect
                         * Enable....(0xe800) */
                        scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004512);
-                       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
 
                        scu_afe_txreg_write(scic, phy_id, afe_xcvr_control1, 0x0050100F);
-                       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
                }
 
                /*
@@ -667,26 +658,26 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)
                else {
                         /* Power down TX and RX (PWRDNTX and PWRDNRX) */
                        scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d7);
-                       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
 
                        /*
                         * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
                         * & increase TX int & ext bias 20%....(0xe85c) */
                        scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d4);
                }
-               scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+               udelay(AFE_REGISTER_WRITE_DELAY);
 
                if (is_a0() || is_a2()) {
                        /* Enable TX equalization (0xe824) */
                        scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000);
-                       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
                }
 
                /*
                 * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
                 * RDD=0x0(RX Detect Enabled) ....(0xe800) */
                scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004100);
-               scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+               udelay(AFE_REGISTER_WRITE_DELAY);
 
                /* Leave DFE/FFE on */
                if (is_a0())
@@ -695,28 +686,28 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)
                        scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F);
                else {
                        scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F);
-                       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+                       udelay(AFE_REGISTER_WRITE_DELAY);
                        /* Enable TX equalization (0xe824) */
                        scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000);
                }
-               scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+               udelay(AFE_REGISTER_WRITE_DELAY);
 
-               scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, 0x000E7C03);
-               scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+               scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control0);
+               udelay(AFE_REGISTER_WRITE_DELAY);
 
-               scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control1, 0x000E7C03);
-               scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+               scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control1);
+               udelay(AFE_REGISTER_WRITE_DELAY);
 
-               scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control2, 0x000E7C03);
-               scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+               scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control2);
+               udelay(AFE_REGISTER_WRITE_DELAY);
 
-               scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control3, 0x000E7C03);
-               scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+               scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control3);
+               udelay(AFE_REGISTER_WRITE_DELAY);
        }
 
        /* Transfer control to the PEs */
        scu_afe_register_write(scic, afe_dfx_master_control0, 0x00010f00);
-       scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY);
+       udelay(AFE_REGISTER_WRITE_DELAY);
 }
 
 /*
@@ -737,30 +728,29 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)
  * none.
  */
 static void scic_sds_controller_transition_to_ready(
-       struct scic_sds_controller *this_controller,
+       struct scic_sds_controller *scic,
        enum sci_status status)
 {
-       if (this_controller->parent.state_machine.current_state_id
-           == SCI_BASE_CONTROLLER_STATE_STARTING) {
+       struct isci_host *ihost = sci_object_get_association(scic);
+
+       if (scic->parent.state_machine.current_state_id ==
+                       SCI_BASE_CONTROLLER_STATE_STARTING) {
                /*
                 * We move into the ready state, because some of the phys/ports
-                * may be up and operational. */
+                * may be up and operational.
+                */
                sci_base_state_machine_change_state(
-                       scic_sds_controller_get_base_state_machine(this_controller),
-                       SCI_BASE_CONTROLLER_STATE_READY
-                       );
+                       scic_sds_controller_get_base_state_machine(scic),
+                       SCI_BASE_CONTROLLER_STATE_READY);
 
-               scic_cb_controller_start_complete(this_controller, status);
+               isci_host_start_complete(ihost, status);
        }
 }
 
-/**
- * This method is the general timeout handler for the controller. It will take
- *    the correct timetout action based on the current controller state
- */
-void scic_sds_controller_timeout_handler(
-       struct scic_sds_controller *scic)
+void scic_sds_controller_timeout_handler(void *_scic)
 {
+       struct scic_sds_controller *scic = _scic;
+       struct isci_host *ihost = sci_object_get_association(scic);
        enum sci_base_controller_states current_state;
 
        current_state = sci_base_state_machine_get_state(
@@ -773,7 +763,7 @@ void scic_sds_controller_timeout_handler(
                sci_base_state_machine_change_state(
                        scic_sds_controller_get_base_state_machine(scic),
                        SCI_BASE_CONTROLLER_STATE_FAILED);
-               scic_cb_controller_stop_complete(scic, SCI_FAILURE_TIMEOUT);
+               isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT);
        } else  /* / @todo Now what do we want to do in this case? */
                dev_err(scic_to_dev(scic),
                        "%s: Controller timer fired when controller was not "
@@ -781,31 +771,6 @@ void scic_sds_controller_timeout_handler(
                        __func__);
 }
 
-/**
- * scic_sds_controller_get_port_configuration_mode
- * @this_controller: This is the controller to use to determine if we are using
- *    manual or automatic port configuration.
- *
- * SCIC_PORT_CONFIGURATION_MODE
- */
-enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode(
-       struct scic_sds_controller *this_controller)
-{
-       u32 index;
-       enum SCIC_PORT_CONFIGURATION_MODE mode;
-
-       mode = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
-
-       for (index = 0; index < SCI_MAX_PORTS; index++) {
-               if (this_controller->oem_parameters.sds1.ports[index].phy_mask != 0) {
-                       mode = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
-                       break;
-               }
-       }
-
-       return mode;
-}
-
 enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)
 {
        u32 index;
@@ -813,7 +778,11 @@ enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)
        enum sci_status status = SCI_SUCCESS;
 
        for (index = 0; index < scic->logical_port_entries; index++) {
-               port_status = scic_port_stop(&scic->port_table[index]);
+               struct scic_sds_port *sci_port = &scic->port_table[index];
+               SCI_BASE_PORT_HANDLER_T stop;
+
+               stop = sci_port->state_handlers->parent.stop_handler;
+               port_status = stop(&sci_port->parent);
 
                if ((port_status != SCI_SUCCESS) &&
                    (port_status != SCI_FAILURE_INVALID_STATE)) {
@@ -823,7 +792,7 @@ enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)
                                 "%s: Controller stop operation failed to "
                                 "stop port %d because of status %d.\n",
                                 __func__,
-                                scic->port_table[index].logical_port_index,
+                                sci_port->logical_port_index,
                                 port_status);
                }
        }
@@ -831,42 +800,26 @@ enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)
        return status;
 }
 
-/**
- *
- *
- *
- */
-static void scic_sds_controller_phy_timer_start(
-       struct scic_sds_controller *this_controller)
+static inline void scic_sds_controller_phy_timer_start(
+               struct scic_sds_controller *scic)
 {
-       scic_cb_timer_start(
-               this_controller,
-               this_controller->phy_startup_timer,
-               SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
-               );
+       isci_timer_start(scic->phy_startup_timer,
+                        SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT);
 
-       this_controller->phy_startup_timer_pending = true;
+       scic->phy_startup_timer_pending = true;
 }
 
-/**
- *
- *
- *
- */
-void scic_sds_controller_phy_timer_stop(
-       struct scic_sds_controller *this_controller)
+inline void scic_sds_controller_phy_timer_stop(
+               struct scic_sds_controller *scic)
 {
-       scic_cb_timer_stop(
-               this_controller,
-               this_controller->phy_startup_timer
-               );
+       isci_timer_stop(scic->phy_startup_timer);
 
-       this_controller->phy_startup_timer_pending = false;
+       scic->phy_startup_timer_pending = false;
 }
 
 /**
  * This method is called internally by the controller object to start the next
- *    phy on the controller.  If all the phys have been starte, then this
+ *    phy on the controller.  If all the phys have been started, then this
  *    method will attempt to transition the controller to the READY state and
  *    inform the user (scic_cb_controller_start_complete()).
  * @this_controller: This parameter specifies the controller object for which
@@ -874,101 +827,88 @@ void scic_sds_controller_phy_timer_stop(
  *
  * enum sci_status
  */
-enum sci_status scic_sds_controller_start_next_phy(
-       struct scic_sds_controller *this_controller)
+enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic)
 {
+       struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1;
+       struct scic_sds_phy *sci_phy;
        enum sci_status status;
 
        status = SCI_SUCCESS;
 
-       if (this_controller->phy_startup_timer_pending == false) {
-               if (this_controller->next_phy_to_start == SCI_MAX_PHYS) {
-                       bool is_controller_start_complete = true;
-                       struct scic_sds_phy *the_phy;
-                       u8 index;
+       if (scic->phy_startup_timer_pending)
+               return status;
 
-                       for (index = 0; index < SCI_MAX_PHYS; index++) {
-                               the_phy = &this_controller->phy_table[index];
-
-                               if (scic_sds_phy_get_port(the_phy) != NULL) {
-                                       /**
-                                        * The controller start operation is complete if and only
-                                        * if:
-                                        * - all links have been given an opportunity to start
-                                        * - have no indication of a connected device
-                                        * - have an indication of a connected device and it has
-                                        *   finished the link training process.
-                                        */
-                                       if (
-                                               (
-                                                       (the_phy->is_in_link_training == false)
-                                                       && (the_phy->parent.state_machine.current_state_id
-                                                           == SCI_BASE_PHY_STATE_INITIAL)
-                                               )
-                                               || (
-                                                       (the_phy->is_in_link_training == false)
-                                                       && (the_phy->parent.state_machine.current_state_id
-                                                           == SCI_BASE_PHY_STATE_STOPPED)
-                                                       )
-                                               || (
-                                                       (the_phy->is_in_link_training == true)
-                                                       && (the_phy->parent.state_machine.current_state_id
-                                                           == SCI_BASE_PHY_STATE_STARTING)
-                                                       )
-                                               ) {
-                                               is_controller_start_complete = false;
-                                               break;
-                                       }
-                               }
-                       }
+       if (scic->next_phy_to_start >= SCI_MAX_PHYS) {
+               bool is_controller_start_complete = true;
+               u32 state;
+               u8 index;
 
-                       /*
-                        * The controller has successfully finished the start process.
-                        * Inform the SCI Core user and transition to the READY state. */
-                       if (is_controller_start_complete == true) {
-                               scic_sds_controller_transition_to_ready(
-                                       this_controller, SCI_SUCCESS
-                                       );
-                               scic_sds_controller_phy_timer_stop(this_controller);
-                       }
-               } else {
-                       struct scic_sds_phy *the_phy;
-
-                       the_phy = &this_controller->phy_table[this_controller->next_phy_to_start];
-
-                       if (
-                               scic_sds_controller_get_port_configuration_mode(this_controller)
-                               == SCIC_PORT_MANUAL_CONFIGURATION_MODE
-                               ) {
-                               if (scic_sds_phy_get_port(the_phy) == NULL) {
-                                       this_controller->next_phy_to_start++;
-
-                                       /*
-                                        * Caution recursion ahead be forwarned
-                                        *
-                                        * The PHY was never added to a PORT in MPC mode so start the next phy in sequence
-                                        * This phy will never go link up and will not draw power the OEM parameters either
-                                        * configured the phy incorrectly for the PORT or it was never assigned to a PORT */
-                                       return scic_sds_controller_start_next_phy(this_controller);
-                               }
+               for (index = 0; index < SCI_MAX_PHYS; index++) {
+                       sci_phy = &scic->phy_table[index];
+                       state = sci_phy->parent.state_machine.current_state_id;
+
+                       if (!scic_sds_phy_get_port(sci_phy))
+                               continue;
+
+                       /* The controller start operation is complete iff:
+                        * - all links have been given an opportunity to start
+                        * - have no indication of a connected device
+                        * - have an indication of a connected device and it has
+                        *   finished the link training process.
+                        */
+                       if ((sci_phy->is_in_link_training == false &&
+                            state == SCI_BASE_PHY_STATE_INITIAL) ||
+                           (sci_phy->is_in_link_training == false &&
+                            state == SCI_BASE_PHY_STATE_STOPPED) ||
+                           (sci_phy->is_in_link_training == true &&
+                            state == SCI_BASE_PHY_STATE_STARTING)) {
+                               is_controller_start_complete = false;
+                               break;
                        }
+               }
 
-                       status = scic_sds_phy_start(the_phy);
-
-                       if (status == SCI_SUCCESS) {
-                               scic_sds_controller_phy_timer_start(this_controller);
-                       } else {
-                               dev_warn(scic_to_dev(this_controller),
-                                        "%s: Controller stop operation failed "
-                                        "to stop phy %d because of status "
-                                        "%d.\n",
-                                        __func__,
-                                        this_controller->phy_table[this_controller->next_phy_to_start].phy_index,
-                                        status);
+               /*
+                * The controller has successfully finished the start process.
+                * Inform the SCI Core user and transition to the READY state. */
+               if (is_controller_start_complete == true) {
+                       scic_sds_controller_transition_to_ready(scic, SCI_SUCCESS);
+                       scic_sds_controller_phy_timer_stop(scic);
+               }
+       } else {
+               sci_phy = &scic->phy_table[scic->next_phy_to_start];
+
+               if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
+                       if (scic_sds_phy_get_port(sci_phy) == NULL) {
+                               scic->next_phy_to_start++;
+
+                               /* Caution recursion ahead be forwarned
+                                *
+                                * The PHY was never added to a PORT in MPC mode
+                                * so start the next phy in sequence This phy
+                                * will never go link up and will not draw power
+                                * the OEM parameters either configured the phy
+                                * incorrectly for the PORT or it was never
+                                * assigned to a PORT
+                                */
+                               return scic_sds_controller_start_next_phy(scic);
                        }
+               }
 
-                       this_controller->next_phy_to_start++;
+               status = scic_sds_phy_start(sci_phy);
+
+               if (status == SCI_SUCCESS) {
+                       scic_sds_controller_phy_timer_start(scic);
+               } else {
+                       dev_warn(scic_to_dev(scic),
+                                "%s: Controller stop operation failed "
+                                "to stop phy %d because of status "
+                                "%d.\n",
+                                __func__,
+                                scic->phy_table[scic->next_phy_to_start].phy_index,
+                                status);
                }
+
+               scic->next_phy_to_start++;
        }
 
        return status;
@@ -1050,19 +990,44 @@ enum sci_status scic_sds_controller_stop_devices(
  * ****************************************************************************- */
 
 /**
+ * This function starts the power control timer for this controller object.
  *
+ * @param scic
+ */
+static inline void scic_sds_controller_power_control_timer_start(
+       struct scic_sds_controller *scic)
+{
+       isci_timer_start(scic->power_control.timer,
+                        SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL);
+
+       scic->power_control.timer_started = true;
+}
+
+/**
+ * This method stops the power control timer for this controller object.
  *
- * This method starts the power control timer for this controller object.
+ * @param scic
  */
-static void scic_sds_controller_power_control_timer_start(
-       struct scic_sds_controller *this_controller)
+static inline void scic_sds_controller_power_control_timer_stop(
+               struct scic_sds_controller *scic)
 {
-       scic_cb_timer_start(
-               this_controller, this_controller->power_control.timer,
-               SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL
-               );
+       if (scic->power_control.timer_started) {
+               isci_timer_stop(scic->power_control.timer);
+               scic->power_control.timer_started = false;
+       }
+}
 
-       this_controller->power_control.timer_started = true;
+/**
+ * This method stops and starts the power control timer for this controller
+ * object.
+ *
+ * @param scic
+ */
+static inline void scic_sds_controller_power_control_timer_restart(
+       struct scic_sds_controller *scic)
+{
+       scic_sds_controller_power_control_timer_stop(scic);
+       scic_sds_controller_power_control_timer_start(scic);
 }
 
 /**
@@ -1077,6 +1042,8 @@ static void scic_sds_controller_power_control_timer_handler(
 
        this_controller = (struct scic_sds_controller *)controller;
 
+       this_controller->power_control.phys_granted_power = 0;
+
        if (this_controller->power_control.phys_waiting == 0) {
                this_controller->power_control.timer_started = false;
        } else {
@@ -1088,19 +1055,24 @@ static void scic_sds_controller_power_control_timer_handler(
                     && (this_controller->power_control.phys_waiting != 0);
                     i++) {
                        if (this_controller->power_control.requesters[i] != NULL) {
-                               the_phy = this_controller->power_control.requesters[i];
-                               this_controller->power_control.requesters[i] = NULL;
-                               this_controller->power_control.phys_waiting--;
-                               break;
+                               if (this_controller->power_control.phys_granted_power <
+                                   this_controller->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) {
+                                       the_phy = this_controller->power_control.requesters[i];
+                                       this_controller->power_control.requesters[i] = NULL;
+                                       this_controller->power_control.phys_waiting--;
+                                       this_controller->power_control.phys_granted_power++;
+                                       scic_sds_phy_consume_power_handler(the_phy);
+                               } else {
+                                       break;
+                               }
                        }
                }
 
                /*
                 * It doesn't matter if the power list is empty, we need to start the
-                * timer in case another phy becomes ready. */
+                * timer in case another phy becomes ready.
+                */
                scic_sds_controller_power_control_timer_start(this_controller);
-
-               scic_sds_phy_consume_power_handler(the_phy);
        }
 }
 
@@ -1116,15 +1088,20 @@ void scic_sds_controller_power_control_queue_insert(
 {
        BUG_ON(the_phy == NULL);
 
-       if (
-               (this_controller->power_control.timer_started)
-               && (this_controller->power_control.requesters[the_phy->phy_index] == NULL)
-               ) {
+       if (this_controller->power_control.phys_granted_power <
+           this_controller->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) {
+               this_controller->power_control.phys_granted_power++;
+               scic_sds_phy_consume_power_handler(the_phy);
+
+               /*
+                * stop and start the power_control timer. When the timer fires, the
+                * no_of_phys_granted_power will be set to 0
+                */
+               scic_sds_controller_power_control_timer_restart(this_controller);
+       } else {
+               /* Add the phy in the waiting list */
                this_controller->power_control.requesters[the_phy->phy_index] = the_phy;
                this_controller->power_control.phys_waiting++;
-       } else {
-               scic_sds_controller_power_control_timer_start(this_controller);
-               scic_sds_phy_consume_power_handler(the_phy);
        }
 }
 
@@ -1519,385 +1496,51 @@ static void scic_sds_controller_process_completions(
                        break;
 
                case SCU_COMPLETION_TYPE_UFI:
-                       scic_sds_controller_unsolicited_frame(this_controller, completion_entry);
-                       break;
-
-               case SCU_COMPLETION_TYPE_EVENT:
-                       INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
-                       scic_sds_controller_event_completion(this_controller, completion_entry);
-                       break;
-
-               case SCU_COMPLETION_TYPE_NOTIFY:
-                       /*
-                        * Presently we do the same thing with a notify event that we do with the
-                        * other event codes. */
-                       INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
-                       scic_sds_controller_event_completion(this_controller, completion_entry);
-                       break;
-
-               default:
-                       dev_warn(scic_to_dev(this_controller),
-                                "%s: SCIC Controller received unknown "
-                                "completion type %x\n",
-                                __func__,
-                                completion_entry);
-                       break;
-               }
-       }
-
-       /* Update the get register if we completed one or more entries */
-       if (completion_count > 0) {
-               this_controller->completion_queue_get =
-                       SMU_CQGR_GEN_BIT(ENABLE)
-                       | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
-                       | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
-                       | get_cycle   | SMU_CQGR_GEN_VAL(POINTER, get_index);
-
-               SMU_CQGR_WRITE(this_controller,
-                              this_controller->completion_queue_get);
-       }
-
-       dev_dbg(scic_to_dev(this_controller),
-               "%s: completion queue ending get:0x%08x\n",
-               __func__,
-               this_controller->completion_queue_get);
-
-}
-
-/**
- * This method is a private routine for processing the completion queue entries.
- * @this_controller:
- *
- */
-static void scic_sds_controller_transitioned_process_completions(
-       struct scic_sds_controller *this_controller)
-{
-       u32 completion_count = 0;
-       u32 completion_entry;
-       u32 get_index;
-       u32 get_cycle;
-       u32 event_index;
-       u32 event_cycle;
-
-       dev_dbg(scic_to_dev(this_controller),
-               "%s: completion queue begining get:0x%08x\n",
-               __func__,
-               this_controller->completion_queue_get);
-
-       /* Get the component parts of the completion queue */
-       get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get);
-       get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get;
-
-       event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get);
-       event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get;
-
-       while (
-               NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
-               == COMPLETION_QUEUE_CYCLE_BIT(
-                       this_controller->completion_queue[get_index])
-               ) {
-               completion_count++;
-
-               completion_entry = this_controller->completion_queue[get_index];
-               INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle);
-
-               dev_dbg(scic_to_dev(this_controller),
-                       "%s: completion queue entry:0x%08x\n",
-                       __func__,
-                       completion_entry);
-
-               switch (SCU_GET_COMPLETION_TYPE(completion_entry)) {
-               case SCU_COMPLETION_TYPE_TASK:
-                       scic_sds_controller_task_completion(this_controller, completion_entry);
-                       break;
-
-               case SCU_COMPLETION_TYPE_NOTIFY:
-               case SCU_COMPLETION_TYPE_EVENT:
-                       /*
-                        * Presently we do the same thing with a notify event that we
-                        * do with the other event codes. */
-                       INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
-               /* Fall-through */
-
-               case SCU_COMPLETION_TYPE_SDMA:
-               case SCU_COMPLETION_TYPE_UFI:
-               default:
-                       dev_warn(scic_to_dev(this_controller),
-                                "%s: SCIC Controller ignoring completion type "
-                                "%x\n",
-                                __func__,
-                                completion_entry);
-                       break;
-               }
-       }
-
-       /* Update the get register if we completed one or more entries */
-       if (completion_count > 0) {
-               this_controller->completion_queue_get =
-                       SMU_CQGR_GEN_BIT(ENABLE)
-                       | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
-                       | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
-                       | get_cycle   | SMU_CQGR_GEN_VAL(POINTER, get_index);
-
-               SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get);
-       }
-
-       dev_dbg(scic_to_dev(this_controller),
-               "%s: completion queue ending get:0x%08x\n",
-               __func__,
-               this_controller->completion_queue_get);
-}
-
-/*
- * ****************************************************************************-
- * * SCIC SDS Controller Interrupt and Completion functions
- * ****************************************************************************- */
-
-/**
- * This method provides standard (common) processing of interrupts for polling
- *    and legacy based interrupts.
- * @controller:
- * @interrupt_status:
- *
- * This method returns a boolean (bool) indication as to whether an completions
- * are pending to be processed. true if an interrupt is to be processed false
- * if no interrupt was pending
- */
-static bool scic_sds_controller_standard_interrupt_handler(
-       struct scic_sds_controller *this_controller,
-       u32 interrupt_status)
-{
-       bool is_completion_needed = false;
-
-       if ((interrupt_status & SMU_ISR_QUEUE_ERROR) ||
-           ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) &&
-            (!scic_sds_controller_completion_queue_has_entries(
-                                                       this_controller)))) {
-               /*
-                * We have a fatal error on the read of the completion queue bar
-                * OR
-                * We have a fatal error there is nothing in the completion queue
-                * but we have a report from the hardware that the queue is full
-                * / @todo how do we request the a controller reset */
-               is_completion_needed = true;
-               this_controller->encountered_fatal_error = true;
-       }
-
-       if (scic_sds_controller_completion_queue_has_entries(this_controller)) {
-               is_completion_needed = true;
-       }
-
-       return is_completion_needed;
-}
-
-/**
- * This is the method provided to handle polling for interrupts for the
- *    controller object.
- *
- * bool true if an interrupt is to be processed false if no interrupt was
- * pending
- */
-static bool scic_sds_controller_polling_interrupt_handler(
-       struct scic_sds_controller *scic)
-{
-       u32 interrupt_status;
-
-       /*
-        * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the
-        * hardware indicates nothing is pending. Since we are not being
-        * called from a real interrupt, we don't want to confuse the hardware
-        * by servicing the completion queue before the hardware indicates it
-        * is ready. We'll simply wait for another polling interval and check
-        * again.
-        */
-       interrupt_status = SMU_ISR_READ(scic);
-       if ((interrupt_status &
-            (SMU_ISR_COMPLETION |
-             SMU_ISR_QUEUE_ERROR |
-             SMU_ISR_QUEUE_SUSPEND)) == 0) {
-               return false;
-       }
-
-       return scic_sds_controller_standard_interrupt_handler(
-                      scic, interrupt_status);
-}
-
-/**
- * This is the method provided to handle completions when interrupt polling is
- *    in use.
- */
-static void scic_sds_controller_polling_completion_handler(
-       struct scic_sds_controller *scic)
-{
-       if (scic->encountered_fatal_error == true) {
-               dev_err(scic_to_dev(scic),
-                       "%s: SCIC Controller has encountered a fatal error.\n",
-                       __func__);
-
-               sci_base_state_machine_change_state(
-                       scic_sds_controller_get_base_state_machine(scic),
-                       SCI_BASE_CONTROLLER_STATE_FAILED);
-       } else if (scic_sds_controller_completion_queue_has_entries(scic)) {
-               if (scic->restrict_completions == false)
-                       scic_sds_controller_process_completions(scic);
-               else
-                       scic_sds_controller_transitioned_process_completions(
-                               scic);
-       }
-
-       /*
-        * The interrupt handler does not adjust the CQ's
-        * get pointer.  So, SCU's INTx pin stays asserted during the
-        * interrupt handler even though it tries to clear the interrupt
-        * source.  Therefore, the completion handler must ensure that the
-        * interrupt source is cleared.  Otherwise, we get a spurious
-        * interrupt for which the interrupt handler will not issue a
-        * corresponding completion event. Also, we unmask interrupts.
-        */
-       SMU_ISR_WRITE(
-               scic,
-               (u32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)
-               );
-}
-
-/**
- * This is the method provided to handle legacy interrupts for the controller
- *    object.
- *
- * bool true if an interrupt is processed false if no interrupt was processed
- */
-static bool scic_sds_controller_legacy_interrupt_handler(
-       struct scic_sds_controller *scic)
-{
-       u32 interrupt_status;
-       bool is_completion_needed;
-
-       interrupt_status     = SMU_ISR_READ(scic);
-       is_completion_needed = scic_sds_controller_standard_interrupt_handler(
-               scic, interrupt_status);
-
-       return is_completion_needed;
-}
-
-
-/**
- * This is the method provided to handle legacy completions it is expected that
- *    the SCI User will call this completion handler anytime the interrupt
- *    handler reports that it has handled an interrupt.
- */
-static void scic_sds_controller_legacy_completion_handler(
-       struct scic_sds_controller *scic)
-{
-       scic_sds_controller_polling_completion_handler(scic);
-       SMU_IMR_WRITE(scic, 0x00000000);
-}
-
-/**
- * This is the method provided to handle an MSIX interrupt message when there
- *    is just a single MSIX message being provided by the hardware.  This mode
- *    of operation is single vector mode.
- *
- * bool true if an interrupt is processed false if no interrupt was processed
- */
-static bool scic_sds_controller_single_vector_interrupt_handler(
-       struct scic_sds_controller *scic)
-{
-       u32 interrupt_status;
-
-       /*
-        * Mask the interrupts
-        * There is a race in the hardware that could cause us not to be notified
-        * of an interrupt completion if we do not take this step.  We will unmask
-        * the interrupts in the completion routine. */
-       SMU_IMR_WRITE(scic, 0xFFFFFFFF);
-
-       interrupt_status = SMU_ISR_READ(scic);
-       interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
-
-       if ((interrupt_status == 0) &&
-           scic_sds_controller_completion_queue_has_entries(scic)) {
-               /*
-                * There is at least one completion queue entry to process so we can
-                * return a success and ignore for now the case of an error interrupt */
-               SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION);
-               return true;
-       }
-
-       if (interrupt_status != 0) {
-               /*
-                * There is an error interrupt pending so let it through and handle
-                * in the callback */
-               return true;
-       }
-
-       /*
-        * Clear any offending interrupts since we could not find any to handle
-        * and unmask them all */
-       SMU_ISR_WRITE(scic, 0x00000000);
-       SMU_IMR_WRITE(scic, 0x00000000);
-
-       return false;
-}
-
-/**
- * This is the method provided to handle completions for a single MSIX message.
- */
-static void scic_sds_controller_single_vector_completion_handler(
-       struct scic_sds_controller *scic)
-{
-       u32 interrupt_status;
-
-       interrupt_status = SMU_ISR_READ(scic);
-       interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
-
-       if (interrupt_status & SMU_ISR_QUEUE_ERROR) {
-               dev_err(scic_to_dev(scic),
-                       "%s: SCIC Controller has encountered a fatal error.\n",
-                       __func__);
-
-               /*
-                * We have a fatal condition and must reset the controller
-                * Leave the interrupt mask in place and get the controller reset */
-               sci_base_state_machine_change_state(
-                       scic_sds_controller_get_base_state_machine(scic),
-                       SCI_BASE_CONTROLLER_STATE_FAILED);
-               return;
-       }
+                       scic_sds_controller_unsolicited_frame(this_controller, completion_entry);
+                       break;
 
-       if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) &&
-           !scic_sds_controller_completion_queue_has_entries(scic)) {
-               dev_err(scic_to_dev(scic),
-                       "%s: SCIC Controller has encountered a fatal error.\n",
-                       __func__);
+               case SCU_COMPLETION_TYPE_EVENT:
+                       INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
+                       scic_sds_controller_event_completion(this_controller, completion_entry);
+                       break;
 
-               /*
-                * We have a fatal condtion and must reset the controller
-                * Leave the interrupt mask in place and get the controller reset */
-               sci_base_state_machine_change_state(
-                       scic_sds_controller_get_base_state_machine(scic),
-                       SCI_BASE_CONTROLLER_STATE_FAILED);
-               return;
+               case SCU_COMPLETION_TYPE_NOTIFY:
+                       /*
+                        * Presently we do the same thing with a notify event that we do with the
+                        * other event codes. */
+                       INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle);
+                       scic_sds_controller_event_completion(this_controller, completion_entry);
+                       break;
+
+               default:
+                       dev_warn(scic_to_dev(this_controller),
+                                "%s: SCIC Controller received unknown "
+                                "completion type %x\n",
+                                __func__,
+                                completion_entry);
+                       break;
+               }
        }
 
-       if (scic_sds_controller_completion_queue_has_entries(scic)) {
-               scic_sds_controller_process_completions(scic);
+       /* Update the get register if we completed one or more entries */
+       if (completion_count > 0) {
+               this_controller->completion_queue_get =
+                       SMU_CQGR_GEN_BIT(ENABLE)
+                       | SMU_CQGR_GEN_BIT(EVENT_ENABLE)
+                       | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index)
+                       | get_cycle   | SMU_CQGR_GEN_VAL(POINTER, get_index);
 
-               /*
-                * We dont care which interrupt got us to processing the completion queu
-                * so clear them both. */
-               SMU_ISR_WRITE(
-                       scic,
-                       (SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND));
+               SMU_CQGR_WRITE(this_controller,
+                              this_controller->completion_queue_get);
        }
 
-       SMU_IMR_WRITE(scic, 0x00000000);
+       dev_dbg(scic_to_dev(this_controller),
+               "%s: completion queue ending get:0x%08x\n",
+               __func__,
+               this_controller->completion_queue_get);
+
 }
 
-/**
- * This is the method provided to handle a MSIX message for a normal completion.
- *
- * bool true if an interrupt is processed false if no interrupt was processed
- */
 bool scic_sds_controller_isr(struct scic_sds_controller *scic)
 {
        if (scic_sds_controller_completion_queue_has_entries(scic)) {
@@ -1920,10 +1563,6 @@ bool scic_sds_controller_isr(struct scic_sds_controller *scic)
        return false;
 }
 
-/**
- * This is the method provided to handle the completions for a normal MSIX
- *    message.
- */
 void scic_sds_controller_completion_handler(struct scic_sds_controller *scic)
 {
        /* Empty out the completion queue */
@@ -1937,18 +1576,12 @@ void scic_sds_controller_completion_handler(struct scic_sds_controller *scic)
        SMU_IMR_WRITE(scic, 0x00000000);
 }
 
-/**
- * This is the method provided to handle the error MSIX message interrupt.
- *    This is the normal operating mode for the hardware if MSIX is enabled.
- *
- * bool true if an interrupt is processed false if no interrupt was processed
- */
-static bool scic_sds_controller_error_vector_interrupt_handler(
-       struct scic_sds_controller *scic)
+bool scic_sds_controller_error_isr(struct scic_sds_controller *scic)
 {
        u32 interrupt_status;
 
        interrupt_status = SMU_ISR_READ(scic);
+
        interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
 
        if (interrupt_status != 0) {
@@ -1970,12 +1603,7 @@ static bool scic_sds_controller_error_vector_interrupt_handler(
        return false;
 }
 
-/**
- * This is the method provided to handle the error completions when the
- *    hardware is using two MSIX messages.
- */
-static void scic_sds_controller_error_vector_completion_handler(
-       struct scic_sds_controller *scic)
+void scic_sds_controller_error_handler(struct scic_sds_controller *scic)
 {
        u32 interrupt_status;
 
@@ -1988,10 +1616,7 @@ static void scic_sds_controller_error_vector_completion_handler(
                SMU_ISR_WRITE(scic, SMU_ISR_QUEUE_SUSPEND);
 
        } else {
-               dev_err(scic_to_dev(scic),
-                       "%s: SCIC Controller reports CRC error on completion "
-                       "ISR %x\n",
-                       __func__,
+               dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__,
                        interrupt_status);
 
                sci_base_state_machine_change_state(
@@ -2008,14 +1633,6 @@ static void scic_sds_controller_error_vector_completion_handler(
 }
 
 
-/*
- * ****************************************************************************-
- * * SCIC SDS Controller External Methods
- * ****************************************************************************- */
-
-/**
- * This method returns the sizeof the SCIC SDS Controller Object
- */
 u32 scic_sds_controller_get_object_size(void)
 {
        return sizeof(struct scic_sds_controller);
@@ -2036,7 +1653,7 @@ void scic_sds_controller_link_up(
        if (link_up)
                link_up(scic, sci_port, sci_phy);
        else
-               dev_warn(scic_to_dev(scic),
+               dev_dbg(scic_to_dev(scic),
                        "%s: SCIC Controller linkup event from phy %d in "
                        "unexpected state %d\n",
                        __func__,
@@ -2061,16 +1678,86 @@ void scic_sds_controller_link_down(
        if (link_down)
                link_down(scic, sci_port, sci_phy);
        else
-               dev_warn(scic_to_dev(scic),
+               dev_dbg(scic_to_dev(scic),
                        "%s: SCIC Controller linkdown event from phy %d in "
                        "unexpected state %d\n",
                        __func__,
-                       sci_phy->phy_index,
-                       sci_base_state_machine_get_state(
-                               scic_sds_controller_get_base_state_machine(
-                                       scic)));
+                       sci_phy->phy_index, state);
+}
+
+/**
+ * This method is called by the remote device to inform the controller
+ * that this remote device has started.
+ *
+ */
+
+void scic_sds_controller_remote_device_started(struct scic_sds_controller *scic,
+                                              struct scic_sds_remote_device *sci_dev)
+{
+       u32 state;
+       scic_sds_controller_device_handler_t started;
+
+       state = scic->parent.state_machine.current_state_id;
+       started = scic_sds_controller_state_handler_table[state].remote_device_started_handler;
+
+       if (started)
+               started(scic, sci_dev);
+       else {
+               dev_dbg(scic_to_dev(scic),
+                        "%s: SCIC Controller 0x%p remote device started event "
+                        "from device 0x%p in unexpected state  %d\n",
+                        __func__, scic, sci_dev, state);
+       }
+}
+
+/**
+ * This is a helper method to determine if any remote devices on this
+ * controller are still in the stopping state.
+ *
+ */
+bool scic_sds_controller_has_remote_devices_stopping(
+       struct scic_sds_controller *this_controller)
+{
+       u32 index;
+
+       for (index = 0; index < this_controller->remote_node_entries; index++) {
+               if ((this_controller->device_table[index] != NULL) &&
+                  (this_controller->device_table[index]->parent.state_machine.current_state_id
+                   == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING))
+                       return true;
+       }
+
+       return false;
+}
+
+/**
+ * This method is called by the remote device to inform the controller
+ * object that the remote device has stopped.
+ *
+ */
+
+void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic,
+                                              struct scic_sds_remote_device *sci_dev)
+{
+
+       u32 state;
+       scic_sds_controller_device_handler_t stopped;
+
+       state = scic->parent.state_machine.current_state_id;
+       stopped = scic_sds_controller_state_handler_table[state].remote_device_stopped_handler;
+
+       if (stopped)
+               stopped(scic, sci_dev);
+       else {
+               dev_dbg(scic_to_dev(scic),
+                       "%s: SCIC Controller 0x%p remote device stopped event "
+                       "from device 0x%p in unexpected state  %d\n",
+                       __func__, scic, sci_dev, state);
+       }
 }
 
+
+
 /**
  * This method will write to the SCU PCP register the request value. The method
  *    is used to suspend/resume ports, devices, and phys.
@@ -2318,47 +2005,53 @@ void scic_sds_controller_release_frame(
  * This method sets user parameters and OEM parameters to default values.
  *    Users can override these values utilizing the scic_user_parameters_set()
  *    and scic_oem_parameters_set() methods.
- * @controller: This parameter specifies the controller for which to set the
+ * @scic: This parameter specifies the controller for which to set the
  *    configuration parameters to their default values.
  *
  */
-static void scic_sds_controller_set_default_config_parameters(
-       struct scic_sds_controller *this_controller)
+static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic)
 {
+       struct isci_host *ihost = sci_object_get_association(scic);
        u16 index;
 
+       /* Default to APC mode. */
+       scic->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
+
+       /* Default to APC mode. */
+       scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1;
+
        /* Default to no SSC operation. */
-       this_controller->oem_parameters.sds1.controller.do_enable_ssc = false;
+       scic->oem_parameters.sds1.controller.do_enable_ssc = false;
 
        /* Initialize all of the port parameter information to narrow ports. */
        for (index = 0; index < SCI_MAX_PORTS; index++) {
-               this_controller->oem_parameters.sds1.ports[index].phy_mask = 0;
+               scic->oem_parameters.sds1.ports[index].phy_mask = 0;
        }
 
        /* Initialize all of the phy parameter information. */
        for (index = 0; index < SCI_MAX_PHYS; index++) {
-               /*
-                * Default to 3G (i.e. Gen 2) for now.  User can override if
-                * they choose. */
-               this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2;
+               /* Default to 6G (i.e. Gen 3) for now. */
+               scic->user_parameters.sds1.phys[index].max_speed_generation = 3;
+
+               /* the frequencies cannot be 0 */
+               scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f;
+               scic->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff;
+               scic->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33;
 
                /*
                 * Previous Vitesse based expanders had a arbitration issue that
                 * is worked around by having the upper 32-bits of SAS address
                 * with a value greater then the Vitesse company identifier.
                 * Hence, usage of 0x5FCFFFFF. */
-               this_controller->oem_parameters.sds1.phys[index].sas_address.low
-                       = 0x00000001;
-               this_controller->oem_parameters.sds1.phys[index].sas_address.high
-                       = 0x5FCFFFFF;
+               scic->oem_parameters.sds1.phys[index].sas_address.low = 0x1 + ihost->id;
+               scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF;
        }
 
-       this_controller->user_parameters.sds1.stp_inactivity_timeout = 5;
-       this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5;
-       this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5;
-       this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20;
-       this_controller->user_parameters.sds1.no_outbound_task_timeout = 5;
-
+       scic->user_parameters.sds1.stp_inactivity_timeout = 5;
+       scic->user_parameters.sds1.ssp_inactivity_timeout = 5;
+       scic->user_parameters.sds1.stp_max_occupancy_timeout = 5;
+       scic->user_parameters.sds1.ssp_max_occupancy_timeout = 20;
+       scic->user_parameters.sds1.no_outbound_task_timeout = 20;
 }
 
 
@@ -2412,7 +2105,7 @@ enum sci_status scic_controller_construct(struct scic_sds_controller *controller
        /* Initialize the User and OEM parameters to default values. */
        scic_sds_controller_set_default_config_parameters(controller);
 
-       return SCI_SUCCESS;
+       return scic_controller_reset(controller);
 }
 
 /* --------------------------------------------------------------------------- */
@@ -2464,9 +2157,9 @@ u32 scic_controller_get_suggested_start_timeout(
         *       per interval - 1 (once OEM parameters are supported).
         *       Currently we assume only 1 phy per interval. */
 
-       return (SCIC_SDS_SIGNATURE_FIS_TIMEOUT
+       return SCIC_SDS_SIGNATURE_FIS_TIMEOUT
                + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
-               + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL));
+               + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL);
 }
 
 /* --------------------------------------------------------------------------- */
@@ -2549,72 +2242,6 @@ enum sci_status scic_controller_reset(
        return status;
 }
 
-/* --------------------------------------------------------------------------- */
-
-enum sci_status scic_controller_get_handler_methods(
-       enum scic_interrupt_type interrupt_type,
-       u16 message_count,
-       struct scic_controller_handler_methods *handler_methods)
-{
-       enum sci_status status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT;
-
-       switch (interrupt_type) {
-       case SCIC_LEGACY_LINE_INTERRUPT_TYPE:
-               if (message_count == 0) {
-                       handler_methods[0].interrupt_handler
-                               = scic_sds_controller_legacy_interrupt_handler;
-                       handler_methods[0].completion_handler
-                               = scic_sds_controller_legacy_completion_handler;
-
-                       status = SCI_SUCCESS;
-               }
-               break;
-
-       case SCIC_MSIX_INTERRUPT_TYPE:
-               if (message_count == 1) {
-                       handler_methods[0].interrupt_handler
-                               = scic_sds_controller_single_vector_interrupt_handler;
-                       handler_methods[0].completion_handler
-                               = scic_sds_controller_single_vector_completion_handler;
-
-                       status = SCI_SUCCESS;
-               } else if (message_count == 2) {
-                       handler_methods[0].interrupt_handler
-                               = scic_sds_controller_isr;
-                       handler_methods[0].completion_handler
-                               = scic_sds_controller_completion_handler;
-
-                       handler_methods[1].interrupt_handler
-                               = scic_sds_controller_error_vector_interrupt_handler;
-                       handler_methods[1].completion_handler
-                               = scic_sds_controller_error_vector_completion_handler;
-
-                       status = SCI_SUCCESS;
-               }
-               break;
-
-       case SCIC_NO_INTERRUPTS:
-               if (message_count == 0) {
-
-                       handler_methods[0].interrupt_handler
-                               = scic_sds_controller_polling_interrupt_handler;
-                       handler_methods[0].completion_handler
-                               = scic_sds_controller_polling_completion_handler;
-
-                       status = SCI_SUCCESS;
-               }
-               break;
-
-       default:
-               status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
-               break;
-       }
-
-       return status;
-}
-
-/* --------------------------------------------------------------------------- */
-
 enum sci_io_status scic_controller_start_io(
        struct scic_sds_controller *scic,
        struct scic_sds_remote_device *remote_device,
@@ -2887,7 +2514,7 @@ void scic_sds_controller_reset_hardware(
        SMU_SMUSRCR_WRITE(scic, 0xFFFFFFFF);
 
        /* Delay for 1ms to before clearing the CQP and UFQPR. */
-       scic_cb_stall_execution(1000);
+       udelay(1000);
 
        /* The write to the CQGR clears the CQP */
        SMU_CQGR_WRITE(scic, 0x00000000);
@@ -2902,30 +2529,48 @@ enum sci_status scic_user_parameters_set(
        struct scic_sds_controller *scic,
        union scic_user_parameters *scic_parms)
 {
-       if (
-               (scic->parent.state_machine.current_state_id
-                == SCI_BASE_CONTROLLER_STATE_RESET)
-               || (scic->parent.state_machine.current_state_id
-                   == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
-               || (scic->parent.state_machine.current_state_id
-                   == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
-               ) {
+       u32 state = scic->parent.state_machine.current_state_id;
+
+       if (state == SCI_BASE_CONTROLLER_STATE_RESET ||
+           state == SCI_BASE_CONTROLLER_STATE_INITIALIZING ||
+           state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) {
                u16 index;
 
                /*
                 * Validate the user parameters.  If they are not legal, then
-                * return a failure. */
+                * return a failure.
+                */
                for (index = 0; index < SCI_MAX_PHYS; index++) {
-                       if (!
-                           (scic_parms->sds1.phys[index].max_speed_generation
-                            <= SCIC_SDS_PARM_MAX_SPEED
-                            && scic_parms->sds1.phys[index].max_speed_generation
-                            > SCIC_SDS_PARM_NO_SPEED
-                           )
-                           )
+                       struct sci_phy_user_params *user_phy;
+
+                       user_phy = &scic_parms->sds1.phys[index];
+
+                       if (!((user_phy->max_speed_generation <=
+                                               SCIC_SDS_PARM_MAX_SPEED) &&
+                             (user_phy->max_speed_generation >
+                                               SCIC_SDS_PARM_NO_SPEED)))
+                               return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+                       if (user_phy->in_connection_align_insertion_frequency <
+                                       3)
+                               return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+                       if ((user_phy->in_connection_align_insertion_frequency <
+                                               3) ||
+                           (user_phy->align_insertion_frequency == 0) ||
+                           (user_phy->
+                               notify_enable_spin_up_insertion_frequency ==
+                                               0))
                                return SCI_FAILURE_INVALID_PARAMETER_VALUE;
                }
 
+               if ((scic_parms->sds1.stp_inactivity_timeout == 0) ||
+                   (scic_parms->sds1.ssp_inactivity_timeout == 0) ||
+                   (scic_parms->sds1.stp_max_occupancy_timeout == 0) ||
+                   (scic_parms->sds1.ssp_max_occupancy_timeout == 0) ||
+                   (scic_parms->sds1.no_outbound_task_timeout == 0))
+                       return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
                memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms));
 
                return SCI_SUCCESS;
@@ -2949,35 +2594,50 @@ enum sci_status scic_oem_parameters_set(
        struct scic_sds_controller *scic,
        union scic_oem_parameters *scic_parms)
 {
-       if (
-               (scic->parent.state_machine.current_state_id
-                == SCI_BASE_CONTROLLER_STATE_RESET)
-               || (scic->parent.state_machine.current_state_id
-                   == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
-               || (scic->parent.state_machine.current_state_id
-                   == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
-               ) {
+       u32 state = scic->parent.state_machine.current_state_id;
+
+       if (state == SCI_BASE_CONTROLLER_STATE_RESET ||
+           state == SCI_BASE_CONTROLLER_STATE_INITIALIZING ||
+           state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) {
                u16 index;
+               u8  combined_phy_mask = 0;
 
                /*
                 * Validate the oem parameters.  If they are not legal, then
                 * return a failure. */
                for (index = 0; index < SCI_MAX_PORTS; index++) {
-                       if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX) {
+                       if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX)
                                return SCI_FAILURE_INVALID_PARAMETER_VALUE;
-                       }
                }
 
                for (index = 0; index < SCI_MAX_PHYS; index++) {
-                       if (
-                               scic_parms->sds1.phys[index].sas_address.high == 0
-                               && scic_parms->sds1.phys[index].sas_address.low  == 0
-                               ) {
+                       if ((scic_parms->sds1.phys[index].sas_address.high == 0) &&
+                           (scic_parms->sds1.phys[index].sas_address.low == 0))
                                return SCI_FAILURE_INVALID_PARAMETER_VALUE;
-                       }
                }
 
-               memcpy(&scic->oem_parameters, scic_parms, sizeof(*scic_parms));
+               if (scic_parms->sds1.controller.mode_type ==
+                               SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) {
+                       for (index = 0; index < SCI_MAX_PHYS; index++) {
+                               if (scic_parms->sds1.ports[index].phy_mask != 0)
+                                       return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+                       }
+               } else if (scic_parms->sds1.controller.mode_type ==
+                               SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
+                       for (index = 0; index < SCI_MAX_PHYS; index++)
+                               combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask;
+
+                       if (combined_phy_mask == 0)
+                               return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+               } else
+                       return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+               if (scic_parms->sds1.controller.max_concurrent_dev_spin_up >
+                               MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
+                       return SCI_FAILURE_INVALID_PARAMETER_VALUE;
+
+               scic->oem_parameters.sds1 = scic_parms->sds1;
+
                return SCI_SUCCESS;
        }
 
@@ -3214,51 +2874,41 @@ static enum sci_status scic_sds_controller_general_reset_handler(
  * * RESET STATE HANDLERS
  * ***************************************************************************** */
 
-/**
- *
- * @controller: This is the struct sci_base_controller object which is cast into a
- *    struct scic_sds_controller object.
- *
- * This method is the struct scic_sds_controller initialize handler for the reset
- * state. - Currently this function does nothing enum sci_status SCI_FAILURE This
- * function is not yet implemented and is a valid request from the reset state.
- */
-static enum sci_status scic_sds_controller_reset_state_initialize_handler(
-       struct sci_base_controller *controller)
+static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct sci_base_controller *base_scic)
 {
-       u32 index;
        enum sci_status result = SCI_SUCCESS;
-       struct scic_sds_controller *this_controller;
+       struct scic_sds_controller *scic;
+       struct isci_host *ihost;
+       u32 index;
 
-       this_controller = (struct scic_sds_controller *)controller;
+       scic = container_of(base_scic, typeof(*scic), parent);
+       ihost = sci_object_get_association(scic);
 
        sci_base_state_machine_change_state(
-               scic_sds_controller_get_base_state_machine(this_controller),
-               SCI_BASE_CONTROLLER_STATE_INITIALIZING
-               );
+               scic_sds_controller_get_base_state_machine(scic),
+               SCI_BASE_CONTROLLER_STATE_INITIALIZING);
 
-       this_controller->timeout_timer = scic_cb_timer_create(
-               this_controller,
-               (void (*)(void *))scic_sds_controller_timeout_handler,
-               (void (*)(void *))controller);
+       scic->timeout_timer = isci_timer_create(ihost,
+                                               scic,
+                                               scic_sds_controller_timeout_handler);
 
-       scic_sds_controller_initialize_phy_startup(this_controller);
+       scic_sds_controller_initialize_phy_startup(scic);
 
-       scic_sds_controller_initialize_power_control(this_controller);
+       scic_sds_controller_initialize_power_control(scic);
 
        /*
         * There is nothing to do here for B0 since we do not have to
         * program the AFE registers.
         * / @todo The AFE settings are supposed to be correct for the B0 but
         * /       presently they seem to be wrong. */
-       scic_sds_controller_afe_initialization(this_controller);
+       scic_sds_controller_afe_initialization(scic);
 
-       if (SCI_SUCCESS == result) {
+       if (result == SCI_SUCCESS) {
                u32 status;
                u32 terminate_loop;
 
                /* Take the hardware out of reset */
-               SMU_SMUSRCR_WRITE(this_controller, 0x00000000);
+               SMU_SMUSRCR_WRITE(scic, 0x00000000);
 
                /*
                 * / @todo Provide meaningfull error code for hardware failure
@@ -3268,12 +2918,12 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(
 
                while (terminate_loop-- && (result != SCI_SUCCESS)) {
                        /* Loop until the hardware reports success */
-                       scic_cb_stall_execution(SCU_CONTEXT_RAM_INIT_STALL_TIME);
-                       status = SMU_SMUCSR_READ(this_controller);
+                       udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME);
+                       status = SMU_SMUCSR_READ(scic);
 
-                       if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED) {
+                       if ((status & SCU_RAM_INIT_COMPLETED) ==
+                                       SCU_RAM_INIT_COMPLETED)
                                result = SCI_SUCCESS;
-                       }
                }
        }
 
@@ -3286,39 +2936,42 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(
                /*
                 * Determine what are the actaul device capacities that the
                 * hardware will support */
-               device_context_capacity = SMU_DCC_READ(this_controller);
+               device_context_capacity = SMU_DCC_READ(scic);
 
-               max_supported_ports =
-                       smu_dcc_get_max_ports(device_context_capacity);
-               max_supported_devices =
-                       smu_dcc_get_max_remote_node_context(device_context_capacity);
-               max_supported_io_requests =
-                       smu_dcc_get_max_task_context(device_context_capacity);
+               max_supported_ports = smu_dcc_get_max_ports(device_context_capacity);
+               max_supported_devices = smu_dcc_get_max_remote_node_context(device_context_capacity);
+               max_supported_io_requests = smu_dcc_get_max_task_context(device_context_capacity);
 
-               /* Make all PEs that are unassigned match up with the logical ports */
+               /*
+                * Make all PEs that are unassigned match up with the
+                * logical ports
+                */
                for (index = 0; index < max_supported_ports; index++) {
-                       scu_register_write(
-                               this_controller,
-                               this_controller->scu_registers->peg0.ptsg.protocol_engine[index],
-                               index
-                               );
+                       struct scu_port_task_scheduler_group_registers *ptsg =
+                               &scic->scu_registers->peg0.ptsg;
+
+                       scu_register_write(scic,
+                                          ptsg->protocol_engine[index],
+                                          index);
                }
 
                /* Record the smaller of the two capacity values */
-               this_controller->logical_port_entries =
-                       min(max_supported_ports, this_controller->logical_port_entries);
+               scic->logical_port_entries =
+                       min(max_supported_ports, scic->logical_port_entries);
 
-               this_controller->task_context_entries =
-                       min(max_supported_io_requests, this_controller->task_context_entries);
+               scic->task_context_entries =
+                       min(max_supported_io_requests,
+                           scic->task_context_entries);
 
-               this_controller->remote_node_entries =
-                       min(max_supported_devices, this_controller->remote_node_entries);
+               scic->remote_node_entries =
+                       min(max_supported_devices, scic->remote_node_entries);
 
                /*
                 * Now that we have the correct hardware reported minimum values
                 * build the MDL for the controller.  Default to a performance
-                * configuration. */
-               scic_controller_set_mode(this_controller, SCI_MODE_SPEED);
+                * configuration.
+                */
+               scic_controller_set_mode(scic, SCI_MODE_SPEED);
        }
 
        /* Initialize hardware PCI Relaxed ordering in DMA engines */
@@ -3326,66 +2979,62 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(
                u32 dma_configuration;
 
                /* Configure the payload DMA */
-               dma_configuration = SCU_PDMACR_READ(this_controller);
-               dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
-               SCU_PDMACR_WRITE(this_controller, dma_configuration);
+               dma_configuration = SCU_PDMACR_READ(scic);
+               dma_configuration |=
+                       SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
+               SCU_PDMACR_WRITE(scic, dma_configuration);
 
                /* Configure the control DMA */
-               dma_configuration = SCU_CDMACR_READ(this_controller);
-               dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
-               SCU_CDMACR_WRITE(this_controller, dma_configuration);
+               dma_configuration = SCU_CDMACR_READ(scic);
+               dma_configuration |=
+                       SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);
+               SCU_CDMACR_WRITE(scic, dma_configuration);
        }
 
        /*
         * Initialize the PHYs before the PORTs because the PHY registers
-        * are accessed during the port initialization. */
+        * are accessed during the port initialization.
+        */
        if (result == SCI_SUCCESS) {
                /* Initialize the phys */
                for (index = 0;
                     (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS);
                     index++) {
                        result = scic_sds_phy_initialize(
-                               &this_controller->phy_table[index],
-                               &this_controller->scu_registers->peg0.pe[index].ll
-                               );
+                               &scic->phy_table[index],
+                               &scic->scu_registers->peg0.pe[index].tl,
+                               &scic->scu_registers->peg0.pe[index].ll);
                }
        }
 
        if (result == SCI_SUCCESS) {
                /* Initialize the logical ports */
                for (index = 0;
-                    (index < this_controller->logical_port_entries)
-                    && (result == SCI_SUCCESS);
+                    (index < scic->logical_port_entries) &&
+                    (result == SCI_SUCCESS);
                     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]
-                               );
+                               &scic->port_table[index],
+                               &scic->scu_registers->peg0.ptsg.port[index],
+                               &scic->scu_registers->peg0.ptsg.protocol_engine,
+                               &scic->scu_registers->peg0.viit[index]);
                }
        }
 
-       if (SCI_SUCCESS == result) {
+       if (result == SCI_SUCCESS)
                result = scic_sds_port_configuration_agent_initialize(
-                       this_controller,
-                       &this_controller->port_agent
-                       );
-       }
+                               scic,
+                               &scic->port_agent);
 
        /* Advance the controller state machine */
-       if (result == SCI_SUCCESS) {
+       if (result == SCI_SUCCESS)
                sci_base_state_machine_change_state(
-                       scic_sds_controller_get_base_state_machine(this_controller),
-                       SCI_BASE_CONTROLLER_STATE_INITIALIZED
-                       );
-       } else {
+                       scic_sds_controller_get_base_state_machine(scic),
+                       SCI_BASE_CONTROLLER_STATE_INITIALIZED);
+       else
                sci_base_state_machine_change_state(
-                       scic_sds_controller_get_base_state_machine(this_controller),
-                       SCI_BASE_CONTROLLER_STATE_FAILED
-                       );
-       }
+                       scic_sds_controller_get_base_state_machine(scic),
+                       SCI_BASE_CONTROLLER_STATE_FAILED);
 
        return result;
 }
@@ -3397,13 +3046,14 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(
 
 /**
  *
- * @controller: This is the struct sci_base_controller object which is cast into a
- *    struct scic_sds_controller object.
+ * @controller: This is the struct sci_base_controller object which is cast
+ * into a struct scic_sds_controller object.
  * @timeout: This is the allowed time for the controller object to reach the
  *    started state.
  *
- * This method is the struct scic_sds_controller start handler for the initialized
- * state. - Validate we have a good memory descriptor table - Initialze the
+ * This function is the struct scic_sds_controller start handler for the
+ * initialized state.
+ * - Validate we have a good memory descriptor table - Initialze the
  * physical memory before programming the hardware - Program the SCU hardware
  * with the physical memory addresses passed in the memory descriptor table. -
  * Initialzie the TCi pool - Initialize the RNi pool - Initialize the
@@ -3420,62 +3070,74 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler(
 {
        u16 index;
        enum sci_status result;
-       struct scic_sds_controller *this_controller;
+       struct scic_sds_controller *scic;
 
-       this_controller = (struct scic_sds_controller *)controller;
+       scic = (struct scic_sds_controller *)controller;
 
-       /* Make sure that the SCI User filled in the memory descriptor table correctly */
-       result = scic_sds_controller_validate_memory_descriptor_table(this_controller);
+       /*
+        * Make sure that the SCI User filled in the memory descriptor
+        * table correctly
+        */
+       result = scic_sds_controller_validate_memory_descriptor_table(scic);
 
        if (result == SCI_SUCCESS) {
-               /* The memory descriptor list looks good so program the hardware */
-               scic_sds_controller_ram_initialization(this_controller);
+               /*
+                * The memory descriptor list looks good so program the
+                * hardware
+                */
+               scic_sds_controller_ram_initialization(scic);
        }
 
-       if (SCI_SUCCESS == result) {
+       if (result == SCI_SUCCESS) {
                /* Build the TCi free pool */
-               sci_pool_initialize(this_controller->tci_pool);
-               for (index = 0; index < this_controller->task_context_entries; index++) {
-                       sci_pool_put(this_controller->tci_pool, index);
-               }
+               sci_pool_initialize(scic->tci_pool);
+               for (index = 0; index < scic->task_context_entries; index++)
+                       sci_pool_put(scic->tci_pool, index);
 
                /* Build the RNi free pool */
                scic_sds_remote_node_table_initialize(
-                       &this_controller->available_remote_nodes,
-                       this_controller->remote_node_entries
-                       );
+                               &scic->available_remote_nodes,
+                               scic->remote_node_entries);
        }
 
-       if (SCI_SUCCESS == result) {
+       if (result == SCI_SUCCESS) {
                /*
-                * Before anything else lets make sure we will not be interrupted
-                * by the hardware. */
-               scic_controller_disable_interrupts(this_controller);
+                * Before anything else lets make sure we will not be
+                * interrupted by the hardware.
+                */
+               scic_controller_disable_interrupts(scic);
 
                /* Enable the port task scheduler */
-               scic_sds_controller_enable_port_task_scheduler(this_controller);
+               scic_sds_controller_enable_port_task_scheduler(scic);
 
-               /* Assign all the task entries to this controller physical function */
-               scic_sds_controller_assign_task_entries(this_controller);
+               /* Assign all the task entries to scic physical function */
+               scic_sds_controller_assign_task_entries(scic);
 
                /* Now initialze the completion queue */
-               scic_sds_controller_initialize_completion_queue(this_controller);
+               scic_sds_controller_initialize_completion_queue(scic);
 
                /* Initialize the unsolicited frame queue for use */
-               scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
+               scic_sds_controller_initialize_unsolicited_frame_queue(scic);
+       }
+
+       /* Start all of the ports on this controller */
+       for (index = 0;
+            (index < scic->logical_port_entries) && (result == SCI_SUCCESS);
+            index++) {
+               struct scic_sds_port *sci_port = &scic->port_table[index];
+
+               result = sci_port->state_handlers->parent.start_handler(
+                               &sci_port->parent);
        }
 
-       if (SCI_SUCCESS == result) {
-               scic_sds_controller_start_next_phy(this_controller);
+       if (result == SCI_SUCCESS) {
+               scic_sds_controller_start_next_phy(scic);
 
-               scic_cb_timer_start(this_controller,
-                                   this_controller->timeout_timer,
-                                   timeout);
+               isci_timer_start(scic->timeout_timer, timeout);
 
                sci_base_state_machine_change_state(
-                       scic_sds_controller_get_base_state_machine(this_controller),
-                       SCI_BASE_CONTROLLER_STATE_STARTING
-                       );
+                       scic_sds_controller_get_base_state_machine(scic),
+                       SCI_BASE_CONTROLLER_STATE_STARTING);
        }
 
        return result;
@@ -3554,18 +3216,14 @@ static enum sci_status scic_sds_controller_ready_state_stop_handler(
        struct sci_base_controller *controller,
        u32 timeout)
 {
-       struct scic_sds_controller *this_controller;
-
-       this_controller = (struct scic_sds_controller *)controller;
+       struct scic_sds_controller *scic =
+               (struct scic_sds_controller *)controller;
 
-       scic_cb_timer_start(this_controller,
-                           this_controller->timeout_timer,
-                           timeout);
+       isci_timer_start(scic->timeout_timer, timeout);
 
        sci_base_state_machine_change_state(
-               scic_sds_controller_get_base_state_machine(this_controller),
-               SCI_BASE_CONTROLLER_STATE_STOPPING
-               );
+               scic_sds_controller_get_base_state_machine(scic),
+               SCI_BASE_CONTROLLER_STATE_STOPPING);
 
        return SCI_SUCCESS;
 }
@@ -3878,23 +3536,22 @@ static enum sci_status scic_sds_controller_stopping_state_complete_io_handler(
  *    struct scic_sds_controller object.
  * @remote_device: This is struct sci_base_remote_device which is cast to a
  *    struct scic_sds_remote_device object.
- * @io_request: This is the struct sci_base_request which is cast to a
- *    SCIC_SDS_IO_REQUEST object.
  *
  * This method is called when the struct scic_sds_controller is in a stopping state
- * and the complete task handler is called. - This function is not yet
- * implemented enum sci_status SCI_FAILURE
- */
-
-/*
- * *****************************************************************************
- * * STOPPED STATE HANDLERS
- * ***************************************************************************** */
-
-/*
- * *****************************************************************************
- * * FAILED STATE HANDLERS
- * ***************************************************************************** */
+ * and the remote device has stopped.
+ **/
+void scic_sds_controller_stopping_state_device_stopped_handler(
+       struct scic_sds_controller *controller,
+       struct scic_sds_remote_device *remote_device
+)
+{
+       if (!scic_sds_controller_has_remote_devices_stopping(controller)) {
+               sci_base_state_machine_change_state(
+                       &controller->parent.state_machine,
+                       SCI_BASE_CONTROLLER_STATE_STOPPED
+               );
+       }
+}
 
 const struct scic_sds_controller_state_handler scic_sds_controller_state_handler_table[] = {
        [SCI_BASE_CONTROLLER_STATE_INITIAL] = {
@@ -3904,6 +3561,7 @@ const struct scic_sds_controller_state_handler scic_sds_controller_state_handler
                .terminate_request = scic_sds_controller_default_request_handler,
        },
        [SCI_BASE_CONTROLLER_STATE_RESET] = {
+               .base.reset        = scic_sds_controller_general_reset_handler,
                .base.initialize   = scic_sds_controller_reset_state_initialize_handler,
                .base.start_io     = scic_sds_controller_default_start_operation_handler,
                .base.complete_io  = scic_sds_controller_default_request_handler,
@@ -3954,6 +3612,7 @@ const struct scic_sds_controller_state_handler scic_sds_controller_state_handler
                .base.complete_io  = scic_sds_controller_stopping_state_complete_io_handler,
                .base.continue_io  = scic_sds_controller_default_request_handler,
                .terminate_request = scic_sds_controller_default_request_handler,
+               .remote_device_stopped_handler = scic_sds_controller_stopping_state_device_stopped_handler,
        },
        [SCI_BASE_CONTROLLER_STATE_STOPPED] = {
                .base.reset        = scic_sds_controller_general_reset_handler,
@@ -4001,12 +3660,12 @@ static void scic_sds_controller_initial_state_enter(
  * from the SCI_BASE_CONTROLLER_STATE_STARTING. - This function stops the
  * controller starting timeout timer. none
  */
-static void scic_sds_controller_starting_state_exit(
+static inline void scic_sds_controller_starting_state_exit(
        struct sci_base_object *object)
 {
        struct scic_sds_controller *scic = (struct scic_sds_controller *)object;
 
-       scic_cb_timer_stop(scic, scic->timeout_timer);
+       isci_timer_stop(scic->timeout_timer);
 }
 
 /**
@@ -4074,21 +3733,20 @@ static void scic_sds_controller_stopping_state_enter(
 
 /**
  *
- * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller
- *    object.
+ * @object: This is the struct sci_base_object which is cast to a struct
+ * scic_sds_controller object.
  *
- * This method implements the actions taken by the struct scic_sds_controller on exit
- * from the SCI_BASE_CONTROLLER_STATE_STOPPING. - This function stops the
- * controller stopping timeout timer. none
+ * This funciton implements the actions taken by the struct scic_sds_controller
+ * on exit from the SCI_BASE_CONTROLLER_STATE_STOPPING. -
+ * This function stops the controller stopping timeout timer.
  */
-static void scic_sds_controller_stopping_state_exit(
+static inline void scic_sds_controller_stopping_state_exit(
        struct sci_base_object *object)
 {
-       struct scic_sds_controller *this_controller;
-
-       this_controller = (struct scic_sds_controller *)object;
+       struct scic_sds_controller *scic =
+               (struct scic_sds_controller *)object;
 
-       scic_cb_timer_stop(this_controller, this_controller->timeout_timer);
+       isci_timer_stop(scic->timeout_timer);
 }
 
 /**