aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/hpsa.h
diff options
context:
space:
mode:
authorMatt Gates <matthew.gates@hp.com>2012-05-01 12:43:06 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-05-10 04:16:25 -0400
commit254f796b9f22b1944c64caabc356a56caaa2facd (patch)
tree4c5ee6950b15456b0d11c3c36587fa659baf6632 /drivers/scsi/hpsa.h
parent1d94f94d89848762306b4a8bd5e658c11828ab12 (diff)
[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: 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.h40
1 files changed, 25 insertions, 15 deletions
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index d8aa95c43f4d..486a7c099246 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -34,7 +34,7 @@ struct access_method {
34 void (*set_intr_mask)(struct ctlr_info *h, unsigned long val); 34 void (*set_intr_mask)(struct ctlr_info *h, unsigned long val);
35 unsigned long (*fifo_full)(struct ctlr_info *h); 35 unsigned long (*fifo_full)(struct ctlr_info *h);
36 bool (*intr_pending)(struct ctlr_info *h); 36 bool (*intr_pending)(struct ctlr_info *h);
37 unsigned long (*command_completed)(struct ctlr_info *h); 37 unsigned long (*command_completed)(struct ctlr_info *h, u8 q);
38}; 38};
39 39
40struct hpsa_scsi_dev_t { 40struct hpsa_scsi_dev_t {
@@ -48,6 +48,13 @@ struct hpsa_scsi_dev_t {
48 unsigned char raid_level; /* from inquiry page 0xC1 */ 48 unsigned char raid_level; /* from inquiry page 0xC1 */
49}; 49};
50 50
51struct reply_pool {
52 u64 *head;
53 size_t size;
54 u8 wraparound;
55 u32 current_entry;
56};
57
51struct ctlr_info { 58struct ctlr_info {
52 int ctlr; 59 int ctlr;
53 char devname[8]; 60 char devname[8];
@@ -68,7 +75,7 @@ struct ctlr_info {
68# define DOORBELL_INT 1 75# define DOORBELL_INT 1
69# define SIMPLE_MODE_INT 2 76# define SIMPLE_MODE_INT 2
70# define MEMQ_MODE_INT 3 77# define MEMQ_MODE_INT 3
71 unsigned int intr[4]; 78 unsigned int intr[MAX_REPLY_QUEUES];
72 unsigned int msix_vector; 79 unsigned int msix_vector;
73 unsigned int msi_vector; 80 unsigned int msi_vector;
74 int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ 81 int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
@@ -111,13 +118,13 @@ struct ctlr_info {
111 unsigned long transMethod; 118 unsigned long transMethod;
112 119
113 /* 120 /*
114 * Performant mode completion buffer 121 * Performant mode completion buffers
115 */ 122 */
116 u64 *reply_pool; 123 u64 *reply_pool;
117 dma_addr_t reply_pool_dhandle;
118 u64 *reply_pool_head;
119 size_t reply_pool_size; 124 size_t reply_pool_size;
120 unsigned char reply_pool_wraparound; 125 struct reply_pool reply_queue[MAX_REPLY_QUEUES];
126 u8 nreply_queues;
127 dma_addr_t reply_pool_dhandle;
121 u32 *blockFetchTable; 128 u32 *blockFetchTable;
122 unsigned char *hba_inquiry_data; 129 unsigned char *hba_inquiry_data;
123 u64 last_intr_timestamp; 130 u64 last_intr_timestamp;
@@ -125,6 +132,8 @@ struct ctlr_info {
125 u64 last_heartbeat_timestamp; 132 u64 last_heartbeat_timestamp;
126 u32 lockup_detected; 133 u32 lockup_detected;
127 struct list_head lockup_list; 134 struct list_head lockup_list;
135 /* Address of h->q[x] is passed to intr handler to know which queue */
136 u8 q[MAX_REPLY_QUEUES];
128 u32 TMFSupportFlags; /* cache what task mgmt funcs are supported. */ 137 u32 TMFSupportFlags; /* cache what task mgmt funcs are supported. */
129#define HPSATMF_BITS_SUPPORTED (1 << 0) 138#define HPSATMF_BITS_SUPPORTED (1 << 0)
130#define HPSATMF_PHYS_LUN_RESET (1 << 1) 139#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 } 284 }
276} 285}
277 286
278static unsigned long SA5_performant_completed(struct ctlr_info *h) 287static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
279{ 288{
289 struct reply_pool *rq = &h->reply_queue[q];
280 unsigned long register_value = FIFO_EMPTY; 290 unsigned long register_value = FIFO_EMPTY;
281 291
282 /* msi auto clears the interrupt pending bit. */ 292 /* msi auto clears the interrupt pending bit. */
@@ -292,19 +302,18 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h)
292 register_value = readl(h->vaddr + SA5_OUTDB_STATUS); 302 register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
293 } 303 }
294 304
295 if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) { 305 if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
296 register_value = *(h->reply_pool_head); 306 register_value = rq->head[rq->current_entry];
297 (h->reply_pool_head)++; 307 rq->current_entry++;
298 h->commands_outstanding--; 308 h->commands_outstanding--;
299 } else { 309 } else {
300 register_value = FIFO_EMPTY; 310 register_value = FIFO_EMPTY;
301 } 311 }
302 /* Check for wraparound */ 312 /* Check for wraparound */
303 if (h->reply_pool_head == (h->reply_pool + h->max_commands)) { 313 if (rq->current_entry == h->max_commands) {
304 h->reply_pool_head = h->reply_pool; 314 rq->current_entry = 0;
305 h->reply_pool_wraparound ^= 1; 315 rq->wraparound ^= 1;
306 } 316 }
307
308 return register_value; 317 return register_value;
309} 318}
310 319
@@ -324,7 +333,8 @@ static unsigned long SA5_fifo_full(struct ctlr_info *h)
324 * returns value read from hardware. 333 * returns value read from hardware.
325 * returns FIFO_EMPTY if there is nothing to read 334 * returns FIFO_EMPTY if there is nothing to read
326 */ 335 */
327static unsigned long SA5_completed(struct ctlr_info *h) 336static unsigned long SA5_completed(struct ctlr_info *h,
337 __attribute__((unused)) u8 q)
328{ 338{
329 unsigned long register_value 339 unsigned long register_value
330 = readl(h->vaddr + SA5_REPLY_PORT_OFFSET); 340 = readl(h->vaddr + SA5_REPLY_PORT_OFFSET);