blob: 1af38505840cbeb71193fef250768f2ad2897b4f [file] [log] [blame]
Dan Williams6f231dd2011-07-02 22:56:22 -07001/*
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
56#include "intel_sas.h"
57#include "sci_base_port.h"
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"
63#include "scic_sds_phy_registers.h"
64#include "scic_sds_port.h"
65#include "scic_sds_port_registers.h"
66#include "scic_sds_remote_device.h"
67#include "scic_sds_remote_node_context.h"
68#include "scic_sds_request.h"
69#include "scic_user_callback.h"
70#include "sci_environment.h"
71
72
73static void scic_sds_port_invalid_link_up(
74 struct scic_sds_port *this_port,
75 struct scic_sds_phy *phy);
76static void scic_sds_port_timeout_handler(
77 void *port);
78#define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS)
79#define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS)
80
81#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000)
82
83void sci_base_port_construct(
84 struct sci_base_port *base_port,
85 const struct sci_base_state *state_table)
86{
87 base_port->parent.private = NULL;
88 sci_base_state_machine_construct(
89 &base_port->state_machine,
90 &base_port->parent,
91 state_table,
92 SCI_BASE_PORT_STATE_STOPPED
93 );
94
95 sci_base_state_machine_start(
96 &base_port->state_machine
97 );
98}
99
100/**
101 *
102 * @this_port: This is the port object to which the phy is being assigned.
103 * @phy_index: This is the phy index that is being assigned to the port.
104 *
105 * This method will return a true value if the specified phy can be assigned to
106 * this port The following is a list of phys for each port that are allowed: -
107 * Port 0 - 3 2 1 0 - Port 1 - 1 - Port 2 - 3 2 - Port 3 - 3 This method
108 * doesn't preclude all configurations. It merely ensures that a phy is part
109 * of the allowable set of phy identifiers for that port. For example, one
110 * could assign phy 3 to port 0 and no other phys. Please refer to
111 * scic_sds_port_is_phy_mask_valid() for information regarding whether the
112 * phy_mask for a port can be supported. bool true if this is a valid phy
113 * assignment for the port false if this is not a valid phy assignment for the
114 * port
115 */
116bool scic_sds_port_is_valid_phy_assignment(
117 struct scic_sds_port *this_port,
118 u32 phy_index)
119{
120 /* Initialize to invalid value. */
121 u32 existing_phy_index = SCI_MAX_PHYS;
122 u32 index;
123
124 if ((this_port->physical_port_index == 1) && (phy_index != 1)) {
125 return false;
126 }
127
128 if (this_port->physical_port_index == 3 && phy_index != 3) {
129 return false;
130 }
131
132 if (
133 (this_port->physical_port_index == 2)
134 && ((phy_index == 0) || (phy_index == 1))
135 ) {
136 return false;
137 }
138
139 for (index = 0; index < SCI_MAX_PHYS; index++) {
140 if ((this_port->phy_table[index] != NULL)
141 && (index != phy_index)) {
142 existing_phy_index = index;
143 }
144 }
145
146 /*
147 * Ensure that all of the phys in the port are capable of
148 * operating at the same maximum link rate. */
149 if (
150 (existing_phy_index < SCI_MAX_PHYS)
151 && (this_port->owning_controller->user_parameters.sds1.phys[
152 phy_index].max_speed_generation !=
153 this_port->owning_controller->user_parameters.sds1.phys[
154 existing_phy_index].max_speed_generation)
155 )
156 return false;
157
158 return true;
159}
160
161/**
162 * This method requests a list (mask) of the phys contained in the supplied SAS
163 * port.
164 * @this_port: a handle corresponding to the SAS port for which to return the
165 * phy mask.
166 *
167 * Return a bit mask indicating which phys are a part of this port. Each bit
168 * corresponds to a phy identifier (e.g. bit 0 = phy id 0).
169 */
170u32 scic_sds_port_get_phys(struct scic_sds_port *this_port)
171{
172 u32 index;
173 u32 mask;
174
175 mask = 0;
176
177 for (index = 0; index < SCI_MAX_PHYS; index++) {
178 if (this_port->phy_table[index] != NULL) {
179 mask |= (1 << index);
180 }
181 }
182
183 return mask;
184}
185
186/**
187 *
188 * @this_port: This is the port object for which to determine if the phy mask
189 * can be supported.
190 *
191 * This method will return a true value if the port's phy mask can be supported
192 * by the SCU. The following is a list of valid PHY mask configurations for
193 * each port: - Port 0 - [[3 2] 1] 0 - Port 1 - [1] - Port 2 - [[3] 2]
194 * - Port 3 - [3] This method returns a boolean indication specifying if the
195 * phy mask can be supported. true if this is a valid phy assignment for the
196 * port false if this is not a valid phy assignment for the port
197 */
198bool scic_sds_port_is_phy_mask_valid(
199 struct scic_sds_port *this_port,
200 u32 phy_mask)
201{
202 if (this_port->physical_port_index == 0) {
203 if (((phy_mask & 0x0F) == 0x0F)
204 || ((phy_mask & 0x03) == 0x03)
205 || ((phy_mask & 0x01) == 0x01)
206 || (phy_mask == 0))
207 return true;
208 } else if (this_port->physical_port_index == 1) {
209 if (((phy_mask & 0x02) == 0x02)
210 || (phy_mask == 0))
211 return true;
212 } else if (this_port->physical_port_index == 2) {
213 if (((phy_mask & 0x0C) == 0x0C)
214 || ((phy_mask & 0x04) == 0x04)
215 || (phy_mask == 0))
216 return true;
217 } else if (this_port->physical_port_index == 3) {
218 if (((phy_mask & 0x08) == 0x08)
219 || (phy_mask == 0))
220 return true;
221 }
222
223 return false;
224}
225
226/**
227 *
228 * @this_port: This parameter specifies the port from which to return a
229 * connected phy.
230 *
231 * This method retrieves a currently active (i.e. connected) phy contained in
232 * the port. Currently, the lowest order phy that is connected is returned.
233 * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is
234 * returned if there are no currently active (i.e. connected to a remote end
235 * point) phys contained in the port. All other values specify a struct scic_sds_phy
236 * object that is active in the port.
237 */
238static struct scic_sds_phy *scic_sds_port_get_a_connected_phy(
239 struct scic_sds_port *this_port
240 ) {
241 u32 index;
242 struct scic_sds_phy *phy;
243
244 for (index = 0; index < SCI_MAX_PHYS; index++) {
245 /*
246 * Ensure that the phy is both part of the port and currently
247 * connected to the remote end-point. */
248 phy = this_port->phy_table[index];
249 if (
250 (phy != NULL)
251 && scic_sds_port_active_phy(this_port, phy)
252 ) {
253 return phy;
254 }
255 }
256
257 return NULL;
258}
259
260/**
261 * scic_sds_port_set_phy() -
262 * @out]: port The port object to which the phy assignement is being made.
263 * @out]: phy The phy which is being assigned to the port.
264 *
265 * This method attempts to make the assignment of the phy to the port. If
266 * successful the phy is assigned to the ports phy table. bool true if the phy
267 * assignment can be made. false if the phy assignement can not be made. This
268 * is a functional test that only fails if the phy is currently assigned to a
269 * different port.
270 */
271enum sci_status scic_sds_port_set_phy(
272 struct scic_sds_port *port,
273 struct scic_sds_phy *phy)
274{
275 /*
276 * Check to see if we can add this phy to a port
277 * that means that the phy is not part of a port and that the port does
278 * not already have a phy assinged to the phy index. */
279 if (
280 (port->phy_table[phy->phy_index] == SCI_INVALID_HANDLE)
281 && (scic_sds_phy_get_port(phy) == SCI_INVALID_HANDLE)
282 && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)
283 ) {
284 /*
285 * Phy is being added in the stopped state so we are in MPC mode
286 * make logical port index = physical port index */
287 port->logical_port_index = port->physical_port_index;
288 port->phy_table[phy->phy_index] = phy;
289 scic_sds_phy_set_port(phy, port);
290
291 return SCI_SUCCESS;
292 }
293
294 return SCI_FAILURE;
295}
296
297/**
298 * scic_sds_port_clear_phy() -
299 * @out]: port The port from which the phy is being cleared.
300 * @out]: phy The phy being cleared from the port.
301 *
302 * This method will clear the phy assigned to this port. This method fails if
303 * this phy is not currently assinged to this port. bool true if the phy is
304 * removed from the port. false if this phy is not assined to this port.
305 */
306enum sci_status scic_sds_port_clear_phy(
307 struct scic_sds_port *port,
308 struct scic_sds_phy *phy)
309{
310 /* Make sure that this phy is part of this port */
311 if (
312 (port->phy_table[phy->phy_index] == phy)
313 && (scic_sds_phy_get_port(phy) == port)
314 ) {
315 /* Yep it is assigned to this port so remove it */
316 scic_sds_phy_set_port(
317 phy,
318 &scic_sds_port_get_controller(port)->port_table[SCI_MAX_PORTS]
319 );
320
321 port->phy_table[phy->phy_index] = SCI_INVALID_HANDLE;
322
323 return SCI_SUCCESS;
324 }
325
326 return SCI_FAILURE;
327}
328
329/**
330 * scic_sds_port_add_phy() -
331 * @this_port: This parameter specifies the port in which the phy will be added.
332 * @the_phy: This parameter is the phy which is to be added to the port.
333 *
334 * This method will add a PHY to the selected port. This method returns an
335 * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other status
336 * is failre to add the phy to the port.
337 */
338enum sci_status scic_sds_port_add_phy(
339 struct scic_sds_port *this_port,
340 struct scic_sds_phy *the_phy)
341{
342 return this_port->state_handlers->parent.add_phy_handler(
343 &this_port->parent, &the_phy->parent);
344}
345
346
347/**
348 * scic_sds_port_remove_phy() -
349 * @this_port: This parameter specifies the port in which the phy will be added.
350 * @the_phy: This parameter is the phy which is to be added to the port.
351 *
352 * This method will remove the PHY from the selected PORT. This method returns
353 * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any other
354 * status is failre to add the phy to the port.
355 */
356enum sci_status scic_sds_port_remove_phy(
357 struct scic_sds_port *this_port,
358 struct scic_sds_phy *the_phy)
359{
360 return this_port->state_handlers->parent.remove_phy_handler(
361 &this_port->parent, &the_phy->parent);
362}
363
364/**
365 * This method requests the SAS address for the supplied SAS port from the SCI
366 * implementation.
367 * @this_port: a handle corresponding to the SAS port for which to return the
368 * SAS address.
369 * @sas_address: This parameter specifies a pointer to a SAS address structure
370 * into which the core will copy the SAS address for the port.
371 *
372 */
373void scic_sds_port_get_sas_address(
374 struct scic_sds_port *this_port,
375 struct sci_sas_address *sas_address)
376{
377 u32 index;
378
379 sas_address->high = 0;
380 sas_address->low = 0;
381
382 for (index = 0; index < SCI_MAX_PHYS; index++) {
383 if (this_port->phy_table[index] != NULL) {
384 scic_sds_phy_get_sas_address(this_port->phy_table[index], sas_address);
385 }
386 }
387}
388
389/**
390 * This method will indicate which protocols are supported by this port.
391 * @this_port: a handle corresponding to the SAS port for which to return the
392 * supported protocols.
393 * @protocols: This parameter specifies a pointer to an IAF protocol field
394 * structure into which the core will copy the protocol values for the port.
395 * The values are returned as part of a bit mask in order to allow for
396 * multi-protocol support.
397 *
398 */
399static void scic_sds_port_get_protocols(
400 struct scic_sds_port *this_port,
401 struct sci_sas_identify_address_frame_protocols *protocols)
402{
403 u8 index;
404
405 protocols->u.all = 0;
406
407 for (index = 0; index < SCI_MAX_PHYS; index++) {
408 if (this_port->phy_table[index] != NULL) {
409 scic_sds_phy_get_protocols(this_port->phy_table[index], protocols);
410 }
411 }
412}
413
414/**
415 * This method requests the SAS address for the device directly attached to
416 * this SAS port.
417 * @this_port: a handle corresponding to the SAS port for which to return the
418 * SAS address.
419 * @sas_address: This parameter specifies a pointer to a SAS address structure
420 * into which the core will copy the SAS address for the device directly
421 * attached to the port.
422 *
423 */
424void scic_sds_port_get_attached_sas_address(
425 struct scic_sds_port *this_port,
426 struct sci_sas_address *sas_address)
427{
428 struct sci_sas_identify_address_frame_protocols protocols;
429 struct scic_sds_phy *phy;
430
431 /*
432 * Ensure that the phy is both part of the port and currently
433 * connected to the remote end-point. */
434 phy = scic_sds_port_get_a_connected_phy(this_port);
435 if (phy != NULL) {
436 scic_sds_phy_get_attached_phy_protocols(phy, &protocols);
437
438 if (!protocols.u.bits.stp_target) {
439 scic_sds_phy_get_attached_sas_address(phy, sas_address);
440 } else {
441 scic_sds_phy_get_sas_address(phy, sas_address);
442 sas_address->low += phy->phy_index;
443 }
444 } else {
445 sas_address->high = 0;
446 sas_address->low = 0;
447 }
448}
449
450/**
451 * This method will indicate which protocols are supported by this remote
452 * device.
453 * @this_port: a handle corresponding to the SAS port for which to return the
454 * supported protocols.
455 * @protocols: This parameter specifies a pointer to an IAF protocol field
456 * structure into which the core will copy the protocol values for the port.
457 * The values are returned as part of a bit mask in order to allow for
458 * multi-protocol support.
459 *
460 */
461void scic_sds_port_get_attached_protocols(
462 struct scic_sds_port *this_port,
463 struct sci_sas_identify_address_frame_protocols *protocols)
464{
465 struct scic_sds_phy *phy;
466
467 /*
468 * Ensure that the phy is both part of the port and currently
469 * connected to the remote end-point. */
470 phy = scic_sds_port_get_a_connected_phy(this_port);
471 if (phy != NULL)
472 scic_sds_phy_get_attached_phy_protocols(phy, protocols);
473 else
474 protocols->u.all = 0;
475}
476
477/**
478 * This method returns the amount of memory requred for a port object.
479 *
480 * u32
481 */
482
483/**
484 * This method returns the minimum number of timers required for all port
485 * objects.
486 *
487 * u32
488 */
489
490/**
491 * This method returns the maximum number of timers required for all port
492 * objects.
493 *
494 * u32
495 */
496
497/**
498 *
499 * @this_port:
500 * @port_index:
501 *
502 *
503 */
504void scic_sds_port_construct(
505 struct scic_sds_port *this_port,
506 u8 port_index,
507 struct scic_sds_controller *owning_controller)
508{
509 u32 index;
510
511 sci_base_port_construct(
512 &this_port->parent,
513 scic_sds_port_state_table
514 );
515
516 sci_base_state_machine_construct(
517 scic_sds_port_get_ready_substate_machine(this_port),
518 &this_port->parent.parent,
519 scic_sds_port_ready_substate_table,
520 SCIC_SDS_PORT_READY_SUBSTATE_WAITING
521 );
522
523 this_port->logical_port_index = SCIC_SDS_DUMMY_PORT;
524 this_port->physical_port_index = port_index;
525 this_port->active_phy_mask = 0;
526
527 this_port->owning_controller = owning_controller;
528
529 this_port->started_request_count = 0;
530 this_port->assigned_device_count = 0;
531
532 this_port->timer_handle = SCI_INVALID_HANDLE;
533
534 this_port->transport_layer_registers = NULL;
535 this_port->port_task_scheduler_registers = NULL;
536
537 for (index = 0; index < SCI_MAX_PHYS; index++) {
538 this_port->phy_table[index] = NULL;
539 }
540}
541
542/**
543 * This method performs initialization of the supplied port. Initialization
544 * includes: - state machine initialization - member variable initialization
545 * - configuring the phy_mask
546 * @this_port:
547 * @transport_layer_registers:
548 * @port_task_scheduler_registers:
549 * @port_configuration_regsiter:
550 *
551 * enum sci_status SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is returned
552 * if the phy being added to the port
553 */
554enum sci_status scic_sds_port_initialize(
555 struct scic_sds_port *this_port,
556 void *transport_layer_registers,
557 void *port_task_scheduler_registers,
558 void *port_configuration_regsiter,
559 void *viit_registers)
560{
561 u32 tl_control;
562
563 this_port->transport_layer_registers = transport_layer_registers;
564 this_port->port_task_scheduler_registers = port_task_scheduler_registers;
565 this_port->port_pe_configuration_register = port_configuration_regsiter;
566 this_port->viit_registers = viit_registers;
567
568 scic_sds_port_set_direct_attached_device_id(
569 this_port,
570 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
571 );
572
573 /*
574 * Hardware team recommends that we enable the STP prefetch
575 * for all ports */
576 tl_control = SCU_TLCR_READ(this_port);
577 tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH);
578 SCU_TLCR_WRITE(this_port, tl_control);
579
580 /*
581 * If this is not the dummy port make the assignment of
582 * the timer and start the state machine */
583 if (this_port->physical_port_index != SCI_MAX_PORTS) {
584 /* / @todo should we create the timer at create time? */
585 this_port->timer_handle = scic_cb_timer_create(
586 scic_sds_port_get_controller(this_port),
587 scic_sds_port_timeout_handler,
588 this_port
589 );
590
591 } else {
592 /*
593 * Force the dummy port into a condition where it rejects all requests
594 * as its in an invalid state for any operation.
595 * / @todo should we set a set of specical handlers for the dummy port? */
596 scic_sds_port_set_base_state_handlers(
597 this_port, SCI_BASE_PORT_STATE_STOPPED
598 );
599 }
600
601 return SCI_SUCCESS;
602}
603
604/**
605 *
606 * @this_port: This is the struct scic_sds_port object for which has a phy that has
607 * gone link up.
608 * @the_phy: This is the struct scic_sds_phy object that has gone link up.
609 * @do_notify_user: This parameter specifies whether to inform the user (via
610 * scic_cb_port_link_up()) as to the fact that a new phy as become ready.
611 *
612 * This method is the a general link up handler for the struct scic_sds_port object.
613 * This function will determine if this struct scic_sds_phy can be assigned to this
614 * struct scic_sds_port object. If the struct scic_sds_phy object can is not a valid PHY for
615 * this port then the function will notify the SCIC_USER. A PHY can only be
616 * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in
617 * the same port. none
618 */
619void scic_sds_port_general_link_up_handler(
620 struct scic_sds_port *this_port,
621 struct scic_sds_phy *the_phy,
622 bool do_notify_user)
623{
624 struct sci_sas_address port_sas_address;
625 struct sci_sas_address phy_sas_address;
626
627 scic_sds_port_get_attached_sas_address(this_port, &port_sas_address);
628 scic_sds_phy_get_attached_sas_address(the_phy, &phy_sas_address);
629
630 /*
631 * If the SAS address of the new phy matches the SAS address of
632 * other phys in the port OR this is the first phy in the port,
633 * then activate the phy and allow it to be used for operations
634 * in this port. */
635 if (
636 (
637 (phy_sas_address.high == port_sas_address.high)
638 && (phy_sas_address.low == port_sas_address.low)
639 )
640 || (this_port->active_phy_mask == 0)
641 ) {
642 scic_sds_port_activate_phy(this_port, the_phy, do_notify_user);
643
644 if (this_port->parent.state_machine.current_state_id
645 == SCI_BASE_PORT_STATE_RESETTING) {
646 sci_base_state_machine_change_state(
647 &this_port->parent.state_machine, SCI_BASE_PORT_STATE_READY
648 );
649 }
650 } else {
651 scic_sds_port_invalid_link_up(this_port, the_phy);
652 }
653}
654
655
656enum sci_status scic_port_start(struct scic_sds_port *port)
657{
658 return port->state_handlers->parent.start_handler(&port->parent);
659}
660
661
662enum sci_status scic_port_stop(struct scic_sds_port *port)
663{
664 return port->state_handlers->parent.stop_handler(&port->parent);
665}
666
667
668enum sci_status scic_port_get_properties(
669 struct scic_sds_port *port,
670 struct scic_port_properties *prop)
671{
672 if ((port == SCI_INVALID_HANDLE) ||
673 (port->logical_port_index == SCIC_SDS_DUMMY_PORT))
674 return SCI_FAILURE_INVALID_PORT;
675
676 prop->index = port->logical_port_index;
677 prop->phy_mask = scic_sds_port_get_phys(port);
678 scic_sds_port_get_sas_address(port, &prop->local.sas_address);
679 scic_sds_port_get_protocols(port, &prop->local.protocols);
680 scic_sds_port_get_attached_sas_address(port, &prop->remote.sas_address);
681 scic_sds_port_get_attached_protocols(port, &prop->remote.protocols);
682
683 return SCI_SUCCESS;
684}
685
686
687enum sci_status scic_port_hard_reset(
688 struct scic_sds_port *port,
689 u32 reset_timeout)
690{
691 return port->state_handlers->parent.reset_handler(
692 &port->parent, reset_timeout);
693}
694
695/**
696 *
697 * @this_port: The port for which the direct attached device id is to be
698 * assigned.
699 *
700 * This method assigns the direct attached device ID for this port.
701 */
702void scic_sds_port_set_direct_attached_device_id(
703 struct scic_sds_port *this_port,
704 u32 device_id)
705{
706 u32 tl_control;
707
708 SCU_STPTLDARNI_WRITE(this_port, device_id);
709
710 /*
711 * The read should guarntee that the first write gets posted
712 * before the next write */
713 tl_control = SCU_TLCR_READ(this_port);
714 tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
715 SCU_TLCR_WRITE(this_port, tl_control);
716}
717
718
719/**
720 *
721 * @this_port: This is the port on which the phy should be enabled.
722 * @the_phy: This is the specific phy which to enable.
723 * @do_notify_user: This parameter specifies whether to inform the user (via
724 * scic_cb_port_link_up()) as to the fact that a new phy as become ready.
725 *
726 * This method will activate the phy in the port. Activation includes: - adding
727 * the phy to the port - enabling the Protocol Engine in the silicon. -
728 * notifying the user that the link is up. none
729 */
730void scic_sds_port_activate_phy(
731 struct scic_sds_port *this_port,
732 struct scic_sds_phy *the_phy,
733 bool do_notify_user)
734{
735 struct scic_sds_controller *controller;
736 struct sci_sas_identify_address_frame_protocols protocols;
737
738 controller = scic_sds_port_get_controller(this_port);
739 scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols);
740
741 /* If this is sata port then the phy has already been resumed */
742 if (!protocols.u.bits.stp_target) {
743 scic_sds_phy_resume(the_phy);
744 }
745
746 this_port->active_phy_mask |= 1 << the_phy->phy_index;
747
748 scic_sds_controller_clear_invalid_phy(controller, the_phy);
749
750 if (do_notify_user == true)
751 scic_cb_port_link_up(this_port->owning_controller, this_port, the_phy);
752}
753
754/**
755 *
756 * @this_port: This is the port on which the phy should be deactivated.
757 * @the_phy: This is the specific phy that is no longer active in the port.
758 * @do_notify_user: This parameter specifies whether to inform the user (via
759 * scic_cb_port_link_down()) as to the fact that a new phy as become ready.
760 *
761 * This method will deactivate the supplied phy in the port. none
762 */
763void scic_sds_port_deactivate_phy(
764 struct scic_sds_port *this_port,
765 struct scic_sds_phy *the_phy,
766 bool do_notify_user)
767{
768 this_port->active_phy_mask &= ~(1 << the_phy->phy_index);
769
770 the_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE;
771
772 /* Re-assign the phy back to the LP as if it were a narrow port */
773 SCU_PCSPExCR_WRITE(this_port, the_phy->phy_index, the_phy->phy_index);
774
775 if (do_notify_user == true)
776 scic_cb_port_link_down(this_port->owning_controller, this_port, the_phy);
777}
778
779/**
780 *
781 * @this_port: This is the port on which the phy should be disabled.
782 * @the_phy: This is the specific phy which to disabled.
783 *
784 * This method will disable the phy and report that the phy is not valid for
785 * this port object. None
786 */
787static void scic_sds_port_invalid_link_up(
788 struct scic_sds_port *this_port,
789 struct scic_sds_phy *the_phy)
790{
791 struct scic_sds_controller *controller = scic_sds_port_get_controller(this_port);
792
793 /*
794 * Check to see if we have alreay reported this link as bad and if not go
795 * ahead and tell the SCI_USER that we have discovered an invalid link. */
796 if ((controller->invalid_phy_mask & (1 << the_phy->phy_index)) == 0) {
797 scic_sds_controller_set_invalid_phy(controller, the_phy);
798
799 scic_cb_port_invalid_link_up(controller, this_port, the_phy);
800 }
801}
802
803/**
804 * This method returns false if the port only has a single phy object assigned.
805 * If there are no phys or more than one phy then the method will return
806 * true.
807 * @this_port: The port for which the wide port condition is to be checked.
808 *
809 * bool true Is returned if this is a wide ported port. false Is returned if
810 * this is a narrow port.
811 */
812static bool scic_sds_port_is_wide(struct scic_sds_port *this_port)
813{
814 u32 index;
815 u32 phy_count = 0;
816
817 for (index = 0; index < SCI_MAX_PHYS; index++) {
818 if (this_port->phy_table[index] != NULL) {
819 phy_count++;
820 }
821 }
822
823 return phy_count != 1;
824}
825
826/**
827 * This method is called by the PHY object when the link is detected. if the
828 * port wants the PHY to continue on to the link up state then the port
829 * layer must return true. If the port object returns false the phy object
830 * must halt its attempt to go link up.
831 * @this_port: The port associated with the phy object.
832 * @the_phy: The phy object that is trying to go link up.
833 *
834 * true if the phy object can continue to the link up condition. true Is
835 * returned if this phy can continue to the ready state. false Is returned if
836 * can not continue on to the ready state. This notification is in place for
837 * wide ports and direct attached phys. Since there are no wide ported SATA
838 * devices this could become an invalid port configuration.
839 */
840bool scic_sds_port_link_detected(
841 struct scic_sds_port *this_port,
842 struct scic_sds_phy *the_phy)
843{
844 struct sci_sas_identify_address_frame_protocols protocols;
845
846 scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols);
847
848 if (
849 (this_port->logical_port_index != SCIC_SDS_DUMMY_PORT)
850 && (protocols.u.bits.stp_target)
851 && scic_sds_port_is_wide(this_port)
852 ) {
853 scic_sds_port_invalid_link_up(this_port, the_phy);
854
855 return false;
856 }
857
858 return true;
859}
860
861/**
862 * This method is the entry point for the phy to inform the port that it is now
863 * in a ready state
864 * @this_port:
865 *
866 *
867 */
868void scic_sds_port_link_up(
869 struct scic_sds_port *this_port,
870 struct scic_sds_phy *the_phy)
871{
872 the_phy->is_in_link_training = false;
873
874 this_port->state_handlers->link_up_handler(this_port, the_phy);
875}
876
877/**
878 * This method is the entry point for the phy to inform the port that it is no
879 * longer in a ready state
880 * @this_port:
881 *
882 *
883 */
884void scic_sds_port_link_down(
885 struct scic_sds_port *this_port,
886 struct scic_sds_phy *the_phy)
887{
888 this_port->state_handlers->link_down_handler(this_port, the_phy);
889}
890
891/**
892 * This method is called to start an IO request on this port.
893 * @this_port:
894 * @the_device:
895 * @the_io_request:
896 *
897 * enum sci_status
898 */
899enum sci_status scic_sds_port_start_io(
900 struct scic_sds_port *this_port,
901 struct scic_sds_remote_device *the_device,
902 struct scic_sds_request *the_io_request)
903{
904 return this_port->state_handlers->start_io_handler(
905 this_port, the_device, the_io_request);
906}
907
908/**
909 * This method is called to complete an IO request to the port.
910 * @this_port:
911 * @the_device:
912 * @the_io_request:
913 *
914 * enum sci_status
915 */
916enum sci_status scic_sds_port_complete_io(
917 struct scic_sds_port *this_port,
918 struct scic_sds_remote_device *the_device,
919 struct scic_sds_request *the_io_request)
920{
921 return this_port->state_handlers->complete_io_handler(
922 this_port, the_device, the_io_request);
923}
924
925/**
926 * This method is provided to timeout requests for port operations. Mostly its
927 * for the port reset operation.
928 *
929 *
930 */
931static void scic_sds_port_timeout_handler(void *port)
932{
933 struct scic_sds_port *this_port = port;
934 u32 current_state;
935
936 current_state = sci_base_state_machine_get_state(
937 &this_port->parent.state_machine);
938
939 if (current_state == SCI_BASE_PORT_STATE_RESETTING) {
940 /*
941 * if the port is still in the resetting state then the timeout fired
942 * before the reset completed. */
943 sci_base_state_machine_change_state(
944 &this_port->parent.state_machine,
945 SCI_BASE_PORT_STATE_FAILED
946 );
947 } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) {
948 /*
949 * if the port is stopped then the start request failed
950 * In this case stay in the stopped state. */
951 dev_err(sciport_to_dev(this_port),
952 "%s: SCIC Port 0x%p failed to stop before tiemout.\n",
953 __func__,
954 this_port);
955 } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) {
956 /* if the port is still stopping then the stop has not completed */
957 scic_cb_port_stop_complete(
958 scic_sds_port_get_controller(this_port),
959 port,
960 SCI_FAILURE_TIMEOUT
961 );
962 } else {
963 /*
964 * The port is in the ready state and we have a timer reporting a timeout
965 * this should not happen. */
966 dev_err(sciport_to_dev(this_port),
967 "%s: SCIC Port 0x%p is processing a timeout operation "
968 "in state %d.\n",
969 __func__,
970 this_port,
971 current_state);
972 }
973}
974
975/* --------------------------------------------------------------------------- */
976
977#ifdef SCIC_DEBUG_ENABLED
978void scic_sds_port_decrement_request_count(struct scic_sds_port *this_port)
979{
980 if (this_port->started_request_count == 0)
981 dev_warn(sciport_to_dev(this_port),
982 __func__,
983 "%s: SCIC Port object requested to decrement started "
984 "io count past zero.\n");
985 else
986 this_port->started_request_count--;
987}
988#endif
989
990/**
991 * This function updates the hardwares VIIT entry for this port.
992 *
993 *
994 */
995void scic_sds_port_update_viit_entry(struct scic_sds_port *this_port)
996{
997 struct sci_sas_address sas_address;
998
999 scic_sds_port_get_sas_address(this_port, &sas_address);
1000
1001 scu_port_viit_register_write(
1002 this_port, initiator_sas_address_hi, sas_address.high);
1003
1004 scu_port_viit_register_write(
1005 this_port, initiator_sas_address_lo, sas_address.low);
1006
1007 /* This value get cleared just in case its not already cleared */
1008 scu_port_viit_register_write(
1009 this_port, reserved, 0);
1010
1011 /* We are required to update the status register last */
1012 scu_port_viit_register_write(
1013 this_port, status, (
1014 SCU_VIIT_ENTRY_ID_VIIT
1015 | SCU_VIIT_IPPT_INITIATOR
1016 | ((1 << this_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT)
1017 | SCU_VIIT_STATUS_ALL_VALID
1018 )
1019 );
1020}
1021
1022/**
1023 * This method returns the maximum allowed speed for data transfers on this
1024 * port. This maximum allowed speed evaluates to the maximum speed of the
1025 * slowest phy in the port.
1026 * @this_port: This parameter specifies the port for which to retrieve the
1027 * maximum allowed speed.
1028 *
1029 * This method returns the maximum negotiated speed of the slowest phy in the
1030 * port.
1031 */
1032enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed(
1033 struct scic_sds_port *this_port)
1034{
1035 u16 index = 0;
1036 enum sci_sas_link_rate max_allowed_speed = SCI_SAS_600_GB;
1037 struct scic_sds_phy *phy = NULL;
1038
1039 /*
1040 * Loop through all of the phys in this port and find the phy with the
1041 * lowest maximum link rate. */
1042 for (index = 0; index < SCI_MAX_PHYS; index++) {
1043 phy = this_port->phy_table[index];
1044 if (
1045 (phy != NULL)
1046 && (scic_sds_port_active_phy(this_port, phy) == true)
1047 && (phy->max_negotiated_speed < max_allowed_speed)
1048 )
1049 max_allowed_speed = phy->max_negotiated_speed;
1050 }
1051
1052 return max_allowed_speed;
1053}
1054
1055
1056/**
1057 * This method passes the event to core user.
1058 * @this_port: The port that a BCN happens.
1059 * @this_phy: The phy that receives BCN.
1060 *
1061 */
1062void scic_sds_port_broadcast_change_received(
1063 struct scic_sds_port *this_port,
1064 struct scic_sds_phy *this_phy)
1065{
1066 /* notify the user. */
1067 scic_cb_port_bc_change_primitive_received(
1068 this_port->owning_controller, this_port, this_phy
1069 );
1070}
1071
1072
1073/**
1074 * This API methhod enables the broadcast change notification from underneath
1075 * hardware.
1076 * @this_port: The port that a BCN had been disabled from.
1077 *
1078 */
1079void scic_port_enable_broadcast_change_notification(
1080 struct scic_sds_port *port)
1081{
1082 struct scic_sds_phy *phy;
1083 u32 register_value;
1084 u8 index;
1085
1086 /* Loop through all of the phys to enable BCN. */
1087 for (index = 0; index < SCI_MAX_PHYS; index++) {
1088 phy = port->phy_table[index];
1089 if (phy != NULL) {
1090 register_value = SCU_SAS_LLCTL_READ(phy);
1091
1092 /* clear the bit by writing 1. */
1093 SCU_SAS_LLCTL_WRITE(phy, register_value);
1094 }
1095 }
1096}
1097
1098/*
1099 * ****************************************************************************
1100 * * READY SUBSTATE HANDLERS
1101 * **************************************************************************** */
1102
1103/**
1104 *
1105 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1106 * object.
1107 *
1108 * This method is the general ready state stop handler for the struct scic_sds_port
1109 * object. This function will transition the ready substate machine to its
1110 * final state. enum sci_status SCI_SUCCESS
1111 */
1112static enum sci_status scic_sds_port_ready_substate_stop_handler(
1113 struct sci_base_port *port)
1114{
1115 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
1116
1117 sci_base_state_machine_change_state(
1118 &this_port->parent.state_machine,
1119 SCI_BASE_PORT_STATE_STOPPING
1120 );
1121
1122 return SCI_SUCCESS;
1123}
1124
1125/**
1126 *
1127 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1128 * object.
1129 * @device: This is the struct sci_base_remote_device object which is not used in this
1130 * function.
1131 * @io_request: This is the struct sci_base_request object which is not used in this
1132 * function.
1133 *
1134 * This method is the general ready substate complete io handler for the
1135 * struct scic_sds_port object. This function decrments the outstanding request count
1136 * for this port object. enum sci_status SCI_SUCCESS
1137 */
1138static enum sci_status scic_sds_port_ready_substate_complete_io_handler(
1139 struct scic_sds_port *port,
1140 struct scic_sds_remote_device *device,
1141 struct scic_sds_request *io_request)
1142{
1143 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
1144
1145 scic_sds_port_decrement_request_count(this_port);
1146
1147 return SCI_SUCCESS;
1148}
1149
1150static enum sci_status scic_sds_port_ready_substate_add_phy_handler(
1151 struct sci_base_port *port,
1152 struct sci_base_phy *phy)
1153{
1154 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
1155 struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy;
1156 enum sci_status status;
1157
1158 status = scic_sds_port_set_phy(this_port, this_phy);
1159
1160 if (status == SCI_SUCCESS) {
1161 scic_sds_port_general_link_up_handler(this_port, this_phy, true);
1162
1163 this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
1164
1165 sci_base_state_machine_change_state(
1166 &this_port->ready_substate_machine,
1167 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
1168 );
1169 }
1170
1171 return status;
1172}
1173
1174
1175static enum sci_status scic_sds_port_ready_substate_remove_phy_handler(
1176 struct sci_base_port *port,
1177 struct sci_base_phy *phy)
1178{
1179 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
1180 struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy;
1181 enum sci_status status;
1182
1183 status = scic_sds_port_clear_phy(this_port, this_phy);
1184
1185 if (status == SCI_SUCCESS) {
1186 scic_sds_port_deactivate_phy(this_port, this_phy, true);
1187
1188 this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
1189
1190 sci_base_state_machine_change_state(
1191 &this_port->ready_substate_machine,
1192 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
1193 );
1194 }
1195
1196 return status;
1197}
1198
1199/*
1200 * ****************************************************************************
1201 * * READY SUBSTATE WAITING HANDLERS
1202 * **************************************************************************** */
1203
1204/**
1205 *
1206 * @this_port: This is the struct scic_sds_port object that which has a phy that has
1207 * gone link up.
1208 * @the_phy: This is the struct scic_sds_phy object that has gone link up.
1209 *
1210 * This method is the ready waiting substate link up handler for the
1211 * struct scic_sds_port object. This methos will report the link up condition for
1212 * this port and will transition to the ready operational substate. none
1213 */
1214static void scic_sds_port_ready_waiting_substate_link_up_handler(
1215 struct scic_sds_port *this_port,
1216 struct scic_sds_phy *the_phy)
1217{
1218 /*
1219 * Since this is the first phy going link up for the port we can just enable
1220 * it and continue. */
1221 scic_sds_port_activate_phy(this_port, the_phy, true);
1222
1223 sci_base_state_machine_change_state(
1224 &this_port->ready_substate_machine,
1225 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
1226 );
1227}
1228
1229/**
1230 *
1231 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1232 * object.
1233 * @device: This is the struct sci_base_remote_device object which is not used in this
1234 * request.
1235 * @io_request: This is the struct sci_base_request object which is not used in this
1236 * function.
1237 *
1238 * This method is the ready waiting substate start io handler for the
1239 * struct scic_sds_port object. The port object can not accept new requests so the
1240 * request is failed. enum sci_status SCI_FAILURE_INVALID_STATE
1241 */
1242static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler(
1243 struct scic_sds_port *port,
1244 struct scic_sds_remote_device *device,
1245 struct scic_sds_request *io_request)
1246{
1247 return SCI_FAILURE_INVALID_STATE;
1248}
1249
1250/*
1251 * ****************************************************************************
1252 * * READY SUBSTATE OPERATIONAL HANDLERS
1253 * **************************************************************************** */
1254
1255/**
1256 *
1257 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1258 * object.
1259 * @timeout: This is the timeout for the reset request to complete.
1260 *
1261 * This method will casue the port to reset. enum sci_status SCI_SUCCESS
1262 */
1263static enum sci_status scic_sds_port_ready_operational_substate_reset_handler(
1264 struct sci_base_port *port,
1265 u32 timeout)
1266{
1267 enum sci_status status = SCI_FAILURE_INVALID_PHY;
1268 u32 phy_index;
1269 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
1270 struct scic_sds_phy *selected_phy = SCI_INVALID_HANDLE;
1271
1272
1273 /* Select a phy on which we can send the hard reset request. */
1274 for (
1275 phy_index = 0;
1276 (phy_index < SCI_MAX_PHYS)
1277 && (selected_phy == SCI_INVALID_HANDLE);
1278 phy_index++
1279 ) {
1280 selected_phy = this_port->phy_table[phy_index];
1281
1282 if (
1283 (selected_phy != SCI_INVALID_HANDLE)
1284 && !scic_sds_port_active_phy(this_port, selected_phy)
1285 ) {
1286 /* We found a phy but it is not ready select different phy */
1287 selected_phy = SCI_INVALID_HANDLE;
1288 }
1289 }
1290
1291 /* If we have a phy then go ahead and start the reset procedure */
1292 if (selected_phy != SCI_INVALID_HANDLE) {
1293 status = scic_sds_phy_reset(selected_phy);
1294
1295 if (status == SCI_SUCCESS) {
1296 scic_cb_timer_start(
1297 scic_sds_port_get_controller(this_port),
1298 this_port->timer_handle,
1299 timeout
1300 );
1301
1302 this_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED;
1303
1304 sci_base_state_machine_change_state(
1305 &this_port->parent.state_machine,
1306 SCI_BASE_PORT_STATE_RESETTING
1307 );
1308 }
1309 }
1310
1311 return status;
1312}
1313
1314/**
1315 * scic_sds_port_ready_operational_substate_link_up_handler() -
1316 * @this_port: This is the struct scic_sds_port object that which has a phy that has
1317 * gone link up.
1318 * @the_phy: This is the struct scic_sds_phy object that has gone link up.
1319 *
1320 * This method is the ready operational substate link up handler for the
1321 * struct scic_sds_port object. This function notifies the SCI User that the phy has
1322 * gone link up. none
1323 */
1324static void scic_sds_port_ready_operational_substate_link_up_handler(
1325 struct scic_sds_port *this_port,
1326 struct scic_sds_phy *the_phy)
1327{
1328 scic_sds_port_general_link_up_handler(this_port, the_phy, true);
1329}
1330
1331/**
1332 * scic_sds_port_ready_operational_substate_link_down_handler() -
1333 * @this_port: This is the struct scic_sds_port object that which has a phy that has
1334 * gone link down.
1335 * @the_phy: This is the struct scic_sds_phy object that has gone link down.
1336 *
1337 * This method is the ready operational substate link down handler for the
1338 * struct scic_sds_port object. This function notifies the SCI User that the phy has
1339 * gone link down and if this is the last phy in the port the port will change
1340 * state to the ready waiting substate. none
1341 */
1342static void scic_sds_port_ready_operational_substate_link_down_handler(
1343 struct scic_sds_port *this_port,
1344 struct scic_sds_phy *the_phy)
1345{
1346 scic_sds_port_deactivate_phy(this_port, the_phy, true);
1347
1348 /*
1349 * If there are no active phys left in the port, then transition
1350 * the port to the WAITING state until such time as a phy goes
1351 * link up. */
1352 if (this_port->active_phy_mask == 0) {
1353 sci_base_state_machine_change_state(
1354 scic_sds_port_get_ready_substate_machine(this_port),
1355 SCIC_SDS_PORT_READY_SUBSTATE_WAITING
1356 );
1357 }
1358}
1359
1360/**
1361 *
1362 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1363 * object.
1364 * @device: This is the struct sci_base_remote_device object which is not used in this
1365 * function.
1366 * @io_request: This is the struct sci_base_request object which is not used in this
1367 * function.
1368 *
1369 * This method is the ready operational substate start io handler for the
1370 * struct scic_sds_port object. This function incremetns the outstanding request
1371 * count for this port object. enum sci_status SCI_SUCCESS
1372 */
1373static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler(
1374 struct scic_sds_port *port,
1375 struct scic_sds_remote_device *device,
1376 struct scic_sds_request *io_request)
1377{
1378 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
1379
1380 scic_sds_port_increment_request_count(this_port);
1381
1382 return SCI_SUCCESS;
1383}
1384
1385/*
1386 * ****************************************************************************
1387 * * READY SUBSTATE OPERATIONAL HANDLERS
1388 * **************************************************************************** */
1389
1390/**
1391 * scic_sds_port_ready_configuring_substate_add_phy_handler() -
1392 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1393 * object.
1394 *
1395 * This is the default method for a port add phy request. It will report a
1396 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1397 */
1398static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler(
1399 struct sci_base_port *port,
1400 struct sci_base_phy *phy)
1401{
1402 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
1403 struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy;
1404 enum sci_status status;
1405
1406 status = scic_sds_port_set_phy(this_port, this_phy);
1407
1408 if (status == SCI_SUCCESS) {
1409 scic_sds_port_general_link_up_handler(this_port, this_phy, true);
1410
1411 /*
1412 * Re-enter the configuring state since this may be the last phy in
1413 * the port. */
1414 sci_base_state_machine_change_state(
1415 &this_port->ready_substate_machine,
1416 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
1417 );
1418 }
1419
1420 return status;
1421}
1422
1423/**
1424 * scic_sds_port_ready_configuring_substate_remove_phy_handler() -
1425 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1426 * object.
1427 *
1428 * This is the default method for a port remove phy request. It will report a
1429 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1430 */
1431static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handler(
1432 struct sci_base_port *port,
1433 struct sci_base_phy *phy)
1434{
1435 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
1436 struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy;
1437 enum sci_status status;
1438
1439 status = scic_sds_port_clear_phy(this_port, this_phy);
1440
1441 if (status == SCI_SUCCESS) {
1442 scic_sds_port_deactivate_phy(this_port, this_phy, true);
1443
1444 /*
1445 * Re-enter the configuring state since this may be the last phy in
1446 * the port. */
1447 sci_base_state_machine_change_state(
1448 &this_port->ready_substate_machine,
1449 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
1450 );
1451 }
1452
1453 return status;
1454}
1455
1456/**
1457 * scic_sds_port_ready_configuring_substate_complete_io_handler() -
1458 * @port: This is the port that is being requested to complete the io request.
1459 * @device: This is the device on which the io is completing.
1460 *
1461 * This method will decrement the outstanding request count for this port. If
1462 * the request count goes to 0 then the port can be reprogrammed with its new
1463 * phy data.
1464 */
1465static enum sci_status scic_sds_port_ready_configuring_substate_complete_io_handler(
1466 struct scic_sds_port *port,
1467 struct scic_sds_remote_device *device,
1468 struct scic_sds_request *io_request)
1469{
1470 scic_sds_port_decrement_request_count(port);
1471
1472 if (port->started_request_count == 0) {
1473 sci_base_state_machine_change_state(
1474 &port->ready_substate_machine,
1475 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
1476 );
1477 }
1478
1479 return SCI_SUCCESS;
1480}
1481
1482/* --------------------------------------------------------------------------- */
1483
1484struct scic_sds_port_state_handler
1485scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] =
1486{
1487 /* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */
1488 {
1489 {
1490 scic_sds_port_default_start_handler,
1491 scic_sds_port_ready_substate_stop_handler,
1492 scic_sds_port_default_destruct_handler,
1493 scic_sds_port_default_reset_handler,
1494 scic_sds_port_ready_substate_add_phy_handler,
1495 scic_sds_port_default_remove_phy_handler
1496 },
1497 scic_sds_port_default_frame_handler,
1498 scic_sds_port_default_event_handler,
1499 scic_sds_port_ready_waiting_substate_link_up_handler,
1500 scic_sds_port_default_link_down_handler,
1501 scic_sds_port_ready_waiting_substate_start_io_handler,
1502 scic_sds_port_ready_substate_complete_io_handler,
1503 },
1504 /* SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL */
1505 {
1506 {
1507 scic_sds_port_default_start_handler,
1508 scic_sds_port_ready_substate_stop_handler,
1509 scic_sds_port_default_destruct_handler,
1510 scic_sds_port_ready_operational_substate_reset_handler,
1511 scic_sds_port_ready_substate_add_phy_handler,
1512 scic_sds_port_ready_substate_remove_phy_handler
1513 },
1514 scic_sds_port_default_frame_handler,
1515 scic_sds_port_default_event_handler,
1516 scic_sds_port_ready_operational_substate_link_up_handler,
1517 scic_sds_port_ready_operational_substate_link_down_handler,
1518 scic_sds_port_ready_operational_substate_start_io_handler,
1519 scic_sds_port_ready_substate_complete_io_handler
1520 },
1521 /* SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING */
1522 {
1523 {
1524 scic_sds_port_default_start_handler,
1525 scic_sds_port_ready_substate_stop_handler,
1526 scic_sds_port_default_destruct_handler,
1527 scic_sds_port_default_reset_handler,
1528 scic_sds_port_ready_configuring_substate_add_phy_handler,
1529 scic_sds_port_ready_configuring_substate_remove_phy_handler
1530 },
1531 scic_sds_port_default_frame_handler,
1532 scic_sds_port_default_event_handler,
1533 scic_sds_port_default_link_up_handler,
1534 scic_sds_port_default_link_down_handler,
1535 scic_sds_port_default_start_io_handler,
1536 scic_sds_port_ready_configuring_substate_complete_io_handler
1537 }
1538};
1539
1540
1541/**
1542 * scic_sds_port_set_ready_state_handlers() -
1543 *
1544 * This macro sets the port ready substate handlers.
1545 */
1546#define scic_sds_port_set_ready_state_handlers(port, state_id) \
1547 scic_sds_port_set_state_handlers(\
1548 port, &scic_sds_port_ready_substate_handler_table[(state_id)] \
1549 )
1550
1551/*
1552 * ******************************************************************************
1553 * * PORT STATE PRIVATE METHODS
1554 * ****************************************************************************** */
1555
1556/**
1557 *
1558 * @this_port: This is the struct scic_sds_port object to suspend.
1559 *
1560 * This method will susped the port task scheduler for this port object. none
1561 */
1562static void scic_sds_port_suspend_port_task_scheduler(
1563 struct scic_sds_port *this_port)
1564{
1565 u32 pts_control_value;
1566 u32 tl_control_value;
1567
1568 pts_control_value = scu_port_task_scheduler_read(this_port, control);
1569 tl_control_value = scu_transport_layer_read(this_port, control);
1570
1571 pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND);
1572 tl_control_value |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
1573
1574 scu_port_task_scheduler_write(this_port, control, pts_control_value);
1575 scu_transport_layer_write(this_port, control, tl_control_value);
1576}
1577
1578/**
1579 *
1580 * @this_port: This is the struct scic_sds_port object to resume.
1581 *
1582 * This method will resume the port task scheduler for this port object. none
1583 */
1584static void scic_sds_port_resume_port_task_scheduler(
1585 struct scic_sds_port *this_port)
1586{
1587 u32 pts_control_value;
1588
1589 pts_control_value = scu_port_task_scheduler_read(this_port, control);
1590
1591 pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND);
1592
1593 scu_port_task_scheduler_write(this_port, control, pts_control_value);
1594}
1595
1596/*
1597 * ******************************************************************************
1598 * * PORT READY SUBSTATE METHODS
1599 * ****************************************************************************** */
1600
1601/**
1602 *
1603 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
1604 *
1605 * This method will perform the actions required by the struct scic_sds_port on
1606 * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the
1607 * port for any ready phys. If there is at least one phy in a ready state then
1608 * the port transitions to the ready operational substate. none
1609 */
1610static void scic_sds_port_ready_substate_waiting_enter(
1611 struct sci_base_object *object)
1612{
1613 struct scic_sds_port *this_port = (struct scic_sds_port *)object;
1614
1615 scic_sds_port_set_ready_state_handlers(
1616 this_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING
1617 );
1618
1619 scic_sds_port_suspend_port_task_scheduler(this_port);
1620
1621 this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS;
1622
1623 if (this_port->active_phy_mask != 0) {
1624 /* At least one of the phys on the port is ready */
1625 sci_base_state_machine_change_state(
1626 &this_port->ready_substate_machine,
1627 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
1628 );
1629 }
1630}
1631
1632/**
1633 *
1634 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
1635 *
1636 * This method will perform the actions required by the struct scic_sds_port on
1637 * entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets
1638 * the state handlers for the port object, notifies the SCI User that the port
1639 * is ready, and resumes port operations. none
1640 */
1641static void scic_sds_port_ready_substate_operational_enter(
1642 struct sci_base_object *object)
1643{
1644 u32 index;
1645 struct scic_sds_port *this_port = (struct scic_sds_port *)object;
1646
1647 scic_sds_port_set_ready_state_handlers(
1648 this_port, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
1649 );
1650
1651 scic_cb_port_ready(
1652 scic_sds_port_get_controller(this_port), this_port
1653 );
1654
1655 for (index = 0; index < SCI_MAX_PHYS; index++) {
1656 if (this_port->phy_table[index] != NULL) {
1657 scic_sds_port_write_phy_assignment(
1658 this_port, this_port->phy_table[index]
1659 );
1660 }
1661 }
1662
1663 scic_sds_port_update_viit_entry(this_port);
1664
1665 scic_sds_port_resume_port_task_scheduler(this_port);
1666}
1667
1668/**
1669 *
1670 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
1671 *
1672 * This method will perform the actions required by the struct scic_sds_port on
1673 * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports
1674 * the port not ready and suspends the port task scheduler. none
1675 */
1676static void scic_sds_port_ready_substate_operational_exit(
1677 struct sci_base_object *object)
1678{
1679 struct scic_sds_port *this_port = (struct scic_sds_port *)object;
1680
1681 scic_cb_port_not_ready(
1682 scic_sds_port_get_controller(this_port),
1683 this_port,
1684 this_port->not_ready_reason
1685 );
1686}
1687
1688/*
1689 * ******************************************************************************
1690 * * PORT READY CONFIGURING METHODS
1691 * ****************************************************************************** */
1692
1693/**
1694 * scic_sds_port_ready_substate_configuring_enter() -
1695 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
1696 *
1697 * This method will perform the actions required by the struct scic_sds_port on
1698 * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports
1699 * the port not ready and suspends the port task scheduler. none
1700 */
1701static void scic_sds_port_ready_substate_configuring_enter(
1702 struct sci_base_object *object)
1703{
1704 struct scic_sds_port *this_port = (struct scic_sds_port *)object;
1705
1706 scic_sds_port_set_ready_state_handlers(
1707 this_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING
1708 );
1709
1710 if (this_port->active_phy_mask == 0) {
1711 scic_cb_port_not_ready(
1712 scic_sds_port_get_controller(this_port),
1713 this_port,
1714 SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS
1715 );
1716
1717 sci_base_state_machine_change_state(
1718 &this_port->ready_substate_machine,
1719 SCIC_SDS_PORT_READY_SUBSTATE_WAITING
1720 );
1721 } else if (this_port->started_request_count == 0) {
1722 sci_base_state_machine_change_state(
1723 &this_port->ready_substate_machine,
1724 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL
1725 );
1726 }
1727}
1728
1729static void scic_sds_port_ready_substate_configuring_exit(
1730 struct sci_base_object *object)
1731{
1732 struct scic_sds_port *this_port = (struct scic_sds_port *)object;
1733
1734 scic_sds_port_suspend_port_task_scheduler(this_port);
1735}
1736
1737/* --------------------------------------------------------------------------- */
1738
1739const struct sci_base_state scic_sds_port_ready_substate_table[] = {
1740 [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = {
1741 .enter_state = scic_sds_port_ready_substate_waiting_enter,
1742 },
1743 [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = {
1744 .enter_state = scic_sds_port_ready_substate_operational_enter,
1745 .exit_state = scic_sds_port_ready_substate_operational_exit
1746 },
1747 [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = {
1748 .enter_state = scic_sds_port_ready_substate_configuring_enter,
1749 .exit_state = scic_sds_port_ready_substate_configuring_exit
1750 },
1751};
1752
1753/*
1754 * ***************************************************************************
1755 * * DEFAULT HANDLERS
1756 * *************************************************************************** */
1757
1758/**
1759 *
1760 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1761 * object.
1762 *
1763 * This is the default method for port a start request. It will report a
1764 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1765 */
1766enum sci_status scic_sds_port_default_start_handler(
1767 struct sci_base_port *port)
1768{
1769 struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
1770
1771 dev_warn(sciport_to_dev(sci_port),
1772 "%s: SCIC Port 0x%p requested to start while in invalid "
1773 "state %d\n",
1774 __func__,
1775 port,
1776 sci_base_state_machine_get_state(
1777 scic_sds_port_get_base_state_machine(
1778 (struct scic_sds_port *)port)));
1779
1780 return SCI_FAILURE_INVALID_STATE;
1781}
1782
1783/**
1784 *
1785 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1786 * object.
1787 *
1788 * This is the default method for a port stop request. It will report a
1789 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1790 */
1791static enum sci_status scic_sds_port_default_stop_handler(
1792 struct sci_base_port *port)
1793{
1794 struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
1795
1796 dev_warn(sciport_to_dev(sci_port),
1797 "%s: SCIC Port 0x%p requested to stop while in invalid "
1798 "state %d\n",
1799 __func__,
1800 port,
1801 sci_base_state_machine_get_state(
1802 scic_sds_port_get_base_state_machine(
1803 (struct scic_sds_port *)port)));
1804
1805 return SCI_FAILURE_INVALID_STATE;
1806}
1807
1808/**
1809 *
1810 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1811 * object.
1812 *
1813 * This is the default method for a port destruct request. It will report a
1814 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1815 */
1816enum sci_status scic_sds_port_default_destruct_handler(
1817 struct sci_base_port *port)
1818{
1819 struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
1820
1821 dev_warn(sciport_to_dev(sci_port),
1822 "%s: SCIC Port 0x%p requested to destruct while in invalid "
1823 "state %d\n",
1824 __func__,
1825 port,
1826 sci_base_state_machine_get_state(
1827 scic_sds_port_get_base_state_machine(
1828 (struct scic_sds_port *)port)));
1829
1830 return SCI_FAILURE_INVALID_STATE;
1831}
1832
1833/**
1834 *
1835 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1836 * object.
1837 * @timeout: This is the timeout for the reset request to complete.
1838 *
1839 * This is the default method for a port reset request. It will report a
1840 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1841 */
1842enum sci_status scic_sds_port_default_reset_handler(
1843 struct sci_base_port *port,
1844 u32 timeout)
1845{
1846 struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
1847
1848 dev_warn(sciport_to_dev(sci_port),
1849 "%s: SCIC Port 0x%p requested to reset while in invalid "
1850 "state %d\n",
1851 __func__,
1852 port,
1853 sci_base_state_machine_get_state(
1854 scic_sds_port_get_base_state_machine(
1855 (struct scic_sds_port *)port)));
1856
1857 return SCI_FAILURE_INVALID_STATE;
1858}
1859
1860/**
1861 *
1862 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1863 * object.
1864 *
1865 * This is the default method for a port add phy request. It will report a
1866 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1867 */
1868static enum sci_status scic_sds_port_default_add_phy_handler(
1869 struct sci_base_port *port,
1870 struct sci_base_phy *phy)
1871{
1872 struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
1873
1874 dev_warn(sciport_to_dev(sci_port),
1875 "%s: SCIC Port 0x%p requested to add phy 0x%p while in "
1876 "invalid state %d\n",
1877 __func__,
1878 port,
1879 phy,
1880 sci_base_state_machine_get_state(
1881 scic_sds_port_get_base_state_machine(
1882 (struct scic_sds_port *)port)));
1883
1884 return SCI_FAILURE_INVALID_STATE;
1885}
1886
1887/**
1888 *
1889 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1890 * object.
1891 *
1892 * This is the default method for a port remove phy request. It will report a
1893 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1894 */
1895enum sci_status scic_sds_port_default_remove_phy_handler(
1896 struct sci_base_port *port,
1897 struct sci_base_phy *phy)
1898{
1899 struct scic_sds_port *sci_port = (struct scic_sds_port *)port;
1900
1901 dev_warn(sciport_to_dev(sci_port),
1902 "%s: SCIC Port 0x%p requested to remove phy 0x%p while in "
1903 "invalid state %d\n",
1904 __func__,
1905 port,
1906 phy,
1907 sci_base_state_machine_get_state(
1908 scic_sds_port_get_base_state_machine(
1909 (struct scic_sds_port *)port)));
1910
1911 return SCI_FAILURE_INVALID_STATE;
1912}
1913
1914/**
1915 *
1916 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1917 * object.
1918 *
1919 * This is the default method for a port unsolicited frame request. It will
1920 * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even
1921 * possible to receive an unsolicited frame directed to a port object? It
1922 * seems possible if we implementing virtual functions but until then?
1923 */
1924enum sci_status scic_sds_port_default_frame_handler(
1925 struct scic_sds_port *port,
1926 u32 frame_index)
1927{
1928 dev_warn(sciport_to_dev(port),
1929 "%s: SCIC Port 0x%p requested to process frame %d while in "
1930 "invalid state %d\n",
1931 __func__,
1932 port,
1933 frame_index,
1934 sci_base_state_machine_get_state(
1935 scic_sds_port_get_base_state_machine(port)));
1936
1937 scic_sds_controller_release_frame(
1938 scic_sds_port_get_controller(port), frame_index
1939 );
1940
1941 return SCI_FAILURE_INVALID_STATE;
1942}
1943
1944/**
1945 *
1946 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1947 * object.
1948 *
1949 * This is the default method for a port event request. It will report a
1950 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1951 */
1952enum sci_status scic_sds_port_default_event_handler(
1953 struct scic_sds_port *port,
1954 u32 event_code)
1955{
1956 dev_warn(sciport_to_dev(port),
1957 "%s: SCIC Port 0x%p requested to process event 0x%x while "
1958 "in invalid state %d\n",
1959 __func__,
1960 port,
1961 event_code,
1962 sci_base_state_machine_get_state(
1963 scic_sds_port_get_base_state_machine(
1964 (struct scic_sds_port *)port)));
1965
1966 return SCI_FAILURE_INVALID_STATE;
1967}
1968
1969/**
1970 *
1971 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1972 * object.
1973 *
1974 * This is the default method for a port link up notification. It will report
1975 * a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1976 */
1977void scic_sds_port_default_link_up_handler(
1978 struct scic_sds_port *this_port,
1979 struct scic_sds_phy *phy)
1980{
1981 dev_warn(sciport_to_dev(this_port),
1982 "%s: SCIC Port 0x%p received link_up notification from phy "
1983 "0x%p while in invalid state %d\n",
1984 __func__,
1985 this_port,
1986 phy,
1987 sci_base_state_machine_get_state(
1988 scic_sds_port_get_base_state_machine(this_port)));
1989}
1990
1991/**
1992 *
1993 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
1994 * object.
1995 *
1996 * This is the default method for a port link down notification. It will
1997 * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
1998 */
1999void scic_sds_port_default_link_down_handler(
2000 struct scic_sds_port *this_port,
2001 struct scic_sds_phy *phy)
2002{
2003 dev_warn(sciport_to_dev(this_port),
2004 "%s: SCIC Port 0x%p received link down notification from "
2005 "phy 0x%p while in invalid state %d\n",
2006 __func__,
2007 this_port,
2008 phy,
2009 sci_base_state_machine_get_state(
2010 scic_sds_port_get_base_state_machine(this_port)));
2011}
2012
2013/**
2014 *
2015 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
2016 * object.
2017 *
2018 * This is the default method for a port start io request. It will report a
2019 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
2020 */
2021enum sci_status scic_sds_port_default_start_io_handler(
2022 struct scic_sds_port *this_port,
2023 struct scic_sds_remote_device *device,
2024 struct scic_sds_request *io_request)
2025{
2026 dev_warn(sciport_to_dev(this_port),
2027 "%s: SCIC Port 0x%p requested to start io request 0x%p "
2028 "while in invalid state %d\n",
2029 __func__,
2030 this_port,
2031 io_request,
2032 sci_base_state_machine_get_state(
2033 scic_sds_port_get_base_state_machine(this_port)));
2034
2035 return SCI_FAILURE_INVALID_STATE;
2036}
2037
2038/**
2039 *
2040 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
2041 * object.
2042 *
2043 * This is the default method for a port complete io request. It will report a
2044 * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE
2045 */
2046static enum sci_status scic_sds_port_default_complete_io_handler(
2047 struct scic_sds_port *this_port,
2048 struct scic_sds_remote_device *device,
2049 struct scic_sds_request *io_request)
2050{
2051 dev_warn(sciport_to_dev(this_port),
2052 "%s: SCIC Port 0x%p requested to complete io request 0x%p "
2053 "while in invalid state %d\n",
2054 __func__,
2055 this_port,
2056 io_request,
2057 sci_base_state_machine_get_state(
2058 scic_sds_port_get_base_state_machine(this_port)));
2059
2060 return SCI_FAILURE_INVALID_STATE;
2061}
2062
2063/*
2064 * ****************************************************************************
2065 * * GENERAL STATE HANDLERS
2066 * **************************************************************************** */
2067
2068/**
2069 *
2070 * @port: This is the struct scic_sds_port object on which the io request count will
2071 * be decremented.
2072 * @device: This is the struct scic_sds_remote_device object to which the io request
2073 * is being directed. This parameter is not required to complete this
2074 * operation.
2075 * @io_request: This is the request that is being completed on this port
2076 * object. This parameter is not required to complete this operation.
2077 *
2078 * This is a general complete io request handler for the struct scic_sds_port object.
2079 * enum sci_status SCI_SUCCESS
2080 */
2081static enum sci_status scic_sds_port_general_complete_io_handler(
2082 struct scic_sds_port *port,
2083 struct scic_sds_remote_device *device,
2084 struct scic_sds_request *io_request)
2085{
2086 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
2087
2088 scic_sds_port_decrement_request_count(this_port);
2089
2090 return SCI_SUCCESS;
2091}
2092
2093/*
2094 * ****************************************************************************
2095 * * STOPPED STATE HANDLERS
2096 * **************************************************************************** */
2097
2098/**
2099 *
2100 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
2101 * object.
2102 *
2103 * This method takes the struct scic_sds_port from a stopped state and attempts to
2104 * start it. To start a port it must have no assiged devices and it must have
2105 * at least one phy assigned to it. If those conditions are met then the port
2106 * can transition to the ready state. enum sci_status
2107 * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This struct scic_sds_port object could
2108 * not be started because the port configuration is not valid. SCI_SUCCESS the
2109 * start request is successful and the struct scic_sds_port object has transitioned to
2110 * the SCI_BASE_PORT_STATE_READY.
2111 */
2112static enum sci_status scic_sds_port_stopped_state_start_handler(
2113 struct sci_base_port *port)
2114{
2115 u32 phy_mask;
2116 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
2117
2118 if (this_port->assigned_device_count > 0) {
2119 /*
2120 * / @todo This is a start failure operation because there are still
2121 * / devices assigned to this port. There must be no devices
2122 * / assigned to a port on a start operation. */
2123 return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
2124 }
2125
2126 phy_mask = scic_sds_port_get_phys(this_port);
2127
2128 /*
2129 * There are one or more phys assigned to this port. Make sure
2130 * the port's phy mask is in fact legal and supported by the
2131 * silicon. */
2132 if (scic_sds_port_is_phy_mask_valid(this_port, phy_mask) == true) {
2133 sci_base_state_machine_change_state(
2134 scic_sds_port_get_base_state_machine(this_port),
2135 SCI_BASE_PORT_STATE_READY
2136 );
2137
2138 return SCI_SUCCESS;
2139 }
2140
2141 return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
2142}
2143
2144/**
2145 *
2146 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
2147 * object.
2148 *
2149 * This method takes the struct scic_sds_port that is in a stopped state and handles a
2150 * stop request. This function takes no action. enum sci_status SCI_SUCCESS the
2151 * stop request is successful as the struct scic_sds_port object is already stopped.
2152 */
2153static enum sci_status scic_sds_port_stopped_state_stop_handler(
2154 struct sci_base_port *port)
2155{
2156 /* We are already stopped so there is nothing to do here */
2157 return SCI_SUCCESS;
2158}
2159
2160/**
2161 *
2162 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
2163 * object.
2164 *
2165 * This method takes the struct scic_sds_port that is in a stopped state and handles
2166 * the destruct request. The stopped state is the only state in which the
2167 * struct scic_sds_port can be destroyed. This function causes the port object to
2168 * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS
2169 */
2170static enum sci_status scic_sds_port_stopped_state_destruct_handler(
2171 struct sci_base_port *port)
2172{
2173 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
2174
2175 sci_base_state_machine_stop(&this_port->parent.state_machine);
2176
2177 return SCI_SUCCESS;
2178}
2179
2180/**
2181 *
2182 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
2183 * object.
2184 * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
2185 * object.
2186 *
2187 * This method takes the struct scic_sds_port that is in a stopped state and handles
2188 * the add phy request. In MPC mode the only time a phy can be added to a port
2189 * is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status
2190 * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not
2191 * be added to the port. SCI_SUCCESS if the phy is added to the port.
2192 */
2193static enum sci_status scic_sds_port_stopped_state_add_phy_handler(
2194 struct sci_base_port *port,
2195 struct sci_base_phy *phy)
2196{
2197 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
2198 struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy;
2199 struct sci_sas_address port_sas_address;
2200
2201 /* Read the port assigned SAS Address if there is one */
2202 scic_sds_port_get_sas_address(this_port, &port_sas_address);
2203
2204 if (port_sas_address.high != 0 && port_sas_address.low != 0) {
2205 struct sci_sas_address phy_sas_address;
2206
2207 /*
2208 * Make sure that the PHY SAS Address matches the SAS Address
2209 * for this port. */
2210 scic_sds_phy_get_sas_address(this_phy, &phy_sas_address);
2211
2212 if (
2213 (port_sas_address.high != phy_sas_address.high)
2214 || (port_sas_address.low != phy_sas_address.low)
2215 ) {
2216 return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
2217 }
2218 }
2219
2220 return scic_sds_port_set_phy(this_port, this_phy);
2221}
2222
2223
2224/**
2225 *
2226 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
2227 * object.
2228 * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy
2229 * object.
2230 *
2231 * This method takes the struct scic_sds_port that is in a stopped state and handles
2232 * the remove phy request. In MPC mode the only time a phy can be removed from
2233 * a port is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status
2234 * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not
2235 * be added to the port. SCI_SUCCESS if the phy is added to the port.
2236 */
2237static enum sci_status scic_sds_port_stopped_state_remove_phy_handler(
2238 struct sci_base_port *port,
2239 struct sci_base_phy *phy)
2240{
2241 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
2242 struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy;
2243
2244 return scic_sds_port_clear_phy(this_port, this_phy);
2245}
2246
2247/*
2248 * ****************************************************************************
2249 * * READY STATE HANDLERS
2250 * **************************************************************************** */
2251
2252/*
2253 * ****************************************************************************
2254 * * RESETTING STATE HANDLERS
2255 * **************************************************************************** */
2256
2257/*
2258 * ****************************************************************************
2259 * * STOPPING STATE HANDLERS
2260 * **************************************************************************** */
2261
2262/**
2263 *
2264 * @port: This is the struct scic_sds_port object on which the io request count will
2265 * be decremented.
2266 * @device: This is the struct scic_sds_remote_device object to which the io request
2267 * is being directed. This parameter is not required to complete this
2268 * operation.
2269 * @io_request: This is the request that is being completed on this port
2270 * object. This parameter is not required to complete this operation.
2271 *
2272 * This method takes the struct scic_sds_port that is in a stopping state and handles
2273 * the complete io request. Should the request count reach 0 then the port
2274 * object will transition to the stopped state. enum sci_status SCI_SUCCESS
2275 */
2276static enum sci_status scic_sds_port_stopping_state_complete_io_handler(
2277 struct scic_sds_port *port,
2278 struct scic_sds_remote_device *device,
2279 struct scic_sds_request *io_request)
2280{
2281 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
2282
2283 scic_sds_port_decrement_request_count(this_port);
2284
2285 if (this_port->started_request_count == 0) {
2286 sci_base_state_machine_change_state(
2287 scic_sds_port_get_base_state_machine(this_port),
2288 SCI_BASE_PORT_STATE_STOPPED
2289 );
2290 }
2291
2292 return SCI_SUCCESS;
2293}
2294
2295/*
2296 * ****************************************************************************
2297 * * RESETTING STATE HANDLERS
2298 * **************************************************************************** */
2299
2300/**
2301 *
2302 * @port: This is the port object which is being requested to stop.
2303 *
2304 * This method will stop a failed port. This causes a transition to the
2305 * stopping state. enum sci_status SCI_SUCCESS
2306 */
2307static enum sci_status scic_sds_port_reset_state_stop_handler(
2308 struct sci_base_port *port)
2309{
2310 struct scic_sds_port *this_port = (struct scic_sds_port *)port;
2311
2312 sci_base_state_machine_change_state(
2313 &this_port->parent.state_machine,
2314 SCI_BASE_PORT_STATE_STOPPING
2315 );
2316
2317 return SCI_SUCCESS;
2318}
2319
2320/**
2321 *
2322 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
2323 * object.
2324 *
2325 * This method will transition a failed port to its ready state. The port
2326 * failed because a hard reset request timed out but at some time later one or
2327 * more phys in the port became ready. enum sci_status SCI_SUCCESS
2328 */
2329static void scic_sds_port_reset_state_link_up_handler(
2330 struct scic_sds_port *this_port,
2331 struct scic_sds_phy *phy)
2332{
2333 /*
2334 * / @todo We should make sure that the phy that has gone link up is the same
2335 * / one on which we sent the reset. It is possible that the phy on
2336 * / which we sent the reset is not the one that has gone link up and we
2337 * / want to make sure that phy being reset comes back. Consider the
2338 * / case where a reset is sent but before the hardware processes the
2339 * / reset it get a link up on the port because of a hot plug event.
2340 * / because of the reset request this phy will go link down almost
2341 * / immediately. */
2342
2343 /*
2344 * In the resetting state we don't notify the user regarding
2345 * link up and link down notifications. */
2346 scic_sds_port_general_link_up_handler(this_port, phy, false);
2347}
2348
2349/**
2350 *
2351 * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port
2352 * object.
2353 *
2354 * This method process link down notifications that occur during a port reset
2355 * operation. Link downs can occur during the reset operation. enum sci_status
2356 * SCI_SUCCESS
2357 */
2358static void scic_sds_port_reset_state_link_down_handler(
2359 struct scic_sds_port *this_port,
2360 struct scic_sds_phy *phy)
2361{
2362 /*
2363 * In the resetting state we don't notify the user regarding
2364 * link up and link down notifications. */
2365 scic_sds_port_deactivate_phy(this_port, phy, false);
2366}
2367
2368/* --------------------------------------------------------------------------- */
2369
2370struct scic_sds_port_state_handler
2371scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] =
2372{
2373 /* SCI_BASE_PORT_STATE_STOPPED */
2374 {
2375 {
2376 scic_sds_port_stopped_state_start_handler,
2377 scic_sds_port_stopped_state_stop_handler,
2378 scic_sds_port_stopped_state_destruct_handler,
2379 scic_sds_port_default_reset_handler,
2380 scic_sds_port_stopped_state_add_phy_handler,
2381 scic_sds_port_stopped_state_remove_phy_handler
2382 },
2383 scic_sds_port_default_frame_handler,
2384 scic_sds_port_default_event_handler,
2385 scic_sds_port_default_link_up_handler,
2386 scic_sds_port_default_link_down_handler,
2387 scic_sds_port_default_start_io_handler,
2388 scic_sds_port_default_complete_io_handler
2389 },
2390 /* SCI_BASE_PORT_STATE_STOPPING */
2391 {
2392 {
2393 scic_sds_port_default_start_handler,
2394 scic_sds_port_default_stop_handler,
2395 scic_sds_port_default_destruct_handler,
2396 scic_sds_port_default_reset_handler,
2397 scic_sds_port_default_add_phy_handler,
2398 scic_sds_port_default_remove_phy_handler
2399 },
2400 scic_sds_port_default_frame_handler,
2401 scic_sds_port_default_event_handler,
2402 scic_sds_port_default_link_up_handler,
2403 scic_sds_port_default_link_down_handler,
2404 scic_sds_port_default_start_io_handler,
2405 scic_sds_port_stopping_state_complete_io_handler
2406 },
2407 /* SCI_BASE_PORT_STATE_READY */
2408 {
2409 {
2410 scic_sds_port_default_start_handler,
2411 scic_sds_port_default_stop_handler,
2412 scic_sds_port_default_destruct_handler,
2413 scic_sds_port_default_reset_handler,
2414 scic_sds_port_default_add_phy_handler,
2415 scic_sds_port_default_remove_phy_handler
2416 },
2417 scic_sds_port_default_frame_handler,
2418 scic_sds_port_default_event_handler,
2419 scic_sds_port_default_link_up_handler,
2420 scic_sds_port_default_link_down_handler,
2421 scic_sds_port_default_start_io_handler,
2422 scic_sds_port_general_complete_io_handler
2423 },
2424 /* SCI_BASE_PORT_STATE_RESETTING */
2425 {
2426 {
2427 scic_sds_port_default_start_handler,
2428 scic_sds_port_reset_state_stop_handler,
2429 scic_sds_port_default_destruct_handler,
2430 scic_sds_port_default_reset_handler,
2431 scic_sds_port_default_add_phy_handler,
2432 scic_sds_port_default_remove_phy_handler
2433 },
2434 scic_sds_port_default_frame_handler,
2435 scic_sds_port_default_event_handler,
2436 scic_sds_port_reset_state_link_up_handler,
2437 scic_sds_port_reset_state_link_down_handler,
2438 scic_sds_port_default_start_io_handler,
2439 scic_sds_port_general_complete_io_handler
2440 },
2441 /* SCI_BASE_PORT_STATE_FAILED */
2442 {
2443 {
2444 scic_sds_port_default_start_handler,
2445 scic_sds_port_default_stop_handler,
2446 scic_sds_port_default_destruct_handler,
2447 scic_sds_port_default_reset_handler,
2448 scic_sds_port_default_add_phy_handler,
2449 scic_sds_port_default_remove_phy_handler
2450 },
2451 scic_sds_port_default_frame_handler,
2452 scic_sds_port_default_event_handler,
2453 scic_sds_port_default_link_up_handler,
2454 scic_sds_port_default_link_down_handler,
2455 scic_sds_port_default_start_io_handler,
2456 scic_sds_port_general_complete_io_handler
2457 }
2458};
2459
2460/*
2461 * ******************************************************************************
2462 * * PORT STATE PRIVATE METHODS
2463 * ****************************************************************************** */
2464
2465/**
2466 *
2467 * @this_port: This is the port object which to suspend.
2468 *
2469 * This method will enable the SCU Port Task Scheduler for this port object but
2470 * will leave the port task scheduler in a suspended state. none
2471 */
2472static void scic_sds_port_enable_port_task_scheduler(
2473 struct scic_sds_port *this_port)
2474{
2475 u32 pts_control_value;
2476
2477 pts_control_value = scu_port_task_scheduler_read(this_port, control);
2478
2479 pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND);
2480
2481 scu_port_task_scheduler_write(this_port, control, pts_control_value);
2482}
2483
2484/**
2485 *
2486 * @this_port: This is the port object which to resume.
2487 *
2488 * This method will disable the SCU port task scheduler for this port object.
2489 * none
2490 */
2491static void scic_sds_port_disable_port_task_scheduler(
2492 struct scic_sds_port *this_port)
2493{
2494 u32 pts_control_value;
2495
2496 pts_control_value = scu_port_task_scheduler_read(this_port, control);
2497
2498 pts_control_value &= ~(SCU_PTSxCR_GEN_BIT(ENABLE)
2499 | SCU_PTSxCR_GEN_BIT(SUSPEND));
2500
2501 scu_port_task_scheduler_write(this_port, control, pts_control_value);
2502}
2503
2504/*
2505 * ******************************************************************************
2506 * * PORT STATE METHODS
2507 * ****************************************************************************** */
2508
2509/**
2510 *
2511 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
2512 *
2513 * This method will perform the actions required by the struct scic_sds_port on
2514 * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped
2515 * state handlers for the struct scic_sds_port object and disables the port task
2516 * scheduler in the hardware. none
2517 */
2518static void scic_sds_port_stopped_state_enter(
2519 struct sci_base_object *object)
2520{
2521 struct scic_sds_port *this_port;
2522
2523 this_port = (struct scic_sds_port *)object;
2524
2525 scic_sds_port_set_base_state_handlers(
2526 this_port, SCI_BASE_PORT_STATE_STOPPED
2527 );
2528
2529 if (
2530 SCI_BASE_PORT_STATE_STOPPING
2531 == this_port->parent.state_machine.previous_state_id
2532 ) {
2533 /*
2534 * If we enter this state becasuse of a request to stop
2535 * the port then we want to disable the hardwares port
2536 * task scheduler. */
2537 scic_sds_port_disable_port_task_scheduler(this_port);
2538 }
2539}
2540
2541/**
2542 *
2543 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
2544 *
2545 * This method will perform the actions required by the struct scic_sds_port on
2546 * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware
2547 * port task scheduler. none
2548 */
2549static void scic_sds_port_stopped_state_exit(
2550 struct sci_base_object *object)
2551{
2552 struct scic_sds_port *this_port;
2553
2554 this_port = (struct scic_sds_port *)object;
2555
2556 /* Enable and suspend the port task scheduler */
2557 scic_sds_port_enable_port_task_scheduler(this_port);
2558}
2559
2560/**
2561 *
2562 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
2563 *
2564 * This method will perform the actions required by the struct scic_sds_port on
2565 * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state
2566 * handlers for the struct scic_sds_port object, reports the port object as not ready
2567 * and starts the ready substate machine. none
2568 */
2569static void scic_sds_port_ready_state_enter(
2570 struct sci_base_object *object)
2571{
2572 struct scic_sds_port *this_port;
2573
2574 this_port = (struct scic_sds_port *)object;
2575
2576 /* Put the ready state handlers in place though they will not be there long */
2577 scic_sds_port_set_base_state_handlers(
2578 this_port, SCI_BASE_PORT_STATE_READY
2579 );
2580
2581 if (
2582 SCI_BASE_PORT_STATE_RESETTING
2583 == this_port->parent.state_machine.previous_state_id
2584 ) {
2585 scic_cb_port_hard_reset_complete(
2586 scic_sds_port_get_controller(this_port),
2587 this_port,
2588 SCI_SUCCESS
2589 );
2590 } else {
2591 /* Notify the caller that the port is not yet ready */
2592 scic_cb_port_not_ready(
2593 scic_sds_port_get_controller(this_port),
2594 this_port,
2595 SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS
2596 );
2597 }
2598
2599 /* Start the ready substate machine */
2600 sci_base_state_machine_start(
2601 scic_sds_port_get_ready_substate_machine(this_port)
2602 );
2603}
2604
2605/**
2606 *
2607 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
2608 *
2609 * This method will perform the actions required by the struct scic_sds_port on
2610 * exiting the SCI_BASE_STATE_READY. This function does nothing. none
2611 */
2612static void scic_sds_port_ready_state_exit(
2613 struct sci_base_object *object)
2614{
2615 struct scic_sds_port *this_port;
2616
2617 this_port = (struct scic_sds_port *)object;
2618
2619 sci_base_state_machine_stop(&this_port->ready_substate_machine);
2620}
2621
2622/**
2623 *
2624 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
2625 *
2626 * This method will perform the actions required by the struct scic_sds_port on
2627 * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the resetting
2628 * state handlers for the struct scic_sds_port object. none
2629 */
2630static void scic_sds_port_resetting_state_enter(
2631 struct sci_base_object *object)
2632{
2633 struct scic_sds_port *this_port;
2634
2635 this_port = (struct scic_sds_port *)object;
2636
2637 scic_sds_port_set_base_state_handlers(
2638 this_port, SCI_BASE_PORT_STATE_RESETTING
2639 );
2640
2641 scic_sds_port_set_direct_attached_device_id(
2642 this_port,
2643 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
2644 );
2645}
2646
2647/**
2648 *
2649 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
2650 *
2651 * This method will perform the actions required by the struct scic_sds_port on
2652 * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. none
2653 */
2654static void scic_sds_port_resetting_state_exit(
2655 struct sci_base_object *object)
2656{
2657 struct scic_sds_port *this_port;
2658
2659 this_port = (struct scic_sds_port *)object;
2660
2661 scic_cb_timer_stop(
2662 scic_sds_port_get_controller(this_port),
2663 this_port->timer_handle
2664 );
2665}
2666
2667/**
2668 *
2669 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
2670 *
2671 * This method will perform the actions required by the struct scic_sds_port on
2672 * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping
2673 * state handlers for the struct scic_sds_port object. none
2674 */
2675static void scic_sds_port_stopping_state_enter(
2676 struct sci_base_object *object)
2677{
2678 struct scic_sds_port *this_port;
2679
2680 this_port = (struct scic_sds_port *)object;
2681
2682 scic_sds_port_set_base_state_handlers(
2683 this_port, SCI_BASE_PORT_STATE_STOPPING
2684 );
2685}
2686
2687/**
2688 *
2689 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
2690 *
2691 * This method will perform the actions required by the struct scic_sds_port on
2692 * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. none
2693 */
2694static void scic_sds_port_stopping_state_exit(
2695 struct sci_base_object *object)
2696{
2697 struct scic_sds_port *this_port;
2698
2699 this_port = (struct scic_sds_port *)object;
2700
2701 scic_cb_timer_stop(
2702 scic_sds_port_get_controller(this_port),
2703 this_port->timer_handle
2704 );
2705}
2706
2707/**
2708 *
2709 * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object.
2710 *
2711 * This method will perform the actions required by the struct scic_sds_port on
2712 * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping
2713 * state handlers for the struct scic_sds_port object. none
2714 */
2715static void scic_sds_port_failed_state_enter(
2716 struct sci_base_object *object)
2717{
2718 struct scic_sds_port *this_port;
2719
2720 this_port = (struct scic_sds_port *)object;
2721
2722 scic_sds_port_set_base_state_handlers(
2723 this_port,
2724 SCI_BASE_PORT_STATE_FAILED
2725 );
2726
2727 scic_cb_port_hard_reset_complete(
2728 scic_sds_port_get_controller(this_port),
2729 this_port,
2730 SCI_FAILURE_TIMEOUT
2731 );
2732}
2733
2734/* --------------------------------------------------------------------------- */
2735
2736const struct sci_base_state scic_sds_port_state_table[] = {
2737 [SCI_BASE_PORT_STATE_STOPPED] = {
2738 .enter_state = scic_sds_port_stopped_state_enter,
2739 .exit_state = scic_sds_port_stopped_state_exit
2740 },
2741 [SCI_BASE_PORT_STATE_STOPPING] = {
2742 .enter_state = scic_sds_port_stopping_state_enter,
2743 .exit_state = scic_sds_port_stopping_state_exit
2744 },
2745 [SCI_BASE_PORT_STATE_READY] = {
2746 .enter_state = scic_sds_port_ready_state_enter,
2747 .exit_state = scic_sds_port_ready_state_exit
2748 },
2749 [SCI_BASE_PORT_STATE_RESETTING] = {
2750 .enter_state = scic_sds_port_resetting_state_enter,
2751 .exit_state = scic_sds_port_resetting_state_exit
2752 },
2753 [SCI_BASE_PORT_STATE_FAILED] = {
2754 .enter_state = scic_sds_port_failed_state_enter,
2755 }
2756};
2757