1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * This file is provided under a dual BSD/GPLv2 license. When using or
3*4882a593Smuzhiyun * redistributing this file, you may do so under either license.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * GPL LICENSE SUMMARY
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
10*4882a593Smuzhiyun * it under the terms of version 2 of the GNU General Public License as
11*4882a593Smuzhiyun * published by the Free Software Foundation.
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful, but
14*4882a593Smuzhiyun * WITHOUT ANY WARRANTY; without even the implied warranty of
15*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16*4882a593Smuzhiyun * General Public License for more details.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * You should have received a copy of the GNU General Public License
19*4882a593Smuzhiyun * along with this program; if not, write to the Free Software
20*4882a593Smuzhiyun * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21*4882a593Smuzhiyun * The full GNU General Public License is included in this distribution
22*4882a593Smuzhiyun * in the file called LICENSE.GPL.
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * BSD LICENSE
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27*4882a593Smuzhiyun * All rights reserved.
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or without
30*4882a593Smuzhiyun * modification, are permitted provided that the following conditions
31*4882a593Smuzhiyun * are met:
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * * Redistributions of source code must retain the above copyright
34*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer.
35*4882a593Smuzhiyun * * Redistributions in binary form must reproduce the above copyright
36*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer in
37*4882a593Smuzhiyun * the documentation and/or other materials provided with the
38*4882a593Smuzhiyun * distribution.
39*4882a593Smuzhiyun * * Neither the name of Intel Corporation nor the names of its
40*4882a593Smuzhiyun * contributors may be used to endorse or promote products derived
41*4882a593Smuzhiyun * from this software without specific prior written permission.
42*4882a593Smuzhiyun *
43*4882a593Smuzhiyun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44*4882a593Smuzhiyun * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45*4882a593Smuzhiyun * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46*4882a593Smuzhiyun * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47*4882a593Smuzhiyun * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48*4882a593Smuzhiyun * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49*4882a593Smuzhiyun * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50*4882a593Smuzhiyun * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51*4882a593Smuzhiyun * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52*4882a593Smuzhiyun * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53*4882a593Smuzhiyun * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54*4882a593Smuzhiyun */
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #ifndef _ISCI_PORT_H_
57*4882a593Smuzhiyun #define _ISCI_PORT_H_
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #include <scsi/libsas.h>
60*4882a593Smuzhiyun #include "isci.h"
61*4882a593Smuzhiyun #include "sas.h"
62*4882a593Smuzhiyun #include "phy.h"
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun #define SCIC_SDS_DUMMY_PORT 0xFF
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun #define PF_NOTIFY (1 << 0)
67*4882a593Smuzhiyun #define PF_RESUME (1 << 1)
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun struct isci_phy;
70*4882a593Smuzhiyun struct isci_host;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun enum isci_status {
73*4882a593Smuzhiyun isci_freed = 0x00,
74*4882a593Smuzhiyun isci_starting = 0x01,
75*4882a593Smuzhiyun isci_ready = 0x02,
76*4882a593Smuzhiyun isci_ready_for_io = 0x03,
77*4882a593Smuzhiyun isci_stopping = 0x04,
78*4882a593Smuzhiyun isci_stopped = 0x05,
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun /**
82*4882a593Smuzhiyun * struct isci_port - isci direct attached sas port object
83*4882a593Smuzhiyun * @ready_exit: several states constitute 'ready'. When exiting ready we
84*4882a593Smuzhiyun * need to take extra port-teardown actions that are
85*4882a593Smuzhiyun * skipped when exiting to another 'ready' state.
86*4882a593Smuzhiyun * @logical_port_index: software port index
87*4882a593Smuzhiyun * @physical_port_index: hardware port index
88*4882a593Smuzhiyun * @active_phy_mask: identifies phy members
89*4882a593Smuzhiyun * @enabled_phy_mask: phy mask for the port
90*4882a593Smuzhiyun * that are already part of the port
91*4882a593Smuzhiyun * @reserved_tag:
92*4882a593Smuzhiyun * @reserved_rni: reserver for port task scheduler workaround
93*4882a593Smuzhiyun * @started_request_count: reference count for outstanding commands
94*4882a593Smuzhiyun * @not_ready_reason: set during state transitions and notified
95*4882a593Smuzhiyun * @timer: timeout start/stop operations
96*4882a593Smuzhiyun */
97*4882a593Smuzhiyun struct isci_port {
98*4882a593Smuzhiyun struct isci_host *isci_host;
99*4882a593Smuzhiyun struct list_head remote_dev_list;
100*4882a593Smuzhiyun #define IPORT_RESET_PENDING 0
101*4882a593Smuzhiyun unsigned long state;
102*4882a593Smuzhiyun enum sci_status hard_reset_status;
103*4882a593Smuzhiyun struct sci_base_state_machine sm;
104*4882a593Smuzhiyun bool ready_exit;
105*4882a593Smuzhiyun u8 logical_port_index;
106*4882a593Smuzhiyun u8 physical_port_index;
107*4882a593Smuzhiyun u8 active_phy_mask;
108*4882a593Smuzhiyun u8 enabled_phy_mask;
109*4882a593Smuzhiyun u8 last_active_phy;
110*4882a593Smuzhiyun u16 reserved_rni;
111*4882a593Smuzhiyun u16 reserved_tag;
112*4882a593Smuzhiyun u32 started_request_count;
113*4882a593Smuzhiyun u32 assigned_device_count;
114*4882a593Smuzhiyun u32 hang_detect_users;
115*4882a593Smuzhiyun u32 not_ready_reason;
116*4882a593Smuzhiyun struct isci_phy *phy_table[SCI_MAX_PHYS];
117*4882a593Smuzhiyun struct isci_host *owning_controller;
118*4882a593Smuzhiyun struct sci_timer timer;
119*4882a593Smuzhiyun struct scu_port_task_scheduler_registers __iomem *port_task_scheduler_registers;
120*4882a593Smuzhiyun /* XXX rework: only one register, no need to replicate per-port */
121*4882a593Smuzhiyun u32 __iomem *port_pe_configuration_register;
122*4882a593Smuzhiyun struct scu_viit_entry __iomem *viit_registers;
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun enum sci_port_not_ready_reason_code {
126*4882a593Smuzhiyun SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS,
127*4882a593Smuzhiyun SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED,
128*4882a593Smuzhiyun SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION,
129*4882a593Smuzhiyun SCIC_PORT_NOT_READY_RECONFIGURING,
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun SCIC_PORT_NOT_READY_REASON_CODE_MAX
132*4882a593Smuzhiyun };
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun struct sci_port_end_point_properties {
135*4882a593Smuzhiyun struct sci_sas_address sas_address;
136*4882a593Smuzhiyun struct sci_phy_proto protocols;
137*4882a593Smuzhiyun };
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun struct sci_port_properties {
140*4882a593Smuzhiyun u32 index;
141*4882a593Smuzhiyun struct sci_port_end_point_properties local;
142*4882a593Smuzhiyun struct sci_port_end_point_properties remote;
143*4882a593Smuzhiyun u32 phy_mask;
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /**
147*4882a593Smuzhiyun * enum sci_port_states - port state machine states
148*4882a593Smuzhiyun * @SCI_PORT_STOPPED: port has successfully been stopped. In this state
149*4882a593Smuzhiyun * no new IO operations are permitted. This state is
150*4882a593Smuzhiyun * entered from the STOPPING state.
151*4882a593Smuzhiyun * @SCI_PORT_STOPPING: port is in the process of stopping. In this
152*4882a593Smuzhiyun * state no new IO operations are permitted, but
153*4882a593Smuzhiyun * existing IO operations are allowed to complete.
154*4882a593Smuzhiyun * This state is entered from the READY state.
155*4882a593Smuzhiyun * @SCI_PORT_READY: port is now ready. Thus, the user is able to
156*4882a593Smuzhiyun * perform IO operations on this port. This state is
157*4882a593Smuzhiyun * entered from the STARTING state.
158*4882a593Smuzhiyun * @SCI_PORT_SUB_WAITING: port is started and ready but has no active
159*4882a593Smuzhiyun * phys.
160*4882a593Smuzhiyun * @SCI_PORT_SUB_OPERATIONAL: port is started and ready and there is at
161*4882a593Smuzhiyun * least one phy operational.
162*4882a593Smuzhiyun * @SCI_PORT_SUB_CONFIGURING: port is started and there was an
163*4882a593Smuzhiyun * add/remove phy event. This state is only
164*4882a593Smuzhiyun * used in Automatic Port Configuration Mode
165*4882a593Smuzhiyun * (APC)
166*4882a593Smuzhiyun * @SCI_PORT_RESETTING: port is in the process of performing a hard
167*4882a593Smuzhiyun * reset. Thus, the user is unable to perform IO
168*4882a593Smuzhiyun * operations on this port. This state is entered
169*4882a593Smuzhiyun * from the READY state.
170*4882a593Smuzhiyun * @SCI_PORT_FAILED: port has failed a reset request. This state is
171*4882a593Smuzhiyun * entered when a port reset request times out. This
172*4882a593Smuzhiyun * state is entered from the RESETTING state.
173*4882a593Smuzhiyun */
174*4882a593Smuzhiyun #define PORT_STATES {\
175*4882a593Smuzhiyun C(PORT_STOPPED),\
176*4882a593Smuzhiyun C(PORT_STOPPING),\
177*4882a593Smuzhiyun C(PORT_READY),\
178*4882a593Smuzhiyun C(PORT_SUB_WAITING),\
179*4882a593Smuzhiyun C(PORT_SUB_OPERATIONAL),\
180*4882a593Smuzhiyun C(PORT_SUB_CONFIGURING),\
181*4882a593Smuzhiyun C(PORT_RESETTING),\
182*4882a593Smuzhiyun C(PORT_FAILED),\
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun #undef C
185*4882a593Smuzhiyun #define C(a) SCI_##a
186*4882a593Smuzhiyun enum sci_port_states PORT_STATES;
187*4882a593Smuzhiyun #undef C
188*4882a593Smuzhiyun
sci_port_decrement_request_count(struct isci_port * iport)189*4882a593Smuzhiyun static inline void sci_port_decrement_request_count(struct isci_port *iport)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun if (WARN_ONCE(iport->started_request_count == 0,
192*4882a593Smuzhiyun "%s: tried to decrement started_request_count past 0!?",
193*4882a593Smuzhiyun __func__))
194*4882a593Smuzhiyun /* pass */;
195*4882a593Smuzhiyun else
196*4882a593Smuzhiyun iport->started_request_count--;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun #define sci_port_active_phy(port, phy) \
200*4882a593Smuzhiyun (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0)
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun void sci_port_construct(
203*4882a593Smuzhiyun struct isci_port *iport,
204*4882a593Smuzhiyun u8 port_index,
205*4882a593Smuzhiyun struct isci_host *ihost);
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun enum sci_status sci_port_start(struct isci_port *iport);
208*4882a593Smuzhiyun enum sci_status sci_port_stop(struct isci_port *iport);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun enum sci_status sci_port_add_phy(
211*4882a593Smuzhiyun struct isci_port *iport,
212*4882a593Smuzhiyun struct isci_phy *iphy);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun enum sci_status sci_port_remove_phy(
215*4882a593Smuzhiyun struct isci_port *iport,
216*4882a593Smuzhiyun struct isci_phy *iphy);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun void sci_port_setup_transports(
219*4882a593Smuzhiyun struct isci_port *iport,
220*4882a593Smuzhiyun u32 device_id);
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun void isci_port_bcn_enable(struct isci_host *, struct isci_port *);
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun void sci_port_deactivate_phy(
225*4882a593Smuzhiyun struct isci_port *iport,
226*4882a593Smuzhiyun struct isci_phy *iphy,
227*4882a593Smuzhiyun bool do_notify_user);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun bool sci_port_link_detected(
230*4882a593Smuzhiyun struct isci_port *iport,
231*4882a593Smuzhiyun struct isci_phy *iphy);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun enum sci_status sci_port_get_properties(
234*4882a593Smuzhiyun struct isci_port *iport,
235*4882a593Smuzhiyun struct sci_port_properties *prop);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun enum sci_status sci_port_link_up(struct isci_port *iport,
238*4882a593Smuzhiyun struct isci_phy *iphy);
239*4882a593Smuzhiyun enum sci_status sci_port_link_down(struct isci_port *iport,
240*4882a593Smuzhiyun struct isci_phy *iphy);
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun struct isci_request;
243*4882a593Smuzhiyun struct isci_remote_device;
244*4882a593Smuzhiyun enum sci_status sci_port_start_io(
245*4882a593Smuzhiyun struct isci_port *iport,
246*4882a593Smuzhiyun struct isci_remote_device *idev,
247*4882a593Smuzhiyun struct isci_request *ireq);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun enum sci_status sci_port_complete_io(
250*4882a593Smuzhiyun struct isci_port *iport,
251*4882a593Smuzhiyun struct isci_remote_device *idev,
252*4882a593Smuzhiyun struct isci_request *ireq);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun enum sas_linkrate sci_port_get_max_allowed_speed(
255*4882a593Smuzhiyun struct isci_port *iport);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun void sci_port_broadcast_change_received(
258*4882a593Smuzhiyun struct isci_port *iport,
259*4882a593Smuzhiyun struct isci_phy *iphy);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun bool sci_port_is_valid_phy_assignment(
262*4882a593Smuzhiyun struct isci_port *iport,
263*4882a593Smuzhiyun u32 phy_index);
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun void sci_port_get_sas_address(
266*4882a593Smuzhiyun struct isci_port *iport,
267*4882a593Smuzhiyun struct sci_sas_address *sas_address);
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun void sci_port_get_attached_sas_address(
270*4882a593Smuzhiyun struct isci_port *iport,
271*4882a593Smuzhiyun struct sci_sas_address *sas_address);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun void sci_port_set_hang_detection_timeout(
274*4882a593Smuzhiyun struct isci_port *isci_port,
275*4882a593Smuzhiyun u32 timeout);
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun void isci_port_formed(struct asd_sas_phy *);
278*4882a593Smuzhiyun void isci_port_deformed(struct asd_sas_phy *);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport,
281*4882a593Smuzhiyun struct isci_phy *iphy);
282*4882a593Smuzhiyun int isci_ata_check_ready(struct domain_device *dev);
283*4882a593Smuzhiyun #endif /* !defined(_ISCI_PORT_H_) */
284