2013-08-23 18:35:45 +04:00
/*
* 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 ( 88 R9580 ) 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 ;
2013-10-01 22:26:01 +04:00
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
2013-08-23 18:35:45 +04:00
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 ) ;
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
2013-10-01 22:26:02 +04:00
* wraps of course ) while preserving the least significant word
2013-08-23 18:35:45 +04:00
*/
2013-10-01 22:26:02 +04:00
vrq - > scsi . handle = ( a - > cmd_ref_no + + < < 16 ) | ( u16 ) vrq - > scsi . handle ;
2013-08-23 18:35:45 +04:00
/*
* 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 )
{
2013-10-01 22:26:01 +04:00
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 ) ;
2013-08-23 18:35:45 +04:00
}
/*
* 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 */
2013-10-01 22:26:01 +04:00
if ( ! test_and_set_bit ( AF_TASKLET_SCHEDULED , & a - > flags ) )
2013-08-23 18:35:45 +04:00
tasklet_hi_schedule ( & a - > tasklet ) ;
}
static inline void esas2r_enable_heartbeat ( struct esas2r_adapter * a )
{
2013-10-01 22:26:01 +04:00
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 ) ;
2013-08-23 18:35:45 +04:00
else
2013-10-01 22:26:01 +04:00
clear_bit ( AF_HEARTBEAT_ENB , & a - > flags ) ;
2013-08-23 18:35:45 +04:00
}
static inline void esas2r_disable_heartbeat ( struct esas2r_adapter * a )
{
2013-10-01 22:26:01 +04:00
clear_bit ( AF_HEARTBEAT_ENB , & a - > flags ) ;
clear_bit ( AF_HEARTBEAT , & a - > flags ) ;
2013-08-23 18:35:45 +04:00
}
/* 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 ) ;
2013-10-01 22:26:01 +04:00
set_bit ( AF_CHPRST_NEEDED , & a - > flags ) ;
set_bit ( AF_CHPRST_PENDING , & a - > flags ) ;
set_bit ( AF_DISC_PENDING , & a - > flags ) ;
2013-08-23 18:35:45 +04:00
}
/* 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 */