Skip to content

Commit

Permalink
cciss: switch to using hlist for command list management
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jens Axboe committed Dec 29, 2008
1 parent 7c0990c commit 8a3173d
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 46 deletions.
72 changes: 30 additions & 42 deletions drivers/block/cciss.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -2548,22 +2535,23 @@ 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");
break;
}

/* 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);
}
}

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -2985,25 +2973,21 @@ 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;
}
}
/*
* 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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions drivers/block/cciss.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions drivers/block/cciss_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 8a3173d

Please sign in to comment.