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