mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-18 18:43:59 +08:00
[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: 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>
This commit is contained in:
parent
ddd474420a
commit
33079b2197
@ -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)
|
|||||||
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)
|
|||||||
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 @@ queue:
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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
|
|||||||
#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 {
|
|||||||
#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 {
|
|||||||
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 {
|
|||||||
CommandList_struct cmd;
|
CommandList_struct cmd;
|
||||||
ErrorInfo_struct Err;
|
ErrorInfo_struct Err;
|
||||||
__u32 busaddr;
|
__u32 busaddr;
|
||||||
|
__u32 pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
Loading…
Reference in New Issue
Block a user