From 8a3173de4ab4cdacc43675dc5c077f9a5bf17f5f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 20 Nov 2008 09:46:09 +0100 Subject: [PATCH] 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 Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 72 ++++++++++++++++----------------------- drivers/block/cciss.h | 4 +-- drivers/block/cciss_cmd.h | 3 +- 3 files changed, 33 insertions(+), 46 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 9f7c543cc04..4e07b5ca847 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -215,31 +215,17 @@ static struct block_device_operations cciss_fops = { /* * Enqueuing and dequeuing functions for cmdlists. */ -static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c) +static inline void addQ(struct hlist_head *list, CommandList_struct *c) { - if (*Qptr == NULL) { - *Qptr = c; - c->next = c->prev = c; - } else { - c->prev = (*Qptr)->prev; - c->next = (*Qptr); - (*Qptr)->prev->next = c; - (*Qptr)->prev = c; - } + hlist_add_head(&c->list, list); } -static inline CommandList_struct *removeQ(CommandList_struct **Qptr, - CommandList_struct *c) +static inline void removeQ(CommandList_struct *c) { - if (c && c->next != c) { - if (*Qptr == c) - *Qptr = c->next; - c->prev->next = c->next; - c->next->prev = c->prev; - } else { - *Qptr = NULL; - } - return c; + if (WARN_ON(hlist_unhashed(&c->list))) + return; + + hlist_del_init(&c->list); } #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) c->cmdindex = i; } + INIT_HLIST_NODE(&c->list); c->busaddr = (__u32) cmd_dma_handle; temp64.val = (__u64) err_dma_handle; c->ErrDesc.Addr.lower = temp64.val32.lower; @@ -2548,7 +2535,8 @@ static void start_io(ctlr_info_t *h) { CommandList_struct *c; - while ((c = h->reqQ) != NULL) { + while (!hlist_empty(&h->reqQ)) { + c = hlist_entry(h->reqQ.first, CommandList_struct, list); /* can't do anything if fifo is full */ if ((h->access.fifo_full(h))) { printk(KERN_WARNING "cciss: fifo full\n"); @@ -2556,14 +2544,14 @@ static void start_io(ctlr_info_t *h) } /* Get the first entry from the Request Q */ - removeQ(&(h->reqQ), c); + removeQ(c); h->Qdepth--; /* Tell the controller execute command */ h->access.submit_command(h, c); /* Put job onto the completed Q */ - addQ(&(h->cmpQ), c); + addQ(&h->cmpQ, c); } } @@ -2576,7 +2564,7 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c) memset(c->err_info, 0, sizeof(ErrorInfo_struct)); /* add it to software queue and then send it to the controller */ - addQ(&(h->reqQ), c); + addQ(&h->reqQ, c); h->Qdepth++; if (h->Qdepth > h->maxQsinceinit) h->maxQsinceinit = h->Qdepth; @@ -2897,7 +2885,7 @@ static void do_cciss_request(struct request_queue *q) spin_lock_irq(q->queue_lock); - addQ(&(h->reqQ), c); + addQ(&h->reqQ, c); h->Qdepth++; if (h->Qdepth > h->maxQsinceinit) h->maxQsinceinit = h->Qdepth; @@ -2985,16 +2973,12 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id) a = c->busaddr; } else { + struct hlist_node *tmp; + a &= ~3; - 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) + c = NULL; + hlist_for_each_entry(c, tmp, &h->cmpQ, list) { + if (c->busaddr == a) break; } } @@ -3002,8 +2986,8 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id) * If we've found the command, take it off the * completion Q and free it */ - if (c->busaddr == a) { - removeQ(&h->cmpQ, c); + if (c && c->busaddr == a) { + removeQ(c); if (c->cmd_type == CMD_RWREQ) { complete_command(h, c, 0); } else if (c->cmd_type == CMD_IOCTL_PEND) { @@ -3423,6 +3407,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, return -1; hba[i]->busy_initializing = 1; + INIT_HLIST_HEAD(&hba[i]->cmpQ); + INIT_HLIST_HEAD(&hba[i]->reqQ); if (cciss_pci_init(hba[i], pdev) != 0) goto clean1; @@ -3730,15 +3716,17 @@ static void fail_all_cmds(unsigned long ctlr) 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); + while (!hlist_empty(&h->reqQ)) { + c = hlist_entry(h->reqQ.first, CommandList_struct, list); + removeQ(c); h->Qdepth--; - addQ(&(h->cmpQ), c); + addQ(&h->cmpQ, c); } /* Now, fail everything on the completed queue with a HW error */ - while ((c = h->cmpQ) != NULL) { - removeQ(&h->cmpQ, c); + while (!hlist_empty(&h->cmpQ)) { + c = hlist_entry(h->cmpQ.first, CommandList_struct, list); + removeQ(c); c->err_info->CommandStatus = CMD_HARDWARE_ERR; if (c->cmd_type == CMD_RWREQ) { complete_command(h, c, 0); diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 24a7efa993a..15e2b84734e 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -89,8 +89,8 @@ struct ctlr_info struct access_method access; /* queue and queue Info */ - CommandList_struct *reqQ; - CommandList_struct *cmpQ; + struct hlist_head reqQ; + struct hlist_head cmpQ; unsigned int Qdepth; unsigned int maxQsinceinit; unsigned int maxSG; diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index 43bf5593b59..24e22dea1a9 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h @@ -265,8 +265,7 @@ typedef struct _CommandList_struct { int ctlr; int cmd_type; long cmdindex; - struct _CommandList_struct *prev; - struct _CommandList_struct *next; + struct hlist_node list; struct request * rq; struct completion *waiting; int retry_count; -- 2.46.0