xref: /OK3568_Linux_fs/kernel/drivers/scsi/isci/port.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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