Commit 254f796b authored by Matt Gates's avatar Matt Gates Committed by James Bottomley

[SCSI] hpsa: use multiple reply queues

Smart Arrays can support multiple reply queues onto which command
completions may be deposited.  It can help performance quite a bit
to arrange for command completions to be processed on the same CPU
from which they were submitted to increase the likelihood of cache
hits.
Signed-off-by: default avatarMatt Gates <matthew.gates@hp.com>
Signed-off-by: default avatarStephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 1d94f94d
This diff is collapsed.
...@@ -34,7 +34,7 @@ struct access_method { ...@@ -34,7 +34,7 @@ struct access_method {
void (*set_intr_mask)(struct ctlr_info *h, unsigned long val); void (*set_intr_mask)(struct ctlr_info *h, unsigned long val);
unsigned long (*fifo_full)(struct ctlr_info *h); unsigned long (*fifo_full)(struct ctlr_info *h);
bool (*intr_pending)(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 { struct hpsa_scsi_dev_t {
...@@ -48,6 +48,13 @@ struct hpsa_scsi_dev_t { ...@@ -48,6 +48,13 @@ struct hpsa_scsi_dev_t {
unsigned char raid_level; /* from inquiry page 0xC1 */ unsigned char raid_level; /* from inquiry page 0xC1 */
}; };
struct reply_pool {
u64 *head;
size_t size;
u8 wraparound;
u32 current_entry;
};
struct ctlr_info { struct ctlr_info {
int ctlr; int ctlr;
char devname[8]; char devname[8];
...@@ -68,7 +75,7 @@ struct ctlr_info { ...@@ -68,7 +75,7 @@ struct ctlr_info {
# define DOORBELL_INT 1 # define DOORBELL_INT 1
# define SIMPLE_MODE_INT 2 # define SIMPLE_MODE_INT 2
# define MEMQ_MODE_INT 3 # define MEMQ_MODE_INT 3
unsigned int intr[4]; unsigned int intr[MAX_REPLY_QUEUES];
unsigned int msix_vector; unsigned int msix_vector;
unsigned int msi_vector; unsigned int msi_vector;
int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
...@@ -111,13 +118,13 @@ struct ctlr_info { ...@@ -111,13 +118,13 @@ struct ctlr_info {
unsigned long transMethod; unsigned long transMethod;
/* /*
* Performant mode completion buffer * Performant mode completion buffers
*/ */
u64 *reply_pool; u64 *reply_pool;
dma_addr_t reply_pool_dhandle;
u64 *reply_pool_head;
size_t reply_pool_size; 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; u32 *blockFetchTable;
unsigned char *hba_inquiry_data; unsigned char *hba_inquiry_data;
u64 last_intr_timestamp; u64 last_intr_timestamp;
...@@ -125,6 +132,8 @@ struct ctlr_info { ...@@ -125,6 +132,8 @@ struct ctlr_info {
u64 last_heartbeat_timestamp; u64 last_heartbeat_timestamp;
u32 lockup_detected; u32 lockup_detected;
struct list_head lockup_list; 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. */ u32 TMFSupportFlags; /* cache what task mgmt funcs are supported. */
#define HPSATMF_BITS_SUPPORTED (1 << 0) #define HPSATMF_BITS_SUPPORTED (1 << 0)
#define HPSATMF_PHYS_LUN_RESET (1 << 1) #define HPSATMF_PHYS_LUN_RESET (1 << 1)
...@@ -275,8 +284,9 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val) ...@@ -275,8 +284,9 @@ 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)
{ {
struct reply_pool *rq = &h->reply_queue[q];
unsigned long register_value = FIFO_EMPTY; unsigned long register_value = FIFO_EMPTY;
/* msi auto clears the interrupt pending bit. */ /* msi auto clears the interrupt pending bit. */
...@@ -292,19 +302,18 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h) ...@@ -292,19 +302,18 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h)
register_value = readl(h->vaddr + SA5_OUTDB_STATUS); register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
} }
if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) { if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
register_value = *(h->reply_pool_head); register_value = rq->head[rq->current_entry];
(h->reply_pool_head)++; rq->current_entry++;
h->commands_outstanding--; h->commands_outstanding--;
} else { } else {
register_value = FIFO_EMPTY; register_value = FIFO_EMPTY;
} }
/* Check for wraparound */ /* Check for wraparound */
if (h->reply_pool_head == (h->reply_pool + h->max_commands)) { if (rq->current_entry == h->max_commands) {
h->reply_pool_head = h->reply_pool; rq->current_entry = 0;
h->reply_pool_wraparound ^= 1; rq->wraparound ^= 1;
} }
return register_value; return register_value;
} }
...@@ -324,7 +333,8 @@ static unsigned long SA5_fifo_full(struct ctlr_info *h) ...@@ -324,7 +333,8 @@ static unsigned long SA5_fifo_full(struct ctlr_info *h)
* returns value read from hardware. * returns value read from hardware.
* returns FIFO_EMPTY if there is nothing to read * 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 unsigned long register_value
= readl(h->vaddr + SA5_REPLY_PORT_OFFSET); = readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
......
...@@ -129,6 +129,7 @@ ...@@ -129,6 +129,7 @@
#define CFGTBL_Trans_Simple 0x00000002l #define CFGTBL_Trans_Simple 0x00000002l
#define CFGTBL_Trans_Performant 0x00000004l #define CFGTBL_Trans_Performant 0x00000004l
#define CFGTBL_Trans_use_short_tags 0x20000000l #define CFGTBL_Trans_use_short_tags 0x20000000l
#define CFGTBL_Trans_enable_directed_msix (1 << 30)
#define CFGTBL_BusType_Ultra2 0x00000001l #define CFGTBL_BusType_Ultra2 0x00000001l
#define CFGTBL_BusType_Ultra3 0x00000002l #define CFGTBL_BusType_Ultra3 0x00000002l
...@@ -380,8 +381,8 @@ struct TransTable_struct { ...@@ -380,8 +381,8 @@ struct TransTable_struct {
u32 RepQCount; u32 RepQCount;
u32 RepQCtrAddrLow32; u32 RepQCtrAddrLow32;
u32 RepQCtrAddrHigh32; u32 RepQCtrAddrHigh32;
u32 RepQAddr0Low32; #define MAX_REPLY_QUEUES 8
u32 RepQAddr0High32; struct vals32 RepQAddr[MAX_REPLY_QUEUES];
}; };
struct hpsa_pci_info { struct hpsa_pci_info {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment