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