isci: fixup SAS iaf protocols data structure
[deliverable/linux.git] / drivers / scsi / isci / core / scic_sds_port.c
CommitLineData
6f231dda
DW
1/*
2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * BSD LICENSE
25 *
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
38 * distribution.
39 * * Neither the name of Intel Corporation nor the names of its
40 * contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 */
55
d7b90fc3 56#include "sas.h"
6f231dda 57#include "intel_sas.h"
6f231dda
DW
58#include "scic_controller.h"
59#include "scic_phy.h"
60#include "scic_port.h"
61#include "scic_sds_controller.h"
62#include "scic_sds_phy.h"
6f231dda 63#include "scic_sds_port.h"
88f3b62a
DW
64#include "remote_device.h"
65#include "remote_node_context.h"
6f231dda 66#include "scic_sds_request.h"
6f231dda 67#include "sci_environment.h"
bc99aa47 68#include "scu_registers.h"
6f231dda 69
6f231dda
DW
70#define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS)
71#define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS)
72
73#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000)
a8d4b9fe 74#define SCU_DUMMY_INDEX (0xFFFF)
6f231dda 75
6f231dda
DW
76
77/**
78 *
e2023b87 79 * @sci_port: This is the port object to which the phy is being assigned.
6f231dda
DW
80 * @phy_index: This is the phy index that is being assigned to the port.
81 *
82 * This method will return a true value if the specified phy can be assigned to
83 * this port The following is a list of phys for each port that are allowed: -
84 * Port 0 - 3 2 1 0 - Port 1 - 1 - Port 2 - 3 2 - Port 3 - 3 This method
85 * doesn't preclude all configurations. It merely ensures that a phy is part
86 * of the allowable set of phy identifiers for that port. For example, one
87 * could assign phy 3 to port 0 and no other phys. Please refer to
88 * scic_sds_port_is_phy_mask_valid() for information regarding whether the
89 * phy_mask for a port can be supported. bool true if this is a valid phy
90 * assignment for the port false if this is not a valid phy assignment for the
91 * port
92 */
93bool scic_sds_port_is_valid_phy_assignment(
e2023b87 94 struct scic_sds_port *sci_port,
6f231dda
DW
95 u32 phy_index)
96{
97 /* Initialize to invalid value. */
98 u32 existing_phy_index = SCI_MAX_PHYS;
99 u32 index;
100
e2023b87 101 if ((sci_port->physical_port_index == 1) && (phy_index != 1)) {
6f231dda
DW
102 return false;
103 }
104
e2023b87 105 if (sci_port->physical_port_index == 3 && phy_index != 3) {
6f231dda
DW
106 return false;
107 }
108
109 if (
e2023b87 110 (sci_port->physical_port_index == 2)
6f231dda
DW
111 && ((phy_index == 0) || (phy_index == 1))
112 ) {
113 return false;
114 }
115
116 for (index = 0; index < SCI_MAX_PHYS; index++) {
e2023b87 117 if ((sci_port->phy_table[index] != NULL)
6f231dda
DW
118 && (index != phy_index)) {
119 existing_phy_index = index;
120 }
121 }
122
123 /*
124 * Ensure that all of the phys in the port are capable of
125 * operating at the same maximum link rate. */
126 if (
127 (existing_phy_index < SCI_MAX_PHYS)
e2023b87 128 && (sci_port->owning_controller->user_parameters.sds1.phys[
6f231dda 129 phy_index].max_speed_generation !=
e2023b87 130 sci_port->owning_controller->user_parameters.sds1.phys[
6f231dda
DW
131 existing_phy_index].max_speed_generation)
132 )
133 return false;
134
135 return true;
136}
137
138/**
139 * This method requests a list (mask) of the phys contained in the supplied SAS
140 * port.
e2023b87 141 * @sci_port: a handle corresponding to the SAS port for which to return the
6f231dda
DW
142 * phy mask.
143 *
144 * Return a bit mask indicating which phys are a part of this port. Each bit
145 * corresponds to a phy identifier (e.g. bit 0 = phy id 0).
146 */
e2023b87 147static u32 scic_sds_port_get_phys(struct scic_sds_port *sci_port)
6f231dda
DW
148{
149 u32 index;
150 u32 mask;
151
152 mask = 0;
153
154 for (index = 0; index < SCI_MAX_PHYS; index++) {
e2023b87 155 if (sci_port->phy_table[index] != NULL) {
6f231dda
DW
156 mask |= (1 << index);
157 }
158 }
159
160 return mask;
161}
162
163/**
164 *
e2023b87 165 * @sci_port: This is the port object for which to determine if the phy mask
6f231dda
DW
166 * can be supported.
167 *
168 * This method will return a true value if the port's phy mask can be supported
169 * by the SCU. The following is a list of valid PHY mask configurations for
170 * each port: - Port 0 - [[3 2] 1] 0 - Port 1 - [1] - Port 2 - [[3] 2]
171 * - Port 3 - [3] This method returns a boolean indication specifying if the
172 * phy mask can be supported. true if this is a valid phy assignment for the
173 * port false if this is not a valid phy assignment for the port
174 */
35173d57 175static bool scic_sds_port_is_phy_mask_valid(
e2023b87 176 struct scic_sds_port *sci_port,
6f231dda
DW
177 u32 phy_mask)
178{
e2023b87 179 if (sci_port->physical_port_index == 0) {
6f231dda
DW
180 if (((phy_mask & 0x0F) == 0x0F)
181 || ((phy_mask & 0x03) == 0x03)
182 || ((phy_mask & 0x01) == 0x01)
183 || (phy_mask == 0))
184 return true;
e2023b87 185 } else if (sci_port->physical_port_index == 1) {
6f231dda
DW
186 if (((phy_mask & 0x02) == 0x02)
187 || (phy_mask == 0))
188 return true;
e2023b87 189 } else if (sci_port->physical_port_index == 2) {
6f231dda
DW
190 if (((phy_mask & 0x0C) == 0x0C)
191 || ((phy_mask & 0x04) == 0x04)
192 || (phy_mask == 0))
193 return true;
e2023b87 194 } else if (sci_port->physical_port_index == 3) {
6f231dda
DW
195 if (((phy_mask & 0x08) == 0x08)
196 || (phy_mask == 0))
197 return true;
198 }
199
200 return false;
201}
202
203/**
204 *
e2023b87 205 * @sci_port: This parameter specifies the port from which to return a
6f231dda
DW
206 * connected phy.
207 *
208 * This method retrieves a currently active (i.e. connected) phy contained in
209 * the port. Currently, the lowest order phy that is connected is returned.
210 * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is
211 * returned if there are no currently active (i.e. connected to a remote end
212 * point) phys contained in the port. All other values specify a struct scic_sds_phy
213 * object that is active in the port.
214 */
215static struct scic_sds_phy *scic_sds_port_get_a_connected_phy(
e2023b87 216 struct scic_sds_port *sci_port
6f231dda
DW
217 ) {
218 u32 index;
219 struct scic_sds_phy *phy;
220
221 for (index = 0; index < SCI_MAX_PHYS; index++) {
222 /*
223 * Ensure that the phy is both part of the port and currently
224 * connected to the remote end-point. */
e2023b87 225 phy = sci_port->phy_table[index];
6f231dda
DW
226 if (
227 (phy != NULL)
e2023b87 228 && scic_sds_port_active_phy(sci_port, phy)
6f231dda
DW
229 ) {
230 return phy;
231 }
232 }
233
234 return NULL;
235}
236
237/**
238 * scic_sds_port_set_phy() -
239 * @out]: port The port object to which the phy assignement is being made.
240 * @out]: phy The phy which is being assigned to the port.
241 *
242 * This method attempts to make the assignment of the phy to the port. If
243 * successful the phy is assigned to the ports phy table. bool true if the phy
244 * assignment can be made. false if the phy assignement can not be made. This
245 * is a functional test that only fails if the phy is currently assigned to a
246 * different port.
247 */
35173d57 248static enum sci_status scic_sds_port_set_phy(
6f231dda
DW
249 struct scic_sds_port *port,
250 struct scic_sds_phy *phy)
251{
252 /*
253 * Check to see if we can add this phy to a port
254 * that means that the phy is not part of a port and that the port does
255 * not already have a phy assinged to the phy index. */
256 if (
a7e536c7
EN
257 (port->phy_table[phy->phy_index] == NULL)
258 && (scic_sds_phy_get_port(phy) == NULL)
6f231dda
DW
259 && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)
260 ) {
261 /*
262 * Phy is being added in the stopped state so we are in MPC mode
263 * make logical port index = physical port index */
264 port->logical_port_index = port->physical_port_index;
265 port->phy_table[phy->phy_index] = phy;
266 scic_sds_phy_set_port(phy, port);
267
268 return SCI_SUCCESS;
269 }
270
271 return SCI_FAILURE;
272}
273
274/**
275 * scic_sds_port_clear_phy() -
276 * @out]: port The port from which the phy is being cleared.
277 * @out]: phy The phy being cleared from the port.
278 *
279 * This method will clear the phy assigned to this port. This method fails if
280 * this phy is not currently assinged to this port. bool true if the phy is
281 * removed from the port. false if this phy is not assined to this port.
282 */
35173d57 283static enum sci_status scic_sds_port_clear_phy(
6f231dda
DW
284 struct scic_sds_port *port,
285 struct scic_sds_phy *phy)
286{
287 /* Make sure that this phy is part of this port */
288 if (
289 (port->phy_table[phy->phy_index] == phy)
290 && (scic_sds_phy_get_port(phy) == port)
291 ) {
292 /* Yep it is assigned to this port so remove it */
293 scic_sds_phy_set_port(
294 phy,
295 &scic_sds_port_get_controller(port)->port_table[SCI_MAX_PORTS]
296 );
297
a7e536c7 298 port->phy_table[phy->phy_index] = NULL;
6f231dda
DW
299
300 return SCI_SUCCESS;
301 }
302
303 return SCI_FAILURE;
304}
305
306/**
307 * scic_sds_port_add_phy() -
e2023b87
DJ
308 * @sci_port: This parameter specifies the port in which the phy will be added.
309 * @sci_phy: This parameter is the phy which is to be added to the port.
6f231dda
DW
310 *
311 * This method will add a PHY to the selected port. This method returns an
312 * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other status
313 * is failre to add the phy to the port.
314 */
315enum sci_status scic_sds_port_add_phy(
e2023b87
DJ
316 struct scic_sds_port *sci_port,
317 struct scic_sds_phy *sci_phy)
6f231dda 318{
e2023b87
DJ
319 return sci_port->state_handlers->add_phy_handler(
320 sci_port, sci_phy);
6f231dda
DW
321}
322
323
324/**
325 * scic_sds_port_remove_phy() -
e2023b87
DJ
326 * @sci_port: This parameter specifies the port in which the phy will be added.
327 * @sci_phy: This parameter is the phy which is to be added to the port.
6f231dda
DW
328 *
329 * This method will remove the PHY from the selected PORT. This method returns
330 * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any other
331 * status is failre to add the phy to the port.
332 */
333enum sci_status scic_sds_port_remove_phy(
e2023b87
DJ
334 struct scic_sds_port *sci_port,
335 struct scic_sds_phy *sci_phy)
6f231dda 336{
e2023b87
DJ
337 return sci_port->state_handlers->remove_phy_handler(
338 sci_port, sci_phy);
6f231dda
DW
339}
340
341/**
342 * This method requests the SAS address for the supplied SAS port from the SCI
343 * implementation.
e2023b87 344 * @sci_port: a handle corresponding to the SAS port for which to return the
6f231dda
DW
345 * SAS address.
346 * @sas_address: This parameter specifies a pointer to a SAS address structure
347 * into which the core will copy the SAS address for the port.
348 *
349 */
350void scic_sds_port_get_sas_address(
e2023b87 351 struct scic_sds_port *sci_port,
6f231dda
DW
352 struct sci_sas_address *sas_address)
353{
354 u32 index;
355
356 sas_address->high = 0;
357 sas_address->low = 0;
358
359 for (index = 0; index < SCI_MAX_PHYS; index++) {
e2023b87
DJ
360 if (sci_port->phy_table[index] != NULL) {
361 scic_sds_phy_get_sas_address(sci_port->phy_table[index], sas_address);
6f231dda
DW
362 }
363 }
364}
365
d7b90fc3
DJ
366/*
367 * This function will indicate which protocols are supported by this port.
e2023b87 368 * @sci_port: a handle corresponding to the SAS port for which to return the
6f231dda 369 * supported protocols.
d7b90fc3
DJ
370 * @protocols: This parameter specifies a pointer to a data structure
371 * which the core will copy the protocol values for the port from the
372 * transmit_identification register.
6f231dda 373 */
d7b90fc3
DJ
374static void
375scic_sds_port_get_protocols(struct scic_sds_port *sci_port,
376 struct scic_phy_proto *protocols)
6f231dda
DW
377{
378 u8 index;
379
d7b90fc3 380 protocols->all = 0;
6f231dda
DW
381
382 for (index = 0; index < SCI_MAX_PHYS; index++) {
e2023b87 383 if (sci_port->phy_table[index] != NULL) {
d7b90fc3
DJ
384 scic_sds_phy_get_protocols(sci_port->phy_table[index],
385 protocols);
6f231dda
DW
386 }
387 }
388}
389
d7b90fc3
DJ
390/*
391 * This function requests the SAS address for the device directly attached to
6f231dda 392 * this SAS port.
e2023b87 393 * @sci_port: a handle corresponding to the SAS port for which to return the
6f231dda
DW
394 * SAS address.
395 * @sas_address: This parameter specifies a pointer to a SAS address structure
396 * into which the core will copy the SAS address for the device directly
397 * attached to the port.
398 *
399 */
400void scic_sds_port_get_attached_sas_address(
e2023b87 401 struct scic_sds_port *sci_port,
6f231dda
DW
402 struct sci_sas_address *sas_address)
403{
d7b90fc3 404 struct scic_sds_phy *sci_phy;
6f231dda
DW
405
406 /*
407 * Ensure that the phy is both part of the port and currently
d7b90fc3
DJ
408 * connected to the remote end-point.
409 */
410 sci_phy = scic_sds_port_get_a_connected_phy(sci_port);
411 if (sci_phy) {
412 if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) {
413 scic_sds_phy_get_attached_sas_address(sci_phy,
414 sas_address);
6f231dda 415 } else {
d7b90fc3
DJ
416 scic_sds_phy_get_sas_address(sci_phy, sas_address);
417 sas_address->low += sci_phy->phy_index;
6f231dda
DW
418 }
419 } else {
420 sas_address->high = 0;
421 sas_address->low = 0;
422 }
423}
424
6f231dda 425/**
a8d4b9fe 426 * scic_sds_port_construct_dummy_rnc() - create dummy rnc for si workaround
6f231dda 427 *
a8d4b9fe
TC
428 * @sci_port: logical port on which we need to create the remote node context
429 * @rni: remote node index for this remote node context.
6f231dda 430 *
a8d4b9fe
TC
431 * This routine will construct a dummy remote node context data structure
432 * This structure will be posted to the hardware to work around a scheduler
433 * error in the hardware.
6f231dda 434 */
35173d57 435static void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u16 rni)
a8d4b9fe
TC
436{
437 union scu_remote_node_context *rnc;
6f231dda 438
a8d4b9fe
TC
439 rnc = &sci_port->owning_controller->remote_node_context_table[rni];
440
441 memset(rnc, 0, sizeof(union scu_remote_node_context));
442
443 rnc->ssp.remote_sas_address_hi = 0;
444 rnc->ssp.remote_sas_address_lo = 0;
445
446 rnc->ssp.remote_node_index = rni;
447 rnc->ssp.remote_node_port_width = 1;
448 rnc->ssp.logical_port_index = sci_port->physical_port_index;
449
450 rnc->ssp.nexus_loss_timer_enable = false;
451 rnc->ssp.check_bit = false;
452 rnc->ssp.is_valid = true;
453 rnc->ssp.is_remote_node_context = true;
454 rnc->ssp.function_number = 0;
455 rnc->ssp.arbitration_wait_time = 0;
456}
6f231dda
DW
457
458/**
a8d4b9fe
TC
459 * scic_sds_port_construct_dummy_task() - create dummy task for si workaround
460 * @sci_port The logical port on which we need to create the
461 * remote node context.
462 * context.
463 * @tci The remote node index for this remote node context.
6f231dda 464 *
a8d4b9fe
TC
465 * This routine will construct a dummy task context data structure. This
466 * structure will be posted to the hardwre to work around a scheduler error
467 * in the hardware.
6f231dda
DW
468 *
469 */
35173d57 470static void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tci)
a8d4b9fe
TC
471{
472 struct scu_task_context *task_context;
473
474 task_context = scic_sds_controller_get_task_context_buffer(sci_port->owning_controller, tci);
475
476 memset(task_context, 0, sizeof(struct scu_task_context));
477
478 task_context->abort = 0;
479 task_context->priority = 0;
480 task_context->initiator_request = 1;
481 task_context->connection_rate = 1;
482 task_context->protocol_engine_index = 0;
483 task_context->logical_port_index = sci_port->physical_port_index;
484 task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
485 task_context->task_index = scic_sds_io_tag_get_index(tci);
486 task_context->valid = SCU_TASK_CONTEXT_VALID;
487 task_context->context_type = SCU_TASK_CONTEXT_TYPE;
488
489 task_context->remote_node_index = sci_port->reserved_rni;
490 task_context->command_code = 0;
491
492 task_context->link_layer_control = 0;
493 task_context->do_not_dma_ssp_good_response = 1;
494 task_context->strict_ordering = 0;
495 task_context->control_frame = 0;
496 task_context->timeout_enable = 0;
497 task_context->block_guard_enable = 0;
498
499 task_context->address_modifier = 0;
500
501 task_context->task_phase = 0x01;
502}
503
35173d57 504static void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port)
a8d4b9fe
TC
505{
506 struct scic_sds_controller *scic = sci_port->owning_controller;
507
508 if (sci_port->reserved_tci != SCU_DUMMY_INDEX)
509 scic_controller_free_io_tag(scic, sci_port->reserved_tci);
510
511 if (sci_port->reserved_rni != SCU_DUMMY_INDEX)
512 scic_sds_remote_node_table_release_remote_node_index(&scic->available_remote_nodes,
513 1, sci_port->reserved_rni);
514
515 sci_port->reserved_rni = SCU_DUMMY_INDEX;
516 sci_port->reserved_tci = SCU_DUMMY_INDEX;
517}
518
6f231dda
DW
519/**
520 * This method performs initialization of the supplied port. Initialization
521 * includes: - state machine initialization - member variable initialization
522 * - configuring the phy_mask
e2023b87 523 * @sci_port:
6f231dda
DW
524 * @transport_layer_registers:
525 * @port_task_scheduler_registers:
526 * @port_configuration_regsiter:
527 *
528 * enum sci_status SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is returned
529 * if the phy being added to the port
530 */
531enum sci_status scic_sds_port_initialize(
e2023b87 532 struct scic_sds_port *sci_port,
24621466
HD
533 void __iomem *port_task_scheduler_registers,
534 void __iomem *port_configuration_regsiter,
535 void __iomem *viit_registers)
6f231dda 536{
e2023b87
DJ
537 sci_port->port_task_scheduler_registers = port_task_scheduler_registers;
538 sci_port->port_pe_configuration_register = port_configuration_regsiter;
539 sci_port->viit_registers = viit_registers;
6f231dda 540
6f231dda
DW
541 return SCI_SUCCESS;
542}
543
544/**
35173d57
DW
545 * scic_port_get_properties() - This method simply returns the properties
546 * regarding the port, such as: physical index, protocols, sas address, etc.
547 * @port: this parameter specifies the port for which to retrieve the physical
548 * index.
549 * @properties: This parameter specifies the properties structure into which to
550 * copy the requested information.
6f231dda 551 *
35173d57
DW
552 * Indicate if the user specified a valid port. SCI_SUCCESS This value is
553 * returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This
554 * value is returned if the specified port is not valid. When this value is
555 * returned, no data is copied to the properties output parameter.
6f231dda 556 */
6f231dda
DW
557enum sci_status scic_port_get_properties(
558 struct scic_sds_port *port,
559 struct scic_port_properties *prop)
560{
a7e536c7 561 if ((port == NULL) ||
6f231dda
DW
562 (port->logical_port_index == SCIC_SDS_DUMMY_PORT))
563 return SCI_FAILURE_INVALID_PORT;
564
565 prop->index = port->logical_port_index;
566 prop->phy_mask = scic_sds_port_get_phys(port);
567 scic_sds_port_get_sas_address(port, &prop->local.sas_address);
568 scic_sds_port_get_protocols(port, &prop->local.protocols);
569 scic_sds_port_get_attached_sas_address(port, &prop->remote.sas_address);
6f231dda
DW
570
571 return SCI_SUCCESS;
572}
573
35173d57 574/**
de728b7d 575 * scic_port_hard_reset() - perform port hard reset
35173d57
DW
576 * @port: a handle corresponding to the SAS port to be hard reset.
577 * @reset_timeout: This parameter specifies the number of milliseconds in which
578 * the port reset operation should complete.
579 *
de728b7d 580 * The SCI User callback in scic_user_callbacks_t will only be called once for
35173d57
DW
581 * each phy in the SAS Port at completion of the hard reset sequence. Return a
582 * status indicating whether the hard reset started successfully. SCI_SUCCESS
583 * This value is returned if the hard reset operation started successfully.
584 */
6f231dda
DW
585enum sci_status scic_port_hard_reset(
586 struct scic_sds_port *port,
587 u32 reset_timeout)
588{
41e2b905
MT
589 return port->state_handlers->reset_handler(
590 port, reset_timeout);
6f231dda
DW
591}
592
593/**
6f231dda 594 * This method assigns the direct attached device ID for this port.
24621466 595 *
e2023b87 596 * @param[in] sci_port The port for which the direct attached device id is to
24621466
HD
597 * be assigned.
598 * @param[in] device_id The direct attached device ID to assign to the port.
599 * This will be the RNi for the device
6f231dda 600 */
24621466 601void scic_sds_port_setup_transports(
e2023b87 602 struct scic_sds_port *sci_port,
6f231dda
DW
603 u32 device_id)
604{
24621466 605 u8 index;
6f231dda 606
24621466 607 for (index = 0; index < SCI_MAX_PHYS; index++) {
e2023b87
DJ
608 if (sci_port->active_phy_mask & (1 << index))
609 scic_sds_phy_setup_transport(sci_port->phy_table[index], device_id);
24621466 610 }
6f231dda
DW
611}
612
6f231dda
DW
613/**
614 *
e2023b87
DJ
615 * @sci_port: This is the port on which the phy should be enabled.
616 * @sci_phy: This is the specific phy which to enable.
6f231dda
DW
617 * @do_notify_user: This parameter specifies whether to inform the user (via
618 * scic_cb_port_link_up()) as to the fact that a new phy as become ready.
619 *
09d7da13
DJ
620 * This function will activate the phy in the port.
621 * Activation includes: - adding
6f231dda
DW
622 * the phy to the port - enabling the Protocol Engine in the silicon. -
623 * notifying the user that the link is up. none
624 */
35173d57
DW
625static void scic_sds_port_activate_phy(struct scic_sds_port *sci_port,
626 struct scic_sds_phy *sci_phy,
627 bool do_notify_user)
6f231dda 628{
d7b90fc3 629 struct scic_sds_controller *scic = sci_port->owning_controller;
d3757c3a 630 struct isci_host *ihost = scic->ihost;
6f231dda 631
d7b90fc3 632 if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA)
09d7da13 633 scic_sds_phy_resume(sci_phy);
6f231dda 634
09d7da13 635 sci_port->active_phy_mask |= 1 << sci_phy->phy_index;
6f231dda 636
09d7da13 637 scic_sds_controller_clear_invalid_phy(scic, sci_phy);
6f231dda
DW
638
639 if (do_notify_user == true)
09d7da13 640 isci_port_link_up(ihost, sci_port, sci_phy);
6f231dda
DW
641}
642
09d7da13
DJ
643void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port,
644 struct scic_sds_phy *sci_phy,
645 bool do_notify_user)
6f231dda 646{
35173d57 647 struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port);
115bd1f9 648 struct isci_port *iport = sci_port->iport;
d3757c3a 649 struct isci_host *ihost = scic->ihost;
e1e72a00 650 struct isci_phy *iphy = sci_phy->iphy;
09d7da13
DJ
651
652 sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index);
6f231dda 653
26bace34 654 sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
6f231dda
DW
655
656 /* Re-assign the phy back to the LP as if it were a narrow port */
bc99aa47
CH
657 writel(sci_phy->phy_index,
658 &sci_port->port_pe_configuration_register[sci_phy->phy_index]);
6f231dda
DW
659
660 if (do_notify_user == true)
09d7da13 661 isci_port_link_down(ihost, iphy, iport);
6f231dda
DW
662}
663
664/**
665 *
e2023b87
DJ
666 * @sci_port: This is the port on which the phy should be disabled.
667 * @sci_phy: This is the specific phy which to disabled.
6f231dda 668 *
09d7da13 669 * This function will disable the phy and report that the phy is not valid for
6f231dda
DW
670 * this port object. None
671 */
672static void scic_sds_port_invalid_link_up(
09d7da13
DJ
673 struct scic_sds_port *sci_port,
674 struct scic_sds_phy *sci_phy)
6f231dda 675{
09d7da13
DJ
676 struct scic_sds_controller *scic =
677 scic_sds_port_get_controller(sci_port);
6f231dda
DW
678
679 /*
09d7da13
DJ
680 * Check to see if we have alreay reported this link as bad and if
681 * not go ahead and tell the SCI_USER that we have discovered an
682 * invalid link.
683 */
684 if ((scic->invalid_phy_mask & (1 << sci_phy->phy_index)) == 0) {
685 scic_sds_controller_set_invalid_phy(scic, sci_phy);
686 isci_port_invalid_link_up(scic, sci_port, sci_phy);
6f231dda
DW
687 }
688}
689
35173d57
DW
690/**
691 * scic_sds_port_general_link_up_handler - phy can be assigned to port?
692 * @sci_port: scic_sds_port object for which has a phy that has gone link up.
693 * @sci_phy: This is the struct scic_sds_phy object that has gone link up.
694 * @do_notify_user: This parameter specifies whether to inform the user (via
695 * scic_cb_port_link_up()) as to the fact that a new phy as become ready.
696 *
697 * Determine if this phy can be assigned to this
698 * port . If the phy is not a valid PHY for
699 * this port then the function will notify the user. A PHY can only be
700 * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in
701 * the same port. none
702 */
703static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port,
704 struct scic_sds_phy *sci_phy,
705 bool do_notify_user)
706{
707 struct sci_sas_address port_sas_address;
708 struct sci_sas_address phy_sas_address;
709
710 scic_sds_port_get_attached_sas_address(sci_port, &port_sas_address);
711 scic_sds_phy_get_attached_sas_address(sci_phy, &phy_sas_address);
712
713 /* If the SAS address of the new phy matches the SAS address of
714 * other phys in the port OR this is the first phy in the port,
715 * then activate the phy and allow it to be used for operations
716 * in this port.
717 */
718 if ((phy_sas_address.high == port_sas_address.high &&
719 phy_sas_address.low == port_sas_address.low) ||
720 sci_port->active_phy_mask == 0) {
41e2b905 721 struct sci_base_state_machine *sm = &sci_port->state_machine;
35173d57
DW
722
723 scic_sds_port_activate_phy(sci_port, sci_phy, do_notify_user);
724 if (sm->current_state_id == SCI_BASE_PORT_STATE_RESETTING)
725 sci_base_state_machine_change_state(sm, SCI_BASE_PORT_STATE_READY);
726 } else
727 scic_sds_port_invalid_link_up(sci_port, sci_phy);
728}
729
730
731
6f231dda
DW
732/**
733 * This method returns false if the port only has a single phy object assigned.
734 * If there are no phys or more than one phy then the method will return
735 * true.
e2023b87 736 * @sci_port: The port for which the wide port condition is to be checked.
6f231dda
DW
737 *
738 * bool true Is returned if this is a wide ported port. false Is returned if
739 * this is a narrow port.
740 */
e2023b87 741static bool scic_sds_port_is_wide(struct scic_sds_port *sci_port)
6f231dda
DW
742{
743 u32 index;
744 u32 phy_count = 0;
745
746 for (index = 0; index < SCI_MAX_PHYS; index++) {
e2023b87 747 if (sci_port->phy_table[index] != NULL) {
6f231dda
DW
748 phy_count++;
749 }
750 }
751
752 return phy_count != 1;
753}
754
755/**
756 * This method is called by the PHY object when the link is detected. if the
757 * port wants the PHY to continue on to the link up state then the port
758 * layer must return true. If the port object returns false the phy object
759 * must halt its attempt to go link up.
e2023b87
DJ
760 * @sci_port: The port associated with the phy object.
761 * @sci_phy: The phy object that is trying to go link up.
6f231dda
DW
762 *
763 * true if the phy object can continue to the link up condition. true Is
764 * returned if this phy can continue to the ready state. false Is returned if
765 * can not continue on to the ready state. This notification is in place for
766 * wide ports and direct attached phys. Since there are no wide ported SATA
767 * devices this could become an invalid port configuration.
768 */
769bool scic_sds_port_link_detected(
e2023b87
DJ
770 struct scic_sds_port *sci_port,
771 struct scic_sds_phy *sci_phy)
6f231dda 772{
d7b90fc3
DJ
773 if ((sci_port->logical_port_index != SCIC_SDS_DUMMY_PORT) &&
774 (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) &&
775 scic_sds_port_is_wide(sci_port)) {
e2023b87 776 scic_sds_port_invalid_link_up(sci_port, sci_phy);
6f231dda
DW
777
778 return false;
779 }
780
781 return true;
782}
783
784/**
785 * This method is the entry point for the phy to inform the port that it is now
786 * in a ready state
e2023b87 787 * @sci_port:
6f231dda
DW
788 *
789 *
790 */
791void scic_sds_port_link_up(
e2023b87
DJ
792 struct scic_sds_port *sci_port,
793 struct scic_sds_phy *sci_phy)
6f231dda 794{
e2023b87 795 sci_phy->is_in_link_training = false;
6f231dda 796
e2023b87 797 sci_port->state_handlers->link_up_handler(sci_port, sci_phy);
6f231dda
DW
798}
799
800/**
801 * This method is the entry point for the phy to inform the port that it is no
802 * longer in a ready state
e2023b87 803 * @sci_port:
6f231dda
DW
804 *
805 *
806 */
807void scic_sds_port_link_down(
e2023b87
DJ
808 struct scic_sds_port *sci_port,
809 struct scic_sds_phy *sci_phy)
6f231dda 810{
e2023b87 811 sci_port->state_handlers->link_down_handler(sci_port, sci_phy);
6f231dda
DW
812}
813
814/**
815 * This method is called to start an IO request on this port.
e2023b87
DJ
816 * @sci_port:
817 * @sci_dev:
818 * @sci_req:
6f231dda
DW
819 *
820 * enum sci_status
821 */
822enum sci_status scic_sds_port_start_io(
e2023b87
DJ
823 struct scic_sds_port *sci_port,
824 struct scic_sds_remote_device *sci_dev,
825 struct scic_sds_request *sci_req)
6f231dda 826{
e2023b87
DJ
827 return sci_port->state_handlers->start_io_handler(
828 sci_port, sci_dev, sci_req);
6f231dda
DW
829}
830
831/**
832 * This method is called to complete an IO request to the port.
e2023b87
DJ
833 * @sci_port:
834 * @sci_dev:
835 * @sci_req:
6f231dda
DW
836 *
837 * enum sci_status
838 */
839enum sci_status scic_sds_port_complete_io(
e2023b87
DJ
840 struct scic_sds_port *sci_port,
841 struct scic_sds_remote_device *sci_dev,
842 struct scic_sds_request *sci_req)
6f231dda 843{
e2023b87
DJ
844 return sci_port->state_handlers->complete_io_handler(
845 sci_port, sci_dev, sci_req);
6f231dda
DW
846}
847
848/**
849 * This method is provided to timeout requests for port operations. Mostly its
850 * for the port reset operation.
851 *
852 *
853 */
854static void scic_sds_port_timeout_handler(void *port)
855{
09d7da13 856 struct scic_sds_port *sci_port = port;
6f231dda
DW
857 u32 current_state;
858
859 current_state = sci_base_state_machine_get_state(
41e2b905 860 &sci_port->state_machine);
6f231dda
DW
861
862 if (current_state == SCI_BASE_PORT_STATE_RESETTING) {
863 /*
09d7da13
DJ
864 * if the port is still in the resetting state then the
865 * timeout fired before the reset completed.
866 */
6f231dda 867 sci_base_state_machine_change_state(
41e2b905 868 &sci_port->state_machine,
09d7da13 869 SCI_BASE_PORT_STATE_FAILED);
6f231dda
DW
870 } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) {
871 /*
872 * if the port is stopped then the start request failed
09d7da13
DJ
873 * In this case stay in the stopped state.
874 */
875 dev_err(sciport_to_dev(sci_port),
6f231dda
DW
876 "%s: SCIC Port 0x%p failed to stop before tiemout.\n",
877 __func__,
09d7da13 878 sci_port);
6f231dda 879 } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) {
09d7da13
DJ
880 /*
881 * if the port is still stopping then the stop has not
882 * completed
883 */
884 isci_port_stop_complete(
885 scic_sds_port_get_controller(sci_port),
886 sci_port,
887 SCI_FAILURE_TIMEOUT);
6f231dda
DW
888 } else {
889 /*
09d7da13
DJ
890 * The port is in the ready state and we have a timer
891 * reporting a timeout this should not happen.
892 */
893 dev_err(sciport_to_dev(sci_port),
6f231dda
DW
894 "%s: SCIC Port 0x%p is processing a timeout operation "
895 "in state %d.\n",
896 __func__,
09d7da13 897 sci_port,
6f231dda
DW
898 current_state);
899 }
900}
901
902/* --------------------------------------------------------------------------- */
903
6f231dda
DW
904/**
905 * This function updates the hardwares VIIT entry for this port.
906 *
907 *
908 */
e2023b87 909static void scic_sds_port_update_viit_entry(struct scic_sds_port *sci_port)
6f231dda
DW
910{
911 struct sci_sas_address sas_address;
912
e2023b87 913 scic_sds_port_get_sas_address(sci_port, &sas_address);
6f231dda 914
bc99aa47 915 writel(sas_address.high,
e2023b87 916 &sci_port->viit_registers->initiator_sas_address_hi);
bc99aa47 917 writel(sas_address.low,
e2023b87 918 &sci_port->viit_registers->initiator_sas_address_lo);
6f231dda
DW
919
920 /* This value get cleared just in case its not already cleared */
e2023b87 921 writel(0, &sci_port->viit_registers->reserved);
6f231dda
DW
922
923 /* We are required to update the status register last */
bc99aa47
CH
924 writel(SCU_VIIT_ENTRY_ID_VIIT |
925 SCU_VIIT_IPPT_INITIATOR |
e2023b87 926 ((1 << sci_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) |
bc99aa47 927 SCU_VIIT_STATUS_ALL_VALID,
e2023b87 928 &sci_port->viit_registers->status);
6f231dda
DW
929}
930
931/**
932 * This method returns the maximum allowed speed for data transfers on this
933 * port. This maximum allowed speed evaluates to the maximum speed of the
934 * slowest phy in the port.
e2023b87 935 * @sci_port: This parameter specifies the port for which to retrieve the
6f231dda
DW
936 * maximum allowed speed.
937 *
938 * This method returns the maximum negotiated speed of the slowest phy in the
939 * port.
940 */
26bace34 941enum sas_linkrate scic_sds_port_get_max_allowed_speed(
e2023b87 942 struct scic_sds_port *sci_port)
6f231dda 943{
26bace34
DW
944 u16 index;
945 enum sas_linkrate max_allowed_speed = SAS_LINK_RATE_6_0_GBPS;
946 struct scic_sds_phy *phy = NULL;
6f231dda
DW
947
948 /*
949 * Loop through all of the phys in this port and find the phy with the
950 * lowest maximum link rate. */
951 for (index = 0; index < SCI_MAX_PHYS; index++) {
e2023b87 952 phy = sci_port->phy_table[index];
6f231dda
DW
953 if (
954 (phy != NULL)
e2023b87 955 && (scic_sds_port_active_phy(sci_port, phy) == true)
6f231dda
DW
956 && (phy->max_negotiated_speed < max_allowed_speed)
957 )
958 max_allowed_speed = phy->max_negotiated_speed;
959 }
960
961 return max_allowed_speed;
962}
963
964
965/**
966 * This method passes the event to core user.
e2023b87
DJ
967 * @sci_port: The port that a BCN happens.
968 * @sci_phy: The phy that receives BCN.
6f231dda
DW
969 *
970 */
971void scic_sds_port_broadcast_change_received(
09d7da13
DJ
972 struct scic_sds_port *sci_port,
973 struct scic_sds_phy *sci_phy)
6f231dda 974{
09d7da13 975 struct scic_sds_controller *scic = sci_port->owning_controller;
d3757c3a 976 struct isci_host *ihost = scic->ihost;
09d7da13 977
6f231dda 978 /* notify the user. */
09d7da13 979 isci_port_bc_change_received(ihost, sci_port, sci_phy);
6f231dda
DW
980}
981
982
983/**
984 * This API methhod enables the broadcast change notification from underneath
985 * hardware.
e2023b87 986 * @sci_port: The port that a BCN had been disabled from.
6f231dda
DW
987 *
988 */
989void scic_port_enable_broadcast_change_notification(
990 struct scic_sds_port *port)
991{
992 struct scic_sds_phy *phy;
993 u32 register_value;
994 u8 index;
995
996 /* Loop through all of the phys to enable BCN. */
997 for (index = 0; index < SCI_MAX_PHYS; index++) {
998 phy = port->phy_table[index];
999 if (phy != NULL) {
bc99aa47
CH
1000 register_value =
1001 readl(&phy->link_layer_registers->link_layer_control);
6f231dda
DW
1002
1003 /* clear the bit by writing 1. */
bc99aa47
CH
1004 writel(register_value,
1005 &phy->link_layer_registers->link_layer_control);
6f231dda
DW
1006 }
1007 }
1008}
1009
1010/*
1011 * ****************************************************************************
1012 * * READY SUBSTATE HANDLERS
1013 * **************************************************************************** */
1014
41e2b905 1015/*
6f231dda
DW
1016 * This method is the general ready state stop handler for the struct scic_sds_port
1017 * object. This function will transition the ready substate machine to its
1018 * final state. enum sci_status SCI_SUCCESS
1019 */
1020static enum sci_status scic_sds_port_ready_substate_stop_handler(
41e2b905 1021 struct scic_sds_port *port)
6f231dda 1022{
6f231dda 1023 sci_base_state_machine_change_state(
41e2b905 1024 &port->state_machine,
6f231dda
DW
1025 SCI_BASE_PORT_STATE_STOPPING
1026 );
1027
1028 return SCI_SUCCESS;
1029}
1030
38aa74eb 1031/*
6f231dda
DW
1032 * This method is the general ready substate complete io handler for the
1033 * struct scic_sds_port object. This function decrments the outstanding request count
1034 * for this port object. enum sci_status SCI_SUCCESS
1035 */
1036static enum sci_status scic_sds_port_ready_substate_complete_io_handler(
1037 struct scic_sds_port *port,
1038 struct scic_sds_remote_device *device,
1039 struct scic_sds_request *io_request)
1040{
41e2b905 1041 scic_sds_port_decrement_request_count(port);
6f231dda
DW
1042
1043 return SCI_SUCCESS;
1044}
1045
1046static enum sci_status scic_sds_port_ready_substate_add_phy_handler(
41e2b905 1047 struct scic_sds_port *port,
d857d9a0 1048 struct scic_sds_phy *phy)
6f231dda 1049{
6f231dda
DW
1050 enum sci_status status;
1051
d857d9a0 1052 status = scic_sds_port_set_phy(port, phy);
6f231dda
DW
1053
1054 if (status == SCI_SUCCESS) {
d857d9a0 1055 scic_sds_port_general_link_up_handler(port, phy, true);
6f231dda 1056
41e2b905 1057 port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
6f231dda
DW
1058
1059 sci_base_state_machine_change_state(
41e2b905 1060 &port->ready_substate_machine,
6f231dda
DW
1061 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
1062 );
1063 }
1064
1065 return status;
1066}
1067
1068
1069static enum sci_status scic_sds_port_ready_substate_remove_phy_handler(
41e2b905 1070 struct scic_sds_port *port,
d857d9a0 1071 struct scic_sds_phy *phy)
6f231dda 1072{
6f231dda
DW
1073 enum sci_status status;
1074
d857d9a0 1075 status = scic_sds_port_clear_phy(port, phy);
6f231dda
DW
1076
1077 if (status == SCI_SUCCESS) {
d857d9a0 1078 scic_sds_port_deactivate_phy(port, phy, true);
6f231dda 1079
41e2b905 1080 port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
6f231dda
DW
1081
1082 sci_base_state_machine_change_state(
41e2b905 1083 &port->ready_substate_machine,
6f231dda
DW
1084 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
1085 );
1086 }
1087
1088 return status;
1089}
1090
1091/*
1092 * ****************************************************************************
1093 * * READY SUBSTATE WAITING HANDLERS
1094 * **************************************************************************** */
1095
1096/**
1097 *
e2023b87 1098 * @sci_port: This is the struct scic_sds_port object that which has a phy that has
6f231dda 1099 * gone link up.
e2023b87 1100 * @sci_phy: This is the struct scic_sds_phy object that has gone link up.
6f231dda
DW
1101 *
1102 * This method is the ready waiting substate link up handler for the
1103 * struct scic_sds_port object. This methos will report the link up condition for
1104 * this port and will transition to the ready operational substate. none
1105 */
1106static void scic_sds_port_ready_waiting_substate_link_up_handler(
e2023b87
DJ
1107 struct scic_sds_port *sci_port,
1108 struct scic_sds_phy *sci_phy)
6f231dda
DW
1109{
1110 /*
1111 * Since this is the first phy going link up for the port we can just enable
1112 * it and continue. */
e2023b87 1113 scic_sds_port_activate_phy(sci_port, sci_phy, true);
6f231dda
DW
1114
1115 sci_base_state_machine_change_state(
e2023b87 1116 &sci_port->ready_substate_machine,
6f231dda
DW
1117 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
1118 );
1119}
1120
38aa74eb 1121/*
6f231dda
DW
1122 * This method is the ready waiting substate start io handler for the
1123 * struct scic_sds_port object. The port object can not accept new requests so the
1124 * request is failed. enum sci_status SCI_FAILURE_INVALID_STATE
1125 */
1126static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler(
1127 struct scic_sds_port *port,
1128 struct scic_sds_remote_device *device,
1129 struct scic_sds_request *io_request)
1130{
1131 return SCI_FAILURE_INVALID_STATE;
1132}
1133
1134/*
1135 * ****************************************************************************
1136 * * READY SUBSTATE OPERATIONAL HANDLERS
1137 * **************************************************************************** */
1138
41e2b905 1139/*
6f231dda
DW
1140 * This method will casue the port to reset. enum sci_status SCI_SUCCESS
1141 */
09d7da13
DJ
1142static enum
1143sci_status scic_sds_port_ready_operational_substate_reset_handler(
41e2b905 1144 struct scic_sds_port *port,
09d7da13 1145 u32 timeout)
6f231dda
DW
1146{
1147 enum sci_status status = SCI_FAILURE_INVALID_PHY;
1148 u32 phy_index;
a7e536c7 1149 struct scic_sds_phy *selected_phy = NULL;
6f231dda
DW
1150
1151
1152 /* Select a phy on which we can send the hard reset request. */
09d7da13
DJ
1153 for (phy_index = 0;
1154 (phy_index < SCI_MAX_PHYS) && (selected_phy == NULL);
1155 phy_index++) {
41e2b905 1156 selected_phy = port->phy_table[phy_index];
09d7da13
DJ
1157
1158 if ((selected_phy != NULL) &&
41e2b905 1159 !scic_sds_port_active_phy(port, selected_phy)) {
09d7da13
DJ
1160 /*
1161 * We found a phy but it is not ready select
1162 * different phy
1163 */
a7e536c7 1164 selected_phy = NULL;
6f231dda
DW
1165 }
1166 }
1167
1168 /* If we have a phy then go ahead and start the reset procedure */
a7e536c7 1169 if (selected_phy != NULL) {
6f231dda
DW
1170 status = scic_sds_phy_reset(selected_phy);
1171
1172 if (status == SCI_SUCCESS) {
41e2b905
MT
1173 isci_timer_start(port->timer_handle, timeout);
1174 port->not_ready_reason =
09d7da13 1175 SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED;
6f231dda
DW
1176
1177 sci_base_state_machine_change_state(
41e2b905 1178 &port->state_machine,
09d7da13 1179 SCI_BASE_PORT_STATE_RESETTING);
6f231dda
DW
1180 }
1181 }
1182
1183 return status;
1184}
1185
1186/**
1187 * scic_sds_port_ready_operational_substate_link_up_handler() -
e2023b87 1188 * @sci_port: This is the struct scic_sds_port object that which has a phy that has
6f231dda 1189 * gone link up.
e2023b87 1190 * @sci_phy: This is the struct scic_sds_phy object that has gone link up.
6f231dda
DW
1191 *
1192 * This method is the ready operational substate link up handler for the
1193 * struct scic_sds_port object. This function notifies the SCI User that the phy has
1194 * gone link up. none
1195 */
1196static void scic_sds_port_ready_operational_substate_link_up_handler(
e2023b87
DJ
1197 struct scic_sds_port *sci_port,
1198 struct scic_sds_phy *sci_phy)
6f231dda 1199{
e2023b87 1200 scic_sds_port_general_link_up_handler(sci_port, sci_phy, true);
6f231dda
DW
1201}
1202
1203/**
1204 * scic_sds_port_ready_operational_substate_link_down_handler() -
068b2c03 1205 * @sci_port: This is the struct scic_sds_port object that which has a phy that has
6f231dda 1206 * gone link down.
068b2c03 1207 * @sci_phy: This is the struct scic_sds_phy object that has gone link down.
6f231dda
DW
1208 *
1209 * This method is the ready operational substate link down handler for the
1210 * struct scic_sds_port object. This function notifies the SCI User that the phy has
1211 * gone link down and if this is the last phy in the port the port will change
1212 * state to the ready waiting substate. none
1213 */
1214static void scic_sds_port_ready_operational_substate_link_down_handler(
068b2c03
DW
1215 struct scic_sds_port *sci_port,
1216 struct scic_sds_phy *sci_phy)
6f231dda 1217{
068b2c03 1218 scic_sds_port_deactivate_phy(sci_port, sci_phy, true);
6f231dda
DW
1219
1220 /*
1221 * If there are no active phys left in the port, then transition
1222 * the port to the WAITING state until such time as a phy goes
1223 * link up. */
068b2c03
DW
1224 if (sci_port->active_phy_mask == 0)
1225 sci_base_state_machine_change_state(&sci_port->ready_substate_machine,
1226 SCIC_SDS_PORT_READY_SUBSTATE_WAITING);
6f231dda
DW
1227}
1228
38aa74eb 1229/*
6f231dda
DW
1230 * This method is the ready operational substate start io handler for the
1231 * struct scic_sds_port object. This function incremetns the outstanding request
1232 * count for this port object. enum sci_status SCI_SUCCESS
1233 */
1234static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler(
1235 struct scic_sds_port *port,
1236 struct scic_sds_remote_device *device,
1237 struct scic_sds_request *io_request)
1238{
41e2b905 1239 scic_sds_port_increment_request_count(port);
6f231dda
DW
1240
1241 return SCI_SUCCESS;
1242}
1243
1244/*
1245 * ****************************************************************************
1246 * * READY SUBSTATE OPERATIONAL HANDLERS
1247 * **************************************************************************** */
1248
41e2b905 1249/*
6f231dda
DW
1250 * This is the default method for a port add phy request. It will report a
1251 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1252 */
1253static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler(
41e2b905 1254 struct scic_sds_port *port,
d857d9a0 1255 struct scic_sds_phy *phy)
6f231dda 1256{
6f231dda
DW
1257 enum sci_status status;
1258
d857d9a0 1259 status = scic_sds_port_set_phy(port, phy);
6f231dda
DW
1260
1261 if (status == SCI_SUCCESS) {
d857d9a0 1262 scic_sds_port_general_link_up_handler(port, phy, true);
6f231dda
DW
1263
1264 /*
1265 * Re-enter the configuring state since this may be the last phy in
1266 * the port. */
1267 sci_base_state_machine_change_state(
41e2b905 1268 &port->ready_substate_machine,
6f231dda
DW
1269 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
1270 );
1271 }
1272
1273 return status;
1274}
1275
41e2b905 1276/*
6f231dda
DW
1277 * This is the default method for a port remove phy request. It will report a
1278 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1279 */
1280static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handler(
41e2b905 1281 struct scic_sds_port *port,
d857d9a0 1282 struct scic_sds_phy *phy)
6f231dda 1283{
6f231dda
DW
1284 enum sci_status status;
1285
d857d9a0 1286 status = scic_sds_port_clear_phy(port, phy);
6f231dda
DW
1287
1288 if (status == SCI_SUCCESS) {
d857d9a0 1289 scic_sds_port_deactivate_phy(port, phy, true);
6f231dda
DW
1290
1291 /*
1292 * Re-enter the configuring state since this may be the last phy in
1293 * the port. */
1294 sci_base_state_machine_change_state(
41e2b905 1295 &port->ready_substate_machine,
6f231dda
DW
1296 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
1297 );
1298 }
1299
1300 return status;
1301}
1302
1303/**
1304 * scic_sds_port_ready_configuring_substate_complete_io_handler() -
1305 * @port: This is the port that is being requested to complete the io request.
1306 * @device: This is the device on which the io is completing.
1307 *
1308 * This method will decrement the outstanding request count for this port. If
1309 * the request count goes to 0 then the port can be reprogrammed with its new
1310 * phy data.
1311 */
41e2b905
MT
1312static enum sci_status
1313scic_sds_port_ready_configuring_substate_complete_io_handler(
6f231dda
DW
1314 struct scic_sds_port *port,
1315 struct scic_sds_remote_device *device,
1316 struct scic_sds_request *io_request)
1317{
1318 scic_sds_port_decrement_request_count(port);
1319
1320 if (port->started_request_count == 0) {
1321 sci_base_state_machine_change_state(
1322 &port->ready_substate_machine,
1323 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
1324 );
1325 }
1326
1327 return SCI_SUCCESS;
1328}
1329
41e2b905
MT
1330static enum sci_status default_port_handler(struct scic_sds_port *sci_port,
1331 const char *func)
35173d57 1332{
35173d57
DW
1333 dev_warn(sciport_to_dev(sci_port),
1334 "%s: in wrong state: %d\n", func,
41e2b905 1335 sci_base_state_machine_get_state(&sci_port->state_machine));
35173d57
DW
1336 return SCI_FAILURE_INVALID_STATE;
1337}
1338
41e2b905
MT
1339static enum sci_status
1340scic_sds_port_default_start_handler(struct scic_sds_port *sci_port)
35173d57 1341{
41e2b905 1342 return default_port_handler(sci_port, __func__);
35173d57
DW
1343}
1344
41e2b905
MT
1345static enum sci_status
1346scic_sds_port_default_stop_handler(struct scic_sds_port *sci_port)
35173d57 1347{
41e2b905 1348 return default_port_handler(sci_port, __func__);
35173d57
DW
1349}
1350
41e2b905
MT
1351static enum sci_status
1352scic_sds_port_default_destruct_handler(struct scic_sds_port *sci_port)
35173d57 1353{
41e2b905 1354 return default_port_handler(sci_port, __func__);
35173d57
DW
1355}
1356
41e2b905
MT
1357static enum sci_status
1358scic_sds_port_default_reset_handler(struct scic_sds_port *sci_port,
1359 u32 timeout)
35173d57 1360{
41e2b905 1361 return default_port_handler(sci_port, __func__);
35173d57
DW
1362}
1363
41e2b905
MT
1364static enum sci_status
1365scic_sds_port_default_add_phy_handler(struct scic_sds_port *sci_port,
d857d9a0 1366 struct scic_sds_phy *base_phy)
35173d57 1367{
41e2b905 1368 return default_port_handler(sci_port, __func__);
35173d57
DW
1369}
1370
41e2b905
MT
1371static enum sci_status
1372scic_sds_port_default_remove_phy_handler(struct scic_sds_port *sci_port,
d857d9a0 1373 struct scic_sds_phy *base_phy)
35173d57 1374{
41e2b905 1375 return default_port_handler(sci_port, __func__);
35173d57
DW
1376}
1377
41e2b905 1378/*
35173d57
DW
1379 * This is the default method for a port unsolicited frame request. It will
1380 * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even
1381 * possible to receive an unsolicited frame directed to a port object? It
1382 * seems possible if we implementing virtual functions but until then?
1383 */
41e2b905
MT
1384static enum sci_status
1385scic_sds_port_default_frame_handler(struct scic_sds_port *sci_port,
1386 u32 frame_index)
35173d57
DW
1387{
1388 struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port);
1389
41e2b905 1390 default_port_handler(sci_port, __func__);
35173d57
DW
1391 scic_sds_controller_release_frame(scic, frame_index);
1392
1393 return SCI_FAILURE_INVALID_STATE;
1394}
1395
1396static enum sci_status scic_sds_port_default_event_handler(struct scic_sds_port *sci_port,
1397 u32 event_code)
1398{
41e2b905 1399 return default_port_handler(sci_port, __func__);
35173d57
DW
1400}
1401
1402static void scic_sds_port_default_link_up_handler(struct scic_sds_port *sci_port,
1403 struct scic_sds_phy *sci_phy)
1404{
41e2b905 1405 default_port_handler(sci_port, __func__);
35173d57
DW
1406}
1407
1408static void scic_sds_port_default_link_down_handler(struct scic_sds_port *sci_port,
1409 struct scic_sds_phy *sci_phy)
1410{
41e2b905 1411 default_port_handler(sci_port, __func__);
35173d57 1412}
6f231dda 1413
35173d57
DW
1414static enum sci_status scic_sds_port_default_start_io_handler(struct scic_sds_port *sci_port,
1415 struct scic_sds_remote_device *sci_dev,
1416 struct scic_sds_request *sci_req)
1417{
41e2b905 1418 return default_port_handler(sci_port, __func__);
35173d57
DW
1419}
1420
1421static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds_port *sci_port,
1422 struct scic_sds_remote_device *sci_dev,
1423 struct scic_sds_request *sci_req)
1424{
41e2b905 1425 return default_port_handler(sci_port, __func__);
35173d57
DW
1426}
1427
1428
1429
1430static struct scic_sds_port_state_handler
41e2b905 1431scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = {
6f231dda 1432 {
41e2b905
MT
1433 /* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */
1434 scic_sds_port_default_start_handler,
1435 scic_sds_port_ready_substate_stop_handler,
1436 scic_sds_port_default_destruct_handler,
1437 scic_sds_port_default_reset_handler,
1438 scic_sds_port_ready_substate_add_phy_handler,
1439 scic_sds_port_default_remove_phy_handler,
6f231dda
DW
1440 scic_sds_port_default_frame_handler,
1441 scic_sds_port_default_event_handler,
1442 scic_sds_port_ready_waiting_substate_link_up_handler,
1443 scic_sds_port_default_link_down_handler,
1444 scic_sds_port_ready_waiting_substate_start_io_handler,
1445 scic_sds_port_ready_substate_complete_io_handler,
1446 },
41e2b905 1447
6f231dda 1448 {
41e2b905
MT
1449 /* SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL */
1450 scic_sds_port_default_start_handler,
1451 scic_sds_port_ready_substate_stop_handler,
1452 scic_sds_port_default_destruct_handler,
1453 scic_sds_port_ready_operational_substate_reset_handler,
1454 scic_sds_port_ready_substate_add_phy_handler,
1455 scic_sds_port_ready_substate_remove_phy_handler,
6f231dda
DW
1456 scic_sds_port_default_frame_handler,
1457 scic_sds_port_default_event_handler,
1458 scic_sds_port_ready_operational_substate_link_up_handler,
1459 scic_sds_port_ready_operational_substate_link_down_handler,
1460 scic_sds_port_ready_operational_substate_start_io_handler,
41e2b905 1461 scic_sds_port_ready_substate_complete_io_handler,
6f231dda 1462 },
41e2b905 1463
6f231dda 1464 {
41e2b905
MT
1465 /* SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING */
1466 scic_sds_port_default_start_handler,
1467 scic_sds_port_ready_substate_stop_handler,
1468 scic_sds_port_default_destruct_handler,
1469 scic_sds_port_default_reset_handler,
1470 scic_sds_port_ready_configuring_substate_add_phy_handler,
1471 scic_sds_port_ready_configuring_substate_remove_phy_handler,
6f231dda
DW
1472 scic_sds_port_default_frame_handler,
1473 scic_sds_port_default_event_handler,
1474 scic_sds_port_default_link_up_handler,
1475 scic_sds_port_default_link_down_handler,
1476 scic_sds_port_default_start_io_handler,
1477 scic_sds_port_ready_configuring_substate_complete_io_handler
1478 }
1479};
1480
6f231dda
DW
1481/**
1482 * scic_sds_port_set_ready_state_handlers() -
1483 *
1484 * This macro sets the port ready substate handlers.
1485 */
1486#define scic_sds_port_set_ready_state_handlers(port, state_id) \
1487 scic_sds_port_set_state_handlers(\
1488 port, &scic_sds_port_ready_substate_handler_table[(state_id)] \
1489 )
1490
1491/*
1492 * ******************************************************************************
1493 * * PORT STATE PRIVATE METHODS
1494 * ****************************************************************************** */
1495
1496/**
1497 *
e2023b87 1498 * @sci_port: This is the struct scic_sds_port object to suspend.
6f231dda
DW
1499 *
1500 * This method will susped the port task scheduler for this port object. none
1501 */
bc99aa47
CH
1502static void
1503scic_sds_port_suspend_port_task_scheduler(struct scic_sds_port *port)
6f231dda
DW
1504{
1505 u32 pts_control_value;
6f231dda 1506
bc99aa47 1507 pts_control_value = readl(&port->port_task_scheduler_registers->control);
6f231dda 1508 pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND);
bc99aa47 1509 writel(pts_control_value, &port->port_task_scheduler_registers->control);
6f231dda
DW
1510}
1511
a8d4b9fe
TC
1512/**
1513 * scic_sds_port_post_dummy_request() - post dummy/workaround request
1514 * @sci_port: port to post task
1515 *
1516 * Prevent the hardware scheduler from posting new requests to the front
1517 * of the scheduler queue causing a starvation problem for currently
1518 * ongoing requests.
1519 *
1520 */
35173d57 1521static void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port)
a8d4b9fe
TC
1522{
1523 u32 command;
1524 struct scu_task_context *task_context;
1525 struct scic_sds_controller *scic = sci_port->owning_controller;
1526 u16 tci = sci_port->reserved_tci;
1527
1528 task_context = scic_sds_controller_get_task_context_buffer(scic, tci);
1529
1530 task_context->abort = 0;
1531
1532 command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
1533 sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT |
1534 tci;
1535
1536 scic_sds_controller_post_request(scic, command);
1537}
1538
1539/**
1540 * This routine will abort the dummy request. This will alow the hardware to
1541 * power down parts of the silicon to save power.
1542 *
1543 * @sci_port: The port on which the task must be aborted.
1544 *
1545 */
35173d57 1546static void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port)
a8d4b9fe
TC
1547{
1548 struct scic_sds_controller *scic = sci_port->owning_controller;
1549 u16 tci = sci_port->reserved_tci;
1550 struct scu_task_context *tc;
1551 u32 command;
1552
1553 tc = scic_sds_controller_get_task_context_buffer(scic, tci);
1554
1555 tc->abort = 1;
1556
1557 command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT |
1558 sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT |
1559 tci;
1560
1561 scic_sds_controller_post_request(scic, command);
1562}
1563
6f231dda
DW
1564/**
1565 *
e2023b87 1566 * @sci_port: This is the struct scic_sds_port object to resume.
6f231dda
DW
1567 *
1568 * This method will resume the port task scheduler for this port object. none
1569 */
bc99aa47
CH
1570static void
1571scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port)
6f231dda
DW
1572{
1573 u32 pts_control_value;
1574
bc99aa47 1575 pts_control_value = readl(&port->port_task_scheduler_registers->control);
6f231dda 1576 pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND);
bc99aa47 1577 writel(pts_control_value, &port->port_task_scheduler_registers->control);
6f231dda
DW
1578}
1579
1580/*
1581 * ******************************************************************************
1582 * * PORT READY SUBSTATE METHODS
1583 * ****************************************************************************** */
1584
1585/**
1586 *
9a0fff7b 1587 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda
DW
1588 *
1589 * This method will perform the actions required by the struct scic_sds_port on
1590 * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the
1591 * port for any ready phys. If there is at least one phy in a ready state then
1592 * the port transitions to the ready operational substate. none
1593 */
9a0fff7b 1594static void scic_sds_port_ready_substate_waiting_enter(void *object)
6f231dda 1595{
115bd1f9 1596 struct scic_sds_port *sci_port = object;
6f231dda
DW
1597
1598 scic_sds_port_set_ready_state_handlers(
e2023b87 1599 sci_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING
6f231dda
DW
1600 );
1601
e2023b87 1602 scic_sds_port_suspend_port_task_scheduler(sci_port);
6f231dda 1603
e2023b87 1604 sci_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS;
6f231dda 1605
e2023b87 1606 if (sci_port->active_phy_mask != 0) {
6f231dda
DW
1607 /* At least one of the phys on the port is ready */
1608 sci_base_state_machine_change_state(
e2023b87 1609 &sci_port->ready_substate_machine,
6f231dda
DW
1610 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
1611 );
1612 }
1613}
1614
1615/**
1616 *
9a0fff7b 1617 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda 1618 *
09d7da13
DJ
1619 * This function will perform the actions required by the struct scic_sds_port
1620 * on entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets
6f231dda
DW
1621 * the state handlers for the port object, notifies the SCI User that the port
1622 * is ready, and resumes port operations. none
1623 */
9a0fff7b 1624static void scic_sds_port_ready_substate_operational_enter(void *object)
6f231dda
DW
1625{
1626 u32 index;
115bd1f9 1627 struct scic_sds_port *sci_port = object;
09d7da13
DJ
1628 struct scic_sds_controller *scic =
1629 scic_sds_port_get_controller(sci_port);
d3757c3a 1630 struct isci_host *ihost = scic->ihost;
115bd1f9 1631 struct isci_port *iport = sci_port->iport;
6f231dda
DW
1632
1633 scic_sds_port_set_ready_state_handlers(
09d7da13
DJ
1634 sci_port,
1635 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL);
6f231dda 1636
09d7da13 1637 isci_port_ready(ihost, iport);
6f231dda
DW
1638
1639 for (index = 0; index < SCI_MAX_PHYS; index++) {
bc99aa47
CH
1640 if (sci_port->phy_table[index]) {
1641 writel(sci_port->physical_port_index,
1642 &sci_port->port_pe_configuration_register[
1643 sci_port->phy_table[index]->phy_index]);
1644 }
6f231dda
DW
1645 }
1646
09d7da13 1647 scic_sds_port_update_viit_entry(sci_port);
6f231dda 1648
09d7da13 1649 scic_sds_port_resume_port_task_scheduler(sci_port);
a8d4b9fe 1650
09d7da13
DJ
1651 /*
1652 * Post the dummy task for the port so the hardware can schedule
a8d4b9fe
TC
1653 * io correctly
1654 */
09d7da13 1655 scic_sds_port_post_dummy_request(sci_port);
6f231dda
DW
1656}
1657
1658/**
1659 *
9a0fff7b 1660 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda
DW
1661 *
1662 * This method will perform the actions required by the struct scic_sds_port on
1663 * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports
1664 * the port not ready and suspends the port task scheduler. none
1665 */
9a0fff7b 1666static void scic_sds_port_ready_substate_operational_exit(void *object)
6f231dda 1667{
115bd1f9 1668 struct scic_sds_port *sci_port = object;
09d7da13
DJ
1669 struct scic_sds_controller *scic =
1670 scic_sds_port_get_controller(sci_port);
d3757c3a 1671 struct isci_host *ihost = scic->ihost;
115bd1f9 1672 struct isci_port *iport = sci_port->iport;
6f231dda 1673
09d7da13
DJ
1674 /*
1675 * Kill the dummy task for this port if it has not yet posted
1676 * the hardware will treat this as a NOP and just return abort
1677 * complete.
1678 */
1679 scic_sds_port_abort_dummy_request(sci_port);
27ce51df 1680
09d7da13 1681 isci_port_not_ready(ihost, iport);
6f231dda
DW
1682}
1683
1684/*
1685 * ******************************************************************************
1686 * * PORT READY CONFIGURING METHODS
1687 * ****************************************************************************** */
1688
1689/**
1690 * scic_sds_port_ready_substate_configuring_enter() -
9a0fff7b 1691 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda
DW
1692 *
1693 * This method will perform the actions required by the struct scic_sds_port on
1694 * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports
1695 * the port not ready and suspends the port task scheduler. none
1696 */
9a0fff7b 1697static void scic_sds_port_ready_substate_configuring_enter(void *object)
6f231dda 1698{
115bd1f9 1699 struct scic_sds_port *sci_port = object;
09d7da13
DJ
1700 struct scic_sds_controller *scic =
1701 scic_sds_port_get_controller(sci_port);
d3757c3a 1702 struct isci_host *ihost = scic->ihost;
115bd1f9 1703 struct isci_port *iport = sci_port->iport;
6f231dda
DW
1704
1705 scic_sds_port_set_ready_state_handlers(
09d7da13
DJ
1706 sci_port,
1707 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING);
6f231dda 1708
09d7da13
DJ
1709 if (sci_port->active_phy_mask == 0) {
1710 isci_port_not_ready(ihost, iport);
6f231dda
DW
1711
1712 sci_base_state_machine_change_state(
09d7da13
DJ
1713 &sci_port->ready_substate_machine,
1714 SCIC_SDS_PORT_READY_SUBSTATE_WAITING);
1715 } else if (sci_port->started_request_count == 0)
6f231dda 1716 sci_base_state_machine_change_state(
09d7da13
DJ
1717 &sci_port->ready_substate_machine,
1718 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL);
6f231dda
DW
1719}
1720
9a0fff7b 1721static void scic_sds_port_ready_substate_configuring_exit(void *object)
6f231dda 1722{
115bd1f9 1723 struct scic_sds_port *sci_port = object;
6f231dda 1724
e2023b87 1725 scic_sds_port_suspend_port_task_scheduler(sci_port);
6f231dda
DW
1726}
1727
1728/* --------------------------------------------------------------------------- */
1729
35173d57 1730static const struct sci_base_state scic_sds_port_ready_substate_table[] = {
6f231dda
DW
1731 [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = {
1732 .enter_state = scic_sds_port_ready_substate_waiting_enter,
1733 },
1734 [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = {
1735 .enter_state = scic_sds_port_ready_substate_operational_enter,
1736 .exit_state = scic_sds_port_ready_substate_operational_exit
1737 },
1738 [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = {
1739 .enter_state = scic_sds_port_ready_substate_configuring_enter,
1740 .exit_state = scic_sds_port_ready_substate_configuring_exit
1741 },
1742};
1743
6f231dda
DW
1744/**
1745 *
1746 * @port: This is the struct scic_sds_port object on which the io request count will
1747 * be decremented.
1748 * @device: This is the struct scic_sds_remote_device object to which the io request
1749 * is being directed. This parameter is not required to complete this
1750 * operation.
1751 * @io_request: This is the request that is being completed on this port
1752 * object. This parameter is not required to complete this operation.
1753 *
1754 * This is a general complete io request handler for the struct scic_sds_port object.
1755 * enum sci_status SCI_SUCCESS
1756 */
1757static enum sci_status scic_sds_port_general_complete_io_handler(
1758 struct scic_sds_port *port,
1759 struct scic_sds_remote_device *device,
1760 struct scic_sds_request *io_request)
1761{
41e2b905 1762 scic_sds_port_decrement_request_count(port);
6f231dda
DW
1763
1764 return SCI_SUCCESS;
1765}
1766
6f231dda 1767/**
a8d4b9fe 1768 * scic_sds_port_stopped_state_start_handler() - stop a port from "started"
6f231dda 1769 *
41e2b905 1770 * @port: This is the struct scic_sds_port object which is cast into a
09d7da13 1771 * struct scic_sds_port object.
6f231dda 1772 *
09d7da13
DJ
1773 * This function takes the struct scic_sds_port from a stopped state and
1774 * attempts to start it. To start a port it must have no assiged devices and
1775 * it must have at least one phy assigned to it. If those conditions are
1776 * met then the port can transition to the ready state.
1777 * enum sci_status
1778 * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION
1779 * This struct scic_sds_port object could not be started because the port
1780 * configuration is not valid.
1781 * SCI_SUCCESS
1782 * the start request is successful and the struct scic_sds_port object
1783 * has transitioned to the SCI_BASE_PORT_STATE_READY.
6f231dda 1784 */
09d7da13 1785static enum sci_status
41e2b905 1786scic_sds_port_stopped_state_start_handler(struct scic_sds_port *sci_port)
6f231dda 1787{
a8d4b9fe 1788 struct scic_sds_controller *scic = sci_port->owning_controller;
d3757c3a 1789 struct isci_host *ihost = scic->ihost;
a8d4b9fe 1790 enum sci_status status = SCI_SUCCESS;
6f231dda 1791 u32 phy_mask;
6f231dda 1792
a8d4b9fe 1793 if (sci_port->assigned_device_count > 0) {
6f231dda 1794 /*
09d7da13
DJ
1795 * @todo This is a start failure operation because
1796 * there are still devices assigned to this port.
1797 * There must be no devices assigned to a port on a
1798 * start operation.
1799 */
6f231dda
DW
1800 return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
1801 }
1802
09d7da13
DJ
1803 sci_port->timer_handle =
1804 isci_timer_create(ihost,
1805 sci_port,
1806 scic_sds_port_timeout_handler);
6f231dda 1807
a8d4b9fe
TC
1808 if (!sci_port->timer_handle)
1809 return SCI_FAILURE_INSUFFICIENT_RESOURCES;
6f231dda 1810
a8d4b9fe 1811 if (sci_port->reserved_rni == SCU_DUMMY_INDEX) {
09d7da13
DJ
1812 u16 rni = scic_sds_remote_node_table_allocate_remote_node(
1813 &scic->available_remote_nodes, 1);
a8d4b9fe
TC
1814
1815 if (rni != SCU_DUMMY_INDEX)
1816 scic_sds_port_construct_dummy_rnc(sci_port, rni);
1817 else
1818 status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
1819 sci_port->reserved_rni = rni;
1820 }
1821
1822 if (sci_port->reserved_tci == SCU_DUMMY_INDEX) {
1823 /* Allocate a TCI and remove the sequence nibble */
1824 u16 tci = scic_controller_allocate_io_tag(scic);
1825
1826 if (tci != SCU_DUMMY_INDEX)
1827 scic_sds_port_construct_dummy_task(sci_port, tci);
1828 else
1829 status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
1830 sci_port->reserved_tci = tci;
1831 }
1832
1833 if (status == SCI_SUCCESS) {
1834 phy_mask = scic_sds_port_get_phys(sci_port);
1835
1836 /*
1837 * There are one or more phys assigned to this port. Make sure
1838 * the port's phy mask is in fact legal and supported by the
1839 * silicon.
1840 */
1841 if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) {
41e2b905
MT
1842 sci_base_state_machine_change_state(
1843 &sci_port->state_machine,
1844 SCI_BASE_PORT_STATE_READY);
a8d4b9fe
TC
1845
1846 return SCI_SUCCESS;
1847 } else
1848 status = SCI_FAILURE;
6f231dda
DW
1849 }
1850
a8d4b9fe
TC
1851 if (status != SCI_SUCCESS)
1852 scic_sds_port_destroy_dummy_resources(sci_port);
1853
1854 return status;
6f231dda
DW
1855}
1856
41e2b905 1857/*
6f231dda
DW
1858 * This method takes the struct scic_sds_port that is in a stopped state and handles a
1859 * stop request. This function takes no action. enum sci_status SCI_SUCCESS the
1860 * stop request is successful as the struct scic_sds_port object is already stopped.
1861 */
1862static enum sci_status scic_sds_port_stopped_state_stop_handler(
41e2b905 1863 struct scic_sds_port *port)
6f231dda
DW
1864{
1865 /* We are already stopped so there is nothing to do here */
1866 return SCI_SUCCESS;
1867}
1868
41e2b905 1869/*
6f231dda
DW
1870 * This method takes the struct scic_sds_port that is in a stopped state and handles
1871 * the destruct request. The stopped state is the only state in which the
1872 * struct scic_sds_port can be destroyed. This function causes the port object to
1873 * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS
1874 */
1875static enum sci_status scic_sds_port_stopped_state_destruct_handler(
41e2b905 1876 struct scic_sds_port *port)
6f231dda 1877{
41e2b905 1878 sci_base_state_machine_stop(&port->state_machine);
6f231dda
DW
1879
1880 return SCI_SUCCESS;
1881}
1882
41e2b905 1883/*
6f231dda
DW
1884 * This method takes the struct scic_sds_port that is in a stopped state and handles
1885 * the add phy request. In MPC mode the only time a phy can be added to a port
1886 * is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status
1887 * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not
1888 * be added to the port. SCI_SUCCESS if the phy is added to the port.
1889 */
1890static enum sci_status scic_sds_port_stopped_state_add_phy_handler(
41e2b905 1891 struct scic_sds_port *port,
d857d9a0 1892 struct scic_sds_phy *phy)
6f231dda 1893{
6f231dda
DW
1894 struct sci_sas_address port_sas_address;
1895
1896 /* Read the port assigned SAS Address if there is one */
41e2b905 1897 scic_sds_port_get_sas_address(port, &port_sas_address);
6f231dda
DW
1898
1899 if (port_sas_address.high != 0 && port_sas_address.low != 0) {
1900 struct sci_sas_address phy_sas_address;
1901
1902 /*
1903 * Make sure that the PHY SAS Address matches the SAS Address
1904 * for this port. */
d857d9a0 1905 scic_sds_phy_get_sas_address(phy, &phy_sas_address);
6f231dda
DW
1906
1907 if (
1908 (port_sas_address.high != phy_sas_address.high)
1909 || (port_sas_address.low != phy_sas_address.low)
1910 ) {
1911 return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
1912 }
1913 }
1914
d857d9a0 1915 return scic_sds_port_set_phy(port, phy);
6f231dda
DW
1916}
1917
41e2b905 1918/*
6f231dda
DW
1919 * This method takes the struct scic_sds_port that is in a stopped state and handles
1920 * the remove phy request. In MPC mode the only time a phy can be removed from
1921 * a port is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status
1922 * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not
1923 * be added to the port. SCI_SUCCESS if the phy is added to the port.
1924 */
1925static enum sci_status scic_sds_port_stopped_state_remove_phy_handler(
41e2b905 1926 struct scic_sds_port *port,
d857d9a0 1927 struct scic_sds_phy *phy)
6f231dda 1928{
d857d9a0 1929 return scic_sds_port_clear_phy(port, phy);
6f231dda
DW
1930}
1931
1932/*
1933 * ****************************************************************************
1934 * * READY STATE HANDLERS
1935 * **************************************************************************** */
1936
1937/*
1938 * ****************************************************************************
1939 * * RESETTING STATE HANDLERS
1940 * **************************************************************************** */
1941
1942/*
1943 * ****************************************************************************
1944 * * STOPPING STATE HANDLERS
1945 * **************************************************************************** */
1946
41e2b905 1947/*
6f231dda
DW
1948 * This method takes the struct scic_sds_port that is in a stopping state and handles
1949 * the complete io request. Should the request count reach 0 then the port
1950 * object will transition to the stopped state. enum sci_status SCI_SUCCESS
1951 */
1952static enum sci_status scic_sds_port_stopping_state_complete_io_handler(
068b2c03 1953 struct scic_sds_port *sci_port,
6f231dda
DW
1954 struct scic_sds_remote_device *device,
1955 struct scic_sds_request *io_request)
1956{
068b2c03 1957 scic_sds_port_decrement_request_count(sci_port);
6f231dda 1958
068b2c03 1959 if (sci_port->started_request_count == 0) {
41e2b905 1960 sci_base_state_machine_change_state(&sci_port->state_machine,
068b2c03 1961 SCI_BASE_PORT_STATE_STOPPED);
6f231dda
DW
1962 }
1963
1964 return SCI_SUCCESS;
1965}
1966
1967/*
1968 * ****************************************************************************
1969 * * RESETTING STATE HANDLERS
1970 * **************************************************************************** */
1971
1972/**
1973 *
1974 * @port: This is the port object which is being requested to stop.
1975 *
1976 * This method will stop a failed port. This causes a transition to the
1977 * stopping state. enum sci_status SCI_SUCCESS
1978 */
1979static enum sci_status scic_sds_port_reset_state_stop_handler(
41e2b905 1980 struct scic_sds_port *port)
6f231dda 1981{
6f231dda 1982 sci_base_state_machine_change_state(
41e2b905 1983 &port->state_machine,
6f231dda
DW
1984 SCI_BASE_PORT_STATE_STOPPING
1985 );
1986
1987 return SCI_SUCCESS;
1988}
1989
41e2b905 1990/*
6f231dda
DW
1991 * This method will transition a failed port to its ready state. The port
1992 * failed because a hard reset request timed out but at some time later one or
1993 * more phys in the port became ready. enum sci_status SCI_SUCCESS
1994 */
1995static void scic_sds_port_reset_state_link_up_handler(
41e2b905 1996 struct scic_sds_port *port,
6f231dda
DW
1997 struct scic_sds_phy *phy)
1998{
1999 /*
2000 * / @todo We should make sure that the phy that has gone link up is the same
2001 * / one on which we sent the reset. It is possible that the phy on
2002 * / which we sent the reset is not the one that has gone link up and we
2003 * / want to make sure that phy being reset comes back. Consider the
2004 * / case where a reset is sent but before the hardware processes the
2005 * / reset it get a link up on the port because of a hot plug event.
2006 * / because of the reset request this phy will go link down almost
2007 * / immediately. */
2008
2009 /*
2010 * In the resetting state we don't notify the user regarding
2011 * link up and link down notifications. */
41e2b905 2012 scic_sds_port_general_link_up_handler(port, phy, false);
6f231dda
DW
2013}
2014
41e2b905 2015/*
6f231dda
DW
2016 * This method process link down notifications that occur during a port reset
2017 * operation. Link downs can occur during the reset operation. enum sci_status
2018 * SCI_SUCCESS
2019 */
2020static void scic_sds_port_reset_state_link_down_handler(
41e2b905 2021 struct scic_sds_port *port,
6f231dda
DW
2022 struct scic_sds_phy *phy)
2023{
2024 /*
2025 * In the resetting state we don't notify the user regarding
2026 * link up and link down notifications. */
41e2b905 2027 scic_sds_port_deactivate_phy(port, phy, false);
6f231dda
DW
2028}
2029
35173d57 2030static struct scic_sds_port_state_handler
6f231dda
DW
2031scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] =
2032{
2033 /* SCI_BASE_PORT_STATE_STOPPED */
2034 {
41e2b905
MT
2035 scic_sds_port_stopped_state_start_handler,
2036 scic_sds_port_stopped_state_stop_handler,
2037 scic_sds_port_stopped_state_destruct_handler,
2038 scic_sds_port_default_reset_handler,
2039 scic_sds_port_stopped_state_add_phy_handler,
2040 scic_sds_port_stopped_state_remove_phy_handler,
6f231dda
DW
2041 scic_sds_port_default_frame_handler,
2042 scic_sds_port_default_event_handler,
2043 scic_sds_port_default_link_up_handler,
2044 scic_sds_port_default_link_down_handler,
2045 scic_sds_port_default_start_io_handler,
2046 scic_sds_port_default_complete_io_handler
2047 },
2048 /* SCI_BASE_PORT_STATE_STOPPING */
2049 {
41e2b905
MT
2050 scic_sds_port_default_start_handler,
2051 scic_sds_port_default_stop_handler,
2052 scic_sds_port_default_destruct_handler,
2053 scic_sds_port_default_reset_handler,
2054 scic_sds_port_default_add_phy_handler,
2055 scic_sds_port_default_remove_phy_handler,
6f231dda
DW
2056 scic_sds_port_default_frame_handler,
2057 scic_sds_port_default_event_handler,
2058 scic_sds_port_default_link_up_handler,
2059 scic_sds_port_default_link_down_handler,
2060 scic_sds_port_default_start_io_handler,
2061 scic_sds_port_stopping_state_complete_io_handler
2062 },
2063 /* SCI_BASE_PORT_STATE_READY */
2064 {
41e2b905
MT
2065 scic_sds_port_default_start_handler,
2066 scic_sds_port_default_stop_handler,
2067 scic_sds_port_default_destruct_handler,
2068 scic_sds_port_default_reset_handler,
2069 scic_sds_port_default_add_phy_handler,
2070 scic_sds_port_default_remove_phy_handler,
6f231dda
DW
2071 scic_sds_port_default_frame_handler,
2072 scic_sds_port_default_event_handler,
2073 scic_sds_port_default_link_up_handler,
2074 scic_sds_port_default_link_down_handler,
2075 scic_sds_port_default_start_io_handler,
2076 scic_sds_port_general_complete_io_handler
2077 },
2078 /* SCI_BASE_PORT_STATE_RESETTING */
2079 {
41e2b905
MT
2080 scic_sds_port_default_start_handler,
2081 scic_sds_port_reset_state_stop_handler,
2082 scic_sds_port_default_destruct_handler,
2083 scic_sds_port_default_reset_handler,
2084 scic_sds_port_default_add_phy_handler,
2085 scic_sds_port_default_remove_phy_handler,
6f231dda
DW
2086 scic_sds_port_default_frame_handler,
2087 scic_sds_port_default_event_handler,
2088 scic_sds_port_reset_state_link_up_handler,
2089 scic_sds_port_reset_state_link_down_handler,
2090 scic_sds_port_default_start_io_handler,
2091 scic_sds_port_general_complete_io_handler
2092 },
2093 /* SCI_BASE_PORT_STATE_FAILED */
2094 {
41e2b905
MT
2095 scic_sds_port_default_start_handler,
2096 scic_sds_port_default_stop_handler,
2097 scic_sds_port_default_destruct_handler,
2098 scic_sds_port_default_reset_handler,
2099 scic_sds_port_default_add_phy_handler,
2100 scic_sds_port_default_remove_phy_handler,
6f231dda
DW
2101 scic_sds_port_default_frame_handler,
2102 scic_sds_port_default_event_handler,
2103 scic_sds_port_default_link_up_handler,
2104 scic_sds_port_default_link_down_handler,
2105 scic_sds_port_default_start_io_handler,
2106 scic_sds_port_general_complete_io_handler
2107 }
2108};
2109
2110/*
2111 * ******************************************************************************
2112 * * PORT STATE PRIVATE METHODS
2113 * ****************************************************************************** */
2114
2115/**
2116 *
e2023b87 2117 * @sci_port: This is the port object which to suspend.
6f231dda
DW
2118 *
2119 * This method will enable the SCU Port Task Scheduler for this port object but
2120 * will leave the port task scheduler in a suspended state. none
2121 */
bc99aa47
CH
2122static void
2123scic_sds_port_enable_port_task_scheduler(struct scic_sds_port *port)
6f231dda
DW
2124{
2125 u32 pts_control_value;
2126
bc99aa47 2127 pts_control_value = readl(&port->port_task_scheduler_registers->control);
6f231dda 2128 pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND);
bc99aa47 2129 writel(pts_control_value, &port->port_task_scheduler_registers->control);
6f231dda
DW
2130}
2131
2132/**
2133 *
e2023b87 2134 * @sci_port: This is the port object which to resume.
6f231dda
DW
2135 *
2136 * This method will disable the SCU port task scheduler for this port object.
2137 * none
2138 */
bc99aa47
CH
2139static void
2140scic_sds_port_disable_port_task_scheduler(struct scic_sds_port *port)
6f231dda
DW
2141{
2142 u32 pts_control_value;
2143
bc99aa47
CH
2144 pts_control_value = readl(&port->port_task_scheduler_registers->control);
2145 pts_control_value &=
2146 ~(SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND));
2147 writel(pts_control_value, &port->port_task_scheduler_registers->control);
6f231dda
DW
2148}
2149
35173d57 2150static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port)
a8d4b9fe
TC
2151{
2152 struct scic_sds_controller *scic = sci_port->owning_controller;
2153 u8 phys_index = sci_port->physical_port_index;
2154 union scu_remote_node_context *rnc;
2155 u16 rni = sci_port->reserved_rni;
2156 u32 command;
2157
2158 rnc = &scic->remote_node_context_table[rni];
2159 rnc->ssp.is_valid = true;
2160
2161 command = SCU_CONTEXT_COMMAND_POST_RNC_32 |
2162 phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
2163
2164 scic_sds_controller_post_request(scic, command);
2165
2166 /* ensure hardware has seen the post rnc command and give it
2167 * ample time to act before sending the suspend
2168 */
bc99aa47 2169 readl(&scic->smu_registers->interrupt_status); /* flush */
a8d4b9fe
TC
2170 udelay(10);
2171
2172 command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX |
2173 phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
2174
2175 scic_sds_controller_post_request(scic, command);
2176}
2177
35173d57 2178static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port)
a8d4b9fe
TC
2179{
2180 struct scic_sds_controller *scic = sci_port->owning_controller;
2181 u8 phys_index = sci_port->physical_port_index;
2182 union scu_remote_node_context *rnc;
2183 u16 rni = sci_port->reserved_rni;
2184 u32 command;
2185
2186 rnc = &scic->remote_node_context_table[rni];
2187
2188 rnc->ssp.is_valid = false;
2189
27ce51df
DW
2190 /* ensure the preceding tc abort request has reached the
2191 * controller and give it ample time to act before posting the rnc
2192 * invalidate
2193 */
bc99aa47 2194 readl(&scic->smu_registers->interrupt_status); /* flush */
27ce51df
DW
2195 udelay(10);
2196
a8d4b9fe
TC
2197 command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE |
2198 phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
2199
2200 scic_sds_controller_post_request(scic, command);
2201}
2202
6f231dda
DW
2203/*
2204 * ******************************************************************************
2205 * * PORT STATE METHODS
2206 * ****************************************************************************** */
2207
2208/**
2209 *
9a0fff7b 2210 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda
DW
2211 *
2212 * This method will perform the actions required by the struct scic_sds_port on
2213 * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped
2214 * state handlers for the struct scic_sds_port object and disables the port task
2215 * scheduler in the hardware. none
2216 */
9a0fff7b 2217static void scic_sds_port_stopped_state_enter(void *object)
6f231dda 2218{
115bd1f9 2219 struct scic_sds_port *sci_port = object;
6f231dda
DW
2220
2221 scic_sds_port_set_base_state_handlers(
e2023b87 2222 sci_port, SCI_BASE_PORT_STATE_STOPPED
6f231dda
DW
2223 );
2224
2225 if (
2226 SCI_BASE_PORT_STATE_STOPPING
e2023b87 2227 == sci_port->state_machine.previous_state_id
6f231dda
DW
2228 ) {
2229 /*
2230 * If we enter this state becasuse of a request to stop
2231 * the port then we want to disable the hardwares port
2232 * task scheduler. */
e2023b87 2233 scic_sds_port_disable_port_task_scheduler(sci_port);
6f231dda
DW
2234 }
2235}
2236
2237/**
2238 *
9a0fff7b 2239 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda
DW
2240 *
2241 * This method will perform the actions required by the struct scic_sds_port on
2242 * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware
2243 * port task scheduler. none
2244 */
9a0fff7b 2245static void scic_sds_port_stopped_state_exit(void *object)
6f231dda 2246{
115bd1f9 2247 struct scic_sds_port *sci_port = object;
6f231dda
DW
2248
2249 /* Enable and suspend the port task scheduler */
e2023b87 2250 scic_sds_port_enable_port_task_scheduler(sci_port);
6f231dda
DW
2251}
2252
2253/**
068b2c03 2254 * scic_sds_port_ready_state_enter -
9a0fff7b 2255 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda
DW
2256 *
2257 * This method will perform the actions required by the struct scic_sds_port on
2258 * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state
09d7da13
DJ
2259 * handlers for the struct scic_sds_port object, reports the port object as
2260 * not ready and starts the ready substate machine. none
6f231dda 2261 */
9a0fff7b 2262static void scic_sds_port_ready_state_enter(void *object)
6f231dda 2263{
068b2c03 2264 struct scic_sds_controller *scic;
115bd1f9 2265 struct scic_sds_port *sci_port = object;
068b2c03
DW
2266 struct isci_port *iport;
2267 struct isci_host *ihost;
2268 u32 prev_state;
6f231dda 2269
068b2c03 2270 scic = scic_sds_port_get_controller(sci_port);
d3757c3a 2271 ihost = scic->ihost;
115bd1f9 2272 iport = sci_port->iport;
6f231dda 2273
068b2c03
DW
2274 /* Put the ready state handlers in place though they will not be there long */
2275 scic_sds_port_set_base_state_handlers(sci_port, SCI_BASE_PORT_STATE_READY);
2276
41e2b905 2277 prev_state = sci_port->state_machine.previous_state_id;
068b2c03 2278 if (prev_state == SCI_BASE_PORT_STATE_RESETTING)
09d7da13 2279 isci_port_hard_reset_complete(iport, SCI_SUCCESS);
068b2c03 2280 else
09d7da13 2281 isci_port_not_ready(ihost, iport);
6f231dda 2282
a8d4b9fe 2283 /* Post and suspend the dummy remote node context for this port. */
09d7da13 2284 scic_sds_port_post_dummy_remote_node(sci_port);
a8d4b9fe 2285
6f231dda 2286 /* Start the ready substate machine */
068b2c03 2287 sci_base_state_machine_start(&sci_port->ready_substate_machine);
6f231dda
DW
2288}
2289
9a0fff7b 2290static void scic_sds_port_ready_state_exit(void *object)
6f231dda 2291{
115bd1f9 2292 struct scic_sds_port *sci_port = object;
a8d4b9fe 2293
068b2c03
DW
2294 sci_base_state_machine_stop(&sci_port->ready_substate_machine);
2295 scic_sds_port_invalidate_dummy_remote_node(sci_port);
6f231dda
DW
2296}
2297
2298/**
2299 *
9a0fff7b 2300 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda
DW
2301 *
2302 * This method will perform the actions required by the struct scic_sds_port on
2303 * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the resetting
2304 * state handlers for the struct scic_sds_port object. none
2305 */
9a0fff7b 2306static void scic_sds_port_resetting_state_enter(void *object)
6f231dda 2307{
115bd1f9 2308 struct scic_sds_port *sci_port = object;
6f231dda
DW
2309
2310 scic_sds_port_set_base_state_handlers(
e2023b87 2311 sci_port, SCI_BASE_PORT_STATE_RESETTING
6f231dda 2312 );
6f231dda
DW
2313}
2314
2315/**
2316 *
9a0fff7b 2317 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda 2318 *
09d7da13
DJ
2319 * This function will perform the actions required by the
2320 * struct scic_sds_port on
6f231dda
DW
2321 * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. none
2322 */
9a0fff7b 2323static inline void scic_sds_port_resetting_state_exit(void *object)
6f231dda 2324{
115bd1f9 2325 struct scic_sds_port *sci_port = object;
6f231dda 2326
09d7da13 2327 isci_timer_stop(sci_port->timer_handle);
6f231dda
DW
2328}
2329
2330/**
2331 *
9a0fff7b
MP
2332 * @object: This is the void object which is cast to a
2333 * struct scic_sds_port object.
6f231dda
DW
2334 *
2335 * This method will perform the actions required by the struct scic_sds_port on
2336 * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping
2337 * state handlers for the struct scic_sds_port object. none
2338 */
9a0fff7b 2339static void scic_sds_port_stopping_state_enter(void *object)
6f231dda 2340{
115bd1f9 2341 struct scic_sds_port *sci_port = object;
6f231dda
DW
2342
2343 scic_sds_port_set_base_state_handlers(
e2023b87 2344 sci_port, SCI_BASE_PORT_STATE_STOPPING
6f231dda
DW
2345 );
2346}
2347
2348/**
2349 *
9a0fff7b 2350 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda 2351 *
09d7da13
DJ
2352 * This function will perform the actions required by the
2353 * struct scic_sds_port on
6f231dda
DW
2354 * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. none
2355 */
09d7da13 2356static inline void
9a0fff7b 2357scic_sds_port_stopping_state_exit(void *object)
6f231dda 2358{
115bd1f9 2359 struct scic_sds_port *sci_port = object;
6f231dda 2360
09d7da13 2361 isci_timer_stop(sci_port->timer_handle);
a8d4b9fe 2362
09d7da13 2363 scic_sds_port_destroy_dummy_resources(sci_port);
6f231dda
DW
2364}
2365
2366/**
2367 *
9a0fff7b 2368 * @object: This is the object which is cast to a struct scic_sds_port object.
6f231dda 2369 *
09d7da13
DJ
2370 * This function will perform the actions required by the
2371 * struct scic_sds_port on
6f231dda
DW
2372 * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping
2373 * state handlers for the struct scic_sds_port object. none
2374 */
9a0fff7b 2375static void scic_sds_port_failed_state_enter(void *object)
6f231dda 2376{
115bd1f9
MP
2377 struct scic_sds_port *sci_port = object;
2378 struct isci_port *iport = sci_port->iport;
6f231dda 2379
09d7da13
DJ
2380 scic_sds_port_set_base_state_handlers(sci_port,
2381 SCI_BASE_PORT_STATE_FAILED);
6f231dda 2382
09d7da13 2383 isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT);
6f231dda
DW
2384}
2385
2386/* --------------------------------------------------------------------------- */
2387
35173d57 2388static const struct sci_base_state scic_sds_port_state_table[] = {
6f231dda
DW
2389 [SCI_BASE_PORT_STATE_STOPPED] = {
2390 .enter_state = scic_sds_port_stopped_state_enter,
2391 .exit_state = scic_sds_port_stopped_state_exit
2392 },
2393 [SCI_BASE_PORT_STATE_STOPPING] = {
2394 .enter_state = scic_sds_port_stopping_state_enter,
2395 .exit_state = scic_sds_port_stopping_state_exit
2396 },
2397 [SCI_BASE_PORT_STATE_READY] = {
2398 .enter_state = scic_sds_port_ready_state_enter,
2399 .exit_state = scic_sds_port_ready_state_exit
2400 },
2401 [SCI_BASE_PORT_STATE_RESETTING] = {
2402 .enter_state = scic_sds_port_resetting_state_enter,
2403 .exit_state = scic_sds_port_resetting_state_exit
2404 },
2405 [SCI_BASE_PORT_STATE_FAILED] = {
2406 .enter_state = scic_sds_port_failed_state_enter,
2407 }
2408};
2409
35173d57
DW
2410void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index,
2411 struct scic_sds_controller *scic)
2412{
2413 u32 index;
2414
41e2b905 2415 sci_base_state_machine_construct(&sci_port->state_machine,
115bd1f9 2416 sci_port,
41e2b905
MT
2417 scic_sds_port_state_table,
2418 SCI_BASE_PORT_STATE_STOPPED);
2419
2420 sci_base_state_machine_start(&sci_port->state_machine);
35173d57
DW
2421
2422 sci_base_state_machine_construct(&sci_port->ready_substate_machine,
115bd1f9 2423 sci_port,
35173d57
DW
2424 scic_sds_port_ready_substate_table,
2425 SCIC_SDS_PORT_READY_SUBSTATE_WAITING);
2426
2427 sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT;
2428 sci_port->physical_port_index = port_index;
2429 sci_port->active_phy_mask = 0;
2430
2431 sci_port->owning_controller = scic;
2432
2433 sci_port->started_request_count = 0;
2434 sci_port->assigned_device_count = 0;
2435
2436 sci_port->reserved_rni = SCU_DUMMY_INDEX;
2437 sci_port->reserved_tci = SCU_DUMMY_INDEX;
2438
2439 sci_port->timer_handle = NULL;
2440
2441 sci_port->port_task_scheduler_registers = NULL;
2442
2443 for (index = 0; index < SCI_MAX_PHYS; index++)
2444 sci_port->phy_table[index] = NULL;
2445}
This page took 0.146078 seconds and 5 git commands to generate.