xref: /openbmc/linux/drivers/scsi/isci/host.h (revision 11cc5183)
16f231ddaSDan Williams /*
26f231ddaSDan Williams  * This file is provided under a dual BSD/GPLv2 license.  When using or
36f231ddaSDan Williams  * redistributing this file, you may do so under either license.
46f231ddaSDan Williams  *
56f231ddaSDan Williams  * GPL LICENSE SUMMARY
66f231ddaSDan Williams  *
76f231ddaSDan Williams  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
86f231ddaSDan Williams  *
96f231ddaSDan Williams  * This program is free software; you can redistribute it and/or modify
106f231ddaSDan Williams  * it under the terms of version 2 of the GNU General Public License as
116f231ddaSDan Williams  * published by the Free Software Foundation.
126f231ddaSDan Williams  *
136f231ddaSDan Williams  * This program is distributed in the hope that it will be useful, but
146f231ddaSDan Williams  * WITHOUT ANY WARRANTY; without even the implied warranty of
156f231ddaSDan Williams  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
166f231ddaSDan Williams  * General Public License for more details.
176f231ddaSDan Williams  *
186f231ddaSDan Williams  * You should have received a copy of the GNU General Public License
196f231ddaSDan Williams  * along with this program; if not, write to the Free Software
206f231ddaSDan Williams  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
216f231ddaSDan Williams  * The full GNU General Public License is included in this distribution
226f231ddaSDan Williams  * in the file called LICENSE.GPL.
236f231ddaSDan Williams  *
246f231ddaSDan Williams  * BSD LICENSE
256f231ddaSDan Williams  *
266f231ddaSDan Williams  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
276f231ddaSDan Williams  * All rights reserved.
286f231ddaSDan Williams  *
296f231ddaSDan Williams  * Redistribution and use in source and binary forms, with or without
306f231ddaSDan Williams  * modification, are permitted provided that the following conditions
316f231ddaSDan Williams  * are met:
326f231ddaSDan Williams  *
336f231ddaSDan Williams  *   * Redistributions of source code must retain the above copyright
346f231ddaSDan Williams  *     notice, this list of conditions and the following disclaimer.
356f231ddaSDan Williams  *   * Redistributions in binary form must reproduce the above copyright
366f231ddaSDan Williams  *     notice, this list of conditions and the following disclaimer in
376f231ddaSDan Williams  *     the documentation and/or other materials provided with the
386f231ddaSDan Williams  *     distribution.
396f231ddaSDan Williams  *   * Neither the name of Intel Corporation nor the names of its
406f231ddaSDan Williams  *     contributors may be used to endorse or promote products derived
416f231ddaSDan Williams  *     from this software without specific prior written permission.
426f231ddaSDan Williams  *
436f231ddaSDan Williams  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
446f231ddaSDan Williams  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
456f231ddaSDan Williams  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
466f231ddaSDan Williams  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
476f231ddaSDan Williams  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
486f231ddaSDan Williams  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
496f231ddaSDan Williams  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
506f231ddaSDan Williams  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
516f231ddaSDan Williams  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
526f231ddaSDan Williams  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
536f231ddaSDan Williams  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
546f231ddaSDan Williams  */
55ce2b3261SDan Williams #ifndef _SCI_HOST_H_
566f231ddaSDan Williams #define _SCI_HOST_H_
576f231ddaSDan Williams 
5811cc5183SDan Williams #include <scsi/sas_ata.h>
596f231ddaSDan Williams #include "remote_device.h"
60ce2b3261SDan Williams #include "phy.h"
6112ef6544SEdmund Nadolski #include "isci.h"
62cc9203bfSDan Williams #include "remote_node_table.h"
6363a3a15fSDan Williams #include "registers.h"
6463a3a15fSDan Williams #include "unsolicited_frame_control.h"
65e2f8db50SDan Williams #include "probe_roms.h"
66cc9203bfSDan Williams 
675076a1a9SDan Williams struct isci_request;
68cc9203bfSDan Williams struct scu_task_context;
69cc9203bfSDan Williams 
70e2f8db50SDan Williams 
71cc9203bfSDan Williams /**
7289a7301fSDan Williams  * struct sci_power_control -
73cc9203bfSDan Williams  *
74cc9203bfSDan Williams  * This structure defines the fields for managing power control for direct
75cc9203bfSDan Williams  * attached disk devices.
76cc9203bfSDan Williams  */
7789a7301fSDan Williams struct sci_power_control {
78cc9203bfSDan Williams 	/**
79cc9203bfSDan Williams 	 * This field is set when the power control timer is running and cleared when
80cc9203bfSDan Williams 	 * it is not.
81cc9203bfSDan Williams 	 */
82cc9203bfSDan Williams 	bool timer_started;
83cc9203bfSDan Williams 
84cc9203bfSDan Williams 	/**
850473661aSEdmund Nadolski 	 * Timer to control when the directed attached disks can consume power.
86cc9203bfSDan Williams 	 */
870473661aSEdmund Nadolski 	struct sci_timer timer;
88cc9203bfSDan Williams 
89cc9203bfSDan Williams 	/**
90cc9203bfSDan Williams 	 * This field is used to keep track of how many phys are put into the
91cc9203bfSDan Williams 	 * requesters field.
92cc9203bfSDan Williams 	 */
93cc9203bfSDan Williams 	u8 phys_waiting;
94cc9203bfSDan Williams 
95cc9203bfSDan Williams 	/**
96cc9203bfSDan Williams 	 * This field is used to keep track of how many phys have been granted to consume power
97cc9203bfSDan Williams 	 */
98cc9203bfSDan Williams 	u8 phys_granted_power;
99cc9203bfSDan Williams 
100cc9203bfSDan Williams 	/**
101cc9203bfSDan Williams 	 * This field is an array of phys that we are waiting on. The phys are direct
10289a7301fSDan Williams 	 * mapped into requesters via struct sci_phy.phy_index
103cc9203bfSDan Williams 	 */
10485280955SDan Williams 	struct isci_phy *requesters[SCI_MAX_PHYS];
105cc9203bfSDan Williams 
106cc9203bfSDan Williams };
107cc9203bfSDan Williams 
10889a7301fSDan Williams struct sci_port_configuration_agent;
109d9dcb4baSDan Williams typedef void (*port_config_fn)(struct isci_host *,
11089a7301fSDan Williams 			       struct sci_port_configuration_agent *,
111ffe191c9SDan Williams 			       struct isci_port *, struct isci_phy *);
112e2f8db50SDan Williams 
11389a7301fSDan Williams struct sci_port_configuration_agent {
114e2f8db50SDan Williams 	u16 phy_configured_mask;
115e2f8db50SDan Williams 	u16 phy_ready_mask;
116e2f8db50SDan Williams 	struct {
117e2f8db50SDan Williams 		u8 min_index;
118e2f8db50SDan Williams 		u8 max_index;
119e2f8db50SDan Williams 	} phy_valid_port_range[SCI_MAX_PHYS];
120e2f8db50SDan Williams 	bool timer_pending;
121e2f8db50SDan Williams 	port_config_fn link_up_handler;
122e2f8db50SDan Williams 	port_config_fn link_down_handler;
123ac0eeb4fSEdmund Nadolski 	struct sci_timer	timer;
124e2f8db50SDan Williams };
125e2f8db50SDan Williams 
126cc9203bfSDan Williams /**
127d9dcb4baSDan Williams  * isci_host - primary host/controller object
128d9dcb4baSDan Williams  * @timer: timeout start/stop operations
129d9dcb4baSDan Williams  * @device_table: rni (hw remote node index) to remote device lookup table
130d9dcb4baSDan Williams  * @available_remote_nodes: rni allocator
131d9dcb4baSDan Williams  * @power_control: manage device spin up
132d9dcb4baSDan Williams  * @io_request_sequence: generation number for tci's (task contexts)
133d9dcb4baSDan Williams  * @task_context_table: hw task context table
134d9dcb4baSDan Williams  * @remote_node_context_table: hw remote node context table
135d9dcb4baSDan Williams  * @completion_queue: hw-producer driver-consumer communication ring
136d9dcb4baSDan Williams  * @completion_queue_get: tracks the driver 'head' of the ring to notify hw
137d9dcb4baSDan Williams  * @logical_port_entries: min({driver|silicon}-supported-port-count)
138d9dcb4baSDan Williams  * @remote_node_entries: min({driver|silicon}-supported-node-count)
139d9dcb4baSDan Williams  * @task_context_entries: min({driver|silicon}-supported-task-count)
140d9dcb4baSDan Williams  * @phy_timer: phy startup timer
141d9dcb4baSDan Williams  * @invalid_phy_mask: if an invalid_link_up notification is reported a bit for
142d9dcb4baSDan Williams  * 		      the phy index is set so further notifications are not
143d9dcb4baSDan Williams  * 		      made.  Once the phy reports link up and is made part of a
144d9dcb4baSDan Williams  * 		      port then this bit is cleared.
145d9dcb4baSDan Williams 
146cc9203bfSDan Williams  */
147d9dcb4baSDan Williams struct isci_host {
148e301370aSEdmund Nadolski 	struct sci_base_state_machine sm;
149d9dcb4baSDan Williams 	/* XXX can we time this externally */
1506cb5853dSEdmund Nadolski 	struct sci_timer timer;
151d9dcb4baSDan Williams 	/* XXX drop reference module params directly */
15289a7301fSDan Williams 	struct sci_user_parameters user_parameters;
153d9dcb4baSDan Williams 	/* XXX no need to be a union */
15489a7301fSDan Williams 	struct sci_oem_params oem_parameters;
15589a7301fSDan Williams 	struct sci_port_configuration_agent port_agent;
15678a6f06eSDan Williams 	struct isci_remote_device *device_table[SCI_MAX_REMOTE_DEVICES];
15789a7301fSDan Williams 	struct sci_remote_node_table available_remote_nodes;
15889a7301fSDan Williams 	struct sci_power_control power_control;
159dd047c8eSDan Williams 	u8 io_request_sequence[SCI_MAX_IO_REQUESTS];
160cc9203bfSDan Williams 	struct scu_task_context *task_context_table;
161312e0c24SDan Williams 	dma_addr_t task_context_dma;
162cc9203bfSDan Williams 	union scu_remote_node_context *remote_node_context_table;
163cc9203bfSDan Williams 	u32 *completion_queue;
164cc9203bfSDan Williams 	u32 completion_queue_get;
165cc9203bfSDan Williams 	u32 logical_port_entries;
166cc9203bfSDan Williams 	u32 remote_node_entries;
167cc9203bfSDan Williams 	u32 task_context_entries;
16889a7301fSDan Williams 	struct sci_unsolicited_frame_control uf_control;
169cc9203bfSDan Williams 
170d9dcb4baSDan Williams 	/* phy startup */
171bb3dbdf6SEdmund Nadolski 	struct sci_timer phy_timer;
172d9dcb4baSDan Williams 	/* XXX kill */
173cc9203bfSDan Williams 	bool phy_startup_timer_pending;
174cc9203bfSDan Williams 	u32 next_phy_to_start;
17534a99158SDan Williams 	/* XXX convert to unsigned long and use bitops */
176cc9203bfSDan Williams 	u8 invalid_phy_mask;
177cc9203bfSDan Williams 
178d9dcb4baSDan Williams 	/* TODO attempt dynamic interrupt coalescing scheme */
179cc9203bfSDan Williams 	u16 interrupt_coalesce_number;
180cc9203bfSDan Williams 	u32 interrupt_coalesce_timeout;
181cc9203bfSDan Williams 	struct smu_registers __iomem *smu_registers;
182cc9203bfSDan Williams 	struct scu_registers __iomem *scu_registers;
183cc9203bfSDan Williams 
184ac668c69SDan Williams 	u16 tci_head;
185ac668c69SDan Williams 	u16 tci_tail;
186ac668c69SDan Williams 	u16 tci_pool[SCI_MAX_IO_REQUESTS];
187ac668c69SDan Williams 
1886f231ddaSDan Williams 	int id; /* unique within a given pci device */
1896f231ddaSDan Williams 	struct isci_phy phys[SCI_MAX_PHYS];
190e531381eSDan Williams 	struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */
191c132f692SDan Williams 	struct asd_sas_port sas_ports[SCI_MAX_PORTS];
1926f231ddaSDan Williams 	struct sas_ha_struct sas_ha;
1936f231ddaSDan Williams 
1946f231ddaSDan Williams 	spinlock_t state_lock;
1956f231ddaSDan Williams 	struct pci_dev *pdev;
1966f231ddaSDan Williams 	enum isci_status status;
1970cf89d1dSDan Williams 	#define IHOST_START_PENDING 0
1980cf89d1dSDan Williams 	#define IHOST_STOP_PENDING 1
1990cf89d1dSDan Williams 	unsigned long flags;
2000cf89d1dSDan Williams 	wait_queue_head_t eventq;
2016f231ddaSDan Williams 	struct Scsi_Host *shost;
2026f231ddaSDan Williams 	struct tasklet_struct completion_tasklet;
2036f231ddaSDan Williams 	struct list_head requests_to_complete;
20411b00c19SJeff Skirvin 	struct list_head requests_to_errorback;
2056f231ddaSDan Williams 	spinlock_t scic_lock;
206db056250SDan Williams 	struct isci_request *reqs[SCI_MAX_IO_REQUESTS];
20757f20f4eSDan Williams 	struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES];
2086f231ddaSDan Williams };
2096f231ddaSDan Williams 
2106f231ddaSDan Williams /**
21189a7301fSDan Williams  * enum sci_controller_states - This enumeration depicts all the states
212cc9203bfSDan Williams  *    for the common controller state machine.
213cc9203bfSDan Williams  */
21489a7301fSDan Williams enum sci_controller_states {
215cc9203bfSDan Williams 	/**
216cc9203bfSDan Williams 	 * Simply the initial state for the base controller state machine.
217cc9203bfSDan Williams 	 */
218e301370aSEdmund Nadolski 	SCIC_INITIAL = 0,
219cc9203bfSDan Williams 
220cc9203bfSDan Williams 	/**
221cc9203bfSDan Williams 	 * This state indicates that the controller is reset.  The memory for
222cc9203bfSDan Williams 	 * the controller is in it's initial state, but the controller requires
223cc9203bfSDan Williams 	 * initialization.
224cc9203bfSDan Williams 	 * This state is entered from the INITIAL state.
225cc9203bfSDan Williams 	 * This state is entered from the RESETTING state.
226cc9203bfSDan Williams 	 */
227e301370aSEdmund Nadolski 	SCIC_RESET,
228cc9203bfSDan Williams 
229cc9203bfSDan Williams 	/**
230cc9203bfSDan Williams 	 * This state is typically an action state that indicates the controller
231cc9203bfSDan Williams 	 * is in the process of initialization.  In this state no new IO operations
232cc9203bfSDan Williams 	 * are permitted.
233cc9203bfSDan Williams 	 * This state is entered from the RESET state.
234cc9203bfSDan Williams 	 */
235e301370aSEdmund Nadolski 	SCIC_INITIALIZING,
236cc9203bfSDan Williams 
237cc9203bfSDan Williams 	/**
238cc9203bfSDan Williams 	 * This state indicates that the controller has been successfully
239cc9203bfSDan Williams 	 * initialized.  In this state no new IO operations are permitted.
240cc9203bfSDan Williams 	 * This state is entered from the INITIALIZING state.
241cc9203bfSDan Williams 	 */
242e301370aSEdmund Nadolski 	SCIC_INITIALIZED,
243cc9203bfSDan Williams 
244cc9203bfSDan Williams 	/**
245cc9203bfSDan Williams 	 * This state indicates the the controller is in the process of becoming
246cc9203bfSDan Williams 	 * ready (i.e. starting).  In this state no new IO operations are permitted.
247cc9203bfSDan Williams 	 * This state is entered from the INITIALIZED state.
248cc9203bfSDan Williams 	 */
249e301370aSEdmund Nadolski 	SCIC_STARTING,
250cc9203bfSDan Williams 
251cc9203bfSDan Williams 	/**
252cc9203bfSDan Williams 	 * This state indicates the controller is now ready.  Thus, the user
253cc9203bfSDan Williams 	 * is able to perform IO operations on the controller.
254cc9203bfSDan Williams 	 * This state is entered from the STARTING state.
255cc9203bfSDan Williams 	 */
256e301370aSEdmund Nadolski 	SCIC_READY,
257cc9203bfSDan Williams 
258cc9203bfSDan Williams 	/**
259cc9203bfSDan Williams 	 * This state is typically an action state that indicates the controller
260cc9203bfSDan Williams 	 * is in the process of resetting.  Thus, the user is unable to perform
261cc9203bfSDan Williams 	 * IO operations on the controller.  A reset is considered destructive in
262cc9203bfSDan Williams 	 * most cases.
263cc9203bfSDan Williams 	 * This state is entered from the READY state.
264cc9203bfSDan Williams 	 * This state is entered from the FAILED state.
265cc9203bfSDan Williams 	 * This state is entered from the STOPPED state.
266cc9203bfSDan Williams 	 */
267e301370aSEdmund Nadolski 	SCIC_RESETTING,
268cc9203bfSDan Williams 
269cc9203bfSDan Williams 	/**
270cc9203bfSDan Williams 	 * This state indicates that the controller is in the process of stopping.
271cc9203bfSDan Williams 	 * In this state no new IO operations are permitted, but existing IO
272cc9203bfSDan Williams 	 * operations are allowed to complete.
273cc9203bfSDan Williams 	 * This state is entered from the READY state.
274cc9203bfSDan Williams 	 */
275e301370aSEdmund Nadolski 	SCIC_STOPPING,
276cc9203bfSDan Williams 
277cc9203bfSDan Williams 	/**
278cc9203bfSDan Williams 	 * This state indicates that the controller has successfully been stopped.
279cc9203bfSDan Williams 	 * In this state no new IO operations are permitted.
280cc9203bfSDan Williams 	 * This state is entered from the STOPPING state.
281cc9203bfSDan Williams 	 */
282e301370aSEdmund Nadolski 	SCIC_STOPPED,
283cc9203bfSDan Williams 
284cc9203bfSDan Williams 	/**
285cc9203bfSDan Williams 	 * This state indicates that the controller could not successfully be
286cc9203bfSDan Williams 	 * initialized.  In this state no new IO operations are permitted.
287cc9203bfSDan Williams 	 * This state is entered from the INITIALIZING state.
288cc9203bfSDan Williams 	 * This state is entered from the STARTING state.
289cc9203bfSDan Williams 	 * This state is entered from the STOPPING state.
290cc9203bfSDan Williams 	 * This state is entered from the RESETTING state.
291cc9203bfSDan Williams 	 */
292e301370aSEdmund Nadolski 	SCIC_FAILED,
293cc9203bfSDan Williams };
294cc9203bfSDan Williams 
295cc9203bfSDan Williams /**
2966f231ddaSDan Williams  * struct isci_pci_info - This class represents the pci function containing the
2976f231ddaSDan Williams  *    controllers. Depending on PCI SKU, there could be up to 2 controllers in
2986f231ddaSDan Williams  *    the PCI function.
2996f231ddaSDan Williams  */
3006f231ddaSDan Williams #define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS)
3016f231ddaSDan Williams 
3026f231ddaSDan Williams struct isci_pci_info {
3036f231ddaSDan Williams 	struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
304b329aff1SDan Williams 	struct isci_host *hosts[SCI_MAX_CONTROLLERS];
305d044af17SDan Williams 	struct isci_orom *orom;
3066f231ddaSDan Williams };
3076f231ddaSDan Williams 
3086f231ddaSDan Williams static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
3096f231ddaSDan Williams {
3106f231ddaSDan Williams 	return pci_get_drvdata(pdev);
3116f231ddaSDan Williams }
3126f231ddaSDan Williams 
313b329aff1SDan Williams #define for_each_isci_host(id, ihost, pdev) \
314b329aff1SDan Williams 	for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \
315b329aff1SDan Williams 	     id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \
316b329aff1SDan Williams 	     ihost = to_pci_info(pdev)->hosts[++id])
3176f231ddaSDan Williams 
318cc9203bfSDan Williams static inline enum isci_status isci_host_get_state(struct isci_host *isci_host)
3196f231ddaSDan Williams {
3206f231ddaSDan Williams 	return isci_host->status;
3216f231ddaSDan Williams }
3226f231ddaSDan Williams 
323cc9203bfSDan Williams static inline void isci_host_change_state(struct isci_host *isci_host,
3246f231ddaSDan Williams 					  enum isci_status status)
3256f231ddaSDan Williams {
3266f231ddaSDan Williams 	unsigned long flags;
3276f231ddaSDan Williams 
3286f231ddaSDan Williams 	dev_dbg(&isci_host->pdev->dev,
3296f231ddaSDan Williams 		"%s: isci_host = %p, state = 0x%x",
3306f231ddaSDan Williams 		__func__,
3316f231ddaSDan Williams 		isci_host,
3326f231ddaSDan Williams 		status);
3336f231ddaSDan Williams 	spin_lock_irqsave(&isci_host->state_lock, flags);
3346f231ddaSDan Williams 	isci_host->status = status;
3356f231ddaSDan Williams 	spin_unlock_irqrestore(&isci_host->state_lock, flags);
3366f231ddaSDan Williams 
3376f231ddaSDan Williams }
3386f231ddaSDan Williams 
3390cf89d1dSDan Williams static inline void wait_for_start(struct isci_host *ihost)
3400cf89d1dSDan Williams {
3410cf89d1dSDan Williams 	wait_event(ihost->eventq, !test_bit(IHOST_START_PENDING, &ihost->flags));
3420cf89d1dSDan Williams }
3430cf89d1dSDan Williams 
3440cf89d1dSDan Williams static inline void wait_for_stop(struct isci_host *ihost)
3450cf89d1dSDan Williams {
3460cf89d1dSDan Williams 	wait_event(ihost->eventq, !test_bit(IHOST_STOP_PENDING, &ihost->flags));
3470cf89d1dSDan Williams }
3480cf89d1dSDan Williams 
3496ad31fecSDan Williams static inline void wait_for_device_start(struct isci_host *ihost, struct isci_remote_device *idev)
3506ad31fecSDan Williams {
3516ad31fecSDan Williams 	wait_event(ihost->eventq, !test_bit(IDEV_START_PENDING, &idev->flags));
3526ad31fecSDan Williams }
3536ad31fecSDan Williams 
3546ad31fecSDan Williams static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_remote_device *idev)
3556ad31fecSDan Williams {
356d9c37390SDan Williams 	wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags));
3576ad31fecSDan Williams }
3580cf89d1dSDan Williams 
3594393aa4eSDan Williams static inline struct isci_host *dev_to_ihost(struct domain_device *dev)
3604393aa4eSDan Williams {
3614393aa4eSDan Williams 	return dev->port->ha->lldd_ha;
3624393aa4eSDan Williams }
3636f231ddaSDan Williams 
36434a99158SDan Williams /* we always use protocol engine group zero */
36534a99158SDan Williams #define ISCI_PEG 0
3666f231ddaSDan Williams 
36789a7301fSDan Williams /* see sci_controller_io_tag_allocate|free for how seq and tci are built */
368dd047c8eSDan Williams #define ISCI_TAG(seq, tci) (((u16) (seq)) << 12 | tci)
369cc9203bfSDan Williams 
370dd047c8eSDan Williams /* these are returned by the hardware, so sanitize them */
371dd047c8eSDan Williams #define ISCI_TAG_SEQ(tag) (((tag) >> 12) & (SCI_MAX_SEQ-1))
372dd047c8eSDan Williams #define ISCI_TAG_TCI(tag) ((tag) & (SCI_MAX_IO_REQUESTS-1))
373cc9203bfSDan Williams 
3749b4be528SDan Williams /* interrupt coalescing baseline: 9 == 3 to 5us interrupt delay per command */
3759b4be528SDan Williams #define ISCI_COALESCE_BASE 9
3769b4be528SDan Williams 
377cc9203bfSDan Williams /* expander attached sata devices require 3 rnc slots */
37889a7301fSDan Williams static inline int sci_remote_device_node_count(struct isci_remote_device *idev)
379cc9203bfSDan Williams {
38078a6f06eSDan Williams 	struct domain_device *dev = idev->domain_dev;
381cc9203bfSDan Williams 
38211cc5183SDan Williams 	if (dev_is_sata(dev) && dev->parent)
383cc9203bfSDan Williams 		return SCU_STP_REMOTE_NODE_COUNT;
384cc9203bfSDan Williams 	return SCU_SSP_REMOTE_NODE_COUNT;
385cc9203bfSDan Williams }
386cc9203bfSDan Williams 
387cc9203bfSDan Williams /**
38889a7301fSDan Williams  * sci_controller_clear_invalid_phy() -
389cc9203bfSDan Williams  *
390cc9203bfSDan Williams  * This macro will clear the bit in the invalid phy mask for this controller
391cc9203bfSDan Williams  * object.  This is used to control messages reported for invalid link up
392cc9203bfSDan Williams  * notifications.
393cc9203bfSDan Williams  */
39489a7301fSDan Williams #define sci_controller_clear_invalid_phy(controller, phy) \
395cc9203bfSDan Williams 	((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index))
396cc9203bfSDan Williams 
39778a6f06eSDan Williams static inline struct device *scirdev_to_dev(struct isci_remote_device *idev)
398cc9203bfSDan Williams {
399cc9203bfSDan Williams 	if (!idev || !idev->isci_port || !idev->isci_port->isci_host)
400cc9203bfSDan Williams 		return NULL;
401cc9203bfSDan Williams 
402cc9203bfSDan Williams 	return &idev->isci_port->isci_host->pdev->dev;
403cc9203bfSDan Williams }
404cc9203bfSDan Williams 
405dc00c8b6SDan Williams static inline bool is_a2(struct pci_dev *pdev)
406cc9203bfSDan Williams {
407dc00c8b6SDan Williams 	if (pdev->revision < 4)
408dc00c8b6SDan Williams 		return true;
409dc00c8b6SDan Williams 	return false;
410cc9203bfSDan Williams }
411cc9203bfSDan Williams 
412dc00c8b6SDan Williams static inline bool is_b0(struct pci_dev *pdev)
413cc9203bfSDan Williams {
414dc00c8b6SDan Williams 	if (pdev->revision == 4)
415dc00c8b6SDan Williams 		return true;
416dc00c8b6SDan Williams 	return false;
417cc9203bfSDan Williams }
418cc9203bfSDan Williams 
419dc00c8b6SDan Williams static inline bool is_c0(struct pci_dev *pdev)
420cc9203bfSDan Williams {
421afd13a1fSJeff Skirvin 	if (pdev->revision == 5)
422afd13a1fSJeff Skirvin 		return true;
423afd13a1fSJeff Skirvin 	return false;
424afd13a1fSJeff Skirvin }
425afd13a1fSJeff Skirvin 
426afd13a1fSJeff Skirvin static inline bool is_c1(struct pci_dev *pdev)
427afd13a1fSJeff Skirvin {
428afd13a1fSJeff Skirvin 	if (pdev->revision >= 6)
429dc00c8b6SDan Williams 		return true;
430dc00c8b6SDan Williams 	return false;
431cc9203bfSDan Williams }
432cc9203bfSDan Williams 
4339fee607fSJeff Skirvin enum cable_selections {
4349fee607fSJeff Skirvin 	short_cable     = 0,
4359fee607fSJeff Skirvin 	long_cable      = 1,
4369fee607fSJeff Skirvin 	medium_cable    = 2,
4379fee607fSJeff Skirvin 	undefined_cable = 3
4389fee607fSJeff Skirvin };
4399fee607fSJeff Skirvin 
4409fee607fSJeff Skirvin #define CABLE_OVERRIDE_DISABLED (0x10000)
4419fee607fSJeff Skirvin 
4429fee607fSJeff Skirvin static inline int is_cable_select_overridden(void)
4439fee607fSJeff Skirvin {
4449fee607fSJeff Skirvin 	return cable_selection_override < CABLE_OVERRIDE_DISABLED;
4459fee607fSJeff Skirvin }
4469fee607fSJeff Skirvin 
4479fee607fSJeff Skirvin enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy);
4489fee607fSJeff Skirvin void validate_cable_selections(struct isci_host *ihost);
4499fee607fSJeff Skirvin char *lookup_cable_names(enum cable_selections);
4509fee607fSJeff Skirvin 
451ad4f4c1dSDan Williams /* set hw control for 'activity', even though active enclosures seem to drive
452ad4f4c1dSDan Williams  * the activity led on their own.  Skip setting FSENG control on 'status' due
453ad4f4c1dSDan Williams  * to unexpected operation and 'error' due to not being a supported automatic
454ad4f4c1dSDan Williams  * FSENG output
455ad4f4c1dSDan Williams  */
456ad4f4c1dSDan Williams #define SGPIO_HW_CONTROL 0x00000443
457ad4f4c1dSDan Williams 
458ad4f4c1dSDan Williams static inline int isci_gpio_count(struct isci_host *ihost)
459ad4f4c1dSDan Williams {
460ad4f4c1dSDan Williams 	return ARRAY_SIZE(ihost->scu_registers->peg0.sgpio.output_data_select);
461ad4f4c1dSDan Williams }
462ad4f4c1dSDan Williams 
46389a7301fSDan Williams void sci_controller_post_request(struct isci_host *ihost,
464cc9203bfSDan Williams 				      u32 request);
46589a7301fSDan Williams void sci_controller_release_frame(struct isci_host *ihost,
466cc9203bfSDan Williams 				       u32 frame_index);
46789a7301fSDan Williams void sci_controller_copy_sata_response(void *response_buffer,
468cc9203bfSDan Williams 					    void *frame_header,
469cc9203bfSDan Williams 					    void *frame_buffer);
47089a7301fSDan Williams enum sci_status sci_controller_allocate_remote_node_context(struct isci_host *ihost,
47178a6f06eSDan Williams 								 struct isci_remote_device *idev,
472cc9203bfSDan Williams 								 u16 *node_id);
47389a7301fSDan Williams void sci_controller_free_remote_node_context(
474d9dcb4baSDan Williams 	struct isci_host *ihost,
47578a6f06eSDan Williams 	struct isci_remote_device *idev,
476cc9203bfSDan Williams 	u16 node_id);
477cc9203bfSDan Williams 
47889a7301fSDan Williams struct isci_request *sci_request_by_tag(struct isci_host *ihost,
479cc9203bfSDan Williams 					     u16 io_tag);
480cc9203bfSDan Williams 
48189a7301fSDan Williams void sci_controller_power_control_queue_insert(
482d9dcb4baSDan Williams 	struct isci_host *ihost,
48385280955SDan Williams 	struct isci_phy *iphy);
484cc9203bfSDan Williams 
48589a7301fSDan Williams void sci_controller_power_control_queue_remove(
486d9dcb4baSDan Williams 	struct isci_host *ihost,
48785280955SDan Williams 	struct isci_phy *iphy);
488cc9203bfSDan Williams 
48989a7301fSDan Williams void sci_controller_link_up(
490d9dcb4baSDan Williams 	struct isci_host *ihost,
491ffe191c9SDan Williams 	struct isci_port *iport,
49285280955SDan Williams 	struct isci_phy *iphy);
493cc9203bfSDan Williams 
49489a7301fSDan Williams void sci_controller_link_down(
495d9dcb4baSDan Williams 	struct isci_host *ihost,
496ffe191c9SDan Williams 	struct isci_port *iport,
49785280955SDan Williams 	struct isci_phy *iphy);
498cc9203bfSDan Williams 
49989a7301fSDan Williams void sci_controller_remote_device_stopped(
500d9dcb4baSDan Williams 	struct isci_host *ihost,
50178a6f06eSDan Williams 	struct isci_remote_device *idev);
502cc9203bfSDan Williams 
50389a7301fSDan Williams void sci_controller_copy_task_context(
504d9dcb4baSDan Williams 	struct isci_host *ihost,
5055076a1a9SDan Williams 	struct isci_request *ireq);
506cc9203bfSDan Williams 
50789a7301fSDan Williams void sci_controller_register_setup(struct isci_host *ihost);
508cc9203bfSDan Williams 
50989a7301fSDan Williams enum sci_status sci_controller_continue_io(struct isci_request *ireq);
510cc9203bfSDan Williams int isci_host_scan_finished(struct Scsi_Host *, unsigned long);
511cc9203bfSDan Williams void isci_host_scan_start(struct Scsi_Host *);
512312e0c24SDan Williams u16 isci_alloc_tag(struct isci_host *ihost);
513312e0c24SDan Williams enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag);
514312e0c24SDan Williams void isci_tci_free(struct isci_host *ihost, u16 tci);
5156f231ddaSDan Williams 
5166f231ddaSDan Williams int isci_host_init(struct isci_host *);
5176f231ddaSDan Williams 
5186f231ddaSDan Williams void isci_host_init_controller_names(
5196f231ddaSDan Williams 	struct isci_host *isci_host,
5206f231ddaSDan Williams 	unsigned int controller_idx);
5216f231ddaSDan Williams 
5226f231ddaSDan Williams void isci_host_deinit(
5236f231ddaSDan Williams 	struct isci_host *);
5246f231ddaSDan Williams 
5256f231ddaSDan Williams void isci_host_port_link_up(
5266f231ddaSDan Williams 	struct isci_host *,
527ffe191c9SDan Williams 	struct isci_port *,
52885280955SDan Williams 	struct isci_phy *);
5296f231ddaSDan Williams int isci_host_dev_found(struct domain_device *);
5306f231ddaSDan Williams 
5316f231ddaSDan Williams void isci_host_remote_device_start_complete(
5326f231ddaSDan Williams 	struct isci_host *,
5336f231ddaSDan Williams 	struct isci_remote_device *,
5346f231ddaSDan Williams 	enum sci_status);
5356f231ddaSDan Williams 
53689a7301fSDan Williams void sci_controller_disable_interrupts(
537d9dcb4baSDan Williams 	struct isci_host *ihost);
538cc9203bfSDan Williams 
53989a7301fSDan Williams enum sci_status sci_controller_start_io(
540d9dcb4baSDan Williams 	struct isci_host *ihost,
54178a6f06eSDan Williams 	struct isci_remote_device *idev,
5425076a1a9SDan Williams 	struct isci_request *ireq);
543cc9203bfSDan Williams 
54489a7301fSDan Williams enum sci_task_status sci_controller_start_task(
545d9dcb4baSDan Williams 	struct isci_host *ihost,
54678a6f06eSDan Williams 	struct isci_remote_device *idev,
5475076a1a9SDan Williams 	struct isci_request *ireq);
548cc9203bfSDan Williams 
54989a7301fSDan Williams enum sci_status sci_controller_terminate_request(
550d9dcb4baSDan Williams 	struct isci_host *ihost,
55178a6f06eSDan Williams 	struct isci_remote_device *idev,
5525076a1a9SDan Williams 	struct isci_request *ireq);
553cc9203bfSDan Williams 
55489a7301fSDan Williams enum sci_status sci_controller_complete_io(
555d9dcb4baSDan Williams 	struct isci_host *ihost,
55678a6f06eSDan Williams 	struct isci_remote_device *idev,
5575076a1a9SDan Williams 	struct isci_request *ireq);
558cc9203bfSDan Williams 
55989a7301fSDan Williams void sci_port_configuration_agent_construct(
56089a7301fSDan Williams 	struct sci_port_configuration_agent *port_agent);
561e2f8db50SDan Williams 
56289a7301fSDan Williams enum sci_status sci_port_configuration_agent_initialize(
563d9dcb4baSDan Williams 	struct isci_host *ihost,
56489a7301fSDan Williams 	struct sci_port_configuration_agent *port_agent);
565ad4f4c1dSDan Williams 
566ad4f4c1dSDan Williams int isci_gpio_write(struct sas_ha_struct *, u8 reg_type, u8 reg_index,
567ad4f4c1dSDan Williams 		    u8 reg_count, u8 *write_data);
568cc9203bfSDan Williams #endif
569