diff options
author | David S. Miller <davem@davemloft.net> | 2010-09-08 23:49:04 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-08 23:49:04 -0700 |
commit | e199e6136ce6b151e6638ae93dca60748424d900 (patch) | |
tree | 0d66e0b5d227c36b005e4f5537f4bbcfc6ed4904 /drivers/block/cciss.h | |
parent | 972c40b5bee429c84ba727f8ac0a08292bc5dc3d (diff) | |
parent | d56557af19867edb8c0e96f8e26399698a08857f (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/block/cciss.h')
-rw-r--r-- | drivers/block/cciss.h | 135 |
1 files changed, 124 insertions, 11 deletions
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index c5d411174db..ae340ffc8f8 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -25,7 +25,7 @@ struct access_method { void (*submit_command)(ctlr_info_t *h, CommandList_struct *c); void (*set_intr_mask)(ctlr_info_t *h, unsigned long val); unsigned long (*fifo_full)(ctlr_info_t *h); - unsigned long (*intr_pending)(ctlr_info_t *h); + bool (*intr_pending)(ctlr_info_t *h); unsigned long (*command_completed)(ctlr_info_t *h); }; typedef struct _drive_info_struct @@ -85,8 +85,8 @@ struct ctlr_info int max_cmd_sgentries; SGDescriptor_struct **cmd_sg_list; -# define DOORBELL_INT 0 -# define PERF_MODE_INT 1 +# define PERF_MODE_INT 0 +# define DOORBELL_INT 1 # define SIMPLE_MODE_INT 2 # define MEMQ_MODE_INT 3 unsigned int intr[4]; @@ -137,10 +137,27 @@ struct ctlr_info struct list_head scan_list; struct completion scan_wait; struct device dev; + /* + * Performant mode tables. + */ + u32 trans_support; + u32 trans_offset; + struct TransTable_struct *transtable; + unsigned long transMethod; + + /* + * Performant mode completion buffer + */ + u64 *reply_pool; + dma_addr_t reply_pool_dhandle; + u64 *reply_pool_head; + size_t reply_pool_size; + unsigned char reply_pool_wraparound; + u32 *blockFetchTable; }; -/* Defining the diffent access_menthods */ -/* +/* Defining the diffent access_methods + * * Memory mapped FIFO interface (SMART 53xx cards) */ #define SA5_DOORBELL 0x20 @@ -159,19 +176,47 @@ struct ctlr_info #define SA5B_INTR_PENDING 0x04 #define FIFO_EMPTY 0xffffffff #define CCISS_FIRMWARE_READY 0xffff0000 /* value in scratchpad register */ +/* Perf. mode flags */ +#define SA5_PERF_INTR_PENDING 0x04 +#define SA5_PERF_INTR_OFF 0x05 +#define SA5_OUTDB_STATUS_PERF_BIT 0x01 +#define SA5_OUTDB_CLEAR_PERF_BIT 0x01 +#define SA5_OUTDB_CLEAR 0xA0 +#define SA5_OUTDB_CLEAR_PERF_BIT 0x01 +#define SA5_OUTDB_STATUS 0x9C + #define CISS_ERROR_BIT 0x02 #define CCISS_INTR_ON 1 #define CCISS_INTR_OFF 0 + + +/* CCISS_BOARD_READY_WAIT_SECS is how long to wait for a board + * to become ready, in seconds, before giving up on it. + * CCISS_BOARD_READY_POLL_INTERVAL_MSECS * is how long to wait + * between polling the board to see if it is ready, in + * milliseconds. CCISS_BOARD_READY_ITERATIONS is derived + * the above. + */ +#define CCISS_BOARD_READY_WAIT_SECS (120) +#define CCISS_BOARD_READY_POLL_INTERVAL_MSECS (100) +#define CCISS_BOARD_READY_ITERATIONS \ + ((CCISS_BOARD_READY_WAIT_SECS * 1000) / \ + CCISS_BOARD_READY_POLL_INTERVAL_MSECS) +#define CCISS_POST_RESET_PAUSE_MSECS (3000) +#define CCISS_POST_RESET_NOOP_INTERVAL_MSECS (1000) +#define CCISS_POST_RESET_NOOP_RETRIES (12) + /* Send the command to the hardware */ static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c) { #ifdef CCISS_DEBUG - printk("Sending %x - down to controller\n", c->busaddr ); -#endif /* CCISS_DEBUG */ + printk(KERN_WARNING "cciss%d: Sending %08x - down to controller\n", + h->ctlr, c->busaddr); +#endif /* CCISS_DEBUG */ writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET); h->commands_outstanding++; if ( h->commands_outstanding > h->max_outstanding) @@ -214,6 +259,20 @@ static void SA5B_intr_mask(ctlr_info_t *h, unsigned long val) h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } } + +/* Performant mode intr_mask */ +static void SA5_performant_intr_mask(ctlr_info_t *h, unsigned long val) +{ + if (val) { /* turn on interrupts */ + h->interrupts_enabled = 1; + writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); + } else { + h->interrupts_enabled = 0; + writel(SA5_PERF_INTR_OFF, + h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); + } +} + /* * Returns true if fifo is full. * @@ -250,10 +309,44 @@ static unsigned long SA5_completed(ctlr_info_t *h) return ( register_value); } + +/* Performant mode command completed */ +static unsigned long SA5_performant_completed(ctlr_info_t *h) +{ + unsigned long 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)) { + 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.) + */ + 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)++; + h->commands_outstanding--; + } 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; + } + + return register_value; +} /* * Returns true if an interrupt is pending.. */ -static unsigned long SA5_intr_pending(ctlr_info_t *h) +static bool SA5_intr_pending(ctlr_info_t *h) { unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS); @@ -268,7 +361,7 @@ static unsigned long SA5_intr_pending(ctlr_info_t *h) /* * Returns true if an interrupt is pending.. */ -static unsigned long SA5B_intr_pending(ctlr_info_t *h) +static bool SA5B_intr_pending(ctlr_info_t *h) { unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS); @@ -280,6 +373,20 @@ static unsigned long SA5B_intr_pending(ctlr_info_t *h) return 0 ; } +static bool SA5_performant_intr_pending(ctlr_info_t *h) +{ + unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS); + + if (!register_value) + return false; + + if (h->msi_vector || h->msix_vector) + return true; + + /* Read outbound doorbell to flush */ + register_value = readl(h->vaddr + SA5_OUTDB_STATUS); + return register_value & SA5_OUTDB_STATUS_PERF_BIT; +} static struct access_method SA5_access = { SA5_submit_command, @@ -297,6 +404,14 @@ static struct access_method SA5B_access = { SA5_completed, }; +static struct access_method SA5_performant_access = { + SA5_submit_command, + SA5_performant_intr_mask, + SA5_fifo_full, + SA5_performant_intr_pending, + SA5_performant_completed, +}; + struct board_type { __u32 board_id; char *product_name; @@ -304,6 +419,4 @@ struct board_type { int nr_cmds; /* Max cmds this kind of ctlr can handle. */ }; -#define CCISS_LOCK(i) (&hba[i]->lock) - #endif /* CCISS_H */ |