aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Chudy <Tomasz.Chudy@intel.com>2011-02-25 05:25:09 -0500
committerDan Williams <dan.j.williams@intel.com>2011-07-03 06:55:28 -0400
commita8d4b9fe911c7d48f7a75c37eb1bfa3273547d97 (patch)
tree8b5fbdb2b6ea0e31dfcfc4c336b8bb5f4ba7d84a
parent7c40a8035815479c7c12ab0cdcea71e0f4c3a9c8 (diff)
isci: workaround port task scheduler starvation issue
There is a condition whereby TCs (task contexts) can jump to the head of the round robin queue causing indefinite starvation of pending tasks. Posting a TC to a suspended RNC (remote node context) causes the hardware to select that task first, but since the RNC is suspended the scheduler proceeds to the next task in the expected round robin fashion, restoring TC arbitration fairness. Signed-off-by: Tomasz Chudy <tomasz.chudy@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--drivers/scsi/isci/core/scic_port.h17
-rw-r--r--drivers/scsi/isci/core/scic_sds_controller.c22
-rw-r--r--drivers/scsi/isci/core/scic_sds_port.c334
-rw-r--r--drivers/scsi/isci/core/scic_sds_port.h9
-rw-r--r--drivers/scsi/isci/host.c7
5 files changed, 298 insertions, 91 deletions
diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h
index e55abb68ff9a..8222443c9fd7 100644
--- a/drivers/scsi/isci/core/scic_port.h
+++ b/drivers/scsi/isci/core/scic_port.h
@@ -147,23 +147,6 @@ enum sci_status scic_port_get_properties(
147 struct scic_sds_port *port, 147 struct scic_sds_port *port,
148 struct scic_port_properties *properties); 148 struct scic_port_properties *properties);
149 149
150
151
152/**
153 * scic_port_start() - This method will make the port ready for operation.
154 * Prior to calling the start method IO operation is not possible.
155 * @port: This parameter specifies the port to be started.
156 *
157 * Indicate if the port was successfully started. SCI_SUCCESS This value is
158 * returned if the port was successfully started. SCI_WARNING_ALREADY_IN_STATE
159 * This value is returned if the port is in the process of starting.
160 * SCI_FAILURE_INVALID_PORT This value is returned if the supplied port is not
161 * valid. SCI_FAILURE_INVALID_STATE This value is returned if a start operation
162 * can't be completed due to the state of port.
163 */
164enum sci_status scic_port_start(
165 struct scic_sds_port *port);
166
167/** 150/**
168 * scic_port_stop() - This method will make the port no longer ready for 151 * scic_port_stop() - This method will make the port no longer ready for
169 * operation. After invoking this method IO operation is not possible. 152 * operation. After invoking this method IO operation is not possible.
diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c
index d642ff7be6db..5e26df7fcb3a 100644
--- a/drivers/scsi/isci/core/scic_sds_controller.c
+++ b/drivers/scsi/isci/core/scic_sds_controller.c
@@ -796,7 +796,11 @@ enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)
796 enum sci_status status = SCI_SUCCESS; 796 enum sci_status status = SCI_SUCCESS;
797 797
798 for (index = 0; index < scic->logical_port_entries; index++) { 798 for (index = 0; index < scic->logical_port_entries; index++) {
799 port_status = scic_port_stop(&scic->port_table[index]); 799 struct scic_sds_port *sci_port = &scic->port_table[index];
800 SCI_BASE_PORT_HANDLER_T stop;
801
802 stop = sci_port->state_handlers->parent.stop_handler;
803 port_status = stop(&sci_port->parent);
800 804
801 if ((port_status != SCI_SUCCESS) && 805 if ((port_status != SCI_SUCCESS) &&
802 (port_status != SCI_FAILURE_INVALID_STATE)) { 806 (port_status != SCI_FAILURE_INVALID_STATE)) {
@@ -806,7 +810,7 @@ enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)
806 "%s: Controller stop operation failed to " 810 "%s: Controller stop operation failed to "
807 "stop port %d because of status %d.\n", 811 "stop port %d because of status %d.\n",
808 __func__, 812 __func__,
809 scic->port_table[index].logical_port_index, 813 sci_port->logical_port_index,
810 port_status); 814 port_status);
811 } 815 }
812 } 816 }
@@ -3003,7 +3007,7 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler(
3003 scic_sds_controller_ram_initialization(this_controller); 3007 scic_sds_controller_ram_initialization(this_controller);
3004 } 3008 }
3005 3009
3006 if (SCI_SUCCESS == result) { 3010 if (result == SCI_SUCCESS) {
3007 /* Build the TCi free pool */ 3011 /* Build the TCi free pool */
3008 sci_pool_initialize(this_controller->tci_pool); 3012 sci_pool_initialize(this_controller->tci_pool);
3009 for (index = 0; index < this_controller->task_context_entries; index++) { 3013 for (index = 0; index < this_controller->task_context_entries; index++) {
@@ -3017,7 +3021,7 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler(
3017 ); 3021 );
3018 } 3022 }
3019 3023
3020 if (SCI_SUCCESS == result) { 3024 if (result == SCI_SUCCESS) {
3021 /* 3025 /*
3022 * Before anything else lets make sure we will not be interrupted 3026 * Before anything else lets make sure we will not be interrupted
3023 * by the hardware. */ 3027 * by the hardware. */
@@ -3036,7 +3040,15 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler(
3036 scic_sds_controller_initialize_unsolicited_frame_queue(this_controller); 3040 scic_sds_controller_initialize_unsolicited_frame_queue(this_controller);
3037 } 3041 }
3038 3042
3039 if (SCI_SUCCESS == result) { 3043 /* Start all of the ports on this controller */
3044 for (index = 0; index < this_controller->logical_port_entries &&
3045 result == SCI_SUCCESS; index++) {
3046 struct scic_sds_port *sci_port = &this_controller->port_table[index];
3047
3048 result = sci_port->state_handlers->parent.start_handler(&sci_port->parent);
3049 }
3050
3051 if (result == SCI_SUCCESS) {
3040 scic_sds_controller_start_next_phy(this_controller); 3052 scic_sds_controller_start_next_phy(this_controller);
3041 3053
3042 isci_event_timer_start(this_controller, 3054 isci_event_timer_start(this_controller,
diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c
index d374c7ac0b71..2a193d30c55d 100644
--- a/drivers/scsi/isci/core/scic_sds_port.c
+++ b/drivers/scsi/isci/core/scic_sds_port.c
@@ -67,6 +67,7 @@
67#include "scic_sds_remote_node_context.h" 67#include "scic_sds_remote_node_context.h"
68#include "scic_sds_request.h" 68#include "scic_sds_request.h"
69#include "sci_environment.h" 69#include "sci_environment.h"
70#include "scic_sds_controller_registers.h"
70 71
71 72
72static void scic_sds_port_invalid_link_up( 73static void scic_sds_port_invalid_link_up(
@@ -78,6 +79,7 @@ static void scic_sds_port_timeout_handler(
78#define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS) 79#define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS)
79 80
80#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) 81#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000)
82#define SCU_DUMMY_INDEX (0xFFFF)
81 83
82void sci_base_port_construct( 84void sci_base_port_construct(
83 struct sci_base_port *base_port, 85 struct sci_base_port *base_port,
@@ -474,67 +476,131 @@ void scic_sds_port_get_attached_protocols(
474} 476}
475 477
476/** 478/**
477 * This method returns the amount of memory requred for a port object. 479 * scic_sds_port_construct_dummy_rnc() - create dummy rnc for si workaround
478 * 480 *
479 * u32 481 * @sci_port: logical port on which we need to create the remote node context
480 */ 482 * @rni: remote node index for this remote node context.
481
482/**
483 * This method returns the minimum number of timers required for all port
484 * objects.
485 * 483 *
486 * u32 484 * This routine will construct a dummy remote node context data structure
485 * This structure will be posted to the hardware to work around a scheduler
486 * error in the hardware.
487 */ 487 */
488void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u16 rni)
489{
490 union scu_remote_node_context *rnc;
488 491
489/** 492 rnc = &sci_port->owning_controller->remote_node_context_table[rni];
490 * This method returns the maximum number of timers required for all port 493
491 * objects. 494 memset(rnc, 0, sizeof(union scu_remote_node_context));
492 * 495
493 * u32 496 rnc->ssp.remote_sas_address_hi = 0;
494 */ 497 rnc->ssp.remote_sas_address_lo = 0;
498
499 rnc->ssp.remote_node_index = rni;
500 rnc->ssp.remote_node_port_width = 1;
501 rnc->ssp.logical_port_index = sci_port->physical_port_index;
502
503 rnc->ssp.nexus_loss_timer_enable = false;
504 rnc->ssp.check_bit = false;
505 rnc->ssp.is_valid = true;
506 rnc->ssp.is_remote_node_context = true;
507 rnc->ssp.function_number = 0;
508 rnc->ssp.arbitration_wait_time = 0;
509}
495 510
496/** 511/**
512 * scic_sds_port_construct_dummy_task() - create dummy task for si workaround
513 * @sci_port The logical port on which we need to create the
514 * remote node context.
515 * context.
516 * @tci The remote node index for this remote node context.
497 * 517 *
498 * @this_port: 518 * This routine will construct a dummy task context data structure. This
499 * @port_index: 519 * structure will be posted to the hardwre to work around a scheduler error
500 * 520 * in the hardware.
501 * 521 *
502 */ 522 */
503void scic_sds_port_construct( 523void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tci)
504 struct scic_sds_port *this_port, 524{
505 u8 port_index, 525 struct scu_task_context *task_context;
506 struct scic_sds_controller *owning_controller) 526
527 task_context = scic_sds_controller_get_task_context_buffer(sci_port->owning_controller, tci);
528
529 memset(task_context, 0, sizeof(struct scu_task_context));
530
531 task_context->abort = 0;
532 task_context->priority = 0;
533 task_context->initiator_request = 1;
534 task_context->connection_rate = 1;
535 task_context->protocol_engine_index = 0;
536 task_context->logical_port_index = sci_port->physical_port_index;
537 task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
538 task_context->task_index = scic_sds_io_tag_get_index(tci);
539 task_context->valid = SCU_TASK_CONTEXT_VALID;
540 task_context->context_type = SCU_TASK_CONTEXT_TYPE;
541
542 task_context->remote_node_index = sci_port->reserved_rni;
543 task_context->command_code = 0;
544
545 task_context->link_layer_control = 0;
546 task_context->do_not_dma_ssp_good_response = 1;
547 task_context->strict_ordering = 0;
548 task_context->control_frame = 0;
549 task_context->timeout_enable = 0;
550 task_context->block_guard_enable = 0;
551
552 task_context->address_modifier = 0;
553
554 task_context->task_phase = 0x01;
555}
556
557void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port)
558{
559 struct scic_sds_controller *scic = sci_port->owning_controller;
560
561 if (sci_port->reserved_tci != SCU_DUMMY_INDEX)
562 scic_controller_free_io_tag(scic, sci_port->reserved_tci);
563
564 if (sci_port->reserved_rni != SCU_DUMMY_INDEX)
565 scic_sds_remote_node_table_release_remote_node_index(&scic->available_remote_nodes,
566 1, sci_port->reserved_rni);
567
568 sci_port->reserved_rni = SCU_DUMMY_INDEX;
569 sci_port->reserved_tci = SCU_DUMMY_INDEX;
570}
571
572void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index,
573 struct scic_sds_controller *scic)
507{ 574{
508 u32 index; 575 u32 index;
509 576
510 sci_base_port_construct( 577 sci_base_port_construct(&sci_port->parent, scic_sds_port_state_table);
511 &this_port->parent,
512 scic_sds_port_state_table
513 );
514 578
515 sci_base_state_machine_construct( 579 sci_base_state_machine_construct(
516 scic_sds_port_get_ready_substate_machine(this_port), 580 scic_sds_port_get_ready_substate_machine(sci_port),
517 &this_port->parent.parent, 581 &sci_port->parent.parent,
518 scic_sds_port_ready_substate_table, 582 scic_sds_port_ready_substate_table,
519 SCIC_SDS_PORT_READY_SUBSTATE_WAITING 583 SCIC_SDS_PORT_READY_SUBSTATE_WAITING
520 ); 584 );
521 585
522 this_port->logical_port_index = SCIC_SDS_DUMMY_PORT; 586 sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT;
523 this_port->physical_port_index = port_index; 587 sci_port->physical_port_index = port_index;
524 this_port->active_phy_mask = 0; 588 sci_port->active_phy_mask = 0;
525 589
526 this_port->owning_controller = owning_controller; 590 sci_port->owning_controller = scic;
527 591
528 this_port->started_request_count = 0; 592 sci_port->started_request_count = 0;
529 this_port->assigned_device_count = 0; 593 sci_port->assigned_device_count = 0;
530 594
531 this_port->timer_handle = NULL; 595 sci_port->reserved_rni = SCU_DUMMY_INDEX;
596 sci_port->reserved_tci = SCU_DUMMY_INDEX;
532 597
533 this_port->port_task_scheduler_registers = NULL; 598 sci_port->timer_handle = NULL;
534 599
535 for (index = 0; index < SCI_MAX_PHYS; index++) { 600 sci_port->port_task_scheduler_registers = NULL;
536 this_port->phy_table[index] = NULL; 601
537 } 602 for (index = 0; index < SCI_MAX_PHYS; index++)
603 sci_port->phy_table[index] = NULL;
538} 604}
539 605
540/** 606/**
@@ -634,19 +700,11 @@ void scic_sds_port_general_link_up_handler(
634 } 700 }
635} 701}
636 702
637
638enum sci_status scic_port_start(struct scic_sds_port *port)
639{
640 return port->state_handlers->parent.start_handler(&port->parent);
641}
642
643
644enum sci_status scic_port_stop(struct scic_sds_port *port) 703enum sci_status scic_port_stop(struct scic_sds_port *port)
645{ 704{
646 return port->state_handlers->parent.stop_handler(&port->parent); 705 return port->state_handlers->parent.stop_handler(&port->parent);
647} 706}
648 707
649
650enum sci_status scic_port_get_properties( 708enum sci_status scic_port_get_properties(
651 struct scic_sds_port *port, 709 struct scic_sds_port *port,
652 struct scic_port_properties *prop) 710 struct scic_port_properties *prop)
@@ -1542,6 +1600,58 @@ static void scic_sds_port_suspend_port_task_scheduler(
1542} 1600}
1543 1601
1544/** 1602/**
1603 * scic_sds_port_post_dummy_request() - post dummy/workaround request
1604 * @sci_port: port to post task
1605 *
1606 * Prevent the hardware scheduler from posting new requests to the front
1607 * of the scheduler queue causing a starvation problem for currently
1608 * ongoing requests.
1609 *
1610 */
1611void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port)
1612{
1613 u32 command;
1614 struct scu_task_context *task_context;
1615 struct scic_sds_controller *scic = sci_port->owning_controller;
1616 u16 tci = sci_port->reserved_tci;
1617
1618 task_context = scic_sds_controller_get_task_context_buffer(scic, tci);
1619
1620 task_context->abort = 0;
1621
1622 command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
1623 sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT |
1624 tci;
1625
1626 scic_sds_controller_post_request(scic, command);
1627}
1628
1629/**
1630 * This routine will abort the dummy request. This will alow the hardware to
1631 * power down parts of the silicon to save power.
1632 *
1633 * @sci_port: The port on which the task must be aborted.
1634 *
1635 */
1636void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port)
1637{
1638 struct scic_sds_controller *scic = sci_port->owning_controller;
1639 u16 tci = sci_port->reserved_tci;
1640 struct scu_task_context *tc;
1641 u32 command;
1642
1643 tc = scic_sds_controller_get_task_context_buffer(scic, tci);
1644
1645 tc->abort = 1;
1646
1647 command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT |
1648 sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT |
1649 tci;
1650
1651 scic_sds_controller_post_request(scic, command);
1652}
1653
1654/**
1545 * 1655 *
1546 * @this_port: This is the struct scic_sds_port object to resume. 1656 * @this_port: This is the struct scic_sds_port object to resume.
1547 * 1657 *
@@ -1584,6 +1694,12 @@ static void scic_sds_port_ready_substate_waiting_enter(
1584 1694
1585 scic_sds_port_suspend_port_task_scheduler(this_port); 1695 scic_sds_port_suspend_port_task_scheduler(this_port);
1586 1696
1697 /* Kill the dummy task for this port if it has not yet posted
1698 * the hardware will treat this as a NOP and just return abort
1699 * complete.
1700 */
1701 scic_sds_port_abort_dummy_request(this_port);
1702
1587 this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; 1703 this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS;
1588 1704
1589 if (this_port->active_phy_mask != 0) { 1705 if (this_port->active_phy_mask != 0) {
@@ -1629,6 +1745,11 @@ static void scic_sds_port_ready_substate_operational_enter(
1629 scic_sds_port_update_viit_entry(this_port); 1745 scic_sds_port_update_viit_entry(this_port);
1630 1746
1631 scic_sds_port_resume_port_task_scheduler(this_port); 1747 scic_sds_port_resume_port_task_scheduler(this_port);
1748
1749 /* Post the dummy task for the port so the hardware can schedule
1750 * io correctly
1751 */
1752 scic_sds_port_post_dummy_request(this_port);
1632} 1753}
1633 1754
1634/** 1755/**
@@ -2062,6 +2183,7 @@ static enum sci_status scic_sds_port_general_complete_io_handler(
2062 * **************************************************************************** */ 2183 * **************************************************************************** */
2063 2184
2064/** 2185/**
2186 * scic_sds_port_stopped_state_start_handler() - stop a port from "started"
2065 * 2187 *
2066 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port 2188 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
2067 * object. 2189 * object.
@@ -2075,13 +2197,14 @@ static enum sci_status scic_sds_port_general_complete_io_handler(
2075 * start request is successful and the struct scic_sds_port object has transitioned to 2197 * start request is successful and the struct scic_sds_port object has transitioned to
2076 * the SCI_BASE_PORT_STATE_READY. 2198 * the SCI_BASE_PORT_STATE_READY.
2077 */ 2199 */
2078static enum sci_status scic_sds_port_stopped_state_start_handler( 2200static enum sci_status scic_sds_port_stopped_state_start_handler(struct sci_base_port *base_port)
2079 struct sci_base_port *port)
2080{ 2201{
2202 struct scic_sds_port *sci_port = container_of(base_port, typeof(*sci_port), parent);
2203 struct scic_sds_controller *scic = sci_port->owning_controller;
2204 enum sci_status status = SCI_SUCCESS;
2081 u32 phy_mask; 2205 u32 phy_mask;
2082 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
2083 2206
2084 if (this_port->assigned_device_count > 0) { 2207 if (sci_port->assigned_device_count > 0) {
2085 /* 2208 /*
2086 * / @todo This is a start failure operation because there are still 2209 * / @todo This is a start failure operation because there are still
2087 * / devices assigned to this port. There must be no devices 2210 * / devices assigned to this port. There must be no devices
@@ -2089,22 +2212,56 @@ static enum sci_status scic_sds_port_stopped_state_start_handler(
2089 return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; 2212 return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
2090 } 2213 }
2091 2214
2092 phy_mask = scic_sds_port_get_phys(this_port); 2215 sci_port->timer_handle = isci_event_timer_create(scic,
2216 scic_sds_port_timeout_handler,
2217 sci_port);
2093 2218
2094 /* 2219 if (!sci_port->timer_handle)
2095 * There are one or more phys assigned to this port. Make sure 2220 return SCI_FAILURE_INSUFFICIENT_RESOURCES;
2096 * the port's phy mask is in fact legal and supported by the
2097 * silicon. */
2098 if (scic_sds_port_is_phy_mask_valid(this_port, phy_mask) == true) {
2099 sci_base_state_machine_change_state(
2100 scic_sds_port_get_base_state_machine(this_port),
2101 SCI_BASE_PORT_STATE_READY
2102 );
2103 2221
2104 return SCI_SUCCESS; 2222 if (sci_port->reserved_rni == SCU_DUMMY_INDEX) {
2223 u16 rni = scic_sds_remote_node_table_allocate_remote_node(&scic->available_remote_nodes, 1);
2224
2225 if (rni != SCU_DUMMY_INDEX)
2226 scic_sds_port_construct_dummy_rnc(sci_port, rni);
2227 else
2228 status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
2229 sci_port->reserved_rni = rni;
2230 }
2231
2232 if (sci_port->reserved_tci == SCU_DUMMY_INDEX) {
2233 /* Allocate a TCI and remove the sequence nibble */
2234 u16 tci = scic_controller_allocate_io_tag(scic);
2235
2236 if (tci != SCU_DUMMY_INDEX)
2237 scic_sds_port_construct_dummy_task(sci_port, tci);
2238 else
2239 status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
2240 sci_port->reserved_tci = tci;
2241 }
2242
2243 if (status == SCI_SUCCESS) {
2244 phy_mask = scic_sds_port_get_phys(sci_port);
2245
2246 /*
2247 * There are one or more phys assigned to this port. Make sure
2248 * the port's phy mask is in fact legal and supported by the
2249 * silicon.
2250 */
2251 if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) {
2252 sci_base_state_machine_change_state(
2253 scic_sds_port_get_base_state_machine(sci_port),
2254 SCI_BASE_PORT_STATE_READY);
2255
2256 return SCI_SUCCESS;
2257 } else
2258 status = SCI_FAILURE;
2105 } 2259 }
2106 2260
2107 return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; 2261 if (status != SCI_SUCCESS)
2262 scic_sds_port_destroy_dummy_resources(sci_port);
2263
2264 return status;
2108} 2265}
2109 2266
2110/** 2267/**
@@ -2467,6 +2624,52 @@ static void scic_sds_port_disable_port_task_scheduler(
2467 scu_port_task_scheduler_write(this_port, control, pts_control_value); 2624 scu_port_task_scheduler_write(this_port, control, pts_control_value);
2468} 2625}
2469 2626
2627void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port)
2628{
2629 struct scic_sds_controller *scic = sci_port->owning_controller;
2630 u8 phys_index = sci_port->physical_port_index;
2631 union scu_remote_node_context *rnc;
2632 u16 rni = sci_port->reserved_rni;
2633 u32 command;
2634
2635 rnc = &scic->remote_node_context_table[rni];
2636 rnc->ssp.is_valid = true;
2637
2638 command = SCU_CONTEXT_COMMAND_POST_RNC_32 |
2639 phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
2640
2641 scic_sds_controller_post_request(scic, command);
2642
2643 /* ensure hardware has seen the post rnc command and give it
2644 * ample time to act before sending the suspend
2645 */
2646 SMU_ISR_READ(scic); /* flush */
2647 udelay(10);
2648
2649 command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX |
2650 phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
2651
2652 scic_sds_controller_post_request(scic, command);
2653}
2654
2655void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port)
2656{
2657 struct scic_sds_controller *scic = sci_port->owning_controller;
2658 u8 phys_index = sci_port->physical_port_index;
2659 union scu_remote_node_context *rnc;
2660 u16 rni = sci_port->reserved_rni;
2661 u32 command;
2662
2663 rnc = &scic->remote_node_context_table[rni];
2664
2665 rnc->ssp.is_valid = false;
2666
2667 command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE |
2668 phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
2669
2670 scic_sds_controller_post_request(scic, command);
2671}
2672
2470/* 2673/*
2471 * ****************************************************************************** 2674 * ******************************************************************************
2472 * * PORT STATE METHODS 2675 * * PORT STATE METHODS
@@ -2562,6 +2765,9 @@ static void scic_sds_port_ready_state_enter(
2562 ); 2765 );
2563 } 2766 }
2564 2767
2768 /* Post and suspend the dummy remote node context for this port. */
2769 scic_sds_port_post_dummy_remote_node(this_port);
2770
2565 /* Start the ready substate machine */ 2771 /* Start the ready substate machine */
2566 sci_base_state_machine_start( 2772 sci_base_state_machine_start(
2567 scic_sds_port_get_ready_substate_machine(this_port) 2773 scic_sds_port_get_ready_substate_machine(this_port)
@@ -2583,6 +2789,8 @@ static void scic_sds_port_ready_state_exit(
2583 this_port = (struct scic_sds_port *)object; 2789 this_port = (struct scic_sds_port *)object;
2584 2790
2585 sci_base_state_machine_stop(&this_port->ready_substate_machine); 2791 sci_base_state_machine_stop(&this_port->ready_substate_machine);
2792
2793 scic_sds_port_invalidate_dummy_remote_node(this_port);
2586} 2794}
2587 2795
2588/** 2796/**
@@ -2663,6 +2871,8 @@ static void scic_sds_port_stopping_state_exit(
2663 scic_sds_port_get_controller(this_port), 2871 scic_sds_port_get_controller(this_port),
2664 this_port->timer_handle 2872 this_port->timer_handle
2665 ); 2873 );
2874
2875 scic_sds_port_destroy_dummy_resources(this_port);
2666} 2876}
2667 2877
2668/** 2878/**
diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h
index 3eb80cb2ea47..c98caefa7cf2 100644
--- a/drivers/scsi/isci/core/scic_sds_port.h
+++ b/drivers/scsi/isci/core/scic_sds_port.h
@@ -73,6 +73,12 @@
73#define SCIC_SDS_DUMMY_PORT 0xFF 73#define SCIC_SDS_DUMMY_PORT 0xFF
74 74
75/** 75/**
76 * This constant defines the value utilized by SCI Components to indicate
77 * an invalid handle.
78 */
79#define SCI_INVALID_HANDLE 0x0
80
81/**
76 * enum SCIC_SDS_PORT_READY_SUBSTATES - 82 * enum SCIC_SDS_PORT_READY_SUBSTATES -
77 * 83 *
78 * This enumeration depicts all of the states for the core port ready substate 84 * This enumeration depicts all of the states for the core port ready substate
@@ -134,6 +140,9 @@ struct scic_sds_port {
134 */ 140 */
135 u8 active_phy_mask; 141 u8 active_phy_mask;
136 142
143 u16 reserved_rni;
144 u16 reserved_tci;
145
137 /** 146 /**
138 * This field contains the count of the io requests started on this port 147 * This field contains the count of the io requests started on this port
139 * object. It is used to control controller shutdown. 148 * object. It is used to control controller shutdown.
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index 1bc91f2b4f93..40614e9ab41b 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -381,7 +381,6 @@ int isci_host_init(struct isci_host *isci_host)
381 int index = 0; 381 int index = 0;
382 enum sci_status status; 382 enum sci_status status;
383 struct scic_sds_controller *controller; 383 struct scic_sds_controller *controller;
384 struct scic_sds_port *scic_port;
385 union scic_oem_parameters scic_oem_params; 384 union scic_oem_parameters scic_oem_params;
386 union scic_user_parameters scic_user_params; 385 union scic_user_parameters scic_user_params;
387 386
@@ -517,11 +516,5 @@ int isci_host_init(struct isci_host *isci_host)
517 for (index = 0; index < SCI_MAX_PHYS; index++) 516 for (index = 0; index < SCI_MAX_PHYS; index++)
518 isci_phy_init(&isci_host->phys[index], isci_host, index); 517 isci_phy_init(&isci_host->phys[index], isci_host, index);
519 518
520 /* Start the ports */
521 for (index = 0; index < SCI_MAX_PORTS; index++) {
522 scic_controller_get_port_handle(controller, index, &scic_port);
523 scic_port_start(scic_port);
524 }
525
526 return 0; 519 return 0;
527} 520}