diff options
author | Mike Miller <mike.miller@hp.com> | 2005-09-13 04:25:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-13 11:22:30 -0400 |
commit | 33079b21978f478865068ee6a3c5807b6c6ecdbe (patch) | |
tree | 086035c299e4dcc0ab6af6623c53ac72be81b303 | |
parent | ddd474420a0b0dfeda38b6b5f83c7af751235cc3 (diff) |
[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>
-rw-r--r-- | drivers/block/cciss.c | 70 | ||||
-rw-r--r-- | drivers/block/cciss.h | 1 | ||||
-rw-r--r-- | drivers/block/cciss_cmd.h | 8 | ||||
-rw-r--r-- | drivers/block/cciss_scsi.c | 1 |
4 files changed, 73 insertions, 7 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 3c6a6a21d540..a12b95eef18e 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -174,6 +174,8 @@ static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, | |||
174 | unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, | 174 | unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, |
175 | int cmd_type); | 175 | int cmd_type); |
176 | 176 | ||
177 | static void fail_all_cmds(unsigned long ctlr); | ||
178 | |||
177 | #ifdef CONFIG_PROC_FS | 179 | #ifdef CONFIG_PROC_FS |
178 | static int cciss_proc_get_info(char *buffer, char **start, off_t offset, | 180 | static int cciss_proc_get_info(char *buffer, char **start, off_t offset, |
179 | int length, int *eof, void *data); | 181 | int length, int *eof, void *data); |
@@ -387,6 +389,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool) | |||
387 | return NULL; | 389 | return NULL; |
388 | memset(c, 0, sizeof(CommandList_struct)); | 390 | memset(c, 0, sizeof(CommandList_struct)); |
389 | 391 | ||
392 | c->cmdindex = -1; | ||
393 | |||
390 | c->err_info = (ErrorInfo_struct *)pci_alloc_consistent( | 394 | c->err_info = (ErrorInfo_struct *)pci_alloc_consistent( |
391 | h->pdev, sizeof(ErrorInfo_struct), | 395 | h->pdev, sizeof(ErrorInfo_struct), |
392 | &err_dma_handle); | 396 | &err_dma_handle); |
@@ -417,6 +421,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool) | |||
417 | err_dma_handle = h->errinfo_pool_dhandle | 421 | err_dma_handle = h->errinfo_pool_dhandle |
418 | + i*sizeof(ErrorInfo_struct); | 422 | + i*sizeof(ErrorInfo_struct); |
419 | h->nr_allocs++; | 423 | h->nr_allocs++; |
424 | |||
425 | c->cmdindex = i; | ||
420 | } | 426 | } |
421 | 427 | ||
422 | c->busaddr = (__u32) cmd_dma_handle; | 428 | c->busaddr = (__u32) cmd_dma_handle; |
@@ -2257,7 +2263,11 @@ queue: | |||
2257 | /* fill in the request */ | 2263 | /* fill in the request */ |
2258 | drv = creq->rq_disk->private_data; | 2264 | drv = creq->rq_disk->private_data; |
2259 | c->Header.ReplyQueue = 0; // unused in simple mode | 2265 | c->Header.ReplyQueue = 0; // unused in simple mode |
2260 | c->Header.Tag.lower = c->busaddr; // use the physical address the cmd block for tag | 2266 | /* got command from pool, so use the command block index instead */ |
2267 | /* for direct lookups. */ | ||
2268 | /* The first 2 bits are reserved for controller error reporting. */ | ||
2269 | c->Header.Tag.lower = (c->cmdindex << 3); | ||
2270 | c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */ | ||
2261 | c->Header.LUN.LogDev.VolId= drv->LunID; | 2271 | c->Header.LUN.LogDev.VolId= drv->LunID; |
2262 | c->Header.LUN.LogDev.Mode = 1; | 2272 | c->Header.LUN.LogDev.Mode = 1; |
2263 | c->Request.CDBLen = 10; // 12 byte commands not in FW yet; | 2273 | 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 | ctlr_info_t *h = dev_id; | 2342 | ctlr_info_t *h = dev_id; |
2333 | CommandList_struct *c; | 2343 | CommandList_struct *c; |
2334 | unsigned long flags; | 2344 | unsigned long flags; |
2335 | __u32 a, a1; | 2345 | __u32 a, a1, a2; |
2336 | int j; | 2346 | int j; |
2337 | int start_queue = h->next_to_run; | 2347 | int start_queue = h->next_to_run; |
2338 | 2348 | ||
@@ -2350,10 +2360,21 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2350 | while((a = h->access.command_completed(h)) != FIFO_EMPTY) | 2360 | while((a = h->access.command_completed(h)) != FIFO_EMPTY) |
2351 | { | 2361 | { |
2352 | a1 = a; | 2362 | a1 = a; |
2363 | if ((a & 0x04)) { | ||
2364 | a2 = (a >> 3); | ||
2365 | if (a2 >= NR_CMDS) { | ||
2366 | printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr); | ||
2367 | fail_all_cmds(h->ctlr); | ||
2368 | return IRQ_HANDLED; | ||
2369 | } | ||
2370 | |||
2371 | c = h->cmd_pool + a2; | ||
2372 | a = c->busaddr; | ||
2373 | |||
2374 | } else { | ||
2353 | a &= ~3; | 2375 | a &= ~3; |
2354 | if ((c = h->cmpQ) == NULL) | 2376 | if ((c = h->cmpQ) == NULL) { |
2355 | { | 2377 | printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1); |
2356 | printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1); | ||
2357 | continue; | 2378 | continue; |
2358 | } | 2379 | } |
2359 | while(c->busaddr != a) { | 2380 | while(c->busaddr != a) { |
@@ -2361,6 +2382,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2361 | if (c == h->cmpQ) | 2382 | if (c == h->cmpQ) |
2362 | break; | 2383 | break; |
2363 | } | 2384 | } |
2385 | } | ||
2364 | /* | 2386 | /* |
2365 | * If we've found the command, take it off the | 2387 | * If we've found the command, take it off the |
2366 | * completion Q and free it | 2388 | * completion Q and free it |
@@ -3124,5 +3146,43 @@ static void __exit cciss_cleanup(void) | |||
3124 | remove_proc_entry("cciss", proc_root_driver); | 3146 | remove_proc_entry("cciss", proc_root_driver); |
3125 | } | 3147 | } |
3126 | 3148 | ||
3149 | static void fail_all_cmds(unsigned long ctlr) | ||
3150 | { | ||
3151 | /* If we get here, the board is apparently dead. */ | ||
3152 | ctlr_info_t *h = hba[ctlr]; | ||
3153 | CommandList_struct *c; | ||
3154 | unsigned long flags; | ||
3155 | |||
3156 | printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr); | ||
3157 | h->alive = 0; /* the controller apparently died... */ | ||
3158 | |||
3159 | spin_lock_irqsave(CCISS_LOCK(ctlr), flags); | ||
3160 | |||
3161 | pci_disable_device(h->pdev); /* Make sure it is really dead. */ | ||
3162 | |||
3163 | /* move everything off the request queue onto the completed queue */ | ||
3164 | while( (c = h->reqQ) != NULL ) { | ||
3165 | removeQ(&(h->reqQ), c); | ||
3166 | h->Qdepth--; | ||
3167 | addQ (&(h->cmpQ), c); | ||
3168 | } | ||
3169 | |||
3170 | /* Now, fail everything on the completed queue with a HW error */ | ||
3171 | while( (c = h->cmpQ) != NULL ) { | ||
3172 | removeQ(&h->cmpQ, c); | ||
3173 | c->err_info->CommandStatus = CMD_HARDWARE_ERR; | ||
3174 | if (c->cmd_type == CMD_RWREQ) { | ||
3175 | complete_command(h, c, 0); | ||
3176 | } else if (c->cmd_type == CMD_IOCTL_PEND) | ||
3177 | complete(c->waiting); | ||
3178 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
3179 | else if (c->cmd_type == CMD_SCSI) | ||
3180 | complete_scsi_command(c, 0, 0); | ||
3181 | #endif | ||
3182 | } | ||
3183 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); | ||
3184 | return; | ||
3185 | } | ||
3186 | |||
3127 | module_init(cciss_init); | 3187 | module_init(cciss_init); |
3128 | module_exit(cciss_cleanup); | 3188 | module_exit(cciss_cleanup); |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index dec27a961120..ef277baee9fd 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -101,6 +101,7 @@ struct ctlr_info | |||
101 | #ifdef CONFIG_CISS_SCSI_TAPE | 101 | #ifdef CONFIG_CISS_SCSI_TAPE |
102 | void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ | 102 | void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ |
103 | #endif | 103 | #endif |
104 | unsigned char alive; | ||
104 | }; | 105 | }; |
105 | 106 | ||
106 | /* Defining the diffent access_menthods */ | 107 | /* Defining the diffent access_menthods */ |
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index a88a88817623..53fea549ba8b 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h | |||
@@ -226,6 +226,10 @@ typedef struct _ErrorInfo_struct { | |||
226 | #define CMD_MSG_DONE 0x04 | 226 | #define CMD_MSG_DONE 0x04 |
227 | #define CMD_MSG_TIMEOUT 0x05 | 227 | #define CMD_MSG_TIMEOUT 0x05 |
228 | 228 | ||
229 | /* This structure needs to be divisible by 8 for new | ||
230 | * indexing method. | ||
231 | */ | ||
232 | #define PADSIZE (sizeof(long) - 4) | ||
229 | typedef struct _CommandList_struct { | 233 | typedef struct _CommandList_struct { |
230 | CommandListHeader_struct Header; | 234 | CommandListHeader_struct Header; |
231 | RequestBlock_struct Request; | 235 | RequestBlock_struct Request; |
@@ -236,14 +240,14 @@ typedef struct _CommandList_struct { | |||
236 | ErrorInfo_struct * err_info; /* pointer to the allocated mem */ | 240 | ErrorInfo_struct * err_info; /* pointer to the allocated mem */ |
237 | int ctlr; | 241 | int ctlr; |
238 | int cmd_type; | 242 | int cmd_type; |
243 | long cmdindex; | ||
239 | struct _CommandList_struct *prev; | 244 | struct _CommandList_struct *prev; |
240 | struct _CommandList_struct *next; | 245 | struct _CommandList_struct *next; |
241 | struct request * rq; | 246 | struct request * rq; |
242 | struct completion *waiting; | 247 | struct completion *waiting; |
243 | int retry_count; | 248 | int retry_count; |
244 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
245 | void * scsi_cmd; | 249 | void * scsi_cmd; |
246 | #endif | 250 | char pad[PADSIZE]; |
247 | } CommandList_struct; | 251 | } CommandList_struct; |
248 | 252 | ||
249 | //Configuration Table Structure | 253 | //Configuration Table Structure |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index f16e3caed58a..df4afacc75d7 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -93,6 +93,7 @@ struct cciss_scsi_cmd_stack_elem_t { | |||
93 | CommandList_struct cmd; | 93 | CommandList_struct cmd; |
94 | ErrorInfo_struct Err; | 94 | ErrorInfo_struct Err; |
95 | __u32 busaddr; | 95 | __u32 busaddr; |
96 | __u32 pad; | ||
96 | }; | 97 | }; |
97 | 98 | ||
98 | #pragma pack() | 99 | #pragma pack() |