aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss.h
diff options
context:
space:
mode:
authorMike Miller <mike.miller@hp.com>2010-06-02 15:58:06 -0400
committerJens Axboe <jaxboe@fusionio.com>2010-08-07 12:12:51 -0400
commit5e216153c34ac21781110795284a784037f808e3 (patch)
treeb42ceb1e884bdb397283ddb01562fe03d1f95cad /drivers/block/cciss.h
parent1d1414419f034702bf587accdf2a9ac53245e000 (diff)
cciss: add performant mode support for Stars/Sirius
Add a mode of controller operation called Performant Mode. Even though cciss has been deprecated in favor of hpsa there are new controllers due out next year that HP must support in older vendor distros. Vendors require all fixes/features be upstream. These new controllers support only 16 commands in simple mode but support up to 1024 in performant mode. This requires us to add this support at this late date. The performant mode transport minimizes host PCI accesses by performinf many completions per read. PCI writes are posted so the host can write then immediately get off the bus not waiting for the writwe to complete to the target. In the context of performant mode the host read out to a controller pulls all posted writes into host memory ensuring the reply queue is coherent. Signed-off-by: Mike Miller <mike.miller@hp.com> Cc: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'drivers/block/cciss.h')
-rw-r--r--drivers/block/cciss.h109
1 files changed, 103 insertions, 6 deletions
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index c527932d223a..8a9f5b58daa8 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -85,8 +85,8 @@ struct ctlr_info
85 int max_cmd_sgentries; 85 int max_cmd_sgentries;
86 SGDescriptor_struct **cmd_sg_list; 86 SGDescriptor_struct **cmd_sg_list;
87 87
88# define DOORBELL_INT 0 88# define PERF_MODE_INT 0
89# define PERF_MODE_INT 1 89# define DOORBELL_INT 1
90# define SIMPLE_MODE_INT 2 90# define SIMPLE_MODE_INT 2
91# define MEMQ_MODE_INT 3 91# define MEMQ_MODE_INT 3
92 unsigned int intr[4]; 92 unsigned int intr[4];
@@ -137,10 +137,27 @@ struct ctlr_info
137 struct list_head scan_list; 137 struct list_head scan_list;
138 struct completion scan_wait; 138 struct completion scan_wait;
139 struct device dev; 139 struct device dev;
140 /*
141 * Performant mode tables.
142 */
143 u32 trans_support;
144 u32 trans_offset;
145 struct TransTable_struct *transtable;
146 unsigned long transMethod;
147
148 /*
149 * Performant mode completion buffer
150 */
151 u64 *reply_pool;
152 dma_addr_t reply_pool_dhandle;
153 u64 *reply_pool_head;
154 size_t reply_pool_size;
155 unsigned char reply_pool_wraparound;
156 u32 *blockFetchTable;
140}; 157};
141 158
142/* Defining the diffent access_menthods */ 159/* Defining the diffent access_methods
143/* 160 *
144 * Memory mapped FIFO interface (SMART 53xx cards) 161 * Memory mapped FIFO interface (SMART 53xx cards)
145 */ 162 */
146#define SA5_DOORBELL 0x20 163#define SA5_DOORBELL 0x20
@@ -159,6 +176,15 @@ struct ctlr_info
159#define SA5B_INTR_PENDING 0x04 176#define SA5B_INTR_PENDING 0x04
160#define FIFO_EMPTY 0xffffffff 177#define FIFO_EMPTY 0xffffffff
161#define CCISS_FIRMWARE_READY 0xffff0000 /* value in scratchpad register */ 178#define CCISS_FIRMWARE_READY 0xffff0000 /* value in scratchpad register */
179/* Perf. mode flags */
180#define SA5_PERF_INTR_PENDING 0x04
181#define SA5_PERF_INTR_OFF 0x05
182#define SA5_OUTDB_STATUS_PERF_BIT 0x01
183#define SA5_OUTDB_CLEAR_PERF_BIT 0x01
184#define SA5_OUTDB_CLEAR 0xA0
185#define SA5_OUTDB_CLEAR_PERF_BIT 0x01
186#define SA5_OUTDB_STATUS 0x9C
187
162 188
163#define CISS_ERROR_BIT 0x02 189#define CISS_ERROR_BIT 0x02
164 190
@@ -170,8 +196,9 @@ struct ctlr_info
170static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c) 196static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c)
171{ 197{
172#ifdef CCISS_DEBUG 198#ifdef CCISS_DEBUG
173 printk("Sending %x - down to controller\n", c->busaddr ); 199 printk(KERN_WARNING "cciss%d: Sending %08x - down to controller\n",
174#endif /* CCISS_DEBUG */ 200 h->ctlr, c->busaddr);
201#endif /* CCISS_DEBUG */
175 writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET); 202 writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
176 h->commands_outstanding++; 203 h->commands_outstanding++;
177 if ( h->commands_outstanding > h->max_outstanding) 204 if ( h->commands_outstanding > h->max_outstanding)
@@ -214,6 +241,20 @@ static void SA5B_intr_mask(ctlr_info_t *h, unsigned long val)
214 h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); 241 h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
215 } 242 }
216} 243}
244
245/* Performant mode intr_mask */
246static void SA5_performant_intr_mask(ctlr_info_t *h, unsigned long val)
247{
248 if (val) { /* turn on interrupts */
249 h->interrupts_enabled = 1;
250 writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
251 } else {
252 h->interrupts_enabled = 0;
253 writel(SA5_PERF_INTR_OFF,
254 h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
255 }
256}
257
217/* 258/*
218 * Returns true if fifo is full. 259 * Returns true if fifo is full.
219 * 260 *
@@ -250,6 +291,40 @@ static unsigned long SA5_completed(ctlr_info_t *h)
250 return ( register_value); 291 return ( register_value);
251 292
252} 293}
294
295/* Performant mode command completed */
296static unsigned long SA5_performant_completed(ctlr_info_t *h)
297{
298 unsigned long register_value = FIFO_EMPTY;
299
300 /* flush the controller write of the reply queue by reading
301 * outbound doorbell status register.
302 */
303 register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
304 /* msi auto clears the interrupt pending bit. */
305 if (!(h->msi_vector || h->msix_vector)) {
306 writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR);
307 /* Do a read in order to flush the write to the controller
308 * (as per spec.)
309 */
310 register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
311 }
312
313 if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
314 register_value = *(h->reply_pool_head);
315 (h->reply_pool_head)++;
316 h->commands_outstanding--;
317 } else {
318 register_value = FIFO_EMPTY;
319 }
320 /* Check for wraparound */
321 if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
322 h->reply_pool_head = h->reply_pool;
323 h->reply_pool_wraparound ^= 1;
324 }
325
326 return register_value;
327}
253/* 328/*
254 * Returns true if an interrupt is pending.. 329 * Returns true if an interrupt is pending..
255 */ 330 */
@@ -280,6 +355,20 @@ static bool SA5B_intr_pending(ctlr_info_t *h)
280 return 0 ; 355 return 0 ;
281} 356}
282 357
358static bool SA5_performant_intr_pending(ctlr_info_t *h)
359{
360 unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS);
361
362 if (!register_value)
363 return false;
364
365 if (h->msi_vector || h->msix_vector)
366 return true;
367
368 /* Read outbound doorbell to flush */
369 register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
370 return register_value & SA5_OUTDB_STATUS_PERF_BIT;
371}
283 372
284static struct access_method SA5_access = { 373static struct access_method SA5_access = {
285 SA5_submit_command, 374 SA5_submit_command,
@@ -297,6 +386,14 @@ static struct access_method SA5B_access = {
297 SA5_completed, 386 SA5_completed,
298}; 387};
299 388
389static struct access_method SA5_performant_access = {
390 SA5_submit_command,
391 SA5_performant_intr_mask,
392 SA5_fifo_full,
393 SA5_performant_intr_pending,
394 SA5_performant_completed,
395};
396
300struct board_type { 397struct board_type {
301 __u32 board_id; 398 __u32 board_id;
302 char *product_name; 399 char *product_name;