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]; 143b329aff1SDan Williams struct isci_host *hosts[SCI_MAX_CONTROLLERS]; 144*d044af17SDan Williams struct isci_orom *orom; 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