|  | /* | 
|  | *  linux/drivers/scsi/esas2r/esas2r.h | 
|  | *      For use with ATTO ExpressSAS R6xx SAS/SATA RAID controllers | 
|  | * | 
|  | *  Copyright (c) 2001-2013 ATTO Technology, Inc. | 
|  | *  (mailto:linuxdrivers@attotech.com) | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU General Public License | 
|  | * as published by the Free Software Foundation; either version 2 | 
|  | * of the License, or (at your option) any later version. | 
|  | * | 
|  | * This program is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | * GNU General Public License for more details. | 
|  | * | 
|  | * NO WARRANTY | 
|  | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | 
|  | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | 
|  | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | 
|  | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | 
|  | * solely responsible for determining the appropriateness of using and | 
|  | * distributing the Program and assumes all risks associated with its | 
|  | * exercise of rights under this Agreement, including but not limited to | 
|  | * the risks and costs of program errors, damage to or loss of data, | 
|  | * programs or equipment, and unavailability or interruption of operations. | 
|  | * | 
|  | * DISCLAIMER OF LIABILITY | 
|  | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | 
|  | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
|  | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | 
|  | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | 
|  | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | 
|  | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | 
|  | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License | 
|  | * along with this program; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, | 
|  | * USA. | 
|  | */ | 
|  |  | 
|  | #include <linux/kernel.h> | 
|  | #include <linux/delay.h> | 
|  | #include <linux/pci.h> | 
|  | #include <linux/proc_fs.h> | 
|  | #include <linux/workqueue.h> | 
|  | #include <linux/interrupt.h> | 
|  | #include <linux/module.h> | 
|  | #include <linux/vmalloc.h> | 
|  | #include <scsi/scsi.h> | 
|  | #include <scsi/scsi_host.h> | 
|  | #include <scsi/scsi_cmnd.h> | 
|  | #include <scsi/scsi_device.h> | 
|  | #include <scsi/scsi_eh.h> | 
|  | #include <scsi/scsi_tcq.h> | 
|  |  | 
|  | #include "esas2r_log.h" | 
|  | #include "atioctl.h" | 
|  | #include "atvda.h" | 
|  |  | 
|  | #ifndef ESAS2R_H | 
|  | #define ESAS2R_H | 
|  |  | 
|  | /* Global Variables */ | 
|  | extern struct esas2r_adapter *esas2r_adapters[]; | 
|  | extern u8 *esas2r_buffered_ioctl; | 
|  | extern dma_addr_t esas2r_buffered_ioctl_addr; | 
|  | extern u32 esas2r_buffered_ioctl_size; | 
|  | extern struct pci_dev *esas2r_buffered_ioctl_pcid; | 
|  | #define SGL_PG_SZ_MIN   64 | 
|  | #define SGL_PG_SZ_MAX   1024 | 
|  | extern int sgl_page_size; | 
|  | #define NUM_SGL_MIN     8 | 
|  | #define NUM_SGL_MAX     2048 | 
|  | extern int num_sg_lists; | 
|  | #define NUM_REQ_MIN     4 | 
|  | #define NUM_REQ_MAX     256 | 
|  | extern int num_requests; | 
|  | #define NUM_AE_MIN      2 | 
|  | #define NUM_AE_MAX      8 | 
|  | extern int num_ae_requests; | 
|  | extern int cmd_per_lun; | 
|  | extern int can_queue; | 
|  | extern int esas2r_max_sectors; | 
|  | extern int sg_tablesize; | 
|  | extern int interrupt_mode; | 
|  | extern int num_io_requests; | 
|  |  | 
|  | /* Macro defintions */ | 
|  | #define ESAS2R_MAX_ID        255 | 
|  | #define MAX_ADAPTERS         32 | 
|  | #define ESAS2R_DRVR_NAME     "esas2r" | 
|  | #define ESAS2R_LONGNAME      "ATTO ExpressSAS 6GB RAID Adapter" | 
|  | #define ESAS2R_MAX_DEVICES     32 | 
|  | #define ATTONODE_NAME         "ATTONode" | 
|  | #define ESAS2R_MAJOR_REV       1 | 
|  | #define ESAS2R_MINOR_REV       00 | 
|  | #define ESAS2R_VERSION_STR     DEFINED_NUM_TO_STR(ESAS2R_MAJOR_REV) "." \ | 
|  | DEFINED_NUM_TO_STR(ESAS2R_MINOR_REV) | 
|  | #define ESAS2R_COPYRIGHT_YEARS "2001-2013" | 
|  | #define ESAS2R_DEFAULT_SGL_PAGE_SIZE 384 | 
|  | #define ESAS2R_DEFAULT_CMD_PER_LUN   64 | 
|  | #define ESAS2R_DEFAULT_NUM_SG_LISTS 1024 | 
|  | #define DEFINED_NUM_TO_STR(num) NUM_TO_STR(num) | 
|  | #define NUM_TO_STR(num) #num | 
|  |  | 
|  | #define ESAS2R_SGL_ALIGN    16 | 
|  | #define ESAS2R_LIST_ALIGN   16 | 
|  | #define ESAS2R_LIST_EXTRA   ESAS2R_NUM_EXTRA | 
|  | #define ESAS2R_DATA_BUF_LEN         256 | 
|  | #define ESAS2R_DEFAULT_TMO          5000 | 
|  | #define ESAS2R_DISC_BUF_LEN         512 | 
|  | #define ESAS2R_FWCOREDUMP_SZ        0x80000 | 
|  | #define ESAS2R_NUM_PHYS             8 | 
|  | #define ESAS2R_TARG_ID_INV          0xFFFF | 
|  | #define ESAS2R_INT_STS_MASK         MU_INTSTAT_MASK | 
|  | #define ESAS2R_INT_ENB_MASK         MU_INTSTAT_MASK | 
|  | #define ESAS2R_INT_DIS_MASK         0 | 
|  | #define ESAS2R_MAX_TARGETS          256 | 
|  | #define ESAS2R_KOBJ_NAME_LEN        20 | 
|  |  | 
|  | /* u16 (WORD) component macros */ | 
|  | #define LOBYTE(w) ((u8)(u16)(w)) | 
|  | #define HIBYTE(w) ((u8)(((u16)(w)) >> 8)) | 
|  | #define MAKEWORD(lo, hi) ((u16)((u8)(lo) | ((u16)(u8)(hi) << 8))) | 
|  |  | 
|  | /* u32 (DWORD) component macros */ | 
|  | #define LOWORD(d) ((u16)(u32)(d)) | 
|  | #define HIWORD(d) ((u16)(((u32)(d)) >> 16)) | 
|  | #define MAKEDWORD(lo, hi) ((u32)((u16)(lo) | ((u32)(u16)(hi) << 16))) | 
|  |  | 
|  | /* macro to get the lowest nonzero bit of a value */ | 
|  | #define LOBIT(x) ((x) & (0 - (x))) | 
|  |  | 
|  | /* These functions are provided to access the chip's control registers. | 
|  | * The register is specified by its byte offset from the register base | 
|  | * for the adapter. | 
|  | */ | 
|  | #define esas2r_read_register_dword(a, reg)                             \ | 
|  | readl((void __iomem *)a->regs + (reg) + MW_REG_OFFSET_HWREG) | 
|  |  | 
|  | #define esas2r_write_register_dword(a, reg, data)                      \ | 
|  | writel(data, (void __iomem *)(a->regs + (reg) + MW_REG_OFFSET_HWREG)) | 
|  |  | 
|  | #define esas2r_flush_register_dword(a, r) esas2r_read_register_dword(a, r) | 
|  |  | 
|  | /* This function is provided to access the chip's data window.   The | 
|  | * register is specified by its byte offset from the window base | 
|  | * for the adapter. | 
|  | */ | 
|  | #define esas2r_read_data_byte(a, reg)                                  \ | 
|  | readb((void __iomem *)a->data_window + (reg)) | 
|  |  | 
|  | /* ATTO vendor and device Ids */ | 
|  | #define ATTO_VENDOR_ID          0x117C | 
|  | #define ATTO_DID_INTEL_IOP348   0x002C | 
|  | #define ATTO_DID_MV_88RC9580    0x0049 | 
|  | #define ATTO_DID_MV_88RC9580TS  0x0066 | 
|  | #define ATTO_DID_MV_88RC9580TSE 0x0067 | 
|  | #define ATTO_DID_MV_88RC9580TL  0x0068 | 
|  |  | 
|  | /* ATTO subsystem device Ids */ | 
|  | #define ATTO_SSDID_TBT      0x4000 | 
|  | #define ATTO_TSSC_3808      0x4066 | 
|  | #define ATTO_TSSC_3808E     0x4067 | 
|  | #define ATTO_TLSH_1068      0x4068 | 
|  | #define ATTO_ESAS_R680      0x0049 | 
|  | #define ATTO_ESAS_R608      0x004A | 
|  | #define ATTO_ESAS_R60F      0x004B | 
|  | #define ATTO_ESAS_R6F0      0x004C | 
|  | #define ATTO_ESAS_R644      0x004D | 
|  | #define ATTO_ESAS_R648      0x004E | 
|  |  | 
|  | /* | 
|  | * flash definitions & structures | 
|  | * define the code types | 
|  | */ | 
|  | #define FBT_CPYR        0xAA00 | 
|  | #define FBT_SETUP       0xAA02 | 
|  | #define FBT_FLASH_VER   0xAA04 | 
|  |  | 
|  | /* offsets to various locations in flash */ | 
|  | #define FLS_OFFSET_BOOT (u32)(0x00700000) | 
|  | #define FLS_OFFSET_NVR  (u32)(0x007C0000) | 
|  | #define FLS_OFFSET_CPYR FLS_OFFSET_NVR | 
|  | #define FLS_LENGTH_BOOT (FLS_OFFSET_CPYR - FLS_OFFSET_BOOT) | 
|  | #define FLS_BLOCK_SIZE  (u32)(0x00020000) | 
|  | #define FI_NVR_2KB  0x0800 | 
|  | #define FI_NVR_8KB  0x2000 | 
|  | #define FM_BUF_SZ   0x800 | 
|  |  | 
|  | /* | 
|  | * marvell frey (88R9580) register definitions | 
|  | * chip revision identifiers | 
|  | */ | 
|  | #define MVR_FREY_B2     0xB2 | 
|  |  | 
|  | /* | 
|  | * memory window definitions.  window 0 is the data window with definitions | 
|  | * of MW_DATA_XXX.  window 1 is the register window with definitions of | 
|  | * MW_REG_XXX. | 
|  | */ | 
|  | #define MW_REG_WINDOW_SIZE      (u32)(0x00040000) | 
|  | #define MW_REG_OFFSET_HWREG     (u32)(0x00000000) | 
|  | #define MW_REG_OFFSET_PCI       (u32)(0x00008000) | 
|  | #define MW_REG_PCI_HWREG_DELTA  (MW_REG_OFFSET_PCI - MW_REG_OFFSET_HWREG) | 
|  | #define MW_DATA_WINDOW_SIZE     (u32)(0x00020000) | 
|  | #define MW_DATA_ADDR_SER_FLASH  (u32)(0xEC000000) | 
|  | #define MW_DATA_ADDR_SRAM       (u32)(0xF4000000) | 
|  | #define MW_DATA_ADDR_PAR_FLASH  (u32)(0xFC000000) | 
|  |  | 
|  | /* | 
|  | * the following registers are for the communication | 
|  | * list interface (AKA message unit (MU)) | 
|  | */ | 
|  | #define MU_IN_LIST_ADDR_LO      (u32)(0x00004000) | 
|  | #define MU_IN_LIST_ADDR_HI      (u32)(0x00004004) | 
|  |  | 
|  | #define MU_IN_LIST_WRITE        (u32)(0x00004018) | 
|  | #define MU_ILW_TOGGLE       (u32)(0x00004000) | 
|  |  | 
|  | #define MU_IN_LIST_READ         (u32)(0x0000401C) | 
|  | #define MU_ILR_TOGGLE       (u32)(0x00004000) | 
|  | #define MU_ILIC_LIST        (u32)(0x0000000F) | 
|  | #define MU_ILIC_LIST_F0     (u32)(0x00000000) | 
|  | #define MU_ILIC_DEST        (u32)(0x00000F00) | 
|  | #define MU_ILIC_DEST_DDR    (u32)(0x00000200) | 
|  | #define MU_IN_LIST_IFC_CONFIG   (u32)(0x00004028) | 
|  |  | 
|  | #define MU_IN_LIST_CONFIG       (u32)(0x0000402C) | 
|  | #define MU_ILC_ENABLE       (u32)(0x00000001) | 
|  | #define MU_ILC_ENTRY_MASK   (u32)(0x000000F0) | 
|  | #define MU_ILC_ENTRY_4_DW   (u32)(0x00000020) | 
|  | #define MU_ILC_DYNAMIC_SRC  (u32)(0x00008000) | 
|  | #define MU_ILC_NUMBER_MASK  (u32)(0x7FFF0000) | 
|  | #define MU_ILC_NUMBER_SHIFT            16 | 
|  |  | 
|  | #define MU_OUT_LIST_ADDR_LO     (u32)(0x00004050) | 
|  | #define MU_OUT_LIST_ADDR_HI     (u32)(0x00004054) | 
|  |  | 
|  | #define MU_OUT_LIST_COPY_PTR_LO (u32)(0x00004058) | 
|  | #define MU_OUT_LIST_COPY_PTR_HI (u32)(0x0000405C) | 
|  |  | 
|  | #define MU_OUT_LIST_WRITE       (u32)(0x00004068) | 
|  | #define MU_OLW_TOGGLE       (u32)(0x00004000) | 
|  |  | 
|  | #define MU_OUT_LIST_COPY        (u32)(0x0000406C) | 
|  | #define MU_OLC_TOGGLE       (u32)(0x00004000) | 
|  | #define MU_OLC_WRT_PTR      (u32)(0x00003FFF) | 
|  |  | 
|  | #define MU_OUT_LIST_IFC_CONFIG  (u32)(0x00004078) | 
|  | #define MU_OLIC_LIST        (u32)(0x0000000F) | 
|  | #define MU_OLIC_LIST_F0     (u32)(0x00000000) | 
|  | #define MU_OLIC_SOURCE      (u32)(0x00000F00) | 
|  | #define MU_OLIC_SOURCE_DDR  (u32)(0x00000200) | 
|  |  | 
|  | #define MU_OUT_LIST_CONFIG      (u32)(0x0000407C) | 
|  | #define MU_OLC_ENABLE       (u32)(0x00000001) | 
|  | #define MU_OLC_ENTRY_MASK   (u32)(0x000000F0) | 
|  | #define MU_OLC_ENTRY_4_DW   (u32)(0x00000020) | 
|  | #define MU_OLC_NUMBER_MASK  (u32)(0x7FFF0000) | 
|  | #define MU_OLC_NUMBER_SHIFT            16 | 
|  |  | 
|  | #define MU_OUT_LIST_INT_STAT    (u32)(0x00004088) | 
|  | #define MU_OLIS_INT         (u32)(0x00000001) | 
|  |  | 
|  | #define MU_OUT_LIST_INT_MASK    (u32)(0x0000408C) | 
|  | #define MU_OLIS_MASK        (u32)(0x00000001) | 
|  |  | 
|  | /* | 
|  | * the maximum size of the communication lists is two greater than the | 
|  | * maximum amount of VDA requests.  the extra are to prevent queue overflow. | 
|  | */ | 
|  | #define ESAS2R_MAX_NUM_REQS         256 | 
|  | #define ESAS2R_NUM_EXTRA            2 | 
|  | #define ESAS2R_MAX_COMM_LIST_SIZE   (ESAS2R_MAX_NUM_REQS + ESAS2R_NUM_EXTRA) | 
|  |  | 
|  | /* | 
|  | * the following registers are for the CPU interface | 
|  | */ | 
|  | #define MU_CTL_STATUS_IN        (u32)(0x00010108) | 
|  | #define MU_CTL_IN_FULL_RST  (u32)(0x00000020) | 
|  | #define MU_CTL_STATUS_IN_B2     (u32)(0x00010130) | 
|  | #define MU_CTL_IN_FULL_RST2 (u32)(0x80000000) | 
|  | #define MU_DOORBELL_IN          (u32)(0x00010460) | 
|  | #define DRBL_RESET_BUS      (u32)(0x00000002) | 
|  | #define DRBL_PAUSE_AE       (u32)(0x00000004) | 
|  | #define DRBL_RESUME_AE      (u32)(0x00000008) | 
|  | #define DRBL_MSG_IFC_DOWN   (u32)(0x00000010) | 
|  | #define DRBL_FLASH_REQ      (u32)(0x00000020) | 
|  | #define DRBL_FLASH_DONE     (u32)(0x00000040) | 
|  | #define DRBL_FORCE_INT      (u32)(0x00000080) | 
|  | #define DRBL_MSG_IFC_INIT   (u32)(0x00000100) | 
|  | #define DRBL_POWER_DOWN     (u32)(0x00000200) | 
|  | #define DRBL_DRV_VER_1      (u32)(0x00010000) | 
|  | #define DRBL_DRV_VER        DRBL_DRV_VER_1 | 
|  | #define MU_DOORBELL_IN_ENB      (u32)(0x00010464) | 
|  | #define MU_DOORBELL_OUT         (u32)(0x00010480) | 
|  | #define DRBL_PANIC_REASON_MASK (u32)(0x00F00000) | 
|  | #define DRBL_UNUSED_HANDLER (u32)(0x00100000) | 
|  | #define DRBL_UNDEF_INSTR    (u32)(0x00200000) | 
|  | #define DRBL_PREFETCH_ABORT (u32)(0x00300000) | 
|  | #define DRBL_DATA_ABORT     (u32)(0x00400000) | 
|  | #define DRBL_JUMP_TO_ZERO   (u32)(0x00500000) | 
|  | #define DRBL_FW_RESET         (u32)(0x00080000) | 
|  | #define DRBL_FW_VER_MSK       (u32)(0x00070000) | 
|  | #define DRBL_FW_VER_0         (u32)(0x00000000) | 
|  | #define DRBL_FW_VER_1         (u32)(0x00010000) | 
|  | #define DRBL_FW_VER           DRBL_FW_VER_1 | 
|  | #define MU_DOORBELL_OUT_ENB     (u32)(0x00010484) | 
|  | #define DRBL_ENB_MASK       (u32)(0x00F803FF) | 
|  | #define MU_INT_STATUS_OUT       (u32)(0x00010200) | 
|  | #define MU_INTSTAT_POST_OUT (u32)(0x00000010) | 
|  | #define MU_INTSTAT_DRBL_IN  (u32)(0x00000100) | 
|  | #define MU_INTSTAT_DRBL     (u32)(0x00001000) | 
|  | #define MU_INTSTAT_MASK     (u32)(0x00001010) | 
|  | #define MU_INT_MASK_OUT         (u32)(0x0001020C) | 
|  |  | 
|  | /* PCI express registers accessed via window 1 */ | 
|  | #define MVR_PCI_WIN1_REMAP      (u32)(0x00008438) | 
|  | #define MVRPW1R_ENABLE      (u32)(0x00000001) | 
|  |  | 
|  |  | 
|  | /* structures */ | 
|  |  | 
|  | /* inbound list dynamic source entry */ | 
|  | struct esas2r_inbound_list_source_entry { | 
|  | u64 address; | 
|  | u32 length; | 
|  | #define HWILSE_INTERFACE_F0  0x00000000 | 
|  | u32 reserved; | 
|  | }; | 
|  |  | 
|  | /* PCI data structure in expansion ROM images */ | 
|  | struct __packed esas2r_boot_header { | 
|  | char signature[4]; | 
|  | u16 vendor_id; | 
|  | u16 device_id; | 
|  | u16 VPD; | 
|  | u16 struct_length; | 
|  | u8 struct_revision; | 
|  | u8 class_code[3]; | 
|  | u16 image_length; | 
|  | u16 code_revision; | 
|  | u8 code_type; | 
|  | #define CODE_TYPE_PC    0 | 
|  | #define CODE_TYPE_OPEN  1 | 
|  | #define CODE_TYPE_EFI   3 | 
|  | u8 indicator; | 
|  | #define INDICATOR_LAST  0x80 | 
|  | u8 reserved[2]; | 
|  | }; | 
|  |  | 
|  | struct __packed esas2r_boot_image { | 
|  | u16 signature; | 
|  | u8 reserved[22]; | 
|  | u16 header_offset; | 
|  | u16 pnp_offset; | 
|  | }; | 
|  |  | 
|  | struct __packed esas2r_pc_image { | 
|  | u16 signature; | 
|  | u8 length; | 
|  | u8 entry_point[3]; | 
|  | u8 checksum; | 
|  | u16 image_end; | 
|  | u16 min_size; | 
|  | u8 rom_flags; | 
|  | u8 reserved[12]; | 
|  | u16 header_offset; | 
|  | u16 pnp_offset; | 
|  | struct esas2r_boot_header boot_image; | 
|  | }; | 
|  |  | 
|  | struct __packed esas2r_efi_image { | 
|  | u16 signature; | 
|  | u16 length; | 
|  | u32 efi_signature; | 
|  | #define EFI_ROM_SIG     0x00000EF1 | 
|  | u16 image_type; | 
|  | #define EFI_IMAGE_APP   10 | 
|  | #define EFI_IMAGE_BSD   11 | 
|  | #define EFI_IMAGE_RTD   12 | 
|  | u16 machine_type; | 
|  | #define EFI_MACHINE_IA32 0x014c | 
|  | #define EFI_MACHINE_IA64 0x0200 | 
|  | #define EFI_MACHINE_X64  0x8664 | 
|  | #define EFI_MACHINE_EBC  0x0EBC | 
|  | u16 compression; | 
|  | #define EFI_UNCOMPRESSED 0x0000 | 
|  | #define EFI_COMPRESSED   0x0001 | 
|  | u8 reserved[8]; | 
|  | u16 efi_offset; | 
|  | u16 header_offset; | 
|  | u16 reserved2; | 
|  | struct esas2r_boot_header boot_image; | 
|  | }; | 
|  |  | 
|  | struct esas2r_adapter; | 
|  | struct esas2r_sg_context; | 
|  | struct esas2r_request; | 
|  |  | 
|  | typedef void (*RQCALLBK)     (struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq); | 
|  | typedef bool (*RQBUILDSGL)   (struct esas2r_adapter *a, | 
|  | struct esas2r_sg_context *sgc); | 
|  |  | 
|  | struct esas2r_component_header { | 
|  | u8 img_type; | 
|  | #define CH_IT_FW    0x00 | 
|  | #define CH_IT_NVR   0x01 | 
|  | #define CH_IT_BIOS  0x02 | 
|  | #define CH_IT_MAC   0x03 | 
|  | #define CH_IT_CFG   0x04 | 
|  | #define CH_IT_EFI   0x05 | 
|  | u8 status; | 
|  | #define CH_STAT_PENDING 0xff | 
|  | #define CH_STAT_FAILED  0x00 | 
|  | #define CH_STAT_SUCCESS 0x01 | 
|  | #define CH_STAT_RETRY   0x02 | 
|  | #define CH_STAT_INVALID 0x03 | 
|  | u8 pad[2]; | 
|  | u32 version; | 
|  | u32 length; | 
|  | u32 image_offset; | 
|  | }; | 
|  |  | 
|  | #define FI_REL_VER_SZ   16 | 
|  |  | 
|  | struct esas2r_flash_img_v0 { | 
|  | u8 fi_version; | 
|  | #define FI_VERSION_0    00 | 
|  | u8 status; | 
|  | u8 adap_typ; | 
|  | u8 action; | 
|  | u32 length; | 
|  | u16 checksum; | 
|  | u16 driver_error; | 
|  | u16 flags; | 
|  | u16 num_comps; | 
|  | #define FI_NUM_COMPS_V0 5 | 
|  | u8 rel_version[FI_REL_VER_SZ]; | 
|  | struct esas2r_component_header cmp_hdr[FI_NUM_COMPS_V0]; | 
|  | u8 scratch_buf[FM_BUF_SZ]; | 
|  | }; | 
|  |  | 
|  | struct esas2r_flash_img { | 
|  | u8 fi_version; | 
|  | #define FI_VERSION_1    01 | 
|  | u8 status; | 
|  | #define FI_STAT_SUCCESS  0x00 | 
|  | #define FI_STAT_FAILED   0x01 | 
|  | #define FI_STAT_REBOOT   0x02 | 
|  | #define FI_STAT_ADAPTYP  0x03 | 
|  | #define FI_STAT_INVALID  0x04 | 
|  | #define FI_STAT_CHKSUM   0x05 | 
|  | #define FI_STAT_LENGTH   0x06 | 
|  | #define FI_STAT_UNKNOWN  0x07 | 
|  | #define FI_STAT_IMG_VER  0x08 | 
|  | #define FI_STAT_BUSY     0x09 | 
|  | #define FI_STAT_DUAL     0x0A | 
|  | #define FI_STAT_MISSING  0x0B | 
|  | #define FI_STAT_UNSUPP   0x0C | 
|  | #define FI_STAT_ERASE    0x0D | 
|  | #define FI_STAT_FLASH    0x0E | 
|  | #define FI_STAT_DEGRADED 0x0F | 
|  | u8 adap_typ; | 
|  | #define FI_AT_UNKNWN    0xFF | 
|  | #define FI_AT_SUN_LAKE  0x0B | 
|  | #define FI_AT_MV_9580   0x0F | 
|  | u8 action; | 
|  | #define FI_ACT_DOWN     0x00 | 
|  | #define FI_ACT_UP       0x01 | 
|  | #define FI_ACT_UPSZ     0x02 | 
|  | #define FI_ACT_MAX      0x02 | 
|  | #define FI_ACT_DOWN1    0x80 | 
|  | u32 length; | 
|  | u16 checksum; | 
|  | u16 driver_error; | 
|  | u16 flags; | 
|  | #define FI_FLG_NVR_DEF  0x0001 | 
|  | u16 num_comps; | 
|  | #define FI_NUM_COMPS_V1 6 | 
|  | u8 rel_version[FI_REL_VER_SZ]; | 
|  | struct esas2r_component_header cmp_hdr[FI_NUM_COMPS_V1]; | 
|  | u8 scratch_buf[FM_BUF_SZ]; | 
|  | }; | 
|  |  | 
|  | /* definitions for flash script (FS) commands */ | 
|  | struct esas2r_ioctlfs_command { | 
|  | u8 command; | 
|  | #define ESAS2R_FS_CMD_ERASE    0 | 
|  | #define ESAS2R_FS_CMD_READ     1 | 
|  | #define ESAS2R_FS_CMD_BEGINW   2 | 
|  | #define ESAS2R_FS_CMD_WRITE    3 | 
|  | #define ESAS2R_FS_CMD_COMMIT   4 | 
|  | #define ESAS2R_FS_CMD_CANCEL   5 | 
|  | u8 checksum; | 
|  | u8 reserved[2]; | 
|  | u32 flash_addr; | 
|  | u32 length; | 
|  | u32 image_offset; | 
|  | }; | 
|  |  | 
|  | struct esas2r_ioctl_fs { | 
|  | u8 version; | 
|  | #define ESAS2R_FS_VER      0 | 
|  | u8 status; | 
|  | u8 driver_error; | 
|  | u8 adap_type; | 
|  | #define ESAS2R_FS_AT_ESASRAID2     3 | 
|  | #define ESAS2R_FS_AT_TSSASRAID2    4 | 
|  | #define ESAS2R_FS_AT_TSSASRAID2E   5 | 
|  | #define ESAS2R_FS_AT_TLSASHBA      6 | 
|  | u8 driver_ver; | 
|  | u8 reserved[11]; | 
|  | struct esas2r_ioctlfs_command command; | 
|  | u8 data[1]; | 
|  | }; | 
|  |  | 
|  | struct esas2r_sas_nvram { | 
|  | u8 signature[4]; | 
|  | u8 version; | 
|  | #define SASNVR_VERSION_0    0x00 | 
|  | #define SASNVR_VERSION      SASNVR_VERSION_0 | 
|  | u8 checksum; | 
|  | #define SASNVR_CKSUM_SEED   0x5A | 
|  | u8 max_lun_for_target; | 
|  | u8 pci_latency; | 
|  | #define SASNVR_PCILAT_DIS   0x00 | 
|  | #define SASNVR_PCILAT_MIN   0x10 | 
|  | #define SASNVR_PCILAT_MAX   0xF8 | 
|  | u8 options1; | 
|  | #define SASNVR1_BOOT_DRVR   0x01 | 
|  | #define SASNVR1_BOOT_SCAN   0x02 | 
|  | #define SASNVR1_DIS_PCI_MWI 0x04 | 
|  | #define SASNVR1_FORCE_ORD_Q 0x08 | 
|  | #define SASNVR1_CACHELINE_0 0x10 | 
|  | #define SASNVR1_DIS_DEVSORT 0x20 | 
|  | #define SASNVR1_PWR_MGT_EN  0x40 | 
|  | #define SASNVR1_WIDEPORT    0x80 | 
|  | u8 options2; | 
|  | #define SASNVR2_SINGLE_BUS  0x01 | 
|  | #define SASNVR2_SLOT_BIND   0x02 | 
|  | #define SASNVR2_EXP_PROG    0x04 | 
|  | #define SASNVR2_CMDTHR_LUN  0x08 | 
|  | #define SASNVR2_HEARTBEAT   0x10 | 
|  | #define SASNVR2_INT_CONNECT 0x20 | 
|  | #define SASNVR2_SW_MUX_CTRL 0x40 | 
|  | #define SASNVR2_DISABLE_NCQ 0x80 | 
|  | u8 int_coalescing; | 
|  | #define SASNVR_COAL_DIS     0x00 | 
|  | #define SASNVR_COAL_LOW     0x01 | 
|  | #define SASNVR_COAL_MED     0x02 | 
|  | #define SASNVR_COAL_HI      0x03 | 
|  | u8 cmd_throttle; | 
|  | #define SASNVR_CMDTHR_NONE  0x00 | 
|  | u8 dev_wait_time; | 
|  | u8 dev_wait_count; | 
|  | u8 spin_up_delay; | 
|  | #define SASNVR_SPINUP_MAX   0x14 | 
|  | u8 ssp_align_rate; | 
|  | u8 sas_addr[8]; | 
|  | u8 phy_speed[16]; | 
|  | #define SASNVR_SPEED_AUTO   0x00 | 
|  | #define SASNVR_SPEED_1_5GB  0x01 | 
|  | #define SASNVR_SPEED_3GB    0x02 | 
|  | #define SASNVR_SPEED_6GB    0x03 | 
|  | #define SASNVR_SPEED_12GB   0x04 | 
|  | u8 phy_mux[16]; | 
|  | #define SASNVR_MUX_DISABLED 0x00 | 
|  | #define SASNVR_MUX_1_5GB    0x01 | 
|  | #define SASNVR_MUX_3GB      0x02 | 
|  | #define SASNVR_MUX_6GB      0x03 | 
|  | u8 phy_flags[16]; | 
|  | #define SASNVR_PHF_DISABLED 0x01 | 
|  | #define SASNVR_PHF_RD_ONLY  0x02 | 
|  | u8 sort_type; | 
|  | #define SASNVR_SORT_SAS_ADDR    0x00 | 
|  | #define SASNVR_SORT_H308_CONN   0x01 | 
|  | #define SASNVR_SORT_PHY_ID      0x02 | 
|  | #define SASNVR_SORT_SLOT_ID     0x03 | 
|  | u8 dpm_reqcmd_lmt; | 
|  | u8 dpm_stndby_time; | 
|  | u8 dpm_active_time; | 
|  | u8 phy_target_id[16]; | 
|  | #define SASNVR_PTI_DISABLED     0xFF | 
|  | u8 virt_ses_mode; | 
|  | #define SASNVR_VSMH_DISABLED    0x00 | 
|  | u8 read_write_mode; | 
|  | #define SASNVR_RWM_DEFAULT      0x00 | 
|  | u8 link_down_to; | 
|  | u8 reserved[0xA1]; | 
|  | }; | 
|  |  | 
|  | typedef u32 (*PGETPHYSADDR) (struct esas2r_sg_context *sgc, u64 *addr); | 
|  |  | 
|  | struct esas2r_sg_context { | 
|  | struct esas2r_adapter *adapter; | 
|  | struct esas2r_request *first_req; | 
|  | u32 length; | 
|  | u8 *cur_offset; | 
|  | PGETPHYSADDR get_phys_addr; | 
|  | union { | 
|  | struct { | 
|  | struct atto_vda_sge *curr; | 
|  | struct atto_vda_sge *last; | 
|  | struct atto_vda_sge *limit; | 
|  | struct atto_vda_sge *chain; | 
|  | } a64; | 
|  | struct { | 
|  | struct atto_physical_region_description *curr; | 
|  | struct atto_physical_region_description *chain; | 
|  | u32 sgl_max_cnt; | 
|  | u32 sge_cnt; | 
|  | } prd; | 
|  | } sge; | 
|  | struct scatterlist *cur_sgel; | 
|  | u8 *exp_offset; | 
|  | int num_sgel; | 
|  | int sgel_count; | 
|  | }; | 
|  |  | 
|  | struct esas2r_target { | 
|  | u8 flags; | 
|  | #define TF_PASS_THRU    0x01 | 
|  | #define TF_USED         0x02 | 
|  | u8 new_target_state; | 
|  | u8 target_state; | 
|  | u8 buffered_target_state; | 
|  | #define TS_NOT_PRESENT      0x00 | 
|  | #define TS_PRESENT          0x05 | 
|  | #define TS_LUN_CHANGE       0x06 | 
|  | #define TS_INVALID          0xFF | 
|  | u32 block_size; | 
|  | u32 inter_block; | 
|  | u32 inter_byte; | 
|  | u16 virt_targ_id; | 
|  | u16 phys_targ_id; | 
|  | u8 identifier_len; | 
|  | u64 sas_addr; | 
|  | u8 identifier[60]; | 
|  | struct atto_vda_ae_lu lu_event; | 
|  | }; | 
|  |  | 
|  | struct esas2r_request { | 
|  | struct list_head comp_list; | 
|  | struct list_head req_list; | 
|  | union atto_vda_req *vrq; | 
|  | struct esas2r_mem_desc *vrq_md; | 
|  | union { | 
|  | void *data_buf; | 
|  | union atto_vda_rsp_data *vda_rsp_data; | 
|  | }; | 
|  | u8 *sense_buf; | 
|  | struct list_head sg_table_head; | 
|  | struct esas2r_mem_desc *sg_table; | 
|  | u32 timeout; | 
|  | #define RQ_TIMEOUT_S1     0xFFFFFFFF | 
|  | #define RQ_TIMEOUT_S2     0xFFFFFFFE | 
|  | #define RQ_MAX_TIMEOUT    0xFFFFFFFD | 
|  | u16 target_id; | 
|  | u8 req_type; | 
|  | #define RT_INI_REQ          0x01 | 
|  | #define RT_DISC_REQ         0x02 | 
|  | u8 sense_len; | 
|  | union atto_vda_func_rsp func_rsp; | 
|  | RQCALLBK comp_cb; | 
|  | RQCALLBK interrupt_cb; | 
|  | void *interrupt_cx; | 
|  | u8 flags; | 
|  | #define RF_1ST_IBLK_BASE    0x04 | 
|  | #define RF_FAILURE_OK       0x08 | 
|  | u8 req_stat; | 
|  | u16 vda_req_sz; | 
|  | #define RQ_SIZE_DEFAULT   0 | 
|  | u64 lba; | 
|  | RQCALLBK aux_req_cb; | 
|  | void *aux_req_cx; | 
|  | u32 blk_len; | 
|  | u32 max_blk_len; | 
|  | union { | 
|  | struct scsi_cmnd *cmd; | 
|  | u8 *task_management_status_ptr; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | struct esas2r_flash_context { | 
|  | struct esas2r_flash_img *fi; | 
|  | RQCALLBK interrupt_cb; | 
|  | u8 *sgc_offset; | 
|  | u8 *scratch; | 
|  | u32 fi_hdr_len; | 
|  | u8 task; | 
|  | #define     FMTSK_ERASE_BOOT    0 | 
|  | #define     FMTSK_WRTBIOS       1 | 
|  | #define     FMTSK_READBIOS      2 | 
|  | #define     FMTSK_WRTMAC        3 | 
|  | #define     FMTSK_READMAC       4 | 
|  | #define     FMTSK_WRTEFI        5 | 
|  | #define     FMTSK_READEFI       6 | 
|  | #define     FMTSK_WRTCFG        7 | 
|  | #define     FMTSK_READCFG       8 | 
|  | u8 func; | 
|  | u16 num_comps; | 
|  | u32 cmp_len; | 
|  | u32 flsh_addr; | 
|  | u32 curr_len; | 
|  | u8 comp_typ; | 
|  | struct esas2r_sg_context sgc; | 
|  | }; | 
|  |  | 
|  | struct esas2r_disc_context { | 
|  | u8 disc_evt; | 
|  | #define DCDE_DEV_CHANGE     0x01 | 
|  | #define DCDE_DEV_SCAN       0x02 | 
|  | u8 state; | 
|  | #define DCS_DEV_RMV         0x00 | 
|  | #define DCS_DEV_ADD         0x01 | 
|  | #define DCS_BLOCK_DEV_SCAN  0x02 | 
|  | #define DCS_RAID_GRP_INFO   0x03 | 
|  | #define DCS_PART_INFO       0x04 | 
|  | #define DCS_PT_DEV_INFO     0x05 | 
|  | #define DCS_PT_DEV_ADDR     0x06 | 
|  | #define DCS_DISC_DONE       0xFF | 
|  | u16 flags; | 
|  | #define DCF_DEV_CHANGE      0x0001 | 
|  | #define DCF_DEV_SCAN        0x0002 | 
|  | #define DCF_POLLED          0x8000 | 
|  | u32 interleave; | 
|  | u32 block_size; | 
|  | u16 dev_ix; | 
|  | u8 part_num; | 
|  | u8 raid_grp_ix; | 
|  | char raid_grp_name[16]; | 
|  | struct esas2r_target *curr_targ; | 
|  | u16 curr_virt_id; | 
|  | u16 curr_phys_id; | 
|  | u8 scan_gen; | 
|  | u8 dev_addr_type; | 
|  | u64 sas_addr; | 
|  | }; | 
|  |  | 
|  | struct esas2r_mem_desc { | 
|  | struct list_head next_desc; | 
|  | void *virt_addr; | 
|  | u64 phys_addr; | 
|  | void *pad; | 
|  | void *esas2r_data; | 
|  | u32 esas2r_param; | 
|  | u32 size; | 
|  | }; | 
|  |  | 
|  | enum fw_event_type { | 
|  | fw_event_null, | 
|  | fw_event_lun_change, | 
|  | fw_event_present, | 
|  | fw_event_not_present, | 
|  | fw_event_vda_ae | 
|  | }; | 
|  |  | 
|  | struct esas2r_vda_ae { | 
|  | u32 signature; | 
|  | #define ESAS2R_VDA_EVENT_SIG  0x4154544F | 
|  | u8 bus_number; | 
|  | u8 devfn; | 
|  | u8 pad[2]; | 
|  | union atto_vda_ae vda_ae; | 
|  | }; | 
|  |  | 
|  | struct esas2r_fw_event_work { | 
|  | struct list_head list; | 
|  | struct delayed_work work; | 
|  | struct esas2r_adapter *a; | 
|  | enum fw_event_type type; | 
|  | u8 data[sizeof(struct esas2r_vda_ae)]; | 
|  | }; | 
|  |  | 
|  | enum state { | 
|  | FW_INVALID_ST, | 
|  | FW_STATUS_ST, | 
|  | FW_COMMAND_ST | 
|  | }; | 
|  |  | 
|  | struct esas2r_firmware { | 
|  | enum state state; | 
|  | struct esas2r_flash_img header; | 
|  | u8 *data; | 
|  | u64 phys; | 
|  | int orig_len; | 
|  | void *header_buff; | 
|  | u64 header_buff_phys; | 
|  | }; | 
|  |  | 
|  | struct esas2r_adapter { | 
|  | struct esas2r_target targetdb[ESAS2R_MAX_TARGETS]; | 
|  | struct esas2r_target *targetdb_end; | 
|  | unsigned char *regs; | 
|  | unsigned char *data_window; | 
|  | long flags; | 
|  | #define AF_PORT_CHANGE      0 | 
|  | #define AF_CHPRST_NEEDED    1 | 
|  | #define AF_CHPRST_PENDING   2 | 
|  | #define AF_CHPRST_DETECTED  3 | 
|  | #define AF_BUSRST_NEEDED    4 | 
|  | #define AF_BUSRST_PENDING   5 | 
|  | #define AF_BUSRST_DETECTED  6 | 
|  | #define AF_DISABLED         7 | 
|  | #define AF_FLASH_LOCK       8 | 
|  | #define AF_OS_RESET         9 | 
|  | #define AF_FLASHING         10 | 
|  | #define AF_POWER_MGT        11 | 
|  | #define AF_NVR_VALID        12 | 
|  | #define AF_DEGRADED_MODE    13 | 
|  | #define AF_DISC_PENDING     14 | 
|  | #define AF_TASKLET_SCHEDULED    15 | 
|  | #define AF_HEARTBEAT        16 | 
|  | #define AF_HEARTBEAT_ENB    17 | 
|  | #define AF_NOT_PRESENT      18 | 
|  | #define AF_CHPRST_STARTED   19 | 
|  | #define AF_FIRST_INIT       20 | 
|  | #define AF_POWER_DOWN       21 | 
|  | #define AF_DISC_IN_PROG     22 | 
|  | #define AF_COMM_LIST_TOGGLE 23 | 
|  | #define AF_LEGACY_SGE_MODE  24 | 
|  | #define AF_DISC_POLLED      25 | 
|  | long flags2; | 
|  | #define AF2_SERIAL_FLASH    0 | 
|  | #define AF2_DEV_SCAN        1 | 
|  | #define AF2_DEV_CNT_OK      2 | 
|  | #define AF2_COREDUMP_AVAIL  3 | 
|  | #define AF2_COREDUMP_SAVED  4 | 
|  | #define AF2_VDA_POWER_DOWN  5 | 
|  | #define AF2_THUNDERLINK     6 | 
|  | #define AF2_THUNDERBOLT     7 | 
|  | #define AF2_INIT_DONE       8 | 
|  | #define AF2_INT_PENDING     9 | 
|  | #define AF2_TIMER_TICK      10 | 
|  | #define AF2_IRQ_CLAIMED     11 | 
|  | #define AF2_MSI_ENABLED     12 | 
|  | atomic_t disable_cnt; | 
|  | atomic_t dis_ints_cnt; | 
|  | u32 int_stat; | 
|  | u32 int_mask; | 
|  | u32 volatile *outbound_copy; | 
|  | struct list_head avail_request; | 
|  | spinlock_t request_lock; | 
|  | spinlock_t sg_list_lock; | 
|  | spinlock_t queue_lock; | 
|  | spinlock_t mem_lock; | 
|  | struct list_head free_sg_list_head; | 
|  | struct esas2r_mem_desc *sg_list_mds; | 
|  | struct list_head active_list; | 
|  | struct list_head defer_list; | 
|  | struct esas2r_request **req_table; | 
|  | union { | 
|  | u16 prev_dev_cnt; | 
|  | u32 heartbeat_time; | 
|  | #define ESAS2R_HEARTBEAT_TIME       (3000) | 
|  | }; | 
|  | u32 chip_uptime; | 
|  | #define ESAS2R_CHP_UPTIME_MAX       (60000) | 
|  | #define ESAS2R_CHP_UPTIME_CNT       (20000) | 
|  | u64 uncached_phys; | 
|  | u8 *uncached; | 
|  | struct esas2r_sas_nvram *nvram; | 
|  | struct esas2r_request general_req; | 
|  | u8 init_msg; | 
|  | #define ESAS2R_INIT_MSG_START       1 | 
|  | #define ESAS2R_INIT_MSG_INIT        2 | 
|  | #define ESAS2R_INIT_MSG_GET_INIT    3 | 
|  | #define ESAS2R_INIT_MSG_REINIT      4 | 
|  | u16 cmd_ref_no; | 
|  | u32 fw_version; | 
|  | u32 fw_build; | 
|  | u32 chip_init_time; | 
|  | #define ESAS2R_CHPRST_TIME         (180000) | 
|  | #define ESAS2R_CHPRST_WAIT_TIME    (2000) | 
|  | u32 last_tick_time; | 
|  | u32 window_base; | 
|  | RQBUILDSGL build_sgl; | 
|  | struct esas2r_request *first_ae_req; | 
|  | u32 list_size; | 
|  | u32 last_write; | 
|  | u32 last_read; | 
|  | u16 max_vdareq_size; | 
|  | u16 disc_wait_cnt; | 
|  | struct esas2r_mem_desc inbound_list_md; | 
|  | struct esas2r_mem_desc outbound_list_md; | 
|  | struct esas2r_disc_context disc_ctx; | 
|  | u8 *disc_buffer; | 
|  | u32 disc_start_time; | 
|  | u32 disc_wait_time; | 
|  | u32 flash_ver; | 
|  | char flash_rev[16]; | 
|  | char fw_rev[16]; | 
|  | char image_type[16]; | 
|  | struct esas2r_flash_context flash_context; | 
|  | u32 num_targets_backend; | 
|  | u32 ioctl_tunnel; | 
|  | struct tasklet_struct tasklet; | 
|  | struct pci_dev *pcid; | 
|  | struct Scsi_Host *host; | 
|  | unsigned int index; | 
|  | char name[32]; | 
|  | struct timer_list timer; | 
|  | struct esas2r_firmware firmware; | 
|  | wait_queue_head_t nvram_waiter; | 
|  | int nvram_command_done; | 
|  | wait_queue_head_t fm_api_waiter; | 
|  | int fm_api_command_done; | 
|  | wait_queue_head_t vda_waiter; | 
|  | int vda_command_done; | 
|  | u8 *vda_buffer; | 
|  | u64 ppvda_buffer; | 
|  | #define VDA_BUFFER_HEADER_SZ (offsetof(struct atto_ioctl_vda, data)) | 
|  | #define VDA_MAX_BUFFER_SIZE  (0x40000 + VDA_BUFFER_HEADER_SZ) | 
|  | wait_queue_head_t fs_api_waiter; | 
|  | int fs_api_command_done; | 
|  | u64 ppfs_api_buffer; | 
|  | u8 *fs_api_buffer; | 
|  | u32 fs_api_buffer_size; | 
|  | wait_queue_head_t buffered_ioctl_waiter; | 
|  | int buffered_ioctl_done; | 
|  | int uncached_size; | 
|  | struct workqueue_struct *fw_event_q; | 
|  | struct list_head fw_event_list; | 
|  | spinlock_t fw_event_lock; | 
|  | u8 fw_events_off;                       /* if '1', then ignore events */ | 
|  | char fw_event_q_name[ESAS2R_KOBJ_NAME_LEN]; | 
|  | /* | 
|  | * intr_mode stores the interrupt mode currently being used by this | 
|  | * adapter. it is based on the interrupt_mode module parameter, but | 
|  | * can be changed based on the ability (or not) to utilize the | 
|  | * mode requested by the parameter. | 
|  | */ | 
|  | int intr_mode; | 
|  | #define INTR_MODE_LEGACY 0 | 
|  | #define INTR_MODE_MSI    1 | 
|  | #define INTR_MODE_MSIX   2 | 
|  | struct esas2r_sg_context fm_api_sgc; | 
|  | u8 *save_offset; | 
|  | struct list_head vrq_mds_head; | 
|  | struct esas2r_mem_desc *vrq_mds; | 
|  | int num_vrqs; | 
|  | struct semaphore fm_api_semaphore; | 
|  | struct semaphore fs_api_semaphore; | 
|  | struct semaphore nvram_semaphore; | 
|  | struct atto_ioctl *local_atto_ioctl; | 
|  | u8 fw_coredump_buff[ESAS2R_FWCOREDUMP_SZ]; | 
|  | unsigned int sysfs_fw_created:1; | 
|  | unsigned int sysfs_fs_created:1; | 
|  | unsigned int sysfs_vda_created:1; | 
|  | unsigned int sysfs_hw_created:1; | 
|  | unsigned int sysfs_live_nvram_created:1; | 
|  | unsigned int sysfs_default_nvram_created:1; | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * Function Declarations | 
|  | * SCSI functions | 
|  | */ | 
|  | int esas2r_release(struct Scsi_Host *); | 
|  | const char *esas2r_info(struct Scsi_Host *); | 
|  | int esas2r_write_params(struct esas2r_adapter *a, struct esas2r_request *rq, | 
|  | struct esas2r_sas_nvram *data); | 
|  | int esas2r_ioctl_handler(void *hostdata, int cmd, void __user *arg); | 
|  | int esas2r_ioctl(struct scsi_device *dev, int cmd, void __user *arg); | 
|  | u8 handle_hba_ioctl(struct esas2r_adapter *a, | 
|  | struct atto_ioctl *ioctl_hba); | 
|  | int esas2r_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd); | 
|  | int esas2r_show_info(struct seq_file *m, struct Scsi_Host *sh); | 
|  | int esas2r_slave_alloc(struct scsi_device *dev); | 
|  | int esas2r_slave_configure(struct scsi_device *dev); | 
|  | void esas2r_slave_destroy(struct scsi_device *dev); | 
|  | int esas2r_change_queue_depth(struct scsi_device *dev, int depth, int reason); | 
|  | int esas2r_change_queue_type(struct scsi_device *dev, int type); | 
|  | long esas2r_proc_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); | 
|  |  | 
|  | /* SCSI error handler (eh) functions */ | 
|  | int esas2r_eh_abort(struct scsi_cmnd *cmd); | 
|  | int esas2r_device_reset(struct scsi_cmnd *cmd); | 
|  | int esas2r_host_reset(struct scsi_cmnd *cmd); | 
|  | int esas2r_bus_reset(struct scsi_cmnd *cmd); | 
|  | int esas2r_target_reset(struct scsi_cmnd *cmd); | 
|  |  | 
|  | /* Internal functions */ | 
|  | int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid, | 
|  | int index); | 
|  | int esas2r_cleanup(struct Scsi_Host *host); | 
|  | int esas2r_read_fw(struct esas2r_adapter *a, char *buf, long off, int count); | 
|  | int esas2r_write_fw(struct esas2r_adapter *a, const char *buf, long off, | 
|  | int count); | 
|  | int esas2r_read_vda(struct esas2r_adapter *a, char *buf, long off, int count); | 
|  | int esas2r_write_vda(struct esas2r_adapter *a, const char *buf, long off, | 
|  | int count); | 
|  | int esas2r_read_fs(struct esas2r_adapter *a, char *buf, long off, int count); | 
|  | int esas2r_write_fs(struct esas2r_adapter *a, const char *buf, long off, | 
|  | int count); | 
|  | void esas2r_adapter_tasklet(unsigned long context); | 
|  | irqreturn_t esas2r_interrupt(int irq, void *dev_id); | 
|  | irqreturn_t esas2r_msi_interrupt(int irq, void *dev_id); | 
|  | void esas2r_kickoff_timer(struct esas2r_adapter *a); | 
|  | int esas2r_suspend(struct pci_dev *pcid, pm_message_t state); | 
|  | int esas2r_resume(struct pci_dev *pcid); | 
|  | void esas2r_fw_event_off(struct esas2r_adapter *a); | 
|  | void esas2r_fw_event_on(struct esas2r_adapter *a); | 
|  | bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq, | 
|  | struct esas2r_sas_nvram *nvram); | 
|  | void esas2r_nvram_get_defaults(struct esas2r_adapter *a, | 
|  | struct esas2r_sas_nvram *nvram); | 
|  | void esas2r_complete_request_cb(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq); | 
|  | void esas2r_reset_detected(struct esas2r_adapter *a); | 
|  | void esas2r_target_state_changed(struct esas2r_adapter *ha, u16 targ_id, | 
|  | u8 state); | 
|  | int esas2r_req_status_to_error(u8 req_stat); | 
|  | void esas2r_kill_adapter(int i); | 
|  | void esas2r_free_request(struct esas2r_adapter *a, struct esas2r_request *rq); | 
|  | struct esas2r_request *esas2r_alloc_request(struct esas2r_adapter *a); | 
|  | u32 esas2r_get_uncached_size(struct esas2r_adapter *a); | 
|  | bool esas2r_init_adapter_struct(struct esas2r_adapter *a, | 
|  | void **uncached_area); | 
|  | bool esas2r_check_adapter(struct esas2r_adapter *a); | 
|  | bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll); | 
|  | void esas2r_start_request(struct esas2r_adapter *a, struct esas2r_request *rq); | 
|  | bool esas2r_send_task_mgmt(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rqaux, u8 task_mgt_func); | 
|  | void esas2r_do_tasklet_tasks(struct esas2r_adapter *a); | 
|  | void esas2r_adapter_interrupt(struct esas2r_adapter *a); | 
|  | void esas2r_do_deferred_processes(struct esas2r_adapter *a); | 
|  | void esas2r_reset_bus(struct esas2r_adapter *a); | 
|  | void esas2r_reset_adapter(struct esas2r_adapter *a); | 
|  | void esas2r_timer_tick(struct esas2r_adapter *a); | 
|  | const char *esas2r_get_model_name(struct esas2r_adapter *a); | 
|  | const char *esas2r_get_model_name_short(struct esas2r_adapter *a); | 
|  | u32 esas2r_stall_execution(struct esas2r_adapter *a, u32 start_time, | 
|  | u32 *delay); | 
|  | void esas2r_build_flash_req(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq, | 
|  | u8 sub_func, | 
|  | u8 cksum, | 
|  | u32 addr, | 
|  | u32 length); | 
|  | void esas2r_build_mgt_req(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq, | 
|  | u8 sub_func, | 
|  | u8 scan_gen, | 
|  | u16 dev_index, | 
|  | u32 length, | 
|  | void *data); | 
|  | void esas2r_build_ae_req(struct esas2r_adapter *a, struct esas2r_request *rq); | 
|  | void esas2r_build_cli_req(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq, | 
|  | u32 length, | 
|  | u32 cmd_rsp_len); | 
|  | void esas2r_build_ioctl_req(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq, | 
|  | u32 length, | 
|  | u8 sub_func); | 
|  | void esas2r_build_cfg_req(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq, | 
|  | u8 sub_func, | 
|  | u32 length, | 
|  | void *data); | 
|  | void esas2r_power_down(struct esas2r_adapter *a); | 
|  | bool esas2r_power_up(struct esas2r_adapter *a, bool init_poll); | 
|  | void esas2r_wait_request(struct esas2r_adapter *a, struct esas2r_request *rq); | 
|  | u32 esas2r_map_data_window(struct esas2r_adapter *a, u32 addr_lo); | 
|  | bool esas2r_process_fs_ioctl(struct esas2r_adapter *a, | 
|  | struct esas2r_ioctl_fs *fs, | 
|  | struct esas2r_request *rq, | 
|  | struct esas2r_sg_context *sgc); | 
|  | bool esas2r_read_flash_block(struct esas2r_adapter *a, void *to, u32 from, | 
|  | u32 size); | 
|  | bool esas2r_read_mem_block(struct esas2r_adapter *a, void *to, u32 from, | 
|  | u32 size); | 
|  | bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi, | 
|  | struct esas2r_request *rq, struct esas2r_sg_context *sgc); | 
|  | void esas2r_force_interrupt(struct esas2r_adapter *a); | 
|  | void esas2r_local_start_request(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq); | 
|  | void esas2r_process_adapter_reset(struct esas2r_adapter *a); | 
|  | void esas2r_complete_request(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq); | 
|  | void esas2r_dummy_complete(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq); | 
|  | void esas2r_ae_complete(struct esas2r_adapter *a, struct esas2r_request *rq); | 
|  | void esas2r_start_vda_request(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq); | 
|  | bool esas2r_read_flash_rev(struct esas2r_adapter *a); | 
|  | bool esas2r_read_image_type(struct esas2r_adapter *a); | 
|  | bool esas2r_nvram_read_direct(struct esas2r_adapter *a); | 
|  | bool esas2r_nvram_validate(struct esas2r_adapter *a); | 
|  | void esas2r_nvram_set_defaults(struct esas2r_adapter *a); | 
|  | bool esas2r_print_flash_rev(struct esas2r_adapter *a); | 
|  | void esas2r_send_reset_ae(struct esas2r_adapter *a, bool pwr_mgt); | 
|  | bool esas2r_init_msgs(struct esas2r_adapter *a); | 
|  | bool esas2r_is_adapter_present(struct esas2r_adapter *a); | 
|  | void esas2r_nuxi_mgt_data(u8 function, void *data); | 
|  | void esas2r_nuxi_cfg_data(u8 function, void *data); | 
|  | void esas2r_nuxi_ae_data(union atto_vda_ae *ae); | 
|  | void esas2r_reset_chip(struct esas2r_adapter *a); | 
|  | void esas2r_log_request_failure(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq); | 
|  | void esas2r_polled_interrupt(struct esas2r_adapter *a); | 
|  | bool esas2r_ioreq_aborted(struct esas2r_adapter *a, struct esas2r_request *rq, | 
|  | u8 status); | 
|  | bool esas2r_build_sg_list_sge(struct esas2r_adapter *a, | 
|  | struct esas2r_sg_context *sgc); | 
|  | bool esas2r_build_sg_list_prd(struct esas2r_adapter *a, | 
|  | struct esas2r_sg_context *sgc); | 
|  | void esas2r_targ_db_initialize(struct esas2r_adapter *a); | 
|  | void esas2r_targ_db_remove_all(struct esas2r_adapter *a, bool notify); | 
|  | void esas2r_targ_db_report_changes(struct esas2r_adapter *a); | 
|  | struct esas2r_target *esas2r_targ_db_add_raid(struct esas2r_adapter *a, | 
|  | struct esas2r_disc_context *dc); | 
|  | struct esas2r_target *esas2r_targ_db_add_pthru(struct esas2r_adapter *a, | 
|  | struct esas2r_disc_context *dc, | 
|  | u8 *ident, | 
|  | u8 ident_len); | 
|  | void esas2r_targ_db_remove(struct esas2r_adapter *a, struct esas2r_target *t); | 
|  | struct esas2r_target *esas2r_targ_db_find_by_sas_addr(struct esas2r_adapter *a, | 
|  | u64 *sas_addr); | 
|  | struct esas2r_target *esas2r_targ_db_find_by_ident(struct esas2r_adapter *a, | 
|  | void *identifier, | 
|  | u8 ident_len); | 
|  | u16 esas2r_targ_db_find_next_present(struct esas2r_adapter *a, u16 target_id); | 
|  | struct esas2r_target *esas2r_targ_db_find_by_virt_id(struct esas2r_adapter *a, | 
|  | u16 virt_id); | 
|  | u16 esas2r_targ_db_get_tgt_cnt(struct esas2r_adapter *a); | 
|  | void esas2r_disc_initialize(struct esas2r_adapter *a); | 
|  | void esas2r_disc_start_waiting(struct esas2r_adapter *a); | 
|  | void esas2r_disc_check_for_work(struct esas2r_adapter *a); | 
|  | void esas2r_disc_check_complete(struct esas2r_adapter *a); | 
|  | void esas2r_disc_queue_event(struct esas2r_adapter *a, u8 disc_evt); | 
|  | bool esas2r_disc_start_port(struct esas2r_adapter *a); | 
|  | void esas2r_disc_local_start_request(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq); | 
|  | bool esas2r_set_degraded_mode(struct esas2r_adapter *a, char *error_str); | 
|  | bool esas2r_process_vda_ioctl(struct esas2r_adapter *a, | 
|  | struct atto_ioctl_vda *vi, | 
|  | struct esas2r_request *rq, | 
|  | struct esas2r_sg_context *sgc); | 
|  | void esas2r_queue_fw_event(struct esas2r_adapter *a, | 
|  | enum fw_event_type type, | 
|  | void *data, | 
|  | int data_sz); | 
|  |  | 
|  | /* Inline functions */ | 
|  |  | 
|  | /* Allocate a chip scatter/gather list entry */ | 
|  | static inline struct esas2r_mem_desc *esas2r_alloc_sgl(struct esas2r_adapter *a) | 
|  | { | 
|  | unsigned long flags; | 
|  | struct list_head *sgl; | 
|  | struct esas2r_mem_desc *result = NULL; | 
|  |  | 
|  | spin_lock_irqsave(&a->sg_list_lock, flags); | 
|  | if (likely(!list_empty(&a->free_sg_list_head))) { | 
|  | sgl = a->free_sg_list_head.next; | 
|  | result = list_entry(sgl, struct esas2r_mem_desc, next_desc); | 
|  | list_del_init(sgl); | 
|  | } | 
|  | spin_unlock_irqrestore(&a->sg_list_lock, flags); | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Initialize a scatter/gather context */ | 
|  | static inline void esas2r_sgc_init(struct esas2r_sg_context *sgc, | 
|  | struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq, | 
|  | struct atto_vda_sge *first) | 
|  | { | 
|  | sgc->adapter = a; | 
|  | sgc->first_req = rq; | 
|  |  | 
|  | /* | 
|  | * set the limit pointer such that an SGE pointer above this value | 
|  | * would be the first one to overflow the SGL. | 
|  | */ | 
|  | sgc->sge.a64.limit = (struct atto_vda_sge *)((u8 *)rq->vrq | 
|  | + (sizeof(union | 
|  | atto_vda_req) / | 
|  | 8) | 
|  | - sizeof(struct | 
|  | atto_vda_sge)); | 
|  | if (first) { | 
|  | sgc->sge.a64.last = | 
|  | sgc->sge.a64.curr = first; | 
|  | rq->vrq->scsi.sg_list_offset = (u8) | 
|  | ((u8 *)first - | 
|  | (u8 *)rq->vrq); | 
|  | } else { | 
|  | sgc->sge.a64.last = | 
|  | sgc->sge.a64.curr = &rq->vrq->scsi.u.sge[0]; | 
|  | rq->vrq->scsi.sg_list_offset = | 
|  | (u8)offsetof(struct atto_vda_scsi_req, u.sge); | 
|  | } | 
|  | sgc->sge.a64.chain = NULL; | 
|  | } | 
|  |  | 
|  | static inline void esas2r_rq_init_request(struct esas2r_request *rq, | 
|  | struct esas2r_adapter *a) | 
|  | { | 
|  | union atto_vda_req *vrq = rq->vrq; | 
|  |  | 
|  | INIT_LIST_HEAD(&rq->sg_table_head); | 
|  | rq->data_buf = (void *)(vrq + 1); | 
|  | rq->interrupt_cb = NULL; | 
|  | rq->comp_cb = esas2r_complete_request_cb; | 
|  | rq->flags = 0; | 
|  | rq->timeout = 0; | 
|  | rq->req_stat = RS_PENDING; | 
|  | rq->req_type = RT_INI_REQ; | 
|  |  | 
|  | /* clear the outbound response */ | 
|  | rq->func_rsp.dwords[0] = 0; | 
|  | rq->func_rsp.dwords[1] = 0; | 
|  |  | 
|  | /* | 
|  | * clear the size of the VDA request.  esas2r_build_sg_list() will | 
|  | * only allow the size of the request to grow.  there are some | 
|  | * management requests that go through there twice and the second | 
|  | * time through sets a smaller request size.  if this is not modified | 
|  | * at all we'll set it to the size of the entire VDA request. | 
|  | */ | 
|  | rq->vda_req_sz = RQ_SIZE_DEFAULT; | 
|  |  | 
|  | /* req_table entry should be NULL at this point - if not, halt */ | 
|  |  | 
|  | if (a->req_table[LOWORD(vrq->scsi.handle)]) | 
|  | esas2r_bugon(); | 
|  |  | 
|  | /* fill in the table for this handle so we can get back to the | 
|  | * request. | 
|  | */ | 
|  | a->req_table[LOWORD(vrq->scsi.handle)] = rq; | 
|  |  | 
|  | /* | 
|  | * add a reference number to the handle to make it unique (until it | 
|  | * wraps of course) while preserving the least significant word | 
|  | */ | 
|  | vrq->scsi.handle = (a->cmd_ref_no++ << 16) | (u16)vrq->scsi.handle; | 
|  |  | 
|  | /* | 
|  | * the following formats a SCSI request.  the caller can override as | 
|  | * necessary.  clear_vda_request can be called to clear the VDA | 
|  | * request for another type of request. | 
|  | */ | 
|  | vrq->scsi.function = VDA_FUNC_SCSI; | 
|  | vrq->scsi.sense_len = SENSE_DATA_SZ; | 
|  |  | 
|  | /* clear out sg_list_offset and chain_offset */ | 
|  | vrq->scsi.sg_list_offset = 0; | 
|  | vrq->scsi.chain_offset = 0; | 
|  | vrq->scsi.flags = 0; | 
|  | vrq->scsi.reserved = 0; | 
|  |  | 
|  | /* set the sense buffer to be the data payload buffer */ | 
|  | vrq->scsi.ppsense_buf | 
|  | = cpu_to_le64(rq->vrq_md->phys_addr + | 
|  | sizeof(union atto_vda_req)); | 
|  | } | 
|  |  | 
|  | static inline void esas2r_rq_free_sg_lists(struct esas2r_request *rq, | 
|  | struct esas2r_adapter *a) | 
|  | { | 
|  | unsigned long flags; | 
|  |  | 
|  | if (list_empty(&rq->sg_table_head)) | 
|  | return; | 
|  |  | 
|  | spin_lock_irqsave(&a->sg_list_lock, flags); | 
|  | list_splice_tail_init(&rq->sg_table_head, &a->free_sg_list_head); | 
|  | spin_unlock_irqrestore(&a->sg_list_lock, flags); | 
|  | } | 
|  |  | 
|  | static inline void esas2r_rq_destroy_request(struct esas2r_request *rq, | 
|  | struct esas2r_adapter *a) | 
|  |  | 
|  | { | 
|  | esas2r_rq_free_sg_lists(rq, a); | 
|  | a->req_table[LOWORD(rq->vrq->scsi.handle)] = NULL; | 
|  | rq->data_buf = NULL; | 
|  | } | 
|  |  | 
|  | static inline bool esas2r_is_tasklet_pending(struct esas2r_adapter *a) | 
|  | { | 
|  |  | 
|  | return test_bit(AF_BUSRST_NEEDED, &a->flags) || | 
|  | test_bit(AF_BUSRST_DETECTED, &a->flags) || | 
|  | test_bit(AF_CHPRST_NEEDED, &a->flags) || | 
|  | test_bit(AF_CHPRST_DETECTED, &a->flags) || | 
|  | test_bit(AF_PORT_CHANGE, &a->flags); | 
|  |  | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Build the scatter/gather list for an I/O request according to the | 
|  | * specifications placed in the esas2r_sg_context.  The caller must initialize | 
|  | * struct esas2r_sg_context prior to the initial call by calling | 
|  | * esas2r_sgc_init() | 
|  | */ | 
|  | static inline bool esas2r_build_sg_list(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq, | 
|  | struct esas2r_sg_context *sgc) | 
|  | { | 
|  | if (unlikely(le32_to_cpu(rq->vrq->scsi.length) == 0)) | 
|  | return true; | 
|  |  | 
|  | return (*a->build_sgl)(a, sgc); | 
|  | } | 
|  |  | 
|  | static inline void esas2r_disable_chip_interrupts(struct esas2r_adapter *a) | 
|  | { | 
|  | if (atomic_inc_return(&a->dis_ints_cnt) == 1) | 
|  | esas2r_write_register_dword(a, MU_INT_MASK_OUT, | 
|  | ESAS2R_INT_DIS_MASK); | 
|  | } | 
|  |  | 
|  | static inline void esas2r_enable_chip_interrupts(struct esas2r_adapter *a) | 
|  | { | 
|  | if (atomic_dec_return(&a->dis_ints_cnt) == 0) | 
|  | esas2r_write_register_dword(a, MU_INT_MASK_OUT, | 
|  | ESAS2R_INT_ENB_MASK); | 
|  | } | 
|  |  | 
|  | /* Schedule a TASKLET to perform non-interrupt tasks that may require delays | 
|  | * or long completion times. | 
|  | */ | 
|  | static inline void esas2r_schedule_tasklet(struct esas2r_adapter *a) | 
|  | { | 
|  | /* make sure we don't schedule twice */ | 
|  | if (!test_and_set_bit(AF_TASKLET_SCHEDULED, &a->flags)) | 
|  | tasklet_hi_schedule(&a->tasklet); | 
|  | } | 
|  |  | 
|  | static inline void esas2r_enable_heartbeat(struct esas2r_adapter *a) | 
|  | { | 
|  | if (!test_bit(AF_DEGRADED_MODE, &a->flags) && | 
|  | !test_bit(AF_CHPRST_PENDING, &a->flags) && | 
|  | (a->nvram->options2 & SASNVR2_HEARTBEAT)) | 
|  | set_bit(AF_HEARTBEAT_ENB, &a->flags); | 
|  | else | 
|  | clear_bit(AF_HEARTBEAT_ENB, &a->flags); | 
|  | } | 
|  |  | 
|  | static inline void esas2r_disable_heartbeat(struct esas2r_adapter *a) | 
|  | { | 
|  | clear_bit(AF_HEARTBEAT_ENB, &a->flags); | 
|  | clear_bit(AF_HEARTBEAT, &a->flags); | 
|  | } | 
|  |  | 
|  | /* Set the initial state for resetting the adapter on the next pass through | 
|  | * esas2r_do_deferred. | 
|  | */ | 
|  | static inline void esas2r_local_reset_adapter(struct esas2r_adapter *a) | 
|  | { | 
|  | esas2r_disable_heartbeat(a); | 
|  |  | 
|  | set_bit(AF_CHPRST_NEEDED, &a->flags); | 
|  | set_bit(AF_CHPRST_PENDING, &a->flags); | 
|  | set_bit(AF_DISC_PENDING, &a->flags); | 
|  | } | 
|  |  | 
|  | /* See if an interrupt is pending on the adapter. */ | 
|  | static inline bool esas2r_adapter_interrupt_pending(struct esas2r_adapter *a) | 
|  | { | 
|  | u32 intstat; | 
|  |  | 
|  | if (a->int_mask == 0) | 
|  | return false; | 
|  |  | 
|  | intstat = esas2r_read_register_dword(a, MU_INT_STATUS_OUT); | 
|  |  | 
|  | if ((intstat & a->int_mask) == 0) | 
|  | return false; | 
|  |  | 
|  | esas2r_disable_chip_interrupts(a); | 
|  |  | 
|  | a->int_stat = intstat; | 
|  | a->int_mask = 0; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static inline u16 esas2r_targ_get_id(struct esas2r_target *t, | 
|  | struct esas2r_adapter *a) | 
|  | { | 
|  | return (u16)(uintptr_t)(t - a->targetdb); | 
|  | } | 
|  |  | 
|  | /*  Build and start an asynchronous event request */ | 
|  | static inline void esas2r_start_ae_request(struct esas2r_adapter *a, | 
|  | struct esas2r_request *rq) | 
|  | { | 
|  | unsigned long flags; | 
|  |  | 
|  | esas2r_build_ae_req(a, rq); | 
|  |  | 
|  | spin_lock_irqsave(&a->queue_lock, flags); | 
|  | esas2r_start_vda_request(a, rq); | 
|  | spin_unlock_irqrestore(&a->queue_lock, flags); | 
|  | } | 
|  |  | 
|  | static inline void esas2r_comp_list_drain(struct esas2r_adapter *a, | 
|  | struct list_head *comp_list) | 
|  | { | 
|  | struct esas2r_request *rq; | 
|  | struct list_head *element, *next; | 
|  |  | 
|  | list_for_each_safe(element, next, comp_list) { | 
|  | rq = list_entry(element, struct esas2r_request, comp_list); | 
|  | list_del_init(element); | 
|  | esas2r_complete_request(a, rq); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* sysfs handlers */ | 
|  | extern struct bin_attribute bin_attr_fw; | 
|  | extern struct bin_attribute bin_attr_fs; | 
|  | extern struct bin_attribute bin_attr_vda; | 
|  | extern struct bin_attribute bin_attr_hw; | 
|  | extern struct bin_attribute bin_attr_live_nvram; | 
|  | extern struct bin_attribute bin_attr_default_nvram; | 
|  |  | 
|  | #endif /* ESAS2R_H */ |