aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_mem.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c101
1 files changed, 97 insertions, 4 deletions
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index ec3bbbde6f7..3594c469494 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig * 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -38,10 +38,13 @@
38#define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */ 38#define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */
39#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */ 39#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */
40 40
41
42
41int 43int
42lpfc_mem_alloc(struct lpfc_hba * phba) 44lpfc_mem_alloc(struct lpfc_hba * phba)
43{ 45{
44 struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 46 struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
47 int longs;
45 int i; 48 int i;
46 49
47 phba->lpfc_scsi_dma_buf_pool = pci_pool_create("lpfc_scsi_dma_buf_pool", 50 phba->lpfc_scsi_dma_buf_pool = pci_pool_create("lpfc_scsi_dma_buf_pool",
@@ -80,10 +83,27 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
80 if (!phba->nlp_mem_pool) 83 if (!phba->nlp_mem_pool)
81 goto fail_free_mbox_pool; 84 goto fail_free_mbox_pool;
82 85
86 phba->lpfc_hbq_pool = pci_pool_create("lpfc_hbq_pool",phba->pcidev,
87 LPFC_BPL_SIZE, 8, 0);
88 if (!phba->lpfc_hbq_pool)
89 goto fail_free_nlp_mem_pool;
90
91 /* vpi zero is reserved for the physical port so add 1 to max */
92 longs = ((phba->max_vpi + 1) + BITS_PER_LONG - 1) / BITS_PER_LONG;
93 phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL);
94 if (!phba->vpi_bmask)
95 goto fail_free_hbq_pool;
96
83 return 0; 97 return 0;
84 98
99 fail_free_hbq_pool:
100 lpfc_sli_hbqbuf_free_all(phba);
101 fail_free_nlp_mem_pool:
102 mempool_destroy(phba->nlp_mem_pool);
103 phba->nlp_mem_pool = NULL;
85 fail_free_mbox_pool: 104 fail_free_mbox_pool:
86 mempool_destroy(phba->mbox_mem_pool); 105 mempool_destroy(phba->mbox_mem_pool);
106 phba->mbox_mem_pool = NULL;
87 fail_free_mbuf_pool: 107 fail_free_mbuf_pool:
88 while (i--) 108 while (i--)
89 pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt, 109 pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
@@ -91,8 +111,10 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
91 kfree(pool->elements); 111 kfree(pool->elements);
92 fail_free_lpfc_mbuf_pool: 112 fail_free_lpfc_mbuf_pool:
93 pci_pool_destroy(phba->lpfc_mbuf_pool); 113 pci_pool_destroy(phba->lpfc_mbuf_pool);
114 phba->lpfc_mbuf_pool = NULL;
94 fail_free_dma_buf_pool: 115 fail_free_dma_buf_pool:
95 pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool); 116 pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
117 phba->lpfc_scsi_dma_buf_pool = NULL;
96 fail: 118 fail:
97 return -ENOMEM; 119 return -ENOMEM;
98} 120}
@@ -106,6 +128,9 @@ lpfc_mem_free(struct lpfc_hba * phba)
106 struct lpfc_dmabuf *mp; 128 struct lpfc_dmabuf *mp;
107 int i; 129 int i;
108 130
131 kfree(phba->vpi_bmask);
132 lpfc_sli_hbqbuf_free_all(phba);
133
109 list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) { 134 list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
110 mp = (struct lpfc_dmabuf *) (mbox->context1); 135 mp = (struct lpfc_dmabuf *) (mbox->context1);
111 if (mp) { 136 if (mp) {
@@ -115,6 +140,15 @@ lpfc_mem_free(struct lpfc_hba * phba)
115 list_del(&mbox->list); 140 list_del(&mbox->list);
116 mempool_free(mbox, phba->mbox_mem_pool); 141 mempool_free(mbox, phba->mbox_mem_pool);
117 } 142 }
143 list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) {
144 mp = (struct lpfc_dmabuf *) (mbox->context1);
145 if (mp) {
146 lpfc_mbuf_free(phba, mp->virt, mp->phys);
147 kfree(mp);
148 }
149 list_del(&mbox->list);
150 mempool_free(mbox, phba->mbox_mem_pool);
151 }
118 152
119 psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; 153 psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
120 if (psli->mbox_active) { 154 if (psli->mbox_active) {
@@ -132,13 +166,21 @@ lpfc_mem_free(struct lpfc_hba * phba)
132 pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt, 166 pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
133 pool->elements[i].phys); 167 pool->elements[i].phys);
134 kfree(pool->elements); 168 kfree(pool->elements);
169
170 pci_pool_destroy(phba->lpfc_hbq_pool);
135 mempool_destroy(phba->nlp_mem_pool); 171 mempool_destroy(phba->nlp_mem_pool);
136 mempool_destroy(phba->mbox_mem_pool); 172 mempool_destroy(phba->mbox_mem_pool);
137 173
138 pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool); 174 pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
139 pci_pool_destroy(phba->lpfc_mbuf_pool); 175 pci_pool_destroy(phba->lpfc_mbuf_pool);
140 176
141 /* Free the iocb lookup array */ 177 phba->lpfc_hbq_pool = NULL;
178 phba->nlp_mem_pool = NULL;
179 phba->mbox_mem_pool = NULL;
180 phba->lpfc_scsi_dma_buf_pool = NULL;
181 phba->lpfc_mbuf_pool = NULL;
182
183 /* Free the iocb lookup array */
142 kfree(psli->iocbq_lookup); 184 kfree(psli->iocbq_lookup);
143 psli->iocbq_lookup = NULL; 185 psli->iocbq_lookup = NULL;
144 186
@@ -148,20 +190,23 @@ void *
148lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) 190lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
149{ 191{
150 struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 192 struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
193 unsigned long iflags;
151 void *ret; 194 void *ret;
152 195
153 ret = pci_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle); 196 ret = pci_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle);
154 197
155 if (!ret && ( mem_flags & MEM_PRI) && pool->current_count) { 198 spin_lock_irqsave(&phba->hbalock, iflags);
199 if (!ret && (mem_flags & MEM_PRI) && pool->current_count) {
156 pool->current_count--; 200 pool->current_count--;
157 ret = pool->elements[pool->current_count].virt; 201 ret = pool->elements[pool->current_count].virt;
158 *handle = pool->elements[pool->current_count].phys; 202 *handle = pool->elements[pool->current_count].phys;
159 } 203 }
204 spin_unlock_irqrestore(&phba->hbalock, iflags);
160 return ret; 205 return ret;
161} 206}
162 207
163void 208void
164lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) 209__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
165{ 210{
166 struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; 211 struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
167 212
@@ -174,3 +219,51 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
174 } 219 }
175 return; 220 return;
176} 221}
222
223void
224lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
225{
226 unsigned long iflags;
227
228 spin_lock_irqsave(&phba->hbalock, iflags);
229 __lpfc_mbuf_free(phba, virt, dma);
230 spin_unlock_irqrestore(&phba->hbalock, iflags);
231 return;
232}
233
234void *
235lpfc_hbq_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
236{
237 void *ret;
238 ret = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_ATOMIC, handle);
239 return ret;
240}
241
242void
243lpfc_hbq_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma)
244{
245 pci_pool_free(phba->lpfc_hbq_pool, virt, dma);
246 return;
247}
248
249void
250lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
251{
252 struct hbq_dmabuf *hbq_entry;
253
254 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
255 hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf);
256 if (hbq_entry->tag == -1) {
257 lpfc_hbq_free(phba, hbq_entry->dbuf.virt,
258 hbq_entry->dbuf.phys);
259 kfree(hbq_entry);
260 } else {
261 lpfc_sli_free_hbq(phba, hbq_entry);
262 }
263 } else {
264 lpfc_mbuf_free(phba, mp->virt, mp->phys);
265 kfree(mp);
266 }
267 return;
268}
269