mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
7c0990c7ee
commit
8a3173de4a
|
@ -215,31 +215,17 @@ static struct block_device_operations cciss_fops = {
|
||||||
/*
|
/*
|
||||||
* Enqueuing and dequeuing functions for cmdlists.
|
* 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) {
|
hlist_add_head(&c->list, list);
|
||||||
*Qptr = c;
|
|
||||||
c->next = c->prev = c;
|
|
||||||
} else {
|
|
||||||
c->prev = (*Qptr)->prev;
|
|
||||||
c->next = (*Qptr);
|
|
||||||
(*Qptr)->prev->next = c;
|
|
||||||
(*Qptr)->prev = c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
|
static inline void removeQ(CommandList_struct *c)
|
||||||
CommandList_struct *c)
|
|
||||||
{
|
{
|
||||||
if (c && c->next != c) {
|
if (WARN_ON(hlist_unhashed(&c->list)))
|
||||||
if (*Qptr == c)
|
return;
|
||||||
*Qptr = c->next;
|
|
||||||
c->prev->next = c->next;
|
hlist_del_init(&c->list);
|
||||||
c->next->prev = c->prev;
|
|
||||||
} else {
|
|
||||||
*Qptr = NULL;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "cciss_scsi.c" /* For SCSI tape support */
|
#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;
|
c->cmdindex = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INIT_HLIST_NODE(&c->list);
|
||||||
c->busaddr = (__u32) cmd_dma_handle;
|
c->busaddr = (__u32) cmd_dma_handle;
|
||||||
temp64.val = (__u64) err_dma_handle;
|
temp64.val = (__u64) err_dma_handle;
|
||||||
c->ErrDesc.Addr.lower = temp64.val32.lower;
|
c->ErrDesc.Addr.lower = temp64.val32.lower;
|
||||||
|
@ -2548,7 +2535,8 @@ static void start_io(ctlr_info_t *h)
|
||||||
{
|
{
|
||||||
CommandList_struct *c;
|
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 */
|
/* can't do anything if fifo is full */
|
||||||
if ((h->access.fifo_full(h))) {
|
if ((h->access.fifo_full(h))) {
|
||||||
printk(KERN_WARNING "cciss: fifo full\n");
|
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 */
|
/* Get the first entry from the Request Q */
|
||||||
removeQ(&(h->reqQ), c);
|
removeQ(c);
|
||||||
h->Qdepth--;
|
h->Qdepth--;
|
||||||
|
|
||||||
/* Tell the controller execute command */
|
/* Tell the controller execute command */
|
||||||
h->access.submit_command(h, c);
|
h->access.submit_command(h, c);
|
||||||
|
|
||||||
/* Put job onto the completed Q */
|
/* 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));
|
memset(c->err_info, 0, sizeof(ErrorInfo_struct));
|
||||||
|
|
||||||
/* add it to software queue and then send it to the controller */
|
/* add it to software queue and then send it to the controller */
|
||||||
addQ(&(h->reqQ), c);
|
addQ(&h->reqQ, c);
|
||||||
h->Qdepth++;
|
h->Qdepth++;
|
||||||
if (h->Qdepth > h->maxQsinceinit)
|
if (h->Qdepth > h->maxQsinceinit)
|
||||||
h->maxQsinceinit = h->Qdepth;
|
h->maxQsinceinit = h->Qdepth;
|
||||||
|
@ -2897,7 +2885,7 @@ static void do_cciss_request(struct request_queue *q)
|
||||||
|
|
||||||
spin_lock_irq(q->queue_lock);
|
spin_lock_irq(q->queue_lock);
|
||||||
|
|
||||||
addQ(&(h->reqQ), c);
|
addQ(&h->reqQ, c);
|
||||||
h->Qdepth++;
|
h->Qdepth++;
|
||||||
if (h->Qdepth > h->maxQsinceinit)
|
if (h->Qdepth > h->maxQsinceinit)
|
||||||
h->maxQsinceinit = h->Qdepth;
|
h->maxQsinceinit = h->Qdepth;
|
||||||
|
@ -2985,16 +2973,12 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
|
||||||
a = c->busaddr;
|
a = c->busaddr;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
struct hlist_node *tmp;
|
||||||
|
|
||||||
a &= ~3;
|
a &= ~3;
|
||||||
if ((c = h->cmpQ) == NULL) {
|
c = NULL;
|
||||||
printk(KERN_WARNING
|
hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
|
||||||
"cciss: Completion of %08x ignored\n",
|
if (c->busaddr == a)
|
||||||
a1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
while (c->busaddr != a) {
|
|
||||||
c = c->next;
|
|
||||||
if (c == h->cmpQ)
|
|
||||||
break;
|
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
|
* If we've found the command, take it off the
|
||||||
* completion Q and free it
|
* completion Q and free it
|
||||||
*/
|
*/
|
||||||
if (c->busaddr == a) {
|
if (c && c->busaddr == a) {
|
||||||
removeQ(&h->cmpQ, c);
|
removeQ(c);
|
||||||
if (c->cmd_type == CMD_RWREQ) {
|
if (c->cmd_type == CMD_RWREQ) {
|
||||||
complete_command(h, c, 0);
|
complete_command(h, c, 0);
|
||||||
} else if (c->cmd_type == CMD_IOCTL_PEND) {
|
} else if (c->cmd_type == CMD_IOCTL_PEND) {
|
||||||
|
@ -3423,6 +3407,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
hba[i]->busy_initializing = 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)
|
if (cciss_pci_init(hba[i], pdev) != 0)
|
||||||
goto clean1;
|
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. */
|
pci_disable_device(h->pdev); /* Make sure it is really dead. */
|
||||||
|
|
||||||
/* move everything off the request queue onto the completed queue */
|
/* move everything off the request queue onto the completed queue */
|
||||||
while ((c = h->reqQ) != NULL) {
|
while (!hlist_empty(&h->reqQ)) {
|
||||||
removeQ(&(h->reqQ), c);
|
c = hlist_entry(h->reqQ.first, CommandList_struct, list);
|
||||||
|
removeQ(c);
|
||||||
h->Qdepth--;
|
h->Qdepth--;
|
||||||
addQ(&(h->cmpQ), c);
|
addQ(&h->cmpQ, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now, fail everything on the completed queue with a HW error */
|
/* Now, fail everything on the completed queue with a HW error */
|
||||||
while ((c = h->cmpQ) != NULL) {
|
while (!hlist_empty(&h->cmpQ)) {
|
||||||
removeQ(&h->cmpQ, c);
|
c = hlist_entry(h->cmpQ.first, CommandList_struct, list);
|
||||||
|
removeQ(c);
|
||||||
c->err_info->CommandStatus = CMD_HARDWARE_ERR;
|
c->err_info->CommandStatus = CMD_HARDWARE_ERR;
|
||||||
if (c->cmd_type == CMD_RWREQ) {
|
if (c->cmd_type == CMD_RWREQ) {
|
||||||
complete_command(h, c, 0);
|
complete_command(h, c, 0);
|
||||||
|
|
|
@ -89,8 +89,8 @@ struct ctlr_info
|
||||||
struct access_method access;
|
struct access_method access;
|
||||||
|
|
||||||
/* queue and queue Info */
|
/* queue and queue Info */
|
||||||
CommandList_struct *reqQ;
|
struct hlist_head reqQ;
|
||||||
CommandList_struct *cmpQ;
|
struct hlist_head cmpQ;
|
||||||
unsigned int Qdepth;
|
unsigned int Qdepth;
|
||||||
unsigned int maxQsinceinit;
|
unsigned int maxQsinceinit;
|
||||||
unsigned int maxSG;
|
unsigned int maxSG;
|
||||||
|
|
|
@ -265,8 +265,7 @@ typedef struct _CommandList_struct {
|
||||||
int ctlr;
|
int ctlr;
|
||||||
int cmd_type;
|
int cmd_type;
|
||||||
long cmdindex;
|
long cmdindex;
|
||||||
struct _CommandList_struct *prev;
|
struct hlist_node list;
|
||||||
struct _CommandList_struct *next;
|
|
||||||
struct request * rq;
|
struct request * rq;
|
||||||
struct completion *waiting;
|
struct completion *waiting;
|
||||||
int retry_count;
|
int retry_count;
|
||||||
|
|
Loading…
Reference in New Issue