diff options
Diffstat (limited to 'drivers/scsi/hpsa.h')
-rw-r--r-- | drivers/scsi/hpsa.h | 171 |
1 files changed, 170 insertions, 1 deletions
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 01c328349c83..44235a27e1b6 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -1,6 +1,6 @@ /* * Disk Array driver for HP Smart Array SAS controllers - * Copyright 2000, 2009 Hewlett-Packard Development Company, L.P. + * Copyright 2000, 2014 Hewlett-Packard Development Company, L.P. * * 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 @@ -46,6 +46,15 @@ struct hpsa_scsi_dev_t { unsigned char vendor[8]; /* bytes 8-15 of inquiry data */ unsigned char model[16]; /* bytes 16-31 of inquiry data */ unsigned char raid_level; /* from inquiry page 0xC1 */ + unsigned char volume_offline; /* discovered via TUR or VPD */ + u32 ioaccel_handle; + int offload_config; /* I/O accel RAID offload configured */ + int offload_enabled; /* I/O accel RAID offload enabled */ + int offload_to_mirror; /* Send next I/O accelerator RAID + * offload request to mirror drive + */ + struct raid_map_data raid_map; /* I/O accelerator RAID map */ + }; struct reply_pool { @@ -55,6 +64,46 @@ struct reply_pool { u32 current_entry; }; +#pragma pack(1) +struct bmic_controller_parameters { + u8 led_flags; + u8 enable_command_list_verification; + u8 backed_out_write_drives; + u16 stripes_for_parity; + u8 parity_distribution_mode_flags; + u16 max_driver_requests; + u16 elevator_trend_count; + u8 disable_elevator; + u8 force_scan_complete; + u8 scsi_transfer_mode; + u8 force_narrow; + u8 rebuild_priority; + u8 expand_priority; + u8 host_sdb_asic_fix; + u8 pdpi_burst_from_host_disabled; + char software_name[64]; + char hardware_name[32]; + u8 bridge_revision; + u8 snapshot_priority; + u32 os_specific; + u8 post_prompt_timeout; + u8 automatic_drive_slamming; + u8 reserved1; + u8 nvram_flags; + u8 cache_nvram_flags; + u8 drive_config_flags; + u16 reserved2; + u8 temp_warning_level; + u8 temp_shutdown_level; + u8 temp_condition_reset; + u8 max_coalesce_commands; + u32 max_coalesce_delay; + u8 orca_password[4]; + u8 access_id[16]; + u8 reserved[356]; +}; +#pragma pack() + struct ctlr_info { int ctlr; char devname[8]; @@ -80,6 +129,7 @@ struct ctlr_info { unsigned int msi_vector; int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ struct access_method access; + char hba_mode_enabled; /* queue and queue Info */ struct list_head reqQ; @@ -95,6 +145,10 @@ struct ctlr_info { /* pointers to command and error info pool */ struct CommandList *cmd_pool; dma_addr_t cmd_pool_dhandle; + struct io_accel1_cmd *ioaccel_cmd_pool; + dma_addr_t ioaccel_cmd_pool_dhandle; + struct io_accel2_cmd *ioaccel2_cmd_pool; + dma_addr_t ioaccel2_cmd_pool_dhandle; struct ErrorInfo *errinfo_pool; dma_addr_t errinfo_pool_dhandle; unsigned long *cmd_pool_bits; @@ -128,7 +182,14 @@ struct ctlr_info { u8 nreply_queues; dma_addr_t reply_pool_dhandle; u32 *blockFetchTable; + u32 *ioaccel1_blockFetchTable; + u32 *ioaccel2_blockFetchTable; + u32 *ioaccel2_bft2_regs; unsigned char *hba_inquiry_data; + u32 driver_support; + u32 fw_support; + int ioaccel_support; + int ioaccel_maxsg; u64 last_intr_timestamp; u32 last_heartbeat; u64 last_heartbeat_timestamp; @@ -161,7 +222,35 @@ struct ctlr_info { #define HPSATMF_LOG_QRY_TASK (1 << 23) #define HPSATMF_LOG_QRY_TSET (1 << 24) #define HPSATMF_LOG_QRY_ASYNC (1 << 25) + u32 events; +#define CTLR_STATE_CHANGE_EVENT (1 << 0) +#define CTLR_ENCLOSURE_HOT_PLUG_EVENT (1 << 1) +#define CTLR_STATE_CHANGE_EVENT_PHYSICAL_DRV (1 << 4) +#define CTLR_STATE_CHANGE_EVENT_LOGICAL_DRV (1 << 5) +#define CTLR_STATE_CHANGE_EVENT_REDUNDANT_CNTRL (1 << 6) +#define CTLR_STATE_CHANGE_EVENT_AIO_ENABLED_DISABLED (1 << 30) +#define CTLR_STATE_CHANGE_EVENT_AIO_CONFIG_CHANGE (1 << 31) + +#define RESCAN_REQUIRED_EVENT_BITS \ + (CTLR_STATE_CHANGE_EVENT | \ + CTLR_ENCLOSURE_HOT_PLUG_EVENT | \ + CTLR_STATE_CHANGE_EVENT_PHYSICAL_DRV | \ + CTLR_STATE_CHANGE_EVENT_LOGICAL_DRV | \ + CTLR_STATE_CHANGE_EVENT_REDUNDANT_CNTRL | \ + CTLR_STATE_CHANGE_EVENT_AIO_ENABLED_DISABLED | \ + CTLR_STATE_CHANGE_EVENT_AIO_CONFIG_CHANGE) + spinlock_t offline_device_lock; + struct list_head offline_device_list; + int acciopath_status; + int drv_req_rescan; /* flag for driver to request rescan event */ + int raid_offload_debug; }; + +struct offline_device_entry { + unsigned char scsi3addr[8]; + struct list_head offline_list; +}; + #define HPSA_ABORT_MSG 0 #define HPSA_DEVICE_RESET_MSG 1 #define HPSA_RESET_TYPE_CONTROLLER 0x00 @@ -242,6 +331,14 @@ struct ctlr_info { #define HPSA_INTR_ON 1 #define HPSA_INTR_OFF 0 + +/* + * Inbound Post Queue offsets for IO Accelerator Mode 2 + */ +#define IOACCEL2_INBOUND_POSTQ_32 0x48 +#define IOACCEL2_INBOUND_POSTQ_64_LOW 0xd0 +#define IOACCEL2_INBOUND_POSTQ_64_HI 0xd4 + /* Send the command to the hardware */ @@ -254,6 +351,18 @@ static void SA5_submit_command(struct ctlr_info *h, (void) readl(h->vaddr + SA5_SCRATCHPAD_OFFSET); } +static void SA5_submit_command_ioaccel2(struct ctlr_info *h, + struct CommandList *c) +{ + dev_dbg(&h->pdev->dev, "Sending %x, tag = %x\n", c->busaddr, + c->Header.Tag.lower); + if (c->cmd_type == CMD_IOACCEL2) + writel(c->busaddr, h->vaddr + IOACCEL2_INBOUND_POSTQ_32); + else + writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET); + (void) readl(h->vaddr + SA5_SCRATCHPAD_OFFSET); +} + /* * This card is the opposite of the other cards. * 0 turns interrupts on... @@ -387,6 +496,50 @@ static bool SA5_performant_intr_pending(struct ctlr_info *h) return register_value & SA5_OUTDB_STATUS_PERF_BIT; } +#define SA5_IOACCEL_MODE1_INTR_STATUS_CMP_BIT 0x100 + +static bool SA5_ioaccel_mode1_intr_pending(struct ctlr_info *h) +{ + unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS); + + return (register_value & SA5_IOACCEL_MODE1_INTR_STATUS_CMP_BIT) ? + true : false; +} + +#define IOACCEL_MODE1_REPLY_QUEUE_INDEX 0x1A0 +#define IOACCEL_MODE1_PRODUCER_INDEX 0x1B8 +#define IOACCEL_MODE1_CONSUMER_INDEX 0x1BC +#define IOACCEL_MODE1_REPLY_UNUSED 0xFFFFFFFFFFFFFFFFULL + +static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q) +{ + u64 register_value; + struct reply_pool *rq = &h->reply_queue[q]; + unsigned long flags; + + BUG_ON(q >= h->nreply_queues); + + register_value = rq->head[rq->current_entry]; + if (register_value != IOACCEL_MODE1_REPLY_UNUSED) { + rq->head[rq->current_entry] = IOACCEL_MODE1_REPLY_UNUSED; + if (++rq->current_entry == rq->size) + rq->current_entry = 0; + /* + * @todo + * + * Don't really need to write the new index after each command, + * but with current driver design this is easiest. + */ + wmb(); + writel((q << 24) | rq->current_entry, h->vaddr + + IOACCEL_MODE1_CONSUMER_INDEX); + spin_lock_irqsave(&h->lock, flags); + h->commands_outstanding--; + spin_unlock_irqrestore(&h->lock, flags); + } + return (unsigned long) register_value; +} + static struct access_method SA5_access = { SA5_submit_command, SA5_intr_mask, @@ -395,6 +548,22 @@ static struct access_method SA5_access = { SA5_completed, }; +static struct access_method SA5_ioaccel_mode1_access = { + SA5_submit_command, + SA5_performant_intr_mask, + SA5_fifo_full, + SA5_ioaccel_mode1_intr_pending, + SA5_ioaccel_mode1_completed, +}; + +static struct access_method SA5_ioaccel_mode2_access = { + SA5_submit_command_ioaccel2, + SA5_performant_intr_mask, + SA5_fifo_full, + SA5_performant_intr_pending, + SA5_performant_completed, +}; + static struct access_method SA5_performant_access = { SA5_submit_command, SA5_performant_intr_mask, |