xref: /openbmc/linux/drivers/scsi/isci/host.h (revision 7c40a803)
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"
646f231ddaSDan Williams 
656f231ddaSDan Williams #define DRV_NAME "isci"
666f231ddaSDan Williams #define SCI_PCI_BAR_COUNT 2
676f231ddaSDan Williams #define SCI_NUM_MSI_X_INT 2
686f231ddaSDan Williams #define SCI_SMU_BAR       0
696f231ddaSDan Williams #define SCI_SMU_BAR_SIZE  (16*1024)
706f231ddaSDan Williams #define SCI_SCU_BAR       1
716f231ddaSDan Williams #define SCI_SCU_BAR_SIZE  (4*1024*1024)
726f231ddaSDan Williams #define SCI_IO_SPACE_BAR0 2
736f231ddaSDan Williams #define SCI_IO_SPACE_BAR1 3
746f231ddaSDan Williams #define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */
756f231ddaSDan Williams #define SCIC_CONTROLLER_STOP_TIMEOUT 5000
766f231ddaSDan Williams 
776f231ddaSDan Williams struct coherent_memory_info {
786f231ddaSDan Williams 	struct list_head node;
796f231ddaSDan Williams 	dma_addr_t dma_handle;
806f231ddaSDan Williams 	void *vaddr;
816f231ddaSDan Williams 	size_t size;
826f231ddaSDan Williams 	struct sci_physical_memory_descriptor *mde;
836f231ddaSDan Williams };
846f231ddaSDan Williams 
856f231ddaSDan Williams struct isci_host {
866f231ddaSDan Williams 	struct scic_sds_controller *core_controller;
876f231ddaSDan Williams 	union scic_oem_parameters oem_parameters;
886f231ddaSDan Williams 
896f231ddaSDan Williams 	int id; /* unique within a given pci device */
907c40a803SDan Williams 	struct list_head timers;
916f231ddaSDan Williams 	void *core_ctrl_memory;
926f231ddaSDan Williams 	struct dma_pool *dma_pool;
936f231ddaSDan Williams 	unsigned int dma_pool_alloc_size;
946f231ddaSDan Williams 	struct isci_phy phys[SCI_MAX_PHYS];
956f231ddaSDan Williams 
966f231ddaSDan Williams 	/* isci_ports and sas_ports are implicitly parallel to the
976f231ddaSDan Williams 	 * ports maintained by the core
986f231ddaSDan Williams 	 */
996f231ddaSDan Williams 	struct isci_port isci_ports[SCI_MAX_PORTS];
1006f231ddaSDan Williams 	struct asd_sas_port sas_ports[SCI_MAX_PORTS];
1016f231ddaSDan Williams 	struct sas_ha_struct sas_ha;
1026f231ddaSDan Williams 
1036f231ddaSDan Williams 	int can_queue;
1046f231ddaSDan Williams 	spinlock_t queue_lock;
1056f231ddaSDan Williams 	spinlock_t state_lock;
1066f231ddaSDan Williams 
1076f231ddaSDan Williams 	struct pci_dev *pdev;
1086f231ddaSDan Williams 
1096f231ddaSDan Williams 	enum isci_status status;
1100cf89d1dSDan Williams 	#define IHOST_START_PENDING 0
1110cf89d1dSDan Williams 	#define IHOST_STOP_PENDING 1
1120cf89d1dSDan Williams 	unsigned long flags;
1130cf89d1dSDan Williams 	wait_queue_head_t eventq;
1146f231ddaSDan Williams 	struct Scsi_Host *shost;
1156f231ddaSDan Williams 	struct tasklet_struct completion_tasklet;
1166f231ddaSDan Williams 	struct list_head mdl_struct_list;
1176f231ddaSDan Williams 	struct list_head requests_to_complete;
1186f231ddaSDan Williams 	struct list_head requests_to_abort;
1196f231ddaSDan Williams 	spinlock_t scic_lock;
1206f231ddaSDan Williams 	struct isci_host *next;
1216f231ddaSDan Williams };
1226f231ddaSDan Williams 
1236f231ddaSDan Williams 
1246f231ddaSDan Williams /**
1256f231ddaSDan Williams  * struct isci_pci_info - This class represents the pci function containing the
1266f231ddaSDan Williams  *    controllers. Depending on PCI SKU, there could be up to 2 controllers in
1276f231ddaSDan Williams  *    the PCI function.
1286f231ddaSDan Williams  */
1296f231ddaSDan Williams #define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS)
1306f231ddaSDan Williams 
1316f231ddaSDan Williams struct isci_pci_info {
1326f231ddaSDan Williams 	struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
1336f231ddaSDan Williams 	int core_lib_array_index;
1346f231ddaSDan Williams 	struct isci_host *hosts;
1356f231ddaSDan Williams };
1366f231ddaSDan Williams 
1376f231ddaSDan Williams static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
1386f231ddaSDan Williams {
1396f231ddaSDan Williams 	return pci_get_drvdata(pdev);
1406f231ddaSDan Williams }
1416f231ddaSDan Williams 
1426f231ddaSDan Williams #define for_each_isci_host(isci_host, pdev) \
1436f231ddaSDan Williams 	for (isci_host = to_pci_info(pdev)->hosts;\
1446f231ddaSDan Williams 	     isci_host; isci_host = isci_host->next)
1456f231ddaSDan Williams 
1466f231ddaSDan Williams static inline
1476f231ddaSDan Williams enum isci_status isci_host_get_state(
1486f231ddaSDan Williams 	struct isci_host *isci_host)
1496f231ddaSDan Williams {
1506f231ddaSDan Williams 	return isci_host->status;
1516f231ddaSDan Williams }
1526f231ddaSDan Williams 
1536f231ddaSDan Williams 
1546f231ddaSDan Williams static inline void isci_host_change_state(
1556f231ddaSDan Williams 	struct isci_host *isci_host,
1566f231ddaSDan Williams 	enum isci_status status)
1576f231ddaSDan Williams {
1586f231ddaSDan Williams 	unsigned long flags;
1596f231ddaSDan Williams 
1606f231ddaSDan Williams 	dev_dbg(&isci_host->pdev->dev,
1616f231ddaSDan Williams 		"%s: isci_host = %p, state = 0x%x",
1626f231ddaSDan Williams 		__func__,
1636f231ddaSDan Williams 		isci_host,
1646f231ddaSDan Williams 		status);
1656f231ddaSDan Williams 	spin_lock_irqsave(&isci_host->state_lock, flags);
1666f231ddaSDan Williams 	isci_host->status = status;
1676f231ddaSDan Williams 	spin_unlock_irqrestore(&isci_host->state_lock, flags);
1686f231ddaSDan Williams 
1696f231ddaSDan Williams }
1706f231ddaSDan Williams 
1716f231ddaSDan Williams static inline int isci_host_can_queue(
1726f231ddaSDan Williams 	struct isci_host *isci_host,
1736f231ddaSDan Williams 	int num)
1746f231ddaSDan Williams {
1756f231ddaSDan Williams 	int ret = 0;
1766f231ddaSDan Williams 	unsigned long flags;
1776f231ddaSDan Williams 
1786f231ddaSDan Williams 	spin_lock_irqsave(&isci_host->queue_lock, flags);
1796f231ddaSDan Williams 	if ((isci_host->can_queue - num) < 0) {
1806f231ddaSDan Williams 		dev_dbg(&isci_host->pdev->dev,
1816f231ddaSDan Williams 			"%s: isci_host->can_queue = %d\n",
1826f231ddaSDan Williams 			__func__,
1836f231ddaSDan Williams 			isci_host->can_queue);
1846f231ddaSDan Williams 		ret = -SAS_QUEUE_FULL;
1856f231ddaSDan Williams 
1866f231ddaSDan Williams 	} else
1876f231ddaSDan Williams 		isci_host->can_queue -= num;
1886f231ddaSDan Williams 
1896f231ddaSDan Williams 	spin_unlock_irqrestore(&isci_host->queue_lock, flags);
1906f231ddaSDan Williams 
1916f231ddaSDan Williams 	return ret;
1926f231ddaSDan Williams }
1936f231ddaSDan Williams 
1946f231ddaSDan Williams static inline void isci_host_can_dequeue(
1956f231ddaSDan Williams 	struct isci_host *isci_host,
1966f231ddaSDan Williams 	int num)
1976f231ddaSDan Williams {
1986f231ddaSDan Williams 	unsigned long flags;
1996f231ddaSDan Williams 
2006f231ddaSDan Williams 	spin_lock_irqsave(&isci_host->queue_lock, flags);
2016f231ddaSDan Williams 	isci_host->can_queue += num;
2026f231ddaSDan Williams 	spin_unlock_irqrestore(&isci_host->queue_lock, flags);
2036f231ddaSDan Williams }
2046f231ddaSDan Williams 
2050cf89d1dSDan Williams static inline void wait_for_start(struct isci_host *ihost)
2060cf89d1dSDan Williams {
2070cf89d1dSDan Williams 	wait_event(ihost->eventq, !test_bit(IHOST_START_PENDING, &ihost->flags));
2080cf89d1dSDan Williams }
2090cf89d1dSDan Williams 
2100cf89d1dSDan Williams static inline void wait_for_stop(struct isci_host *ihost)
2110cf89d1dSDan Williams {
2120cf89d1dSDan Williams 	wait_event(ihost->eventq, !test_bit(IHOST_STOP_PENDING, &ihost->flags));
2130cf89d1dSDan Williams }
2140cf89d1dSDan Williams 
2150cf89d1dSDan Williams 
2166f231ddaSDan Williams /**
2176f231ddaSDan Williams  * isci_host_from_sas_ha() - This accessor retrieves the isci_host object
2186f231ddaSDan Williams  *    reference from the Linux sas_ha_struct reference.
2196f231ddaSDan Williams  * @ha_struct,: This parameter points to the Linux sas_ha_struct object
2206f231ddaSDan Williams  *
2216f231ddaSDan Williams  * A reference to the associated isci_host structure.
2226f231ddaSDan Williams  */
2236f231ddaSDan Williams #define isci_host_from_sas_ha(ha_struct) \
2246f231ddaSDan Williams 	((struct isci_host *)(ha_struct)->lldd_ha)
2256f231ddaSDan Williams 
2266f231ddaSDan Williams /**
2276f231ddaSDan Williams  * isci_host_scan_finished() -
2286f231ddaSDan Williams  *
2296f231ddaSDan Williams  * This function is one of the SCSI Host Template functions. The SCSI midlayer
2306f231ddaSDan Williams  * calls this function during a target scan, approx. once every 10 millisecs.
2316f231ddaSDan Williams  */
2326f231ddaSDan Williams int isci_host_scan_finished(
2336f231ddaSDan Williams 	struct Scsi_Host *,
2346f231ddaSDan Williams 	unsigned long);
2356f231ddaSDan Williams 
2366f231ddaSDan Williams 
2376f231ddaSDan Williams /**
2386f231ddaSDan Williams  * isci_host_scan_start() -
2396f231ddaSDan Williams  *
2406f231ddaSDan Williams  * This function is one of the SCSI Host Template function, called by the SCSI
2416f231ddaSDan Williams  * mid layer berfore a target scan begins. The core library controller start
2426f231ddaSDan Williams  * routine is called from here.
2436f231ddaSDan Williams  */
2446f231ddaSDan Williams void isci_host_scan_start(
2456f231ddaSDan Williams 	struct Scsi_Host *);
2466f231ddaSDan Williams 
2476f231ddaSDan Williams /**
2486f231ddaSDan Williams  * isci_host_start_complete() -
2496f231ddaSDan Williams  *
2506f231ddaSDan Williams  * This function is called by the core library, through the ISCI Module, to
2516f231ddaSDan Williams  * indicate controller start status.
2526f231ddaSDan Williams  */
2536f231ddaSDan Williams void isci_host_start_complete(
2546f231ddaSDan Williams 	struct isci_host *,
2556f231ddaSDan Williams 	enum sci_status);
2566f231ddaSDan Williams 
2576f231ddaSDan Williams void isci_host_stop_complete(
2586f231ddaSDan Williams 	struct isci_host *isci_host,
2596f231ddaSDan Williams 	enum sci_status completion_status);
2606f231ddaSDan Williams 
2616f231ddaSDan Williams int isci_host_init(struct isci_host *);
2626f231ddaSDan Williams 
2636f231ddaSDan Williams void isci_host_init_controller_names(
2646f231ddaSDan Williams 	struct isci_host *isci_host,
2656f231ddaSDan Williams 	unsigned int controller_idx);
2666f231ddaSDan Williams 
2676f231ddaSDan Williams void isci_host_deinit(
2686f231ddaSDan Williams 	struct isci_host *);
2696f231ddaSDan Williams 
2706f231ddaSDan Williams void isci_host_port_link_up(
2716f231ddaSDan Williams 	struct isci_host *,
2726f231ddaSDan Williams 	struct scic_sds_port *,
2736f231ddaSDan Williams 	struct scic_sds_phy *);
2746f231ddaSDan Williams int isci_host_dev_found(struct domain_device *);
2756f231ddaSDan Williams 
2766f231ddaSDan Williams void isci_host_remote_device_start_complete(
2776f231ddaSDan Williams 	struct isci_host *,
2786f231ddaSDan Williams 	struct isci_remote_device *,
2796f231ddaSDan Williams 	enum sci_status);
2806f231ddaSDan Williams 
2816f231ddaSDan Williams #endif /* !defined(_SCI_HOST_H_) */
282