Commit | Line | Data |
---|---|---|
dea3101e | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | |
c44ce173 JSEC |
3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2005 Emulex. All rights reserved. * | |
5 | * EMULEX and SLI are trademarks of Emulex. * | |
dea3101e | 6 | * www.emulex.com * |
c44ce173 | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
dea3101e | 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 | 20 | *******************************************************************/ |
21 | ||
dea3101e | 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 | 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 | ||
dea3101e | 41 | int |
42 | lpfc_mem_alloc(struct lpfc_hba * phba) | |
43 | { | |
44 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | |
45 | int i; | |
46 | ||
47 | phba->lpfc_scsi_dma_buf_pool = pci_pool_create("lpfc_scsi_dma_buf_pool", | |
48 | phba->pcidev, phba->cfg_sg_dma_buf_size, 8, 0); | |
49 | if (!phba->lpfc_scsi_dma_buf_pool) | |
50 | goto fail; | |
51 | ||
52 | phba->lpfc_mbuf_pool = pci_pool_create("lpfc_mbuf_pool", phba->pcidev, | |
53 | LPFC_BPL_SIZE, 8,0); | |
54 | if (!phba->lpfc_mbuf_pool) | |
55 | goto fail_free_dma_buf_pool; | |
56 | ||
57 | pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) * | |
58 | LPFC_MBUF_POOL_SIZE, GFP_KERNEL); | |
a96e0c77 MK |
59 | if (!pool->elements) |
60 | goto fail_free_lpfc_mbuf_pool; | |
61 | ||
dea3101e | 62 | pool->max_count = 0; |
63 | pool->current_count = 0; | |
64 | for ( i = 0; i < LPFC_MBUF_POOL_SIZE; i++) { | |
65 | pool->elements[i].virt = pci_pool_alloc(phba->lpfc_mbuf_pool, | |
66 | GFP_KERNEL, &pool->elements[i].phys); | |
67 | if (!pool->elements[i].virt) | |
68 | goto fail_free_mbuf_pool; | |
69 | pool->max_count++; | |
70 | pool->current_count++; | |
71 | } | |
72 | ||
0eaae62a MD |
73 | phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, |
74 | sizeof(LPFC_MBOXQ_t)); | |
dea3101e | 75 | if (!phba->mbox_mem_pool) |
76 | goto fail_free_mbuf_pool; | |
77 | ||
0eaae62a MD |
78 | phba->nlp_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, |
79 | sizeof(struct lpfc_nodelist)); | |
dea3101e | 80 | if (!phba->nlp_mem_pool) |
81 | goto fail_free_mbox_pool; | |
82 | ||
83 | return 0; | |
84 | ||
85 | fail_free_mbox_pool: | |
86 | mempool_destroy(phba->mbox_mem_pool); | |
87 | fail_free_mbuf_pool: | |
a96e0c77 | 88 | while (i--) |
dea3101e | 89 | pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt, |
90 | pool->elements[i].phys); | |
91 | kfree(pool->elements); | |
a96e0c77 | 92 | fail_free_lpfc_mbuf_pool: |
dea3101e | 93 | pci_pool_destroy(phba->lpfc_mbuf_pool); |
94 | fail_free_dma_buf_pool: | |
95 | pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool); | |
96 | fail: | |
97 | return -ENOMEM; | |
98 | } | |
99 | ||
100 | void | |
101 | lpfc_mem_free(struct lpfc_hba * phba) | |
102 | { | |
103 | struct lpfc_sli *psli = &phba->sli; | |
104 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | |
105 | LPFC_MBOXQ_t *mbox, *next_mbox; | |
106 | struct lpfc_dmabuf *mp; | |
107 | int i; | |
108 | ||
109 | list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) { | |
110 | mp = (struct lpfc_dmabuf *) (mbox->context1); | |
111 | if (mp) { | |
112 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | |
113 | kfree(mp); | |
114 | } | |
115 | list_del(&mbox->list); | |
116 | mempool_free(mbox, phba->mbox_mem_pool); | |
117 | } | |
118 | ||
119 | psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; | |
120 | if (psli->mbox_active) { | |
121 | mbox = psli->mbox_active; | |
122 | mp = (struct lpfc_dmabuf *) (mbox->context1); | |
123 | if (mp) { | |
124 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | |
125 | kfree(mp); | |
126 | } | |
127 | mempool_free(mbox, phba->mbox_mem_pool); | |
128 | psli->mbox_active = NULL; | |
129 | } | |
130 | ||
131 | for (i = 0; i < pool->current_count; i++) | |
132 | pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt, | |
133 | pool->elements[i].phys); | |
134 | kfree(pool->elements); | |
135 | mempool_destroy(phba->nlp_mem_pool); | |
136 | mempool_destroy(phba->mbox_mem_pool); | |
137 | ||
138 | pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool); | |
139 | pci_pool_destroy(phba->lpfc_mbuf_pool); | |
9f49d3b0 JS |
140 | |
141 | /* Free the iocb lookup array */ | |
142 | kfree(psli->iocbq_lookup); | |
143 | psli->iocbq_lookup = NULL; | |
144 | ||
dea3101e | 145 | } |
146 | ||
147 | void * | |
148 | lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) | |
149 | { | |
150 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | |
151 | void *ret; | |
152 | ||
153 | ret = pci_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle); | |
154 | ||
155 | if (!ret && ( mem_flags & MEM_PRI) && pool->current_count) { | |
156 | pool->current_count--; | |
157 | ret = pool->elements[pool->current_count].virt; | |
158 | *handle = pool->elements[pool->current_count].phys; | |
159 | } | |
160 | return ret; | |
161 | } | |
162 | ||
163 | void | |
164 | lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) | |
165 | { | |
166 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | |
167 | ||
168 | if (pool->current_count < pool->max_count) { | |
169 | pool->elements[pool->current_count].virt = virt; | |
170 | pool->elements[pool->current_count].phys = dma; | |
171 | pool->current_count++; | |
172 | } else { | |
173 | pci_pool_free(phba->lpfc_mbuf_pool, virt, dma); | |
174 | } | |
175 | return; | |
176 | } |