diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_mem.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mem.c | 101 |
1 files changed, 97 insertions, 4 deletions
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index ec3bbbde6f7a..3594c469494f 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 | |||
41 | int | 43 | int |
42 | lpfc_mem_alloc(struct lpfc_hba * phba) | 44 | lpfc_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 * | |||
148 | lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) | 190 | lpfc_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 | ||
163 | void | 208 | void |
164 | lpfc_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 | |||
223 | void | ||
224 | lpfc_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 | |||
234 | void * | ||
235 | lpfc_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 | |||
242 | void | ||
243 | lpfc_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 | |||
249 | void | ||
250 | lpfc_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 | |||