From 072b0518b0f75296443a0df9fe7f25e052e62652 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 29 May 2014 10:53:07 -0500 Subject: [PATCH] hpsa: allocate reply queues individually Now that we can allocate more than 4 reply queues (up to 64) we shouldn't try to make them share the same allocation but should allocate them separately. Signed-off-by: Stephen M. Cameron Reviewed-by: Mike Miller Reviewed-by: Scott Teel Signed-off-by: Christoph Hellwig --- drivers/scsi/hpsa.c | 53 +++++++++++++++++++++++++++------------------ drivers/scsi/hpsa.h | 13 +++++------ 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 87066954a859..b474dbaaa8d0 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -695,7 +695,7 @@ static inline void addQ(struct list_head *list, struct CommandList *c) static inline u32 next_command(struct ctlr_info *h, u8 q) { u32 a; - struct reply_pool *rq = &h->reply_queue[q]; + struct reply_queue_buffer *rq = &h->reply_queue[q]; unsigned long flags; if (h->transMethod & CFGTBL_Trans_io_accel1) @@ -6707,6 +6707,20 @@ static void hpsa_free_irqs_and_disable_msix(struct ctlr_info *h) #endif /* CONFIG_PCI_MSI */ } +static void hpsa_free_reply_queues(struct ctlr_info *h) +{ + int i; + + for (i = 0; i < h->nreply_queues; i++) { + if (!h->reply_queue[i].head) + continue; + pci_free_consistent(h->pdev, h->reply_queue_size, + h->reply_queue[i].head, h->reply_queue[i].busaddr); + h->reply_queue[i].head = NULL; + h->reply_queue[i].busaddr = 0; + } +} + static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h) { hpsa_free_irqs_and_disable_msix(h); @@ -6714,8 +6728,7 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h) hpsa_free_cmd_pool(h); kfree(h->ioaccel1_blockFetchTable); kfree(h->blockFetchTable); - pci_free_consistent(h->pdev, h->reply_pool_size, - h->reply_pool, h->reply_pool_dhandle); + hpsa_free_reply_queues(h); if (h->vaddr) iounmap(h->vaddr); if (h->transtable) @@ -7164,8 +7177,7 @@ static void hpsa_remove_one(struct pci_dev *pdev) pci_free_consistent(h->pdev, h->nr_cmds * sizeof(struct ErrorInfo), h->errinfo_pool, h->errinfo_pool_dhandle); - pci_free_consistent(h->pdev, h->reply_pool_size, - h->reply_pool, h->reply_pool_dhandle); + hpsa_free_reply_queues(h); kfree(h->cmd_pool_bits); kfree(h->blockFetchTable); kfree(h->ioaccel1_blockFetchTable); @@ -7278,7 +7290,8 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) */ /* Controller spec: zero out this buffer. */ - memset(h->reply_pool, 0, h->reply_pool_size); + for (i = 0; i < h->nreply_queues; i++) + memset(h->reply_queue[i].head, 0, h->reply_queue_size); bft[7] = SG_ENTRIES_IN_CMD + 4; calc_bucket_map(bft, ARRAY_SIZE(bft), @@ -7294,8 +7307,7 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) for (i = 0; i < h->nreply_queues; i++) { writel(0, &h->transtable->RepQAddr[i].upper); - writel(h->reply_pool_dhandle + - (h->max_commands * sizeof(u64) * i), + writel(h->reply_queue[i].busaddr, &h->transtable->RepQAddr[i].lower); } @@ -7343,8 +7355,10 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) h->ioaccel1_blockFetchTable); /* initialize all reply queue entries to unused */ - memset(h->reply_pool, (u8) IOACCEL_MODE1_REPLY_UNUSED, - h->reply_pool_size); + for (i = 0; i < h->nreply_queues; i++) + memset(h->reply_queue[i].head, + (u8) IOACCEL_MODE1_REPLY_UNUSED, + h->reply_queue_size); /* set all the constant fields in the accelerator command * frames once at init time to save CPU cycles later. @@ -7500,16 +7514,17 @@ static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) } } - /* TODO, check that this next line h->nreply_queues is correct */ h->nreply_queues = h->msix_vector > 0 ? h->msix_vector : 1; hpsa_get_max_perf_mode_cmds(h); /* Performant mode ring buffer and supporting data structures */ - h->reply_pool_size = h->max_commands * sizeof(u64) * h->nreply_queues; - h->reply_pool = pci_alloc_consistent(h->pdev, h->reply_pool_size, - &(h->reply_pool_dhandle)); + h->reply_queue_size = h->max_commands * sizeof(u64); for (i = 0; i < h->nreply_queues; i++) { - h->reply_queue[i].head = &h->reply_pool[h->max_commands * i]; + h->reply_queue[i].head = pci_alloc_consistent(h->pdev, + h->reply_queue_size, + &(h->reply_queue[i].busaddr)); + if (!h->reply_queue[i].head) + goto clean_up; h->reply_queue[i].size = h->max_commands; h->reply_queue[i].wraparound = 1; /* spec: init to 1 */ h->reply_queue[i].current_entry = 0; @@ -7518,18 +7533,14 @@ static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) /* Need a block fetch table for performant mode */ h->blockFetchTable = kmalloc(((SG_ENTRIES_IN_CMD + 1) * sizeof(u32)), GFP_KERNEL); - - if ((h->reply_pool == NULL) - || (h->blockFetchTable == NULL)) + if (!h->blockFetchTable) goto clean_up; hpsa_enter_performant_mode(h, trans_support); return; clean_up: - if (h->reply_pool) - pci_free_consistent(h->pdev, h->reply_pool_size, - h->reply_pool, h->reply_pool_dhandle); + hpsa_free_reply_queues(h); kfree(h->blockFetchTable); } diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 5ee3e7a9126d..60d72fc3c180 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -57,11 +57,12 @@ struct hpsa_scsi_dev_t { }; -struct reply_pool { +struct reply_queue_buffer { u64 *head; size_t size; u8 wraparound; u32 current_entry; + dma_addr_t busaddr; }; #pragma pack(1) @@ -174,11 +175,9 @@ struct ctlr_info { /* * Performant mode completion buffers */ - u64 *reply_pool; - size_t reply_pool_size; - struct reply_pool reply_queue[MAX_REPLY_QUEUES]; + size_t reply_queue_size; + struct reply_queue_buffer reply_queue[MAX_REPLY_QUEUES]; u8 nreply_queues; - dma_addr_t reply_pool_dhandle; u32 *blockFetchTable; u32 *ioaccel1_blockFetchTable; u32 *ioaccel2_blockFetchTable; @@ -392,7 +391,7 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val) static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q) { - struct reply_pool *rq = &h->reply_queue[q]; + struct reply_queue_buffer *rq = &h->reply_queue[q]; unsigned long flags, register_value = FIFO_EMPTY; /* msi auto clears the interrupt pending bit. */ @@ -507,7 +506,7 @@ static bool SA5_ioaccel_mode1_intr_pending(struct ctlr_info *h) static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q) { u64 register_value; - struct reply_pool *rq = &h->reply_queue[q]; + struct reply_queue_buffer *rq = &h->reply_queue[q]; unsigned long flags; BUG_ON(q >= h->nreply_queues);