Commit | Line | Data |
---|---|---|
dea3101e JB |
1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | |
c44ce173 | 3 | * Fibre Channel Host Bus Adapters. * |
2e0fef85 | 4 | * Copyright (C) 2004-2006 Emulex. All rights reserved. * |
c44ce173 | 5 | * EMULEX and SLI are trademarks of Emulex. * |
dea3101e | 6 | * www.emulex.com * |
c44ce173 | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
dea3101e JB |
8 | * * |
9 | * This program is free software; you can redistribute it and/or * | |
c44ce173 JSEC |
10 | * modify it under the terms of version 2 of the GNU General * |
11 | * Public License as published by the Free Software Foundation. * | |
12 | * This program is distributed in the hope that it will be useful. * | |
13 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | |
14 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | |
15 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | |
16 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | |
17 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | |
18 | * more details, a copy of which can be found in the file COPYING * | |
19 | * included with this package. * | |
dea3101e JB |
20 | *******************************************************************/ |
21 | ||
dea3101e JB |
22 | #include <linux/mempool.h> |
23 | #include <linux/pci.h> | |
24 | #include <linux/interrupt.h> | |
25 | ||
f888ba3c JSEC |
26 | #include <scsi/scsi_device.h> |
27 | #include <scsi/scsi_transport_fc.h> | |
28 | ||
91886523 JSEC |
29 | #include <scsi/scsi.h> |
30 | ||
dea3101e JB |
31 | #include "lpfc_hw.h" |
32 | #include "lpfc_sli.h" | |
33 | #include "lpfc_disc.h" | |
34 | #include "lpfc_scsi.h" | |
35 | #include "lpfc.h" | |
36 | #include "lpfc_crtn.h" | |
37 | ||
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 */ | |
40 | ||
2e0fef85 JS |
41 | |
42 | ||
dea3101e JB |
43 | int |
44 | lpfc_mem_alloc(struct lpfc_hba * phba) | |
45 | { | |
46 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | |
47 | int i; | |
48 | ||
49 | phba->lpfc_scsi_dma_buf_pool = pci_pool_create("lpfc_scsi_dma_buf_pool", | |
50 | phba->pcidev, phba->cfg_sg_dma_buf_size, 8, 0); | |
51 | if (!phba->lpfc_scsi_dma_buf_pool) | |
52 | goto fail; | |
53 | ||
54 | phba->lpfc_mbuf_pool = pci_pool_create("lpfc_mbuf_pool", phba->pcidev, | |
55 | LPFC_BPL_SIZE, 8,0); | |
56 | if (!phba->lpfc_mbuf_pool) | |
57 | goto fail_free_dma_buf_pool; | |
58 | ||
59 | pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) * | |
60 | LPFC_MBUF_POOL_SIZE, GFP_KERNEL); | |
a96e0c77 MK |
61 | if (!pool->elements) |
62 | goto fail_free_lpfc_mbuf_pool; | |
63 | ||
dea3101e JB |
64 | pool->max_count = 0; |
65 | pool->current_count = 0; | |
66 | for ( i = 0; i < LPFC_MBUF_POOL_SIZE; i++) { | |
67 | pool->elements[i].virt = pci_pool_alloc(phba->lpfc_mbuf_pool, | |
68 | GFP_KERNEL, &pool->elements[i].phys); | |
69 | if (!pool->elements[i].virt) | |
70 | goto fail_free_mbuf_pool; | |
71 | pool->max_count++; | |
72 | pool->current_count++; | |
73 | } | |
74 | ||
0eaae62a MD |
75 | phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, |
76 | sizeof(LPFC_MBOXQ_t)); | |
dea3101e JB |
77 | if (!phba->mbox_mem_pool) |
78 | goto fail_free_mbuf_pool; | |
79 | ||
0eaae62a MD |
80 | phba->nlp_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, |
81 | sizeof(struct lpfc_nodelist)); | |
dea3101e JB |
82 | if (!phba->nlp_mem_pool) |
83 | goto fail_free_mbox_pool; | |
84 | ||
85 | return 0; | |
86 | ||
87 | fail_free_mbox_pool: | |
88 | mempool_destroy(phba->mbox_mem_pool); | |
2e0fef85 | 89 | phba->mbox_mem_pool = NULL; |
dea3101e | 90 | fail_free_mbuf_pool: |
a96e0c77 | 91 | while (i--) |
dea3101e JB |
92 | pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt, |
93 | pool->elements[i].phys); | |
94 | kfree(pool->elements); | |
a96e0c77 | 95 | fail_free_lpfc_mbuf_pool: |
dea3101e | 96 | pci_pool_destroy(phba->lpfc_mbuf_pool); |
2e0fef85 | 97 | phba->lpfc_mbuf_pool = NULL; |
dea3101e JB |
98 | fail_free_dma_buf_pool: |
99 | pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool); | |
2e0fef85 | 100 | phba->lpfc_scsi_dma_buf_pool = NULL; |
dea3101e JB |
101 | fail: |
102 | return -ENOMEM; | |
103 | } | |
104 | ||
105 | void | |
106 | lpfc_mem_free(struct lpfc_hba * phba) | |
107 | { | |
108 | struct lpfc_sli *psli = &phba->sli; | |
109 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | |
110 | LPFC_MBOXQ_t *mbox, *next_mbox; | |
111 | struct lpfc_dmabuf *mp; | |
112 | int i; | |
113 | ||
2e0fef85 | 114 | spin_lock_irq(&phba->hbalock); |
dea3101e JB |
115 | list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) { |
116 | mp = (struct lpfc_dmabuf *) (mbox->context1); | |
117 | if (mp) { | |
118 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | |
119 | kfree(mp); | |
120 | } | |
121 | list_del(&mbox->list); | |
122 | mempool_free(mbox, phba->mbox_mem_pool); | |
123 | } | |
124 | ||
125 | psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; | |
2e0fef85 | 126 | spin_unlock_irq(&phba->hbalock); |
dea3101e JB |
127 | if (psli->mbox_active) { |
128 | mbox = psli->mbox_active; | |
129 | mp = (struct lpfc_dmabuf *) (mbox->context1); | |
130 | if (mp) { | |
131 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | |
132 | kfree(mp); | |
133 | } | |
134 | mempool_free(mbox, phba->mbox_mem_pool); | |
135 | psli->mbox_active = NULL; | |
136 | } | |
137 | ||
138 | for (i = 0; i < pool->current_count; i++) | |
139 | pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt, | |
140 | pool->elements[i].phys); | |
141 | kfree(pool->elements); | |
2e0fef85 | 142 | |
dea3101e JB |
143 | mempool_destroy(phba->nlp_mem_pool); |
144 | mempool_destroy(phba->mbox_mem_pool); | |
145 | ||
146 | pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool); | |
147 | pci_pool_destroy(phba->lpfc_mbuf_pool); | |
9f49d3b0 | 148 | |
2e0fef85 JS |
149 | phba->nlp_mem_pool = NULL; |
150 | phba->mbox_mem_pool = NULL; | |
151 | phba->lpfc_scsi_dma_buf_pool = NULL; | |
152 | phba->lpfc_mbuf_pool = NULL; | |
153 | ||
9f49d3b0 JS |
154 | /* Free the iocb lookup array */ |
155 | kfree(psli->iocbq_lookup); | |
156 | psli->iocbq_lookup = NULL; | |
157 | ||
dea3101e JB |
158 | } |
159 | ||
160 | void * | |
161 | lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) | |
162 | { | |
163 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | |
2e0fef85 | 164 | unsigned long iflags; |
dea3101e JB |
165 | void *ret; |
166 | ||
167 | ret = pci_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle); | |
168 | ||
2e0fef85 | 169 | spin_lock_irqsave(&phba->hbalock, iflags); |
dea3101e JB |
170 | if (!ret && ( mem_flags & MEM_PRI) && pool->current_count) { |
171 | pool->current_count--; | |
172 | ret = pool->elements[pool->current_count].virt; | |
173 | *handle = pool->elements[pool->current_count].phys; | |
174 | } | |
2e0fef85 | 175 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
dea3101e JB |
176 | return ret; |
177 | } | |
178 | ||
179 | void | |
2e0fef85 | 180 | __lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) |
dea3101e JB |
181 | { |
182 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | |
183 | ||
184 | if (pool->current_count < pool->max_count) { | |
185 | pool->elements[pool->current_count].virt = virt; | |
186 | pool->elements[pool->current_count].phys = dma; | |
187 | pool->current_count++; | |
188 | } else { | |
189 | pci_pool_free(phba->lpfc_mbuf_pool, virt, dma); | |
190 | } | |
191 | return; | |
192 | } | |
2e0fef85 JS |
193 | |
194 | void | |
195 | lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) | |
196 | { | |
197 | unsigned long iflags; | |
198 | ||
199 | spin_lock_irqsave(&phba->hbalock, iflags); | |
200 | __lpfc_mbuf_free(phba, virt, dma); | |
201 | spin_unlock_irqrestore(&phba->hbalock, iflags); | |
202 | return; | |
203 | } |