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 56ce2b3261SDan Williams #ifndef _SCI_HOST_H_ 576f231ddaSDan Williams #define _SCI_HOST_H_ 586f231ddaSDan Williams 59cc3dbd0aSArtur Wojcik #include "scic_sds_controller.h" 606f231ddaSDan Williams #include "remote_device.h" 61ce2b3261SDan Williams #include "phy.h" 626f231ddaSDan Williams 636f231ddaSDan Williams struct isci_host { 64cc3dbd0aSArtur Wojcik struct scic_sds_controller sci; 656f231ddaSDan Williams union scic_oem_parameters oem_parameters; 666f231ddaSDan Williams 676f231ddaSDan Williams int id; /* unique within a given pci device */ 687c40a803SDan Williams struct list_head timers; 696f231ddaSDan Williams void *core_ctrl_memory; 706f231ddaSDan Williams struct dma_pool *dma_pool; 716f231ddaSDan Williams struct isci_phy phys[SCI_MAX_PHYS]; 72e531381eSDan Williams struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ 736f231ddaSDan Williams struct sas_ha_struct sas_ha; 746f231ddaSDan Williams 756f231ddaSDan Williams int can_queue; 766f231ddaSDan Williams spinlock_t queue_lock; 776f231ddaSDan Williams spinlock_t state_lock; 786f231ddaSDan Williams 796f231ddaSDan Williams struct pci_dev *pdev; 806f231ddaSDan Williams 816f231ddaSDan Williams enum isci_status status; 820cf89d1dSDan Williams #define IHOST_START_PENDING 0 830cf89d1dSDan Williams #define IHOST_STOP_PENDING 1 840cf89d1dSDan Williams unsigned long flags; 850cf89d1dSDan Williams wait_queue_head_t eventq; 866f231ddaSDan Williams struct Scsi_Host *shost; 876f231ddaSDan Williams struct tasklet_struct completion_tasklet; 886f231ddaSDan Williams struct list_head requests_to_complete; 8911b00c19SJeff Skirvin struct list_head requests_to_errorback; 906f231ddaSDan Williams spinlock_t scic_lock; 91d9c37390SDan Williams 9257f20f4eSDan Williams struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES]; 936f231ddaSDan Williams }; 946f231ddaSDan Williams 956f231ddaSDan Williams /** 966f231ddaSDan Williams * struct isci_pci_info - This class represents the pci function containing the 976f231ddaSDan Williams * controllers. Depending on PCI SKU, there could be up to 2 controllers in 986f231ddaSDan Williams * the PCI function. 996f231ddaSDan Williams */ 1006f231ddaSDan Williams #define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS) 1016f231ddaSDan Williams 1026f231ddaSDan Williams struct isci_pci_info { 1036f231ddaSDan Williams struct msix_entry msix_entries[SCI_MAX_MSIX_INT]; 104b329aff1SDan Williams struct isci_host *hosts[SCI_MAX_CONTROLLERS]; 105d044af17SDan Williams struct isci_orom *orom; 1066f231ddaSDan Williams }; 1076f231ddaSDan Williams 1086f231ddaSDan Williams static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev) 1096f231ddaSDan Williams { 1106f231ddaSDan Williams return pci_get_drvdata(pdev); 1116f231ddaSDan Williams } 1126f231ddaSDan Williams 113b329aff1SDan Williams #define for_each_isci_host(id, ihost, pdev) \ 114b329aff1SDan Williams for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \ 115b329aff1SDan Williams id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \ 116b329aff1SDan Williams ihost = to_pci_info(pdev)->hosts[++id]) 1176f231ddaSDan Williams 1186f231ddaSDan Williams static inline 1196f231ddaSDan Williams enum isci_status isci_host_get_state( 1206f231ddaSDan Williams struct isci_host *isci_host) 1216f231ddaSDan Williams { 1226f231ddaSDan Williams return isci_host->status; 1236f231ddaSDan Williams } 1246f231ddaSDan Williams 1256f231ddaSDan Williams 1266f231ddaSDan Williams static inline void isci_host_change_state( 1276f231ddaSDan Williams struct isci_host *isci_host, 1286f231ddaSDan Williams enum isci_status status) 1296f231ddaSDan Williams { 1306f231ddaSDan Williams unsigned long flags; 1316f231ddaSDan Williams 1326f231ddaSDan Williams dev_dbg(&isci_host->pdev->dev, 1336f231ddaSDan Williams "%s: isci_host = %p, state = 0x%x", 1346f231ddaSDan Williams __func__, 1356f231ddaSDan Williams isci_host, 1366f231ddaSDan Williams status); 1376f231ddaSDan Williams spin_lock_irqsave(&isci_host->state_lock, flags); 1386f231ddaSDan Williams isci_host->status = status; 1396f231ddaSDan Williams spin_unlock_irqrestore(&isci_host->state_lock, flags); 1406f231ddaSDan Williams 1416f231ddaSDan Williams } 1426f231ddaSDan Williams 1436f231ddaSDan Williams static inline int isci_host_can_queue( 1446f231ddaSDan Williams struct isci_host *isci_host, 1456f231ddaSDan Williams int num) 1466f231ddaSDan Williams { 1476f231ddaSDan Williams int ret = 0; 1486f231ddaSDan Williams unsigned long flags; 1496f231ddaSDan Williams 1506f231ddaSDan Williams spin_lock_irqsave(&isci_host->queue_lock, flags); 1516f231ddaSDan Williams if ((isci_host->can_queue - num) < 0) { 1526f231ddaSDan Williams dev_dbg(&isci_host->pdev->dev, 1536f231ddaSDan Williams "%s: isci_host->can_queue = %d\n", 1546f231ddaSDan Williams __func__, 1556f231ddaSDan Williams isci_host->can_queue); 1566f231ddaSDan Williams ret = -SAS_QUEUE_FULL; 1576f231ddaSDan Williams 1586f231ddaSDan Williams } else 1596f231ddaSDan Williams isci_host->can_queue -= num; 1606f231ddaSDan Williams 1616f231ddaSDan Williams spin_unlock_irqrestore(&isci_host->queue_lock, flags); 1626f231ddaSDan Williams 1636f231ddaSDan Williams return ret; 1646f231ddaSDan Williams } 1656f231ddaSDan Williams 1666f231ddaSDan Williams static inline void isci_host_can_dequeue( 1676f231ddaSDan Williams struct isci_host *isci_host, 1686f231ddaSDan Williams int num) 1696f231ddaSDan Williams { 1706f231ddaSDan Williams unsigned long flags; 1716f231ddaSDan Williams 1726f231ddaSDan Williams spin_lock_irqsave(&isci_host->queue_lock, flags); 1736f231ddaSDan Williams isci_host->can_queue += num; 1746f231ddaSDan Williams spin_unlock_irqrestore(&isci_host->queue_lock, flags); 1756f231ddaSDan Williams } 1766f231ddaSDan Williams 1770cf89d1dSDan Williams static inline void wait_for_start(struct isci_host *ihost) 1780cf89d1dSDan Williams { 1790cf89d1dSDan Williams wait_event(ihost->eventq, !test_bit(IHOST_START_PENDING, &ihost->flags)); 1800cf89d1dSDan Williams } 1810cf89d1dSDan Williams 1820cf89d1dSDan Williams static inline void wait_for_stop(struct isci_host *ihost) 1830cf89d1dSDan Williams { 1840cf89d1dSDan Williams wait_event(ihost->eventq, !test_bit(IHOST_STOP_PENDING, &ihost->flags)); 1850cf89d1dSDan Williams } 1860cf89d1dSDan Williams 1876ad31fecSDan Williams static inline void wait_for_device_start(struct isci_host *ihost, struct isci_remote_device *idev) 1886ad31fecSDan Williams { 1896ad31fecSDan Williams wait_event(ihost->eventq, !test_bit(IDEV_START_PENDING, &idev->flags)); 1906ad31fecSDan Williams } 1916ad31fecSDan Williams 1926ad31fecSDan Williams static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_remote_device *idev) 1936ad31fecSDan Williams { 194d9c37390SDan Williams wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags)); 1956ad31fecSDan Williams } 1960cf89d1dSDan Williams 1974393aa4eSDan Williams static inline struct isci_host *dev_to_ihost(struct domain_device *dev) 1984393aa4eSDan Williams { 1994393aa4eSDan Williams return dev->port->ha->lldd_ha; 2004393aa4eSDan Williams } 2016f231ddaSDan Williams 202cc3dbd0aSArtur Wojcik static inline struct isci_host *scic_to_ihost(struct scic_sds_controller *scic) 203cc3dbd0aSArtur Wojcik { 204cc3dbd0aSArtur Wojcik /* XXX delete after merging scic_sds_contoller and isci_host */ 205cc3dbd0aSArtur Wojcik struct isci_host *ihost = container_of(scic, typeof(*ihost), sci); 206cc3dbd0aSArtur Wojcik 207cc3dbd0aSArtur Wojcik return ihost; 208cc3dbd0aSArtur Wojcik } 209cc3dbd0aSArtur Wojcik 2106f231ddaSDan Williams /** 2116f231ddaSDan Williams * isci_host_scan_finished() - 2126f231ddaSDan Williams * 2136f231ddaSDan Williams * This function is one of the SCSI Host Template functions. The SCSI midlayer 2146f231ddaSDan Williams * calls this function during a target scan, approx. once every 10 millisecs. 2156f231ddaSDan Williams */ 2166f231ddaSDan Williams int isci_host_scan_finished( 2176f231ddaSDan Williams struct Scsi_Host *, 2186f231ddaSDan Williams unsigned long); 2196f231ddaSDan Williams 2206f231ddaSDan Williams 2216f231ddaSDan Williams /** 2226f231ddaSDan Williams * isci_host_scan_start() - 2236f231ddaSDan Williams * 2246f231ddaSDan Williams * This function is one of the SCSI Host Template function, called by the SCSI 2256f231ddaSDan Williams * mid layer berfore a target scan begins. The core library controller start 2266f231ddaSDan Williams * routine is called from here. 2276f231ddaSDan Williams */ 2286f231ddaSDan Williams void isci_host_scan_start( 2296f231ddaSDan Williams struct Scsi_Host *); 2306f231ddaSDan Williams 2316f231ddaSDan Williams /** 2326f231ddaSDan Williams * isci_host_start_complete() - 2336f231ddaSDan Williams * 2346f231ddaSDan Williams * This function is called by the core library, through the ISCI Module, to 2356f231ddaSDan Williams * indicate controller start status. 2366f231ddaSDan Williams */ 2376f231ddaSDan Williams void isci_host_start_complete( 2386f231ddaSDan Williams struct isci_host *, 2396f231ddaSDan Williams enum sci_status); 2406f231ddaSDan Williams 2416f231ddaSDan Williams void isci_host_stop_complete( 2426f231ddaSDan Williams struct isci_host *isci_host, 2436f231ddaSDan Williams enum sci_status completion_status); 2446f231ddaSDan Williams 2456f231ddaSDan Williams int isci_host_init(struct isci_host *); 2466f231ddaSDan Williams 2476f231ddaSDan Williams void isci_host_init_controller_names( 2486f231ddaSDan Williams struct isci_host *isci_host, 2496f231ddaSDan Williams unsigned int controller_idx); 2506f231ddaSDan Williams 2516f231ddaSDan Williams void isci_host_deinit( 2526f231ddaSDan Williams struct isci_host *); 2536f231ddaSDan Williams 2546f231ddaSDan Williams void isci_host_port_link_up( 2556f231ddaSDan Williams struct isci_host *, 2566f231ddaSDan Williams struct scic_sds_port *, 2576f231ddaSDan Williams struct scic_sds_phy *); 2586f231ddaSDan Williams int isci_host_dev_found(struct domain_device *); 2596f231ddaSDan Williams 2606f231ddaSDan Williams void isci_host_remote_device_start_complete( 2616f231ddaSDan Williams struct isci_host *, 2626f231ddaSDan Williams struct isci_remote_device *, 2636f231ddaSDan Williams enum sci_status); 2646f231ddaSDan Williams 2656f231ddaSDan Williams #endif /* !defined(_SCI_HOST_H_) */ 266