Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1 | /* |
| 2 | * linux/drivers/scsi/esas2r/esas2r.h |
| 3 | * For use with ATTO ExpressSAS R6xx SAS/SATA RAID controllers |
| 4 | * |
| 5 | * Copyright (c) 2001-2013 ATTO Technology, Inc. |
| 6 | * (mailto:linuxdrivers@attotech.com) |
| 7 | * |
| 8 | * This program is free software; you can redistribute it and/or |
| 9 | * modify it under the terms of the GNU General Public License |
| 10 | * as published by the Free Software Foundation; either version 2 |
| 11 | * of the License, or (at your option) any later version. |
| 12 | * |
| 13 | * This program is distributed in the hope that it will be useful, |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | * GNU General Public License for more details. |
| 17 | * |
| 18 | * NO WARRANTY |
| 19 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR |
| 20 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT |
| 21 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, |
| 22 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is |
| 23 | * solely responsible for determining the appropriateness of using and |
| 24 | * distributing the Program and assumes all risks associated with its |
| 25 | * exercise of rights under this Agreement, including but not limited to |
| 26 | * the risks and costs of program errors, damage to or loss of data, |
| 27 | * programs or equipment, and unavailability or interruption of operations. |
| 28 | * |
| 29 | * DISCLAIMER OF LIABILITY |
| 30 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY |
| 31 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 32 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND |
| 33 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
| 34 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
| 35 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED |
| 36 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES |
| 37 | * |
| 38 | * You should have received a copy of the GNU General Public License |
| 39 | * along with this program; if not, write to the Free Software |
| 40 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
| 41 | * USA. |
| 42 | */ |
| 43 | |
| 44 | #include <linux/kernel.h> |
| 45 | #include <linux/delay.h> |
| 46 | #include <linux/pci.h> |
| 47 | #include <linux/proc_fs.h> |
| 48 | #include <linux/workqueue.h> |
| 49 | #include <linux/interrupt.h> |
| 50 | #include <linux/module.h> |
| 51 | #include <linux/vmalloc.h> |
| 52 | #include <scsi/scsi.h> |
| 53 | #include <scsi/scsi_host.h> |
| 54 | #include <scsi/scsi_cmnd.h> |
| 55 | #include <scsi/scsi_device.h> |
| 56 | #include <scsi/scsi_eh.h> |
| 57 | #include <scsi/scsi_tcq.h> |
| 58 | |
| 59 | #include "esas2r_log.h" |
| 60 | #include "atioctl.h" |
| 61 | #include "atvda.h" |
| 62 | |
| 63 | #ifndef ESAS2R_H |
| 64 | #define ESAS2R_H |
| 65 | |
| 66 | /* Global Variables */ |
| 67 | extern struct esas2r_adapter *esas2r_adapters[]; |
| 68 | extern u8 *esas2r_buffered_ioctl; |
| 69 | extern dma_addr_t esas2r_buffered_ioctl_addr; |
| 70 | extern u32 esas2r_buffered_ioctl_size; |
| 71 | extern struct pci_dev *esas2r_buffered_ioctl_pcid; |
| 72 | #define SGL_PG_SZ_MIN 64 |
| 73 | #define SGL_PG_SZ_MAX 1024 |
| 74 | extern int sgl_page_size; |
| 75 | #define NUM_SGL_MIN 8 |
| 76 | #define NUM_SGL_MAX 2048 |
| 77 | extern int num_sg_lists; |
| 78 | #define NUM_REQ_MIN 4 |
| 79 | #define NUM_REQ_MAX 256 |
| 80 | extern int num_requests; |
| 81 | #define NUM_AE_MIN 2 |
| 82 | #define NUM_AE_MAX 8 |
| 83 | extern int num_ae_requests; |
| 84 | extern int cmd_per_lun; |
| 85 | extern int can_queue; |
| 86 | extern int esas2r_max_sectors; |
| 87 | extern int sg_tablesize; |
| 88 | extern int interrupt_mode; |
| 89 | extern int num_io_requests; |
| 90 | |
| 91 | /* Macro defintions */ |
| 92 | #define ESAS2R_MAX_ID 255 |
| 93 | #define MAX_ADAPTERS 32 |
| 94 | #define ESAS2R_DRVR_NAME "esas2r" |
| 95 | #define ESAS2R_LONGNAME "ATTO ExpressSAS 6GB RAID Adapter" |
| 96 | #define ESAS2R_MAX_DEVICES 32 |
| 97 | #define ATTONODE_NAME "ATTONode" |
| 98 | #define ESAS2R_MAJOR_REV 1 |
| 99 | #define ESAS2R_MINOR_REV 00 |
| 100 | #define ESAS2R_VERSION_STR DEFINED_NUM_TO_STR(ESAS2R_MAJOR_REV) "." \ |
| 101 | DEFINED_NUM_TO_STR(ESAS2R_MINOR_REV) |
| 102 | #define ESAS2R_COPYRIGHT_YEARS "2001-2013" |
| 103 | #define ESAS2R_DEFAULT_SGL_PAGE_SIZE 384 |
| 104 | #define ESAS2R_DEFAULT_CMD_PER_LUN 64 |
| 105 | #define ESAS2R_DEFAULT_NUM_SG_LISTS 1024 |
| 106 | #define DEFINED_NUM_TO_STR(num) NUM_TO_STR(num) |
| 107 | #define NUM_TO_STR(num) #num |
| 108 | |
| 109 | #define ESAS2R_SGL_ALIGN 16 |
| 110 | #define ESAS2R_LIST_ALIGN 16 |
| 111 | #define ESAS2R_LIST_EXTRA ESAS2R_NUM_EXTRA |
| 112 | #define ESAS2R_DATA_BUF_LEN 256 |
| 113 | #define ESAS2R_DEFAULT_TMO 5000 |
| 114 | #define ESAS2R_DISC_BUF_LEN 512 |
| 115 | #define ESAS2R_FWCOREDUMP_SZ 0x80000 |
| 116 | #define ESAS2R_NUM_PHYS 8 |
| 117 | #define ESAS2R_TARG_ID_INV 0xFFFF |
| 118 | #define ESAS2R_INT_STS_MASK MU_INTSTAT_MASK |
| 119 | #define ESAS2R_INT_ENB_MASK MU_INTSTAT_MASK |
| 120 | #define ESAS2R_INT_DIS_MASK 0 |
| 121 | #define ESAS2R_MAX_TARGETS 256 |
| 122 | #define ESAS2R_KOBJ_NAME_LEN 20 |
| 123 | |
| 124 | /* u16 (WORD) component macros */ |
| 125 | #define LOBYTE(w) ((u8)(u16)(w)) |
| 126 | #define HIBYTE(w) ((u8)(((u16)(w)) >> 8)) |
| 127 | #define MAKEWORD(lo, hi) ((u16)((u8)(lo) | ((u16)(u8)(hi) << 8))) |
| 128 | |
| 129 | /* u32 (DWORD) component macros */ |
| 130 | #define LOWORD(d) ((u16)(u32)(d)) |
| 131 | #define HIWORD(d) ((u16)(((u32)(d)) >> 16)) |
| 132 | #define MAKEDWORD(lo, hi) ((u32)((u16)(lo) | ((u32)(u16)(hi) << 16))) |
| 133 | |
| 134 | /* macro to get the lowest nonzero bit of a value */ |
| 135 | #define LOBIT(x) ((x) & (0 - (x))) |
| 136 | |
| 137 | /* These functions are provided to access the chip's control registers. |
| 138 | * The register is specified by its byte offset from the register base |
| 139 | * for the adapter. |
| 140 | */ |
| 141 | #define esas2r_read_register_dword(a, reg) \ |
| 142 | readl((void __iomem *)a->regs + (reg) + MW_REG_OFFSET_HWREG) |
| 143 | |
| 144 | #define esas2r_write_register_dword(a, reg, data) \ |
| 145 | writel(data, (void __iomem *)(a->regs + (reg) + MW_REG_OFFSET_HWREG)) |
| 146 | |
| 147 | #define esas2r_flush_register_dword(a, r) esas2r_read_register_dword(a, r) |
| 148 | |
| 149 | /* This function is provided to access the chip's data window. The |
| 150 | * register is specified by its byte offset from the window base |
| 151 | * for the adapter. |
| 152 | */ |
| 153 | #define esas2r_read_data_byte(a, reg) \ |
| 154 | readb((void __iomem *)a->data_window + (reg)) |
| 155 | |
| 156 | /* ATTO vendor and device Ids */ |
| 157 | #define ATTO_VENDOR_ID 0x117C |
| 158 | #define ATTO_DID_INTEL_IOP348 0x002C |
| 159 | #define ATTO_DID_MV_88RC9580 0x0049 |
| 160 | #define ATTO_DID_MV_88RC9580TS 0x0066 |
| 161 | #define ATTO_DID_MV_88RC9580TSE 0x0067 |
| 162 | #define ATTO_DID_MV_88RC9580TL 0x0068 |
| 163 | |
| 164 | /* ATTO subsystem device Ids */ |
| 165 | #define ATTO_SSDID_TBT 0x4000 |
| 166 | #define ATTO_TSSC_3808 0x4066 |
| 167 | #define ATTO_TSSC_3808E 0x4067 |
| 168 | #define ATTO_TLSH_1068 0x4068 |
| 169 | #define ATTO_ESAS_R680 0x0049 |
| 170 | #define ATTO_ESAS_R608 0x004A |
| 171 | #define ATTO_ESAS_R60F 0x004B |
| 172 | #define ATTO_ESAS_R6F0 0x004C |
| 173 | #define ATTO_ESAS_R644 0x004D |
| 174 | #define ATTO_ESAS_R648 0x004E |
| 175 | |
| 176 | /* |
| 177 | * flash definitions & structures |
| 178 | * define the code types |
| 179 | */ |
| 180 | #define FBT_CPYR 0xAA00 |
| 181 | #define FBT_SETUP 0xAA02 |
| 182 | #define FBT_FLASH_VER 0xAA04 |
| 183 | |
| 184 | /* offsets to various locations in flash */ |
| 185 | #define FLS_OFFSET_BOOT (u32)(0x00700000) |
| 186 | #define FLS_OFFSET_NVR (u32)(0x007C0000) |
| 187 | #define FLS_OFFSET_CPYR FLS_OFFSET_NVR |
| 188 | #define FLS_LENGTH_BOOT (FLS_OFFSET_CPYR - FLS_OFFSET_BOOT) |
| 189 | #define FLS_BLOCK_SIZE (u32)(0x00020000) |
| 190 | #define FI_NVR_2KB 0x0800 |
| 191 | #define FI_NVR_8KB 0x2000 |
| 192 | #define FM_BUF_SZ 0x800 |
| 193 | |
| 194 | /* |
| 195 | * marvell frey (88R9580) register definitions |
| 196 | * chip revision identifiers |
| 197 | */ |
| 198 | #define MVR_FREY_B2 0xB2 |
| 199 | |
| 200 | /* |
| 201 | * memory window definitions. window 0 is the data window with definitions |
| 202 | * of MW_DATA_XXX. window 1 is the register window with definitions of |
| 203 | * MW_REG_XXX. |
| 204 | */ |
| 205 | #define MW_REG_WINDOW_SIZE (u32)(0x00040000) |
| 206 | #define MW_REG_OFFSET_HWREG (u32)(0x00000000) |
| 207 | #define MW_REG_OFFSET_PCI (u32)(0x00008000) |
| 208 | #define MW_REG_PCI_HWREG_DELTA (MW_REG_OFFSET_PCI - MW_REG_OFFSET_HWREG) |
| 209 | #define MW_DATA_WINDOW_SIZE (u32)(0x00020000) |
| 210 | #define MW_DATA_ADDR_SER_FLASH (u32)(0xEC000000) |
| 211 | #define MW_DATA_ADDR_SRAM (u32)(0xF4000000) |
| 212 | #define MW_DATA_ADDR_PAR_FLASH (u32)(0xFC000000) |
| 213 | |
| 214 | /* |
| 215 | * the following registers are for the communication |
| 216 | * list interface (AKA message unit (MU)) |
| 217 | */ |
| 218 | #define MU_IN_LIST_ADDR_LO (u32)(0x00004000) |
| 219 | #define MU_IN_LIST_ADDR_HI (u32)(0x00004004) |
| 220 | |
| 221 | #define MU_IN_LIST_WRITE (u32)(0x00004018) |
| 222 | #define MU_ILW_TOGGLE (u32)(0x00004000) |
| 223 | |
| 224 | #define MU_IN_LIST_READ (u32)(0x0000401C) |
| 225 | #define MU_ILR_TOGGLE (u32)(0x00004000) |
| 226 | #define MU_ILIC_LIST (u32)(0x0000000F) |
| 227 | #define MU_ILIC_LIST_F0 (u32)(0x00000000) |
| 228 | #define MU_ILIC_DEST (u32)(0x00000F00) |
| 229 | #define MU_ILIC_DEST_DDR (u32)(0x00000200) |
| 230 | #define MU_IN_LIST_IFC_CONFIG (u32)(0x00004028) |
| 231 | |
| 232 | #define MU_IN_LIST_CONFIG (u32)(0x0000402C) |
| 233 | #define MU_ILC_ENABLE (u32)(0x00000001) |
| 234 | #define MU_ILC_ENTRY_MASK (u32)(0x000000F0) |
| 235 | #define MU_ILC_ENTRY_4_DW (u32)(0x00000020) |
| 236 | #define MU_ILC_DYNAMIC_SRC (u32)(0x00008000) |
| 237 | #define MU_ILC_NUMBER_MASK (u32)(0x7FFF0000) |
| 238 | #define MU_ILC_NUMBER_SHIFT 16 |
| 239 | |
| 240 | #define MU_OUT_LIST_ADDR_LO (u32)(0x00004050) |
| 241 | #define MU_OUT_LIST_ADDR_HI (u32)(0x00004054) |
| 242 | |
| 243 | #define MU_OUT_LIST_COPY_PTR_LO (u32)(0x00004058) |
| 244 | #define MU_OUT_LIST_COPY_PTR_HI (u32)(0x0000405C) |
| 245 | |
| 246 | #define MU_OUT_LIST_WRITE (u32)(0x00004068) |
| 247 | #define MU_OLW_TOGGLE (u32)(0x00004000) |
| 248 | |
| 249 | #define MU_OUT_LIST_COPY (u32)(0x0000406C) |
| 250 | #define MU_OLC_TOGGLE (u32)(0x00004000) |
| 251 | #define MU_OLC_WRT_PTR (u32)(0x00003FFF) |
| 252 | |
| 253 | #define MU_OUT_LIST_IFC_CONFIG (u32)(0x00004078) |
| 254 | #define MU_OLIC_LIST (u32)(0x0000000F) |
| 255 | #define MU_OLIC_LIST_F0 (u32)(0x00000000) |
| 256 | #define MU_OLIC_SOURCE (u32)(0x00000F00) |
| 257 | #define MU_OLIC_SOURCE_DDR (u32)(0x00000200) |
| 258 | |
| 259 | #define MU_OUT_LIST_CONFIG (u32)(0x0000407C) |
| 260 | #define MU_OLC_ENABLE (u32)(0x00000001) |
| 261 | #define MU_OLC_ENTRY_MASK (u32)(0x000000F0) |
| 262 | #define MU_OLC_ENTRY_4_DW (u32)(0x00000020) |
| 263 | #define MU_OLC_NUMBER_MASK (u32)(0x7FFF0000) |
| 264 | #define MU_OLC_NUMBER_SHIFT 16 |
| 265 | |
| 266 | #define MU_OUT_LIST_INT_STAT (u32)(0x00004088) |
| 267 | #define MU_OLIS_INT (u32)(0x00000001) |
| 268 | |
| 269 | #define MU_OUT_LIST_INT_MASK (u32)(0x0000408C) |
| 270 | #define MU_OLIS_MASK (u32)(0x00000001) |
| 271 | |
| 272 | /* |
| 273 | * the maximum size of the communication lists is two greater than the |
| 274 | * maximum amount of VDA requests. the extra are to prevent queue overflow. |
| 275 | */ |
| 276 | #define ESAS2R_MAX_NUM_REQS 256 |
| 277 | #define ESAS2R_NUM_EXTRA 2 |
| 278 | #define ESAS2R_MAX_COMM_LIST_SIZE (ESAS2R_MAX_NUM_REQS + ESAS2R_NUM_EXTRA) |
| 279 | |
| 280 | /* |
| 281 | * the following registers are for the CPU interface |
| 282 | */ |
| 283 | #define MU_CTL_STATUS_IN (u32)(0x00010108) |
| 284 | #define MU_CTL_IN_FULL_RST (u32)(0x00000020) |
| 285 | #define MU_CTL_STATUS_IN_B2 (u32)(0x00010130) |
| 286 | #define MU_CTL_IN_FULL_RST2 (u32)(0x80000000) |
| 287 | #define MU_DOORBELL_IN (u32)(0x00010460) |
| 288 | #define DRBL_RESET_BUS (u32)(0x00000002) |
| 289 | #define DRBL_PAUSE_AE (u32)(0x00000004) |
| 290 | #define DRBL_RESUME_AE (u32)(0x00000008) |
| 291 | #define DRBL_MSG_IFC_DOWN (u32)(0x00000010) |
| 292 | #define DRBL_FLASH_REQ (u32)(0x00000020) |
| 293 | #define DRBL_FLASH_DONE (u32)(0x00000040) |
| 294 | #define DRBL_FORCE_INT (u32)(0x00000080) |
| 295 | #define DRBL_MSG_IFC_INIT (u32)(0x00000100) |
| 296 | #define DRBL_POWER_DOWN (u32)(0x00000200) |
| 297 | #define DRBL_DRV_VER_1 (u32)(0x00010000) |
| 298 | #define DRBL_DRV_VER DRBL_DRV_VER_1 |
| 299 | #define MU_DOORBELL_IN_ENB (u32)(0x00010464) |
| 300 | #define MU_DOORBELL_OUT (u32)(0x00010480) |
| 301 | #define DRBL_PANIC_REASON_MASK (u32)(0x00F00000) |
| 302 | #define DRBL_UNUSED_HANDLER (u32)(0x00100000) |
| 303 | #define DRBL_UNDEF_INSTR (u32)(0x00200000) |
| 304 | #define DRBL_PREFETCH_ABORT (u32)(0x00300000) |
| 305 | #define DRBL_DATA_ABORT (u32)(0x00400000) |
| 306 | #define DRBL_JUMP_TO_ZERO (u32)(0x00500000) |
| 307 | #define DRBL_FW_RESET (u32)(0x00080000) |
| 308 | #define DRBL_FW_VER_MSK (u32)(0x00070000) |
| 309 | #define DRBL_FW_VER_0 (u32)(0x00000000) |
| 310 | #define DRBL_FW_VER_1 (u32)(0x00010000) |
| 311 | #define DRBL_FW_VER DRBL_FW_VER_1 |
| 312 | #define MU_DOORBELL_OUT_ENB (u32)(0x00010484) |
| 313 | #define DRBL_ENB_MASK (u32)(0x00F803FF) |
| 314 | #define MU_INT_STATUS_OUT (u32)(0x00010200) |
| 315 | #define MU_INTSTAT_POST_OUT (u32)(0x00000010) |
| 316 | #define MU_INTSTAT_DRBL_IN (u32)(0x00000100) |
| 317 | #define MU_INTSTAT_DRBL (u32)(0x00001000) |
| 318 | #define MU_INTSTAT_MASK (u32)(0x00001010) |
| 319 | #define MU_INT_MASK_OUT (u32)(0x0001020C) |
| 320 | |
| 321 | /* PCI express registers accessed via window 1 */ |
| 322 | #define MVR_PCI_WIN1_REMAP (u32)(0x00008438) |
| 323 | #define MVRPW1R_ENABLE (u32)(0x00000001) |
| 324 | |
| 325 | |
| 326 | /* structures */ |
| 327 | |
| 328 | /* inbound list dynamic source entry */ |
| 329 | struct esas2r_inbound_list_source_entry { |
| 330 | u64 address; |
| 331 | u32 length; |
| 332 | #define HWILSE_INTERFACE_F0 0x00000000 |
| 333 | u32 reserved; |
| 334 | }; |
| 335 | |
| 336 | /* PCI data structure in expansion ROM images */ |
| 337 | struct __packed esas2r_boot_header { |
| 338 | char signature[4]; |
| 339 | u16 vendor_id; |
| 340 | u16 device_id; |
| 341 | u16 VPD; |
| 342 | u16 struct_length; |
| 343 | u8 struct_revision; |
| 344 | u8 class_code[3]; |
| 345 | u16 image_length; |
| 346 | u16 code_revision; |
| 347 | u8 code_type; |
| 348 | #define CODE_TYPE_PC 0 |
| 349 | #define CODE_TYPE_OPEN 1 |
| 350 | #define CODE_TYPE_EFI 3 |
| 351 | u8 indicator; |
| 352 | #define INDICATOR_LAST 0x80 |
| 353 | u8 reserved[2]; |
| 354 | }; |
| 355 | |
| 356 | struct __packed esas2r_boot_image { |
| 357 | u16 signature; |
| 358 | u8 reserved[22]; |
| 359 | u16 header_offset; |
| 360 | u16 pnp_offset; |
| 361 | }; |
| 362 | |
| 363 | struct __packed esas2r_pc_image { |
| 364 | u16 signature; |
| 365 | u8 length; |
| 366 | u8 entry_point[3]; |
| 367 | u8 checksum; |
| 368 | u16 image_end; |
| 369 | u16 min_size; |
| 370 | u8 rom_flags; |
| 371 | u8 reserved[12]; |
| 372 | u16 header_offset; |
| 373 | u16 pnp_offset; |
| 374 | struct esas2r_boot_header boot_image; |
| 375 | }; |
| 376 | |
| 377 | struct __packed esas2r_efi_image { |
| 378 | u16 signature; |
| 379 | u16 length; |
| 380 | u32 efi_signature; |
| 381 | #define EFI_ROM_SIG 0x00000EF1 |
| 382 | u16 image_type; |
| 383 | #define EFI_IMAGE_APP 10 |
| 384 | #define EFI_IMAGE_BSD 11 |
| 385 | #define EFI_IMAGE_RTD 12 |
| 386 | u16 machine_type; |
| 387 | #define EFI_MACHINE_IA32 0x014c |
| 388 | #define EFI_MACHINE_IA64 0x0200 |
| 389 | #define EFI_MACHINE_X64 0x8664 |
| 390 | #define EFI_MACHINE_EBC 0x0EBC |
| 391 | u16 compression; |
| 392 | #define EFI_UNCOMPRESSED 0x0000 |
| 393 | #define EFI_COMPRESSED 0x0001 |
| 394 | u8 reserved[8]; |
| 395 | u16 efi_offset; |
| 396 | u16 header_offset; |
| 397 | u16 reserved2; |
| 398 | struct esas2r_boot_header boot_image; |
| 399 | }; |
| 400 | |
| 401 | struct esas2r_adapter; |
| 402 | struct esas2r_sg_context; |
| 403 | struct esas2r_request; |
| 404 | |
| 405 | typedef void (*RQCALLBK) (struct esas2r_adapter *a, |
| 406 | struct esas2r_request *rq); |
| 407 | typedef bool (*RQBUILDSGL) (struct esas2r_adapter *a, |
| 408 | struct esas2r_sg_context *sgc); |
| 409 | |
| 410 | struct esas2r_component_header { |
| 411 | u8 img_type; |
| 412 | #define CH_IT_FW 0x00 |
| 413 | #define CH_IT_NVR 0x01 |
| 414 | #define CH_IT_BIOS 0x02 |
| 415 | #define CH_IT_MAC 0x03 |
| 416 | #define CH_IT_CFG 0x04 |
| 417 | #define CH_IT_EFI 0x05 |
| 418 | u8 status; |
| 419 | #define CH_STAT_PENDING 0xff |
| 420 | #define CH_STAT_FAILED 0x00 |
| 421 | #define CH_STAT_SUCCESS 0x01 |
| 422 | #define CH_STAT_RETRY 0x02 |
| 423 | #define CH_STAT_INVALID 0x03 |
| 424 | u8 pad[2]; |
| 425 | u32 version; |
| 426 | u32 length; |
| 427 | u32 image_offset; |
| 428 | }; |
| 429 | |
| 430 | #define FI_REL_VER_SZ 16 |
| 431 | |
| 432 | struct esas2r_flash_img_v0 { |
| 433 | u8 fi_version; |
| 434 | #define FI_VERSION_0 00 |
| 435 | u8 status; |
| 436 | u8 adap_typ; |
| 437 | u8 action; |
| 438 | u32 length; |
| 439 | u16 checksum; |
| 440 | u16 driver_error; |
| 441 | u16 flags; |
| 442 | u16 num_comps; |
| 443 | #define FI_NUM_COMPS_V0 5 |
| 444 | u8 rel_version[FI_REL_VER_SZ]; |
| 445 | struct esas2r_component_header cmp_hdr[FI_NUM_COMPS_V0]; |
| 446 | u8 scratch_buf[FM_BUF_SZ]; |
| 447 | }; |
| 448 | |
| 449 | struct esas2r_flash_img { |
| 450 | u8 fi_version; |
| 451 | #define FI_VERSION_1 01 |
| 452 | u8 status; |
| 453 | #define FI_STAT_SUCCESS 0x00 |
| 454 | #define FI_STAT_FAILED 0x01 |
| 455 | #define FI_STAT_REBOOT 0x02 |
| 456 | #define FI_STAT_ADAPTYP 0x03 |
| 457 | #define FI_STAT_INVALID 0x04 |
| 458 | #define FI_STAT_CHKSUM 0x05 |
| 459 | #define FI_STAT_LENGTH 0x06 |
| 460 | #define FI_STAT_UNKNOWN 0x07 |
| 461 | #define FI_STAT_IMG_VER 0x08 |
| 462 | #define FI_STAT_BUSY 0x09 |
| 463 | #define FI_STAT_DUAL 0x0A |
| 464 | #define FI_STAT_MISSING 0x0B |
| 465 | #define FI_STAT_UNSUPP 0x0C |
| 466 | #define FI_STAT_ERASE 0x0D |
| 467 | #define FI_STAT_FLASH 0x0E |
| 468 | #define FI_STAT_DEGRADED 0x0F |
| 469 | u8 adap_typ; |
| 470 | #define FI_AT_UNKNWN 0xFF |
| 471 | #define FI_AT_SUN_LAKE 0x0B |
| 472 | #define FI_AT_MV_9580 0x0F |
| 473 | u8 action; |
| 474 | #define FI_ACT_DOWN 0x00 |
| 475 | #define FI_ACT_UP 0x01 |
| 476 | #define FI_ACT_UPSZ 0x02 |
| 477 | #define FI_ACT_MAX 0x02 |
| 478 | #define FI_ACT_DOWN1 0x80 |
| 479 | u32 length; |
| 480 | u16 checksum; |
| 481 | u16 driver_error; |
| 482 | u16 flags; |
| 483 | #define FI_FLG_NVR_DEF 0x0001 |
| 484 | u16 num_comps; |
| 485 | #define FI_NUM_COMPS_V1 6 |
| 486 | u8 rel_version[FI_REL_VER_SZ]; |
| 487 | struct esas2r_component_header cmp_hdr[FI_NUM_COMPS_V1]; |
| 488 | u8 scratch_buf[FM_BUF_SZ]; |
| 489 | }; |
| 490 | |
| 491 | /* definitions for flash script (FS) commands */ |
| 492 | struct esas2r_ioctlfs_command { |
| 493 | u8 command; |
| 494 | #define ESAS2R_FS_CMD_ERASE 0 |
| 495 | #define ESAS2R_FS_CMD_READ 1 |
| 496 | #define ESAS2R_FS_CMD_BEGINW 2 |
| 497 | #define ESAS2R_FS_CMD_WRITE 3 |
| 498 | #define ESAS2R_FS_CMD_COMMIT 4 |
| 499 | #define ESAS2R_FS_CMD_CANCEL 5 |
| 500 | u8 checksum; |
| 501 | u8 reserved[2]; |
| 502 | u32 flash_addr; |
| 503 | u32 length; |
| 504 | u32 image_offset; |
| 505 | }; |
| 506 | |
| 507 | struct esas2r_ioctl_fs { |
| 508 | u8 version; |
| 509 | #define ESAS2R_FS_VER 0 |
| 510 | u8 status; |
| 511 | u8 driver_error; |
| 512 | u8 adap_type; |
| 513 | #define ESAS2R_FS_AT_ESASRAID2 3 |
| 514 | #define ESAS2R_FS_AT_TSSASRAID2 4 |
| 515 | #define ESAS2R_FS_AT_TSSASRAID2E 5 |
| 516 | #define ESAS2R_FS_AT_TLSASHBA 6 |
| 517 | u8 driver_ver; |
| 518 | u8 reserved[11]; |
| 519 | struct esas2r_ioctlfs_command command; |
| 520 | u8 data[1]; |
| 521 | }; |
| 522 | |
| 523 | struct esas2r_sas_nvram { |
| 524 | u8 signature[4]; |
| 525 | u8 version; |
| 526 | #define SASNVR_VERSION_0 0x00 |
| 527 | #define SASNVR_VERSION SASNVR_VERSION_0 |
| 528 | u8 checksum; |
| 529 | #define SASNVR_CKSUM_SEED 0x5A |
| 530 | u8 max_lun_for_target; |
| 531 | u8 pci_latency; |
| 532 | #define SASNVR_PCILAT_DIS 0x00 |
| 533 | #define SASNVR_PCILAT_MIN 0x10 |
| 534 | #define SASNVR_PCILAT_MAX 0xF8 |
| 535 | u8 options1; |
| 536 | #define SASNVR1_BOOT_DRVR 0x01 |
| 537 | #define SASNVR1_BOOT_SCAN 0x02 |
| 538 | #define SASNVR1_DIS_PCI_MWI 0x04 |
| 539 | #define SASNVR1_FORCE_ORD_Q 0x08 |
| 540 | #define SASNVR1_CACHELINE_0 0x10 |
| 541 | #define SASNVR1_DIS_DEVSORT 0x20 |
| 542 | #define SASNVR1_PWR_MGT_EN 0x40 |
| 543 | #define SASNVR1_WIDEPORT 0x80 |
| 544 | u8 options2; |
| 545 | #define SASNVR2_SINGLE_BUS 0x01 |
| 546 | #define SASNVR2_SLOT_BIND 0x02 |
| 547 | #define SASNVR2_EXP_PROG 0x04 |
| 548 | #define SASNVR2_CMDTHR_LUN 0x08 |
| 549 | #define SASNVR2_HEARTBEAT 0x10 |
| 550 | #define SASNVR2_INT_CONNECT 0x20 |
| 551 | #define SASNVR2_SW_MUX_CTRL 0x40 |
| 552 | #define SASNVR2_DISABLE_NCQ 0x80 |
| 553 | u8 int_coalescing; |
| 554 | #define SASNVR_COAL_DIS 0x00 |
| 555 | #define SASNVR_COAL_LOW 0x01 |
| 556 | #define SASNVR_COAL_MED 0x02 |
| 557 | #define SASNVR_COAL_HI 0x03 |
| 558 | u8 cmd_throttle; |
| 559 | #define SASNVR_CMDTHR_NONE 0x00 |
| 560 | u8 dev_wait_time; |
| 561 | u8 dev_wait_count; |
| 562 | u8 spin_up_delay; |
| 563 | #define SASNVR_SPINUP_MAX 0x14 |
| 564 | u8 ssp_align_rate; |
| 565 | u8 sas_addr[8]; |
| 566 | u8 phy_speed[16]; |
| 567 | #define SASNVR_SPEED_AUTO 0x00 |
| 568 | #define SASNVR_SPEED_1_5GB 0x01 |
| 569 | #define SASNVR_SPEED_3GB 0x02 |
| 570 | #define SASNVR_SPEED_6GB 0x03 |
| 571 | #define SASNVR_SPEED_12GB 0x04 |
| 572 | u8 phy_mux[16]; |
| 573 | #define SASNVR_MUX_DISABLED 0x00 |
| 574 | #define SASNVR_MUX_1_5GB 0x01 |
| 575 | #define SASNVR_MUX_3GB 0x02 |
| 576 | #define SASNVR_MUX_6GB 0x03 |
| 577 | u8 phy_flags[16]; |
| 578 | #define SASNVR_PHF_DISABLED 0x01 |
| 579 | #define SASNVR_PHF_RD_ONLY 0x02 |
| 580 | u8 sort_type; |
| 581 | #define SASNVR_SORT_SAS_ADDR 0x00 |
| 582 | #define SASNVR_SORT_H308_CONN 0x01 |
| 583 | #define SASNVR_SORT_PHY_ID 0x02 |
| 584 | #define SASNVR_SORT_SLOT_ID 0x03 |
| 585 | u8 dpm_reqcmd_lmt; |
| 586 | u8 dpm_stndby_time; |
| 587 | u8 dpm_active_time; |
| 588 | u8 phy_target_id[16]; |
| 589 | #define SASNVR_PTI_DISABLED 0xFF |
| 590 | u8 virt_ses_mode; |
| 591 | #define SASNVR_VSMH_DISABLED 0x00 |
| 592 | u8 read_write_mode; |
| 593 | #define SASNVR_RWM_DEFAULT 0x00 |
| 594 | u8 link_down_to; |
| 595 | u8 reserved[0xA1]; |
| 596 | }; |
| 597 | |
| 598 | typedef u32 (*PGETPHYSADDR) (struct esas2r_sg_context *sgc, u64 *addr); |
| 599 | |
| 600 | struct esas2r_sg_context { |
| 601 | struct esas2r_adapter *adapter; |
| 602 | struct esas2r_request *first_req; |
| 603 | u32 length; |
| 604 | u8 *cur_offset; |
| 605 | PGETPHYSADDR get_phys_addr; |
| 606 | union { |
| 607 | struct { |
| 608 | struct atto_vda_sge *curr; |
| 609 | struct atto_vda_sge *last; |
| 610 | struct atto_vda_sge *limit; |
| 611 | struct atto_vda_sge *chain; |
| 612 | } a64; |
| 613 | struct { |
| 614 | struct atto_physical_region_description *curr; |
| 615 | struct atto_physical_region_description *chain; |
| 616 | u32 sgl_max_cnt; |
| 617 | u32 sge_cnt; |
| 618 | } prd; |
| 619 | } sge; |
| 620 | struct scatterlist *cur_sgel; |
| 621 | u8 *exp_offset; |
| 622 | int num_sgel; |
| 623 | int sgel_count; |
| 624 | }; |
| 625 | |
| 626 | struct esas2r_target { |
| 627 | u8 flags; |
| 628 | #define TF_PASS_THRU 0x01 |
| 629 | #define TF_USED 0x02 |
| 630 | u8 new_target_state; |
| 631 | u8 target_state; |
| 632 | u8 buffered_target_state; |
| 633 | #define TS_NOT_PRESENT 0x00 |
| 634 | #define TS_PRESENT 0x05 |
| 635 | #define TS_LUN_CHANGE 0x06 |
| 636 | #define TS_INVALID 0xFF |
| 637 | u32 block_size; |
| 638 | u32 inter_block; |
| 639 | u32 inter_byte; |
| 640 | u16 virt_targ_id; |
| 641 | u16 phys_targ_id; |
| 642 | u8 identifier_len; |
| 643 | u64 sas_addr; |
| 644 | u8 identifier[60]; |
| 645 | struct atto_vda_ae_lu lu_event; |
| 646 | }; |
| 647 | |
| 648 | struct esas2r_request { |
| 649 | struct list_head comp_list; |
| 650 | struct list_head req_list; |
| 651 | union atto_vda_req *vrq; |
| 652 | struct esas2r_mem_desc *vrq_md; |
| 653 | union { |
| 654 | void *data_buf; |
| 655 | union atto_vda_rsp_data *vda_rsp_data; |
| 656 | }; |
| 657 | u8 *sense_buf; |
| 658 | struct list_head sg_table_head; |
| 659 | struct esas2r_mem_desc *sg_table; |
| 660 | u32 timeout; |
| 661 | #define RQ_TIMEOUT_S1 0xFFFFFFFF |
| 662 | #define RQ_TIMEOUT_S2 0xFFFFFFFE |
| 663 | #define RQ_MAX_TIMEOUT 0xFFFFFFFD |
| 664 | u16 target_id; |
| 665 | u8 req_type; |
| 666 | #define RT_INI_REQ 0x01 |
| 667 | #define RT_DISC_REQ 0x02 |
| 668 | u8 sense_len; |
| 669 | union atto_vda_func_rsp func_rsp; |
| 670 | RQCALLBK comp_cb; |
| 671 | RQCALLBK interrupt_cb; |
| 672 | void *interrupt_cx; |
| 673 | u8 flags; |
| 674 | #define RF_1ST_IBLK_BASE 0x04 |
| 675 | #define RF_FAILURE_OK 0x08 |
| 676 | u8 req_stat; |
| 677 | u16 vda_req_sz; |
| 678 | #define RQ_SIZE_DEFAULT 0 |
| 679 | u64 lba; |
| 680 | RQCALLBK aux_req_cb; |
| 681 | void *aux_req_cx; |
| 682 | u32 blk_len; |
| 683 | u32 max_blk_len; |
| 684 | union { |
| 685 | struct scsi_cmnd *cmd; |
| 686 | u8 *task_management_status_ptr; |
| 687 | }; |
| 688 | }; |
| 689 | |
| 690 | struct esas2r_flash_context { |
| 691 | struct esas2r_flash_img *fi; |
| 692 | RQCALLBK interrupt_cb; |
| 693 | u8 *sgc_offset; |
| 694 | u8 *scratch; |
| 695 | u32 fi_hdr_len; |
| 696 | u8 task; |
| 697 | #define FMTSK_ERASE_BOOT 0 |
| 698 | #define FMTSK_WRTBIOS 1 |
| 699 | #define FMTSK_READBIOS 2 |
| 700 | #define FMTSK_WRTMAC 3 |
| 701 | #define FMTSK_READMAC 4 |
| 702 | #define FMTSK_WRTEFI 5 |
| 703 | #define FMTSK_READEFI 6 |
| 704 | #define FMTSK_WRTCFG 7 |
| 705 | #define FMTSK_READCFG 8 |
| 706 | u8 func; |
| 707 | u16 num_comps; |
| 708 | u32 cmp_len; |
| 709 | u32 flsh_addr; |
| 710 | u32 curr_len; |
| 711 | u8 comp_typ; |
| 712 | struct esas2r_sg_context sgc; |
| 713 | }; |
| 714 | |
| 715 | struct esas2r_disc_context { |
| 716 | u8 disc_evt; |
| 717 | #define DCDE_DEV_CHANGE 0x01 |
| 718 | #define DCDE_DEV_SCAN 0x02 |
| 719 | u8 state; |
| 720 | #define DCS_DEV_RMV 0x00 |
| 721 | #define DCS_DEV_ADD 0x01 |
| 722 | #define DCS_BLOCK_DEV_SCAN 0x02 |
| 723 | #define DCS_RAID_GRP_INFO 0x03 |
| 724 | #define DCS_PART_INFO 0x04 |
| 725 | #define DCS_PT_DEV_INFO 0x05 |
| 726 | #define DCS_PT_DEV_ADDR 0x06 |
| 727 | #define DCS_DISC_DONE 0xFF |
| 728 | u16 flags; |
| 729 | #define DCF_DEV_CHANGE 0x0001 |
| 730 | #define DCF_DEV_SCAN 0x0002 |
| 731 | #define DCF_POLLED 0x8000 |
| 732 | u32 interleave; |
| 733 | u32 block_size; |
| 734 | u16 dev_ix; |
| 735 | u8 part_num; |
| 736 | u8 raid_grp_ix; |
| 737 | char raid_grp_name[16]; |
| 738 | struct esas2r_target *curr_targ; |
| 739 | u16 curr_virt_id; |
| 740 | u16 curr_phys_id; |
| 741 | u8 scan_gen; |
| 742 | u8 dev_addr_type; |
| 743 | u64 sas_addr; |
| 744 | }; |
| 745 | |
| 746 | struct esas2r_mem_desc { |
| 747 | struct list_head next_desc; |
| 748 | void *virt_addr; |
| 749 | u64 phys_addr; |
| 750 | void *pad; |
| 751 | void *esas2r_data; |
| 752 | u32 esas2r_param; |
| 753 | u32 size; |
| 754 | }; |
| 755 | |
| 756 | enum fw_event_type { |
| 757 | fw_event_null, |
| 758 | fw_event_lun_change, |
| 759 | fw_event_present, |
| 760 | fw_event_not_present, |
| 761 | fw_event_vda_ae |
| 762 | }; |
| 763 | |
| 764 | struct esas2r_vda_ae { |
| 765 | u32 signature; |
| 766 | #define ESAS2R_VDA_EVENT_SIG 0x4154544F |
| 767 | u8 bus_number; |
| 768 | u8 devfn; |
| 769 | u8 pad[2]; |
| 770 | union atto_vda_ae vda_ae; |
| 771 | }; |
| 772 | |
| 773 | struct esas2r_fw_event_work { |
| 774 | struct list_head list; |
| 775 | struct delayed_work work; |
| 776 | struct esas2r_adapter *a; |
| 777 | enum fw_event_type type; |
| 778 | u8 data[sizeof(struct esas2r_vda_ae)]; |
| 779 | }; |
| 780 | |
| 781 | enum state { |
| 782 | FW_INVALID_ST, |
| 783 | FW_STATUS_ST, |
| 784 | FW_COMMAND_ST |
| 785 | }; |
| 786 | |
| 787 | struct esas2r_firmware { |
| 788 | enum state state; |
| 789 | struct esas2r_flash_img header; |
| 790 | u8 *data; |
| 791 | u64 phys; |
| 792 | int orig_len; |
| 793 | void *header_buff; |
| 794 | u64 header_buff_phys; |
| 795 | }; |
| 796 | |
| 797 | struct esas2r_adapter { |
| 798 | struct esas2r_target targetdb[ESAS2R_MAX_TARGETS]; |
| 799 | struct esas2r_target *targetdb_end; |
| 800 | unsigned char *regs; |
| 801 | unsigned char *data_window; |
Bradley Grove | 9588d24 | 2013-10-01 14:26:01 -0400 | [diff] [blame] | 802 | long flags; |
| 803 | #define AF_PORT_CHANGE 0 |
| 804 | #define AF_CHPRST_NEEDED 1 |
| 805 | #define AF_CHPRST_PENDING 2 |
| 806 | #define AF_CHPRST_DETECTED 3 |
| 807 | #define AF_BUSRST_NEEDED 4 |
| 808 | #define AF_BUSRST_PENDING 5 |
| 809 | #define AF_BUSRST_DETECTED 6 |
| 810 | #define AF_DISABLED 7 |
| 811 | #define AF_FLASH_LOCK 8 |
| 812 | #define AF_OS_RESET 9 |
| 813 | #define AF_FLASHING 10 |
| 814 | #define AF_POWER_MGT 11 |
| 815 | #define AF_NVR_VALID 12 |
| 816 | #define AF_DEGRADED_MODE 13 |
| 817 | #define AF_DISC_PENDING 14 |
| 818 | #define AF_TASKLET_SCHEDULED 15 |
| 819 | #define AF_HEARTBEAT 16 |
| 820 | #define AF_HEARTBEAT_ENB 17 |
| 821 | #define AF_NOT_PRESENT 18 |
| 822 | #define AF_CHPRST_STARTED 19 |
| 823 | #define AF_FIRST_INIT 20 |
| 824 | #define AF_POWER_DOWN 21 |
| 825 | #define AF_DISC_IN_PROG 22 |
| 826 | #define AF_COMM_LIST_TOGGLE 23 |
| 827 | #define AF_LEGACY_SGE_MODE 24 |
| 828 | #define AF_DISC_POLLED 25 |
| 829 | long flags2; |
| 830 | #define AF2_SERIAL_FLASH 0 |
| 831 | #define AF2_DEV_SCAN 1 |
| 832 | #define AF2_DEV_CNT_OK 2 |
| 833 | #define AF2_COREDUMP_AVAIL 3 |
| 834 | #define AF2_COREDUMP_SAVED 4 |
| 835 | #define AF2_VDA_POWER_DOWN 5 |
| 836 | #define AF2_THUNDERLINK 6 |
| 837 | #define AF2_THUNDERBOLT 7 |
| 838 | #define AF2_INIT_DONE 8 |
| 839 | #define AF2_INT_PENDING 9 |
| 840 | #define AF2_TIMER_TICK 10 |
| 841 | #define AF2_IRQ_CLAIMED 11 |
| 842 | #define AF2_MSI_ENABLED 12 |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 843 | atomic_t disable_cnt; |
| 844 | atomic_t dis_ints_cnt; |
| 845 | u32 int_stat; |
| 846 | u32 int_mask; |
| 847 | u32 volatile *outbound_copy; |
| 848 | struct list_head avail_request; |
| 849 | spinlock_t request_lock; |
| 850 | spinlock_t sg_list_lock; |
| 851 | spinlock_t queue_lock; |
| 852 | spinlock_t mem_lock; |
| 853 | struct list_head free_sg_list_head; |
| 854 | struct esas2r_mem_desc *sg_list_mds; |
| 855 | struct list_head active_list; |
| 856 | struct list_head defer_list; |
| 857 | struct esas2r_request **req_table; |
| 858 | union { |
| 859 | u16 prev_dev_cnt; |
| 860 | u32 heartbeat_time; |
| 861 | #define ESAS2R_HEARTBEAT_TIME (3000) |
| 862 | }; |
| 863 | u32 chip_uptime; |
| 864 | #define ESAS2R_CHP_UPTIME_MAX (60000) |
| 865 | #define ESAS2R_CHP_UPTIME_CNT (20000) |
| 866 | u64 uncached_phys; |
| 867 | u8 *uncached; |
| 868 | struct esas2r_sas_nvram *nvram; |
| 869 | struct esas2r_request general_req; |
| 870 | u8 init_msg; |
| 871 | #define ESAS2R_INIT_MSG_START 1 |
| 872 | #define ESAS2R_INIT_MSG_INIT 2 |
| 873 | #define ESAS2R_INIT_MSG_GET_INIT 3 |
| 874 | #define ESAS2R_INIT_MSG_REINIT 4 |
| 875 | u16 cmd_ref_no; |
| 876 | u32 fw_version; |
| 877 | u32 fw_build; |
| 878 | u32 chip_init_time; |
| 879 | #define ESAS2R_CHPRST_TIME (180000) |
| 880 | #define ESAS2R_CHPRST_WAIT_TIME (2000) |
| 881 | u32 last_tick_time; |
| 882 | u32 window_base; |
| 883 | RQBUILDSGL build_sgl; |
| 884 | struct esas2r_request *first_ae_req; |
| 885 | u32 list_size; |
| 886 | u32 last_write; |
| 887 | u32 last_read; |
| 888 | u16 max_vdareq_size; |
| 889 | u16 disc_wait_cnt; |
| 890 | struct esas2r_mem_desc inbound_list_md; |
| 891 | struct esas2r_mem_desc outbound_list_md; |
| 892 | struct esas2r_disc_context disc_ctx; |
| 893 | u8 *disc_buffer; |
| 894 | u32 disc_start_time; |
| 895 | u32 disc_wait_time; |
| 896 | u32 flash_ver; |
| 897 | char flash_rev[16]; |
| 898 | char fw_rev[16]; |
| 899 | char image_type[16]; |
| 900 | struct esas2r_flash_context flash_context; |
| 901 | u32 num_targets_backend; |
| 902 | u32 ioctl_tunnel; |
| 903 | struct tasklet_struct tasklet; |
| 904 | struct pci_dev *pcid; |
| 905 | struct Scsi_Host *host; |
| 906 | unsigned int index; |
| 907 | char name[32]; |
| 908 | struct timer_list timer; |
| 909 | struct esas2r_firmware firmware; |
| 910 | wait_queue_head_t nvram_waiter; |
| 911 | int nvram_command_done; |
| 912 | wait_queue_head_t fm_api_waiter; |
| 913 | int fm_api_command_done; |
| 914 | wait_queue_head_t vda_waiter; |
| 915 | int vda_command_done; |
| 916 | u8 *vda_buffer; |
| 917 | u64 ppvda_buffer; |
| 918 | #define VDA_BUFFER_HEADER_SZ (offsetof(struct atto_ioctl_vda, data)) |
| 919 | #define VDA_MAX_BUFFER_SIZE (0x40000 + VDA_BUFFER_HEADER_SZ) |
| 920 | wait_queue_head_t fs_api_waiter; |
| 921 | int fs_api_command_done; |
| 922 | u64 ppfs_api_buffer; |
| 923 | u8 *fs_api_buffer; |
| 924 | u32 fs_api_buffer_size; |
| 925 | wait_queue_head_t buffered_ioctl_waiter; |
| 926 | int buffered_ioctl_done; |
| 927 | int uncached_size; |
| 928 | struct workqueue_struct *fw_event_q; |
| 929 | struct list_head fw_event_list; |
| 930 | spinlock_t fw_event_lock; |
| 931 | u8 fw_events_off; /* if '1', then ignore events */ |
| 932 | char fw_event_q_name[ESAS2R_KOBJ_NAME_LEN]; |
| 933 | /* |
| 934 | * intr_mode stores the interrupt mode currently being used by this |
| 935 | * adapter. it is based on the interrupt_mode module parameter, but |
| 936 | * can be changed based on the ability (or not) to utilize the |
| 937 | * mode requested by the parameter. |
| 938 | */ |
| 939 | int intr_mode; |
| 940 | #define INTR_MODE_LEGACY 0 |
| 941 | #define INTR_MODE_MSI 1 |
| 942 | #define INTR_MODE_MSIX 2 |
| 943 | struct esas2r_sg_context fm_api_sgc; |
| 944 | u8 *save_offset; |
| 945 | struct list_head vrq_mds_head; |
| 946 | struct esas2r_mem_desc *vrq_mds; |
| 947 | int num_vrqs; |
| 948 | struct semaphore fm_api_semaphore; |
| 949 | struct semaphore fs_api_semaphore; |
| 950 | struct semaphore nvram_semaphore; |
| 951 | struct atto_ioctl *local_atto_ioctl; |
| 952 | u8 fw_coredump_buff[ESAS2R_FWCOREDUMP_SZ]; |
| 953 | unsigned int sysfs_fw_created:1; |
| 954 | unsigned int sysfs_fs_created:1; |
| 955 | unsigned int sysfs_vda_created:1; |
| 956 | unsigned int sysfs_hw_created:1; |
| 957 | unsigned int sysfs_live_nvram_created:1; |
| 958 | unsigned int sysfs_default_nvram_created:1; |
| 959 | }; |
| 960 | |
| 961 | /* |
| 962 | * Function Declarations |
| 963 | * SCSI functions |
| 964 | */ |
| 965 | int esas2r_release(struct Scsi_Host *); |
| 966 | const char *esas2r_info(struct Scsi_Host *); |
| 967 | int esas2r_write_params(struct esas2r_adapter *a, struct esas2r_request *rq, |
| 968 | struct esas2r_sas_nvram *data); |
| 969 | int esas2r_ioctl_handler(void *hostdata, int cmd, void __user *arg); |
| 970 | int esas2r_ioctl(struct scsi_device *dev, int cmd, void __user *arg); |
| 971 | u8 handle_hba_ioctl(struct esas2r_adapter *a, |
| 972 | struct atto_ioctl *ioctl_hba); |
| 973 | int esas2r_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd); |
| 974 | int esas2r_show_info(struct seq_file *m, struct Scsi_Host *sh); |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 975 | int esas2r_change_queue_depth(struct scsi_device *dev, int depth, int reason); |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 976 | long esas2r_proc_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); |
| 977 | |
| 978 | /* SCSI error handler (eh) functions */ |
| 979 | int esas2r_eh_abort(struct scsi_cmnd *cmd); |
| 980 | int esas2r_device_reset(struct scsi_cmnd *cmd); |
| 981 | int esas2r_host_reset(struct scsi_cmnd *cmd); |
| 982 | int esas2r_bus_reset(struct scsi_cmnd *cmd); |
| 983 | int esas2r_target_reset(struct scsi_cmnd *cmd); |
| 984 | |
| 985 | /* Internal functions */ |
| 986 | int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid, |
| 987 | int index); |
| 988 | int esas2r_cleanup(struct Scsi_Host *host); |
| 989 | int esas2r_read_fw(struct esas2r_adapter *a, char *buf, long off, int count); |
| 990 | int esas2r_write_fw(struct esas2r_adapter *a, const char *buf, long off, |
| 991 | int count); |
| 992 | int esas2r_read_vda(struct esas2r_adapter *a, char *buf, long off, int count); |
| 993 | int esas2r_write_vda(struct esas2r_adapter *a, const char *buf, long off, |
| 994 | int count); |
| 995 | int esas2r_read_fs(struct esas2r_adapter *a, char *buf, long off, int count); |
| 996 | int esas2r_write_fs(struct esas2r_adapter *a, const char *buf, long off, |
| 997 | int count); |
| 998 | void esas2r_adapter_tasklet(unsigned long context); |
| 999 | irqreturn_t esas2r_interrupt(int irq, void *dev_id); |
| 1000 | irqreturn_t esas2r_msi_interrupt(int irq, void *dev_id); |
| 1001 | void esas2r_kickoff_timer(struct esas2r_adapter *a); |
| 1002 | int esas2r_suspend(struct pci_dev *pcid, pm_message_t state); |
| 1003 | int esas2r_resume(struct pci_dev *pcid); |
| 1004 | void esas2r_fw_event_off(struct esas2r_adapter *a); |
| 1005 | void esas2r_fw_event_on(struct esas2r_adapter *a); |
| 1006 | bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq, |
| 1007 | struct esas2r_sas_nvram *nvram); |
| 1008 | void esas2r_nvram_get_defaults(struct esas2r_adapter *a, |
| 1009 | struct esas2r_sas_nvram *nvram); |
| 1010 | void esas2r_complete_request_cb(struct esas2r_adapter *a, |
| 1011 | struct esas2r_request *rq); |
| 1012 | void esas2r_reset_detected(struct esas2r_adapter *a); |
| 1013 | void esas2r_target_state_changed(struct esas2r_adapter *ha, u16 targ_id, |
| 1014 | u8 state); |
| 1015 | int esas2r_req_status_to_error(u8 req_stat); |
| 1016 | void esas2r_kill_adapter(int i); |
| 1017 | void esas2r_free_request(struct esas2r_adapter *a, struct esas2r_request *rq); |
| 1018 | struct esas2r_request *esas2r_alloc_request(struct esas2r_adapter *a); |
| 1019 | u32 esas2r_get_uncached_size(struct esas2r_adapter *a); |
| 1020 | bool esas2r_init_adapter_struct(struct esas2r_adapter *a, |
| 1021 | void **uncached_area); |
| 1022 | bool esas2r_check_adapter(struct esas2r_adapter *a); |
| 1023 | bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll); |
| 1024 | void esas2r_start_request(struct esas2r_adapter *a, struct esas2r_request *rq); |
| 1025 | bool esas2r_send_task_mgmt(struct esas2r_adapter *a, |
| 1026 | struct esas2r_request *rqaux, u8 task_mgt_func); |
| 1027 | void esas2r_do_tasklet_tasks(struct esas2r_adapter *a); |
| 1028 | void esas2r_adapter_interrupt(struct esas2r_adapter *a); |
| 1029 | void esas2r_do_deferred_processes(struct esas2r_adapter *a); |
| 1030 | void esas2r_reset_bus(struct esas2r_adapter *a); |
| 1031 | void esas2r_reset_adapter(struct esas2r_adapter *a); |
| 1032 | void esas2r_timer_tick(struct esas2r_adapter *a); |
| 1033 | const char *esas2r_get_model_name(struct esas2r_adapter *a); |
| 1034 | const char *esas2r_get_model_name_short(struct esas2r_adapter *a); |
| 1035 | u32 esas2r_stall_execution(struct esas2r_adapter *a, u32 start_time, |
| 1036 | u32 *delay); |
| 1037 | void esas2r_build_flash_req(struct esas2r_adapter *a, |
| 1038 | struct esas2r_request *rq, |
| 1039 | u8 sub_func, |
| 1040 | u8 cksum, |
| 1041 | u32 addr, |
| 1042 | u32 length); |
| 1043 | void esas2r_build_mgt_req(struct esas2r_adapter *a, |
| 1044 | struct esas2r_request *rq, |
| 1045 | u8 sub_func, |
| 1046 | u8 scan_gen, |
| 1047 | u16 dev_index, |
| 1048 | u32 length, |
| 1049 | void *data); |
| 1050 | void esas2r_build_ae_req(struct esas2r_adapter *a, struct esas2r_request *rq); |
| 1051 | void esas2r_build_cli_req(struct esas2r_adapter *a, |
| 1052 | struct esas2r_request *rq, |
| 1053 | u32 length, |
| 1054 | u32 cmd_rsp_len); |
| 1055 | void esas2r_build_ioctl_req(struct esas2r_adapter *a, |
| 1056 | struct esas2r_request *rq, |
| 1057 | u32 length, |
| 1058 | u8 sub_func); |
| 1059 | void esas2r_build_cfg_req(struct esas2r_adapter *a, |
| 1060 | struct esas2r_request *rq, |
| 1061 | u8 sub_func, |
| 1062 | u32 length, |
| 1063 | void *data); |
| 1064 | void esas2r_power_down(struct esas2r_adapter *a); |
| 1065 | bool esas2r_power_up(struct esas2r_adapter *a, bool init_poll); |
| 1066 | void esas2r_wait_request(struct esas2r_adapter *a, struct esas2r_request *rq); |
| 1067 | u32 esas2r_map_data_window(struct esas2r_adapter *a, u32 addr_lo); |
| 1068 | bool esas2r_process_fs_ioctl(struct esas2r_adapter *a, |
| 1069 | struct esas2r_ioctl_fs *fs, |
| 1070 | struct esas2r_request *rq, |
| 1071 | struct esas2r_sg_context *sgc); |
| 1072 | bool esas2r_read_flash_block(struct esas2r_adapter *a, void *to, u32 from, |
| 1073 | u32 size); |
| 1074 | bool esas2r_read_mem_block(struct esas2r_adapter *a, void *to, u32 from, |
| 1075 | u32 size); |
| 1076 | bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi, |
| 1077 | struct esas2r_request *rq, struct esas2r_sg_context *sgc); |
| 1078 | void esas2r_force_interrupt(struct esas2r_adapter *a); |
| 1079 | void esas2r_local_start_request(struct esas2r_adapter *a, |
| 1080 | struct esas2r_request *rq); |
| 1081 | void esas2r_process_adapter_reset(struct esas2r_adapter *a); |
| 1082 | void esas2r_complete_request(struct esas2r_adapter *a, |
| 1083 | struct esas2r_request *rq); |
| 1084 | void esas2r_dummy_complete(struct esas2r_adapter *a, |
| 1085 | struct esas2r_request *rq); |
| 1086 | void esas2r_ae_complete(struct esas2r_adapter *a, struct esas2r_request *rq); |
| 1087 | void esas2r_start_vda_request(struct esas2r_adapter *a, |
| 1088 | struct esas2r_request *rq); |
| 1089 | bool esas2r_read_flash_rev(struct esas2r_adapter *a); |
| 1090 | bool esas2r_read_image_type(struct esas2r_adapter *a); |
| 1091 | bool esas2r_nvram_read_direct(struct esas2r_adapter *a); |
| 1092 | bool esas2r_nvram_validate(struct esas2r_adapter *a); |
| 1093 | void esas2r_nvram_set_defaults(struct esas2r_adapter *a); |
| 1094 | bool esas2r_print_flash_rev(struct esas2r_adapter *a); |
| 1095 | void esas2r_send_reset_ae(struct esas2r_adapter *a, bool pwr_mgt); |
| 1096 | bool esas2r_init_msgs(struct esas2r_adapter *a); |
| 1097 | bool esas2r_is_adapter_present(struct esas2r_adapter *a); |
| 1098 | void esas2r_nuxi_mgt_data(u8 function, void *data); |
| 1099 | void esas2r_nuxi_cfg_data(u8 function, void *data); |
| 1100 | void esas2r_nuxi_ae_data(union atto_vda_ae *ae); |
| 1101 | void esas2r_reset_chip(struct esas2r_adapter *a); |
| 1102 | void esas2r_log_request_failure(struct esas2r_adapter *a, |
| 1103 | struct esas2r_request *rq); |
| 1104 | void esas2r_polled_interrupt(struct esas2r_adapter *a); |
| 1105 | bool esas2r_ioreq_aborted(struct esas2r_adapter *a, struct esas2r_request *rq, |
| 1106 | u8 status); |
| 1107 | bool esas2r_build_sg_list_sge(struct esas2r_adapter *a, |
| 1108 | struct esas2r_sg_context *sgc); |
| 1109 | bool esas2r_build_sg_list_prd(struct esas2r_adapter *a, |
| 1110 | struct esas2r_sg_context *sgc); |
| 1111 | void esas2r_targ_db_initialize(struct esas2r_adapter *a); |
| 1112 | void esas2r_targ_db_remove_all(struct esas2r_adapter *a, bool notify); |
| 1113 | void esas2r_targ_db_report_changes(struct esas2r_adapter *a); |
| 1114 | struct esas2r_target *esas2r_targ_db_add_raid(struct esas2r_adapter *a, |
| 1115 | struct esas2r_disc_context *dc); |
| 1116 | struct esas2r_target *esas2r_targ_db_add_pthru(struct esas2r_adapter *a, |
| 1117 | struct esas2r_disc_context *dc, |
| 1118 | u8 *ident, |
| 1119 | u8 ident_len); |
| 1120 | void esas2r_targ_db_remove(struct esas2r_adapter *a, struct esas2r_target *t); |
| 1121 | struct esas2r_target *esas2r_targ_db_find_by_sas_addr(struct esas2r_adapter *a, |
| 1122 | u64 *sas_addr); |
| 1123 | struct esas2r_target *esas2r_targ_db_find_by_ident(struct esas2r_adapter *a, |
| 1124 | void *identifier, |
| 1125 | u8 ident_len); |
| 1126 | u16 esas2r_targ_db_find_next_present(struct esas2r_adapter *a, u16 target_id); |
| 1127 | struct esas2r_target *esas2r_targ_db_find_by_virt_id(struct esas2r_adapter *a, |
| 1128 | u16 virt_id); |
| 1129 | u16 esas2r_targ_db_get_tgt_cnt(struct esas2r_adapter *a); |
| 1130 | void esas2r_disc_initialize(struct esas2r_adapter *a); |
| 1131 | void esas2r_disc_start_waiting(struct esas2r_adapter *a); |
| 1132 | void esas2r_disc_check_for_work(struct esas2r_adapter *a); |
| 1133 | void esas2r_disc_check_complete(struct esas2r_adapter *a); |
| 1134 | void esas2r_disc_queue_event(struct esas2r_adapter *a, u8 disc_evt); |
| 1135 | bool esas2r_disc_start_port(struct esas2r_adapter *a); |
| 1136 | void esas2r_disc_local_start_request(struct esas2r_adapter *a, |
| 1137 | struct esas2r_request *rq); |
| 1138 | bool esas2r_set_degraded_mode(struct esas2r_adapter *a, char *error_str); |
| 1139 | bool esas2r_process_vda_ioctl(struct esas2r_adapter *a, |
| 1140 | struct atto_ioctl_vda *vi, |
| 1141 | struct esas2r_request *rq, |
| 1142 | struct esas2r_sg_context *sgc); |
| 1143 | void esas2r_queue_fw_event(struct esas2r_adapter *a, |
| 1144 | enum fw_event_type type, |
| 1145 | void *data, |
| 1146 | int data_sz); |
| 1147 | |
| 1148 | /* Inline functions */ |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1149 | |
| 1150 | /* Allocate a chip scatter/gather list entry */ |
| 1151 | static inline struct esas2r_mem_desc *esas2r_alloc_sgl(struct esas2r_adapter *a) |
| 1152 | { |
| 1153 | unsigned long flags; |
| 1154 | struct list_head *sgl; |
| 1155 | struct esas2r_mem_desc *result = NULL; |
| 1156 | |
| 1157 | spin_lock_irqsave(&a->sg_list_lock, flags); |
| 1158 | if (likely(!list_empty(&a->free_sg_list_head))) { |
| 1159 | sgl = a->free_sg_list_head.next; |
| 1160 | result = list_entry(sgl, struct esas2r_mem_desc, next_desc); |
| 1161 | list_del_init(sgl); |
| 1162 | } |
| 1163 | spin_unlock_irqrestore(&a->sg_list_lock, flags); |
| 1164 | |
| 1165 | return result; |
| 1166 | } |
| 1167 | |
| 1168 | /* Initialize a scatter/gather context */ |
| 1169 | static inline void esas2r_sgc_init(struct esas2r_sg_context *sgc, |
| 1170 | struct esas2r_adapter *a, |
| 1171 | struct esas2r_request *rq, |
| 1172 | struct atto_vda_sge *first) |
| 1173 | { |
| 1174 | sgc->adapter = a; |
| 1175 | sgc->first_req = rq; |
| 1176 | |
| 1177 | /* |
| 1178 | * set the limit pointer such that an SGE pointer above this value |
| 1179 | * would be the first one to overflow the SGL. |
| 1180 | */ |
| 1181 | sgc->sge.a64.limit = (struct atto_vda_sge *)((u8 *)rq->vrq |
| 1182 | + (sizeof(union |
| 1183 | atto_vda_req) / |
| 1184 | 8) |
| 1185 | - sizeof(struct |
| 1186 | atto_vda_sge)); |
| 1187 | if (first) { |
| 1188 | sgc->sge.a64.last = |
| 1189 | sgc->sge.a64.curr = first; |
| 1190 | rq->vrq->scsi.sg_list_offset = (u8) |
| 1191 | ((u8 *)first - |
| 1192 | (u8 *)rq->vrq); |
| 1193 | } else { |
| 1194 | sgc->sge.a64.last = |
| 1195 | sgc->sge.a64.curr = &rq->vrq->scsi.u.sge[0]; |
| 1196 | rq->vrq->scsi.sg_list_offset = |
| 1197 | (u8)offsetof(struct atto_vda_scsi_req, u.sge); |
| 1198 | } |
| 1199 | sgc->sge.a64.chain = NULL; |
| 1200 | } |
| 1201 | |
| 1202 | static inline void esas2r_rq_init_request(struct esas2r_request *rq, |
| 1203 | struct esas2r_adapter *a) |
| 1204 | { |
| 1205 | union atto_vda_req *vrq = rq->vrq; |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1206 | |
| 1207 | INIT_LIST_HEAD(&rq->sg_table_head); |
| 1208 | rq->data_buf = (void *)(vrq + 1); |
| 1209 | rq->interrupt_cb = NULL; |
| 1210 | rq->comp_cb = esas2r_complete_request_cb; |
| 1211 | rq->flags = 0; |
| 1212 | rq->timeout = 0; |
| 1213 | rq->req_stat = RS_PENDING; |
| 1214 | rq->req_type = RT_INI_REQ; |
| 1215 | |
| 1216 | /* clear the outbound response */ |
| 1217 | rq->func_rsp.dwords[0] = 0; |
| 1218 | rq->func_rsp.dwords[1] = 0; |
| 1219 | |
| 1220 | /* |
| 1221 | * clear the size of the VDA request. esas2r_build_sg_list() will |
| 1222 | * only allow the size of the request to grow. there are some |
| 1223 | * management requests that go through there twice and the second |
| 1224 | * time through sets a smaller request size. if this is not modified |
| 1225 | * at all we'll set it to the size of the entire VDA request. |
| 1226 | */ |
| 1227 | rq->vda_req_sz = RQ_SIZE_DEFAULT; |
| 1228 | |
| 1229 | /* req_table entry should be NULL at this point - if not, halt */ |
| 1230 | |
| 1231 | if (a->req_table[LOWORD(vrq->scsi.handle)]) |
| 1232 | esas2r_bugon(); |
| 1233 | |
| 1234 | /* fill in the table for this handle so we can get back to the |
| 1235 | * request. |
| 1236 | */ |
| 1237 | a->req_table[LOWORD(vrq->scsi.handle)] = rq; |
| 1238 | |
| 1239 | /* |
| 1240 | * add a reference number to the handle to make it unique (until it |
Bradley Grove | 8e65e2f | 2013-10-01 14:26:02 -0400 | [diff] [blame] | 1241 | * wraps of course) while preserving the least significant word |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1242 | */ |
Bradley Grove | 8e65e2f | 2013-10-01 14:26:02 -0400 | [diff] [blame] | 1243 | vrq->scsi.handle = (a->cmd_ref_no++ << 16) | (u16)vrq->scsi.handle; |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1244 | |
| 1245 | /* |
| 1246 | * the following formats a SCSI request. the caller can override as |
| 1247 | * necessary. clear_vda_request can be called to clear the VDA |
| 1248 | * request for another type of request. |
| 1249 | */ |
| 1250 | vrq->scsi.function = VDA_FUNC_SCSI; |
| 1251 | vrq->scsi.sense_len = SENSE_DATA_SZ; |
| 1252 | |
| 1253 | /* clear out sg_list_offset and chain_offset */ |
| 1254 | vrq->scsi.sg_list_offset = 0; |
| 1255 | vrq->scsi.chain_offset = 0; |
| 1256 | vrq->scsi.flags = 0; |
| 1257 | vrq->scsi.reserved = 0; |
| 1258 | |
| 1259 | /* set the sense buffer to be the data payload buffer */ |
| 1260 | vrq->scsi.ppsense_buf |
| 1261 | = cpu_to_le64(rq->vrq_md->phys_addr + |
| 1262 | sizeof(union atto_vda_req)); |
| 1263 | } |
| 1264 | |
| 1265 | static inline void esas2r_rq_free_sg_lists(struct esas2r_request *rq, |
| 1266 | struct esas2r_adapter *a) |
| 1267 | { |
| 1268 | unsigned long flags; |
| 1269 | |
| 1270 | if (list_empty(&rq->sg_table_head)) |
| 1271 | return; |
| 1272 | |
| 1273 | spin_lock_irqsave(&a->sg_list_lock, flags); |
| 1274 | list_splice_tail_init(&rq->sg_table_head, &a->free_sg_list_head); |
| 1275 | spin_unlock_irqrestore(&a->sg_list_lock, flags); |
| 1276 | } |
| 1277 | |
| 1278 | static inline void esas2r_rq_destroy_request(struct esas2r_request *rq, |
| 1279 | struct esas2r_adapter *a) |
| 1280 | |
| 1281 | { |
| 1282 | esas2r_rq_free_sg_lists(rq, a); |
| 1283 | a->req_table[LOWORD(rq->vrq->scsi.handle)] = NULL; |
| 1284 | rq->data_buf = NULL; |
| 1285 | } |
| 1286 | |
| 1287 | static inline bool esas2r_is_tasklet_pending(struct esas2r_adapter *a) |
| 1288 | { |
Bradley Grove | 9588d24 | 2013-10-01 14:26:01 -0400 | [diff] [blame] | 1289 | |
| 1290 | return test_bit(AF_BUSRST_NEEDED, &a->flags) || |
| 1291 | test_bit(AF_BUSRST_DETECTED, &a->flags) || |
| 1292 | test_bit(AF_CHPRST_NEEDED, &a->flags) || |
| 1293 | test_bit(AF_CHPRST_DETECTED, &a->flags) || |
| 1294 | test_bit(AF_PORT_CHANGE, &a->flags); |
| 1295 | |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1296 | } |
| 1297 | |
| 1298 | /* |
| 1299 | * Build the scatter/gather list for an I/O request according to the |
| 1300 | * specifications placed in the esas2r_sg_context. The caller must initialize |
| 1301 | * struct esas2r_sg_context prior to the initial call by calling |
| 1302 | * esas2r_sgc_init() |
| 1303 | */ |
| 1304 | static inline bool esas2r_build_sg_list(struct esas2r_adapter *a, |
| 1305 | struct esas2r_request *rq, |
| 1306 | struct esas2r_sg_context *sgc) |
| 1307 | { |
| 1308 | if (unlikely(le32_to_cpu(rq->vrq->scsi.length) == 0)) |
| 1309 | return true; |
| 1310 | |
| 1311 | return (*a->build_sgl)(a, sgc); |
| 1312 | } |
| 1313 | |
| 1314 | static inline void esas2r_disable_chip_interrupts(struct esas2r_adapter *a) |
| 1315 | { |
| 1316 | if (atomic_inc_return(&a->dis_ints_cnt) == 1) |
| 1317 | esas2r_write_register_dword(a, MU_INT_MASK_OUT, |
| 1318 | ESAS2R_INT_DIS_MASK); |
| 1319 | } |
| 1320 | |
| 1321 | static inline void esas2r_enable_chip_interrupts(struct esas2r_adapter *a) |
| 1322 | { |
| 1323 | if (atomic_dec_return(&a->dis_ints_cnt) == 0) |
| 1324 | esas2r_write_register_dword(a, MU_INT_MASK_OUT, |
| 1325 | ESAS2R_INT_ENB_MASK); |
| 1326 | } |
| 1327 | |
| 1328 | /* Schedule a TASKLET to perform non-interrupt tasks that may require delays |
| 1329 | * or long completion times. |
| 1330 | */ |
| 1331 | static inline void esas2r_schedule_tasklet(struct esas2r_adapter *a) |
| 1332 | { |
| 1333 | /* make sure we don't schedule twice */ |
Bradley Grove | 9588d24 | 2013-10-01 14:26:01 -0400 | [diff] [blame] | 1334 | if (!test_and_set_bit(AF_TASKLET_SCHEDULED, &a->flags)) |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1335 | tasklet_hi_schedule(&a->tasklet); |
| 1336 | } |
| 1337 | |
| 1338 | static inline void esas2r_enable_heartbeat(struct esas2r_adapter *a) |
| 1339 | { |
Bradley Grove | 9588d24 | 2013-10-01 14:26:01 -0400 | [diff] [blame] | 1340 | if (!test_bit(AF_DEGRADED_MODE, &a->flags) && |
| 1341 | !test_bit(AF_CHPRST_PENDING, &a->flags) && |
| 1342 | (a->nvram->options2 & SASNVR2_HEARTBEAT)) |
| 1343 | set_bit(AF_HEARTBEAT_ENB, &a->flags); |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1344 | else |
Bradley Grove | 9588d24 | 2013-10-01 14:26:01 -0400 | [diff] [blame] | 1345 | clear_bit(AF_HEARTBEAT_ENB, &a->flags); |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1346 | } |
| 1347 | |
| 1348 | static inline void esas2r_disable_heartbeat(struct esas2r_adapter *a) |
| 1349 | { |
Bradley Grove | 9588d24 | 2013-10-01 14:26:01 -0400 | [diff] [blame] | 1350 | clear_bit(AF_HEARTBEAT_ENB, &a->flags); |
| 1351 | clear_bit(AF_HEARTBEAT, &a->flags); |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1352 | } |
| 1353 | |
| 1354 | /* Set the initial state for resetting the adapter on the next pass through |
| 1355 | * esas2r_do_deferred. |
| 1356 | */ |
| 1357 | static inline void esas2r_local_reset_adapter(struct esas2r_adapter *a) |
| 1358 | { |
| 1359 | esas2r_disable_heartbeat(a); |
| 1360 | |
Bradley Grove | 9588d24 | 2013-10-01 14:26:01 -0400 | [diff] [blame] | 1361 | set_bit(AF_CHPRST_NEEDED, &a->flags); |
| 1362 | set_bit(AF_CHPRST_PENDING, &a->flags); |
| 1363 | set_bit(AF_DISC_PENDING, &a->flags); |
Bradley Grove | 26780d9 | 2013-08-23 10:35:45 -0400 | [diff] [blame] | 1364 | } |
| 1365 | |
| 1366 | /* See if an interrupt is pending on the adapter. */ |
| 1367 | static inline bool esas2r_adapter_interrupt_pending(struct esas2r_adapter *a) |
| 1368 | { |
| 1369 | u32 intstat; |
| 1370 | |
| 1371 | if (a->int_mask == 0) |
| 1372 | return false; |
| 1373 | |
| 1374 | intstat = esas2r_read_register_dword(a, MU_INT_STATUS_OUT); |
| 1375 | |
| 1376 | if ((intstat & a->int_mask) == 0) |
| 1377 | return false; |
| 1378 | |
| 1379 | esas2r_disable_chip_interrupts(a); |
| 1380 | |
| 1381 | a->int_stat = intstat; |
| 1382 | a->int_mask = 0; |
| 1383 | |
| 1384 | return true; |
| 1385 | } |
| 1386 | |
| 1387 | static inline u16 esas2r_targ_get_id(struct esas2r_target *t, |
| 1388 | struct esas2r_adapter *a) |
| 1389 | { |
| 1390 | return (u16)(uintptr_t)(t - a->targetdb); |
| 1391 | } |
| 1392 | |
| 1393 | /* Build and start an asynchronous event request */ |
| 1394 | static inline void esas2r_start_ae_request(struct esas2r_adapter *a, |
| 1395 | struct esas2r_request *rq) |
| 1396 | { |
| 1397 | unsigned long flags; |
| 1398 | |
| 1399 | esas2r_build_ae_req(a, rq); |
| 1400 | |
| 1401 | spin_lock_irqsave(&a->queue_lock, flags); |
| 1402 | esas2r_start_vda_request(a, rq); |
| 1403 | spin_unlock_irqrestore(&a->queue_lock, flags); |
| 1404 | } |
| 1405 | |
| 1406 | static inline void esas2r_comp_list_drain(struct esas2r_adapter *a, |
| 1407 | struct list_head *comp_list) |
| 1408 | { |
| 1409 | struct esas2r_request *rq; |
| 1410 | struct list_head *element, *next; |
| 1411 | |
| 1412 | list_for_each_safe(element, next, comp_list) { |
| 1413 | rq = list_entry(element, struct esas2r_request, comp_list); |
| 1414 | list_del_init(element); |
| 1415 | esas2r_complete_request(a, rq); |
| 1416 | } |
| 1417 | } |
| 1418 | |
| 1419 | /* sysfs handlers */ |
| 1420 | extern struct bin_attribute bin_attr_fw; |
| 1421 | extern struct bin_attribute bin_attr_fs; |
| 1422 | extern struct bin_attribute bin_attr_vda; |
| 1423 | extern struct bin_attribute bin_attr_hw; |
| 1424 | extern struct bin_attribute bin_attr_live_nvram; |
| 1425 | extern struct bin_attribute bin_attr_default_nvram; |
| 1426 | |
| 1427 | #endif /* ESAS2R_H */ |