Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a3173de authored by Jens Axboe's avatar Jens Axboe
Browse files

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: default avatarMike Miller <mike.miller@hp.com>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 7c0990c7
Loading
Loading
Loading
Loading
+30 −42
Original line number Diff line number Diff line
@@ -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);
+2 −2
Original line number Diff line number Diff line
@@ -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;
+1 −2
Original line number Diff line number Diff line
@@ -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;