summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/hpsa.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/hpsa.h')
-rw-r--r--drivers/scsi/hpsa.h85
1 files changed, 60 insertions, 25 deletions
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 7b28d54fa87..981647989bf 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -34,7 +34,7 @@ struct access_method {
void (*set_intr_mask)(struct ctlr_info *h, unsigned long val);
unsigned long (*fifo_full)(struct ctlr_info *h);
bool (*intr_pending)(struct ctlr_info *h);
- unsigned long (*command_completed)(struct ctlr_info *h);
+ unsigned long (*command_completed)(struct ctlr_info *h, u8 q);
};
struct hpsa_scsi_dev_t {
@@ -48,6 +48,13 @@ struct hpsa_scsi_dev_t {
unsigned char raid_level; /* from inquiry page 0xC1 */
};
+struct reply_pool {
+ u64 *head;
+ size_t size;
+ u8 wraparound;
+ u32 current_entry;
+};
+
struct ctlr_info {
int ctlr;
char devname[8];
@@ -68,7 +75,7 @@ struct ctlr_info {
# define DOORBELL_INT 1
# define SIMPLE_MODE_INT 2
# define MEMQ_MODE_INT 3
- unsigned int intr[4];
+ unsigned int intr[MAX_REPLY_QUEUES];
unsigned int msix_vector;
unsigned int msi_vector;
int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
@@ -78,7 +85,6 @@ struct ctlr_info {
struct list_head reqQ;
struct list_head cmpQ;
unsigned int Qdepth;
- unsigned int maxQsinceinit;
unsigned int maxSG;
spinlock_t lock;
int maxsgentries;
@@ -111,20 +117,45 @@ struct ctlr_info {
unsigned long transMethod;
/*
- * Performant mode completion buffer
+ * Performant mode completion buffers
*/
u64 *reply_pool;
- dma_addr_t reply_pool_dhandle;
- u64 *reply_pool_head;
size_t reply_pool_size;
- unsigned char reply_pool_wraparound;
+ struct reply_pool reply_queue[MAX_REPLY_QUEUES];
+ u8 nreply_queues;
+ dma_addr_t reply_pool_dhandle;
u32 *blockFetchTable;
unsigned char *hba_inquiry_data;
u64 last_intr_timestamp;
u32 last_heartbeat;
u64 last_heartbeat_timestamp;
+ u32 heartbeat_sample_interval;
+ atomic_t firmware_flash_in_progress;
u32 lockup_detected;
struct list_head lockup_list;
+ /* Address of h->q[x] is passed to intr handler to know which queue */
+ u8 q[MAX_REPLY_QUEUES];
+ u32 TMFSupportFlags; /* cache what task mgmt funcs are supported. */
+#define HPSATMF_BITS_SUPPORTED (1 << 0)
+#define HPSATMF_PHYS_LUN_RESET (1 << 1)
+#define HPSATMF_PHYS_NEX_RESET (1 << 2)
+#define HPSATMF_PHYS_TASK_ABORT (1 << 3)
+#define HPSATMF_PHYS_TSET_ABORT (1 << 4)
+#define HPSATMF_PHYS_CLEAR_ACA (1 << 5)
+#define HPSATMF_PHYS_CLEAR_TSET (1 << 6)
+#define HPSATMF_PHYS_QRY_TASK (1 << 7)
+#define HPSATMF_PHYS_QRY_TSET (1 << 8)
+#define HPSATMF_PHYS_QRY_ASYNC (1 << 9)
+#define HPSATMF_MASK_SUPPORTED (1 << 16)
+#define HPSATMF_LOG_LUN_RESET (1 << 17)
+#define HPSATMF_LOG_NEX_RESET (1 << 18)
+#define HPSATMF_LOG_TASK_ABORT (1 << 19)
+#define HPSATMF_LOG_TSET_ABORT (1 << 20)
+#define HPSATMF_LOG_CLEAR_ACA (1 << 21)
+#define HPSATMF_LOG_CLEAR_TSET (1 << 22)
+#define HPSATMF_LOG_QRY_TASK (1 << 23)
+#define HPSATMF_LOG_QRY_TSET (1 << 24)
+#define HPSATMF_LOG_QRY_ASYNC (1 << 25)
};
#define HPSA_ABORT_MSG 0
#define HPSA_DEVICE_RESET_MSG 1
@@ -216,9 +247,6 @@ static void SA5_submit_command(struct ctlr_info *h,
c->Header.Tag.lower);
writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
(void) readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
- h->commands_outstanding++;
- if (h->commands_outstanding > h->max_outstanding)
- h->max_outstanding = h->commands_outstanding;
}
/*
@@ -254,16 +282,17 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
}
}
-static unsigned long SA5_performant_completed(struct ctlr_info *h)
+static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
{
- unsigned long register_value = FIFO_EMPTY;
+ struct reply_pool *rq = &h->reply_queue[q];
+ unsigned long flags, register_value = FIFO_EMPTY;
- /* flush the controller write of the reply queue by reading
- * outbound doorbell status register.
- */
- register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
/* msi auto clears the interrupt pending bit. */
if (!(h->msi_vector || h->msix_vector)) {
+ /* flush the controller write of the reply queue by reading
+ * outbound doorbell status register.
+ */
+ register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR);
/* Do a read in order to flush the write to the controller
* (as per spec.)
@@ -271,19 +300,20 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h)
register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
}
- if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
- register_value = *(h->reply_pool_head);
- (h->reply_pool_head)++;
+ if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
+ register_value = rq->head[rq->current_entry];
+ rq->current_entry++;
+ spin_lock_irqsave(&h->lock, flags);
h->commands_outstanding--;
+ spin_unlock_irqrestore(&h->lock, flags);
} else {
register_value = FIFO_EMPTY;
}
/* Check for wraparound */
- if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
- h->reply_pool_head = h->reply_pool;
- h->reply_pool_wraparound ^= 1;
+ if (rq->current_entry == h->max_commands) {
+ rq->current_entry = 0;
+ rq->wraparound ^= 1;
}
-
return register_value;
}
@@ -303,13 +333,18 @@ static unsigned long SA5_fifo_full(struct ctlr_info *h)
* returns value read from hardware.
* returns FIFO_EMPTY if there is nothing to read
*/
-static unsigned long SA5_completed(struct ctlr_info *h)
+static unsigned long SA5_completed(struct ctlr_info *h,
+ __attribute__((unused)) u8 q)
{
unsigned long register_value
= readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
+ unsigned long flags;
- if (register_value != FIFO_EMPTY)
+ if (register_value != FIFO_EMPTY) {
+ spin_lock_irqsave(&h->lock, flags);
h->commands_outstanding--;
+ spin_unlock_irqrestore(&h->lock, flags);
+ }
#ifdef HPSA_DEBUG
if (register_value != FIFO_EMPTY)