xref: /linux/drivers/scsi/isci/host.h (revision 57f20f4ed6fb702339be2ef4dea9d15e6a7d0d07)
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 isci_host {
796f231ddaSDan Williams 	struct scic_sds_controller *core_controller;
806f231ddaSDan Williams 	union scic_oem_parameters oem_parameters;
816f231ddaSDan Williams 
826f231ddaSDan Williams 	int id; /* unique within a given pci device */
837c40a803SDan Williams 	struct list_head timers;
846f231ddaSDan Williams 	void *core_ctrl_memory;
856f231ddaSDan Williams 	struct dma_pool *dma_pool;
866f231ddaSDan Williams 	unsigned int dma_pool_alloc_size;
876f231ddaSDan Williams 	struct isci_phy phys[SCI_MAX_PHYS];
886f231ddaSDan Williams 
896f231ddaSDan Williams 	/* isci_ports and sas_ports are implicitly parallel to the
906f231ddaSDan Williams 	 * ports maintained by the core
916f231ddaSDan Williams 	 */
926f231ddaSDan Williams 	struct isci_port isci_ports[SCI_MAX_PORTS];
936f231ddaSDan Williams 	struct asd_sas_port sas_ports[SCI_MAX_PORTS];
946f231ddaSDan Williams 	struct sas_ha_struct sas_ha;
956f231ddaSDan Williams 
966f231ddaSDan Williams 	int can_queue;
976f231ddaSDan Williams 	spinlock_t queue_lock;
986f231ddaSDan Williams 	spinlock_t state_lock;
996f231ddaSDan Williams 
1006f231ddaSDan Williams 	struct pci_dev *pdev;
1016f231ddaSDan Williams 
1026f231ddaSDan Williams 	enum isci_status status;
1030cf89d1dSDan Williams 	#define IHOST_START_PENDING 0
1040cf89d1dSDan Williams 	#define IHOST_STOP_PENDING 1
1050cf89d1dSDan Williams 	unsigned long flags;
1060cf89d1dSDan Williams 	wait_queue_head_t eventq;
1076f231ddaSDan Williams 	struct Scsi_Host *shost;
1086f231ddaSDan Williams 	struct tasklet_struct completion_tasklet;
1096f231ddaSDan Williams 	struct list_head requests_to_complete;
11011b00c19SJeff Skirvin 	struct list_head requests_to_errorback;
1116f231ddaSDan Williams 	spinlock_t scic_lock;
112d9c37390SDan Williams 
113*57f20f4eSDan Williams 	struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES];
1146f231ddaSDan Williams };
1156f231ddaSDan Williams 
1166f231ddaSDan Williams /**
1176f231ddaSDan Williams  * struct isci_pci_info - This class represents the pci function containing the
1186f231ddaSDan Williams  *    controllers. Depending on PCI SKU, there could be up to 2 controllers in
1196f231ddaSDan Williams  *    the PCI function.
1206f231ddaSDan Williams  */
1216f231ddaSDan Williams #define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS)
1226f231ddaSDan Williams 
1236f231ddaSDan Williams struct isci_pci_info {
1246f231ddaSDan Williams 	struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
125b329aff1SDan Williams 	struct isci_host *hosts[SCI_MAX_CONTROLLERS];
126d044af17SDan Williams 	struct isci_orom *orom;
1276f231ddaSDan Williams };
1286f231ddaSDan Williams 
1296f231ddaSDan Williams static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
1306f231ddaSDan Williams {
1316f231ddaSDan Williams 	return pci_get_drvdata(pdev);
1326f231ddaSDan Williams }
1336f231ddaSDan Williams 
134b329aff1SDan Williams #define for_each_isci_host(id, ihost, pdev) \
135b329aff1SDan Williams 	for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \
136b329aff1SDan Williams 	     id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \
137b329aff1SDan Williams 	     ihost = to_pci_info(pdev)->hosts[++id])
1386f231ddaSDan Williams 
1396f231ddaSDan Williams static inline
1406f231ddaSDan Williams enum isci_status isci_host_get_state(
1416f231ddaSDan Williams 	struct isci_host *isci_host)
1426f231ddaSDan Williams {
1436f231ddaSDan Williams 	return isci_host->status;
1446f231ddaSDan Williams }
1456f231ddaSDan Williams 
1466f231ddaSDan Williams 
1476f231ddaSDan Williams static inline void isci_host_change_state(
1486f231ddaSDan Williams 	struct isci_host *isci_host,
1496f231ddaSDan Williams 	enum isci_status status)
1506f231ddaSDan Williams {
1516f231ddaSDan Williams 	unsigned long flags;
1526f231ddaSDan Williams 
1536f231ddaSDan Williams 	dev_dbg(&isci_host->pdev->dev,
1546f231ddaSDan Williams 		"%s: isci_host = %p, state = 0x%x",
1556f231ddaSDan Williams 		__func__,
1566f231ddaSDan Williams 		isci_host,
1576f231ddaSDan Williams 		status);
1586f231ddaSDan Williams 	spin_lock_irqsave(&isci_host->state_lock, flags);
1596f231ddaSDan Williams 	isci_host->status = status;
1606f231ddaSDan Williams 	spin_unlock_irqrestore(&isci_host->state_lock, flags);
1616f231ddaSDan Williams 
1626f231ddaSDan Williams }
1636f231ddaSDan Williams 
1646f231ddaSDan Williams static inline int isci_host_can_queue(
1656f231ddaSDan Williams 	struct isci_host *isci_host,
1666f231ddaSDan Williams 	int num)
1676f231ddaSDan Williams {
1686f231ddaSDan Williams 	int ret = 0;
1696f231ddaSDan Williams 	unsigned long flags;
1706f231ddaSDan Williams 
1716f231ddaSDan Williams 	spin_lock_irqsave(&isci_host->queue_lock, flags);
1726f231ddaSDan Williams 	if ((isci_host->can_queue - num) < 0) {
1736f231ddaSDan Williams 		dev_dbg(&isci_host->pdev->dev,
1746f231ddaSDan Williams 			"%s: isci_host->can_queue = %d\n",
1756f231ddaSDan Williams 			__func__,
1766f231ddaSDan Williams 			isci_host->can_queue);
1776f231ddaSDan Williams 		ret = -SAS_QUEUE_FULL;
1786f231ddaSDan Williams 
1796f231ddaSDan Williams 	} else
1806f231ddaSDan Williams 		isci_host->can_queue -= num;
1816f231ddaSDan Williams 
1826f231ddaSDan Williams 	spin_unlock_irqrestore(&isci_host->queue_lock, flags);
1836f231ddaSDan Williams 
1846f231ddaSDan Williams 	return ret;
1856f231ddaSDan Williams }
1866f231ddaSDan Williams 
1876f231ddaSDan Williams static inline void isci_host_can_dequeue(
1886f231ddaSDan Williams 	struct isci_host *isci_host,
1896f231ddaSDan Williams 	int num)
1906f231ddaSDan Williams {
1916f231ddaSDan Williams 	unsigned long flags;
1926f231ddaSDan Williams 
1936f231ddaSDan Williams 	spin_lock_irqsave(&isci_host->queue_lock, flags);
1946f231ddaSDan Williams 	isci_host->can_queue += num;
1956f231ddaSDan Williams 	spin_unlock_irqrestore(&isci_host->queue_lock, flags);
1966f231ddaSDan Williams }
1976f231ddaSDan Williams 
1980cf89d1dSDan Williams static inline void wait_for_start(struct isci_host *ihost)
1990cf89d1dSDan Williams {
2000cf89d1dSDan Williams 	wait_event(ihost->eventq, !test_bit(IHOST_START_PENDING, &ihost->flags));
2010cf89d1dSDan Williams }
2020cf89d1dSDan Williams 
2030cf89d1dSDan Williams static inline void wait_for_stop(struct isci_host *ihost)
2040cf89d1dSDan Williams {
2050cf89d1dSDan Williams 	wait_event(ihost->eventq, !test_bit(IHOST_STOP_PENDING, &ihost->flags));
2060cf89d1dSDan Williams }
2070cf89d1dSDan Williams 
2086ad31fecSDan Williams static inline void wait_for_device_start(struct isci_host *ihost, struct isci_remote_device *idev)
2096ad31fecSDan Williams {
2106ad31fecSDan Williams 	wait_event(ihost->eventq, !test_bit(IDEV_START_PENDING, &idev->flags));
2116ad31fecSDan Williams }
2126ad31fecSDan Williams 
2136ad31fecSDan Williams static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_remote_device *idev)
2146ad31fecSDan Williams {
215d9c37390SDan Williams 	wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags));
2166ad31fecSDan Williams }
2170cf89d1dSDan Williams 
2184393aa4eSDan Williams static inline struct isci_host *dev_to_ihost(struct domain_device *dev)
2194393aa4eSDan Williams {
2204393aa4eSDan Williams 	return dev->port->ha->lldd_ha;
2214393aa4eSDan Williams }
2226f231ddaSDan Williams 
2236f231ddaSDan Williams /**
2246f231ddaSDan Williams  * isci_host_scan_finished() -
2256f231ddaSDan Williams  *
2266f231ddaSDan Williams  * This function is one of the SCSI Host Template functions. The SCSI midlayer
2276f231ddaSDan Williams  * calls this function during a target scan, approx. once every 10 millisecs.
2286f231ddaSDan Williams  */
2296f231ddaSDan Williams int isci_host_scan_finished(
2306f231ddaSDan Williams 	struct Scsi_Host *,
2316f231ddaSDan Williams 	unsigned long);
2326f231ddaSDan Williams 
2336f231ddaSDan Williams 
2346f231ddaSDan Williams /**
2356f231ddaSDan Williams  * isci_host_scan_start() -
2366f231ddaSDan Williams  *
2376f231ddaSDan Williams  * This function is one of the SCSI Host Template function, called by the SCSI
2386f231ddaSDan Williams  * mid layer berfore a target scan begins. The core library controller start
2396f231ddaSDan Williams  * routine is called from here.
2406f231ddaSDan Williams  */
2416f231ddaSDan Williams void isci_host_scan_start(
2426f231ddaSDan Williams 	struct Scsi_Host *);
2436f231ddaSDan Williams 
2446f231ddaSDan Williams /**
2456f231ddaSDan Williams  * isci_host_start_complete() -
2466f231ddaSDan Williams  *
2476f231ddaSDan Williams  * This function is called by the core library, through the ISCI Module, to
2486f231ddaSDan Williams  * indicate controller start status.
2496f231ddaSDan Williams  */
2506f231ddaSDan Williams void isci_host_start_complete(
2516f231ddaSDan Williams 	struct isci_host *,
2526f231ddaSDan Williams 	enum sci_status);
2536f231ddaSDan Williams 
2546f231ddaSDan Williams void isci_host_stop_complete(
2556f231ddaSDan Williams 	struct isci_host *isci_host,
2566f231ddaSDan Williams 	enum sci_status completion_status);
2576f231ddaSDan Williams 
2586f231ddaSDan Williams int isci_host_init(struct isci_host *);
2596f231ddaSDan Williams 
2606f231ddaSDan Williams void isci_host_init_controller_names(
2616f231ddaSDan Williams 	struct isci_host *isci_host,
2626f231ddaSDan Williams 	unsigned int controller_idx);
2636f231ddaSDan Williams 
2646f231ddaSDan Williams void isci_host_deinit(
2656f231ddaSDan Williams 	struct isci_host *);
2666f231ddaSDan Williams 
2676f231ddaSDan Williams void isci_host_port_link_up(
2686f231ddaSDan Williams 	struct isci_host *,
2696f231ddaSDan Williams 	struct scic_sds_port *,
2706f231ddaSDan Williams 	struct scic_sds_phy *);
2716f231ddaSDan Williams int isci_host_dev_found(struct domain_device *);
2726f231ddaSDan Williams 
2736f231ddaSDan Williams void isci_host_remote_device_start_complete(
2746f231ddaSDan Williams 	struct isci_host *,
2756f231ddaSDan Williams 	struct isci_remote_device *,
2766f231ddaSDan Williams 	enum sci_status);
2776f231ddaSDan Williams 
2786f231ddaSDan Williams #endif /* !defined(_SCI_HOST_H_) */
279