aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2008-11-20 03:46:09 -0500
committerJens Axboe <jens.axboe@oracle.com>2008-12-29 02:28:43 -0500
commit8a3173de4ab4cdacc43675dc5c077f9a5bf17f5f (patch)
treee1998a856a09c805c588740c8c83d50dd9663c40 /drivers/block
parent7c0990c7ee988aa193abbb7da3faeb9279146dbf (diff)
cciss: switch to using hlist for command list management
This both cleans up the code and also helps detect the spurious case of a command attempted being removed from a queue it doesn't belong to. Acked-by: Mike Miller <mike.miller@hp.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/cciss.c72
-rw-r--r--drivers/block/cciss.h4
-rw-r--r--drivers/block/cciss_cmd.h3
3 files changed, 33 insertions, 46 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 9f7c543cc04b..4e07b5ca847c 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -215,31 +215,17 @@ static struct block_device_operations cciss_fops = {
215/* 215/*
216 * Enqueuing and dequeuing functions for cmdlists. 216 * Enqueuing and dequeuing functions for cmdlists.
217 */ 217 */
218static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c) 218static inline void addQ(struct hlist_head *list, CommandList_struct *c)
219{ 219{
220 if (*Qptr == NULL) { 220 hlist_add_head(&c->list, list);
221 *Qptr = c;
222 c->next = c->prev = c;
223 } else {
224 c->prev = (*Qptr)->prev;
225 c->next = (*Qptr);
226 (*Qptr)->prev->next = c;
227 (*Qptr)->prev = c;
228 }
229} 221}
230 222
231static inline CommandList_struct *removeQ(CommandList_struct **Qptr, 223static inline void removeQ(CommandList_struct *c)
232 CommandList_struct *c)
233{ 224{
234 if (c && c->next != c) { 225 if (WARN_ON(hlist_unhashed(&c->list)))
235 if (*Qptr == c) 226 return;
236 *Qptr = c->next; 227
237 c->prev->next = c->next; 228 hlist_del_init(&c->list);
238 c->next->prev = c->prev;
239 } else {
240 *Qptr = NULL;
241 }
242 return c;
243} 229}
244 230
245#include "cciss_scsi.c" /* For SCSI tape support */ 231#include "cciss_scsi.c" /* For SCSI tape support */
@@ -506,6 +492,7 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool)
506 c->cmdindex = i; 492 c->cmdindex = i;
507 } 493 }
508 494
495 INIT_HLIST_NODE(&c->list);
509 c->busaddr = (__u32) cmd_dma_handle; 496 c->busaddr = (__u32) cmd_dma_handle;
510 temp64.val = (__u64) err_dma_handle; 497 temp64.val = (__u64) err_dma_handle;
511 c->ErrDesc.Addr.lower = temp64.val32.lower; 498 c->ErrDesc.Addr.lower = temp64.val32.lower;
@@ -2548,7 +2535,8 @@ static void start_io(ctlr_info_t *h)
2548{ 2535{
2549 CommandList_struct *c; 2536 CommandList_struct *c;
2550 2537
2551 while ((c = h->reqQ) != NULL) { 2538 while (!hlist_empty(&h->reqQ)) {
2539 c = hlist_entry(h->reqQ.first, CommandList_struct, list);
2552 /* can't do anything if fifo is full */ 2540 /* can't do anything if fifo is full */
2553 if ((h->access.fifo_full(h))) { 2541 if ((h->access.fifo_full(h))) {
2554 printk(KERN_WARNING "cciss: fifo full\n"); 2542 printk(KERN_WARNING "cciss: fifo full\n");
@@ -2556,14 +2544,14 @@ static void start_io(ctlr_info_t *h)
2556 } 2544 }
2557 2545
2558 /* Get the first entry from the Request Q */ 2546 /* Get the first entry from the Request Q */
2559 removeQ(&(h->reqQ), c); 2547 removeQ(c);
2560 h->Qdepth--; 2548 h->Qdepth--;
2561 2549
2562 /* Tell the controller execute command */ 2550 /* Tell the controller execute command */
2563 h->access.submit_command(h, c); 2551 h->access.submit_command(h, c);
2564 2552
2565 /* Put job onto the completed Q */ 2553 /* Put job onto the completed Q */
2566 addQ(&(h->cmpQ), c); 2554 addQ(&h->cmpQ, c);
2567 } 2555 }
2568} 2556}
2569 2557
@@ -2576,7 +2564,7 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
2576 memset(c->err_info, 0, sizeof(ErrorInfo_struct)); 2564 memset(c->err_info, 0, sizeof(ErrorInfo_struct));
2577 2565
2578 /* add it to software queue and then send it to the controller */ 2566 /* add it to software queue and then send it to the controller */
2579 addQ(&(h->reqQ), c); 2567 addQ(&h->reqQ, c);
2580 h->Qdepth++; 2568 h->Qdepth++;
2581 if (h->Qdepth > h->maxQsinceinit) 2569 if (h->Qdepth > h->maxQsinceinit)
2582 h->maxQsinceinit = h->Qdepth; 2570 h->maxQsinceinit = h->Qdepth;
@@ -2897,7 +2885,7 @@ static void do_cciss_request(struct request_queue *q)
2897 2885
2898 spin_lock_irq(q->queue_lock); 2886 spin_lock_irq(q->queue_lock);
2899 2887
2900 addQ(&(h->reqQ), c); 2888 addQ(&h->reqQ, c);
2901 h->Qdepth++; 2889 h->Qdepth++;
2902 if (h->Qdepth > h->maxQsinceinit) 2890 if (h->Qdepth > h->maxQsinceinit)
2903 h->maxQsinceinit = h->Qdepth; 2891 h->maxQsinceinit = h->Qdepth;
@@ -2985,16 +2973,12 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
2985 a = c->busaddr; 2973 a = c->busaddr;
2986 2974
2987 } else { 2975 } else {
2976 struct hlist_node *tmp;
2977
2988 a &= ~3; 2978 a &= ~3;
2989 if ((c = h->cmpQ) == NULL) { 2979 c = NULL;
2990 printk(KERN_WARNING 2980 hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
2991 "cciss: Completion of %08x ignored\n", 2981 if (c->busaddr == a)
2992 a1);
2993 continue;
2994 }
2995 while (c->busaddr != a) {
2996 c = c->next;
2997 if (c == h->cmpQ)
2998 break; 2982 break;
2999 } 2983 }
3000 } 2984 }
@@ -3002,8 +2986,8 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
3002 * If we've found the command, take it off the 2986 * If we've found the command, take it off the
3003 * completion Q and free it 2987 * completion Q and free it
3004 */ 2988 */
3005 if (c->busaddr == a) { 2989 if (c && c->busaddr == a) {
3006 removeQ(&h->cmpQ, c); 2990 removeQ(c);
3007 if (c->cmd_type == CMD_RWREQ) { 2991 if (c->cmd_type == CMD_RWREQ) {
3008 complete_command(h, c, 0); 2992 complete_command(h, c, 0);
3009 } else if (c->cmd_type == CMD_IOCTL_PEND) { 2993 } else if (c->cmd_type == CMD_IOCTL_PEND) {
@@ -3423,6 +3407,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
3423 return -1; 3407 return -1;
3424 3408
3425 hba[i]->busy_initializing = 1; 3409 hba[i]->busy_initializing = 1;
3410 INIT_HLIST_HEAD(&hba[i]->cmpQ);
3411 INIT_HLIST_HEAD(&hba[i]->reqQ);
3426 3412
3427 if (cciss_pci_init(hba[i], pdev) != 0) 3413 if (cciss_pci_init(hba[i], pdev) != 0)
3428 goto clean1; 3414 goto clean1;
@@ -3730,15 +3716,17 @@ static void fail_all_cmds(unsigned long ctlr)
3730 pci_disable_device(h->pdev); /* Make sure it is really dead. */ 3716 pci_disable_device(h->pdev); /* Make sure it is really dead. */
3731 3717
3732 /* move everything off the request queue onto the completed queue */ 3718 /* move everything off the request queue onto the completed queue */
3733 while ((c = h->reqQ) != NULL) { 3719 while (!hlist_empty(&h->reqQ)) {
3734 removeQ(&(h->reqQ), c); 3720 c = hlist_entry(h->reqQ.first, CommandList_struct, list);
3721 removeQ(c);
3735 h->Qdepth--; 3722 h->Qdepth--;
3736 addQ(&(h->cmpQ), c); 3723 addQ(&h->cmpQ, c);
3737 } 3724 }
3738 3725
3739 /* Now, fail everything on the completed queue with a HW error */ 3726 /* Now, fail everything on the completed queue with a HW error */
3740 while ((c = h->cmpQ) != NULL) { 3727 while (!hlist_empty(&h->cmpQ)) {
3741 removeQ(&h->cmpQ, c); 3728 c = hlist_entry(h->cmpQ.first, CommandList_struct, list);
3729 removeQ(c);
3742 c->err_info->CommandStatus = CMD_HARDWARE_ERR; 3730 c->err_info->CommandStatus = CMD_HARDWARE_ERR;
3743 if (c->cmd_type == CMD_RWREQ) { 3731 if (c->cmd_type == CMD_RWREQ) {
3744 complete_command(h, c, 0); 3732 complete_command(h, c, 0);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 24a7efa993ab..15e2b84734e3 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -89,8 +89,8 @@ struct ctlr_info
89 struct access_method access; 89 struct access_method access;
90 90
91 /* queue and queue Info */ 91 /* queue and queue Info */
92 CommandList_struct *reqQ; 92 struct hlist_head reqQ;
93 CommandList_struct *cmpQ; 93 struct hlist_head cmpQ;
94 unsigned int Qdepth; 94 unsigned int Qdepth;
95 unsigned int maxQsinceinit; 95 unsigned int maxQsinceinit;
96 unsigned int maxSG; 96 unsigned int maxSG;
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index 43bf5593b59b..24e22dea1a99 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -265,8 +265,7 @@ typedef struct _CommandList_struct {
265 int ctlr; 265 int ctlr;
266 int cmd_type; 266 int cmd_type;
267 long cmdindex; 267 long cmdindex;
268 struct _CommandList_struct *prev; 268 struct hlist_node list;
269 struct _CommandList_struct *next;
270 struct request * rq; 269 struct request * rq;
271 struct completion *waiting; 270 struct completion *waiting;
272 int retry_count; 271 int retry_count;