Skip to content

Commit

Permalink
[PATCH] cciss: direct lookup for command completions
Browse files Browse the repository at this point in the history
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: Don Brace <dab@hp.com>
Signed-off-by: Mike Miller <mike.miller@hp.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Mike Miller authored and Linus Torvalds committed Sep 13, 2005
1 parent ddd4744 commit 33079b2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 7 deletions.
70 changes: 65 additions & 5 deletions drivers/block/cciss.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
int cmd_type);

static void fail_all_cmds(unsigned long ctlr);

#ifdef CONFIG_PROC_FS
static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
int length, int *eof, void *data);
Expand Down Expand Up @@ -387,6 +389,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
return NULL;
memset(c, 0, sizeof(CommandList_struct));

c->cmdindex = -1;

c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
h->pdev, sizeof(ErrorInfo_struct),
&err_dma_handle);
Expand Down Expand Up @@ -417,6 +421,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
err_dma_handle = h->errinfo_pool_dhandle
+ i*sizeof(ErrorInfo_struct);
h->nr_allocs++;

c->cmdindex = i;
}

c->busaddr = (__u32) cmd_dma_handle;
Expand Down Expand Up @@ -2257,7 +2263,11 @@ static void do_cciss_request(request_queue_t *q)
/* fill in the request */
drv = creq->rq_disk->private_data;
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.Mode = 1;
c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
Expand Down Expand Up @@ -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;
CommandList_struct *c;
unsigned long flags;
__u32 a, a1;
__u32 a, a1, a2;
int j;
int start_queue = h->next_to_run;

Expand All @@ -2350,17 +2360,29 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
while((a = h->access.command_completed(h)) != FIFO_EMPTY)
{
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;
if ((c = h->cmpQ) == NULL)
{
printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1);
if ((c = h->cmpQ) == NULL) {
printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1);
continue;
}
while(c->busaddr != a) {
c = c->next;
if (c == h->cmpQ)
break;
}
}
/*
* If we've found the command, take it off the
* completion Q and free it
Expand Down Expand Up @@ -3124,5 +3146,43 @@ static void __exit cciss_cleanup(void)
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_exit(cciss_cleanup);
1 change: 1 addition & 0 deletions drivers/block/cciss.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ struct ctlr_info
#ifdef CONFIG_CISS_SCSI_TAPE
void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
#endif
unsigned char alive;
};

/* Defining the diffent access_menthods */
Expand Down
8 changes: 6 additions & 2 deletions drivers/block/cciss_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ typedef struct _ErrorInfo_struct {
#define CMD_MSG_DONE 0x04
#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 {
CommandListHeader_struct Header;
RequestBlock_struct Request;
Expand All @@ -236,14 +240,14 @@ typedef struct _CommandList_struct {
ErrorInfo_struct * err_info; /* pointer to the allocated mem */
int ctlr;
int cmd_type;
long cmdindex;
struct _CommandList_struct *prev;
struct _CommandList_struct *next;
struct request * rq;
struct completion *waiting;
int retry_count;
#ifdef CONFIG_CISS_SCSI_TAPE
void * scsi_cmd;
#endif
char pad[PADSIZE];
} CommandList_struct;

//Configuration Table Structure
Expand Down
1 change: 1 addition & 0 deletions drivers/block/cciss_scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ struct cciss_scsi_cmd_stack_elem_t {
CommandList_struct cmd;
ErrorInfo_struct Err;
__u32 busaddr;
__u32 pad;
};

#pragma pack()
Expand Down

0 comments on commit 33079b2

Please sign in to comment.