summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/hpsa.h
diff options
context:
space:
mode:
authorMatt Gates <matthew.gates@hp.com>2014-02-18 20:55:17 +0100
committerJames Bottomley <JBottomley@Parallels.com>2014-03-15 18:19:02 +0100
commite1f7de0cdd68d246d7008241cd9e443a54f880a8 (patch)
tree060525e7cdc5f2f86f9fcf4bb5ee3a22861c9e8f /drivers/scsi/hpsa.h
parent[SCSI] hpsa: mark last scatter gather element as the last (diff)
downloadlinux-e1f7de0cdd68d246d7008241cd9e443a54f880a8.tar.xz
linux-e1f7de0cdd68d246d7008241cd9e443a54f880a8.zip
[SCSI] hpsa: add support for 'fastpath' i/o
For certain i/o's to certain devices (unmasked physical disks) we can bypass the RAID stack firmware and do the i/o to the device directly and it will be faster. Signed-off-by: Matt Gates <matthew.gates@hp.com> Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/hpsa.h')
-rw-r--r--drivers/scsi/hpsa.h51
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 01c328349c83..c7865f30ffd1 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -46,6 +46,7 @@ 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 */
+ u32 ioaccel_handle;
};
struct reply_pool {
@@ -95,6 +96,8 @@ 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 ErrorInfo *errinfo_pool;
dma_addr_t errinfo_pool_dhandle;
unsigned long *cmd_pool_bits;
@@ -128,6 +131,7 @@ struct ctlr_info {
u8 nreply_queues;
dma_addr_t reply_pool_dhandle;
u32 *blockFetchTable;
+ u32 *ioaccel1_blockFetchTable;
unsigned char *hba_inquiry_data;
u64 last_intr_timestamp;
u32 last_heartbeat;
@@ -387,6 +391,45 @@ 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;
+ spin_lock_irqsave(&h->lock, flags);
+ h->commands_outstanding--;
+ spin_unlock_irqrestore(&h->lock, flags);
+ } else {
+ writel((q << 24) | rq->current_entry,
+ h->vaddr + IOACCEL_MODE1_CONSUMER_INDEX);
+ }
+ return (unsigned long) register_value;
+}
+
static struct access_method SA5_access = {
SA5_submit_command,
SA5_intr_mask,
@@ -395,6 +438,14 @@ 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_performant_access = {
SA5_submit_command,
SA5_performant_intr_mask,