xref: /openbmc/linux/drivers/scsi/isci/host.h (revision 11b00c19)
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  */
556f231ddaSDan Williams 
566f231ddaSDan Williams 
576f231ddaSDan Williams #if !defined(_SCI_HOST_H_)
586f231ddaSDan Williams #define _SCI_HOST_H_
596f231ddaSDan Williams 
606f231ddaSDan Williams #include "phy.h"
616f231ddaSDan Williams /*#include "task.h"*/
626f231ddaSDan Williams #include "timers.h"
636f231ddaSDan Williams #include "remote_device.h"
64d9c37390SDan Williams #include "scic_remote_device.h"
656f231ddaSDan Williams 
666f231ddaSDan Williams #define DRV_NAME "isci"
676f231ddaSDan Williams #define SCI_PCI_BAR_COUNT 2
686f231ddaSDan Williams #define SCI_NUM_MSI_X_INT 2
696f231ddaSDan Williams #define SCI_SMU_BAR       0
706f231ddaSDan Williams #define SCI_SMU_BAR_SIZE  (16*1024)
716f231ddaSDan Williams #define SCI_SCU_BAR       1
726f231ddaSDan Williams #define SCI_SCU_BAR_SIZE  (4*1024*1024)
736f231ddaSDan Williams #define SCI_IO_SPACE_BAR0 2
746f231ddaSDan Williams #define SCI_IO_SPACE_BAR1 3
756f231ddaSDan Williams #define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */
766f231ddaSDan Williams #define SCIC_CONTROLLER_STOP_TIMEOUT 5000
776f231ddaSDan Williams 
786f231ddaSDan Williams struct coherent_memory_info {
796f231ddaSDan Williams 	struct list_head node;
806f231ddaSDan Williams 	dma_addr_t dma_handle;
816f231ddaSDan Williams 	void *vaddr;
826f231ddaSDan Williams 	size_t size;
836f231ddaSDan Williams 	struct sci_physical_memory_descriptor *mde;
846f231ddaSDan Williams };
856f231ddaSDan Williams 
866f231ddaSDan Williams struct isci_host {
876f231ddaSDan Williams 	struct scic_sds_controller *core_controller;
886f231ddaSDan Williams 	union scic_oem_parameters oem_parameters;
896f231ddaSDan Williams 
906f231ddaSDan Williams 	int id; /* unique within a given pci device */
917c40a803SDan Williams 	struct list_head timers;
926f231ddaSDan Williams 	void *core_ctrl_memory;
936f231ddaSDan Williams 	struct dma_pool *dma_pool;
946f231ddaSDan Williams 	unsigned int dma_pool_alloc_size;
956f231ddaSDan Williams 	struct isci_phy phys[SCI_MAX_PHYS];
966f231ddaSDan Williams 
976f231ddaSDan Williams 	/* isci_ports and sas_ports are implicitly parallel to the
986f231ddaSDan Williams 	 * ports maintained by the core
996f231ddaSDan Williams 	 */
1006f231ddaSDan Williams 	struct isci_port isci_ports[SCI_MAX_PORTS];
1016f231ddaSDan Williams 	struct asd_sas_port sas_ports[SCI_MAX_PORTS];
1026f231ddaSDan Williams 	struct sas_ha_struct sas_ha;
1036f231ddaSDan Williams 
1046f231ddaSDan Williams 	int can_queue;
1056f231ddaSDan Williams 	spinlock_t queue_lock;
1066f231ddaSDan Williams 	spinlock_t state_lock;
1076f231ddaSDan Williams 
1086f231ddaSDan Williams 	struct pci_dev *pdev;
1096f231ddaSDan Williams 
1106f231ddaSDan Williams 	enum isci_status status;
1110cf89d1dSDan Williams 	#define IHOST_START_PENDING 0
1120cf89d1dSDan Williams 	#define IHOST_STOP_PENDING 1
1130cf89d1dSDan Williams 	unsigned long flags;
1140cf89d1dSDan Williams 	wait_queue_head_t eventq;
1156f231ddaSDan Williams 	struct Scsi_Host *shost;
1166f231ddaSDan Williams 	struct tasklet_struct completion_tasklet;
1176f231ddaSDan Williams 	struct list_head mdl_struct_list;
1186f231ddaSDan Williams 	struct list_head requests_to_complete;
11911b00c19SJeff Skirvin 	struct list_head requests_to_errorback;
1206f231ddaSDan Williams 	spinlock_t scic_lock;
121d9c37390SDan Williams 
122d9c37390SDan Williams 	/* careful only access this via idev_by_id */
123d9c37390SDan Williams 	struct isci_remote_device devices[0];
1246f231ddaSDan Williams };
1256f231ddaSDan Williams 
126d9c37390SDan Williams static inline struct isci_remote_device *idev_by_id(struct isci_host *ihost, int i)
127d9c37390SDan Williams {
128d9c37390SDan Williams 	void *p = ihost->devices;
129d9c37390SDan Williams 
130d9c37390SDan Williams 	return p + i * (sizeof(struct isci_remote_device) +
131d9c37390SDan Williams 			scic_remote_device_get_object_size());
132d9c37390SDan Williams }
1336f231ddaSDan Williams 
1346f231ddaSDan Williams /**
1356f231ddaSDan Williams  * struct isci_pci_info - This class represents the pci function containing the
1366f231ddaSDan Williams  *    controllers. Depending on PCI SKU, there could be up to 2 controllers in
1376f231ddaSDan Williams  *    the PCI function.
1386f231ddaSDan Williams  */
1396f231ddaSDan Williams #define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS)
1406f231ddaSDan Williams 
1416f231ddaSDan Williams struct isci_pci_info {
1426f231ddaSDan Williams 	struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
1436f231ddaSDan Williams 	int core_lib_array_index;
144b329aff1SDan Williams 	struct isci_host *hosts[SCI_MAX_CONTROLLERS];
1456f231ddaSDan Williams };
1466f231ddaSDan Williams 
1476f231ddaSDan Williams static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
1486f231ddaSDan Williams {
1496f231ddaSDan Williams 	return pci_get_drvdata(pdev);
1506f231ddaSDan Williams }
1516f231ddaSDan Williams 
152b329aff1SDan Williams #define for_each_isci_host(id, ihost, pdev) \
153b329aff1SDan Williams 	for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \
154b329aff1SDan Williams 	     id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \
155b329aff1SDan Williams 	     ihost = to_pci_info(pdev)->hosts[++id])
1566f231ddaSDan Williams 
1576f231ddaSDan Williams static inline
1586f231ddaSDan Williams enum isci_status isci_host_get_state(
1596f231ddaSDan Williams 	struct isci_host *isci_host)
1606f231ddaSDan Williams {
1616f231ddaSDan Williams 	return isci_host->status;
1626f231ddaSDan Williams }
1636f231ddaSDan Williams 
1646f231ddaSDan Williams 
1656f231ddaSDan Williams static inline void isci_host_change_state(
1666f231ddaSDan Williams 	struct isci_host *isci_host,
1676f231ddaSDan Williams 	enum isci_status status)
1686f231ddaSDan Williams {
1696f231ddaSDan Williams 	unsigned long flags;
1706f231ddaSDan Williams 
1716f231ddaSDan Williams 	dev_dbg(&isci_host->pdev->dev,
1726f231ddaSDan Williams 		"%s: isci_host = %p, state = 0x%x",
1736f231ddaSDan Williams 		__func__,
1746f231ddaSDan Williams 		isci_host,
1756f231ddaSDan Williams 		status);
1766f231ddaSDan Williams 	spin_lock_irqsave(&isci_host->state_lock, flags);
1776f231ddaSDan Williams 	isci_host->status = status;
1786f231ddaSDan Williams 	spin_unlock_irqrestore(&isci_host->state_lock, flags);
1796f231ddaSDan Williams 
1806f231ddaSDan Williams }
1816f231ddaSDan Williams 
1826f231ddaSDan Williams static inline int isci_host_can_queue(
1836f231ddaSDan Williams 	struct isci_host *isci_host,
1846f231ddaSDan Williams 	int num)
1856f231ddaSDan Williams {
1866f231ddaSDan Williams 	int ret = 0;
1876f231ddaSDan Williams 	unsigned long flags;
1886f231ddaSDan Williams 
1896f231ddaSDan Williams 	spin_lock_irqsave(&isci_host->queue_lock, flags);
1906f231ddaSDan Williams 	if ((isci_host->can_queue - num) < 0) {
1916f231ddaSDan Williams 		dev_dbg(&isci_host->pdev->dev,
1926f231ddaSDan Williams 			"%s: isci_host->can_queue = %d\n",
1936f231ddaSDan Williams 			__func__,
1946f231ddaSDan Williams 			isci_host->can_queue);
1956f231ddaSDan Williams 		ret = -SAS_QUEUE_FULL;
1966f231ddaSDan Williams 
1976f231ddaSDan Williams 	} else
1986f231ddaSDan Williams 		isci_host->can_queue -= num;
1996f231ddaSDan Williams 
2006f231ddaSDan Williams 	spin_unlock_irqrestore(&isci_host->queue_lock, flags);
2016f231ddaSDan Williams 
2026f231ddaSDan Williams 	return ret;
2036f231ddaSDan Williams }
2046f231ddaSDan Williams 
2056f231ddaSDan Williams static inline void isci_host_can_dequeue(
2066f231ddaSDan Williams 	struct isci_host *isci_host,
2076f231ddaSDan Williams 	int num)
2086f231ddaSDan Williams {
2096f231ddaSDan Williams 	unsigned long flags;
2106f231ddaSDan Williams 
2116f231ddaSDan Williams 	spin_lock_irqsave(&isci_host->queue_lock, flags);
2126f231ddaSDan Williams 	isci_host->can_queue += num;
2136f231ddaSDan Williams 	spin_unlock_irqrestore(&isci_host->queue_lock, flags);
2146f231ddaSDan Williams }
2156f231ddaSDan Williams 
2160cf89d1dSDan Williams static inline void wait_for_start(struct isci_host *ihost)
2170cf89d1dSDan Williams {
2180cf89d1dSDan Williams 	wait_event(ihost->eventq, !test_bit(IHOST_START_PENDING, &ihost->flags));
2190cf89d1dSDan Williams }
2200cf89d1dSDan Williams 
2210cf89d1dSDan Williams static inline void wait_for_stop(struct isci_host *ihost)
2220cf89d1dSDan Williams {
2230cf89d1dSDan Williams 	wait_event(ihost->eventq, !test_bit(IHOST_STOP_PENDING, &ihost->flags));
2240cf89d1dSDan Williams }
2250cf89d1dSDan Williams 
2266ad31fecSDan Williams static inline void wait_for_device_start(struct isci_host *ihost, struct isci_remote_device *idev)
2276ad31fecSDan Williams {
2286ad31fecSDan Williams 	wait_event(ihost->eventq, !test_bit(IDEV_START_PENDING, &idev->flags));
2296ad31fecSDan Williams }
2306ad31fecSDan Williams 
2316ad31fecSDan Williams static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_remote_device *idev)
2326ad31fecSDan Williams {
233d9c37390SDan Williams 	wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags));
2346ad31fecSDan Williams }
2350cf89d1dSDan Williams 
2366f231ddaSDan Williams /**
2376f231ddaSDan Williams  * isci_host_from_sas_ha() - This accessor retrieves the isci_host object
2386f231ddaSDan Williams  *    reference from the Linux sas_ha_struct reference.
2396f231ddaSDan Williams  * @ha_struct,: This parameter points to the Linux sas_ha_struct object
2406f231ddaSDan Williams  *
2416f231ddaSDan Williams  * A reference to the associated isci_host structure.
2426f231ddaSDan Williams  */
2436f231ddaSDan Williams #define isci_host_from_sas_ha(ha_struct) \
2446f231ddaSDan Williams 	((struct isci_host *)(ha_struct)->lldd_ha)
2456f231ddaSDan Williams 
2466f231ddaSDan Williams /**
2476f231ddaSDan Williams  * isci_host_scan_finished() -
2486f231ddaSDan Williams  *
2496f231ddaSDan Williams  * This function is one of the SCSI Host Template functions. The SCSI midlayer
2506f231ddaSDan Williams  * calls this function during a target scan, approx. once every 10 millisecs.
2516f231ddaSDan Williams  */
2526f231ddaSDan Williams int isci_host_scan_finished(
2536f231ddaSDan Williams 	struct Scsi_Host *,
2546f231ddaSDan Williams 	unsigned long);
2556f231ddaSDan Williams 
2566f231ddaSDan Williams 
2576f231ddaSDan Williams /**
2586f231ddaSDan Williams  * isci_host_scan_start() -
2596f231ddaSDan Williams  *
2606f231ddaSDan Williams  * This function is one of the SCSI Host Template function, called by the SCSI
2616f231ddaSDan Williams  * mid layer berfore a target scan begins. The core library controller start
2626f231ddaSDan Williams  * routine is called from here.
2636f231ddaSDan Williams  */
2646f231ddaSDan Williams void isci_host_scan_start(
2656f231ddaSDan Williams 	struct Scsi_Host *);
2666f231ddaSDan Williams 
2676f231ddaSDan Williams /**
2686f231ddaSDan Williams  * isci_host_start_complete() -
2696f231ddaSDan Williams  *
2706f231ddaSDan Williams  * This function is called by the core library, through the ISCI Module, to
2716f231ddaSDan Williams  * indicate controller start status.
2726f231ddaSDan Williams  */
2736f231ddaSDan Williams void isci_host_start_complete(
2746f231ddaSDan Williams 	struct isci_host *,
2756f231ddaSDan Williams 	enum sci_status);
2766f231ddaSDan Williams 
2776f231ddaSDan Williams void isci_host_stop_complete(
2786f231ddaSDan Williams 	struct isci_host *isci_host,
2796f231ddaSDan Williams 	enum sci_status completion_status);
2806f231ddaSDan Williams 
2816f231ddaSDan Williams int isci_host_init(struct isci_host *);
2826f231ddaSDan Williams 
2836f231ddaSDan Williams void isci_host_init_controller_names(
2846f231ddaSDan Williams 	struct isci_host *isci_host,
2856f231ddaSDan Williams 	unsigned int controller_idx);
2866f231ddaSDan Williams 
2876f231ddaSDan Williams void isci_host_deinit(
2886f231ddaSDan Williams 	struct isci_host *);
2896f231ddaSDan Williams 
2906f231ddaSDan Williams void isci_host_port_link_up(
2916f231ddaSDan Williams 	struct isci_host *,
2926f231ddaSDan Williams 	struct scic_sds_port *,
2936f231ddaSDan Williams 	struct scic_sds_phy *);
2946f231ddaSDan Williams int isci_host_dev_found(struct domain_device *);
2956f231ddaSDan Williams 
2966f231ddaSDan Williams void isci_host_remote_device_start_complete(
2976f231ddaSDan Williams 	struct isci_host *,
2986f231ddaSDan Williams 	struct isci_remote_device *,
2996f231ddaSDan Williams 	enum sci_status);
3006f231ddaSDan Williams 
3016f231ddaSDan Williams #endif /* !defined(_SCI_HOST_H_) */
302