From fe5389c87f13c16cd77d976801c93422d0c05a49 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 6 Jan 2011 14:48:03 -0600 Subject: [SCSI] hpsa: fix board status waiting code After a reset, we should first wait for the board to become "not ready", and then wait for it to become "ready", instead of immediately waiting for it to become "ready", and do this waiting *after* restoring PCI config space registers. Also, only wait 10 secs for board to become "not ready" after a reset (it should quickly become not ready.) Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/scsi/hpsa.h') diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 19586e189f0f..074d237f4497 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -154,12 +154,16 @@ struct ctlr_info { * HPSA_BOARD_READY_ITERATIONS are derived from those. */ #define HPSA_BOARD_READY_WAIT_SECS (120) +#define HPSA_BOARD_NOT_READY_WAIT_SECS (10) #define HPSA_BOARD_READY_POLL_INTERVAL_MSECS (100) #define HPSA_BOARD_READY_POLL_INTERVAL \ ((HPSA_BOARD_READY_POLL_INTERVAL_MSECS * HZ) / 1000) #define HPSA_BOARD_READY_ITERATIONS \ ((HPSA_BOARD_READY_WAIT_SECS * 1000) / \ HPSA_BOARD_READY_POLL_INTERVAL_MSECS) +#define HPSA_BOARD_NOT_READY_ITERATIONS \ + ((HPSA_BOARD_NOT_READY_WAIT_SECS * 1000) / \ + HPSA_BOARD_READY_POLL_INTERVAL_MSECS) #define HPSA_POST_RESET_PAUSE_MSECS (3000) #define HPSA_POST_RESET_NOOP_RETRIES (12) -- cgit v1.2.3 From 9e0fc764eaec082cd2ffcf82568dfdd086935934 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Tue, 15 Feb 2011 15:32:48 -0600 Subject: [SCSI] hpsa: do not re-order commands in internal queues Driver's internal queues should be FIFO, not LIFO. This is a port of an almost identical patch from cciss by Jens Axboe. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 23 +++++++++++------------ drivers/scsi/hpsa.h | 4 ++-- drivers/scsi/hpsa_cmd.h | 2 +- 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers/scsi/hpsa.h') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 959eeb202d92..0f40de2a33de 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -314,9 +314,9 @@ static ssize_t host_show_commands_outstanding(struct device *dev, } /* Enqueuing and dequeuing functions for cmdlists. */ -static inline void addQ(struct hlist_head *list, struct CommandList *c) +static inline void addQ(struct list_head *list, struct CommandList *c) { - hlist_add_head(&c->list, list); + list_add_tail(&c->list, list); } static inline u32 next_command(struct ctlr_info *h) @@ -366,9 +366,9 @@ static void enqueue_cmd_and_start_io(struct ctlr_info *h, static inline void removeQ(struct CommandList *c) { - if (WARN_ON(hlist_unhashed(&c->list))) + if (WARN_ON(list_empty(&c->list))) return; - hlist_del_init(&c->list); + list_del_init(&c->list); } static inline int is_hba_lunid(unsigned char scsi3addr[]) @@ -2228,7 +2228,7 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h) c->cmdindex = i; - INIT_HLIST_NODE(&c->list); + INIT_LIST_HEAD(&c->list); c->busaddr = (u32) cmd_dma_handle; temp64.val = (u64) err_dma_handle; c->ErrDesc.Addr.lower = temp64.val32.lower; @@ -2266,7 +2266,7 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h) } memset(c->err_info, 0, sizeof(*c->err_info)); - INIT_HLIST_NODE(&c->list); + INIT_LIST_HEAD(&c->list); c->busaddr = (u32) cmd_dma_handle; temp64.val = (u64) err_dma_handle; c->ErrDesc.Addr.lower = temp64.val32.lower; @@ -2837,8 +2837,8 @@ static void start_io(struct ctlr_info *h) { struct CommandList *c; - while (!hlist_empty(&h->reqQ)) { - c = hlist_entry(h->reqQ.first, struct CommandList, list); + while (!list_empty(&h->reqQ)) { + c = list_entry(h->reqQ.next, struct CommandList, list); /* can't do anything if fifo is full */ if ((h->access.fifo_full(h))) { dev_warn(&h->pdev->dev, "fifo full\n"); @@ -2929,10 +2929,9 @@ static inline u32 process_nonindexed_cmd(struct ctlr_info *h, { u32 tag; struct CommandList *c = NULL; - struct hlist_node *tmp; tag = hpsa_tag_discard_error_bits(raw_tag); - hlist_for_each_entry(c, tmp, &h->cmpQ, list) { + list_for_each_entry(c, &h->cmpQ, list) { if ((c->busaddr & 0xFFFFFFE0) == (tag & 0xFFFFFFE0)) { finish_cmd(c, raw_tag); return next_command(h); @@ -3761,8 +3760,8 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev, h->pdev = pdev; h->busy_initializing = 1; - INIT_HLIST_HEAD(&h->cmpQ); - INIT_HLIST_HEAD(&h->reqQ); + INIT_LIST_HEAD(&h->cmpQ); + INIT_LIST_HEAD(&h->reqQ); spin_lock_init(&h->lock); spin_lock_init(&h->scan_lock); rc = hpsa_pci_init(h); diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 074d237f4497..e89819342364 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -75,8 +75,8 @@ struct ctlr_info { struct access_method access; /* queue and queue Info */ - struct hlist_head reqQ; - struct hlist_head cmpQ; + struct list_head reqQ; + struct list_head cmpQ; unsigned int Qdepth; unsigned int maxQsinceinit; unsigned int maxSG; diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 7910c1411156..785abdd0333c 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -292,7 +292,7 @@ struct CommandList { struct ctlr_info *h; int cmd_type; long cmdindex; - struct hlist_node list; + struct list_head list; struct request *rq; struct completion *waiting; void *scsi_cmd; -- cgit v1.2.3 From a9a3a2739a44fc05dcaba0d4d36e52dc444c294f Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Tue, 15 Feb 2011 15:32:53 -0600 Subject: [SCSI] hpsa: make hpsa.hpsa_simple_mode=1 module parameter actually work It's not enough to simple avoid putting the board into performant mode, as we have to set up the interrupts differently, etc. When I originally tested this module parameter, I tested it incorrectly without realizing it, and the driver was running in performant mode the whole time unbeknownst to me. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 37 +++++++++++++++++++++++-------------- drivers/scsi/hpsa.h | 1 + 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'drivers/scsi/hpsa.h') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0f40de2a33de..66ccacfffd51 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1186,7 +1186,7 @@ static int hpsa_scsi_detect(struct ctlr_info *h) sh->sg_tablesize = h->maxsgentries; h->scsi_host = sh; sh->hostdata[0] = (unsigned long) h; - sh->irq = h->intr[PERF_MODE_INT]; + sh->irq = h->intr[h->intr_mode]; sh->unique_id = sh->irq; error = scsi_add_host(sh, &h->pdev->dev); if (error) @@ -2902,10 +2902,14 @@ static inline u32 hpsa_tag_to_index(u32 tag) return tag >> DIRECT_LOOKUP_SHIFT; } -static inline u32 hpsa_tag_discard_error_bits(u32 tag) + +static inline u32 hpsa_tag_discard_error_bits(struct ctlr_info *h, u32 tag) { -#define HPSA_ERROR_BITS 0x03 - return tag & ~HPSA_ERROR_BITS; +#define HPSA_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1) +#define HPSA_SIMPLE_ERROR_BITS 0x03 + if (unlikely(h->transMethod != CFGTBL_Trans_Performant)) + return tag & ~HPSA_SIMPLE_ERROR_BITS; + return tag & ~HPSA_PERF_ERROR_BITS; } /* process completion of an indexed ("direct lookup") command */ @@ -2930,7 +2934,7 @@ static inline u32 process_nonindexed_cmd(struct ctlr_info *h, u32 tag; struct CommandList *c = NULL; - tag = hpsa_tag_discard_error_bits(raw_tag); + tag = hpsa_tag_discard_error_bits(h, raw_tag); list_for_each_entry(c, &h->cmpQ, list) { if ((c->busaddr & 0xFFFFFFE0) == (tag & 0xFFFFFFE0)) { finish_cmd(c, raw_tag); @@ -2981,7 +2985,10 @@ static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id) return IRQ_HANDLED; } -/* Send a message CDB to the firmware. */ +/* Send a message CDB to the firmware. Careful, this only works + * in simple mode, not performant mode due to the tag lookup. + * We only ever use this immediately after a controller reset. + */ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode, unsigned char type) { @@ -3047,7 +3054,7 @@ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode, for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) { tag = readl(vaddr + SA5_REPLY_PORT_OFFSET); - if (hpsa_tag_discard_error_bits(tag) == paddr32) + if ((tag & ~HPSA_SIMPLE_ERROR_BITS) == paddr32) break; msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS); } @@ -3379,7 +3386,7 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h) default_int_mode: #endif /* CONFIG_PCI_MSI */ /* if we get here we're going to use the default interrupt mode */ - h->intr[PERF_MODE_INT] = h->pdev->irq; + h->intr[h->intr_mode] = h->pdev->irq; } static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id) @@ -3760,6 +3767,8 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev, h->pdev = pdev; h->busy_initializing = 1; + h->intr_mode = hpsa_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT; + printk(KERN_WARNING "hpsa_simple_mode is %d\n", hpsa_simple_mode); INIT_LIST_HEAD(&h->cmpQ); INIT_LIST_HEAD(&h->reqQ); spin_lock_init(&h->lock); @@ -3790,20 +3799,20 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev, h->access.set_intr_mask(h, HPSA_INTR_OFF); if (h->msix_vector || h->msi_vector) - rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr_msi, + rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_msi, IRQF_DISABLED, h->devname, h); else - rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr_intx, + rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_intx, IRQF_DISABLED, h->devname, h); if (rc) { dev_err(&pdev->dev, "unable to get irq %d for %s\n", - h->intr[PERF_MODE_INT], h->devname); + h->intr[h->intr_mode], h->devname); goto clean2; } dev_info(&pdev->dev, "%s: <0x%x> at IRQ %d%s using DAC\n", h->devname, pdev->device, - h->intr[PERF_MODE_INT], dac ? "" : " not"); + h->intr[h->intr_mode], dac ? "" : " not"); h->cmd_pool_bits = kmalloc(((h->nr_cmds + BITS_PER_LONG - @@ -3854,7 +3863,7 @@ clean4: h->nr_cmds * sizeof(struct ErrorInfo), h->errinfo_pool, h->errinfo_pool_dhandle); - free_irq(h->intr[PERF_MODE_INT], h); + free_irq(h->intr[h->intr_mode], h); clean2: clean1: h->busy_initializing = 0; @@ -3898,7 +3907,7 @@ static void hpsa_shutdown(struct pci_dev *pdev) */ hpsa_flush_cache(h); h->access.set_intr_mask(h, HPSA_INTR_OFF); - free_irq(h->intr[PERF_MODE_INT], h); + free_irq(h->intr[h->intr_mode], h); #ifdef CONFIG_PCI_MSI if (h->msix_vector) pci_disable_msix(h->pdev); diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index e89819342364..621a1530054a 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -72,6 +72,7 @@ struct ctlr_info { unsigned int intr[4]; unsigned int msix_vector; unsigned int msi_vector; + int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ struct access_method access; /* queue and queue Info */ -- cgit v1.2.3