Commit 33079b21 authored by Mike Miller's avatar Mike Miller Committed by Linus Torvalds

[PATCH] cciss: direct lookup for command completions

This patch changes the way we complete commands.  In the old method when we
got a completion we searched our command list from the top until we find it.

This method uses a tag associated with each command (not SCSI command tagging)
to index us directly to the completed command.  This helps performance.
Signed-off-by: default avatarDon Brace <dab@hp.com>
Signed-off-by: default avatarMike Miller <mike.miller@hp.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ddd47442
...@@ -174,6 +174,8 @@ static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, ...@@ -174,6 +174,8 @@ static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
int cmd_type); int cmd_type);
static void fail_all_cmds(unsigned long ctlr);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int cciss_proc_get_info(char *buffer, char **start, off_t offset, static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
int length, int *eof, void *data); int length, int *eof, void *data);
...@@ -387,6 +389,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool) ...@@ -387,6 +389,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
return NULL; return NULL;
memset(c, 0, sizeof(CommandList_struct)); memset(c, 0, sizeof(CommandList_struct));
c->cmdindex = -1;
c->err_info = (ErrorInfo_struct *)pci_alloc_consistent( c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
h->pdev, sizeof(ErrorInfo_struct), h->pdev, sizeof(ErrorInfo_struct),
&err_dma_handle); &err_dma_handle);
...@@ -417,6 +421,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool) ...@@ -417,6 +421,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
err_dma_handle = h->errinfo_pool_dhandle err_dma_handle = h->errinfo_pool_dhandle
+ i*sizeof(ErrorInfo_struct); + i*sizeof(ErrorInfo_struct);
h->nr_allocs++; h->nr_allocs++;
c->cmdindex = i;
} }
c->busaddr = (__u32) cmd_dma_handle; c->busaddr = (__u32) cmd_dma_handle;
...@@ -2257,7 +2263,11 @@ static void do_cciss_request(request_queue_t *q) ...@@ -2257,7 +2263,11 @@ static void do_cciss_request(request_queue_t *q)
/* fill in the request */ /* fill in the request */
drv = creq->rq_disk->private_data; drv = creq->rq_disk->private_data;
c->Header.ReplyQueue = 0; // unused in simple mode c->Header.ReplyQueue = 0; // unused in simple mode
c->Header.Tag.lower = c->busaddr; // use the physical address the cmd block for tag /* got command from pool, so use the command block index instead */
/* for direct lookups. */
/* The first 2 bits are reserved for controller error reporting. */
c->Header.Tag.lower = (c->cmdindex << 3);
c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */
c->Header.LUN.LogDev.VolId= drv->LunID; c->Header.LUN.LogDev.VolId= drv->LunID;
c->Header.LUN.LogDev.Mode = 1; c->Header.LUN.LogDev.Mode = 1;
c->Request.CDBLen = 10; // 12 byte commands not in FW yet; c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
...@@ -2332,7 +2342,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -2332,7 +2342,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
ctlr_info_t *h = dev_id; ctlr_info_t *h = dev_id;
CommandList_struct *c; CommandList_struct *c;
unsigned long flags; unsigned long flags;
__u32 a, a1; __u32 a, a1, a2;
int j; int j;
int start_queue = h->next_to_run; int start_queue = h->next_to_run;
...@@ -2350,10 +2360,21 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -2350,10 +2360,21 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
while((a = h->access.command_completed(h)) != FIFO_EMPTY) while((a = h->access.command_completed(h)) != FIFO_EMPTY)
{ {
a1 = a; a1 = a;
if ((a & 0x04)) {
a2 = (a >> 3);
if (a2 >= NR_CMDS) {
printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr);
fail_all_cmds(h->ctlr);
return IRQ_HANDLED;
}
c = h->cmd_pool + a2;
a = c->busaddr;
} else {
a &= ~3; a &= ~3;
if ((c = h->cmpQ) == NULL) if ((c = h->cmpQ) == NULL) {
{ printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1);
printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1);
continue; continue;
} }
while(c->busaddr != a) { while(c->busaddr != a) {
...@@ -2361,6 +2382,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -2361,6 +2382,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
if (c == h->cmpQ) if (c == h->cmpQ)
break; break;
} }
}
/* /*
* If we've found the command, take it off the * If we've found the command, take it off the
* completion Q and free it * completion Q and free it
...@@ -3124,5 +3146,43 @@ static void __exit cciss_cleanup(void) ...@@ -3124,5 +3146,43 @@ static void __exit cciss_cleanup(void)
remove_proc_entry("cciss", proc_root_driver); remove_proc_entry("cciss", proc_root_driver);
} }
static void fail_all_cmds(unsigned long ctlr)
{
/* If we get here, the board is apparently dead. */
ctlr_info_t *h = hba[ctlr];
CommandList_struct *c;
unsigned long flags;
printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr);
h->alive = 0; /* the controller apparently died... */
spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
pci_disable_device(h->pdev); /* Make sure it is really dead. */
/* move everything off the request queue onto the completed queue */
while( (c = h->reqQ) != NULL ) {
removeQ(&(h->reqQ), c);
h->Qdepth--;
addQ (&(h->cmpQ), c);
}
/* Now, fail everything on the completed queue with a HW error */
while( (c = h->cmpQ) != NULL ) {
removeQ(&h->cmpQ, c);
c->err_info->CommandStatus = CMD_HARDWARE_ERR;
if (c->cmd_type == CMD_RWREQ) {
complete_command(h, c, 0);
} else if (c->cmd_type == CMD_IOCTL_PEND)
complete(c->waiting);
#ifdef CONFIG_CISS_SCSI_TAPE
else if (c->cmd_type == CMD_SCSI)
complete_scsi_command(c, 0, 0);
#endif
}
spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
return;
}
module_init(cciss_init); module_init(cciss_init);
module_exit(cciss_cleanup); module_exit(cciss_cleanup);
...@@ -101,6 +101,7 @@ struct ctlr_info ...@@ -101,6 +101,7 @@ struct ctlr_info
#ifdef CONFIG_CISS_SCSI_TAPE #ifdef CONFIG_CISS_SCSI_TAPE
void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
#endif #endif
unsigned char alive;
}; };
/* Defining the diffent access_menthods */ /* Defining the diffent access_menthods */
......
...@@ -226,6 +226,10 @@ typedef struct _ErrorInfo_struct { ...@@ -226,6 +226,10 @@ typedef struct _ErrorInfo_struct {
#define CMD_MSG_DONE 0x04 #define CMD_MSG_DONE 0x04
#define CMD_MSG_TIMEOUT 0x05 #define CMD_MSG_TIMEOUT 0x05
/* This structure needs to be divisible by 8 for new
* indexing method.
*/
#define PADSIZE (sizeof(long) - 4)
typedef struct _CommandList_struct { typedef struct _CommandList_struct {
CommandListHeader_struct Header; CommandListHeader_struct Header;
RequestBlock_struct Request; RequestBlock_struct Request;
...@@ -236,14 +240,14 @@ typedef struct _CommandList_struct { ...@@ -236,14 +240,14 @@ typedef struct _CommandList_struct {
ErrorInfo_struct * err_info; /* pointer to the allocated mem */ ErrorInfo_struct * err_info; /* pointer to the allocated mem */
int ctlr; int ctlr;
int cmd_type; int cmd_type;
long cmdindex;
struct _CommandList_struct *prev; struct _CommandList_struct *prev;
struct _CommandList_struct *next; struct _CommandList_struct *next;
struct request * rq; struct request * rq;
struct completion *waiting; struct completion *waiting;
int retry_count; int retry_count;
#ifdef CONFIG_CISS_SCSI_TAPE
void * scsi_cmd; void * scsi_cmd;
#endif char pad[PADSIZE];
} CommandList_struct; } CommandList_struct;
//Configuration Table Structure //Configuration Table Structure
......
...@@ -93,6 +93,7 @@ struct cciss_scsi_cmd_stack_elem_t { ...@@ -93,6 +93,7 @@ struct cciss_scsi_cmd_stack_elem_t {
CommandList_struct cmd; CommandList_struct cmd;
ErrorInfo_struct Err; ErrorInfo_struct Err;
__u32 busaddr; __u32 busaddr;
__u32 pad;
}; };
#pragma pack() #pragma pack()
......
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